22e59094e82e377d1e62e66c2592989112ac7b7c
[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 "backend.h"
29 #include "target.h"
30 #include "rtl.h"
31 #include "tree.h"
32 #include "gimple.h"
33 #include "cfghooks.h"
34 #include "alloc-pool.h"
35 #include "tree-pass.h"
36 #include "ssa.h"
37 #include "expmed.h"
38 #include "optabs.h"
39 #include "emit-rtl.h"
40 #include "cgraph.h"
41 #include "pretty-print.h"
42 #include "diagnostic-core.h"
43 #include "alias.h"
44 #include "fold-const.h"
45 #include "stor-layout.h"
46 #include "cfganal.h"
47 #include "internal-fn.h"
48 #include "gimple-fold.h"
49 #include "gimplify.h"
50 #include "gimple-iterator.h"
51 #include "gimplify-me.h"
52 #include "gimple-walk.h"
53 #include "tree-iterator.h"
54 #include "tree-inline.h"
55 #include "langhooks.h"
56 #include "tree-cfg.h"
57 #include "tree-into-ssa.h"
58 #include "flags.h"
59 #include "dojump.h"
60 #include "explow.h"
61 #include "calls.h"
62 #include "varasm.h"
63 #include "stmt.h"
64 #include "expr.h"
65 #include "tree-dfa.h"
66 #include "tree-ssa.h"
67 #include "except.h"
68 #include "splay-tree.h"
69 #include "cfgloop.h"
70 #include "common/common-target.h"
71 #include "omp-low.h"
72 #include "gimple-low.h"
73 #include "tree-cfgcleanup.h"
74 #include "symbol-summary.h"
75 #include "ipa-prop.h"
76 #include "tree-nested.h"
77 #include "tree-eh.h"
78 #include "cilk.h"
79 #include "context.h"
80 #include "lto-section-names.h"
81 #include "gomp-constants.h"
82 #include "gimple-pretty-print.h"
83 #include "symbol-summary.h"
84 #include "hsa.h"
85 #include "params.h"
86
87 /* Lowering of OMP parallel and workshare constructs proceeds in two
88 phases. The first phase scans the function looking for OMP statements
89 and then for variables that must be replaced to satisfy data sharing
90 clauses. The second phase expands code for the constructs, as well as
91 re-gimplifying things when variables have been replaced with complex
92 expressions.
93
94 Final code generation is done by pass_expand_omp. The flowgraph is
95 scanned for regions which are then moved to a new
96 function, to be invoked by the thread library, or offloaded. */
97
98 /* OMP region information. Every parallel and workshare
99 directive is enclosed between two markers, the OMP_* directive
100 and a corresponding GIMPLE_OMP_RETURN statement. */
101
102 struct omp_region
103 {
104 /* The enclosing region. */
105 struct omp_region *outer;
106
107 /* First child region. */
108 struct omp_region *inner;
109
110 /* Next peer region. */
111 struct omp_region *next;
112
113 /* Block containing the omp directive as its last stmt. */
114 basic_block entry;
115
116 /* Block containing the GIMPLE_OMP_RETURN as its last stmt. */
117 basic_block exit;
118
119 /* Block containing the GIMPLE_OMP_CONTINUE as its last stmt. */
120 basic_block cont;
121
122 /* If this is a combined parallel+workshare region, this is a list
123 of additional arguments needed by the combined parallel+workshare
124 library call. */
125 vec<tree, va_gc> *ws_args;
126
127 /* The code for the omp directive of this region. */
128 enum gimple_code type;
129
130 /* Schedule kind, only used for GIMPLE_OMP_FOR type regions. */
131 enum omp_clause_schedule_kind sched_kind;
132
133 /* Schedule modifiers. */
134 unsigned char sched_modifiers;
135
136 /* True if this is a combined parallel+workshare region. */
137 bool is_combined_parallel;
138
139 /* The ordered stmt if type is GIMPLE_OMP_ORDERED and it has
140 a depend clause. */
141 gomp_ordered *ord_stmt;
142 };
143
144 /* Context structure. Used to store information about each parallel
145 directive in the code. */
146
147 struct omp_context
148 {
149 /* This field must be at the beginning, as we do "inheritance": Some
150 callback functions for tree-inline.c (e.g., omp_copy_decl)
151 receive a copy_body_data pointer that is up-casted to an
152 omp_context pointer. */
153 copy_body_data cb;
154
155 /* The tree of contexts corresponding to the encountered constructs. */
156 struct omp_context *outer;
157 gimple *stmt;
158
159 /* Map variables to fields in a structure that allows communication
160 between sending and receiving threads. */
161 splay_tree field_map;
162 tree record_type;
163 tree sender_decl;
164 tree receiver_decl;
165
166 /* These are used just by task contexts, if task firstprivate fn is
167 needed. srecord_type is used to communicate from the thread
168 that encountered the task construct to task firstprivate fn,
169 record_type is allocated by GOMP_task, initialized by task firstprivate
170 fn and passed to the task body fn. */
171 splay_tree sfield_map;
172 tree srecord_type;
173
174 /* A chain of variables to add to the top-level block surrounding the
175 construct. In the case of a parallel, this is in the child function. */
176 tree block_vars;
177
178 /* Label to which GOMP_cancel{,llation_point} and explicit and implicit
179 barriers should jump to during omplower pass. */
180 tree cancel_label;
181
182 /* What to do with variables with implicitly determined sharing
183 attributes. */
184 enum omp_clause_default_kind default_kind;
185
186 /* Nesting depth of this context. Used to beautify error messages re
187 invalid gotos. The outermost ctx is depth 1, with depth 0 being
188 reserved for the main body of the function. */
189 int depth;
190
191 /* True if this parallel directive is nested within another. */
192 bool is_nested;
193
194 /* True if this construct can be cancelled. */
195 bool cancellable;
196 };
197
198 /* A structure holding the elements of:
199 for (V = N1; V cond N2; V += STEP) [...] */
200
201 struct omp_for_data_loop
202 {
203 tree v, n1, n2, step;
204 enum tree_code cond_code;
205 };
206
207 /* A structure describing the main elements of a parallel loop. */
208
209 struct omp_for_data
210 {
211 struct omp_for_data_loop loop;
212 tree chunk_size;
213 gomp_for *for_stmt;
214 tree pre, iter_type;
215 int collapse;
216 int ordered;
217 bool have_nowait, have_ordered, simd_schedule;
218 unsigned char sched_modifiers;
219 enum omp_clause_schedule_kind sched_kind;
220 struct omp_for_data_loop *loops;
221 };
222
223 /* Describe the OpenACC looping structure of a function. The entire
224 function is held in a 'NULL' loop. */
225
226 struct oacc_loop
227 {
228 oacc_loop *parent; /* Containing loop. */
229
230 oacc_loop *child; /* First inner loop. */
231
232 oacc_loop *sibling; /* Next loop within same parent. */
233
234 location_t loc; /* Location of the loop start. */
235
236 gcall *marker; /* Initial head marker. */
237
238 gcall *heads[GOMP_DIM_MAX]; /* Head marker functions. */
239 gcall *tails[GOMP_DIM_MAX]; /* Tail marker functions. */
240
241 tree routine; /* Pseudo-loop enclosing a routine. */
242
243 unsigned mask; /* Partitioning mask. */
244 unsigned inner; /* Partitioning of inner loops. */
245 unsigned flags; /* Partitioning flags. */
246 unsigned ifns; /* Contained loop abstraction functions. */
247 tree chunk_size; /* Chunk size. */
248 gcall *head_end; /* Final marker of head sequence. */
249 };
250
251 /* Flags for an OpenACC loop. */
252
253 enum oacc_loop_flags {
254 OLF_SEQ = 1u << 0, /* Explicitly sequential */
255 OLF_AUTO = 1u << 1, /* Compiler chooses axes. */
256 OLF_INDEPENDENT = 1u << 2, /* Iterations are known independent. */
257 OLF_GANG_STATIC = 1u << 3, /* Gang partitioning is static (has op). */
258
259 /* Explicitly specified loop axes. */
260 OLF_DIM_BASE = 4,
261 OLF_DIM_GANG = 1u << (OLF_DIM_BASE + GOMP_DIM_GANG),
262 OLF_DIM_WORKER = 1u << (OLF_DIM_BASE + GOMP_DIM_WORKER),
263 OLF_DIM_VECTOR = 1u << (OLF_DIM_BASE + GOMP_DIM_VECTOR),
264
265 OLF_MAX = OLF_DIM_BASE + GOMP_DIM_MAX
266 };
267
268
269 static splay_tree all_contexts;
270 static int taskreg_nesting_level;
271 static int target_nesting_level;
272 static struct omp_region *root_omp_region;
273 static bitmap task_shared_vars;
274 static vec<omp_context *> taskreg_contexts;
275 static bool omp_any_child_fn_dumped;
276
277 static void scan_omp (gimple_seq *, omp_context *);
278 static tree scan_omp_1_op (tree *, int *, void *);
279 static gphi *find_phi_with_arg_on_edge (tree, edge);
280
281 #define WALK_SUBSTMTS \
282 case GIMPLE_BIND: \
283 case GIMPLE_TRY: \
284 case GIMPLE_CATCH: \
285 case GIMPLE_EH_FILTER: \
286 case GIMPLE_TRANSACTION: \
287 /* The sub-statements for these should be walked. */ \
288 *handled_ops_p = false; \
289 break;
290
291 /* Return true if CTX corresponds to an oacc parallel region. */
292
293 static bool
294 is_oacc_parallel (omp_context *ctx)
295 {
296 enum gimple_code outer_type = gimple_code (ctx->stmt);
297 return ((outer_type == GIMPLE_OMP_TARGET)
298 && (gimple_omp_target_kind (ctx->stmt)
299 == GF_OMP_TARGET_KIND_OACC_PARALLEL));
300 }
301
302 /* Return true if CTX corresponds to an oacc kernels region. */
303
304 static bool
305 is_oacc_kernels (omp_context *ctx)
306 {
307 enum gimple_code outer_type = gimple_code (ctx->stmt);
308 return ((outer_type == GIMPLE_OMP_TARGET)
309 && (gimple_omp_target_kind (ctx->stmt)
310 == GF_OMP_TARGET_KIND_OACC_KERNELS));
311 }
312
313 /* If DECL is the artificial dummy VAR_DECL created for non-static
314 data member privatization, return the underlying "this" parameter,
315 otherwise return NULL. */
316
317 tree
318 omp_member_access_dummy_var (tree decl)
319 {
320 if (!VAR_P (decl)
321 || !DECL_ARTIFICIAL (decl)
322 || !DECL_IGNORED_P (decl)
323 || !DECL_HAS_VALUE_EXPR_P (decl)
324 || !lang_hooks.decls.omp_disregard_value_expr (decl, false))
325 return NULL_TREE;
326
327 tree v = DECL_VALUE_EXPR (decl);
328 if (TREE_CODE (v) != COMPONENT_REF)
329 return NULL_TREE;
330
331 while (1)
332 switch (TREE_CODE (v))
333 {
334 case COMPONENT_REF:
335 case MEM_REF:
336 case INDIRECT_REF:
337 CASE_CONVERT:
338 case POINTER_PLUS_EXPR:
339 v = TREE_OPERAND (v, 0);
340 continue;
341 case PARM_DECL:
342 if (DECL_CONTEXT (v) == current_function_decl
343 && DECL_ARTIFICIAL (v)
344 && TREE_CODE (TREE_TYPE (v)) == POINTER_TYPE)
345 return v;
346 return NULL_TREE;
347 default:
348 return NULL_TREE;
349 }
350 }
351
352 /* Helper for unshare_and_remap, called through walk_tree. */
353
354 static tree
355 unshare_and_remap_1 (tree *tp, int *walk_subtrees, void *data)
356 {
357 tree *pair = (tree *) data;
358 if (*tp == pair[0])
359 {
360 *tp = unshare_expr (pair[1]);
361 *walk_subtrees = 0;
362 }
363 else if (IS_TYPE_OR_DECL_P (*tp))
364 *walk_subtrees = 0;
365 return NULL_TREE;
366 }
367
368 /* Return unshare_expr (X) with all occurrences of FROM
369 replaced with TO. */
370
371 static tree
372 unshare_and_remap (tree x, tree from, tree to)
373 {
374 tree pair[2] = { from, to };
375 x = unshare_expr (x);
376 walk_tree (&x, unshare_and_remap_1, pair, NULL);
377 return x;
378 }
379
380 /* Holds offload tables with decls. */
381 vec<tree, va_gc> *offload_funcs, *offload_vars;
382
383 /* Convenience function for calling scan_omp_1_op on tree operands. */
384
385 static inline tree
386 scan_omp_op (tree *tp, omp_context *ctx)
387 {
388 struct walk_stmt_info wi;
389
390 memset (&wi, 0, sizeof (wi));
391 wi.info = ctx;
392 wi.want_locations = true;
393
394 return walk_tree (tp, scan_omp_1_op, &wi, NULL);
395 }
396
397 static void lower_omp (gimple_seq *, omp_context *);
398 static tree lookup_decl_in_outer_ctx (tree, omp_context *);
399 static tree maybe_lookup_decl_in_outer_ctx (tree, omp_context *);
400
401 /* Find an OMP clause of type KIND within CLAUSES. */
402
403 tree
404 find_omp_clause (tree clauses, enum omp_clause_code kind)
405 {
406 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
407 if (OMP_CLAUSE_CODE (clauses) == kind)
408 return clauses;
409
410 return NULL_TREE;
411 }
412
413 /* Return true if CTX is for an omp parallel. */
414
415 static inline bool
416 is_parallel_ctx (omp_context *ctx)
417 {
418 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL;
419 }
420
421
422 /* Return true if CTX is for an omp task. */
423
424 static inline bool
425 is_task_ctx (omp_context *ctx)
426 {
427 return gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
428 }
429
430
431 /* Return true if CTX is for an omp taskloop. */
432
433 static inline bool
434 is_taskloop_ctx (omp_context *ctx)
435 {
436 return gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
437 && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_TASKLOOP;
438 }
439
440
441 /* Return true if CTX is for an omp parallel or omp task. */
442
443 static inline bool
444 is_taskreg_ctx (omp_context *ctx)
445 {
446 return is_parallel_ctx (ctx) || is_task_ctx (ctx);
447 }
448
449
450 /* Return true if REGION is a combined parallel+workshare region. */
451
452 static inline bool
453 is_combined_parallel (struct omp_region *region)
454 {
455 return region->is_combined_parallel;
456 }
457
458 /* Adjust *COND_CODE and *N2 so that the former is either LT_EXPR or
459 GT_EXPR. */
460
461 static void
462 adjust_for_condition (location_t loc, enum tree_code *cond_code, tree *n2)
463 {
464 switch (*cond_code)
465 {
466 case LT_EXPR:
467 case GT_EXPR:
468 case NE_EXPR:
469 break;
470 case LE_EXPR:
471 if (POINTER_TYPE_P (TREE_TYPE (*n2)))
472 *n2 = fold_build_pointer_plus_hwi_loc (loc, *n2, 1);
473 else
474 *n2 = fold_build2_loc (loc, PLUS_EXPR, TREE_TYPE (*n2), *n2,
475 build_int_cst (TREE_TYPE (*n2), 1));
476 *cond_code = LT_EXPR;
477 break;
478 case GE_EXPR:
479 if (POINTER_TYPE_P (TREE_TYPE (*n2)))
480 *n2 = fold_build_pointer_plus_hwi_loc (loc, *n2, -1);
481 else
482 *n2 = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (*n2), *n2,
483 build_int_cst (TREE_TYPE (*n2), 1));
484 *cond_code = GT_EXPR;
485 break;
486 default:
487 gcc_unreachable ();
488 }
489 }
490
491 /* Return the looping step from INCR, extracted from the step of a gimple omp
492 for statement. */
493
494 static tree
495 get_omp_for_step_from_incr (location_t loc, tree incr)
496 {
497 tree step;
498 switch (TREE_CODE (incr))
499 {
500 case PLUS_EXPR:
501 step = TREE_OPERAND (incr, 1);
502 break;
503 case POINTER_PLUS_EXPR:
504 step = fold_convert (ssizetype, TREE_OPERAND (incr, 1));
505 break;
506 case MINUS_EXPR:
507 step = TREE_OPERAND (incr, 1);
508 step = fold_build1_loc (loc, NEGATE_EXPR, TREE_TYPE (step), step);
509 break;
510 default:
511 gcc_unreachable ();
512 }
513 return step;
514 }
515
516 /* Extract the header elements of parallel loop FOR_STMT and store
517 them into *FD. */
518
519 static void
520 extract_omp_for_data (gomp_for *for_stmt, struct omp_for_data *fd,
521 struct omp_for_data_loop *loops)
522 {
523 tree t, var, *collapse_iter, *collapse_count;
524 tree count = NULL_TREE, iter_type = long_integer_type_node;
525 struct omp_for_data_loop *loop;
526 int i;
527 struct omp_for_data_loop dummy_loop;
528 location_t loc = gimple_location (for_stmt);
529 bool simd = gimple_omp_for_kind (for_stmt) & GF_OMP_FOR_SIMD;
530 bool distribute = gimple_omp_for_kind (for_stmt)
531 == GF_OMP_FOR_KIND_DISTRIBUTE;
532 bool taskloop = gimple_omp_for_kind (for_stmt)
533 == GF_OMP_FOR_KIND_TASKLOOP;
534 tree iterv, countv;
535
536 fd->for_stmt = for_stmt;
537 fd->pre = NULL;
538 if (gimple_omp_for_collapse (for_stmt) > 1)
539 fd->loops = loops;
540 else
541 fd->loops = &fd->loop;
542
543 fd->have_nowait = distribute || simd;
544 fd->have_ordered = false;
545 fd->collapse = 1;
546 fd->ordered = 0;
547 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
548 fd->sched_modifiers = 0;
549 fd->chunk_size = NULL_TREE;
550 fd->simd_schedule = false;
551 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
552 fd->sched_kind = OMP_CLAUSE_SCHEDULE_CILKFOR;
553 collapse_iter = NULL;
554 collapse_count = NULL;
555
556 for (t = gimple_omp_for_clauses (for_stmt); t ; t = OMP_CLAUSE_CHAIN (t))
557 switch (OMP_CLAUSE_CODE (t))
558 {
559 case OMP_CLAUSE_NOWAIT:
560 fd->have_nowait = true;
561 break;
562 case OMP_CLAUSE_ORDERED:
563 fd->have_ordered = true;
564 if (OMP_CLAUSE_ORDERED_EXPR (t))
565 fd->ordered = tree_to_shwi (OMP_CLAUSE_ORDERED_EXPR (t));
566 break;
567 case OMP_CLAUSE_SCHEDULE:
568 gcc_assert (!distribute && !taskloop);
569 fd->sched_kind
570 = (enum omp_clause_schedule_kind)
571 (OMP_CLAUSE_SCHEDULE_KIND (t) & OMP_CLAUSE_SCHEDULE_MASK);
572 fd->sched_modifiers = (OMP_CLAUSE_SCHEDULE_KIND (t)
573 & ~OMP_CLAUSE_SCHEDULE_MASK);
574 fd->chunk_size = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t);
575 fd->simd_schedule = OMP_CLAUSE_SCHEDULE_SIMD (t);
576 break;
577 case OMP_CLAUSE_DIST_SCHEDULE:
578 gcc_assert (distribute);
579 fd->chunk_size = OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (t);
580 break;
581 case OMP_CLAUSE_COLLAPSE:
582 fd->collapse = tree_to_shwi (OMP_CLAUSE_COLLAPSE_EXPR (t));
583 if (fd->collapse > 1)
584 {
585 collapse_iter = &OMP_CLAUSE_COLLAPSE_ITERVAR (t);
586 collapse_count = &OMP_CLAUSE_COLLAPSE_COUNT (t);
587 }
588 break;
589 default:
590 break;
591 }
592 if (fd->ordered && fd->collapse == 1 && loops != NULL)
593 {
594 fd->loops = loops;
595 iterv = NULL_TREE;
596 countv = NULL_TREE;
597 collapse_iter = &iterv;
598 collapse_count = &countv;
599 }
600
601 /* FIXME: for now map schedule(auto) to schedule(static).
602 There should be analysis to determine whether all iterations
603 are approximately the same amount of work (then schedule(static)
604 is best) or if it varies (then schedule(dynamic,N) is better). */
605 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_AUTO)
606 {
607 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
608 gcc_assert (fd->chunk_size == NULL);
609 }
610 gcc_assert (fd->collapse == 1 || collapse_iter != NULL);
611 if (taskloop)
612 fd->sched_kind = OMP_CLAUSE_SCHEDULE_RUNTIME;
613 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
614 gcc_assert (fd->chunk_size == NULL);
615 else if (fd->chunk_size == NULL)
616 {
617 /* We only need to compute a default chunk size for ordered
618 static loops and dynamic loops. */
619 if (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
620 || fd->have_ordered)
621 fd->chunk_size = (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
622 ? integer_zero_node : integer_one_node;
623 }
624
625 int cnt = fd->ordered ? fd->ordered : fd->collapse;
626 for (i = 0; i < cnt; i++)
627 {
628 if (i == 0 && fd->collapse == 1 && (fd->ordered == 0 || loops == NULL))
629 loop = &fd->loop;
630 else if (loops != NULL)
631 loop = loops + i;
632 else
633 loop = &dummy_loop;
634
635 loop->v = gimple_omp_for_index (for_stmt, i);
636 gcc_assert (SSA_VAR_P (loop->v));
637 gcc_assert (TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
638 || TREE_CODE (TREE_TYPE (loop->v)) == POINTER_TYPE);
639 var = TREE_CODE (loop->v) == SSA_NAME ? SSA_NAME_VAR (loop->v) : loop->v;
640 loop->n1 = gimple_omp_for_initial (for_stmt, i);
641
642 loop->cond_code = gimple_omp_for_cond (for_stmt, i);
643 loop->n2 = gimple_omp_for_final (for_stmt, i);
644 gcc_assert (loop->cond_code != NE_EXPR
645 || gimple_omp_for_kind (for_stmt) == GF_OMP_FOR_KIND_CILKSIMD
646 || gimple_omp_for_kind (for_stmt) == GF_OMP_FOR_KIND_CILKFOR);
647 adjust_for_condition (loc, &loop->cond_code, &loop->n2);
648
649 t = gimple_omp_for_incr (for_stmt, i);
650 gcc_assert (TREE_OPERAND (t, 0) == var);
651 loop->step = get_omp_for_step_from_incr (loc, t);
652
653 if (simd
654 || (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
655 && !fd->have_ordered))
656 {
657 if (fd->collapse == 1)
658 iter_type = TREE_TYPE (loop->v);
659 else if (i == 0
660 || TYPE_PRECISION (iter_type)
661 < TYPE_PRECISION (TREE_TYPE (loop->v)))
662 iter_type
663 = build_nonstandard_integer_type
664 (TYPE_PRECISION (TREE_TYPE (loop->v)), 1);
665 }
666 else if (iter_type != long_long_unsigned_type_node)
667 {
668 if (POINTER_TYPE_P (TREE_TYPE (loop->v)))
669 iter_type = long_long_unsigned_type_node;
670 else if (TYPE_UNSIGNED (TREE_TYPE (loop->v))
671 && TYPE_PRECISION (TREE_TYPE (loop->v))
672 >= TYPE_PRECISION (iter_type))
673 {
674 tree n;
675
676 if (loop->cond_code == LT_EXPR)
677 n = fold_build2_loc (loc,
678 PLUS_EXPR, TREE_TYPE (loop->v),
679 loop->n2, loop->step);
680 else
681 n = loop->n1;
682 if (TREE_CODE (n) != INTEGER_CST
683 || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type), n))
684 iter_type = long_long_unsigned_type_node;
685 }
686 else if (TYPE_PRECISION (TREE_TYPE (loop->v))
687 > TYPE_PRECISION (iter_type))
688 {
689 tree n1, n2;
690
691 if (loop->cond_code == LT_EXPR)
692 {
693 n1 = loop->n1;
694 n2 = fold_build2_loc (loc,
695 PLUS_EXPR, TREE_TYPE (loop->v),
696 loop->n2, loop->step);
697 }
698 else
699 {
700 n1 = fold_build2_loc (loc,
701 MINUS_EXPR, TREE_TYPE (loop->v),
702 loop->n2, loop->step);
703 n2 = loop->n1;
704 }
705 if (TREE_CODE (n1) != INTEGER_CST
706 || TREE_CODE (n2) != INTEGER_CST
707 || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type), n1)
708 || !tree_int_cst_lt (n2, TYPE_MAX_VALUE (iter_type)))
709 iter_type = long_long_unsigned_type_node;
710 }
711 }
712
713 if (i >= fd->collapse)
714 continue;
715
716 if (collapse_count && *collapse_count == NULL)
717 {
718 t = fold_binary (loop->cond_code, boolean_type_node,
719 fold_convert (TREE_TYPE (loop->v), loop->n1),
720 fold_convert (TREE_TYPE (loop->v), loop->n2));
721 if (t && integer_zerop (t))
722 count = build_zero_cst (long_long_unsigned_type_node);
723 else if ((i == 0 || count != NULL_TREE)
724 && TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
725 && TREE_CONSTANT (loop->n1)
726 && TREE_CONSTANT (loop->n2)
727 && TREE_CODE (loop->step) == INTEGER_CST)
728 {
729 tree itype = TREE_TYPE (loop->v);
730
731 if (POINTER_TYPE_P (itype))
732 itype = signed_type_for (itype);
733 t = build_int_cst (itype, (loop->cond_code == LT_EXPR ? -1 : 1));
734 t = fold_build2_loc (loc,
735 PLUS_EXPR, itype,
736 fold_convert_loc (loc, itype, loop->step), t);
737 t = fold_build2_loc (loc, PLUS_EXPR, itype, t,
738 fold_convert_loc (loc, itype, loop->n2));
739 t = fold_build2_loc (loc, MINUS_EXPR, itype, t,
740 fold_convert_loc (loc, itype, loop->n1));
741 if (TYPE_UNSIGNED (itype) && loop->cond_code == GT_EXPR)
742 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype,
743 fold_build1_loc (loc, NEGATE_EXPR, itype, t),
744 fold_build1_loc (loc, NEGATE_EXPR, itype,
745 fold_convert_loc (loc, itype,
746 loop->step)));
747 else
748 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, t,
749 fold_convert_loc (loc, itype, loop->step));
750 t = fold_convert_loc (loc, long_long_unsigned_type_node, t);
751 if (count != NULL_TREE)
752 count = fold_build2_loc (loc,
753 MULT_EXPR, long_long_unsigned_type_node,
754 count, t);
755 else
756 count = t;
757 if (TREE_CODE (count) != INTEGER_CST)
758 count = NULL_TREE;
759 }
760 else if (count && !integer_zerop (count))
761 count = NULL_TREE;
762 }
763 }
764
765 if (count
766 && !simd
767 && (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
768 || fd->have_ordered))
769 {
770 if (!tree_int_cst_lt (count, TYPE_MAX_VALUE (long_integer_type_node)))
771 iter_type = long_long_unsigned_type_node;
772 else
773 iter_type = long_integer_type_node;
774 }
775 else if (collapse_iter && *collapse_iter != NULL)
776 iter_type = TREE_TYPE (*collapse_iter);
777 fd->iter_type = iter_type;
778 if (collapse_iter && *collapse_iter == NULL)
779 *collapse_iter = create_tmp_var (iter_type, ".iter");
780 if (collapse_count && *collapse_count == NULL)
781 {
782 if (count)
783 *collapse_count = fold_convert_loc (loc, iter_type, count);
784 else
785 *collapse_count = create_tmp_var (iter_type, ".count");
786 }
787
788 if (fd->collapse > 1 || (fd->ordered && loops))
789 {
790 fd->loop.v = *collapse_iter;
791 fd->loop.n1 = build_int_cst (TREE_TYPE (fd->loop.v), 0);
792 fd->loop.n2 = *collapse_count;
793 fd->loop.step = build_int_cst (TREE_TYPE (fd->loop.v), 1);
794 fd->loop.cond_code = LT_EXPR;
795 }
796 else if (loops)
797 loops[0] = fd->loop;
798 }
799
800
801 /* Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB
802 is the immediate dominator of PAR_ENTRY_BB, return true if there
803 are no data dependencies that would prevent expanding the parallel
804 directive at PAR_ENTRY_BB as a combined parallel+workshare region.
805
806 When expanding a combined parallel+workshare region, the call to
807 the child function may need additional arguments in the case of
808 GIMPLE_OMP_FOR regions. In some cases, these arguments are
809 computed out of variables passed in from the parent to the child
810 via 'struct .omp_data_s'. For instance:
811
812 #pragma omp parallel for schedule (guided, i * 4)
813 for (j ...)
814
815 Is lowered into:
816
817 # BLOCK 2 (PAR_ENTRY_BB)
818 .omp_data_o.i = i;
819 #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
820
821 # BLOCK 3 (WS_ENTRY_BB)
822 .omp_data_i = &.omp_data_o;
823 D.1667 = .omp_data_i->i;
824 D.1598 = D.1667 * 4;
825 #pragma omp for schedule (guided, D.1598)
826
827 When we outline the parallel region, the call to the child function
828 'bar.omp_fn.0' will need the value D.1598 in its argument list, but
829 that value is computed *after* the call site. So, in principle we
830 cannot do the transformation.
831
832 To see whether the code in WS_ENTRY_BB blocks the combined
833 parallel+workshare call, we collect all the variables used in the
834 GIMPLE_OMP_FOR header check whether they appear on the LHS of any
835 statement in WS_ENTRY_BB. If so, then we cannot emit the combined
836 call.
837
838 FIXME. If we had the SSA form built at this point, we could merely
839 hoist the code in block 3 into block 2 and be done with it. But at
840 this point we don't have dataflow information and though we could
841 hack something up here, it is really not worth the aggravation. */
842
843 static bool
844 workshare_safe_to_combine_p (basic_block ws_entry_bb)
845 {
846 struct omp_for_data fd;
847 gimple *ws_stmt = last_stmt (ws_entry_bb);
848
849 if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
850 return true;
851
852 gcc_assert (gimple_code (ws_stmt) == GIMPLE_OMP_FOR);
853
854 extract_omp_for_data (as_a <gomp_for *> (ws_stmt), &fd, NULL);
855
856 if (fd.collapse > 1 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
857 return false;
858 if (fd.iter_type != long_integer_type_node)
859 return false;
860
861 /* FIXME. We give up too easily here. If any of these arguments
862 are not constants, they will likely involve variables that have
863 been mapped into fields of .omp_data_s for sharing with the child
864 function. With appropriate data flow, it would be possible to
865 see through this. */
866 if (!is_gimple_min_invariant (fd.loop.n1)
867 || !is_gimple_min_invariant (fd.loop.n2)
868 || !is_gimple_min_invariant (fd.loop.step)
869 || (fd.chunk_size && !is_gimple_min_invariant (fd.chunk_size)))
870 return false;
871
872 return true;
873 }
874
875
876 static int omp_max_vf (void);
877
878 /* Adjust CHUNK_SIZE from SCHEDULE clause, depending on simd modifier
879 presence (SIMD_SCHEDULE). */
880
881 static tree
882 omp_adjust_chunk_size (tree chunk_size, bool simd_schedule)
883 {
884 if (!simd_schedule)
885 return chunk_size;
886
887 int vf = omp_max_vf ();
888 if (vf == 1)
889 return chunk_size;
890
891 tree type = TREE_TYPE (chunk_size);
892 chunk_size = fold_build2 (PLUS_EXPR, type, chunk_size,
893 build_int_cst (type, vf - 1));
894 return fold_build2 (BIT_AND_EXPR, type, chunk_size,
895 build_int_cst (type, -vf));
896 }
897
898
899 /* Collect additional arguments needed to emit a combined
900 parallel+workshare call. WS_STMT is the workshare directive being
901 expanded. */
902
903 static vec<tree, va_gc> *
904 get_ws_args_for (gimple *par_stmt, gimple *ws_stmt)
905 {
906 tree t;
907 location_t loc = gimple_location (ws_stmt);
908 vec<tree, va_gc> *ws_args;
909
910 if (gomp_for *for_stmt = dyn_cast <gomp_for *> (ws_stmt))
911 {
912 struct omp_for_data fd;
913 tree n1, n2;
914
915 extract_omp_for_data (for_stmt, &fd, NULL);
916 n1 = fd.loop.n1;
917 n2 = fd.loop.n2;
918
919 if (gimple_omp_for_combined_into_p (for_stmt))
920 {
921 tree innerc
922 = find_omp_clause (gimple_omp_parallel_clauses (par_stmt),
923 OMP_CLAUSE__LOOPTEMP_);
924 gcc_assert (innerc);
925 n1 = OMP_CLAUSE_DECL (innerc);
926 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
927 OMP_CLAUSE__LOOPTEMP_);
928 gcc_assert (innerc);
929 n2 = OMP_CLAUSE_DECL (innerc);
930 }
931
932 vec_alloc (ws_args, 3 + (fd.chunk_size != 0));
933
934 t = fold_convert_loc (loc, long_integer_type_node, n1);
935 ws_args->quick_push (t);
936
937 t = fold_convert_loc (loc, long_integer_type_node, n2);
938 ws_args->quick_push (t);
939
940 t = fold_convert_loc (loc, long_integer_type_node, fd.loop.step);
941 ws_args->quick_push (t);
942
943 if (fd.chunk_size)
944 {
945 t = fold_convert_loc (loc, long_integer_type_node, fd.chunk_size);
946 t = omp_adjust_chunk_size (t, fd.simd_schedule);
947 ws_args->quick_push (t);
948 }
949
950 return ws_args;
951 }
952 else if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
953 {
954 /* Number of sections is equal to the number of edges from the
955 GIMPLE_OMP_SECTIONS_SWITCH statement, except for the one to
956 the exit of the sections region. */
957 basic_block bb = single_succ (gimple_bb (ws_stmt));
958 t = build_int_cst (unsigned_type_node, EDGE_COUNT (bb->succs) - 1);
959 vec_alloc (ws_args, 1);
960 ws_args->quick_push (t);
961 return ws_args;
962 }
963
964 gcc_unreachable ();
965 }
966
967
968 /* Discover whether REGION is a combined parallel+workshare region. */
969
970 static void
971 determine_parallel_type (struct omp_region *region)
972 {
973 basic_block par_entry_bb, par_exit_bb;
974 basic_block ws_entry_bb, ws_exit_bb;
975
976 if (region == NULL || region->inner == NULL
977 || region->exit == NULL || region->inner->exit == NULL
978 || region->inner->cont == NULL)
979 return;
980
981 /* We only support parallel+for and parallel+sections. */
982 if (region->type != GIMPLE_OMP_PARALLEL
983 || (region->inner->type != GIMPLE_OMP_FOR
984 && region->inner->type != GIMPLE_OMP_SECTIONS))
985 return;
986
987 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
988 WS_EXIT_BB -> PAR_EXIT_BB. */
989 par_entry_bb = region->entry;
990 par_exit_bb = region->exit;
991 ws_entry_bb = region->inner->entry;
992 ws_exit_bb = region->inner->exit;
993
994 if (single_succ (par_entry_bb) == ws_entry_bb
995 && single_succ (ws_exit_bb) == par_exit_bb
996 && workshare_safe_to_combine_p (ws_entry_bb)
997 && (gimple_omp_parallel_combined_p (last_stmt (par_entry_bb))
998 || (last_and_only_stmt (ws_entry_bb)
999 && last_and_only_stmt (par_exit_bb))))
1000 {
1001 gimple *par_stmt = last_stmt (par_entry_bb);
1002 gimple *ws_stmt = last_stmt (ws_entry_bb);
1003
1004 if (region->inner->type == GIMPLE_OMP_FOR)
1005 {
1006 /* If this is a combined parallel loop, we need to determine
1007 whether or not to use the combined library calls. There
1008 are two cases where we do not apply the transformation:
1009 static loops and any kind of ordered loop. In the first
1010 case, we already open code the loop so there is no need
1011 to do anything else. In the latter case, the combined
1012 parallel loop call would still need extra synchronization
1013 to implement ordered semantics, so there would not be any
1014 gain in using the combined call. */
1015 tree clauses = gimple_omp_for_clauses (ws_stmt);
1016 tree c = find_omp_clause (clauses, OMP_CLAUSE_SCHEDULE);
1017 if (c == NULL
1018 || ((OMP_CLAUSE_SCHEDULE_KIND (c) & OMP_CLAUSE_SCHEDULE_MASK)
1019 == OMP_CLAUSE_SCHEDULE_STATIC)
1020 || find_omp_clause (clauses, OMP_CLAUSE_ORDERED))
1021 {
1022 region->is_combined_parallel = false;
1023 region->inner->is_combined_parallel = false;
1024 return;
1025 }
1026 }
1027
1028 region->is_combined_parallel = true;
1029 region->inner->is_combined_parallel = true;
1030 region->ws_args = get_ws_args_for (par_stmt, ws_stmt);
1031 }
1032 }
1033
1034
1035 /* Return true if EXPR is variable sized. */
1036
1037 static inline bool
1038 is_variable_sized (const_tree expr)
1039 {
1040 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr)));
1041 }
1042
1043 /* Return true if DECL is a reference type. */
1044
1045 static inline bool
1046 is_reference (tree decl)
1047 {
1048 return lang_hooks.decls.omp_privatize_by_reference (decl);
1049 }
1050
1051 /* Return the type of a decl. If the decl is reference type,
1052 return its base type. */
1053 static inline tree
1054 get_base_type (tree decl)
1055 {
1056 tree type = TREE_TYPE (decl);
1057 if (is_reference (decl))
1058 type = TREE_TYPE (type);
1059 return type;
1060 }
1061
1062 /* Lookup variables. The "maybe" form
1063 allows for the variable form to not have been entered, otherwise we
1064 assert that the variable must have been entered. */
1065
1066 static inline tree
1067 lookup_decl (tree var, omp_context *ctx)
1068 {
1069 tree *n = ctx->cb.decl_map->get (var);
1070 return *n;
1071 }
1072
1073 static inline tree
1074 maybe_lookup_decl (const_tree var, omp_context *ctx)
1075 {
1076 tree *n = ctx->cb.decl_map->get (const_cast<tree> (var));
1077 return n ? *n : NULL_TREE;
1078 }
1079
1080 static inline tree
1081 lookup_field (tree var, omp_context *ctx)
1082 {
1083 splay_tree_node n;
1084 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
1085 return (tree) n->value;
1086 }
1087
1088 static inline tree
1089 lookup_sfield (splay_tree_key key, omp_context *ctx)
1090 {
1091 splay_tree_node n;
1092 n = splay_tree_lookup (ctx->sfield_map
1093 ? ctx->sfield_map : ctx->field_map, key);
1094 return (tree) n->value;
1095 }
1096
1097 static inline tree
1098 lookup_sfield (tree var, omp_context *ctx)
1099 {
1100 return lookup_sfield ((splay_tree_key) var, ctx);
1101 }
1102
1103 static inline tree
1104 maybe_lookup_field (splay_tree_key key, omp_context *ctx)
1105 {
1106 splay_tree_node n;
1107 n = splay_tree_lookup (ctx->field_map, key);
1108 return n ? (tree) n->value : NULL_TREE;
1109 }
1110
1111 static inline tree
1112 maybe_lookup_field (tree var, omp_context *ctx)
1113 {
1114 return maybe_lookup_field ((splay_tree_key) var, ctx);
1115 }
1116
1117 /* Return true if DECL should be copied by pointer. SHARED_CTX is
1118 the parallel context if DECL is to be shared. */
1119
1120 static bool
1121 use_pointer_for_field (tree decl, omp_context *shared_ctx)
1122 {
1123 if (AGGREGATE_TYPE_P (TREE_TYPE (decl)))
1124 return true;
1125
1126 /* We can only use copy-in/copy-out semantics for shared variables
1127 when we know the value is not accessible from an outer scope. */
1128 if (shared_ctx)
1129 {
1130 gcc_assert (!is_gimple_omp_oacc (shared_ctx->stmt));
1131
1132 /* ??? Trivially accessible from anywhere. But why would we even
1133 be passing an address in this case? Should we simply assert
1134 this to be false, or should we have a cleanup pass that removes
1135 these from the list of mappings? */
1136 if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
1137 return true;
1138
1139 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
1140 without analyzing the expression whether or not its location
1141 is accessible to anyone else. In the case of nested parallel
1142 regions it certainly may be. */
1143 if (TREE_CODE (decl) != RESULT_DECL && DECL_HAS_VALUE_EXPR_P (decl))
1144 return true;
1145
1146 /* Do not use copy-in/copy-out for variables that have their
1147 address taken. */
1148 if (TREE_ADDRESSABLE (decl))
1149 return true;
1150
1151 /* lower_send_shared_vars only uses copy-in, but not copy-out
1152 for these. */
1153 if (TREE_READONLY (decl)
1154 || ((TREE_CODE (decl) == RESULT_DECL
1155 || TREE_CODE (decl) == PARM_DECL)
1156 && DECL_BY_REFERENCE (decl)))
1157 return false;
1158
1159 /* Disallow copy-in/out in nested parallel if
1160 decl is shared in outer parallel, otherwise
1161 each thread could store the shared variable
1162 in its own copy-in location, making the
1163 variable no longer really shared. */
1164 if (shared_ctx->is_nested)
1165 {
1166 omp_context *up;
1167
1168 for (up = shared_ctx->outer; up; up = up->outer)
1169 if (is_taskreg_ctx (up) && maybe_lookup_decl (decl, up))
1170 break;
1171
1172 if (up)
1173 {
1174 tree c;
1175
1176 for (c = gimple_omp_taskreg_clauses (up->stmt);
1177 c; c = OMP_CLAUSE_CHAIN (c))
1178 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
1179 && OMP_CLAUSE_DECL (c) == decl)
1180 break;
1181
1182 if (c)
1183 goto maybe_mark_addressable_and_ret;
1184 }
1185 }
1186
1187 /* For tasks avoid using copy-in/out. As tasks can be
1188 deferred or executed in different thread, when GOMP_task
1189 returns, the task hasn't necessarily terminated. */
1190 if (is_task_ctx (shared_ctx))
1191 {
1192 tree outer;
1193 maybe_mark_addressable_and_ret:
1194 outer = maybe_lookup_decl_in_outer_ctx (decl, shared_ctx);
1195 if (is_gimple_reg (outer) && !omp_member_access_dummy_var (outer))
1196 {
1197 /* Taking address of OUTER in lower_send_shared_vars
1198 might need regimplification of everything that uses the
1199 variable. */
1200 if (!task_shared_vars)
1201 task_shared_vars = BITMAP_ALLOC (NULL);
1202 bitmap_set_bit (task_shared_vars, DECL_UID (outer));
1203 TREE_ADDRESSABLE (outer) = 1;
1204 }
1205 return true;
1206 }
1207 }
1208
1209 return false;
1210 }
1211
1212 /* Construct a new automatic decl similar to VAR. */
1213
1214 static tree
1215 omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx)
1216 {
1217 tree copy = copy_var_decl (var, name, type);
1218
1219 DECL_CONTEXT (copy) = current_function_decl;
1220 DECL_CHAIN (copy) = ctx->block_vars;
1221 /* If VAR is listed in task_shared_vars, it means it wasn't
1222 originally addressable and is just because task needs to take
1223 it's address. But we don't need to take address of privatizations
1224 from that var. */
1225 if (TREE_ADDRESSABLE (var)
1226 && task_shared_vars
1227 && bitmap_bit_p (task_shared_vars, DECL_UID (var)))
1228 TREE_ADDRESSABLE (copy) = 0;
1229 ctx->block_vars = copy;
1230
1231 return copy;
1232 }
1233
1234 static tree
1235 omp_copy_decl_1 (tree var, omp_context *ctx)
1236 {
1237 return omp_copy_decl_2 (var, DECL_NAME (var), TREE_TYPE (var), ctx);
1238 }
1239
1240 /* Build COMPONENT_REF and set TREE_THIS_VOLATILE and TREE_READONLY on it
1241 as appropriate. */
1242 static tree
1243 omp_build_component_ref (tree obj, tree field)
1244 {
1245 tree ret = build3 (COMPONENT_REF, TREE_TYPE (field), obj, field, NULL);
1246 if (TREE_THIS_VOLATILE (field))
1247 TREE_THIS_VOLATILE (ret) |= 1;
1248 if (TREE_READONLY (field))
1249 TREE_READONLY (ret) |= 1;
1250 return ret;
1251 }
1252
1253 /* Build tree nodes to access the field for VAR on the receiver side. */
1254
1255 static tree
1256 build_receiver_ref (tree var, bool by_ref, omp_context *ctx)
1257 {
1258 tree x, field = lookup_field (var, ctx);
1259
1260 /* If the receiver record type was remapped in the child function,
1261 remap the field into the new record type. */
1262 x = maybe_lookup_field (field, ctx);
1263 if (x != NULL)
1264 field = x;
1265
1266 x = build_simple_mem_ref (ctx->receiver_decl);
1267 TREE_THIS_NOTRAP (x) = 1;
1268 x = omp_build_component_ref (x, field);
1269 if (by_ref)
1270 {
1271 x = build_simple_mem_ref (x);
1272 TREE_THIS_NOTRAP (x) = 1;
1273 }
1274
1275 return x;
1276 }
1277
1278 /* Build tree nodes to access VAR in the scope outer to CTX. In the case
1279 of a parallel, this is a component reference; for workshare constructs
1280 this is some variable. */
1281
1282 static tree
1283 build_outer_var_ref (tree var, omp_context *ctx, bool lastprivate = false)
1284 {
1285 tree x;
1286
1287 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx)))
1288 x = var;
1289 else if (is_variable_sized (var))
1290 {
1291 x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
1292 x = build_outer_var_ref (x, ctx, lastprivate);
1293 x = build_simple_mem_ref (x);
1294 }
1295 else if (is_taskreg_ctx (ctx))
1296 {
1297 bool by_ref = use_pointer_for_field (var, NULL);
1298 x = build_receiver_ref (var, by_ref, ctx);
1299 }
1300 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
1301 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
1302 {
1303 /* #pragma omp simd isn't a worksharing construct, and can reference even
1304 private vars in its linear etc. clauses. */
1305 x = NULL_TREE;
1306 if (ctx->outer && is_taskreg_ctx (ctx))
1307 x = lookup_decl (var, ctx->outer);
1308 else if (ctx->outer)
1309 x = maybe_lookup_decl_in_outer_ctx (var, ctx);
1310 if (x == NULL_TREE)
1311 x = var;
1312 }
1313 else if (lastprivate && is_taskloop_ctx (ctx))
1314 {
1315 gcc_assert (ctx->outer);
1316 splay_tree_node n
1317 = splay_tree_lookup (ctx->outer->field_map,
1318 (splay_tree_key) &DECL_UID (var));
1319 if (n == NULL)
1320 {
1321 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx->outer)))
1322 x = var;
1323 else
1324 x = lookup_decl (var, ctx->outer);
1325 }
1326 else
1327 {
1328 tree field = (tree) n->value;
1329 /* If the receiver record type was remapped in the child function,
1330 remap the field into the new record type. */
1331 x = maybe_lookup_field (field, ctx->outer);
1332 if (x != NULL)
1333 field = x;
1334
1335 x = build_simple_mem_ref (ctx->outer->receiver_decl);
1336 x = omp_build_component_ref (x, field);
1337 if (use_pointer_for_field (var, ctx->outer))
1338 x = build_simple_mem_ref (x);
1339 }
1340 }
1341 else if (ctx->outer)
1342 {
1343 omp_context *outer = ctx->outer;
1344 if (gimple_code (outer->stmt) == GIMPLE_OMP_GRID_BODY)
1345 {
1346 outer = outer->outer;
1347 gcc_assert (outer
1348 && gimple_code (outer->stmt) != GIMPLE_OMP_GRID_BODY);
1349 }
1350 x = lookup_decl (var, outer);
1351 }
1352 else if (is_reference (var))
1353 /* This can happen with orphaned constructs. If var is reference, it is
1354 possible it is shared and as such valid. */
1355 x = var;
1356 else if (omp_member_access_dummy_var (var))
1357 x = var;
1358 else
1359 gcc_unreachable ();
1360
1361 if (x == var)
1362 {
1363 tree t = omp_member_access_dummy_var (var);
1364 if (t)
1365 {
1366 x = DECL_VALUE_EXPR (var);
1367 tree o = maybe_lookup_decl_in_outer_ctx (t, ctx);
1368 if (o != t)
1369 x = unshare_and_remap (x, t, o);
1370 else
1371 x = unshare_expr (x);
1372 }
1373 }
1374
1375 if (is_reference (var))
1376 x = build_simple_mem_ref (x);
1377
1378 return x;
1379 }
1380
1381 /* Build tree nodes to access the field for VAR on the sender side. */
1382
1383 static tree
1384 build_sender_ref (splay_tree_key key, omp_context *ctx)
1385 {
1386 tree field = lookup_sfield (key, ctx);
1387 return omp_build_component_ref (ctx->sender_decl, field);
1388 }
1389
1390 static tree
1391 build_sender_ref (tree var, omp_context *ctx)
1392 {
1393 return build_sender_ref ((splay_tree_key) var, ctx);
1394 }
1395
1396 /* Add a new field for VAR inside the structure CTX->SENDER_DECL. If
1397 BASE_POINTERS_RESTRICT, declare the field with restrict. */
1398
1399 static void
1400 install_var_field (tree var, bool by_ref, int mask, omp_context *ctx,
1401 bool base_pointers_restrict = false)
1402 {
1403 tree field, type, sfield = NULL_TREE;
1404 splay_tree_key key = (splay_tree_key) var;
1405
1406 if ((mask & 8) != 0)
1407 {
1408 key = (splay_tree_key) &DECL_UID (var);
1409 gcc_checking_assert (key != (splay_tree_key) var);
1410 }
1411 gcc_assert ((mask & 1) == 0
1412 || !splay_tree_lookup (ctx->field_map, key));
1413 gcc_assert ((mask & 2) == 0 || !ctx->sfield_map
1414 || !splay_tree_lookup (ctx->sfield_map, key));
1415 gcc_assert ((mask & 3) == 3
1416 || !is_gimple_omp_oacc (ctx->stmt));
1417
1418 type = TREE_TYPE (var);
1419 /* Prevent redeclaring the var in the split-off function with a restrict
1420 pointer type. Note that we only clear type itself, restrict qualifiers in
1421 the pointed-to type will be ignored by points-to analysis. */
1422 if (POINTER_TYPE_P (type)
1423 && TYPE_RESTRICT (type))
1424 type = build_qualified_type (type, TYPE_QUALS (type) & ~TYPE_QUAL_RESTRICT);
1425
1426 if (mask & 4)
1427 {
1428 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
1429 type = build_pointer_type (build_pointer_type (type));
1430 }
1431 else if (by_ref)
1432 {
1433 type = build_pointer_type (type);
1434 if (base_pointers_restrict)
1435 type = build_qualified_type (type, TYPE_QUAL_RESTRICT);
1436 }
1437 else if ((mask & 3) == 1 && is_reference (var))
1438 type = TREE_TYPE (type);
1439
1440 field = build_decl (DECL_SOURCE_LOCATION (var),
1441 FIELD_DECL, DECL_NAME (var), type);
1442
1443 /* Remember what variable this field was created for. This does have a
1444 side effect of making dwarf2out ignore this member, so for helpful
1445 debugging we clear it later in delete_omp_context. */
1446 DECL_ABSTRACT_ORIGIN (field) = var;
1447 if (type == TREE_TYPE (var))
1448 {
1449 SET_DECL_ALIGN (field, DECL_ALIGN (var));
1450 DECL_USER_ALIGN (field) = DECL_USER_ALIGN (var);
1451 TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (var);
1452 }
1453 else
1454 SET_DECL_ALIGN (field, TYPE_ALIGN (type));
1455
1456 if ((mask & 3) == 3)
1457 {
1458 insert_field_into_struct (ctx->record_type, field);
1459 if (ctx->srecord_type)
1460 {
1461 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1462 FIELD_DECL, DECL_NAME (var), type);
1463 DECL_ABSTRACT_ORIGIN (sfield) = var;
1464 SET_DECL_ALIGN (sfield, DECL_ALIGN (field));
1465 DECL_USER_ALIGN (sfield) = DECL_USER_ALIGN (field);
1466 TREE_THIS_VOLATILE (sfield) = TREE_THIS_VOLATILE (field);
1467 insert_field_into_struct (ctx->srecord_type, sfield);
1468 }
1469 }
1470 else
1471 {
1472 if (ctx->srecord_type == NULL_TREE)
1473 {
1474 tree t;
1475
1476 ctx->srecord_type = lang_hooks.types.make_type (RECORD_TYPE);
1477 ctx->sfield_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1478 for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
1479 {
1480 sfield = build_decl (DECL_SOURCE_LOCATION (t),
1481 FIELD_DECL, DECL_NAME (t), TREE_TYPE (t));
1482 DECL_ABSTRACT_ORIGIN (sfield) = DECL_ABSTRACT_ORIGIN (t);
1483 insert_field_into_struct (ctx->srecord_type, sfield);
1484 splay_tree_insert (ctx->sfield_map,
1485 (splay_tree_key) DECL_ABSTRACT_ORIGIN (t),
1486 (splay_tree_value) sfield);
1487 }
1488 }
1489 sfield = field;
1490 insert_field_into_struct ((mask & 1) ? ctx->record_type
1491 : ctx->srecord_type, field);
1492 }
1493
1494 if (mask & 1)
1495 splay_tree_insert (ctx->field_map, key, (splay_tree_value) field);
1496 if ((mask & 2) && ctx->sfield_map)
1497 splay_tree_insert (ctx->sfield_map, key, (splay_tree_value) sfield);
1498 }
1499
1500 static tree
1501 install_var_local (tree var, omp_context *ctx)
1502 {
1503 tree new_var = omp_copy_decl_1 (var, ctx);
1504 insert_decl_map (&ctx->cb, var, new_var);
1505 return new_var;
1506 }
1507
1508 /* Adjust the replacement for DECL in CTX for the new context. This means
1509 copying the DECL_VALUE_EXPR, and fixing up the type. */
1510
1511 static void
1512 fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug)
1513 {
1514 tree new_decl, size;
1515
1516 new_decl = lookup_decl (decl, ctx);
1517
1518 TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb);
1519
1520 if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug)
1521 && DECL_HAS_VALUE_EXPR_P (decl))
1522 {
1523 tree ve = DECL_VALUE_EXPR (decl);
1524 walk_tree (&ve, copy_tree_body_r, &ctx->cb, NULL);
1525 SET_DECL_VALUE_EXPR (new_decl, ve);
1526 DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
1527 }
1528
1529 if (!TREE_CONSTANT (DECL_SIZE (new_decl)))
1530 {
1531 size = remap_decl (DECL_SIZE (decl), &ctx->cb);
1532 if (size == error_mark_node)
1533 size = TYPE_SIZE (TREE_TYPE (new_decl));
1534 DECL_SIZE (new_decl) = size;
1535
1536 size = remap_decl (DECL_SIZE_UNIT (decl), &ctx->cb);
1537 if (size == error_mark_node)
1538 size = TYPE_SIZE_UNIT (TREE_TYPE (new_decl));
1539 DECL_SIZE_UNIT (new_decl) = size;
1540 }
1541 }
1542
1543 /* The callback for remap_decl. Search all containing contexts for a
1544 mapping of the variable; this avoids having to duplicate the splay
1545 tree ahead of time. We know a mapping doesn't already exist in the
1546 given context. Create new mappings to implement default semantics. */
1547
1548 static tree
1549 omp_copy_decl (tree var, copy_body_data *cb)
1550 {
1551 omp_context *ctx = (omp_context *) cb;
1552 tree new_var;
1553
1554 if (TREE_CODE (var) == LABEL_DECL)
1555 {
1556 new_var = create_artificial_label (DECL_SOURCE_LOCATION (var));
1557 DECL_CONTEXT (new_var) = current_function_decl;
1558 insert_decl_map (&ctx->cb, var, new_var);
1559 return new_var;
1560 }
1561
1562 while (!is_taskreg_ctx (ctx))
1563 {
1564 ctx = ctx->outer;
1565 if (ctx == NULL)
1566 return var;
1567 new_var = maybe_lookup_decl (var, ctx);
1568 if (new_var)
1569 return new_var;
1570 }
1571
1572 if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn)
1573 return var;
1574
1575 return error_mark_node;
1576 }
1577
1578
1579 /* Debugging dumps for parallel regions. */
1580 void dump_omp_region (FILE *, struct omp_region *, int);
1581 void debug_omp_region (struct omp_region *);
1582 void debug_all_omp_regions (void);
1583
1584 /* Dump the parallel region tree rooted at REGION. */
1585
1586 void
1587 dump_omp_region (FILE *file, struct omp_region *region, int indent)
1588 {
1589 fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index,
1590 gimple_code_name[region->type]);
1591
1592 if (region->inner)
1593 dump_omp_region (file, region->inner, indent + 4);
1594
1595 if (region->cont)
1596 {
1597 fprintf (file, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent, "",
1598 region->cont->index);
1599 }
1600
1601 if (region->exit)
1602 fprintf (file, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent, "",
1603 region->exit->index);
1604 else
1605 fprintf (file, "%*s[no exit marker]\n", indent, "");
1606
1607 if (region->next)
1608 dump_omp_region (file, region->next, indent);
1609 }
1610
1611 DEBUG_FUNCTION void
1612 debug_omp_region (struct omp_region *region)
1613 {
1614 dump_omp_region (stderr, region, 0);
1615 }
1616
1617 DEBUG_FUNCTION void
1618 debug_all_omp_regions (void)
1619 {
1620 dump_omp_region (stderr, root_omp_region, 0);
1621 }
1622
1623
1624 /* Create a new parallel region starting at STMT inside region PARENT. */
1625
1626 static struct omp_region *
1627 new_omp_region (basic_block bb, enum gimple_code type,
1628 struct omp_region *parent)
1629 {
1630 struct omp_region *region = XCNEW (struct omp_region);
1631
1632 region->outer = parent;
1633 region->entry = bb;
1634 region->type = type;
1635
1636 if (parent)
1637 {
1638 /* This is a nested region. Add it to the list of inner
1639 regions in PARENT. */
1640 region->next = parent->inner;
1641 parent->inner = region;
1642 }
1643 else
1644 {
1645 /* This is a toplevel region. Add it to the list of toplevel
1646 regions in ROOT_OMP_REGION. */
1647 region->next = root_omp_region;
1648 root_omp_region = region;
1649 }
1650
1651 return region;
1652 }
1653
1654 /* Release the memory associated with the region tree rooted at REGION. */
1655
1656 static void
1657 free_omp_region_1 (struct omp_region *region)
1658 {
1659 struct omp_region *i, *n;
1660
1661 for (i = region->inner; i ; i = n)
1662 {
1663 n = i->next;
1664 free_omp_region_1 (i);
1665 }
1666
1667 free (region);
1668 }
1669
1670 /* Release the memory for the entire omp region tree. */
1671
1672 void
1673 free_omp_regions (void)
1674 {
1675 struct omp_region *r, *n;
1676 for (r = root_omp_region; r ; r = n)
1677 {
1678 n = r->next;
1679 free_omp_region_1 (r);
1680 }
1681 root_omp_region = NULL;
1682 }
1683
1684
1685 /* Create a new context, with OUTER_CTX being the surrounding context. */
1686
1687 static omp_context *
1688 new_omp_context (gimple *stmt, omp_context *outer_ctx)
1689 {
1690 omp_context *ctx = XCNEW (omp_context);
1691
1692 splay_tree_insert (all_contexts, (splay_tree_key) stmt,
1693 (splay_tree_value) ctx);
1694 ctx->stmt = stmt;
1695
1696 if (outer_ctx)
1697 {
1698 ctx->outer = outer_ctx;
1699 ctx->cb = outer_ctx->cb;
1700 ctx->cb.block = NULL;
1701 ctx->depth = outer_ctx->depth + 1;
1702 }
1703 else
1704 {
1705 ctx->cb.src_fn = current_function_decl;
1706 ctx->cb.dst_fn = current_function_decl;
1707 ctx->cb.src_node = cgraph_node::get (current_function_decl);
1708 gcc_checking_assert (ctx->cb.src_node);
1709 ctx->cb.dst_node = ctx->cb.src_node;
1710 ctx->cb.src_cfun = cfun;
1711 ctx->cb.copy_decl = omp_copy_decl;
1712 ctx->cb.eh_lp_nr = 0;
1713 ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
1714 ctx->depth = 1;
1715 }
1716
1717 ctx->cb.decl_map = new hash_map<tree, tree>;
1718
1719 return ctx;
1720 }
1721
1722 static gimple_seq maybe_catch_exception (gimple_seq);
1723
1724 /* Finalize task copyfn. */
1725
1726 static void
1727 finalize_task_copyfn (gomp_task *task_stmt)
1728 {
1729 struct function *child_cfun;
1730 tree child_fn;
1731 gimple_seq seq = NULL, new_seq;
1732 gbind *bind;
1733
1734 child_fn = gimple_omp_task_copy_fn (task_stmt);
1735 if (child_fn == NULL_TREE)
1736 return;
1737
1738 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
1739 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
1740
1741 push_cfun (child_cfun);
1742 bind = gimplify_body (child_fn, false);
1743 gimple_seq_add_stmt (&seq, bind);
1744 new_seq = maybe_catch_exception (seq);
1745 if (new_seq != seq)
1746 {
1747 bind = gimple_build_bind (NULL, new_seq, NULL);
1748 seq = NULL;
1749 gimple_seq_add_stmt (&seq, bind);
1750 }
1751 gimple_set_body (child_fn, seq);
1752 pop_cfun ();
1753
1754 /* Inform the callgraph about the new function. */
1755 cgraph_node *node = cgraph_node::get_create (child_fn);
1756 node->parallelized_function = 1;
1757 cgraph_node::add_new_function (child_fn, false);
1758 }
1759
1760 /* Destroy a omp_context data structures. Called through the splay tree
1761 value delete callback. */
1762
1763 static void
1764 delete_omp_context (splay_tree_value value)
1765 {
1766 omp_context *ctx = (omp_context *) value;
1767
1768 delete ctx->cb.decl_map;
1769
1770 if (ctx->field_map)
1771 splay_tree_delete (ctx->field_map);
1772 if (ctx->sfield_map)
1773 splay_tree_delete (ctx->sfield_map);
1774
1775 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
1776 it produces corrupt debug information. */
1777 if (ctx->record_type)
1778 {
1779 tree t;
1780 for (t = TYPE_FIELDS (ctx->record_type); t ; t = DECL_CHAIN (t))
1781 DECL_ABSTRACT_ORIGIN (t) = NULL;
1782 }
1783 if (ctx->srecord_type)
1784 {
1785 tree t;
1786 for (t = TYPE_FIELDS (ctx->srecord_type); t ; t = DECL_CHAIN (t))
1787 DECL_ABSTRACT_ORIGIN (t) = NULL;
1788 }
1789
1790 if (is_task_ctx (ctx))
1791 finalize_task_copyfn (as_a <gomp_task *> (ctx->stmt));
1792
1793 XDELETE (ctx);
1794 }
1795
1796 /* Fix up RECEIVER_DECL with a type that has been remapped to the child
1797 context. */
1798
1799 static void
1800 fixup_child_record_type (omp_context *ctx)
1801 {
1802 tree f, type = ctx->record_type;
1803
1804 if (!ctx->receiver_decl)
1805 return;
1806 /* ??? It isn't sufficient to just call remap_type here, because
1807 variably_modified_type_p doesn't work the way we expect for
1808 record types. Testing each field for whether it needs remapping
1809 and creating a new record by hand works, however. */
1810 for (f = TYPE_FIELDS (type); f ; f = DECL_CHAIN (f))
1811 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
1812 break;
1813 if (f)
1814 {
1815 tree name, new_fields = NULL;
1816
1817 type = lang_hooks.types.make_type (RECORD_TYPE);
1818 name = DECL_NAME (TYPE_NAME (ctx->record_type));
1819 name = build_decl (DECL_SOURCE_LOCATION (ctx->receiver_decl),
1820 TYPE_DECL, name, type);
1821 TYPE_NAME (type) = name;
1822
1823 for (f = TYPE_FIELDS (ctx->record_type); f ; f = DECL_CHAIN (f))
1824 {
1825 tree new_f = copy_node (f);
1826 DECL_CONTEXT (new_f) = type;
1827 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
1828 DECL_CHAIN (new_f) = new_fields;
1829 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &ctx->cb, NULL);
1830 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r,
1831 &ctx->cb, NULL);
1832 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
1833 &ctx->cb, NULL);
1834 new_fields = new_f;
1835
1836 /* Arrange to be able to look up the receiver field
1837 given the sender field. */
1838 splay_tree_insert (ctx->field_map, (splay_tree_key) f,
1839 (splay_tree_value) new_f);
1840 }
1841 TYPE_FIELDS (type) = nreverse (new_fields);
1842 layout_type (type);
1843 }
1844
1845 /* In a target region we never modify any of the pointers in *.omp_data_i,
1846 so attempt to help the optimizers. */
1847 if (is_gimple_omp_offloaded (ctx->stmt))
1848 type = build_qualified_type (type, TYPE_QUAL_CONST);
1849
1850 TREE_TYPE (ctx->receiver_decl)
1851 = build_qualified_type (build_reference_type (type), TYPE_QUAL_RESTRICT);
1852 }
1853
1854 /* Instantiate decls as necessary in CTX to satisfy the data sharing
1855 specified by CLAUSES. If BASE_POINTERS_RESTRICT, install var field with
1856 restrict. */
1857
1858 static void
1859 scan_sharing_clauses (tree clauses, omp_context *ctx,
1860 bool base_pointers_restrict = false)
1861 {
1862 tree c, decl;
1863 bool scan_array_reductions = false;
1864
1865 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1866 {
1867 bool by_ref;
1868
1869 switch (OMP_CLAUSE_CODE (c))
1870 {
1871 case OMP_CLAUSE_PRIVATE:
1872 decl = OMP_CLAUSE_DECL (c);
1873 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
1874 goto do_private;
1875 else if (!is_variable_sized (decl))
1876 install_var_local (decl, ctx);
1877 break;
1878
1879 case OMP_CLAUSE_SHARED:
1880 decl = OMP_CLAUSE_DECL (c);
1881 /* Ignore shared directives in teams construct. */
1882 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1883 {
1884 /* Global variables don't need to be copied,
1885 the receiver side will use them directly. */
1886 tree odecl = maybe_lookup_decl_in_outer_ctx (decl, ctx);
1887 if (is_global_var (odecl))
1888 break;
1889 insert_decl_map (&ctx->cb, decl, odecl);
1890 break;
1891 }
1892 gcc_assert (is_taskreg_ctx (ctx));
1893 gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl))
1894 || !is_variable_sized (decl));
1895 /* Global variables don't need to be copied,
1896 the receiver side will use them directly. */
1897 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1898 break;
1899 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
1900 {
1901 use_pointer_for_field (decl, ctx);
1902 break;
1903 }
1904 by_ref = use_pointer_for_field (decl, NULL);
1905 if ((! TREE_READONLY (decl) && !OMP_CLAUSE_SHARED_READONLY (c))
1906 || TREE_ADDRESSABLE (decl)
1907 || by_ref
1908 || is_reference (decl))
1909 {
1910 by_ref = use_pointer_for_field (decl, ctx);
1911 install_var_field (decl, by_ref, 3, ctx);
1912 install_var_local (decl, ctx);
1913 break;
1914 }
1915 /* We don't need to copy const scalar vars back. */
1916 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
1917 goto do_private;
1918
1919 case OMP_CLAUSE_REDUCTION:
1920 decl = OMP_CLAUSE_DECL (c);
1921 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1922 && TREE_CODE (decl) == MEM_REF)
1923 {
1924 tree t = TREE_OPERAND (decl, 0);
1925 if (TREE_CODE (t) == POINTER_PLUS_EXPR)
1926 t = TREE_OPERAND (t, 0);
1927 if (TREE_CODE (t) == INDIRECT_REF
1928 || TREE_CODE (t) == ADDR_EXPR)
1929 t = TREE_OPERAND (t, 0);
1930 install_var_local (t, ctx);
1931 if (is_taskreg_ctx (ctx)
1932 && !is_global_var (maybe_lookup_decl_in_outer_ctx (t, ctx))
1933 && !is_variable_sized (t))
1934 {
1935 by_ref = use_pointer_for_field (t, ctx);
1936 install_var_field (t, by_ref, 3, ctx);
1937 }
1938 break;
1939 }
1940 goto do_private;
1941
1942 case OMP_CLAUSE_LASTPRIVATE:
1943 /* Let the corresponding firstprivate clause create
1944 the variable. */
1945 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1946 break;
1947 /* FALLTHRU */
1948
1949 case OMP_CLAUSE_FIRSTPRIVATE:
1950 case OMP_CLAUSE_LINEAR:
1951 decl = OMP_CLAUSE_DECL (c);
1952 do_private:
1953 if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
1954 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IS_DEVICE_PTR)
1955 && is_gimple_omp_offloaded (ctx->stmt))
1956 {
1957 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
1958 install_var_field (decl, !is_reference (decl), 3, ctx);
1959 else if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1960 install_var_field (decl, true, 3, ctx);
1961 else
1962 install_var_field (decl, false, 3, ctx);
1963 }
1964 if (is_variable_sized (decl))
1965 {
1966 if (is_task_ctx (ctx))
1967 install_var_field (decl, false, 1, ctx);
1968 break;
1969 }
1970 else if (is_taskreg_ctx (ctx))
1971 {
1972 bool global
1973 = is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx));
1974 by_ref = use_pointer_for_field (decl, NULL);
1975
1976 if (is_task_ctx (ctx)
1977 && (global || by_ref || is_reference (decl)))
1978 {
1979 install_var_field (decl, false, 1, ctx);
1980 if (!global)
1981 install_var_field (decl, by_ref, 2, ctx);
1982 }
1983 else if (!global)
1984 install_var_field (decl, by_ref, 3, ctx);
1985 }
1986 install_var_local (decl, ctx);
1987 break;
1988
1989 case OMP_CLAUSE_USE_DEVICE_PTR:
1990 decl = OMP_CLAUSE_DECL (c);
1991 if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1992 install_var_field (decl, true, 3, ctx);
1993 else
1994 install_var_field (decl, false, 3, ctx);
1995 if (DECL_SIZE (decl)
1996 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1997 {
1998 tree decl2 = DECL_VALUE_EXPR (decl);
1999 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2000 decl2 = TREE_OPERAND (decl2, 0);
2001 gcc_assert (DECL_P (decl2));
2002 install_var_local (decl2, ctx);
2003 }
2004 install_var_local (decl, ctx);
2005 break;
2006
2007 case OMP_CLAUSE_IS_DEVICE_PTR:
2008 decl = OMP_CLAUSE_DECL (c);
2009 goto do_private;
2010
2011 case OMP_CLAUSE__LOOPTEMP_:
2012 gcc_assert (is_taskreg_ctx (ctx));
2013 decl = OMP_CLAUSE_DECL (c);
2014 install_var_field (decl, false, 3, ctx);
2015 install_var_local (decl, ctx);
2016 break;
2017
2018 case OMP_CLAUSE_COPYPRIVATE:
2019 case OMP_CLAUSE_COPYIN:
2020 decl = OMP_CLAUSE_DECL (c);
2021 by_ref = use_pointer_for_field (decl, NULL);
2022 install_var_field (decl, by_ref, 3, ctx);
2023 break;
2024
2025 case OMP_CLAUSE_DEFAULT:
2026 ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
2027 break;
2028
2029 case OMP_CLAUSE_FINAL:
2030 case OMP_CLAUSE_IF:
2031 case OMP_CLAUSE_NUM_THREADS:
2032 case OMP_CLAUSE_NUM_TEAMS:
2033 case OMP_CLAUSE_THREAD_LIMIT:
2034 case OMP_CLAUSE_DEVICE:
2035 case OMP_CLAUSE_SCHEDULE:
2036 case OMP_CLAUSE_DIST_SCHEDULE:
2037 case OMP_CLAUSE_DEPEND:
2038 case OMP_CLAUSE_PRIORITY:
2039 case OMP_CLAUSE_GRAINSIZE:
2040 case OMP_CLAUSE_NUM_TASKS:
2041 case OMP_CLAUSE__CILK_FOR_COUNT_:
2042 case OMP_CLAUSE_NUM_GANGS:
2043 case OMP_CLAUSE_NUM_WORKERS:
2044 case OMP_CLAUSE_VECTOR_LENGTH:
2045 if (ctx->outer)
2046 scan_omp_op (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
2047 break;
2048
2049 case OMP_CLAUSE_TO:
2050 case OMP_CLAUSE_FROM:
2051 case OMP_CLAUSE_MAP:
2052 if (ctx->outer)
2053 scan_omp_op (&OMP_CLAUSE_SIZE (c), ctx->outer);
2054 decl = OMP_CLAUSE_DECL (c);
2055 /* Global variables with "omp declare target" attribute
2056 don't need to be copied, the receiver side will use them
2057 directly. However, global variables with "omp declare target link"
2058 attribute need to be copied. */
2059 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
2060 && DECL_P (decl)
2061 && ((OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_FIRSTPRIVATE_POINTER
2062 && (OMP_CLAUSE_MAP_KIND (c)
2063 != GOMP_MAP_FIRSTPRIVATE_REFERENCE))
2064 || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
2065 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
2066 && varpool_node::get_create (decl)->offloadable
2067 && !lookup_attribute ("omp declare target link",
2068 DECL_ATTRIBUTES (decl)))
2069 break;
2070 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
2071 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER)
2072 {
2073 /* Ignore GOMP_MAP_POINTER kind for arrays in regions that are
2074 not offloaded; there is nothing to map for those. */
2075 if (!is_gimple_omp_offloaded (ctx->stmt)
2076 && !POINTER_TYPE_P (TREE_TYPE (decl))
2077 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
2078 break;
2079 }
2080 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
2081 && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
2082 || (OMP_CLAUSE_MAP_KIND (c)
2083 == GOMP_MAP_FIRSTPRIVATE_REFERENCE)))
2084 {
2085 if (TREE_CODE (decl) == COMPONENT_REF
2086 || (TREE_CODE (decl) == INDIRECT_REF
2087 && TREE_CODE (TREE_OPERAND (decl, 0)) == COMPONENT_REF
2088 && (TREE_CODE (TREE_TYPE (TREE_OPERAND (decl, 0)))
2089 == REFERENCE_TYPE)))
2090 break;
2091 if (DECL_SIZE (decl)
2092 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
2093 {
2094 tree decl2 = DECL_VALUE_EXPR (decl);
2095 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2096 decl2 = TREE_OPERAND (decl2, 0);
2097 gcc_assert (DECL_P (decl2));
2098 install_var_local (decl2, ctx);
2099 }
2100 install_var_local (decl, ctx);
2101 break;
2102 }
2103 if (DECL_P (decl))
2104 {
2105 if (DECL_SIZE (decl)
2106 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
2107 {
2108 tree decl2 = DECL_VALUE_EXPR (decl);
2109 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2110 decl2 = TREE_OPERAND (decl2, 0);
2111 gcc_assert (DECL_P (decl2));
2112 install_var_field (decl2, true, 3, ctx);
2113 install_var_local (decl2, ctx);
2114 install_var_local (decl, ctx);
2115 }
2116 else
2117 {
2118 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
2119 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
2120 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
2121 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
2122 install_var_field (decl, true, 7, ctx);
2123 else
2124 install_var_field (decl, true, 3, ctx,
2125 base_pointers_restrict);
2126 if (is_gimple_omp_offloaded (ctx->stmt)
2127 && !OMP_CLAUSE_MAP_IN_REDUCTION (c))
2128 install_var_local (decl, ctx);
2129 }
2130 }
2131 else
2132 {
2133 tree base = get_base_address (decl);
2134 tree nc = OMP_CLAUSE_CHAIN (c);
2135 if (DECL_P (base)
2136 && nc != NULL_TREE
2137 && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
2138 && OMP_CLAUSE_DECL (nc) == base
2139 && OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_POINTER
2140 && integer_zerop (OMP_CLAUSE_SIZE (nc)))
2141 {
2142 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c) = 1;
2143 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (nc) = 1;
2144 }
2145 else
2146 {
2147 if (ctx->outer)
2148 {
2149 scan_omp_op (&OMP_CLAUSE_DECL (c), ctx->outer);
2150 decl = OMP_CLAUSE_DECL (c);
2151 }
2152 gcc_assert (!splay_tree_lookup (ctx->field_map,
2153 (splay_tree_key) decl));
2154 tree field
2155 = build_decl (OMP_CLAUSE_LOCATION (c),
2156 FIELD_DECL, NULL_TREE, ptr_type_node);
2157 SET_DECL_ALIGN (field, TYPE_ALIGN (ptr_type_node));
2158 insert_field_into_struct (ctx->record_type, field);
2159 splay_tree_insert (ctx->field_map, (splay_tree_key) decl,
2160 (splay_tree_value) field);
2161 }
2162 }
2163 break;
2164
2165 case OMP_CLAUSE__GRIDDIM_:
2166 if (ctx->outer)
2167 {
2168 scan_omp_op (&OMP_CLAUSE__GRIDDIM__SIZE (c), ctx->outer);
2169 scan_omp_op (&OMP_CLAUSE__GRIDDIM__GROUP (c), ctx->outer);
2170 }
2171 break;
2172
2173 case OMP_CLAUSE_NOWAIT:
2174 case OMP_CLAUSE_ORDERED:
2175 case OMP_CLAUSE_COLLAPSE:
2176 case OMP_CLAUSE_UNTIED:
2177 case OMP_CLAUSE_MERGEABLE:
2178 case OMP_CLAUSE_PROC_BIND:
2179 case OMP_CLAUSE_SAFELEN:
2180 case OMP_CLAUSE_SIMDLEN:
2181 case OMP_CLAUSE_THREADS:
2182 case OMP_CLAUSE_SIMD:
2183 case OMP_CLAUSE_NOGROUP:
2184 case OMP_CLAUSE_DEFAULTMAP:
2185 case OMP_CLAUSE_ASYNC:
2186 case OMP_CLAUSE_WAIT:
2187 case OMP_CLAUSE_GANG:
2188 case OMP_CLAUSE_WORKER:
2189 case OMP_CLAUSE_VECTOR:
2190 case OMP_CLAUSE_INDEPENDENT:
2191 case OMP_CLAUSE_AUTO:
2192 case OMP_CLAUSE_SEQ:
2193 break;
2194
2195 case OMP_CLAUSE_ALIGNED:
2196 decl = OMP_CLAUSE_DECL (c);
2197 if (is_global_var (decl)
2198 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
2199 install_var_local (decl, ctx);
2200 break;
2201
2202 case OMP_CLAUSE_TILE:
2203 case OMP_CLAUSE__CACHE_:
2204 default:
2205 gcc_unreachable ();
2206 }
2207 }
2208
2209 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2210 {
2211 switch (OMP_CLAUSE_CODE (c))
2212 {
2213 case OMP_CLAUSE_LASTPRIVATE:
2214 /* Let the corresponding firstprivate clause create
2215 the variable. */
2216 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
2217 scan_array_reductions = true;
2218 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
2219 break;
2220 /* FALLTHRU */
2221
2222 case OMP_CLAUSE_FIRSTPRIVATE:
2223 case OMP_CLAUSE_PRIVATE:
2224 case OMP_CLAUSE_LINEAR:
2225 case OMP_CLAUSE_IS_DEVICE_PTR:
2226 decl = OMP_CLAUSE_DECL (c);
2227 if (is_variable_sized (decl))
2228 {
2229 if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
2230 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IS_DEVICE_PTR)
2231 && is_gimple_omp_offloaded (ctx->stmt))
2232 {
2233 tree decl2 = DECL_VALUE_EXPR (decl);
2234 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2235 decl2 = TREE_OPERAND (decl2, 0);
2236 gcc_assert (DECL_P (decl2));
2237 install_var_local (decl2, ctx);
2238 fixup_remapped_decl (decl2, ctx, false);
2239 }
2240 install_var_local (decl, ctx);
2241 }
2242 fixup_remapped_decl (decl, ctx,
2243 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
2244 && OMP_CLAUSE_PRIVATE_DEBUG (c));
2245 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
2246 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
2247 scan_array_reductions = true;
2248 break;
2249
2250 case OMP_CLAUSE_REDUCTION:
2251 decl = OMP_CLAUSE_DECL (c);
2252 if (TREE_CODE (decl) != MEM_REF)
2253 {
2254 if (is_variable_sized (decl))
2255 install_var_local (decl, ctx);
2256 fixup_remapped_decl (decl, ctx, false);
2257 }
2258 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2259 scan_array_reductions = true;
2260 break;
2261
2262 case OMP_CLAUSE_SHARED:
2263 /* Ignore shared directives in teams construct. */
2264 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
2265 break;
2266 decl = OMP_CLAUSE_DECL (c);
2267 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
2268 break;
2269 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
2270 {
2271 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl,
2272 ctx->outer)))
2273 break;
2274 bool by_ref = use_pointer_for_field (decl, ctx);
2275 install_var_field (decl, by_ref, 11, ctx);
2276 break;
2277 }
2278 fixup_remapped_decl (decl, ctx, false);
2279 break;
2280
2281 case OMP_CLAUSE_MAP:
2282 if (!is_gimple_omp_offloaded (ctx->stmt))
2283 break;
2284 decl = OMP_CLAUSE_DECL (c);
2285 if (DECL_P (decl)
2286 && ((OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_FIRSTPRIVATE_POINTER
2287 && (OMP_CLAUSE_MAP_KIND (c)
2288 != GOMP_MAP_FIRSTPRIVATE_REFERENCE))
2289 || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
2290 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
2291 && varpool_node::get_create (decl)->offloadable)
2292 break;
2293 if (DECL_P (decl))
2294 {
2295 if ((OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
2296 || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER)
2297 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
2298 && !COMPLETE_TYPE_P (TREE_TYPE (decl)))
2299 {
2300 tree new_decl = lookup_decl (decl, ctx);
2301 TREE_TYPE (new_decl)
2302 = remap_type (TREE_TYPE (decl), &ctx->cb);
2303 }
2304 else if (DECL_SIZE (decl)
2305 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
2306 {
2307 tree decl2 = DECL_VALUE_EXPR (decl);
2308 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2309 decl2 = TREE_OPERAND (decl2, 0);
2310 gcc_assert (DECL_P (decl2));
2311 fixup_remapped_decl (decl2, ctx, false);
2312 fixup_remapped_decl (decl, ctx, true);
2313 }
2314 else
2315 fixup_remapped_decl (decl, ctx, false);
2316 }
2317 break;
2318
2319 case OMP_CLAUSE_COPYPRIVATE:
2320 case OMP_CLAUSE_COPYIN:
2321 case OMP_CLAUSE_DEFAULT:
2322 case OMP_CLAUSE_IF:
2323 case OMP_CLAUSE_NUM_THREADS:
2324 case OMP_CLAUSE_NUM_TEAMS:
2325 case OMP_CLAUSE_THREAD_LIMIT:
2326 case OMP_CLAUSE_DEVICE:
2327 case OMP_CLAUSE_SCHEDULE:
2328 case OMP_CLAUSE_DIST_SCHEDULE:
2329 case OMP_CLAUSE_NOWAIT:
2330 case OMP_CLAUSE_ORDERED:
2331 case OMP_CLAUSE_COLLAPSE:
2332 case OMP_CLAUSE_UNTIED:
2333 case OMP_CLAUSE_FINAL:
2334 case OMP_CLAUSE_MERGEABLE:
2335 case OMP_CLAUSE_PROC_BIND:
2336 case OMP_CLAUSE_SAFELEN:
2337 case OMP_CLAUSE_SIMDLEN:
2338 case OMP_CLAUSE_ALIGNED:
2339 case OMP_CLAUSE_DEPEND:
2340 case OMP_CLAUSE__LOOPTEMP_:
2341 case OMP_CLAUSE_TO:
2342 case OMP_CLAUSE_FROM:
2343 case OMP_CLAUSE_PRIORITY:
2344 case OMP_CLAUSE_GRAINSIZE:
2345 case OMP_CLAUSE_NUM_TASKS:
2346 case OMP_CLAUSE_THREADS:
2347 case OMP_CLAUSE_SIMD:
2348 case OMP_CLAUSE_NOGROUP:
2349 case OMP_CLAUSE_DEFAULTMAP:
2350 case OMP_CLAUSE_USE_DEVICE_PTR:
2351 case OMP_CLAUSE__CILK_FOR_COUNT_:
2352 case OMP_CLAUSE_ASYNC:
2353 case OMP_CLAUSE_WAIT:
2354 case OMP_CLAUSE_NUM_GANGS:
2355 case OMP_CLAUSE_NUM_WORKERS:
2356 case OMP_CLAUSE_VECTOR_LENGTH:
2357 case OMP_CLAUSE_GANG:
2358 case OMP_CLAUSE_WORKER:
2359 case OMP_CLAUSE_VECTOR:
2360 case OMP_CLAUSE_INDEPENDENT:
2361 case OMP_CLAUSE_AUTO:
2362 case OMP_CLAUSE_SEQ:
2363 case OMP_CLAUSE__GRIDDIM_:
2364 break;
2365
2366 case OMP_CLAUSE_TILE:
2367 case OMP_CLAUSE__CACHE_:
2368 default:
2369 gcc_unreachable ();
2370 }
2371 }
2372
2373 gcc_checking_assert (!scan_array_reductions
2374 || !is_gimple_omp_oacc (ctx->stmt));
2375 if (scan_array_reductions)
2376 {
2377 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2378 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
2379 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2380 {
2381 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
2382 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
2383 }
2384 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
2385 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
2386 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
2387 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
2388 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
2389 scan_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
2390 }
2391 }
2392
2393 /* Create a new name for omp child function. Returns an identifier. If
2394 IS_CILK_FOR is true then the suffix for the child function is
2395 "_cilk_for_fn." */
2396
2397 static tree
2398 create_omp_child_function_name (bool task_copy, bool is_cilk_for)
2399 {
2400 if (is_cilk_for)
2401 return clone_function_name (current_function_decl, "_cilk_for_fn");
2402 return clone_function_name (current_function_decl,
2403 task_copy ? "_omp_cpyfn" : "_omp_fn");
2404 }
2405
2406 /* Returns the type of the induction variable for the child function for
2407 _Cilk_for and the types for _high and _low variables based on TYPE. */
2408
2409 static tree
2410 cilk_for_check_loop_diff_type (tree type)
2411 {
2412 if (TYPE_PRECISION (type) <= TYPE_PRECISION (uint32_type_node))
2413 {
2414 if (TYPE_UNSIGNED (type))
2415 return uint32_type_node;
2416 else
2417 return integer_type_node;
2418 }
2419 else
2420 {
2421 if (TYPE_UNSIGNED (type))
2422 return uint64_type_node;
2423 else
2424 return long_long_integer_type_node;
2425 }
2426 }
2427
2428 /* Build a decl for the omp child function. It'll not contain a body
2429 yet, just the bare decl. */
2430
2431 static void
2432 create_omp_child_function (omp_context *ctx, bool task_copy)
2433 {
2434 tree decl, type, name, t;
2435
2436 tree cilk_for_count
2437 = (flag_cilkplus && gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2438 ? find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
2439 OMP_CLAUSE__CILK_FOR_COUNT_) : NULL_TREE;
2440 tree cilk_var_type = NULL_TREE;
2441
2442 name = create_omp_child_function_name (task_copy,
2443 cilk_for_count != NULL_TREE);
2444 if (task_copy)
2445 type = build_function_type_list (void_type_node, ptr_type_node,
2446 ptr_type_node, NULL_TREE);
2447 else if (cilk_for_count)
2448 {
2449 type = TREE_TYPE (OMP_CLAUSE_OPERAND (cilk_for_count, 0));
2450 cilk_var_type = cilk_for_check_loop_diff_type (type);
2451 type = build_function_type_list (void_type_node, ptr_type_node,
2452 cilk_var_type, cilk_var_type, NULL_TREE);
2453 }
2454 else
2455 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
2456
2457 decl = build_decl (gimple_location (ctx->stmt), FUNCTION_DECL, name, type);
2458
2459 gcc_checking_assert (!is_gimple_omp_oacc (ctx->stmt)
2460 || !task_copy);
2461 if (!task_copy)
2462 ctx->cb.dst_fn = decl;
2463 else
2464 gimple_omp_task_set_copy_fn (ctx->stmt, decl);
2465
2466 TREE_STATIC (decl) = 1;
2467 TREE_USED (decl) = 1;
2468 DECL_ARTIFICIAL (decl) = 1;
2469 DECL_IGNORED_P (decl) = 0;
2470 TREE_PUBLIC (decl) = 0;
2471 DECL_UNINLINABLE (decl) = 1;
2472 DECL_EXTERNAL (decl) = 0;
2473 DECL_CONTEXT (decl) = NULL_TREE;
2474 DECL_INITIAL (decl) = make_node (BLOCK);
2475 if (cgraph_node::get (current_function_decl)->offloadable)
2476 cgraph_node::get_create (decl)->offloadable = 1;
2477 else
2478 {
2479 omp_context *octx;
2480 for (octx = ctx; octx; octx = octx->outer)
2481 if (is_gimple_omp_offloaded (octx->stmt))
2482 {
2483 cgraph_node::get_create (decl)->offloadable = 1;
2484 if (ENABLE_OFFLOADING)
2485 g->have_offload = true;
2486
2487 break;
2488 }
2489 }
2490
2491 if (cgraph_node::get_create (decl)->offloadable
2492 && !lookup_attribute ("omp declare target",
2493 DECL_ATTRIBUTES (current_function_decl)))
2494 DECL_ATTRIBUTES (decl)
2495 = tree_cons (get_identifier ("omp target entrypoint"),
2496 NULL_TREE, DECL_ATTRIBUTES (decl));
2497
2498 t = build_decl (DECL_SOURCE_LOCATION (decl),
2499 RESULT_DECL, NULL_TREE, void_type_node);
2500 DECL_ARTIFICIAL (t) = 1;
2501 DECL_IGNORED_P (t) = 1;
2502 DECL_CONTEXT (t) = decl;
2503 DECL_RESULT (decl) = t;
2504
2505 /* _Cilk_for's child function requires two extra parameters called
2506 __low and __high that are set the by Cilk runtime when it calls this
2507 function. */
2508 if (cilk_for_count)
2509 {
2510 t = build_decl (DECL_SOURCE_LOCATION (decl),
2511 PARM_DECL, get_identifier ("__high"), cilk_var_type);
2512 DECL_ARTIFICIAL (t) = 1;
2513 DECL_NAMELESS (t) = 1;
2514 DECL_ARG_TYPE (t) = ptr_type_node;
2515 DECL_CONTEXT (t) = current_function_decl;
2516 TREE_USED (t) = 1;
2517 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2518 DECL_ARGUMENTS (decl) = t;
2519
2520 t = build_decl (DECL_SOURCE_LOCATION (decl),
2521 PARM_DECL, get_identifier ("__low"), cilk_var_type);
2522 DECL_ARTIFICIAL (t) = 1;
2523 DECL_NAMELESS (t) = 1;
2524 DECL_ARG_TYPE (t) = ptr_type_node;
2525 DECL_CONTEXT (t) = current_function_decl;
2526 TREE_USED (t) = 1;
2527 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2528 DECL_ARGUMENTS (decl) = t;
2529 }
2530
2531 tree data_name = get_identifier (".omp_data_i");
2532 t = build_decl (DECL_SOURCE_LOCATION (decl), PARM_DECL, data_name,
2533 ptr_type_node);
2534 DECL_ARTIFICIAL (t) = 1;
2535 DECL_NAMELESS (t) = 1;
2536 DECL_ARG_TYPE (t) = ptr_type_node;
2537 DECL_CONTEXT (t) = current_function_decl;
2538 TREE_USED (t) = 1;
2539 TREE_READONLY (t) = 1;
2540 if (cilk_for_count)
2541 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2542 DECL_ARGUMENTS (decl) = t;
2543 if (!task_copy)
2544 ctx->receiver_decl = t;
2545 else
2546 {
2547 t = build_decl (DECL_SOURCE_LOCATION (decl),
2548 PARM_DECL, get_identifier (".omp_data_o"),
2549 ptr_type_node);
2550 DECL_ARTIFICIAL (t) = 1;
2551 DECL_NAMELESS (t) = 1;
2552 DECL_ARG_TYPE (t) = ptr_type_node;
2553 DECL_CONTEXT (t) = current_function_decl;
2554 TREE_USED (t) = 1;
2555 TREE_ADDRESSABLE (t) = 1;
2556 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2557 DECL_ARGUMENTS (decl) = t;
2558 }
2559
2560 /* Allocate memory for the function structure. The call to
2561 allocate_struct_function clobbers CFUN, so we need to restore
2562 it afterward. */
2563 push_struct_function (decl);
2564 cfun->function_end_locus = gimple_location (ctx->stmt);
2565 init_tree_ssa (cfun);
2566 pop_cfun ();
2567 }
2568
2569 /* Callback for walk_gimple_seq. Check if combined parallel
2570 contains gimple_omp_for_combined_into_p OMP_FOR. */
2571
2572 static tree
2573 find_combined_for (gimple_stmt_iterator *gsi_p,
2574 bool *handled_ops_p,
2575 struct walk_stmt_info *wi)
2576 {
2577 gimple *stmt = gsi_stmt (*gsi_p);
2578
2579 *handled_ops_p = true;
2580 switch (gimple_code (stmt))
2581 {
2582 WALK_SUBSTMTS;
2583
2584 case GIMPLE_OMP_FOR:
2585 if (gimple_omp_for_combined_into_p (stmt)
2586 && gimple_omp_for_kind (stmt)
2587 == *(const enum gf_mask *) (wi->info))
2588 {
2589 wi->info = stmt;
2590 return integer_zero_node;
2591 }
2592 break;
2593 default:
2594 break;
2595 }
2596 return NULL;
2597 }
2598
2599 /* Add _LOOPTEMP_ clauses on OpenMP parallel or task. */
2600
2601 static void
2602 add_taskreg_looptemp_clauses (enum gf_mask msk, gimple *stmt,
2603 omp_context *outer_ctx)
2604 {
2605 struct walk_stmt_info wi;
2606
2607 memset (&wi, 0, sizeof (wi));
2608 wi.val_only = true;
2609 wi.info = (void *) &msk;
2610 walk_gimple_seq (gimple_omp_body (stmt), find_combined_for, NULL, &wi);
2611 if (wi.info != (void *) &msk)
2612 {
2613 gomp_for *for_stmt = as_a <gomp_for *> ((gimple *) wi.info);
2614 struct omp_for_data fd;
2615 extract_omp_for_data (for_stmt, &fd, NULL);
2616 /* We need two temporaries with fd.loop.v type (istart/iend)
2617 and then (fd.collapse - 1) temporaries with the same
2618 type for count2 ... countN-1 vars if not constant. */
2619 size_t count = 2, i;
2620 tree type = fd.iter_type;
2621 if (fd.collapse > 1
2622 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
2623 {
2624 count += fd.collapse - 1;
2625 /* If there are lastprivate clauses on the inner
2626 GIMPLE_OMP_FOR, add one more temporaries for the total number
2627 of iterations (product of count1 ... countN-1). */
2628 if (find_omp_clause (gimple_omp_for_clauses (for_stmt),
2629 OMP_CLAUSE_LASTPRIVATE))
2630 count++;
2631 else if (msk == GF_OMP_FOR_KIND_FOR
2632 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
2633 OMP_CLAUSE_LASTPRIVATE))
2634 count++;
2635 }
2636 for (i = 0; i < count; i++)
2637 {
2638 tree temp = create_tmp_var (type);
2639 tree c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
2640 insert_decl_map (&outer_ctx->cb, temp, temp);
2641 OMP_CLAUSE_DECL (c) = temp;
2642 OMP_CLAUSE_CHAIN (c) = gimple_omp_taskreg_clauses (stmt);
2643 gimple_omp_taskreg_set_clauses (stmt, c);
2644 }
2645 }
2646 }
2647
2648 /* Scan an OpenMP parallel directive. */
2649
2650 static void
2651 scan_omp_parallel (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2652 {
2653 omp_context *ctx;
2654 tree name;
2655 gomp_parallel *stmt = as_a <gomp_parallel *> (gsi_stmt (*gsi));
2656
2657 /* Ignore parallel directives with empty bodies, unless there
2658 are copyin clauses. */
2659 if (optimize > 0
2660 && empty_body_p (gimple_omp_body (stmt))
2661 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
2662 OMP_CLAUSE_COPYIN) == NULL)
2663 {
2664 gsi_replace (gsi, gimple_build_nop (), false);
2665 return;
2666 }
2667
2668 if (gimple_omp_parallel_combined_p (stmt))
2669 add_taskreg_looptemp_clauses (GF_OMP_FOR_KIND_FOR, stmt, outer_ctx);
2670
2671 ctx = new_omp_context (stmt, outer_ctx);
2672 taskreg_contexts.safe_push (ctx);
2673 if (taskreg_nesting_level > 1)
2674 ctx->is_nested = true;
2675 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2676 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2677 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2678 name = create_tmp_var_name (".omp_data_s");
2679 name = build_decl (gimple_location (stmt),
2680 TYPE_DECL, name, ctx->record_type);
2681 DECL_ARTIFICIAL (name) = 1;
2682 DECL_NAMELESS (name) = 1;
2683 TYPE_NAME (ctx->record_type) = name;
2684 TYPE_ARTIFICIAL (ctx->record_type) = 1;
2685 if (!gimple_omp_parallel_grid_phony (stmt))
2686 {
2687 create_omp_child_function (ctx, false);
2688 gimple_omp_parallel_set_child_fn (stmt, ctx->cb.dst_fn);
2689 }
2690
2691 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt), ctx);
2692 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2693
2694 if (TYPE_FIELDS (ctx->record_type) == NULL)
2695 ctx->record_type = ctx->receiver_decl = NULL;
2696 }
2697
2698 /* Scan an OpenMP task directive. */
2699
2700 static void
2701 scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2702 {
2703 omp_context *ctx;
2704 tree name, t;
2705 gomp_task *stmt = as_a <gomp_task *> (gsi_stmt (*gsi));
2706
2707 /* Ignore task directives with empty bodies. */
2708 if (optimize > 0
2709 && empty_body_p (gimple_omp_body (stmt)))
2710 {
2711 gsi_replace (gsi, gimple_build_nop (), false);
2712 return;
2713 }
2714
2715 if (gimple_omp_task_taskloop_p (stmt))
2716 add_taskreg_looptemp_clauses (GF_OMP_FOR_KIND_TASKLOOP, stmt, outer_ctx);
2717
2718 ctx = new_omp_context (stmt, outer_ctx);
2719 taskreg_contexts.safe_push (ctx);
2720 if (taskreg_nesting_level > 1)
2721 ctx->is_nested = true;
2722 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2723 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2724 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2725 name = create_tmp_var_name (".omp_data_s");
2726 name = build_decl (gimple_location (stmt),
2727 TYPE_DECL, name, ctx->record_type);
2728 DECL_ARTIFICIAL (name) = 1;
2729 DECL_NAMELESS (name) = 1;
2730 TYPE_NAME (ctx->record_type) = name;
2731 TYPE_ARTIFICIAL (ctx->record_type) = 1;
2732 create_omp_child_function (ctx, false);
2733 gimple_omp_task_set_child_fn (stmt, ctx->cb.dst_fn);
2734
2735 scan_sharing_clauses (gimple_omp_task_clauses (stmt), ctx);
2736
2737 if (ctx->srecord_type)
2738 {
2739 name = create_tmp_var_name (".omp_data_a");
2740 name = build_decl (gimple_location (stmt),
2741 TYPE_DECL, name, ctx->srecord_type);
2742 DECL_ARTIFICIAL (name) = 1;
2743 DECL_NAMELESS (name) = 1;
2744 TYPE_NAME (ctx->srecord_type) = name;
2745 TYPE_ARTIFICIAL (ctx->srecord_type) = 1;
2746 create_omp_child_function (ctx, true);
2747 }
2748
2749 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2750
2751 if (TYPE_FIELDS (ctx->record_type) == NULL)
2752 {
2753 ctx->record_type = ctx->receiver_decl = NULL;
2754 t = build_int_cst (long_integer_type_node, 0);
2755 gimple_omp_task_set_arg_size (stmt, t);
2756 t = build_int_cst (long_integer_type_node, 1);
2757 gimple_omp_task_set_arg_align (stmt, t);
2758 }
2759 }
2760
2761
2762 /* If any decls have been made addressable during scan_omp,
2763 adjust their fields if needed, and layout record types
2764 of parallel/task constructs. */
2765
2766 static void
2767 finish_taskreg_scan (omp_context *ctx)
2768 {
2769 if (ctx->record_type == NULL_TREE)
2770 return;
2771
2772 /* If any task_shared_vars were needed, verify all
2773 OMP_CLAUSE_SHARED clauses on GIMPLE_OMP_{PARALLEL,TASK}
2774 statements if use_pointer_for_field hasn't changed
2775 because of that. If it did, update field types now. */
2776 if (task_shared_vars)
2777 {
2778 tree c;
2779
2780 for (c = gimple_omp_taskreg_clauses (ctx->stmt);
2781 c; c = OMP_CLAUSE_CHAIN (c))
2782 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
2783 && !OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
2784 {
2785 tree decl = OMP_CLAUSE_DECL (c);
2786
2787 /* Global variables don't need to be copied,
2788 the receiver side will use them directly. */
2789 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
2790 continue;
2791 if (!bitmap_bit_p (task_shared_vars, DECL_UID (decl))
2792 || !use_pointer_for_field (decl, ctx))
2793 continue;
2794 tree field = lookup_field (decl, ctx);
2795 if (TREE_CODE (TREE_TYPE (field)) == POINTER_TYPE
2796 && TREE_TYPE (TREE_TYPE (field)) == TREE_TYPE (decl))
2797 continue;
2798 TREE_TYPE (field) = build_pointer_type (TREE_TYPE (decl));
2799 TREE_THIS_VOLATILE (field) = 0;
2800 DECL_USER_ALIGN (field) = 0;
2801 SET_DECL_ALIGN (field, TYPE_ALIGN (TREE_TYPE (field)));
2802 if (TYPE_ALIGN (ctx->record_type) < DECL_ALIGN (field))
2803 SET_TYPE_ALIGN (ctx->record_type, DECL_ALIGN (field));
2804 if (ctx->srecord_type)
2805 {
2806 tree sfield = lookup_sfield (decl, ctx);
2807 TREE_TYPE (sfield) = TREE_TYPE (field);
2808 TREE_THIS_VOLATILE (sfield) = 0;
2809 DECL_USER_ALIGN (sfield) = 0;
2810 SET_DECL_ALIGN (sfield, DECL_ALIGN (field));
2811 if (TYPE_ALIGN (ctx->srecord_type) < DECL_ALIGN (sfield))
2812 SET_TYPE_ALIGN (ctx->srecord_type, DECL_ALIGN (sfield));
2813 }
2814 }
2815 }
2816
2817 if (gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2818 {
2819 layout_type (ctx->record_type);
2820 fixup_child_record_type (ctx);
2821 }
2822 else
2823 {
2824 location_t loc = gimple_location (ctx->stmt);
2825 tree *p, vla_fields = NULL_TREE, *q = &vla_fields;
2826 /* Move VLA fields to the end. */
2827 p = &TYPE_FIELDS (ctx->record_type);
2828 while (*p)
2829 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p))
2830 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p))))
2831 {
2832 *q = *p;
2833 *p = TREE_CHAIN (*p);
2834 TREE_CHAIN (*q) = NULL_TREE;
2835 q = &TREE_CHAIN (*q);
2836 }
2837 else
2838 p = &DECL_CHAIN (*p);
2839 *p = vla_fields;
2840 if (gimple_omp_task_taskloop_p (ctx->stmt))
2841 {
2842 /* Move fields corresponding to first and second _looptemp_
2843 clause first. There are filled by GOMP_taskloop
2844 and thus need to be in specific positions. */
2845 tree c1 = gimple_omp_task_clauses (ctx->stmt);
2846 c1 = find_omp_clause (c1, OMP_CLAUSE__LOOPTEMP_);
2847 tree c2 = find_omp_clause (OMP_CLAUSE_CHAIN (c1),
2848 OMP_CLAUSE__LOOPTEMP_);
2849 tree f1 = lookup_field (OMP_CLAUSE_DECL (c1), ctx);
2850 tree f2 = lookup_field (OMP_CLAUSE_DECL (c2), ctx);
2851 p = &TYPE_FIELDS (ctx->record_type);
2852 while (*p)
2853 if (*p == f1 || *p == f2)
2854 *p = DECL_CHAIN (*p);
2855 else
2856 p = &DECL_CHAIN (*p);
2857 DECL_CHAIN (f1) = f2;
2858 DECL_CHAIN (f2) = TYPE_FIELDS (ctx->record_type);
2859 TYPE_FIELDS (ctx->record_type) = f1;
2860 if (ctx->srecord_type)
2861 {
2862 f1 = lookup_sfield (OMP_CLAUSE_DECL (c1), ctx);
2863 f2 = lookup_sfield (OMP_CLAUSE_DECL (c2), ctx);
2864 p = &TYPE_FIELDS (ctx->srecord_type);
2865 while (*p)
2866 if (*p == f1 || *p == f2)
2867 *p = DECL_CHAIN (*p);
2868 else
2869 p = &DECL_CHAIN (*p);
2870 DECL_CHAIN (f1) = f2;
2871 DECL_CHAIN (f2) = TYPE_FIELDS (ctx->srecord_type);
2872 TYPE_FIELDS (ctx->srecord_type) = f1;
2873 }
2874 }
2875 layout_type (ctx->record_type);
2876 fixup_child_record_type (ctx);
2877 if (ctx->srecord_type)
2878 layout_type (ctx->srecord_type);
2879 tree t = fold_convert_loc (loc, long_integer_type_node,
2880 TYPE_SIZE_UNIT (ctx->record_type));
2881 gimple_omp_task_set_arg_size (ctx->stmt, t);
2882 t = build_int_cst (long_integer_type_node,
2883 TYPE_ALIGN_UNIT (ctx->record_type));
2884 gimple_omp_task_set_arg_align (ctx->stmt, t);
2885 }
2886 }
2887
2888 /* Find the enclosing offload context. */
2889
2890 static omp_context *
2891 enclosing_target_ctx (omp_context *ctx)
2892 {
2893 for (; ctx; ctx = ctx->outer)
2894 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET)
2895 break;
2896
2897 return ctx;
2898 }
2899
2900 /* Return true if ctx is part of an oacc kernels region. */
2901
2902 static bool
2903 ctx_in_oacc_kernels_region (omp_context *ctx)
2904 {
2905 for (;ctx != NULL; ctx = ctx->outer)
2906 {
2907 gimple *stmt = ctx->stmt;
2908 if (gimple_code (stmt) == GIMPLE_OMP_TARGET
2909 && gimple_omp_target_kind (stmt) == GF_OMP_TARGET_KIND_OACC_KERNELS)
2910 return true;
2911 }
2912
2913 return false;
2914 }
2915
2916 /* Check the parallelism clauses inside a kernels regions.
2917 Until kernels handling moves to use the same loop indirection
2918 scheme as parallel, we need to do this checking early. */
2919
2920 static unsigned
2921 check_oacc_kernel_gwv (gomp_for *stmt, omp_context *ctx)
2922 {
2923 bool checking = true;
2924 unsigned outer_mask = 0;
2925 unsigned this_mask = 0;
2926 bool has_seq = false, has_auto = false;
2927
2928 if (ctx->outer)
2929 outer_mask = check_oacc_kernel_gwv (NULL, ctx->outer);
2930 if (!stmt)
2931 {
2932 checking = false;
2933 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR)
2934 return outer_mask;
2935 stmt = as_a <gomp_for *> (ctx->stmt);
2936 }
2937
2938 for (tree c = gimple_omp_for_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
2939 {
2940 switch (OMP_CLAUSE_CODE (c))
2941 {
2942 case OMP_CLAUSE_GANG:
2943 this_mask |= GOMP_DIM_MASK (GOMP_DIM_GANG);
2944 break;
2945 case OMP_CLAUSE_WORKER:
2946 this_mask |= GOMP_DIM_MASK (GOMP_DIM_WORKER);
2947 break;
2948 case OMP_CLAUSE_VECTOR:
2949 this_mask |= GOMP_DIM_MASK (GOMP_DIM_VECTOR);
2950 break;
2951 case OMP_CLAUSE_SEQ:
2952 has_seq = true;
2953 break;
2954 case OMP_CLAUSE_AUTO:
2955 has_auto = true;
2956 break;
2957 default:
2958 break;
2959 }
2960 }
2961
2962 if (checking)
2963 {
2964 if (has_seq && (this_mask || has_auto))
2965 error_at (gimple_location (stmt), "%<seq%> overrides other"
2966 " OpenACC loop specifiers");
2967 else if (has_auto && this_mask)
2968 error_at (gimple_location (stmt), "%<auto%> conflicts with other"
2969 " OpenACC loop specifiers");
2970
2971 if (this_mask & outer_mask)
2972 error_at (gimple_location (stmt), "inner loop uses same"
2973 " OpenACC parallelism as containing loop");
2974 }
2975
2976 return outer_mask | this_mask;
2977 }
2978
2979 /* Scan a GIMPLE_OMP_FOR. */
2980
2981 static void
2982 scan_omp_for (gomp_for *stmt, omp_context *outer_ctx)
2983 {
2984 omp_context *ctx;
2985 size_t i;
2986 tree clauses = gimple_omp_for_clauses (stmt);
2987
2988 ctx = new_omp_context (stmt, outer_ctx);
2989
2990 if (is_gimple_omp_oacc (stmt))
2991 {
2992 omp_context *tgt = enclosing_target_ctx (outer_ctx);
2993
2994 if (!tgt || is_oacc_parallel (tgt))
2995 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2996 {
2997 char const *check = NULL;
2998
2999 switch (OMP_CLAUSE_CODE (c))
3000 {
3001 case OMP_CLAUSE_GANG:
3002 check = "gang";
3003 break;
3004
3005 case OMP_CLAUSE_WORKER:
3006 check = "worker";
3007 break;
3008
3009 case OMP_CLAUSE_VECTOR:
3010 check = "vector";
3011 break;
3012
3013 default:
3014 break;
3015 }
3016
3017 if (check && OMP_CLAUSE_OPERAND (c, 0))
3018 error_at (gimple_location (stmt),
3019 "argument not permitted on %qs clause in"
3020 " OpenACC %<parallel%>", check);
3021 }
3022
3023 if (tgt && is_oacc_kernels (tgt))
3024 {
3025 /* Strip out reductions, as they are not handled yet. */
3026 tree *prev_ptr = &clauses;
3027
3028 while (tree probe = *prev_ptr)
3029 {
3030 tree *next_ptr = &OMP_CLAUSE_CHAIN (probe);
3031
3032 if (OMP_CLAUSE_CODE (probe) == OMP_CLAUSE_REDUCTION)
3033 *prev_ptr = *next_ptr;
3034 else
3035 prev_ptr = next_ptr;
3036 }
3037
3038 gimple_omp_for_set_clauses (stmt, clauses);
3039 check_oacc_kernel_gwv (stmt, ctx);
3040 }
3041 }
3042
3043 scan_sharing_clauses (clauses, ctx);
3044
3045 scan_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
3046 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
3047 {
3048 scan_omp_op (gimple_omp_for_index_ptr (stmt, i), ctx);
3049 scan_omp_op (gimple_omp_for_initial_ptr (stmt, i), ctx);
3050 scan_omp_op (gimple_omp_for_final_ptr (stmt, i), ctx);
3051 scan_omp_op (gimple_omp_for_incr_ptr (stmt, i), ctx);
3052 }
3053 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3054 }
3055
3056 /* Scan an OpenMP sections directive. */
3057
3058 static void
3059 scan_omp_sections (gomp_sections *stmt, omp_context *outer_ctx)
3060 {
3061 omp_context *ctx;
3062
3063 ctx = new_omp_context (stmt, outer_ctx);
3064 scan_sharing_clauses (gimple_omp_sections_clauses (stmt), ctx);
3065 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3066 }
3067
3068 /* Scan an OpenMP single directive. */
3069
3070 static void
3071 scan_omp_single (gomp_single *stmt, omp_context *outer_ctx)
3072 {
3073 omp_context *ctx;
3074 tree name;
3075
3076 ctx = new_omp_context (stmt, outer_ctx);
3077 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
3078 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
3079 name = create_tmp_var_name (".omp_copy_s");
3080 name = build_decl (gimple_location (stmt),
3081 TYPE_DECL, name, ctx->record_type);
3082 TYPE_NAME (ctx->record_type) = name;
3083
3084 scan_sharing_clauses (gimple_omp_single_clauses (stmt), ctx);
3085 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3086
3087 if (TYPE_FIELDS (ctx->record_type) == NULL)
3088 ctx->record_type = NULL;
3089 else
3090 layout_type (ctx->record_type);
3091 }
3092
3093 /* Return true if the CLAUSES of an omp target guarantee that the base pointers
3094 used in the corresponding offloaded function are restrict. */
3095
3096 static bool
3097 omp_target_base_pointers_restrict_p (tree clauses)
3098 {
3099 /* The analysis relies on the GOMP_MAP_FORCE_* mapping kinds, which are only
3100 used by OpenACC. */
3101 if (flag_openacc == 0)
3102 return false;
3103
3104 /* I. Basic example:
3105
3106 void foo (void)
3107 {
3108 unsigned int a[2], b[2];
3109
3110 #pragma acc kernels \
3111 copyout (a) \
3112 copyout (b)
3113 {
3114 a[0] = 0;
3115 b[0] = 1;
3116 }
3117 }
3118
3119 After gimplification, we have:
3120
3121 #pragma omp target oacc_kernels \
3122 map(force_from:a [len: 8]) \
3123 map(force_from:b [len: 8])
3124 {
3125 a[0] = 0;
3126 b[0] = 1;
3127 }
3128
3129 Because both mappings have the force prefix, we know that they will be
3130 allocated when calling the corresponding offloaded function, which means we
3131 can mark the base pointers for a and b in the offloaded function as
3132 restrict. */
3133
3134 tree c;
3135 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
3136 {
3137 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP)
3138 return false;
3139
3140 switch (OMP_CLAUSE_MAP_KIND (c))
3141 {
3142 case GOMP_MAP_FORCE_ALLOC:
3143 case GOMP_MAP_FORCE_TO:
3144 case GOMP_MAP_FORCE_FROM:
3145 case GOMP_MAP_FORCE_TOFROM:
3146 break;
3147 default:
3148 return false;
3149 }
3150 }
3151
3152 return true;
3153 }
3154
3155 /* Scan a GIMPLE_OMP_TARGET. */
3156
3157 static void
3158 scan_omp_target (gomp_target *stmt, omp_context *outer_ctx)
3159 {
3160 omp_context *ctx;
3161 tree name;
3162 bool offloaded = is_gimple_omp_offloaded (stmt);
3163 tree clauses = gimple_omp_target_clauses (stmt);
3164
3165 ctx = new_omp_context (stmt, outer_ctx);
3166 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
3167 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
3168 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
3169 name = create_tmp_var_name (".omp_data_t");
3170 name = build_decl (gimple_location (stmt),
3171 TYPE_DECL, name, ctx->record_type);
3172 DECL_ARTIFICIAL (name) = 1;
3173 DECL_NAMELESS (name) = 1;
3174 TYPE_NAME (ctx->record_type) = name;
3175 TYPE_ARTIFICIAL (ctx->record_type) = 1;
3176
3177 bool base_pointers_restrict = false;
3178 if (offloaded)
3179 {
3180 create_omp_child_function (ctx, false);
3181 gimple_omp_target_set_child_fn (stmt, ctx->cb.dst_fn);
3182
3183 base_pointers_restrict = omp_target_base_pointers_restrict_p (clauses);
3184 if (base_pointers_restrict
3185 && dump_file && (dump_flags & TDF_DETAILS))
3186 fprintf (dump_file,
3187 "Base pointers in offloaded function are restrict\n");
3188 }
3189
3190 scan_sharing_clauses (clauses, ctx, base_pointers_restrict);
3191 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3192
3193 if (TYPE_FIELDS (ctx->record_type) == NULL)
3194 ctx->record_type = ctx->receiver_decl = NULL;
3195 else
3196 {
3197 TYPE_FIELDS (ctx->record_type)
3198 = nreverse (TYPE_FIELDS (ctx->record_type));
3199 if (flag_checking)
3200 {
3201 unsigned int align = DECL_ALIGN (TYPE_FIELDS (ctx->record_type));
3202 for (tree field = TYPE_FIELDS (ctx->record_type);
3203 field;
3204 field = DECL_CHAIN (field))
3205 gcc_assert (DECL_ALIGN (field) == align);
3206 }
3207 layout_type (ctx->record_type);
3208 if (offloaded)
3209 fixup_child_record_type (ctx);
3210 }
3211 }
3212
3213 /* Scan an OpenMP teams directive. */
3214
3215 static void
3216 scan_omp_teams (gomp_teams *stmt, omp_context *outer_ctx)
3217 {
3218 omp_context *ctx = new_omp_context (stmt, outer_ctx);
3219 scan_sharing_clauses (gimple_omp_teams_clauses (stmt), ctx);
3220 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3221 }
3222
3223 /* Check nesting restrictions. */
3224 static bool
3225 check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx)
3226 {
3227 tree c;
3228
3229 if (ctx && gimple_code (ctx->stmt) == GIMPLE_OMP_GRID_BODY)
3230 /* GRID_BODY is an artificial construct, nesting rules will be checked in
3231 the original copy of its contents. */
3232 return true;
3233
3234 /* No nesting of non-OpenACC STMT (that is, an OpenMP one, or a GOMP builtin)
3235 inside an OpenACC CTX. */
3236 if (!(is_gimple_omp (stmt)
3237 && is_gimple_omp_oacc (stmt))
3238 /* Except for atomic codes that we share with OpenMP. */
3239 && !(gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD
3240 || gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE))
3241 {
3242 if (get_oacc_fn_attrib (cfun->decl) != NULL)
3243 {
3244 error_at (gimple_location (stmt),
3245 "non-OpenACC construct inside of OpenACC routine");
3246 return false;
3247 }
3248 else
3249 for (omp_context *octx = ctx; octx != NULL; octx = octx->outer)
3250 if (is_gimple_omp (octx->stmt)
3251 && is_gimple_omp_oacc (octx->stmt))
3252 {
3253 error_at (gimple_location (stmt),
3254 "non-OpenACC construct inside of OpenACC region");
3255 return false;
3256 }
3257 }
3258
3259 if (ctx != NULL)
3260 {
3261 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3262 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3263 {
3264 c = NULL_TREE;
3265 if (gimple_code (stmt) == GIMPLE_OMP_ORDERED)
3266 {
3267 c = gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt));
3268 if (find_omp_clause (c, OMP_CLAUSE_SIMD))
3269 {
3270 if (find_omp_clause (c, OMP_CLAUSE_THREADS)
3271 && (ctx->outer == NULL
3272 || !gimple_omp_for_combined_into_p (ctx->stmt)
3273 || gimple_code (ctx->outer->stmt) != GIMPLE_OMP_FOR
3274 || (gimple_omp_for_kind (ctx->outer->stmt)
3275 != GF_OMP_FOR_KIND_FOR)
3276 || !gimple_omp_for_combined_p (ctx->outer->stmt)))
3277 {
3278 error_at (gimple_location (stmt),
3279 "%<ordered simd threads%> must be closely "
3280 "nested inside of %<for simd%> region");
3281 return false;
3282 }
3283 return true;
3284 }
3285 }
3286 error_at (gimple_location (stmt),
3287 "OpenMP constructs other than %<#pragma omp ordered simd%>"
3288 " may not be nested inside %<simd%> region");
3289 return false;
3290 }
3291 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3292 {
3293 if ((gimple_code (stmt) != GIMPLE_OMP_FOR
3294 || (gimple_omp_for_kind (stmt)
3295 != GF_OMP_FOR_KIND_DISTRIBUTE))
3296 && gimple_code (stmt) != GIMPLE_OMP_PARALLEL)
3297 {
3298 error_at (gimple_location (stmt),
3299 "only %<distribute%> or %<parallel%> regions are "
3300 "allowed to be strictly nested inside %<teams%> "
3301 "region");
3302 return false;
3303 }
3304 }
3305 }
3306 switch (gimple_code (stmt))
3307 {
3308 case GIMPLE_OMP_FOR:
3309 if (gimple_omp_for_kind (stmt) & GF_OMP_FOR_SIMD)
3310 return true;
3311 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
3312 {
3313 if (ctx != NULL && gimple_code (ctx->stmt) != GIMPLE_OMP_TEAMS)
3314 {
3315 error_at (gimple_location (stmt),
3316 "%<distribute%> region must be strictly nested "
3317 "inside %<teams%> construct");
3318 return false;
3319 }
3320 return true;
3321 }
3322 /* We split taskloop into task and nested taskloop in it. */
3323 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_TASKLOOP)
3324 return true;
3325 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
3326 {
3327 bool ok = false;
3328
3329 if (ctx)
3330 switch (gimple_code (ctx->stmt))
3331 {
3332 case GIMPLE_OMP_FOR:
3333 ok = (gimple_omp_for_kind (ctx->stmt)
3334 == GF_OMP_FOR_KIND_OACC_LOOP);
3335 break;
3336
3337 case GIMPLE_OMP_TARGET:
3338 switch (gimple_omp_target_kind (ctx->stmt))
3339 {
3340 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
3341 case GF_OMP_TARGET_KIND_OACC_KERNELS:
3342 ok = true;
3343 break;
3344
3345 default:
3346 break;
3347 }
3348
3349 default:
3350 break;
3351 }
3352 else if (get_oacc_fn_attrib (current_function_decl))
3353 ok = true;
3354 if (!ok)
3355 {
3356 error_at (gimple_location (stmt),
3357 "OpenACC loop directive must be associated with"
3358 " an OpenACC compute region");
3359 return false;
3360 }
3361 }
3362 /* FALLTHRU */
3363 case GIMPLE_CALL:
3364 if (is_gimple_call (stmt)
3365 && (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3366 == BUILT_IN_GOMP_CANCEL
3367 || DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3368 == BUILT_IN_GOMP_CANCELLATION_POINT))
3369 {
3370 const char *bad = NULL;
3371 const char *kind = NULL;
3372 const char *construct
3373 = (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3374 == BUILT_IN_GOMP_CANCEL)
3375 ? "#pragma omp cancel"
3376 : "#pragma omp cancellation point";
3377 if (ctx == NULL)
3378 {
3379 error_at (gimple_location (stmt), "orphaned %qs construct",
3380 construct);
3381 return false;
3382 }
3383 switch (tree_fits_shwi_p (gimple_call_arg (stmt, 0))
3384 ? tree_to_shwi (gimple_call_arg (stmt, 0))
3385 : 0)
3386 {
3387 case 1:
3388 if (gimple_code (ctx->stmt) != GIMPLE_OMP_PARALLEL)
3389 bad = "#pragma omp parallel";
3390 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3391 == BUILT_IN_GOMP_CANCEL
3392 && !integer_zerop (gimple_call_arg (stmt, 1)))
3393 ctx->cancellable = true;
3394 kind = "parallel";
3395 break;
3396 case 2:
3397 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
3398 || gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR)
3399 bad = "#pragma omp for";
3400 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3401 == BUILT_IN_GOMP_CANCEL
3402 && !integer_zerop (gimple_call_arg (stmt, 1)))
3403 {
3404 ctx->cancellable = true;
3405 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3406 OMP_CLAUSE_NOWAIT))
3407 warning_at (gimple_location (stmt), 0,
3408 "%<#pragma omp cancel for%> inside "
3409 "%<nowait%> for construct");
3410 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3411 OMP_CLAUSE_ORDERED))
3412 warning_at (gimple_location (stmt), 0,
3413 "%<#pragma omp cancel for%> inside "
3414 "%<ordered%> for construct");
3415 }
3416 kind = "for";
3417 break;
3418 case 4:
3419 if (gimple_code (ctx->stmt) != GIMPLE_OMP_SECTIONS
3420 && gimple_code (ctx->stmt) != GIMPLE_OMP_SECTION)
3421 bad = "#pragma omp sections";
3422 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3423 == BUILT_IN_GOMP_CANCEL
3424 && !integer_zerop (gimple_call_arg (stmt, 1)))
3425 {
3426 if (gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS)
3427 {
3428 ctx->cancellable = true;
3429 if (find_omp_clause (gimple_omp_sections_clauses
3430 (ctx->stmt),
3431 OMP_CLAUSE_NOWAIT))
3432 warning_at (gimple_location (stmt), 0,
3433 "%<#pragma omp cancel sections%> inside "
3434 "%<nowait%> sections construct");
3435 }
3436 else
3437 {
3438 gcc_assert (ctx->outer
3439 && gimple_code (ctx->outer->stmt)
3440 == GIMPLE_OMP_SECTIONS);
3441 ctx->outer->cancellable = true;
3442 if (find_omp_clause (gimple_omp_sections_clauses
3443 (ctx->outer->stmt),
3444 OMP_CLAUSE_NOWAIT))
3445 warning_at (gimple_location (stmt), 0,
3446 "%<#pragma omp cancel sections%> inside "
3447 "%<nowait%> sections construct");
3448 }
3449 }
3450 kind = "sections";
3451 break;
3452 case 8:
3453 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TASK)
3454 bad = "#pragma omp task";
3455 else
3456 {
3457 for (omp_context *octx = ctx->outer;
3458 octx; octx = octx->outer)
3459 {
3460 switch (gimple_code (octx->stmt))
3461 {
3462 case GIMPLE_OMP_TASKGROUP:
3463 break;
3464 case GIMPLE_OMP_TARGET:
3465 if (gimple_omp_target_kind (octx->stmt)
3466 != GF_OMP_TARGET_KIND_REGION)
3467 continue;
3468 /* FALLTHRU */
3469 case GIMPLE_OMP_PARALLEL:
3470 case GIMPLE_OMP_TEAMS:
3471 error_at (gimple_location (stmt),
3472 "%<%s taskgroup%> construct not closely "
3473 "nested inside of %<taskgroup%> region",
3474 construct);
3475 return false;
3476 default:
3477 continue;
3478 }
3479 break;
3480 }
3481 ctx->cancellable = true;
3482 }
3483 kind = "taskgroup";
3484 break;
3485 default:
3486 error_at (gimple_location (stmt), "invalid arguments");
3487 return false;
3488 }
3489 if (bad)
3490 {
3491 error_at (gimple_location (stmt),
3492 "%<%s %s%> construct not closely nested inside of %qs",
3493 construct, kind, bad);
3494 return false;
3495 }
3496 }
3497 /* FALLTHRU */
3498 case GIMPLE_OMP_SECTIONS:
3499 case GIMPLE_OMP_SINGLE:
3500 for (; ctx != NULL; ctx = ctx->outer)
3501 switch (gimple_code (ctx->stmt))
3502 {
3503 case GIMPLE_OMP_FOR:
3504 if (gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR
3505 && gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_TASKLOOP)
3506 break;
3507 /* FALLTHRU */
3508 case GIMPLE_OMP_SECTIONS:
3509 case GIMPLE_OMP_SINGLE:
3510 case GIMPLE_OMP_ORDERED:
3511 case GIMPLE_OMP_MASTER:
3512 case GIMPLE_OMP_TASK:
3513 case GIMPLE_OMP_CRITICAL:
3514 if (is_gimple_call (stmt))
3515 {
3516 if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3517 != BUILT_IN_GOMP_BARRIER)
3518 return true;
3519 error_at (gimple_location (stmt),
3520 "barrier region may not be closely nested inside "
3521 "of work-sharing, %<critical%>, %<ordered%>, "
3522 "%<master%>, explicit %<task%> or %<taskloop%> "
3523 "region");
3524 return false;
3525 }
3526 error_at (gimple_location (stmt),
3527 "work-sharing region may not be closely nested inside "
3528 "of work-sharing, %<critical%>, %<ordered%>, "
3529 "%<master%>, explicit %<task%> or %<taskloop%> region");
3530 return false;
3531 case GIMPLE_OMP_PARALLEL:
3532 case GIMPLE_OMP_TEAMS:
3533 return true;
3534 case GIMPLE_OMP_TARGET:
3535 if (gimple_omp_target_kind (ctx->stmt)
3536 == GF_OMP_TARGET_KIND_REGION)
3537 return true;
3538 break;
3539 default:
3540 break;
3541 }
3542 break;
3543 case GIMPLE_OMP_MASTER:
3544 for (; ctx != NULL; ctx = ctx->outer)
3545 switch (gimple_code (ctx->stmt))
3546 {
3547 case GIMPLE_OMP_FOR:
3548 if (gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR
3549 && gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_TASKLOOP)
3550 break;
3551 /* FALLTHRU */
3552 case GIMPLE_OMP_SECTIONS:
3553 case GIMPLE_OMP_SINGLE:
3554 case GIMPLE_OMP_TASK:
3555 error_at (gimple_location (stmt),
3556 "%<master%> region may not be closely nested inside "
3557 "of work-sharing, explicit %<task%> or %<taskloop%> "
3558 "region");
3559 return false;
3560 case GIMPLE_OMP_PARALLEL:
3561 case GIMPLE_OMP_TEAMS:
3562 return true;
3563 case GIMPLE_OMP_TARGET:
3564 if (gimple_omp_target_kind (ctx->stmt)
3565 == GF_OMP_TARGET_KIND_REGION)
3566 return true;
3567 break;
3568 default:
3569 break;
3570 }
3571 break;
3572 case GIMPLE_OMP_TASK:
3573 for (c = gimple_omp_task_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
3574 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
3575 && (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE
3576 || OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK))
3577 {
3578 enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c);
3579 error_at (OMP_CLAUSE_LOCATION (c),
3580 "%<depend(%s)%> is only allowed in %<omp ordered%>",
3581 kind == OMP_CLAUSE_DEPEND_SOURCE ? "source" : "sink");
3582 return false;
3583 }
3584 break;
3585 case GIMPLE_OMP_ORDERED:
3586 for (c = gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt));
3587 c; c = OMP_CLAUSE_CHAIN (c))
3588 {
3589 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND)
3590 {
3591 gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_THREADS
3592 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SIMD);
3593 continue;
3594 }
3595 enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c);
3596 if (kind == OMP_CLAUSE_DEPEND_SOURCE
3597 || kind == OMP_CLAUSE_DEPEND_SINK)
3598 {
3599 tree oclause;
3600 /* Look for containing ordered(N) loop. */
3601 if (ctx == NULL
3602 || gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
3603 || (oclause
3604 = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3605 OMP_CLAUSE_ORDERED)) == NULL_TREE)
3606 {
3607 error_at (OMP_CLAUSE_LOCATION (c),
3608 "%<ordered%> construct with %<depend%> clause "
3609 "must be closely nested inside an %<ordered%> "
3610 "loop");
3611 return false;
3612 }
3613 else if (OMP_CLAUSE_ORDERED_EXPR (oclause) == NULL_TREE)
3614 {
3615 error_at (OMP_CLAUSE_LOCATION (c),
3616 "%<ordered%> construct with %<depend%> clause "
3617 "must be closely nested inside a loop with "
3618 "%<ordered%> clause with a parameter");
3619 return false;
3620 }
3621 }
3622 else
3623 {
3624 error_at (OMP_CLAUSE_LOCATION (c),
3625 "invalid depend kind in omp %<ordered%> %<depend%>");
3626 return false;
3627 }
3628 }
3629 c = gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt));
3630 if (find_omp_clause (c, OMP_CLAUSE_SIMD))
3631 {
3632 /* ordered simd must be closely nested inside of simd region,
3633 and simd region must not encounter constructs other than
3634 ordered simd, therefore ordered simd may be either orphaned,
3635 or ctx->stmt must be simd. The latter case is handled already
3636 earlier. */
3637 if (ctx != NULL)
3638 {
3639 error_at (gimple_location (stmt),
3640 "%<ordered%> %<simd%> must be closely nested inside "
3641 "%<simd%> region");
3642 return false;
3643 }
3644 }
3645 for (; ctx != NULL; ctx = ctx->outer)
3646 switch (gimple_code (ctx->stmt))
3647 {
3648 case GIMPLE_OMP_CRITICAL:
3649 case GIMPLE_OMP_TASK:
3650 case GIMPLE_OMP_ORDERED:
3651 ordered_in_taskloop:
3652 error_at (gimple_location (stmt),
3653 "%<ordered%> region may not be closely nested inside "
3654 "of %<critical%>, %<ordered%>, explicit %<task%> or "
3655 "%<taskloop%> region");
3656 return false;
3657 case GIMPLE_OMP_FOR:
3658 if (gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_TASKLOOP)
3659 goto ordered_in_taskloop;
3660 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3661 OMP_CLAUSE_ORDERED) == NULL)
3662 {
3663 error_at (gimple_location (stmt),
3664 "%<ordered%> region must be closely nested inside "
3665 "a loop region with an %<ordered%> clause");
3666 return false;
3667 }
3668 return true;
3669 case GIMPLE_OMP_TARGET:
3670 if (gimple_omp_target_kind (ctx->stmt)
3671 != GF_OMP_TARGET_KIND_REGION)
3672 break;
3673 /* FALLTHRU */
3674 case GIMPLE_OMP_PARALLEL:
3675 case GIMPLE_OMP_TEAMS:
3676 error_at (gimple_location (stmt),
3677 "%<ordered%> region must be closely nested inside "
3678 "a loop region with an %<ordered%> clause");
3679 return false;
3680 default:
3681 break;
3682 }
3683 break;
3684 case GIMPLE_OMP_CRITICAL:
3685 {
3686 tree this_stmt_name
3687 = gimple_omp_critical_name (as_a <gomp_critical *> (stmt));
3688 for (; ctx != NULL; ctx = ctx->outer)
3689 if (gomp_critical *other_crit
3690 = dyn_cast <gomp_critical *> (ctx->stmt))
3691 if (this_stmt_name == gimple_omp_critical_name (other_crit))
3692 {
3693 error_at (gimple_location (stmt),
3694 "%<critical%> region may not be nested inside "
3695 "a %<critical%> region with the same name");
3696 return false;
3697 }
3698 }
3699 break;
3700 case GIMPLE_OMP_TEAMS:
3701 if (ctx == NULL
3702 || gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET
3703 || gimple_omp_target_kind (ctx->stmt) != GF_OMP_TARGET_KIND_REGION)
3704 {
3705 error_at (gimple_location (stmt),
3706 "%<teams%> construct not closely nested inside of "
3707 "%<target%> construct");
3708 return false;
3709 }
3710 break;
3711 case GIMPLE_OMP_TARGET:
3712 for (c = gimple_omp_target_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
3713 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
3714 && (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE
3715 || OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK))
3716 {
3717 enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c);
3718 error_at (OMP_CLAUSE_LOCATION (c),
3719 "%<depend(%s)%> is only allowed in %<omp ordered%>",
3720 kind == OMP_CLAUSE_DEPEND_SOURCE ? "source" : "sink");
3721 return false;
3722 }
3723 if (is_gimple_omp_offloaded (stmt)
3724 && get_oacc_fn_attrib (cfun->decl) != NULL)
3725 {
3726 error_at (gimple_location (stmt),
3727 "OpenACC region inside of OpenACC routine, nested "
3728 "parallelism not supported yet");
3729 return false;
3730 }
3731 for (; ctx != NULL; ctx = ctx->outer)
3732 {
3733 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET)
3734 {
3735 if (is_gimple_omp (stmt)
3736 && is_gimple_omp_oacc (stmt)
3737 && is_gimple_omp (ctx->stmt))
3738 {
3739 error_at (gimple_location (stmt),
3740 "OpenACC construct inside of non-OpenACC region");
3741 return false;
3742 }
3743 continue;
3744 }
3745
3746 const char *stmt_name, *ctx_stmt_name;
3747 switch (gimple_omp_target_kind (stmt))
3748 {
3749 case GF_OMP_TARGET_KIND_REGION: stmt_name = "target"; break;
3750 case GF_OMP_TARGET_KIND_DATA: stmt_name = "target data"; break;
3751 case GF_OMP_TARGET_KIND_UPDATE: stmt_name = "target update"; break;
3752 case GF_OMP_TARGET_KIND_ENTER_DATA:
3753 stmt_name = "target enter data"; break;
3754 case GF_OMP_TARGET_KIND_EXIT_DATA:
3755 stmt_name = "target exit data"; break;
3756 case GF_OMP_TARGET_KIND_OACC_PARALLEL: stmt_name = "parallel"; break;
3757 case GF_OMP_TARGET_KIND_OACC_KERNELS: stmt_name = "kernels"; break;
3758 case GF_OMP_TARGET_KIND_OACC_DATA: stmt_name = "data"; break;
3759 case GF_OMP_TARGET_KIND_OACC_UPDATE: stmt_name = "update"; break;
3760 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
3761 stmt_name = "enter/exit data"; break;
3762 case GF_OMP_TARGET_KIND_OACC_HOST_DATA: stmt_name = "host_data";
3763 break;
3764 default: gcc_unreachable ();
3765 }
3766 switch (gimple_omp_target_kind (ctx->stmt))
3767 {
3768 case GF_OMP_TARGET_KIND_REGION: ctx_stmt_name = "target"; break;
3769 case GF_OMP_TARGET_KIND_DATA: ctx_stmt_name = "target data"; break;
3770 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
3771 ctx_stmt_name = "parallel"; break;
3772 case GF_OMP_TARGET_KIND_OACC_KERNELS:
3773 ctx_stmt_name = "kernels"; break;
3774 case GF_OMP_TARGET_KIND_OACC_DATA: ctx_stmt_name = "data"; break;
3775 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
3776 ctx_stmt_name = "host_data"; break;
3777 default: gcc_unreachable ();
3778 }
3779
3780 /* OpenACC/OpenMP mismatch? */
3781 if (is_gimple_omp_oacc (stmt)
3782 != is_gimple_omp_oacc (ctx->stmt))
3783 {
3784 error_at (gimple_location (stmt),
3785 "%s %qs construct inside of %s %qs region",
3786 (is_gimple_omp_oacc (stmt)
3787 ? "OpenACC" : "OpenMP"), stmt_name,
3788 (is_gimple_omp_oacc (ctx->stmt)
3789 ? "OpenACC" : "OpenMP"), ctx_stmt_name);
3790 return false;
3791 }
3792 if (is_gimple_omp_offloaded (ctx->stmt))
3793 {
3794 /* No GIMPLE_OMP_TARGET inside offloaded OpenACC CTX. */
3795 if (is_gimple_omp_oacc (ctx->stmt))
3796 {
3797 error_at (gimple_location (stmt),
3798 "%qs construct inside of %qs region",
3799 stmt_name, ctx_stmt_name);
3800 return false;
3801 }
3802 else
3803 {
3804 warning_at (gimple_location (stmt), 0,
3805 "%qs construct inside of %qs region",
3806 stmt_name, ctx_stmt_name);
3807 }
3808 }
3809 }
3810 break;
3811 default:
3812 break;
3813 }
3814 return true;
3815 }
3816
3817
3818 /* Helper function scan_omp.
3819
3820 Callback for walk_tree or operators in walk_gimple_stmt used to
3821 scan for OMP directives in TP. */
3822
3823 static tree
3824 scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
3825 {
3826 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
3827 omp_context *ctx = (omp_context *) wi->info;
3828 tree t = *tp;
3829
3830 switch (TREE_CODE (t))
3831 {
3832 case VAR_DECL:
3833 case PARM_DECL:
3834 case LABEL_DECL:
3835 case RESULT_DECL:
3836 if (ctx)
3837 {
3838 tree repl = remap_decl (t, &ctx->cb);
3839 gcc_checking_assert (TREE_CODE (repl) != ERROR_MARK);
3840 *tp = repl;
3841 }
3842 break;
3843
3844 default:
3845 if (ctx && TYPE_P (t))
3846 *tp = remap_type (t, &ctx->cb);
3847 else if (!DECL_P (t))
3848 {
3849 *walk_subtrees = 1;
3850 if (ctx)
3851 {
3852 tree tem = remap_type (TREE_TYPE (t), &ctx->cb);
3853 if (tem != TREE_TYPE (t))
3854 {
3855 if (TREE_CODE (t) == INTEGER_CST)
3856 *tp = wide_int_to_tree (tem, t);
3857 else
3858 TREE_TYPE (t) = tem;
3859 }
3860 }
3861 }
3862 break;
3863 }
3864
3865 return NULL_TREE;
3866 }
3867
3868 /* Return true if FNDECL is a setjmp or a longjmp. */
3869
3870 static bool
3871 setjmp_or_longjmp_p (const_tree fndecl)
3872 {
3873 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
3874 && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_SETJMP
3875 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LONGJMP))
3876 return true;
3877
3878 tree declname = DECL_NAME (fndecl);
3879 if (!declname)
3880 return false;
3881 const char *name = IDENTIFIER_POINTER (declname);
3882 return !strcmp (name, "setjmp") || !strcmp (name, "longjmp");
3883 }
3884
3885
3886 /* Helper function for scan_omp.
3887
3888 Callback for walk_gimple_stmt used to scan for OMP directives in
3889 the current statement in GSI. */
3890
3891 static tree
3892 scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
3893 struct walk_stmt_info *wi)
3894 {
3895 gimple *stmt = gsi_stmt (*gsi);
3896 omp_context *ctx = (omp_context *) wi->info;
3897
3898 if (gimple_has_location (stmt))
3899 input_location = gimple_location (stmt);
3900
3901 /* Check the nesting restrictions. */
3902 bool remove = false;
3903 if (is_gimple_omp (stmt))
3904 remove = !check_omp_nesting_restrictions (stmt, ctx);
3905 else if (is_gimple_call (stmt))
3906 {
3907 tree fndecl = gimple_call_fndecl (stmt);
3908 if (fndecl)
3909 {
3910 if (setjmp_or_longjmp_p (fndecl)
3911 && ctx
3912 && gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3913 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3914 {
3915 remove = true;
3916 error_at (gimple_location (stmt),
3917 "setjmp/longjmp inside simd construct");
3918 }
3919 else if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
3920 switch (DECL_FUNCTION_CODE (fndecl))
3921 {
3922 case BUILT_IN_GOMP_BARRIER:
3923 case BUILT_IN_GOMP_CANCEL:
3924 case BUILT_IN_GOMP_CANCELLATION_POINT:
3925 case BUILT_IN_GOMP_TASKYIELD:
3926 case BUILT_IN_GOMP_TASKWAIT:
3927 case BUILT_IN_GOMP_TASKGROUP_START:
3928 case BUILT_IN_GOMP_TASKGROUP_END:
3929 remove = !check_omp_nesting_restrictions (stmt, ctx);
3930 break;
3931 default:
3932 break;
3933 }
3934 }
3935 }
3936 if (remove)
3937 {
3938 stmt = gimple_build_nop ();
3939 gsi_replace (gsi, stmt, false);
3940 }
3941
3942 *handled_ops_p = true;
3943
3944 switch (gimple_code (stmt))
3945 {
3946 case GIMPLE_OMP_PARALLEL:
3947 taskreg_nesting_level++;
3948 scan_omp_parallel (gsi, ctx);
3949 taskreg_nesting_level--;
3950 break;
3951
3952 case GIMPLE_OMP_TASK:
3953 taskreg_nesting_level++;
3954 scan_omp_task (gsi, ctx);
3955 taskreg_nesting_level--;
3956 break;
3957
3958 case GIMPLE_OMP_FOR:
3959 scan_omp_for (as_a <gomp_for *> (stmt), ctx);
3960 break;
3961
3962 case GIMPLE_OMP_SECTIONS:
3963 scan_omp_sections (as_a <gomp_sections *> (stmt), ctx);
3964 break;
3965
3966 case GIMPLE_OMP_SINGLE:
3967 scan_omp_single (as_a <gomp_single *> (stmt), ctx);
3968 break;
3969
3970 case GIMPLE_OMP_SECTION:
3971 case GIMPLE_OMP_MASTER:
3972 case GIMPLE_OMP_TASKGROUP:
3973 case GIMPLE_OMP_ORDERED:
3974 case GIMPLE_OMP_CRITICAL:
3975 case GIMPLE_OMP_GRID_BODY:
3976 ctx = new_omp_context (stmt, ctx);
3977 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3978 break;
3979
3980 case GIMPLE_OMP_TARGET:
3981 scan_omp_target (as_a <gomp_target *> (stmt), ctx);
3982 break;
3983
3984 case GIMPLE_OMP_TEAMS:
3985 scan_omp_teams (as_a <gomp_teams *> (stmt), ctx);
3986 break;
3987
3988 case GIMPLE_BIND:
3989 {
3990 tree var;
3991
3992 *handled_ops_p = false;
3993 if (ctx)
3994 for (var = gimple_bind_vars (as_a <gbind *> (stmt));
3995 var ;
3996 var = DECL_CHAIN (var))
3997 insert_decl_map (&ctx->cb, var, var);
3998 }
3999 break;
4000 default:
4001 *handled_ops_p = false;
4002 break;
4003 }
4004
4005 return NULL_TREE;
4006 }
4007
4008
4009 /* Scan all the statements starting at the current statement. CTX
4010 contains context information about the OMP directives and
4011 clauses found during the scan. */
4012
4013 static void
4014 scan_omp (gimple_seq *body_p, omp_context *ctx)
4015 {
4016 location_t saved_location;
4017 struct walk_stmt_info wi;
4018
4019 memset (&wi, 0, sizeof (wi));
4020 wi.info = ctx;
4021 wi.want_locations = true;
4022
4023 saved_location = input_location;
4024 walk_gimple_seq_mod (body_p, scan_omp_1_stmt, scan_omp_1_op, &wi);
4025 input_location = saved_location;
4026 }
4027 \f
4028 /* Re-gimplification and code generation routines. */
4029
4030 /* Build a call to GOMP_barrier. */
4031
4032 static gimple *
4033 build_omp_barrier (tree lhs)
4034 {
4035 tree fndecl = builtin_decl_explicit (lhs ? BUILT_IN_GOMP_BARRIER_CANCEL
4036 : BUILT_IN_GOMP_BARRIER);
4037 gcall *g = gimple_build_call (fndecl, 0);
4038 if (lhs)
4039 gimple_call_set_lhs (g, lhs);
4040 return g;
4041 }
4042
4043 /* If a context was created for STMT when it was scanned, return it. */
4044
4045 static omp_context *
4046 maybe_lookup_ctx (gimple *stmt)
4047 {
4048 splay_tree_node n;
4049 n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
4050 return n ? (omp_context *) n->value : NULL;
4051 }
4052
4053
4054 /* Find the mapping for DECL in CTX or the immediately enclosing
4055 context that has a mapping for DECL.
4056
4057 If CTX is a nested parallel directive, we may have to use the decl
4058 mappings created in CTX's parent context. Suppose that we have the
4059 following parallel nesting (variable UIDs showed for clarity):
4060
4061 iD.1562 = 0;
4062 #omp parallel shared(iD.1562) -> outer parallel
4063 iD.1562 = iD.1562 + 1;
4064
4065 #omp parallel shared (iD.1562) -> inner parallel
4066 iD.1562 = iD.1562 - 1;
4067
4068 Each parallel structure will create a distinct .omp_data_s structure
4069 for copying iD.1562 in/out of the directive:
4070
4071 outer parallel .omp_data_s.1.i -> iD.1562
4072 inner parallel .omp_data_s.2.i -> iD.1562
4073
4074 A shared variable mapping will produce a copy-out operation before
4075 the parallel directive and a copy-in operation after it. So, in
4076 this case we would have:
4077
4078 iD.1562 = 0;
4079 .omp_data_o.1.i = iD.1562;
4080 #omp parallel shared(iD.1562) -> outer parallel
4081 .omp_data_i.1 = &.omp_data_o.1
4082 .omp_data_i.1->i = .omp_data_i.1->i + 1;
4083
4084 .omp_data_o.2.i = iD.1562; -> **
4085 #omp parallel shared(iD.1562) -> inner parallel
4086 .omp_data_i.2 = &.omp_data_o.2
4087 .omp_data_i.2->i = .omp_data_i.2->i - 1;
4088
4089
4090 ** This is a problem. The symbol iD.1562 cannot be referenced
4091 inside the body of the outer parallel region. But since we are
4092 emitting this copy operation while expanding the inner parallel
4093 directive, we need to access the CTX structure of the outer
4094 parallel directive to get the correct mapping:
4095
4096 .omp_data_o.2.i = .omp_data_i.1->i
4097
4098 Since there may be other workshare or parallel directives enclosing
4099 the parallel directive, it may be necessary to walk up the context
4100 parent chain. This is not a problem in general because nested
4101 parallelism happens only rarely. */
4102
4103 static tree
4104 lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
4105 {
4106 tree t;
4107 omp_context *up;
4108
4109 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
4110 t = maybe_lookup_decl (decl, up);
4111
4112 gcc_assert (!ctx->is_nested || t || is_global_var (decl));
4113
4114 return t ? t : decl;
4115 }
4116
4117
4118 /* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
4119 in outer contexts. */
4120
4121 static tree
4122 maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
4123 {
4124 tree t = NULL;
4125 omp_context *up;
4126
4127 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
4128 t = maybe_lookup_decl (decl, up);
4129
4130 return t ? t : decl;
4131 }
4132
4133
4134 /* Construct the initialization value for reduction operation OP. */
4135
4136 tree
4137 omp_reduction_init_op (location_t loc, enum tree_code op, tree type)
4138 {
4139 switch (op)
4140 {
4141 case PLUS_EXPR:
4142 case MINUS_EXPR:
4143 case BIT_IOR_EXPR:
4144 case BIT_XOR_EXPR:
4145 case TRUTH_OR_EXPR:
4146 case TRUTH_ORIF_EXPR:
4147 case TRUTH_XOR_EXPR:
4148 case NE_EXPR:
4149 return build_zero_cst (type);
4150
4151 case MULT_EXPR:
4152 case TRUTH_AND_EXPR:
4153 case TRUTH_ANDIF_EXPR:
4154 case EQ_EXPR:
4155 return fold_convert_loc (loc, type, integer_one_node);
4156
4157 case BIT_AND_EXPR:
4158 return fold_convert_loc (loc, type, integer_minus_one_node);
4159
4160 case MAX_EXPR:
4161 if (SCALAR_FLOAT_TYPE_P (type))
4162 {
4163 REAL_VALUE_TYPE max, min;
4164 if (HONOR_INFINITIES (type))
4165 {
4166 real_inf (&max);
4167 real_arithmetic (&min, NEGATE_EXPR, &max, NULL);
4168 }
4169 else
4170 real_maxval (&min, 1, TYPE_MODE (type));
4171 return build_real (type, min);
4172 }
4173 else if (POINTER_TYPE_P (type))
4174 {
4175 wide_int min
4176 = wi::min_value (TYPE_PRECISION (type), TYPE_SIGN (type));
4177 return wide_int_to_tree (type, min);
4178 }
4179 else
4180 {
4181 gcc_assert (INTEGRAL_TYPE_P (type));
4182 return TYPE_MIN_VALUE (type);
4183 }
4184
4185 case MIN_EXPR:
4186 if (SCALAR_FLOAT_TYPE_P (type))
4187 {
4188 REAL_VALUE_TYPE max;
4189 if (HONOR_INFINITIES (type))
4190 real_inf (&max);
4191 else
4192 real_maxval (&max, 0, TYPE_MODE (type));
4193 return build_real (type, max);
4194 }
4195 else if (POINTER_TYPE_P (type))
4196 {
4197 wide_int max
4198 = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type));
4199 return wide_int_to_tree (type, max);
4200 }
4201 else
4202 {
4203 gcc_assert (INTEGRAL_TYPE_P (type));
4204 return TYPE_MAX_VALUE (type);
4205 }
4206
4207 default:
4208 gcc_unreachable ();
4209 }
4210 }
4211
4212 /* Construct the initialization value for reduction CLAUSE. */
4213
4214 tree
4215 omp_reduction_init (tree clause, tree type)
4216 {
4217 return omp_reduction_init_op (OMP_CLAUSE_LOCATION (clause),
4218 OMP_CLAUSE_REDUCTION_CODE (clause), type);
4219 }
4220
4221 /* Return alignment to be assumed for var in CLAUSE, which should be
4222 OMP_CLAUSE_ALIGNED. */
4223
4224 static tree
4225 omp_clause_aligned_alignment (tree clause)
4226 {
4227 if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause))
4228 return OMP_CLAUSE_ALIGNED_ALIGNMENT (clause);
4229
4230 /* Otherwise return implementation defined alignment. */
4231 unsigned int al = 1;
4232 machine_mode mode, vmode;
4233 int vs = targetm.vectorize.autovectorize_vector_sizes ();
4234 if (vs)
4235 vs = 1 << floor_log2 (vs);
4236 static enum mode_class classes[]
4237 = { MODE_INT, MODE_VECTOR_INT, MODE_FLOAT, MODE_VECTOR_FLOAT };
4238 for (int i = 0; i < 4; i += 2)
4239 for (mode = GET_CLASS_NARROWEST_MODE (classes[i]);
4240 mode != VOIDmode;
4241 mode = GET_MODE_WIDER_MODE (mode))
4242 {
4243 vmode = targetm.vectorize.preferred_simd_mode (mode);
4244 if (GET_MODE_CLASS (vmode) != classes[i + 1])
4245 continue;
4246 while (vs
4247 && GET_MODE_SIZE (vmode) < vs
4248 && GET_MODE_2XWIDER_MODE (vmode) != VOIDmode)
4249 vmode = GET_MODE_2XWIDER_MODE (vmode);
4250
4251 tree type = lang_hooks.types.type_for_mode (mode, 1);
4252 if (type == NULL_TREE || TYPE_MODE (type) != mode)
4253 continue;
4254 type = build_vector_type (type, GET_MODE_SIZE (vmode)
4255 / GET_MODE_SIZE (mode));
4256 if (TYPE_MODE (type) != vmode)
4257 continue;
4258 if (TYPE_ALIGN_UNIT (type) > al)
4259 al = TYPE_ALIGN_UNIT (type);
4260 }
4261 return build_int_cst (integer_type_node, al);
4262 }
4263
4264 /* Return maximum possible vectorization factor for the target. */
4265
4266 static int
4267 omp_max_vf (void)
4268 {
4269 if (!optimize
4270 || optimize_debug
4271 || !flag_tree_loop_optimize
4272 || (!flag_tree_loop_vectorize
4273 && (global_options_set.x_flag_tree_loop_vectorize
4274 || global_options_set.x_flag_tree_vectorize)))
4275 return 1;
4276
4277 int vs = targetm.vectorize.autovectorize_vector_sizes ();
4278 if (vs)
4279 {
4280 vs = 1 << floor_log2 (vs);
4281 return vs;
4282 }
4283 machine_mode vqimode = targetm.vectorize.preferred_simd_mode (QImode);
4284 if (GET_MODE_CLASS (vqimode) == MODE_VECTOR_INT)
4285 return GET_MODE_NUNITS (vqimode);
4286 return 1;
4287 }
4288
4289 /* Helper function of lower_rec_input_clauses, used for #pragma omp simd
4290 privatization. */
4291
4292 static bool
4293 lower_rec_simd_input_clauses (tree new_var, omp_context *ctx, int &max_vf,
4294 tree &idx, tree &lane, tree &ivar, tree &lvar)
4295 {
4296 if (max_vf == 0)
4297 {
4298 max_vf = omp_max_vf ();
4299 if (max_vf > 1)
4300 {
4301 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
4302 OMP_CLAUSE_SAFELEN);
4303 if (c && TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) != INTEGER_CST)
4304 max_vf = 1;
4305 else if (c && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
4306 max_vf) == -1)
4307 max_vf = tree_to_shwi (OMP_CLAUSE_SAFELEN_EXPR (c));
4308 }
4309 if (max_vf > 1)
4310 {
4311 idx = create_tmp_var (unsigned_type_node);
4312 lane = create_tmp_var (unsigned_type_node);
4313 }
4314 }
4315 if (max_vf == 1)
4316 return false;
4317
4318 tree atype = build_array_type_nelts (TREE_TYPE (new_var), max_vf);
4319 tree avar = create_tmp_var_raw (atype);
4320 if (TREE_ADDRESSABLE (new_var))
4321 TREE_ADDRESSABLE (avar) = 1;
4322 DECL_ATTRIBUTES (avar)
4323 = tree_cons (get_identifier ("omp simd array"), NULL,
4324 DECL_ATTRIBUTES (avar));
4325 gimple_add_tmp_var (avar);
4326 ivar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, idx,
4327 NULL_TREE, NULL_TREE);
4328 lvar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, lane,
4329 NULL_TREE, NULL_TREE);
4330 if (DECL_P (new_var))
4331 {
4332 SET_DECL_VALUE_EXPR (new_var, lvar);
4333 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4334 }
4335 return true;
4336 }
4337
4338 /* Helper function of lower_rec_input_clauses. For a reference
4339 in simd reduction, add an underlying variable it will reference. */
4340
4341 static void
4342 handle_simd_reference (location_t loc, tree new_vard, gimple_seq *ilist)
4343 {
4344 tree z = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard)));
4345 if (TREE_CONSTANT (z))
4346 {
4347 z = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_vard)),
4348 get_name (new_vard));
4349 gimple_add_tmp_var (z);
4350 TREE_ADDRESSABLE (z) = 1;
4351 z = build_fold_addr_expr_loc (loc, z);
4352 gimplify_assign (new_vard, z, ilist);
4353 }
4354 }
4355
4356 /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
4357 from the receiver (aka child) side and initializers for REFERENCE_TYPE
4358 private variables. Initialization statements go in ILIST, while calls
4359 to destructors go in DLIST. */
4360
4361 static void
4362 lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
4363 omp_context *ctx, struct omp_for_data *fd)
4364 {
4365 tree c, dtor, copyin_seq, x, ptr;
4366 bool copyin_by_ref = false;
4367 bool lastprivate_firstprivate = false;
4368 bool reduction_omp_orig_ref = false;
4369 int pass;
4370 bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
4371 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD);
4372 int max_vf = 0;
4373 tree lane = NULL_TREE, idx = NULL_TREE;
4374 tree ivar = NULL_TREE, lvar = NULL_TREE;
4375 gimple_seq llist[2] = { NULL, NULL };
4376
4377 copyin_seq = NULL;
4378
4379 /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
4380 with data sharing clauses referencing variable sized vars. That
4381 is unnecessarily hard to support and very unlikely to result in
4382 vectorized code anyway. */
4383 if (is_simd)
4384 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4385 switch (OMP_CLAUSE_CODE (c))
4386 {
4387 case OMP_CLAUSE_LINEAR:
4388 if (OMP_CLAUSE_LINEAR_ARRAY (c))
4389 max_vf = 1;
4390 /* FALLTHRU */
4391 case OMP_CLAUSE_PRIVATE:
4392 case OMP_CLAUSE_FIRSTPRIVATE:
4393 case OMP_CLAUSE_LASTPRIVATE:
4394 if (is_variable_sized (OMP_CLAUSE_DECL (c)))
4395 max_vf = 1;
4396 break;
4397 case OMP_CLAUSE_REDUCTION:
4398 if (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF
4399 || is_variable_sized (OMP_CLAUSE_DECL (c)))
4400 max_vf = 1;
4401 break;
4402 default:
4403 continue;
4404 }
4405
4406 /* Do all the fixed sized types in the first pass, and the variable sized
4407 types in the second pass. This makes sure that the scalar arguments to
4408 the variable sized types are processed before we use them in the
4409 variable sized operations. */
4410 for (pass = 0; pass < 2; ++pass)
4411 {
4412 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4413 {
4414 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
4415 tree var, new_var;
4416 bool by_ref;
4417 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4418
4419 switch (c_kind)
4420 {
4421 case OMP_CLAUSE_PRIVATE:
4422 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
4423 continue;
4424 break;
4425 case OMP_CLAUSE_SHARED:
4426 /* Ignore shared directives in teams construct. */
4427 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
4428 continue;
4429 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
4430 {
4431 gcc_assert (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c)
4432 || is_global_var (OMP_CLAUSE_DECL (c)));
4433 continue;
4434 }
4435 case OMP_CLAUSE_FIRSTPRIVATE:
4436 case OMP_CLAUSE_COPYIN:
4437 break;
4438 case OMP_CLAUSE_LINEAR:
4439 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c)
4440 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
4441 lastprivate_firstprivate = true;
4442 break;
4443 case OMP_CLAUSE_REDUCTION:
4444 if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
4445 reduction_omp_orig_ref = true;
4446 break;
4447 case OMP_CLAUSE__LOOPTEMP_:
4448 /* Handle _looptemp_ clauses only on parallel/task. */
4449 if (fd)
4450 continue;
4451 break;
4452 case OMP_CLAUSE_LASTPRIVATE:
4453 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4454 {
4455 lastprivate_firstprivate = true;
4456 if (pass != 0 || is_taskloop_ctx (ctx))
4457 continue;
4458 }
4459 /* Even without corresponding firstprivate, if
4460 decl is Fortran allocatable, it needs outer var
4461 reference. */
4462 else if (pass == 0
4463 && lang_hooks.decls.omp_private_outer_ref
4464 (OMP_CLAUSE_DECL (c)))
4465 lastprivate_firstprivate = true;
4466 break;
4467 case OMP_CLAUSE_ALIGNED:
4468 if (pass == 0)
4469 continue;
4470 var = OMP_CLAUSE_DECL (c);
4471 if (TREE_CODE (TREE_TYPE (var)) == POINTER_TYPE
4472 && !is_global_var (var))
4473 {
4474 new_var = maybe_lookup_decl (var, ctx);
4475 if (new_var == NULL_TREE)
4476 new_var = maybe_lookup_decl_in_outer_ctx (var, ctx);
4477 x = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
4478 x = build_call_expr_loc (clause_loc, x, 2, new_var,
4479 omp_clause_aligned_alignment (c));
4480 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
4481 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
4482 gimplify_and_add (x, ilist);
4483 }
4484 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
4485 && is_global_var (var))
4486 {
4487 tree ptype = build_pointer_type (TREE_TYPE (var)), t, t2;
4488 new_var = lookup_decl (var, ctx);
4489 t = maybe_lookup_decl_in_outer_ctx (var, ctx);
4490 t = build_fold_addr_expr_loc (clause_loc, t);
4491 t2 = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
4492 t = build_call_expr_loc (clause_loc, t2, 2, t,
4493 omp_clause_aligned_alignment (c));
4494 t = fold_convert_loc (clause_loc, ptype, t);
4495 x = create_tmp_var (ptype);
4496 t = build2 (MODIFY_EXPR, ptype, x, t);
4497 gimplify_and_add (t, ilist);
4498 t = build_simple_mem_ref_loc (clause_loc, x);
4499 SET_DECL_VALUE_EXPR (new_var, t);
4500 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4501 }
4502 continue;
4503 default:
4504 continue;
4505 }
4506
4507 new_var = var = OMP_CLAUSE_DECL (c);
4508 if (c_kind == OMP_CLAUSE_REDUCTION && TREE_CODE (var) == MEM_REF)
4509 {
4510 var = TREE_OPERAND (var, 0);
4511 if (TREE_CODE (var) == POINTER_PLUS_EXPR)
4512 var = TREE_OPERAND (var, 0);
4513 if (TREE_CODE (var) == INDIRECT_REF
4514 || TREE_CODE (var) == ADDR_EXPR)
4515 var = TREE_OPERAND (var, 0);
4516 if (is_variable_sized (var))
4517 {
4518 gcc_assert (DECL_HAS_VALUE_EXPR_P (var));
4519 var = DECL_VALUE_EXPR (var);
4520 gcc_assert (TREE_CODE (var) == INDIRECT_REF);
4521 var = TREE_OPERAND (var, 0);
4522 gcc_assert (DECL_P (var));
4523 }
4524 new_var = var;
4525 }
4526 if (c_kind != OMP_CLAUSE_COPYIN)
4527 new_var = lookup_decl (var, ctx);
4528
4529 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
4530 {
4531 if (pass != 0)
4532 continue;
4533 }
4534 /* C/C++ array section reductions. */
4535 else if (c_kind == OMP_CLAUSE_REDUCTION
4536 && var != OMP_CLAUSE_DECL (c))
4537 {
4538 if (pass == 0)
4539 continue;
4540
4541 tree bias = TREE_OPERAND (OMP_CLAUSE_DECL (c), 1);
4542 tree orig_var = TREE_OPERAND (OMP_CLAUSE_DECL (c), 0);
4543 if (TREE_CODE (orig_var) == POINTER_PLUS_EXPR)
4544 {
4545 tree b = TREE_OPERAND (orig_var, 1);
4546 b = maybe_lookup_decl (b, ctx);
4547 if (b == NULL)
4548 {
4549 b = TREE_OPERAND (orig_var, 1);
4550 b = maybe_lookup_decl_in_outer_ctx (b, ctx);
4551 }
4552 if (integer_zerop (bias))
4553 bias = b;
4554 else
4555 {
4556 bias = fold_convert_loc (clause_loc,
4557 TREE_TYPE (b), bias);
4558 bias = fold_build2_loc (clause_loc, PLUS_EXPR,
4559 TREE_TYPE (b), b, bias);
4560 }
4561 orig_var = TREE_OPERAND (orig_var, 0);
4562 }
4563 if (TREE_CODE (orig_var) == INDIRECT_REF
4564 || TREE_CODE (orig_var) == ADDR_EXPR)
4565 orig_var = TREE_OPERAND (orig_var, 0);
4566 tree d = OMP_CLAUSE_DECL (c);
4567 tree type = TREE_TYPE (d);
4568 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
4569 tree v = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
4570 const char *name = get_name (orig_var);
4571 if (TREE_CONSTANT (v))
4572 {
4573 x = create_tmp_var_raw (type, name);
4574 gimple_add_tmp_var (x);
4575 TREE_ADDRESSABLE (x) = 1;
4576 x = build_fold_addr_expr_loc (clause_loc, x);
4577 }
4578 else
4579 {
4580 tree atmp
4581 = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
4582 tree t = maybe_lookup_decl (v, ctx);
4583 if (t)
4584 v = t;
4585 else
4586 v = maybe_lookup_decl_in_outer_ctx (v, ctx);
4587 gimplify_expr (&v, ilist, NULL, is_gimple_val, fb_rvalue);
4588 t = fold_build2_loc (clause_loc, PLUS_EXPR,
4589 TREE_TYPE (v), v,
4590 build_int_cst (TREE_TYPE (v), 1));
4591 t = fold_build2_loc (clause_loc, MULT_EXPR,
4592 TREE_TYPE (v), t,
4593 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4594 tree al = size_int (TYPE_ALIGN (TREE_TYPE (type)));
4595 x = build_call_expr_loc (clause_loc, atmp, 2, t, al);
4596 }
4597
4598 tree ptype = build_pointer_type (TREE_TYPE (type));
4599 x = fold_convert_loc (clause_loc, ptype, x);
4600 tree y = create_tmp_var (ptype, name);
4601 gimplify_assign (y, x, ilist);
4602 x = y;
4603 tree yb = y;
4604
4605 if (!integer_zerop (bias))
4606 {
4607 bias = fold_convert_loc (clause_loc, pointer_sized_int_node,
4608 bias);
4609 yb = fold_convert_loc (clause_loc, pointer_sized_int_node,
4610 x);
4611 yb = fold_build2_loc (clause_loc, MINUS_EXPR,
4612 pointer_sized_int_node, yb, bias);
4613 x = fold_convert_loc (clause_loc, TREE_TYPE (x), yb);
4614 yb = create_tmp_var (ptype, name);
4615 gimplify_assign (yb, x, ilist);
4616 x = yb;
4617 }
4618
4619 d = TREE_OPERAND (d, 0);
4620 if (TREE_CODE (d) == POINTER_PLUS_EXPR)
4621 d = TREE_OPERAND (d, 0);
4622 if (TREE_CODE (d) == ADDR_EXPR)
4623 {
4624 if (orig_var != var)
4625 {
4626 gcc_assert (is_variable_sized (orig_var));
4627 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var),
4628 x);
4629 gimplify_assign (new_var, x, ilist);
4630 tree new_orig_var = lookup_decl (orig_var, ctx);
4631 tree t = build_fold_indirect_ref (new_var);
4632 DECL_IGNORED_P (new_var) = 0;
4633 TREE_THIS_NOTRAP (t);
4634 SET_DECL_VALUE_EXPR (new_orig_var, t);
4635 DECL_HAS_VALUE_EXPR_P (new_orig_var) = 1;
4636 }
4637 else
4638 {
4639 x = build2 (MEM_REF, TREE_TYPE (new_var), x,
4640 build_int_cst (ptype, 0));
4641 SET_DECL_VALUE_EXPR (new_var, x);
4642 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4643 }
4644 }
4645 else
4646 {
4647 gcc_assert (orig_var == var);
4648 if (TREE_CODE (d) == INDIRECT_REF)
4649 {
4650 x = create_tmp_var (ptype, name);
4651 TREE_ADDRESSABLE (x) = 1;
4652 gimplify_assign (x, yb, ilist);
4653 x = build_fold_addr_expr_loc (clause_loc, x);
4654 }
4655 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
4656 gimplify_assign (new_var, x, ilist);
4657 }
4658 tree y1 = create_tmp_var (ptype, NULL);
4659 gimplify_assign (y1, y, ilist);
4660 tree i2 = NULL_TREE, y2 = NULL_TREE;
4661 tree body2 = NULL_TREE, end2 = NULL_TREE;
4662 tree y3 = NULL_TREE, y4 = NULL_TREE;
4663 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) || is_simd)
4664 {
4665 y2 = create_tmp_var (ptype, NULL);
4666 gimplify_assign (y2, y, ilist);
4667 tree ref = build_outer_var_ref (var, ctx);
4668 /* For ref build_outer_var_ref already performs this. */
4669 if (TREE_CODE (d) == INDIRECT_REF)
4670 gcc_assert (is_reference (var));
4671 else if (TREE_CODE (d) == ADDR_EXPR)
4672 ref = build_fold_addr_expr (ref);
4673 else if (is_reference (var))
4674 ref = build_fold_addr_expr (ref);
4675 ref = fold_convert_loc (clause_loc, ptype, ref);
4676 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
4677 && OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
4678 {
4679 y3 = create_tmp_var (ptype, NULL);
4680 gimplify_assign (y3, unshare_expr (ref), ilist);
4681 }
4682 if (is_simd)
4683 {
4684 y4 = create_tmp_var (ptype, NULL);
4685 gimplify_assign (y4, ref, dlist);
4686 }
4687 }
4688 tree i = create_tmp_var (TREE_TYPE (v), NULL);
4689 gimplify_assign (i, build_int_cst (TREE_TYPE (v), 0), ilist);
4690 tree body = create_artificial_label (UNKNOWN_LOCATION);
4691 tree end = create_artificial_label (UNKNOWN_LOCATION);
4692 gimple_seq_add_stmt (ilist, gimple_build_label (body));
4693 if (y2)
4694 {
4695 i2 = create_tmp_var (TREE_TYPE (v), NULL);
4696 gimplify_assign (i2, build_int_cst (TREE_TYPE (v), 0), dlist);
4697 body2 = create_artificial_label (UNKNOWN_LOCATION);
4698 end2 = create_artificial_label (UNKNOWN_LOCATION);
4699 gimple_seq_add_stmt (dlist, gimple_build_label (body2));
4700 }
4701 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4702 {
4703 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
4704 tree decl_placeholder
4705 = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c);
4706 SET_DECL_VALUE_EXPR (decl_placeholder,
4707 build_simple_mem_ref (y1));
4708 DECL_HAS_VALUE_EXPR_P (decl_placeholder) = 1;
4709 SET_DECL_VALUE_EXPR (placeholder,
4710 y3 ? build_simple_mem_ref (y3)
4711 : error_mark_node);
4712 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
4713 x = lang_hooks.decls.omp_clause_default_ctor
4714 (c, build_simple_mem_ref (y1),
4715 y3 ? build_simple_mem_ref (y3) : NULL_TREE);
4716 if (x)
4717 gimplify_and_add (x, ilist);
4718 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
4719 {
4720 gimple_seq tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
4721 lower_omp (&tseq, ctx);
4722 gimple_seq_add_seq (ilist, tseq);
4723 }
4724 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
4725 if (is_simd)
4726 {
4727 SET_DECL_VALUE_EXPR (decl_placeholder,
4728 build_simple_mem_ref (y2));
4729 SET_DECL_VALUE_EXPR (placeholder,
4730 build_simple_mem_ref (y4));
4731 gimple_seq tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
4732 lower_omp (&tseq, ctx);
4733 gimple_seq_add_seq (dlist, tseq);
4734 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4735 }
4736 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
4737 DECL_HAS_VALUE_EXPR_P (decl_placeholder) = 0;
4738 x = lang_hooks.decls.omp_clause_dtor
4739 (c, build_simple_mem_ref (y2));
4740 if (x)
4741 {
4742 gimple_seq tseq = NULL;
4743 dtor = x;
4744 gimplify_stmt (&dtor, &tseq);
4745 gimple_seq_add_seq (dlist, tseq);
4746 }
4747 }
4748 else
4749 {
4750 x = omp_reduction_init (c, TREE_TYPE (type));
4751 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
4752
4753 /* reduction(-:var) sums up the partial results, so it
4754 acts identically to reduction(+:var). */
4755 if (code == MINUS_EXPR)
4756 code = PLUS_EXPR;
4757
4758 gimplify_assign (build_simple_mem_ref (y1), x, ilist);
4759 if (is_simd)
4760 {
4761 x = build2 (code, TREE_TYPE (type),
4762 build_simple_mem_ref (y4),
4763 build_simple_mem_ref (y2));
4764 gimplify_assign (build_simple_mem_ref (y4), x, dlist);
4765 }
4766 }
4767 gimple *g
4768 = gimple_build_assign (y1, POINTER_PLUS_EXPR, y1,
4769 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4770 gimple_seq_add_stmt (ilist, g);
4771 if (y3)
4772 {
4773 g = gimple_build_assign (y3, POINTER_PLUS_EXPR, y3,
4774 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4775 gimple_seq_add_stmt (ilist, g);
4776 }
4777 g = gimple_build_assign (i, PLUS_EXPR, i,
4778 build_int_cst (TREE_TYPE (i), 1));
4779 gimple_seq_add_stmt (ilist, g);
4780 g = gimple_build_cond (LE_EXPR, i, v, body, end);
4781 gimple_seq_add_stmt (ilist, g);
4782 gimple_seq_add_stmt (ilist, gimple_build_label (end));
4783 if (y2)
4784 {
4785 g = gimple_build_assign (y2, POINTER_PLUS_EXPR, y2,
4786 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4787 gimple_seq_add_stmt (dlist, g);
4788 if (y4)
4789 {
4790 g = gimple_build_assign
4791 (y4, POINTER_PLUS_EXPR, y4,
4792 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4793 gimple_seq_add_stmt (dlist, g);
4794 }
4795 g = gimple_build_assign (i2, PLUS_EXPR, i2,
4796 build_int_cst (TREE_TYPE (i2), 1));
4797 gimple_seq_add_stmt (dlist, g);
4798 g = gimple_build_cond (LE_EXPR, i2, v, body2, end2);
4799 gimple_seq_add_stmt (dlist, g);
4800 gimple_seq_add_stmt (dlist, gimple_build_label (end2));
4801 }
4802 continue;
4803 }
4804 else if (is_variable_sized (var))
4805 {
4806 /* For variable sized types, we need to allocate the
4807 actual storage here. Call alloca and store the
4808 result in the pointer decl that we created elsewhere. */
4809 if (pass == 0)
4810 continue;
4811
4812 if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
4813 {
4814 gcall *stmt;
4815 tree tmp, atmp;
4816
4817 ptr = DECL_VALUE_EXPR (new_var);
4818 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
4819 ptr = TREE_OPERAND (ptr, 0);
4820 gcc_assert (DECL_P (ptr));
4821 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
4822
4823 /* void *tmp = __builtin_alloca */
4824 atmp = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
4825 stmt = gimple_build_call (atmp, 2, x,
4826 size_int (DECL_ALIGN (var)));
4827 tmp = create_tmp_var_raw (ptr_type_node);
4828 gimple_add_tmp_var (tmp);
4829 gimple_call_set_lhs (stmt, tmp);
4830
4831 gimple_seq_add_stmt (ilist, stmt);
4832
4833 x = fold_convert_loc (clause_loc, TREE_TYPE (ptr), tmp);
4834 gimplify_assign (ptr, x, ilist);
4835 }
4836 }
4837 else if (is_reference (var))
4838 {
4839 /* For references that are being privatized for Fortran,
4840 allocate new backing storage for the new pointer
4841 variable. This allows us to avoid changing all the
4842 code that expects a pointer to something that expects
4843 a direct variable. */
4844 if (pass == 0)
4845 continue;
4846
4847 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
4848 if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx))
4849 {
4850 x = build_receiver_ref (var, false, ctx);
4851 x = build_fold_addr_expr_loc (clause_loc, x);
4852 }
4853 else if (TREE_CONSTANT (x))
4854 {
4855 /* For reduction in SIMD loop, defer adding the
4856 initialization of the reference, because if we decide
4857 to use SIMD array for it, the initilization could cause
4858 expansion ICE. */
4859 if (c_kind == OMP_CLAUSE_REDUCTION && is_simd)
4860 x = NULL_TREE;
4861 else
4862 {
4863 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
4864 get_name (var));
4865 gimple_add_tmp_var (x);
4866 TREE_ADDRESSABLE (x) = 1;
4867 x = build_fold_addr_expr_loc (clause_loc, x);
4868 }
4869 }
4870 else
4871 {
4872 tree atmp
4873 = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
4874 tree rtype = TREE_TYPE (TREE_TYPE (new_var));
4875 tree al = size_int (TYPE_ALIGN (rtype));
4876 x = build_call_expr_loc (clause_loc, atmp, 2, x, al);
4877 }
4878
4879 if (x)
4880 {
4881 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
4882 gimplify_assign (new_var, x, ilist);
4883 }
4884
4885 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4886 }
4887 else if (c_kind == OMP_CLAUSE_REDUCTION
4888 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4889 {
4890 if (pass == 0)
4891 continue;
4892 }
4893 else if (pass != 0)
4894 continue;
4895
4896 switch (OMP_CLAUSE_CODE (c))
4897 {
4898 case OMP_CLAUSE_SHARED:
4899 /* Ignore shared directives in teams construct. */
4900 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
4901 continue;
4902 /* Shared global vars are just accessed directly. */
4903 if (is_global_var (new_var))
4904 break;
4905 /* For taskloop firstprivate/lastprivate, represented
4906 as firstprivate and shared clause on the task, new_var
4907 is the firstprivate var. */
4908 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
4909 break;
4910 /* Set up the DECL_VALUE_EXPR for shared variables now. This
4911 needs to be delayed until after fixup_child_record_type so
4912 that we get the correct type during the dereference. */
4913 by_ref = use_pointer_for_field (var, ctx);
4914 x = build_receiver_ref (var, by_ref, ctx);
4915 SET_DECL_VALUE_EXPR (new_var, x);
4916 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4917
4918 /* ??? If VAR is not passed by reference, and the variable
4919 hasn't been initialized yet, then we'll get a warning for
4920 the store into the omp_data_s structure. Ideally, we'd be
4921 able to notice this and not store anything at all, but
4922 we're generating code too early. Suppress the warning. */
4923 if (!by_ref)
4924 TREE_NO_WARNING (var) = 1;
4925 break;
4926
4927 case OMP_CLAUSE_LASTPRIVATE:
4928 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4929 break;
4930 /* FALLTHRU */
4931
4932 case OMP_CLAUSE_PRIVATE:
4933 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE)
4934 x = build_outer_var_ref (var, ctx);
4935 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
4936 {
4937 if (is_task_ctx (ctx))
4938 x = build_receiver_ref (var, false, ctx);
4939 else
4940 x = build_outer_var_ref (var, ctx);
4941 }
4942 else
4943 x = NULL;
4944 do_private:
4945 tree nx;
4946 nx = lang_hooks.decls.omp_clause_default_ctor
4947 (c, unshare_expr (new_var), x);
4948 if (is_simd)
4949 {
4950 tree y = lang_hooks.decls.omp_clause_dtor (c, new_var);
4951 if ((TREE_ADDRESSABLE (new_var) || nx || y
4952 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
4953 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4954 idx, lane, ivar, lvar))
4955 {
4956 if (nx)
4957 x = lang_hooks.decls.omp_clause_default_ctor
4958 (c, unshare_expr (ivar), x);
4959 if (nx && x)
4960 gimplify_and_add (x, &llist[0]);
4961 if (y)
4962 {
4963 y = lang_hooks.decls.omp_clause_dtor (c, ivar);
4964 if (y)
4965 {
4966 gimple_seq tseq = NULL;
4967
4968 dtor = y;
4969 gimplify_stmt (&dtor, &tseq);
4970 gimple_seq_add_seq (&llist[1], tseq);
4971 }
4972 }
4973 break;
4974 }
4975 }
4976 if (nx)
4977 gimplify_and_add (nx, ilist);
4978 /* FALLTHRU */
4979
4980 do_dtor:
4981 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
4982 if (x)
4983 {
4984 gimple_seq tseq = NULL;
4985
4986 dtor = x;
4987 gimplify_stmt (&dtor, &tseq);
4988 gimple_seq_add_seq (dlist, tseq);
4989 }
4990 break;
4991
4992 case OMP_CLAUSE_LINEAR:
4993 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c))
4994 goto do_firstprivate;
4995 if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
4996 x = NULL;
4997 else
4998 x = build_outer_var_ref (var, ctx);
4999 goto do_private;
5000
5001 case OMP_CLAUSE_FIRSTPRIVATE:
5002 if (is_task_ctx (ctx))
5003 {
5004 if (is_reference (var) || is_variable_sized (var))
5005 goto do_dtor;
5006 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var,
5007 ctx))
5008 || use_pointer_for_field (var, NULL))
5009 {
5010 x = build_receiver_ref (var, false, ctx);
5011 SET_DECL_VALUE_EXPR (new_var, x);
5012 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
5013 goto do_dtor;
5014 }
5015 }
5016 do_firstprivate:
5017 x = build_outer_var_ref (var, ctx);
5018 if (is_simd)
5019 {
5020 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
5021 && gimple_omp_for_combined_into_p (ctx->stmt))
5022 {
5023 tree t = OMP_CLAUSE_LINEAR_STEP (c);
5024 tree stept = TREE_TYPE (t);
5025 tree ct = find_omp_clause (clauses,
5026 OMP_CLAUSE__LOOPTEMP_);
5027 gcc_assert (ct);
5028 tree l = OMP_CLAUSE_DECL (ct);
5029 tree n1 = fd->loop.n1;
5030 tree step = fd->loop.step;
5031 tree itype = TREE_TYPE (l);
5032 if (POINTER_TYPE_P (itype))
5033 itype = signed_type_for (itype);
5034 l = fold_build2 (MINUS_EXPR, itype, l, n1);
5035 if (TYPE_UNSIGNED (itype)
5036 && fd->loop.cond_code == GT_EXPR)
5037 l = fold_build2 (TRUNC_DIV_EXPR, itype,
5038 fold_build1 (NEGATE_EXPR, itype, l),
5039 fold_build1 (NEGATE_EXPR,
5040 itype, step));
5041 else
5042 l = fold_build2 (TRUNC_DIV_EXPR, itype, l, step);
5043 t = fold_build2 (MULT_EXPR, stept,
5044 fold_convert (stept, l), t);
5045
5046 if (OMP_CLAUSE_LINEAR_ARRAY (c))
5047 {
5048 x = lang_hooks.decls.omp_clause_linear_ctor
5049 (c, new_var, x, t);
5050 gimplify_and_add (x, ilist);
5051 goto do_dtor;
5052 }
5053
5054 if (POINTER_TYPE_P (TREE_TYPE (x)))
5055 x = fold_build2 (POINTER_PLUS_EXPR,
5056 TREE_TYPE (x), x, t);
5057 else
5058 x = fold_build2 (PLUS_EXPR, TREE_TYPE (x), x, t);
5059 }
5060
5061 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
5062 || TREE_ADDRESSABLE (new_var))
5063 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
5064 idx, lane, ivar, lvar))
5065 {
5066 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR)
5067 {
5068 tree iv = create_tmp_var (TREE_TYPE (new_var));
5069 x = lang_hooks.decls.omp_clause_copy_ctor (c, iv, x);
5070 gimplify_and_add (x, ilist);
5071 gimple_stmt_iterator gsi
5072 = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
5073 gassign *g
5074 = gimple_build_assign (unshare_expr (lvar), iv);
5075 gsi_insert_before_without_update (&gsi, g,
5076 GSI_SAME_STMT);
5077 tree t = OMP_CLAUSE_LINEAR_STEP (c);
5078 enum tree_code code = PLUS_EXPR;
5079 if (POINTER_TYPE_P (TREE_TYPE (new_var)))
5080 code = POINTER_PLUS_EXPR;
5081 g = gimple_build_assign (iv, code, iv, t);
5082 gsi_insert_before_without_update (&gsi, g,
5083 GSI_SAME_STMT);
5084 break;
5085 }
5086 x = lang_hooks.decls.omp_clause_copy_ctor
5087 (c, unshare_expr (ivar), x);
5088 gimplify_and_add (x, &llist[0]);
5089 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
5090 if (x)
5091 {
5092 gimple_seq tseq = NULL;
5093
5094 dtor = x;
5095 gimplify_stmt (&dtor, &tseq);
5096 gimple_seq_add_seq (&llist[1], tseq);
5097 }
5098 break;
5099 }
5100 }
5101 x = lang_hooks.decls.omp_clause_copy_ctor
5102 (c, unshare_expr (new_var), x);
5103 gimplify_and_add (x, ilist);
5104 goto do_dtor;
5105
5106 case OMP_CLAUSE__LOOPTEMP_:
5107 gcc_assert (is_taskreg_ctx (ctx));
5108 x = build_outer_var_ref (var, ctx);
5109 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
5110 gimplify_and_add (x, ilist);
5111 break;
5112
5113 case OMP_CLAUSE_COPYIN:
5114 by_ref = use_pointer_for_field (var, NULL);
5115 x = build_receiver_ref (var, by_ref, ctx);
5116 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
5117 append_to_statement_list (x, &copyin_seq);
5118 copyin_by_ref |= by_ref;
5119 break;
5120
5121 case OMP_CLAUSE_REDUCTION:
5122 /* OpenACC reductions are initialized using the
5123 GOACC_REDUCTION internal function. */
5124 if (is_gimple_omp_oacc (ctx->stmt))
5125 break;
5126 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
5127 {
5128 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
5129 gimple *tseq;
5130 x = build_outer_var_ref (var, ctx);
5131
5132 if (is_reference (var)
5133 && !useless_type_conversion_p (TREE_TYPE (placeholder),
5134 TREE_TYPE (x)))
5135 x = build_fold_addr_expr_loc (clause_loc, x);
5136 SET_DECL_VALUE_EXPR (placeholder, x);
5137 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
5138 tree new_vard = new_var;
5139 if (is_reference (var))
5140 {
5141 gcc_assert (TREE_CODE (new_var) == MEM_REF);
5142 new_vard = TREE_OPERAND (new_var, 0);
5143 gcc_assert (DECL_P (new_vard));
5144 }
5145 if (is_simd
5146 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
5147 idx, lane, ivar, lvar))
5148 {
5149 if (new_vard == new_var)
5150 {
5151 gcc_assert (DECL_VALUE_EXPR (new_var) == lvar);
5152 SET_DECL_VALUE_EXPR (new_var, ivar);
5153 }
5154 else
5155 {
5156 SET_DECL_VALUE_EXPR (new_vard,
5157 build_fold_addr_expr (ivar));
5158 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
5159 }
5160 x = lang_hooks.decls.omp_clause_default_ctor
5161 (c, unshare_expr (ivar),
5162 build_outer_var_ref (var, ctx));
5163 if (x)
5164 gimplify_and_add (x, &llist[0]);
5165 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
5166 {
5167 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
5168 lower_omp (&tseq, ctx);
5169 gimple_seq_add_seq (&llist[0], tseq);
5170 }
5171 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
5172 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
5173 lower_omp (&tseq, ctx);
5174 gimple_seq_add_seq (&llist[1], tseq);
5175 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
5176 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
5177 if (new_vard == new_var)
5178 SET_DECL_VALUE_EXPR (new_var, lvar);
5179 else
5180 SET_DECL_VALUE_EXPR (new_vard,
5181 build_fold_addr_expr (lvar));
5182 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
5183 if (x)
5184 {
5185 tseq = NULL;
5186 dtor = x;
5187 gimplify_stmt (&dtor, &tseq);
5188 gimple_seq_add_seq (&llist[1], tseq);
5189 }
5190 break;
5191 }
5192 /* If this is a reference to constant size reduction var
5193 with placeholder, we haven't emitted the initializer
5194 for it because it is undesirable if SIMD arrays are used.
5195 But if they aren't used, we need to emit the deferred
5196 initialization now. */
5197 else if (is_reference (var) && is_simd)
5198 handle_simd_reference (clause_loc, new_vard, ilist);
5199 x = lang_hooks.decls.omp_clause_default_ctor
5200 (c, unshare_expr (new_var),
5201 build_outer_var_ref (var, ctx));
5202 if (x)
5203 gimplify_and_add (x, ilist);
5204 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
5205 {
5206 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
5207 lower_omp (&tseq, ctx);
5208 gimple_seq_add_seq (ilist, tseq);
5209 }
5210 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
5211 if (is_simd)
5212 {
5213 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
5214 lower_omp (&tseq, ctx);
5215 gimple_seq_add_seq (dlist, tseq);
5216 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
5217 }
5218 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
5219 goto do_dtor;
5220 }
5221 else
5222 {
5223 x = omp_reduction_init (c, TREE_TYPE (new_var));
5224 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
5225 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
5226
5227 /* reduction(-:var) sums up the partial results, so it
5228 acts identically to reduction(+:var). */
5229 if (code == MINUS_EXPR)
5230 code = PLUS_EXPR;
5231
5232 tree new_vard = new_var;
5233 if (is_simd && is_reference (var))
5234 {
5235 gcc_assert (TREE_CODE (new_var) == MEM_REF);
5236 new_vard = TREE_OPERAND (new_var, 0);
5237 gcc_assert (DECL_P (new_vard));
5238 }
5239 if (is_simd
5240 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
5241 idx, lane, ivar, lvar))
5242 {
5243 tree ref = build_outer_var_ref (var, ctx);
5244
5245 gimplify_assign (unshare_expr (ivar), x, &llist[0]);
5246
5247 x = build2 (code, TREE_TYPE (ref), ref, ivar);
5248 ref = build_outer_var_ref (var, ctx);
5249 gimplify_assign (ref, x, &llist[1]);
5250
5251 if (new_vard != new_var)
5252 {
5253 SET_DECL_VALUE_EXPR (new_vard,
5254 build_fold_addr_expr (lvar));
5255 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
5256 }
5257 }
5258 else
5259 {
5260 if (is_reference (var) && is_simd)
5261 handle_simd_reference (clause_loc, new_vard, ilist);
5262 gimplify_assign (new_var, x, ilist);
5263 if (is_simd)
5264 {
5265 tree ref = build_outer_var_ref (var, ctx);
5266
5267 x = build2 (code, TREE_TYPE (ref), ref, new_var);
5268 ref = build_outer_var_ref (var, ctx);
5269 gimplify_assign (ref, x, dlist);
5270 }
5271 }
5272 }
5273 break;
5274
5275 default:
5276 gcc_unreachable ();
5277 }
5278 }
5279 }
5280
5281 if (lane)
5282 {
5283 tree uid = create_tmp_var (ptr_type_node, "simduid");
5284 /* Don't want uninit warnings on simduid, it is always uninitialized,
5285 but we use it not for the value, but for the DECL_UID only. */
5286 TREE_NO_WARNING (uid) = 1;
5287 gimple *g
5288 = gimple_build_call_internal (IFN_GOMP_SIMD_LANE, 1, uid);
5289 gimple_call_set_lhs (g, lane);
5290 gimple_stmt_iterator gsi = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
5291 gsi_insert_before_without_update (&gsi, g, GSI_SAME_STMT);
5292 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SIMDUID_);
5293 OMP_CLAUSE__SIMDUID__DECL (c) = uid;
5294 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
5295 gimple_omp_for_set_clauses (ctx->stmt, c);
5296 g = gimple_build_assign (lane, INTEGER_CST,
5297 build_int_cst (unsigned_type_node, 0));
5298 gimple_seq_add_stmt (ilist, g);
5299 for (int i = 0; i < 2; i++)
5300 if (llist[i])
5301 {
5302 tree vf = create_tmp_var (unsigned_type_node);
5303 g = gimple_build_call_internal (IFN_GOMP_SIMD_VF, 1, uid);
5304 gimple_call_set_lhs (g, vf);
5305 gimple_seq *seq = i == 0 ? ilist : dlist;
5306 gimple_seq_add_stmt (seq, g);
5307 tree t = build_int_cst (unsigned_type_node, 0);
5308 g = gimple_build_assign (idx, INTEGER_CST, t);
5309 gimple_seq_add_stmt (seq, g);
5310 tree body = create_artificial_label (UNKNOWN_LOCATION);
5311 tree header = create_artificial_label (UNKNOWN_LOCATION);
5312 tree end = create_artificial_label (UNKNOWN_LOCATION);
5313 gimple_seq_add_stmt (seq, gimple_build_goto (header));
5314 gimple_seq_add_stmt (seq, gimple_build_label (body));
5315 gimple_seq_add_seq (seq, llist[i]);
5316 t = build_int_cst (unsigned_type_node, 1);
5317 g = gimple_build_assign (idx, PLUS_EXPR, idx, t);
5318 gimple_seq_add_stmt (seq, g);
5319 gimple_seq_add_stmt (seq, gimple_build_label (header));
5320 g = gimple_build_cond (LT_EXPR, idx, vf, body, end);
5321 gimple_seq_add_stmt (seq, g);
5322 gimple_seq_add_stmt (seq, gimple_build_label (end));
5323 }
5324 }
5325
5326 /* The copyin sequence is not to be executed by the main thread, since
5327 that would result in self-copies. Perhaps not visible to scalars,
5328 but it certainly is to C++ operator=. */
5329 if (copyin_seq)
5330 {
5331 x = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM),
5332 0);
5333 x = build2 (NE_EXPR, boolean_type_node, x,
5334 build_int_cst (TREE_TYPE (x), 0));
5335 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
5336 gimplify_and_add (x, ilist);
5337 }
5338
5339 /* If any copyin variable is passed by reference, we must ensure the
5340 master thread doesn't modify it before it is copied over in all
5341 threads. Similarly for variables in both firstprivate and
5342 lastprivate clauses we need to ensure the lastprivate copying
5343 happens after firstprivate copying in all threads. And similarly
5344 for UDRs if initializer expression refers to omp_orig. */
5345 if (copyin_by_ref || lastprivate_firstprivate || reduction_omp_orig_ref)
5346 {
5347 /* Don't add any barrier for #pragma omp simd or
5348 #pragma omp distribute. */
5349 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
5350 || gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_FOR)
5351 gimple_seq_add_stmt (ilist, build_omp_barrier (NULL_TREE));
5352 }
5353
5354 /* If max_vf is non-zero, then we can use only a vectorization factor
5355 up to the max_vf we chose. So stick it into the safelen clause. */
5356 if (max_vf)
5357 {
5358 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
5359 OMP_CLAUSE_SAFELEN);
5360 if (c == NULL_TREE
5361 || (TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) == INTEGER_CST
5362 && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
5363 max_vf) == 1))
5364 {
5365 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_SAFELEN);
5366 OMP_CLAUSE_SAFELEN_EXPR (c) = build_int_cst (integer_type_node,
5367 max_vf);
5368 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
5369 gimple_omp_for_set_clauses (ctx->stmt, c);
5370 }
5371 }
5372 }
5373
5374
5375 /* Generate code to implement the LASTPRIVATE clauses. This is used for
5376 both parallel and workshare constructs. PREDICATE may be NULL if it's
5377 always true. */
5378
5379 static void
5380 lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
5381 omp_context *ctx)
5382 {
5383 tree x, c, label = NULL, orig_clauses = clauses;
5384 bool par_clauses = false;
5385 tree simduid = NULL, lastlane = NULL;
5386
5387 /* Early exit if there are no lastprivate or linear clauses. */
5388 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
5389 if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LASTPRIVATE
5390 || (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LINEAR
5391 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses)))
5392 break;
5393 if (clauses == NULL)
5394 {
5395 /* If this was a workshare clause, see if it had been combined
5396 with its parallel. In that case, look for the clauses on the
5397 parallel statement itself. */
5398 if (is_parallel_ctx (ctx))
5399 return;
5400
5401 ctx = ctx->outer;
5402 if (ctx == NULL || !is_parallel_ctx (ctx))
5403 return;
5404
5405 clauses = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
5406 OMP_CLAUSE_LASTPRIVATE);
5407 if (clauses == NULL)
5408 return;
5409 par_clauses = true;
5410 }
5411
5412 if (predicate)
5413 {
5414 gcond *stmt;
5415 tree label_true, arm1, arm2;
5416
5417 label = create_artificial_label (UNKNOWN_LOCATION);
5418 label_true = create_artificial_label (UNKNOWN_LOCATION);
5419 arm1 = TREE_OPERAND (predicate, 0);
5420 arm2 = TREE_OPERAND (predicate, 1);
5421 gimplify_expr (&arm1, stmt_list, NULL, is_gimple_val, fb_rvalue);
5422 gimplify_expr (&arm2, stmt_list, NULL, is_gimple_val, fb_rvalue);
5423 stmt = gimple_build_cond (TREE_CODE (predicate), arm1, arm2,
5424 label_true, label);
5425 gimple_seq_add_stmt (stmt_list, stmt);
5426 gimple_seq_add_stmt (stmt_list, gimple_build_label (label_true));
5427 }
5428
5429 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
5430 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
5431 {
5432 simduid = find_omp_clause (orig_clauses, OMP_CLAUSE__SIMDUID_);
5433 if (simduid)
5434 simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
5435 }
5436
5437 for (c = clauses; c ;)
5438 {
5439 tree var, new_var;
5440 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
5441
5442 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5443 || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
5444 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
5445 {
5446 var = OMP_CLAUSE_DECL (c);
5447 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5448 && OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c)
5449 && is_taskloop_ctx (ctx))
5450 {
5451 gcc_checking_assert (ctx->outer && is_task_ctx (ctx->outer));
5452 new_var = lookup_decl (var, ctx->outer);
5453 }
5454 else
5455 new_var = lookup_decl (var, ctx);
5456
5457 if (simduid && DECL_HAS_VALUE_EXPR_P (new_var))
5458 {
5459 tree val = DECL_VALUE_EXPR (new_var);
5460 if (TREE_CODE (val) == ARRAY_REF
5461 && VAR_P (TREE_OPERAND (val, 0))
5462 && lookup_attribute ("omp simd array",
5463 DECL_ATTRIBUTES (TREE_OPERAND (val,
5464 0))))
5465 {
5466 if (lastlane == NULL)
5467 {
5468 lastlane = create_tmp_var (unsigned_type_node);
5469 gcall *g
5470 = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE,
5471 2, simduid,
5472 TREE_OPERAND (val, 1));
5473 gimple_call_set_lhs (g, lastlane);
5474 gimple_seq_add_stmt (stmt_list, g);
5475 }
5476 new_var = build4 (ARRAY_REF, TREE_TYPE (val),
5477 TREE_OPERAND (val, 0), lastlane,
5478 NULL_TREE, NULL_TREE);
5479 }
5480 }
5481
5482 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5483 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
5484 {
5485 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
5486 gimple_seq_add_seq (stmt_list,
5487 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
5488 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) = NULL;
5489 }
5490 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
5491 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
5492 {
5493 lower_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
5494 gimple_seq_add_seq (stmt_list,
5495 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c));
5496 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c) = NULL;
5497 }
5498
5499 x = NULL_TREE;
5500 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5501 && OMP_CLAUSE_LASTPRIVATE_TASKLOOP_IV (c))
5502 {
5503 gcc_checking_assert (is_taskloop_ctx (ctx));
5504 tree ovar = maybe_lookup_decl_in_outer_ctx (var,
5505 ctx->outer->outer);
5506 if (is_global_var (ovar))
5507 x = ovar;
5508 }
5509 if (!x)
5510 x = build_outer_var_ref (var, ctx, true);
5511 if (is_reference (var))
5512 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
5513 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
5514 gimplify_and_add (x, stmt_list);
5515 }
5516 c = OMP_CLAUSE_CHAIN (c);
5517 if (c == NULL && !par_clauses)
5518 {
5519 /* If this was a workshare clause, see if it had been combined
5520 with its parallel. In that case, continue looking for the
5521 clauses also on the parallel statement itself. */
5522 if (is_parallel_ctx (ctx))
5523 break;
5524
5525 ctx = ctx->outer;
5526 if (ctx == NULL || !is_parallel_ctx (ctx))
5527 break;
5528
5529 c = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
5530 OMP_CLAUSE_LASTPRIVATE);
5531 par_clauses = true;
5532 }
5533 }
5534
5535 if (label)
5536 gimple_seq_add_stmt (stmt_list, gimple_build_label (label));
5537 }
5538
5539 /* Lower the OpenACC reductions of CLAUSES for compute axis LEVEL
5540 (which might be a placeholder). INNER is true if this is an inner
5541 axis of a multi-axis loop. FORK and JOIN are (optional) fork and
5542 join markers. Generate the before-loop forking sequence in
5543 FORK_SEQ and the after-loop joining sequence to JOIN_SEQ. The
5544 general form of these sequences is
5545
5546 GOACC_REDUCTION_SETUP
5547 GOACC_FORK
5548 GOACC_REDUCTION_INIT
5549 ...
5550 GOACC_REDUCTION_FINI
5551 GOACC_JOIN
5552 GOACC_REDUCTION_TEARDOWN. */
5553
5554 static void
5555 lower_oacc_reductions (location_t loc, tree clauses, tree level, bool inner,
5556 gcall *fork, gcall *join, gimple_seq *fork_seq,
5557 gimple_seq *join_seq, omp_context *ctx)
5558 {
5559 gimple_seq before_fork = NULL;
5560 gimple_seq after_fork = NULL;
5561 gimple_seq before_join = NULL;
5562 gimple_seq after_join = NULL;
5563 tree init_code = NULL_TREE, fini_code = NULL_TREE,
5564 setup_code = NULL_TREE, teardown_code = NULL_TREE;
5565 unsigned offset = 0;
5566
5567 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
5568 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
5569 {
5570 tree orig = OMP_CLAUSE_DECL (c);
5571 tree var = maybe_lookup_decl (orig, ctx);
5572 tree ref_to_res = NULL_TREE;
5573 tree incoming, outgoing, v1, v2, v3;
5574 bool is_private = false;
5575
5576 enum tree_code rcode = OMP_CLAUSE_REDUCTION_CODE (c);
5577 if (rcode == MINUS_EXPR)
5578 rcode = PLUS_EXPR;
5579 else if (rcode == TRUTH_ANDIF_EXPR)
5580 rcode = BIT_AND_EXPR;
5581 else if (rcode == TRUTH_ORIF_EXPR)
5582 rcode = BIT_IOR_EXPR;
5583 tree op = build_int_cst (unsigned_type_node, rcode);
5584
5585 if (!var)
5586 var = orig;
5587
5588 incoming = outgoing = var;
5589
5590 if (!inner)
5591 {
5592 /* See if an outer construct also reduces this variable. */
5593 omp_context *outer = ctx;
5594
5595 while (omp_context *probe = outer->outer)
5596 {
5597 enum gimple_code type = gimple_code (probe->stmt);
5598 tree cls;
5599
5600 switch (type)
5601 {
5602 case GIMPLE_OMP_FOR:
5603 cls = gimple_omp_for_clauses (probe->stmt);
5604 break;
5605
5606 case GIMPLE_OMP_TARGET:
5607 if (gimple_omp_target_kind (probe->stmt)
5608 != GF_OMP_TARGET_KIND_OACC_PARALLEL)
5609 goto do_lookup;
5610
5611 cls = gimple_omp_target_clauses (probe->stmt);
5612 break;
5613
5614 default:
5615 goto do_lookup;
5616 }
5617
5618 outer = probe;
5619 for (; cls; cls = OMP_CLAUSE_CHAIN (cls))
5620 if (OMP_CLAUSE_CODE (cls) == OMP_CLAUSE_REDUCTION
5621 && orig == OMP_CLAUSE_DECL (cls))
5622 {
5623 incoming = outgoing = lookup_decl (orig, probe);
5624 goto has_outer_reduction;
5625 }
5626 else if ((OMP_CLAUSE_CODE (cls) == OMP_CLAUSE_FIRSTPRIVATE
5627 || OMP_CLAUSE_CODE (cls) == OMP_CLAUSE_PRIVATE)
5628 && orig == OMP_CLAUSE_DECL (cls))
5629 {
5630 is_private = true;
5631 goto do_lookup;
5632 }
5633 }
5634
5635 do_lookup:
5636 /* This is the outermost construct with this reduction,
5637 see if there's a mapping for it. */
5638 if (gimple_code (outer->stmt) == GIMPLE_OMP_TARGET
5639 && maybe_lookup_field (orig, outer) && !is_private)
5640 {
5641 ref_to_res = build_receiver_ref (orig, false, outer);
5642 if (is_reference (orig))
5643 ref_to_res = build_simple_mem_ref (ref_to_res);
5644
5645 tree type = TREE_TYPE (var);
5646 if (POINTER_TYPE_P (type))
5647 type = TREE_TYPE (type);
5648
5649 outgoing = var;
5650 incoming = omp_reduction_init_op (loc, rcode, type);
5651 }
5652 else if (ctx->outer)
5653 incoming = outgoing = lookup_decl (orig, ctx->outer);
5654 else
5655 incoming = outgoing = orig;
5656
5657 has_outer_reduction:;
5658 }
5659
5660 if (!ref_to_res)
5661 ref_to_res = integer_zero_node;
5662
5663 if (is_reference (orig))
5664 {
5665 tree type = TREE_TYPE (var);
5666 const char *id = IDENTIFIER_POINTER (DECL_NAME (var));
5667
5668 if (!inner)
5669 {
5670 tree x = create_tmp_var (TREE_TYPE (type), id);
5671 gimplify_assign (var, build_fold_addr_expr (x), fork_seq);
5672 }
5673
5674 v1 = create_tmp_var (type, id);
5675 v2 = create_tmp_var (type, id);
5676 v3 = create_tmp_var (type, id);
5677
5678 gimplify_assign (v1, var, fork_seq);
5679 gimplify_assign (v2, var, fork_seq);
5680 gimplify_assign (v3, var, fork_seq);
5681
5682 var = build_simple_mem_ref (var);
5683 v1 = build_simple_mem_ref (v1);
5684 v2 = build_simple_mem_ref (v2);
5685 v3 = build_simple_mem_ref (v3);
5686 outgoing = build_simple_mem_ref (outgoing);
5687
5688 if (!TREE_CONSTANT (incoming))
5689 incoming = build_simple_mem_ref (incoming);
5690 }
5691 else
5692 v1 = v2 = v3 = var;
5693
5694 /* Determine position in reduction buffer, which may be used
5695 by target. */
5696 enum machine_mode mode = TYPE_MODE (TREE_TYPE (var));
5697 unsigned align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
5698 offset = (offset + align - 1) & ~(align - 1);
5699 tree off = build_int_cst (sizetype, offset);
5700 offset += GET_MODE_SIZE (mode);
5701
5702 if (!init_code)
5703 {
5704 init_code = build_int_cst (integer_type_node,
5705 IFN_GOACC_REDUCTION_INIT);
5706 fini_code = build_int_cst (integer_type_node,
5707 IFN_GOACC_REDUCTION_FINI);
5708 setup_code = build_int_cst (integer_type_node,
5709 IFN_GOACC_REDUCTION_SETUP);
5710 teardown_code = build_int_cst (integer_type_node,
5711 IFN_GOACC_REDUCTION_TEARDOWN);
5712 }
5713
5714 tree setup_call
5715 = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
5716 TREE_TYPE (var), 6, setup_code,
5717 unshare_expr (ref_to_res),
5718 incoming, level, op, off);
5719 tree init_call
5720 = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
5721 TREE_TYPE (var), 6, init_code,
5722 unshare_expr (ref_to_res),
5723 v1, level, op, off);
5724 tree fini_call
5725 = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
5726 TREE_TYPE (var), 6, fini_code,
5727 unshare_expr (ref_to_res),
5728 v2, level, op, off);
5729 tree teardown_call
5730 = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
5731 TREE_TYPE (var), 6, teardown_code,
5732 ref_to_res, v3, level, op, off);
5733
5734 gimplify_assign (v1, setup_call, &before_fork);
5735 gimplify_assign (v2, init_call, &after_fork);
5736 gimplify_assign (v3, fini_call, &before_join);
5737 gimplify_assign (outgoing, teardown_call, &after_join);
5738 }
5739
5740 /* Now stitch things together. */
5741 gimple_seq_add_seq (fork_seq, before_fork);
5742 if (fork)
5743 gimple_seq_add_stmt (fork_seq, fork);
5744 gimple_seq_add_seq (fork_seq, after_fork);
5745
5746 gimple_seq_add_seq (join_seq, before_join);
5747 if (join)
5748 gimple_seq_add_stmt (join_seq, join);
5749 gimple_seq_add_seq (join_seq, after_join);
5750 }
5751
5752 /* Generate code to implement the REDUCTION clauses. */
5753
5754 static void
5755 lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
5756 {
5757 gimple_seq sub_seq = NULL;
5758 gimple *stmt;
5759 tree x, c;
5760 int count = 0;
5761
5762 /* OpenACC loop reductions are handled elsewhere. */
5763 if (is_gimple_omp_oacc (ctx->stmt))
5764 return;
5765
5766 /* SIMD reductions are handled in lower_rec_input_clauses. */
5767 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
5768 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
5769 return;
5770
5771 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
5772 update in that case, otherwise use a lock. */
5773 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
5774 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
5775 {
5776 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
5777 || TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF)
5778 {
5779 /* Never use OMP_ATOMIC for array reductions or UDRs. */
5780 count = -1;
5781 break;
5782 }
5783 count++;
5784 }
5785
5786 if (count == 0)
5787 return;
5788
5789 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
5790 {
5791 tree var, ref, new_var, orig_var;
5792 enum tree_code code;
5793 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
5794
5795 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
5796 continue;
5797
5798 orig_var = var = OMP_CLAUSE_DECL (c);
5799 if (TREE_CODE (var) == MEM_REF)
5800 {
5801 var = TREE_OPERAND (var, 0);
5802 if (TREE_CODE (var) == POINTER_PLUS_EXPR)
5803 var = TREE_OPERAND (var, 0);
5804 if (TREE_CODE (var) == INDIRECT_REF
5805 || TREE_CODE (var) == ADDR_EXPR)
5806 var = TREE_OPERAND (var, 0);
5807 orig_var = var;
5808 if (is_variable_sized (var))
5809 {
5810 gcc_assert (DECL_HAS_VALUE_EXPR_P (var));
5811 var = DECL_VALUE_EXPR (var);
5812 gcc_assert (TREE_CODE (var) == INDIRECT_REF);
5813 var = TREE_OPERAND (var, 0);
5814 gcc_assert (DECL_P (var));
5815 }
5816 }
5817 new_var = lookup_decl (var, ctx);
5818 if (var == OMP_CLAUSE_DECL (c) && is_reference (var))
5819 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
5820 ref = build_outer_var_ref (var, ctx);
5821 code = OMP_CLAUSE_REDUCTION_CODE (c);
5822
5823 /* reduction(-:var) sums up the partial results, so it acts
5824 identically to reduction(+:var). */
5825 if (code == MINUS_EXPR)
5826 code = PLUS_EXPR;
5827
5828 if (count == 1)
5829 {
5830 tree addr = build_fold_addr_expr_loc (clause_loc, ref);
5831
5832 addr = save_expr (addr);
5833 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
5834 x = fold_build2_loc (clause_loc, code, TREE_TYPE (ref), ref, new_var);
5835 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
5836 gimplify_and_add (x, stmt_seqp);
5837 return;
5838 }
5839 else if (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF)
5840 {
5841 tree d = OMP_CLAUSE_DECL (c);
5842 tree type = TREE_TYPE (d);
5843 tree v = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
5844 tree i = create_tmp_var (TREE_TYPE (v), NULL);
5845 tree ptype = build_pointer_type (TREE_TYPE (type));
5846 tree bias = TREE_OPERAND (d, 1);
5847 d = TREE_OPERAND (d, 0);
5848 if (TREE_CODE (d) == POINTER_PLUS_EXPR)
5849 {
5850 tree b = TREE_OPERAND (d, 1);
5851 b = maybe_lookup_decl (b, ctx);
5852 if (b == NULL)
5853 {
5854 b = TREE_OPERAND (d, 1);
5855 b = maybe_lookup_decl_in_outer_ctx (b, ctx);
5856 }
5857 if (integer_zerop (bias))
5858 bias = b;
5859 else
5860 {
5861 bias = fold_convert_loc (clause_loc, TREE_TYPE (b), bias);
5862 bias = fold_build2_loc (clause_loc, PLUS_EXPR,
5863 TREE_TYPE (b), b, bias);
5864 }
5865 d = TREE_OPERAND (d, 0);
5866 }
5867 /* For ref build_outer_var_ref already performs this, so
5868 only new_var needs a dereference. */
5869 if (TREE_CODE (d) == INDIRECT_REF)
5870 {
5871 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
5872 gcc_assert (is_reference (var) && var == orig_var);
5873 }
5874 else if (TREE_CODE (d) == ADDR_EXPR)
5875 {
5876 if (orig_var == var)
5877 {
5878 new_var = build_fold_addr_expr (new_var);
5879 ref = build_fold_addr_expr (ref);
5880 }
5881 }
5882 else
5883 {
5884 gcc_assert (orig_var == var);
5885 if (is_reference (var))
5886 ref = build_fold_addr_expr (ref);
5887 }
5888 if (DECL_P (v))
5889 {
5890 tree t = maybe_lookup_decl (v, ctx);
5891 if (t)
5892 v = t;
5893 else
5894 v = maybe_lookup_decl_in_outer_ctx (v, ctx);
5895 gimplify_expr (&v, stmt_seqp, NULL, is_gimple_val, fb_rvalue);
5896 }
5897 if (!integer_zerop (bias))
5898 {
5899 bias = fold_convert_loc (clause_loc, sizetype, bias);
5900 new_var = fold_build2_loc (clause_loc, POINTER_PLUS_EXPR,
5901 TREE_TYPE (new_var), new_var,
5902 unshare_expr (bias));
5903 ref = fold_build2_loc (clause_loc, POINTER_PLUS_EXPR,
5904 TREE_TYPE (ref), ref, bias);
5905 }
5906 new_var = fold_convert_loc (clause_loc, ptype, new_var);
5907 ref = fold_convert_loc (clause_loc, ptype, ref);
5908 tree m = create_tmp_var (ptype, NULL);
5909 gimplify_assign (m, new_var, stmt_seqp);
5910 new_var = m;
5911 m = create_tmp_var (ptype, NULL);
5912 gimplify_assign (m, ref, stmt_seqp);
5913 ref = m;
5914 gimplify_assign (i, build_int_cst (TREE_TYPE (v), 0), stmt_seqp);
5915 tree body = create_artificial_label (UNKNOWN_LOCATION);
5916 tree end = create_artificial_label (UNKNOWN_LOCATION);
5917 gimple_seq_add_stmt (&sub_seq, gimple_build_label (body));
5918 tree priv = build_simple_mem_ref_loc (clause_loc, new_var);
5919 tree out = build_simple_mem_ref_loc (clause_loc, ref);
5920 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
5921 {
5922 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
5923 tree decl_placeholder
5924 = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c);
5925 SET_DECL_VALUE_EXPR (placeholder, out);
5926 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
5927 SET_DECL_VALUE_EXPR (decl_placeholder, priv);
5928 DECL_HAS_VALUE_EXPR_P (decl_placeholder) = 1;
5929 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
5930 gimple_seq_add_seq (&sub_seq,
5931 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
5932 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
5933 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
5934 OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c) = NULL;
5935 }
5936 else
5937 {
5938 x = build2 (code, TREE_TYPE (out), out, priv);
5939 out = unshare_expr (out);
5940 gimplify_assign (out, x, &sub_seq);
5941 }
5942 gimple *g = gimple_build_assign (new_var, POINTER_PLUS_EXPR, new_var,
5943 TYPE_SIZE_UNIT (TREE_TYPE (type)));
5944 gimple_seq_add_stmt (&sub_seq, g);
5945 g = gimple_build_assign (ref, POINTER_PLUS_EXPR, ref,
5946 TYPE_SIZE_UNIT (TREE_TYPE (type)));
5947 gimple_seq_add_stmt (&sub_seq, g);
5948 g = gimple_build_assign (i, PLUS_EXPR, i,
5949 build_int_cst (TREE_TYPE (i), 1));
5950 gimple_seq_add_stmt (&sub_seq, g);
5951 g = gimple_build_cond (LE_EXPR, i, v, body, end);
5952 gimple_seq_add_stmt (&sub_seq, g);
5953 gimple_seq_add_stmt (&sub_seq, gimple_build_label (end));
5954 }
5955 else if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
5956 {
5957 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
5958
5959 if (is_reference (var)
5960 && !useless_type_conversion_p (TREE_TYPE (placeholder),
5961 TREE_TYPE (ref)))
5962 ref = build_fold_addr_expr_loc (clause_loc, ref);
5963 SET_DECL_VALUE_EXPR (placeholder, ref);
5964 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
5965 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
5966 gimple_seq_add_seq (&sub_seq, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
5967 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
5968 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
5969 }
5970 else
5971 {
5972 x = build2 (code, TREE_TYPE (ref), ref, new_var);
5973 ref = build_outer_var_ref (var, ctx);
5974 gimplify_assign (ref, x, &sub_seq);
5975 }
5976 }
5977
5978 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START),
5979 0);
5980 gimple_seq_add_stmt (stmt_seqp, stmt);
5981
5982 gimple_seq_add_seq (stmt_seqp, sub_seq);
5983
5984 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END),
5985 0);
5986 gimple_seq_add_stmt (stmt_seqp, stmt);
5987 }
5988
5989
5990 /* Generate code to implement the COPYPRIVATE clauses. */
5991
5992 static void
5993 lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist,
5994 omp_context *ctx)
5995 {
5996 tree c;
5997
5998 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
5999 {
6000 tree var, new_var, ref, x;
6001 bool by_ref;
6002 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
6003
6004 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
6005 continue;
6006
6007 var = OMP_CLAUSE_DECL (c);
6008 by_ref = use_pointer_for_field (var, NULL);
6009
6010 ref = build_sender_ref (var, ctx);
6011 x = new_var = lookup_decl_in_outer_ctx (var, ctx);
6012 if (by_ref)
6013 {
6014 x = build_fold_addr_expr_loc (clause_loc, new_var);
6015 x = fold_convert_loc (clause_loc, TREE_TYPE (ref), x);
6016 }
6017 gimplify_assign (ref, x, slist);
6018
6019 ref = build_receiver_ref (var, false, ctx);
6020 if (by_ref)
6021 {
6022 ref = fold_convert_loc (clause_loc,
6023 build_pointer_type (TREE_TYPE (new_var)),
6024 ref);
6025 ref = build_fold_indirect_ref_loc (clause_loc, ref);
6026 }
6027 if (is_reference (var))
6028 {
6029 ref = fold_convert_loc (clause_loc, TREE_TYPE (new_var), ref);
6030 ref = build_simple_mem_ref_loc (clause_loc, ref);
6031 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
6032 }
6033 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, ref);
6034 gimplify_and_add (x, rlist);
6035 }
6036 }
6037
6038
6039 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
6040 and REDUCTION from the sender (aka parent) side. */
6041
6042 static void
6043 lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
6044 omp_context *ctx)
6045 {
6046 tree c, t;
6047 int ignored_looptemp = 0;
6048 bool is_taskloop = false;
6049
6050 /* For taskloop, ignore first two _looptemp_ clauses, those are initialized
6051 by GOMP_taskloop. */
6052 if (is_task_ctx (ctx) && gimple_omp_task_taskloop_p (ctx->stmt))
6053 {
6054 ignored_looptemp = 2;
6055 is_taskloop = true;
6056 }
6057
6058 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
6059 {
6060 tree val, ref, x, var;
6061 bool by_ref, do_in = false, do_out = false;
6062 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
6063
6064 switch (OMP_CLAUSE_CODE (c))
6065 {
6066 case OMP_CLAUSE_PRIVATE:
6067 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
6068 break;
6069 continue;
6070 case OMP_CLAUSE_FIRSTPRIVATE:
6071 case OMP_CLAUSE_COPYIN:
6072 case OMP_CLAUSE_LASTPRIVATE:
6073 case OMP_CLAUSE_REDUCTION:
6074 break;
6075 case OMP_CLAUSE_SHARED:
6076 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
6077 break;
6078 continue;
6079 case OMP_CLAUSE__LOOPTEMP_:
6080 if (ignored_looptemp)
6081 {
6082 ignored_looptemp--;
6083 continue;
6084 }
6085 break;
6086 default:
6087 continue;
6088 }
6089
6090 val = OMP_CLAUSE_DECL (c);
6091 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
6092 && TREE_CODE (val) == MEM_REF)
6093 {
6094 val = TREE_OPERAND (val, 0);
6095 if (TREE_CODE (val) == POINTER_PLUS_EXPR)
6096 val = TREE_OPERAND (val, 0);
6097 if (TREE_CODE (val) == INDIRECT_REF
6098 || TREE_CODE (val) == ADDR_EXPR)
6099 val = TREE_OPERAND (val, 0);
6100 if (is_variable_sized (val))
6101 continue;
6102 }
6103
6104 /* For OMP_CLAUSE_SHARED_FIRSTPRIVATE, look beyond the
6105 outer taskloop region. */
6106 omp_context *ctx_for_o = ctx;
6107 if (is_taskloop
6108 && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
6109 && OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
6110 ctx_for_o = ctx->outer;
6111
6112 var = lookup_decl_in_outer_ctx (val, ctx_for_o);
6113
6114 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
6115 && is_global_var (var))
6116 continue;
6117
6118 t = omp_member_access_dummy_var (var);
6119 if (t)
6120 {
6121 var = DECL_VALUE_EXPR (var);
6122 tree o = maybe_lookup_decl_in_outer_ctx (t, ctx_for_o);
6123 if (o != t)
6124 var = unshare_and_remap (var, t, o);
6125 else
6126 var = unshare_expr (var);
6127 }
6128
6129 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED)
6130 {
6131 /* Handle taskloop firstprivate/lastprivate, where the
6132 lastprivate on GIMPLE_OMP_TASK is represented as
6133 OMP_CLAUSE_SHARED_FIRSTPRIVATE. */
6134 tree f = lookup_sfield ((splay_tree_key) &DECL_UID (val), ctx);
6135 x = omp_build_component_ref (ctx->sender_decl, f);
6136 if (use_pointer_for_field (val, ctx))
6137 var = build_fold_addr_expr (var);
6138 gimplify_assign (x, var, ilist);
6139 DECL_ABSTRACT_ORIGIN (f) = NULL;
6140 continue;
6141 }
6142
6143 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION
6144 || val == OMP_CLAUSE_DECL (c))
6145 && is_variable_sized (val))
6146 continue;
6147 by_ref = use_pointer_for_field (val, NULL);
6148
6149 switch (OMP_CLAUSE_CODE (c))
6150 {
6151 case OMP_CLAUSE_FIRSTPRIVATE:
6152 if (OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c)
6153 && !by_ref
6154 && is_task_ctx (ctx))
6155 TREE_NO_WARNING (var) = 1;
6156 do_in = true;
6157 break;
6158
6159 case OMP_CLAUSE_PRIVATE:
6160 case OMP_CLAUSE_COPYIN:
6161 case OMP_CLAUSE__LOOPTEMP_:
6162 do_in = true;
6163 break;
6164
6165 case OMP_CLAUSE_LASTPRIVATE:
6166 if (by_ref || is_reference (val))
6167 {
6168 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
6169 continue;
6170 do_in = true;
6171 }
6172 else
6173 {
6174 do_out = true;
6175 if (lang_hooks.decls.omp_private_outer_ref (val))
6176 do_in = true;
6177 }
6178 break;
6179
6180 case OMP_CLAUSE_REDUCTION:
6181 do_in = true;
6182 if (val == OMP_CLAUSE_DECL (c))
6183 do_out = !(by_ref || is_reference (val));
6184 else
6185 by_ref = TREE_CODE (TREE_TYPE (val)) == ARRAY_TYPE;
6186 break;
6187
6188 default:
6189 gcc_unreachable ();
6190 }
6191
6192 if (do_in)
6193 {
6194 ref = build_sender_ref (val, ctx);
6195 x = by_ref ? build_fold_addr_expr_loc (clause_loc, var) : var;
6196 gimplify_assign (ref, x, ilist);
6197 if (is_task_ctx (ctx))
6198 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref, 1)) = NULL;
6199 }
6200
6201 if (do_out)
6202 {
6203 ref = build_sender_ref (val, ctx);
6204 gimplify_assign (var, ref, olist);
6205 }
6206 }
6207 }
6208
6209 /* Generate code to implement SHARED from the sender (aka parent)
6210 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
6211 list things that got automatically shared. */
6212
6213 static void
6214 lower_send_shared_vars (gimple_seq *ilist, gimple_seq *olist, omp_context *ctx)
6215 {
6216 tree var, ovar, nvar, t, f, x, record_type;
6217
6218 if (ctx->record_type == NULL)
6219 return;
6220
6221 record_type = ctx->srecord_type ? ctx->srecord_type : ctx->record_type;
6222 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
6223 {
6224 ovar = DECL_ABSTRACT_ORIGIN (f);
6225 if (!ovar || TREE_CODE (ovar) == FIELD_DECL)
6226 continue;
6227
6228 nvar = maybe_lookup_decl (ovar, ctx);
6229 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
6230 continue;
6231
6232 /* If CTX is a nested parallel directive. Find the immediately
6233 enclosing parallel or workshare construct that contains a
6234 mapping for OVAR. */
6235 var = lookup_decl_in_outer_ctx (ovar, ctx);
6236
6237 t = omp_member_access_dummy_var (var);
6238 if (t)
6239 {
6240 var = DECL_VALUE_EXPR (var);
6241 tree o = maybe_lookup_decl_in_outer_ctx (t, ctx);
6242 if (o != t)
6243 var = unshare_and_remap (var, t, o);
6244 else
6245 var = unshare_expr (var);
6246 }
6247
6248 if (use_pointer_for_field (ovar, ctx))
6249 {
6250 x = build_sender_ref (ovar, ctx);
6251 var = build_fold_addr_expr (var);
6252 gimplify_assign (x, var, ilist);
6253 }
6254 else
6255 {
6256 x = build_sender_ref (ovar, ctx);
6257 gimplify_assign (x, var, ilist);
6258
6259 if (!TREE_READONLY (var)
6260 /* We don't need to receive a new reference to a result
6261 or parm decl. In fact we may not store to it as we will
6262 invalidate any pending RSO and generate wrong gimple
6263 during inlining. */
6264 && !((TREE_CODE (var) == RESULT_DECL
6265 || TREE_CODE (var) == PARM_DECL)
6266 && DECL_BY_REFERENCE (var)))
6267 {
6268 x = build_sender_ref (ovar, ctx);
6269 gimplify_assign (var, x, olist);
6270 }
6271 }
6272 }
6273 }
6274
6275 /* Emit an OpenACC head marker call, encapulating the partitioning and
6276 other information that must be processed by the target compiler.
6277 Return the maximum number of dimensions the associated loop might
6278 be partitioned over. */
6279
6280 static unsigned
6281 lower_oacc_head_mark (location_t loc, tree ddvar, tree clauses,
6282 gimple_seq *seq, omp_context *ctx)
6283 {
6284 unsigned levels = 0;
6285 unsigned tag = 0;
6286 tree gang_static = NULL_TREE;
6287 auto_vec<tree, 5> args;
6288
6289 args.quick_push (build_int_cst
6290 (integer_type_node, IFN_UNIQUE_OACC_HEAD_MARK));
6291 args.quick_push (ddvar);
6292 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
6293 {
6294 switch (OMP_CLAUSE_CODE (c))
6295 {
6296 case OMP_CLAUSE_GANG:
6297 tag |= OLF_DIM_GANG;
6298 gang_static = OMP_CLAUSE_GANG_STATIC_EXPR (c);
6299 /* static:* is represented by -1, and we can ignore it, as
6300 scheduling is always static. */
6301 if (gang_static && integer_minus_onep (gang_static))
6302 gang_static = NULL_TREE;
6303 levels++;
6304 break;
6305
6306 case OMP_CLAUSE_WORKER:
6307 tag |= OLF_DIM_WORKER;
6308 levels++;
6309 break;
6310
6311 case OMP_CLAUSE_VECTOR:
6312 tag |= OLF_DIM_VECTOR;
6313 levels++;
6314 break;
6315
6316 case OMP_CLAUSE_SEQ:
6317 tag |= OLF_SEQ;
6318 break;
6319
6320 case OMP_CLAUSE_AUTO:
6321 tag |= OLF_AUTO;
6322 break;
6323
6324 case OMP_CLAUSE_INDEPENDENT:
6325 tag |= OLF_INDEPENDENT;
6326 break;
6327
6328 default:
6329 continue;
6330 }
6331 }
6332
6333 if (gang_static)
6334 {
6335 if (DECL_P (gang_static))
6336 gang_static = build_outer_var_ref (gang_static, ctx);
6337 tag |= OLF_GANG_STATIC;
6338 }
6339
6340 /* In a parallel region, loops are implicitly INDEPENDENT. */
6341 omp_context *tgt = enclosing_target_ctx (ctx);
6342 if (!tgt || is_oacc_parallel (tgt))
6343 tag |= OLF_INDEPENDENT;
6344
6345 /* A loop lacking SEQ, GANG, WORKER and/or VECTOR is implicitly AUTO. */
6346 if (!(tag & (((GOMP_DIM_MASK (GOMP_DIM_MAX) - 1) << OLF_DIM_BASE)
6347 | OLF_SEQ)))
6348 tag |= OLF_AUTO;
6349
6350 /* Ensure at least one level. */
6351 if (!levels)
6352 levels++;
6353
6354 args.quick_push (build_int_cst (integer_type_node, levels));
6355 args.quick_push (build_int_cst (integer_type_node, tag));
6356 if (gang_static)
6357 args.quick_push (gang_static);
6358
6359 gcall *call = gimple_build_call_internal_vec (IFN_UNIQUE, args);
6360 gimple_set_location (call, loc);
6361 gimple_set_lhs (call, ddvar);
6362 gimple_seq_add_stmt (seq, call);
6363
6364 return levels;
6365 }
6366
6367 /* Emit an OpenACC lopp head or tail marker to SEQ. LEVEL is the
6368 partitioning level of the enclosed region. */
6369
6370 static void
6371 lower_oacc_loop_marker (location_t loc, tree ddvar, bool head,
6372 tree tofollow, gimple_seq *seq)
6373 {
6374 int marker_kind = (head ? IFN_UNIQUE_OACC_HEAD_MARK
6375 : IFN_UNIQUE_OACC_TAIL_MARK);
6376 tree marker = build_int_cst (integer_type_node, marker_kind);
6377 int nargs = 2 + (tofollow != NULL_TREE);
6378 gcall *call = gimple_build_call_internal (IFN_UNIQUE, nargs,
6379 marker, ddvar, tofollow);
6380 gimple_set_location (call, loc);
6381 gimple_set_lhs (call, ddvar);
6382 gimple_seq_add_stmt (seq, call);
6383 }
6384
6385 /* Generate the before and after OpenACC loop sequences. CLAUSES are
6386 the loop clauses, from which we extract reductions. Initialize
6387 HEAD and TAIL. */
6388
6389 static void
6390 lower_oacc_head_tail (location_t loc, tree clauses,
6391 gimple_seq *head, gimple_seq *tail, omp_context *ctx)
6392 {
6393 bool inner = false;
6394 tree ddvar = create_tmp_var (integer_type_node, ".data_dep");
6395 gimple_seq_add_stmt (head, gimple_build_assign (ddvar, integer_zero_node));
6396
6397 unsigned count = lower_oacc_head_mark (loc, ddvar, clauses, head, ctx);
6398 tree fork_kind = build_int_cst (unsigned_type_node, IFN_UNIQUE_OACC_FORK);
6399 tree join_kind = build_int_cst (unsigned_type_node, IFN_UNIQUE_OACC_JOIN);
6400
6401 gcc_assert (count);
6402 for (unsigned done = 1; count; count--, done++)
6403 {
6404 gimple_seq fork_seq = NULL;
6405 gimple_seq join_seq = NULL;
6406
6407 tree place = build_int_cst (integer_type_node, -1);
6408 gcall *fork = gimple_build_call_internal (IFN_UNIQUE, 3,
6409 fork_kind, ddvar, place);
6410 gimple_set_location (fork, loc);
6411 gimple_set_lhs (fork, ddvar);
6412
6413 gcall *join = gimple_build_call_internal (IFN_UNIQUE, 3,
6414 join_kind, ddvar, place);
6415 gimple_set_location (join, loc);
6416 gimple_set_lhs (join, ddvar);
6417
6418 /* Mark the beginning of this level sequence. */
6419 if (inner)
6420 lower_oacc_loop_marker (loc, ddvar, true,
6421 build_int_cst (integer_type_node, count),
6422 &fork_seq);
6423 lower_oacc_loop_marker (loc, ddvar, false,
6424 build_int_cst (integer_type_node, done),
6425 &join_seq);
6426
6427 lower_oacc_reductions (loc, clauses, place, inner,
6428 fork, join, &fork_seq, &join_seq, ctx);
6429
6430 /* Append this level to head. */
6431 gimple_seq_add_seq (head, fork_seq);
6432 /* Prepend it to tail. */
6433 gimple_seq_add_seq (&join_seq, *tail);
6434 *tail = join_seq;
6435
6436 inner = true;
6437 }
6438
6439 /* Mark the end of the sequence. */
6440 lower_oacc_loop_marker (loc, ddvar, true, NULL_TREE, head);
6441 lower_oacc_loop_marker (loc, ddvar, false, NULL_TREE, tail);
6442 }
6443
6444 /* A convenience function to build an empty GIMPLE_COND with just the
6445 condition. */
6446
6447 static gcond *
6448 gimple_build_cond_empty (tree cond)
6449 {
6450 enum tree_code pred_code;
6451 tree lhs, rhs;
6452
6453 gimple_cond_get_ops_from_tree (cond, &pred_code, &lhs, &rhs);
6454 return gimple_build_cond (pred_code, lhs, rhs, NULL_TREE, NULL_TREE);
6455 }
6456
6457 /* Return true if a parallel REGION is within a declare target function or
6458 within a target region and is not a part of a gridified target. */
6459
6460 static bool
6461 parallel_needs_hsa_kernel_p (struct omp_region *region)
6462 {
6463 bool indirect = false;
6464 for (region = region->outer; region; region = region->outer)
6465 {
6466 if (region->type == GIMPLE_OMP_PARALLEL)
6467 indirect = true;
6468 else if (region->type == GIMPLE_OMP_TARGET)
6469 {
6470 gomp_target *tgt_stmt
6471 = as_a <gomp_target *> (last_stmt (region->entry));
6472
6473 if (find_omp_clause (gimple_omp_target_clauses (tgt_stmt),
6474 OMP_CLAUSE__GRIDDIM_))
6475 return indirect;
6476 else
6477 return true;
6478 }
6479 }
6480
6481 if (lookup_attribute ("omp declare target",
6482 DECL_ATTRIBUTES (current_function_decl)))
6483 return true;
6484
6485 return false;
6486 }
6487
6488 static void expand_omp_build_assign (gimple_stmt_iterator *, tree, tree,
6489 bool = false);
6490
6491 /* Build the function calls to GOMP_parallel_start etc to actually
6492 generate the parallel operation. REGION is the parallel region
6493 being expanded. BB is the block where to insert the code. WS_ARGS
6494 will be set if this is a call to a combined parallel+workshare
6495 construct, it contains the list of additional arguments needed by
6496 the workshare construct. */
6497
6498 static void
6499 expand_parallel_call (struct omp_region *region, basic_block bb,
6500 gomp_parallel *entry_stmt,
6501 vec<tree, va_gc> *ws_args)
6502 {
6503 tree t, t1, t2, val, cond, c, clauses, flags;
6504 gimple_stmt_iterator gsi;
6505 gimple *stmt;
6506 enum built_in_function start_ix;
6507 int start_ix2;
6508 location_t clause_loc;
6509 vec<tree, va_gc> *args;
6510
6511 clauses = gimple_omp_parallel_clauses (entry_stmt);
6512
6513 /* Determine what flavor of GOMP_parallel we will be
6514 emitting. */
6515 start_ix = BUILT_IN_GOMP_PARALLEL;
6516 if (is_combined_parallel (region))
6517 {
6518 switch (region->inner->type)
6519 {
6520 case GIMPLE_OMP_FOR:
6521 gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
6522 switch (region->inner->sched_kind)
6523 {
6524 case OMP_CLAUSE_SCHEDULE_RUNTIME:
6525 start_ix2 = 3;
6526 break;
6527 case OMP_CLAUSE_SCHEDULE_DYNAMIC:
6528 case OMP_CLAUSE_SCHEDULE_GUIDED:
6529 if (region->inner->sched_modifiers
6530 & OMP_CLAUSE_SCHEDULE_NONMONOTONIC)
6531 {
6532 start_ix2 = 3 + region->inner->sched_kind;
6533 break;
6534 }
6535 /* FALLTHRU */
6536 default:
6537 start_ix2 = region->inner->sched_kind;
6538 break;
6539 }
6540 start_ix2 += (int) BUILT_IN_GOMP_PARALLEL_LOOP_STATIC;
6541 start_ix = (enum built_in_function) start_ix2;
6542 break;
6543 case GIMPLE_OMP_SECTIONS:
6544 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS;
6545 break;
6546 default:
6547 gcc_unreachable ();
6548 }
6549 }
6550
6551 /* By default, the value of NUM_THREADS is zero (selected at run time)
6552 and there is no conditional. */
6553 cond = NULL_TREE;
6554 val = build_int_cst (unsigned_type_node, 0);
6555 flags = build_int_cst (unsigned_type_node, 0);
6556
6557 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
6558 if (c)
6559 cond = OMP_CLAUSE_IF_EXPR (c);
6560
6561 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
6562 if (c)
6563 {
6564 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
6565 clause_loc = OMP_CLAUSE_LOCATION (c);
6566 }
6567 else
6568 clause_loc = gimple_location (entry_stmt);
6569
6570 c = find_omp_clause (clauses, OMP_CLAUSE_PROC_BIND);
6571 if (c)
6572 flags = build_int_cst (unsigned_type_node, OMP_CLAUSE_PROC_BIND_KIND (c));
6573
6574 /* Ensure 'val' is of the correct type. */
6575 val = fold_convert_loc (clause_loc, unsigned_type_node, val);
6576
6577 /* If we found the clause 'if (cond)', build either
6578 (cond != 0) or (cond ? val : 1u). */
6579 if (cond)
6580 {
6581 cond = gimple_boolify (cond);
6582
6583 if (integer_zerop (val))
6584 val = fold_build2_loc (clause_loc,
6585 EQ_EXPR, unsigned_type_node, cond,
6586 build_int_cst (TREE_TYPE (cond), 0));
6587 else
6588 {
6589 basic_block cond_bb, then_bb, else_bb;
6590 edge e, e_then, e_else;
6591 tree tmp_then, tmp_else, tmp_join, tmp_var;
6592
6593 tmp_var = create_tmp_var (TREE_TYPE (val));
6594 if (gimple_in_ssa_p (cfun))
6595 {
6596 tmp_then = make_ssa_name (tmp_var);
6597 tmp_else = make_ssa_name (tmp_var);
6598 tmp_join = make_ssa_name (tmp_var);
6599 }
6600 else
6601 {
6602 tmp_then = tmp_var;
6603 tmp_else = tmp_var;
6604 tmp_join = tmp_var;
6605 }
6606
6607 e = split_block_after_labels (bb);
6608 cond_bb = e->src;
6609 bb = e->dest;
6610 remove_edge (e);
6611
6612 then_bb = create_empty_bb (cond_bb);
6613 else_bb = create_empty_bb (then_bb);
6614 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
6615 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
6616
6617 stmt = gimple_build_cond_empty (cond);
6618 gsi = gsi_start_bb (cond_bb);
6619 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6620
6621 gsi = gsi_start_bb (then_bb);
6622 expand_omp_build_assign (&gsi, tmp_then, val, true);
6623
6624 gsi = gsi_start_bb (else_bb);
6625 expand_omp_build_assign (&gsi, tmp_else,
6626 build_int_cst (unsigned_type_node, 1),
6627 true);
6628
6629 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
6630 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
6631 add_bb_to_loop (then_bb, cond_bb->loop_father);
6632 add_bb_to_loop (else_bb, cond_bb->loop_father);
6633 e_then = make_edge (then_bb, bb, EDGE_FALLTHRU);
6634 e_else = make_edge (else_bb, bb, EDGE_FALLTHRU);
6635
6636 if (gimple_in_ssa_p (cfun))
6637 {
6638 gphi *phi = create_phi_node (tmp_join, bb);
6639 add_phi_arg (phi, tmp_then, e_then, UNKNOWN_LOCATION);
6640 add_phi_arg (phi, tmp_else, e_else, UNKNOWN_LOCATION);
6641 }
6642
6643 val = tmp_join;
6644 }
6645
6646 gsi = gsi_start_bb (bb);
6647 val = force_gimple_operand_gsi (&gsi, val, true, NULL_TREE,
6648 false, GSI_CONTINUE_LINKING);
6649 }
6650
6651 gsi = gsi_last_bb (bb);
6652 t = gimple_omp_parallel_data_arg (entry_stmt);
6653 if (t == NULL)
6654 t1 = null_pointer_node;
6655 else
6656 t1 = build_fold_addr_expr (t);
6657 tree child_fndecl = gimple_omp_parallel_child_fn (entry_stmt);
6658 t2 = build_fold_addr_expr (child_fndecl);
6659
6660 vec_alloc (args, 4 + vec_safe_length (ws_args));
6661 args->quick_push (t2);
6662 args->quick_push (t1);
6663 args->quick_push (val);
6664 if (ws_args)
6665 args->splice (*ws_args);
6666 args->quick_push (flags);
6667
6668 t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
6669 builtin_decl_explicit (start_ix), args);
6670
6671 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6672 false, GSI_CONTINUE_LINKING);
6673
6674 if (hsa_gen_requested_p ()
6675 && parallel_needs_hsa_kernel_p (region))
6676 {
6677 cgraph_node *child_cnode = cgraph_node::get (child_fndecl);
6678 hsa_register_kernel (child_cnode);
6679 }
6680 }
6681
6682 /* Insert a function call whose name is FUNC_NAME with the information from
6683 ENTRY_STMT into the basic_block BB. */
6684
6685 static void
6686 expand_cilk_for_call (basic_block bb, gomp_parallel *entry_stmt,
6687 vec <tree, va_gc> *ws_args)
6688 {
6689 tree t, t1, t2;
6690 gimple_stmt_iterator gsi;
6691 vec <tree, va_gc> *args;
6692
6693 gcc_assert (vec_safe_length (ws_args) == 2);
6694 tree func_name = (*ws_args)[0];
6695 tree grain = (*ws_args)[1];
6696
6697 tree clauses = gimple_omp_parallel_clauses (entry_stmt);
6698 tree count = find_omp_clause (clauses, OMP_CLAUSE__CILK_FOR_COUNT_);
6699 gcc_assert (count != NULL_TREE);
6700 count = OMP_CLAUSE_OPERAND (count, 0);
6701
6702 gsi = gsi_last_bb (bb);
6703 t = gimple_omp_parallel_data_arg (entry_stmt);
6704 if (t == NULL)
6705 t1 = null_pointer_node;
6706 else
6707 t1 = build_fold_addr_expr (t);
6708 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
6709
6710 vec_alloc (args, 4);
6711 args->quick_push (t2);
6712 args->quick_push (t1);
6713 args->quick_push (count);
6714 args->quick_push (grain);
6715 t = build_call_expr_loc_vec (UNKNOWN_LOCATION, func_name, args);
6716
6717 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, false,
6718 GSI_CONTINUE_LINKING);
6719 }
6720
6721 /* Build the function call to GOMP_task to actually
6722 generate the task operation. BB is the block where to insert the code. */
6723
6724 static void
6725 expand_task_call (struct omp_region *region, basic_block bb,
6726 gomp_task *entry_stmt)
6727 {
6728 tree t1, t2, t3;
6729 gimple_stmt_iterator gsi;
6730 location_t loc = gimple_location (entry_stmt);
6731
6732 tree clauses = gimple_omp_task_clauses (entry_stmt);
6733
6734 tree ifc = find_omp_clause (clauses, OMP_CLAUSE_IF);
6735 tree untied = find_omp_clause (clauses, OMP_CLAUSE_UNTIED);
6736 tree mergeable = find_omp_clause (clauses, OMP_CLAUSE_MERGEABLE);
6737 tree depend = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
6738 tree finalc = find_omp_clause (clauses, OMP_CLAUSE_FINAL);
6739 tree priority = find_omp_clause (clauses, OMP_CLAUSE_PRIORITY);
6740
6741 unsigned int iflags
6742 = (untied ? GOMP_TASK_FLAG_UNTIED : 0)
6743 | (mergeable ? GOMP_TASK_FLAG_MERGEABLE : 0)
6744 | (depend ? GOMP_TASK_FLAG_DEPEND : 0);
6745
6746 bool taskloop_p = gimple_omp_task_taskloop_p (entry_stmt);
6747 tree startvar = NULL_TREE, endvar = NULL_TREE, step = NULL_TREE;
6748 tree num_tasks = NULL_TREE;
6749 bool ull = false;
6750 if (taskloop_p)
6751 {
6752 gimple *g = last_stmt (region->outer->entry);
6753 gcc_assert (gimple_code (g) == GIMPLE_OMP_FOR
6754 && gimple_omp_for_kind (g) == GF_OMP_FOR_KIND_TASKLOOP);
6755 struct omp_for_data fd;
6756 extract_omp_for_data (as_a <gomp_for *> (g), &fd, NULL);
6757 startvar = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
6758 endvar = find_omp_clause (OMP_CLAUSE_CHAIN (startvar),
6759 OMP_CLAUSE__LOOPTEMP_);
6760 startvar = OMP_CLAUSE_DECL (startvar);
6761 endvar = OMP_CLAUSE_DECL (endvar);
6762 step = fold_convert_loc (loc, fd.iter_type, fd.loop.step);
6763 if (fd.loop.cond_code == LT_EXPR)
6764 iflags |= GOMP_TASK_FLAG_UP;
6765 tree tclauses = gimple_omp_for_clauses (g);
6766 num_tasks = find_omp_clause (tclauses, OMP_CLAUSE_NUM_TASKS);
6767 if (num_tasks)
6768 num_tasks = OMP_CLAUSE_NUM_TASKS_EXPR (num_tasks);
6769 else
6770 {
6771 num_tasks = find_omp_clause (tclauses, OMP_CLAUSE_GRAINSIZE);
6772 if (num_tasks)
6773 {
6774 iflags |= GOMP_TASK_FLAG_GRAINSIZE;
6775 num_tasks = OMP_CLAUSE_GRAINSIZE_EXPR (num_tasks);
6776 }
6777 else
6778 num_tasks = integer_zero_node;
6779 }
6780 num_tasks = fold_convert_loc (loc, long_integer_type_node, num_tasks);
6781 if (ifc == NULL_TREE)
6782 iflags |= GOMP_TASK_FLAG_IF;
6783 if (find_omp_clause (tclauses, OMP_CLAUSE_NOGROUP))
6784 iflags |= GOMP_TASK_FLAG_NOGROUP;
6785 ull = fd.iter_type == long_long_unsigned_type_node;
6786 }
6787 else if (priority)
6788 iflags |= GOMP_TASK_FLAG_PRIORITY;
6789
6790 tree flags = build_int_cst (unsigned_type_node, iflags);
6791
6792 tree cond = boolean_true_node;
6793 if (ifc)
6794 {
6795 if (taskloop_p)
6796 {
6797 tree t = gimple_boolify (OMP_CLAUSE_IF_EXPR (ifc));
6798 t = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, t,
6799 build_int_cst (unsigned_type_node,
6800 GOMP_TASK_FLAG_IF),
6801 build_int_cst (unsigned_type_node, 0));
6802 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node,
6803 flags, t);
6804 }
6805 else
6806 cond = gimple_boolify (OMP_CLAUSE_IF_EXPR (ifc));
6807 }
6808
6809 if (finalc)
6810 {
6811 tree t = gimple_boolify (OMP_CLAUSE_FINAL_EXPR (finalc));
6812 t = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, t,
6813 build_int_cst (unsigned_type_node,
6814 GOMP_TASK_FLAG_FINAL),
6815 build_int_cst (unsigned_type_node, 0));
6816 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node, flags, t);
6817 }
6818 if (depend)
6819 depend = OMP_CLAUSE_DECL (depend);
6820 else
6821 depend = build_int_cst (ptr_type_node, 0);
6822 if (priority)
6823 priority = fold_convert (integer_type_node,
6824 OMP_CLAUSE_PRIORITY_EXPR (priority));
6825 else
6826 priority = integer_zero_node;
6827
6828 gsi = gsi_last_bb (bb);
6829 tree t = gimple_omp_task_data_arg (entry_stmt);
6830 if (t == NULL)
6831 t2 = null_pointer_node;
6832 else
6833 t2 = build_fold_addr_expr_loc (loc, t);
6834 t1 = build_fold_addr_expr_loc (loc, gimple_omp_task_child_fn (entry_stmt));
6835 t = gimple_omp_task_copy_fn (entry_stmt);
6836 if (t == NULL)
6837 t3 = null_pointer_node;
6838 else
6839 t3 = build_fold_addr_expr_loc (loc, t);
6840
6841 if (taskloop_p)
6842 t = build_call_expr (ull
6843 ? builtin_decl_explicit (BUILT_IN_GOMP_TASKLOOP_ULL)
6844 : builtin_decl_explicit (BUILT_IN_GOMP_TASKLOOP),
6845 11, t1, t2, t3,
6846 gimple_omp_task_arg_size (entry_stmt),
6847 gimple_omp_task_arg_align (entry_stmt), flags,
6848 num_tasks, priority, startvar, endvar, step);
6849 else
6850 t = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK),
6851 9, t1, t2, t3,
6852 gimple_omp_task_arg_size (entry_stmt),
6853 gimple_omp_task_arg_align (entry_stmt), cond, flags,
6854 depend, priority);
6855
6856 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6857 false, GSI_CONTINUE_LINKING);
6858 }
6859
6860
6861 /* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
6862 catch handler and return it. This prevents programs from violating the
6863 structured block semantics with throws. */
6864
6865 static gimple_seq
6866 maybe_catch_exception (gimple_seq body)
6867 {
6868 gimple *g;
6869 tree decl;
6870
6871 if (!flag_exceptions)
6872 return body;
6873
6874 if (lang_hooks.eh_protect_cleanup_actions != NULL)
6875 decl = lang_hooks.eh_protect_cleanup_actions ();
6876 else
6877 decl = builtin_decl_explicit (BUILT_IN_TRAP);
6878
6879 g = gimple_build_eh_must_not_throw (decl);
6880 g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g),
6881 GIMPLE_TRY_CATCH);
6882
6883 return gimple_seq_alloc_with_stmt (g);
6884 }
6885
6886 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
6887
6888 static tree
6889 vec2chain (vec<tree, va_gc> *v)
6890 {
6891 tree chain = NULL_TREE, t;
6892 unsigned ix;
6893
6894 FOR_EACH_VEC_SAFE_ELT_REVERSE (v, ix, t)
6895 {
6896 DECL_CHAIN (t) = chain;
6897 chain = t;
6898 }
6899
6900 return chain;
6901 }
6902
6903
6904 /* Remove barriers in REGION->EXIT's block. Note that this is only
6905 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
6906 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
6907 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
6908 removed. */
6909
6910 static void
6911 remove_exit_barrier (struct omp_region *region)
6912 {
6913 gimple_stmt_iterator gsi;
6914 basic_block exit_bb;
6915 edge_iterator ei;
6916 edge e;
6917 gimple *stmt;
6918 int any_addressable_vars = -1;
6919
6920 exit_bb = region->exit;
6921
6922 /* If the parallel region doesn't return, we don't have REGION->EXIT
6923 block at all. */
6924 if (! exit_bb)
6925 return;
6926
6927 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
6928 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
6929 statements that can appear in between are extremely limited -- no
6930 memory operations at all. Here, we allow nothing at all, so the
6931 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
6932 gsi = gsi_last_bb (exit_bb);
6933 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
6934 gsi_prev (&gsi);
6935 if (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
6936 return;
6937
6938 FOR_EACH_EDGE (e, ei, exit_bb->preds)
6939 {
6940 gsi = gsi_last_bb (e->src);
6941 if (gsi_end_p (gsi))
6942 continue;
6943 stmt = gsi_stmt (gsi);
6944 if (gimple_code (stmt) == GIMPLE_OMP_RETURN
6945 && !gimple_omp_return_nowait_p (stmt))
6946 {
6947 /* OpenMP 3.0 tasks unfortunately prevent this optimization
6948 in many cases. If there could be tasks queued, the barrier
6949 might be needed to let the tasks run before some local
6950 variable of the parallel that the task uses as shared
6951 runs out of scope. The task can be spawned either
6952 from within current function (this would be easy to check)
6953 or from some function it calls and gets passed an address
6954 of such a variable. */
6955 if (any_addressable_vars < 0)
6956 {
6957 gomp_parallel *parallel_stmt
6958 = as_a <gomp_parallel *> (last_stmt (region->entry));
6959 tree child_fun = gimple_omp_parallel_child_fn (parallel_stmt);
6960 tree local_decls, block, decl;
6961 unsigned ix;
6962
6963 any_addressable_vars = 0;
6964 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun), ix, decl)
6965 if (TREE_ADDRESSABLE (decl))
6966 {
6967 any_addressable_vars = 1;
6968 break;
6969 }
6970 for (block = gimple_block (stmt);
6971 !any_addressable_vars
6972 && block
6973 && TREE_CODE (block) == BLOCK;
6974 block = BLOCK_SUPERCONTEXT (block))
6975 {
6976 for (local_decls = BLOCK_VARS (block);
6977 local_decls;
6978 local_decls = DECL_CHAIN (local_decls))
6979 if (TREE_ADDRESSABLE (local_decls))
6980 {
6981 any_addressable_vars = 1;
6982 break;
6983 }
6984 if (block == gimple_block (parallel_stmt))
6985 break;
6986 }
6987 }
6988 if (!any_addressable_vars)
6989 gimple_omp_return_set_nowait (stmt);
6990 }
6991 }
6992 }
6993
6994 static void
6995 remove_exit_barriers (struct omp_region *region)
6996 {
6997 if (region->type == GIMPLE_OMP_PARALLEL)
6998 remove_exit_barrier (region);
6999
7000 if (region->inner)
7001 {
7002 region = region->inner;
7003 remove_exit_barriers (region);
7004 while (region->next)
7005 {
7006 region = region->next;
7007 remove_exit_barriers (region);
7008 }
7009 }
7010 }
7011
7012 /* Optimize omp_get_thread_num () and omp_get_num_threads ()
7013 calls. These can't be declared as const functions, but
7014 within one parallel body they are constant, so they can be
7015 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
7016 which are declared const. Similarly for task body, except
7017 that in untied task omp_get_thread_num () can change at any task
7018 scheduling point. */
7019
7020 static void
7021 optimize_omp_library_calls (gimple *entry_stmt)
7022 {
7023 basic_block bb;
7024 gimple_stmt_iterator gsi;
7025 tree thr_num_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
7026 tree thr_num_id = DECL_ASSEMBLER_NAME (thr_num_tree);
7027 tree num_thr_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
7028 tree num_thr_id = DECL_ASSEMBLER_NAME (num_thr_tree);
7029 bool untied_task = (gimple_code (entry_stmt) == GIMPLE_OMP_TASK
7030 && find_omp_clause (gimple_omp_task_clauses (entry_stmt),
7031 OMP_CLAUSE_UNTIED) != NULL);
7032
7033 FOR_EACH_BB_FN (bb, cfun)
7034 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
7035 {
7036 gimple *call = gsi_stmt (gsi);
7037 tree decl;
7038
7039 if (is_gimple_call (call)
7040 && (decl = gimple_call_fndecl (call))
7041 && DECL_EXTERNAL (decl)
7042 && TREE_PUBLIC (decl)
7043 && DECL_INITIAL (decl) == NULL)
7044 {
7045 tree built_in;
7046
7047 if (DECL_NAME (decl) == thr_num_id)
7048 {
7049 /* In #pragma omp task untied omp_get_thread_num () can change
7050 during the execution of the task region. */
7051 if (untied_task)
7052 continue;
7053 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
7054 }
7055 else if (DECL_NAME (decl) == num_thr_id)
7056 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
7057 else
7058 continue;
7059
7060 if (DECL_ASSEMBLER_NAME (decl) != DECL_ASSEMBLER_NAME (built_in)
7061 || gimple_call_num_args (call) != 0)
7062 continue;
7063
7064 if (flag_exceptions && !TREE_NOTHROW (decl))
7065 continue;
7066
7067 if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
7068 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl)),
7069 TREE_TYPE (TREE_TYPE (built_in))))
7070 continue;
7071
7072 gimple_call_set_fndecl (call, built_in);
7073 }
7074 }
7075 }
7076
7077 /* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
7078 regimplified. */
7079
7080 static tree
7081 expand_omp_regimplify_p (tree *tp, int *walk_subtrees, void *)
7082 {
7083 tree t = *tp;
7084
7085 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
7086 if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t))
7087 return t;
7088
7089 if (TREE_CODE (t) == ADDR_EXPR)
7090 recompute_tree_invariant_for_addr_expr (t);
7091
7092 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
7093 return NULL_TREE;
7094 }
7095
7096 /* Prepend or append TO = FROM assignment before or after *GSI_P. */
7097
7098 static void
7099 expand_omp_build_assign (gimple_stmt_iterator *gsi_p, tree to, tree from,
7100 bool after)
7101 {
7102 bool simple_p = DECL_P (to) && TREE_ADDRESSABLE (to);
7103 from = force_gimple_operand_gsi (gsi_p, from, simple_p, NULL_TREE,
7104 !after, after ? GSI_CONTINUE_LINKING
7105 : GSI_SAME_STMT);
7106 gimple *stmt = gimple_build_assign (to, from);
7107 if (after)
7108 gsi_insert_after (gsi_p, stmt, GSI_CONTINUE_LINKING);
7109 else
7110 gsi_insert_before (gsi_p, stmt, GSI_SAME_STMT);
7111 if (walk_tree (&from, expand_omp_regimplify_p, NULL, NULL)
7112 || walk_tree (&to, expand_omp_regimplify_p, NULL, NULL))
7113 {
7114 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
7115 gimple_regimplify_operands (stmt, &gsi);
7116 }
7117 }
7118
7119 /* Expand the OpenMP parallel or task directive starting at REGION. */
7120
7121 static void
7122 expand_omp_taskreg (struct omp_region *region)
7123 {
7124 basic_block entry_bb, exit_bb, new_bb;
7125 struct function *child_cfun;
7126 tree child_fn, block, t;
7127 gimple_stmt_iterator gsi;
7128 gimple *entry_stmt, *stmt;
7129 edge e;
7130 vec<tree, va_gc> *ws_args;
7131
7132 entry_stmt = last_stmt (region->entry);
7133 child_fn = gimple_omp_taskreg_child_fn (entry_stmt);
7134 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
7135
7136 entry_bb = region->entry;
7137 if (gimple_code (entry_stmt) == GIMPLE_OMP_TASK)
7138 exit_bb = region->cont;
7139 else
7140 exit_bb = region->exit;
7141
7142 bool is_cilk_for
7143 = (flag_cilkplus
7144 && gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL
7145 && find_omp_clause (gimple_omp_parallel_clauses (entry_stmt),
7146 OMP_CLAUSE__CILK_FOR_COUNT_) != NULL_TREE);
7147
7148 if (is_cilk_for)
7149 /* If it is a _Cilk_for statement, it is modelled *like* a parallel for,
7150 and the inner statement contains the name of the built-in function
7151 and grain. */
7152 ws_args = region->inner->ws_args;
7153 else if (is_combined_parallel (region))
7154 ws_args = region->ws_args;
7155 else
7156 ws_args = NULL;
7157
7158 if (child_cfun->cfg)
7159 {
7160 /* Due to inlining, it may happen that we have already outlined
7161 the region, in which case all we need to do is make the
7162 sub-graph unreachable and emit the parallel call. */
7163 edge entry_succ_e, exit_succ_e;
7164
7165 entry_succ_e = single_succ_edge (entry_bb);
7166
7167 gsi = gsi_last_bb (entry_bb);
7168 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_PARALLEL
7169 || gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_TASK);
7170 gsi_remove (&gsi, true);
7171
7172 new_bb = entry_bb;
7173 if (exit_bb)
7174 {
7175 exit_succ_e = single_succ_edge (exit_bb);
7176 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
7177 }
7178 remove_edge_and_dominated_blocks (entry_succ_e);
7179 }
7180 else
7181 {
7182 unsigned srcidx, dstidx, num;
7183
7184 /* If the parallel region needs data sent from the parent
7185 function, then the very first statement (except possible
7186 tree profile counter updates) of the parallel body
7187 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
7188 &.OMP_DATA_O is passed as an argument to the child function,
7189 we need to replace it with the argument as seen by the child
7190 function.
7191
7192 In most cases, this will end up being the identity assignment
7193 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
7194 a function call that has been inlined, the original PARM_DECL
7195 .OMP_DATA_I may have been converted into a different local
7196 variable. In which case, we need to keep the assignment. */
7197 if (gimple_omp_taskreg_data_arg (entry_stmt))
7198 {
7199 basic_block entry_succ_bb
7200 = single_succ_p (entry_bb) ? single_succ (entry_bb)
7201 : FALLTHRU_EDGE (entry_bb)->dest;
7202 tree arg;
7203 gimple *parcopy_stmt = NULL;
7204
7205 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
7206 {
7207 gimple *stmt;
7208
7209 gcc_assert (!gsi_end_p (gsi));
7210 stmt = gsi_stmt (gsi);
7211 if (gimple_code (stmt) != GIMPLE_ASSIGN)
7212 continue;
7213
7214 if (gimple_num_ops (stmt) == 2)
7215 {
7216 tree arg = gimple_assign_rhs1 (stmt);
7217
7218 /* We're ignore the subcode because we're
7219 effectively doing a STRIP_NOPS. */
7220
7221 if (TREE_CODE (arg) == ADDR_EXPR
7222 && TREE_OPERAND (arg, 0)
7223 == gimple_omp_taskreg_data_arg (entry_stmt))
7224 {
7225 parcopy_stmt = stmt;
7226 break;
7227 }
7228 }
7229 }
7230
7231 gcc_assert (parcopy_stmt != NULL);
7232 arg = DECL_ARGUMENTS (child_fn);
7233
7234 if (!gimple_in_ssa_p (cfun))
7235 {
7236 if (gimple_assign_lhs (parcopy_stmt) == arg)
7237 gsi_remove (&gsi, true);
7238 else
7239 {
7240 /* ?? Is setting the subcode really necessary ?? */
7241 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (arg));
7242 gimple_assign_set_rhs1 (parcopy_stmt, arg);
7243 }
7244 }
7245 else
7246 {
7247 tree lhs = gimple_assign_lhs (parcopy_stmt);
7248 gcc_assert (SSA_NAME_VAR (lhs) == arg);
7249 /* We'd like to set the rhs to the default def in the child_fn,
7250 but it's too early to create ssa names in the child_fn.
7251 Instead, we set the rhs to the parm. In
7252 move_sese_region_to_fn, we introduce a default def for the
7253 parm, map the parm to it's default def, and once we encounter
7254 this stmt, replace the parm with the default def. */
7255 gimple_assign_set_rhs1 (parcopy_stmt, arg);
7256 update_stmt (parcopy_stmt);
7257 }
7258 }
7259
7260 /* Declare local variables needed in CHILD_CFUN. */
7261 block = DECL_INITIAL (child_fn);
7262 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
7263 /* The gimplifier could record temporaries in parallel/task block
7264 rather than in containing function's local_decls chain,
7265 which would mean cgraph missed finalizing them. Do it now. */
7266 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
7267 if (TREE_CODE (t) == VAR_DECL
7268 && TREE_STATIC (t)
7269 && !DECL_EXTERNAL (t))
7270 varpool_node::finalize_decl (t);
7271 DECL_SAVED_TREE (child_fn) = NULL;
7272 /* We'll create a CFG for child_fn, so no gimple body is needed. */
7273 gimple_set_body (child_fn, NULL);
7274 TREE_USED (block) = 1;
7275
7276 /* Reset DECL_CONTEXT on function arguments. */
7277 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
7278 DECL_CONTEXT (t) = child_fn;
7279
7280 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
7281 so that it can be moved to the child function. */
7282 gsi = gsi_last_bb (entry_bb);
7283 stmt = gsi_stmt (gsi);
7284 gcc_assert (stmt && (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
7285 || gimple_code (stmt) == GIMPLE_OMP_TASK));
7286 e = split_block (entry_bb, stmt);
7287 gsi_remove (&gsi, true);
7288 entry_bb = e->dest;
7289 edge e2 = NULL;
7290 if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
7291 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7292 else
7293 {
7294 e2 = make_edge (e->src, BRANCH_EDGE (entry_bb)->dest, EDGE_ABNORMAL);
7295 gcc_assert (e2->dest == region->exit);
7296 remove_edge (BRANCH_EDGE (entry_bb));
7297 set_immediate_dominator (CDI_DOMINATORS, e2->dest, e->src);
7298 gsi = gsi_last_bb (region->exit);
7299 gcc_assert (!gsi_end_p (gsi)
7300 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
7301 gsi_remove (&gsi, true);
7302 }
7303
7304 /* Convert GIMPLE_OMP_{RETURN,CONTINUE} into a RETURN_EXPR. */
7305 if (exit_bb)
7306 {
7307 gsi = gsi_last_bb (exit_bb);
7308 gcc_assert (!gsi_end_p (gsi)
7309 && (gimple_code (gsi_stmt (gsi))
7310 == (e2 ? GIMPLE_OMP_CONTINUE : GIMPLE_OMP_RETURN)));
7311 stmt = gimple_build_return (NULL);
7312 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
7313 gsi_remove (&gsi, true);
7314 }
7315
7316 /* Move the parallel region into CHILD_CFUN. */
7317
7318 if (gimple_in_ssa_p (cfun))
7319 {
7320 init_tree_ssa (child_cfun);
7321 init_ssa_operands (child_cfun);
7322 child_cfun->gimple_df->in_ssa_p = true;
7323 block = NULL_TREE;
7324 }
7325 else
7326 block = gimple_block (entry_stmt);
7327
7328 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
7329 if (exit_bb)
7330 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
7331 if (e2)
7332 {
7333 basic_block dest_bb = e2->dest;
7334 if (!exit_bb)
7335 make_edge (new_bb, dest_bb, EDGE_FALLTHRU);
7336 remove_edge (e2);
7337 set_immediate_dominator (CDI_DOMINATORS, dest_bb, new_bb);
7338 }
7339 /* When the OMP expansion process cannot guarantee an up-to-date
7340 loop tree arrange for the child function to fixup loops. */
7341 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
7342 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
7343
7344 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
7345 num = vec_safe_length (child_cfun->local_decls);
7346 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
7347 {
7348 t = (*child_cfun->local_decls)[srcidx];
7349 if (DECL_CONTEXT (t) == cfun->decl)
7350 continue;
7351 if (srcidx != dstidx)
7352 (*child_cfun->local_decls)[dstidx] = t;
7353 dstidx++;
7354 }
7355 if (dstidx != num)
7356 vec_safe_truncate (child_cfun->local_decls, dstidx);
7357
7358 /* Inform the callgraph about the new function. */
7359 child_cfun->curr_properties = cfun->curr_properties;
7360 child_cfun->has_simduid_loops |= cfun->has_simduid_loops;
7361 child_cfun->has_force_vectorize_loops |= cfun->has_force_vectorize_loops;
7362 cgraph_node *node = cgraph_node::get_create (child_fn);
7363 node->parallelized_function = 1;
7364 cgraph_node::add_new_function (child_fn, true);
7365
7366 bool need_asm = DECL_ASSEMBLER_NAME_SET_P (current_function_decl)
7367 && !DECL_ASSEMBLER_NAME_SET_P (child_fn);
7368
7369 /* Fix the callgraph edges for child_cfun. Those for cfun will be
7370 fixed in a following pass. */
7371 push_cfun (child_cfun);
7372 if (need_asm)
7373 assign_assembler_name_if_neeeded (child_fn);
7374
7375 if (optimize)
7376 optimize_omp_library_calls (entry_stmt);
7377 cgraph_edge::rebuild_edges ();
7378
7379 /* Some EH regions might become dead, see PR34608. If
7380 pass_cleanup_cfg isn't the first pass to happen with the
7381 new child, these dead EH edges might cause problems.
7382 Clean them up now. */
7383 if (flag_exceptions)
7384 {
7385 basic_block bb;
7386 bool changed = false;
7387
7388 FOR_EACH_BB_FN (bb, cfun)
7389 changed |= gimple_purge_dead_eh_edges (bb);
7390 if (changed)
7391 cleanup_tree_cfg ();
7392 }
7393 if (gimple_in_ssa_p (cfun))
7394 update_ssa (TODO_update_ssa);
7395 if (flag_checking && !loops_state_satisfies_p (LOOPS_NEED_FIXUP))
7396 verify_loop_structure ();
7397 pop_cfun ();
7398
7399 if (dump_file && !gimple_in_ssa_p (cfun))
7400 {
7401 omp_any_child_fn_dumped = true;
7402 dump_function_header (dump_file, child_fn, dump_flags);
7403 dump_function_to_file (child_fn, dump_file, dump_flags);
7404 }
7405 }
7406
7407 /* Emit a library call to launch the children threads. */
7408 if (is_cilk_for)
7409 expand_cilk_for_call (new_bb,
7410 as_a <gomp_parallel *> (entry_stmt), ws_args);
7411 else if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
7412 expand_parallel_call (region, new_bb,
7413 as_a <gomp_parallel *> (entry_stmt), ws_args);
7414 else
7415 expand_task_call (region, new_bb, as_a <gomp_task *> (entry_stmt));
7416 if (gimple_in_ssa_p (cfun))
7417 update_ssa (TODO_update_ssa_only_virtuals);
7418 }
7419
7420 /* Information about members of an OpenACC collapsed loop nest. */
7421
7422 struct oacc_collapse
7423 {
7424 tree base; /* Base value. */
7425 tree iters; /* Number of steps. */
7426 tree step; /* step size. */
7427 };
7428
7429 /* Helper for expand_oacc_for. Determine collapsed loop information.
7430 Fill in COUNTS array. Emit any initialization code before GSI.
7431 Return the calculated outer loop bound of BOUND_TYPE. */
7432
7433 static tree
7434 expand_oacc_collapse_init (const struct omp_for_data *fd,
7435 gimple_stmt_iterator *gsi,
7436 oacc_collapse *counts, tree bound_type)
7437 {
7438 tree total = build_int_cst (bound_type, 1);
7439 int ix;
7440
7441 gcc_assert (integer_onep (fd->loop.step));
7442 gcc_assert (integer_zerop (fd->loop.n1));
7443
7444 for (ix = 0; ix != fd->collapse; ix++)
7445 {
7446 const omp_for_data_loop *loop = &fd->loops[ix];
7447
7448 tree iter_type = TREE_TYPE (loop->v);
7449 tree diff_type = iter_type;
7450 tree plus_type = iter_type;
7451
7452 gcc_assert (loop->cond_code == fd->loop.cond_code);
7453
7454 if (POINTER_TYPE_P (iter_type))
7455 plus_type = sizetype;
7456 if (POINTER_TYPE_P (diff_type) || TYPE_UNSIGNED (diff_type))
7457 diff_type = signed_type_for (diff_type);
7458
7459 tree b = loop->n1;
7460 tree e = loop->n2;
7461 tree s = loop->step;
7462 bool up = loop->cond_code == LT_EXPR;
7463 tree dir = build_int_cst (diff_type, up ? +1 : -1);
7464 bool negating;
7465 tree expr;
7466
7467 b = force_gimple_operand_gsi (gsi, b, true, NULL_TREE,
7468 true, GSI_SAME_STMT);
7469 e = force_gimple_operand_gsi (gsi, e, true, NULL_TREE,
7470 true, GSI_SAME_STMT);
7471
7472 /* Convert the step, avoiding possible unsigned->signed overflow. */
7473 negating = !up && TYPE_UNSIGNED (TREE_TYPE (s));
7474 if (negating)
7475 s = fold_build1 (NEGATE_EXPR, TREE_TYPE (s), s);
7476 s = fold_convert (diff_type, s);
7477 if (negating)
7478 s = fold_build1 (NEGATE_EXPR, diff_type, s);
7479 s = force_gimple_operand_gsi (gsi, s, true, NULL_TREE,
7480 true, GSI_SAME_STMT);
7481
7482 /* Determine the range, avoiding possible unsigned->signed overflow. */
7483 negating = !up && TYPE_UNSIGNED (iter_type);
7484 expr = fold_build2 (MINUS_EXPR, plus_type,
7485 fold_convert (plus_type, negating ? b : e),
7486 fold_convert (plus_type, negating ? e : b));
7487 expr = fold_convert (diff_type, expr);
7488 if (negating)
7489 expr = fold_build1 (NEGATE_EXPR, diff_type, expr);
7490 tree range = force_gimple_operand_gsi
7491 (gsi, expr, true, NULL_TREE, true, GSI_SAME_STMT);
7492
7493 /* Determine number of iterations. */
7494 expr = fold_build2 (MINUS_EXPR, diff_type, range, dir);
7495 expr = fold_build2 (PLUS_EXPR, diff_type, expr, s);
7496 expr = fold_build2 (TRUNC_DIV_EXPR, diff_type, expr, s);
7497
7498 tree iters = force_gimple_operand_gsi (gsi, expr, true, NULL_TREE,
7499 true, GSI_SAME_STMT);
7500
7501 counts[ix].base = b;
7502 counts[ix].iters = iters;
7503 counts[ix].step = s;
7504
7505 total = fold_build2 (MULT_EXPR, bound_type, total,
7506 fold_convert (bound_type, iters));
7507 }
7508
7509 return total;
7510 }
7511
7512 /* Emit initializers for collapsed loop members. IVAR is the outer
7513 loop iteration variable, from which collapsed loop iteration values
7514 are calculated. COUNTS array has been initialized by
7515 expand_oacc_collapse_inits. */
7516
7517 static void
7518 expand_oacc_collapse_vars (const struct omp_for_data *fd,
7519 gimple_stmt_iterator *gsi,
7520 const oacc_collapse *counts, tree ivar)
7521 {
7522 tree ivar_type = TREE_TYPE (ivar);
7523
7524 /* The most rapidly changing iteration variable is the innermost
7525 one. */
7526 for (int ix = fd->collapse; ix--;)
7527 {
7528 const omp_for_data_loop *loop = &fd->loops[ix];
7529 const oacc_collapse *collapse = &counts[ix];
7530 tree iter_type = TREE_TYPE (loop->v);
7531 tree diff_type = TREE_TYPE (collapse->step);
7532 tree plus_type = iter_type;
7533 enum tree_code plus_code = PLUS_EXPR;
7534 tree expr;
7535
7536 if (POINTER_TYPE_P (iter_type))
7537 {
7538 plus_code = POINTER_PLUS_EXPR;
7539 plus_type = sizetype;
7540 }
7541
7542 expr = fold_build2 (TRUNC_MOD_EXPR, ivar_type, ivar,
7543 fold_convert (ivar_type, collapse->iters));
7544 expr = fold_build2 (MULT_EXPR, diff_type, fold_convert (diff_type, expr),
7545 collapse->step);
7546 expr = fold_build2 (plus_code, iter_type, collapse->base,
7547 fold_convert (plus_type, expr));
7548 expr = force_gimple_operand_gsi (gsi, expr, false, NULL_TREE,
7549 true, GSI_SAME_STMT);
7550 gassign *ass = gimple_build_assign (loop->v, expr);
7551 gsi_insert_before (gsi, ass, GSI_SAME_STMT);
7552
7553 if (ix)
7554 {
7555 expr = fold_build2 (TRUNC_DIV_EXPR, ivar_type, ivar,
7556 fold_convert (ivar_type, collapse->iters));
7557 ivar = force_gimple_operand_gsi (gsi, expr, true, NULL_TREE,
7558 true, GSI_SAME_STMT);
7559 }
7560 }
7561 }
7562
7563
7564 /* Helper function for expand_omp_{for_*,simd}. If this is the outermost
7565 of the combined collapse > 1 loop constructs, generate code like:
7566 if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
7567 if (cond3 is <)
7568 adj = STEP3 - 1;
7569 else
7570 adj = STEP3 + 1;
7571 count3 = (adj + N32 - N31) / STEP3;
7572 if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
7573 if (cond2 is <)
7574 adj = STEP2 - 1;
7575 else
7576 adj = STEP2 + 1;
7577 count2 = (adj + N22 - N21) / STEP2;
7578 if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
7579 if (cond1 is <)
7580 adj = STEP1 - 1;
7581 else
7582 adj = STEP1 + 1;
7583 count1 = (adj + N12 - N11) / STEP1;
7584 count = count1 * count2 * count3;
7585 Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
7586 count = 0;
7587 and set ZERO_ITER_BB to that bb. If this isn't the outermost
7588 of the combined loop constructs, just initialize COUNTS array
7589 from the _looptemp_ clauses. */
7590
7591 /* NOTE: It *could* be better to moosh all of the BBs together,
7592 creating one larger BB with all the computation and the unexpected
7593 jump at the end. I.e.
7594
7595 bool zero3, zero2, zero1, zero;
7596
7597 zero3 = N32 c3 N31;
7598 count3 = (N32 - N31) /[cl] STEP3;
7599 zero2 = N22 c2 N21;
7600 count2 = (N22 - N21) /[cl] STEP2;
7601 zero1 = N12 c1 N11;
7602 count1 = (N12 - N11) /[cl] STEP1;
7603 zero = zero3 || zero2 || zero1;
7604 count = count1 * count2 * count3;
7605 if (__builtin_expect(zero, false)) goto zero_iter_bb;
7606
7607 After all, we expect the zero=false, and thus we expect to have to
7608 evaluate all of the comparison expressions, so short-circuiting
7609 oughtn't be a win. Since the condition isn't protecting a
7610 denominator, we're not concerned about divide-by-zero, so we can
7611 fully evaluate count even if a numerator turned out to be wrong.
7612
7613 It seems like putting this all together would create much better
7614 scheduling opportunities, and less pressure on the chip's branch
7615 predictor. */
7616
7617 static void
7618 expand_omp_for_init_counts (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
7619 basic_block &entry_bb, tree *counts,
7620 basic_block &zero_iter1_bb, int &first_zero_iter1,
7621 basic_block &zero_iter2_bb, int &first_zero_iter2,
7622 basic_block &l2_dom_bb)
7623 {
7624 tree t, type = TREE_TYPE (fd->loop.v);
7625 edge e, ne;
7626 int i;
7627
7628 /* Collapsed loops need work for expansion into SSA form. */
7629 gcc_assert (!gimple_in_ssa_p (cfun));
7630
7631 if (gimple_omp_for_combined_into_p (fd->for_stmt)
7632 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
7633 {
7634 gcc_assert (fd->ordered == 0);
7635 /* First two _looptemp_ clauses are for istart/iend, counts[0]
7636 isn't supposed to be handled, as the inner loop doesn't
7637 use it. */
7638 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7639 OMP_CLAUSE__LOOPTEMP_);
7640 gcc_assert (innerc);
7641 for (i = 0; i < fd->collapse; i++)
7642 {
7643 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7644 OMP_CLAUSE__LOOPTEMP_);
7645 gcc_assert (innerc);
7646 if (i)
7647 counts[i] = OMP_CLAUSE_DECL (innerc);
7648 else
7649 counts[0] = NULL_TREE;
7650 }
7651 return;
7652 }
7653
7654 for (i = fd->collapse; i < fd->ordered; i++)
7655 {
7656 tree itype = TREE_TYPE (fd->loops[i].v);
7657 counts[i] = NULL_TREE;
7658 t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
7659 fold_convert (itype, fd->loops[i].n1),
7660 fold_convert (itype, fd->loops[i].n2));
7661 if (t && integer_zerop (t))
7662 {
7663 for (i = fd->collapse; i < fd->ordered; i++)
7664 counts[i] = build_int_cst (type, 0);
7665 break;
7666 }
7667 }
7668 for (i = 0; i < (fd->ordered ? fd->ordered : fd->collapse); i++)
7669 {
7670 tree itype = TREE_TYPE (fd->loops[i].v);
7671
7672 if (i >= fd->collapse && counts[i])
7673 continue;
7674 if ((SSA_VAR_P (fd->loop.n2) || i >= fd->collapse)
7675 && ((t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
7676 fold_convert (itype, fd->loops[i].n1),
7677 fold_convert (itype, fd->loops[i].n2)))
7678 == NULL_TREE || !integer_onep (t)))
7679 {
7680 gcond *cond_stmt;
7681 tree n1, n2;
7682 n1 = fold_convert (itype, unshare_expr (fd->loops[i].n1));
7683 n1 = force_gimple_operand_gsi (gsi, n1, true, NULL_TREE,
7684 true, GSI_SAME_STMT);
7685 n2 = fold_convert (itype, unshare_expr (fd->loops[i].n2));
7686 n2 = force_gimple_operand_gsi (gsi, n2, true, NULL_TREE,
7687 true, GSI_SAME_STMT);
7688 cond_stmt = gimple_build_cond (fd->loops[i].cond_code, n1, n2,
7689 NULL_TREE, NULL_TREE);
7690 gsi_insert_before (gsi, cond_stmt, GSI_SAME_STMT);
7691 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
7692 expand_omp_regimplify_p, NULL, NULL)
7693 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
7694 expand_omp_regimplify_p, NULL, NULL))
7695 {
7696 *gsi = gsi_for_stmt (cond_stmt);
7697 gimple_regimplify_operands (cond_stmt, gsi);
7698 }
7699 e = split_block (entry_bb, cond_stmt);
7700 basic_block &zero_iter_bb
7701 = i < fd->collapse ? zero_iter1_bb : zero_iter2_bb;
7702 int &first_zero_iter
7703 = i < fd->collapse ? first_zero_iter1 : first_zero_iter2;
7704 if (zero_iter_bb == NULL)
7705 {
7706 gassign *assign_stmt;
7707 first_zero_iter = i;
7708 zero_iter_bb = create_empty_bb (entry_bb);
7709 add_bb_to_loop (zero_iter_bb, entry_bb->loop_father);
7710 *gsi = gsi_after_labels (zero_iter_bb);
7711 if (i < fd->collapse)
7712 assign_stmt = gimple_build_assign (fd->loop.n2,
7713 build_zero_cst (type));
7714 else
7715 {
7716 counts[i] = create_tmp_reg (type, ".count");
7717 assign_stmt
7718 = gimple_build_assign (counts[i], build_zero_cst (type));
7719 }
7720 gsi_insert_before (gsi, assign_stmt, GSI_SAME_STMT);
7721 set_immediate_dominator (CDI_DOMINATORS, zero_iter_bb,
7722 entry_bb);
7723 }
7724 ne = make_edge (entry_bb, zero_iter_bb, EDGE_FALSE_VALUE);
7725 ne->probability = REG_BR_PROB_BASE / 2000 - 1;
7726 e->flags = EDGE_TRUE_VALUE;
7727 e->probability = REG_BR_PROB_BASE - ne->probability;
7728 if (l2_dom_bb == NULL)
7729 l2_dom_bb = entry_bb;
7730 entry_bb = e->dest;
7731 *gsi = gsi_last_bb (entry_bb);
7732 }
7733
7734 if (POINTER_TYPE_P (itype))
7735 itype = signed_type_for (itype);
7736 t = build_int_cst (itype, (fd->loops[i].cond_code == LT_EXPR
7737 ? -1 : 1));
7738 t = fold_build2 (PLUS_EXPR, itype,
7739 fold_convert (itype, fd->loops[i].step), t);
7740 t = fold_build2 (PLUS_EXPR, itype, t,
7741 fold_convert (itype, fd->loops[i].n2));
7742 t = fold_build2 (MINUS_EXPR, itype, t,
7743 fold_convert (itype, fd->loops[i].n1));
7744 /* ?? We could probably use CEIL_DIV_EXPR instead of
7745 TRUNC_DIV_EXPR and adjusting by hand. Unless we can't
7746 generate the same code in the end because generically we
7747 don't know that the values involved must be negative for
7748 GT?? */
7749 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
7750 t = fold_build2 (TRUNC_DIV_EXPR, itype,
7751 fold_build1 (NEGATE_EXPR, itype, t),
7752 fold_build1 (NEGATE_EXPR, itype,
7753 fold_convert (itype,
7754 fd->loops[i].step)));
7755 else
7756 t = fold_build2 (TRUNC_DIV_EXPR, itype, t,
7757 fold_convert (itype, fd->loops[i].step));
7758 t = fold_convert (type, t);
7759 if (TREE_CODE (t) == INTEGER_CST)
7760 counts[i] = t;
7761 else
7762 {
7763 if (i < fd->collapse || i != first_zero_iter2)
7764 counts[i] = create_tmp_reg (type, ".count");
7765 expand_omp_build_assign (gsi, counts[i], t);
7766 }
7767 if (SSA_VAR_P (fd->loop.n2) && i < fd->collapse)
7768 {
7769 if (i == 0)
7770 t = counts[0];
7771 else
7772 t = fold_build2 (MULT_EXPR, type, fd->loop.n2, counts[i]);
7773 expand_omp_build_assign (gsi, fd->loop.n2, t);
7774 }
7775 }
7776 }
7777
7778
7779 /* Helper function for expand_omp_{for_*,simd}. Generate code like:
7780 T = V;
7781 V3 = N31 + (T % count3) * STEP3;
7782 T = T / count3;
7783 V2 = N21 + (T % count2) * STEP2;
7784 T = T / count2;
7785 V1 = N11 + T * STEP1;
7786 if this loop doesn't have an inner loop construct combined with it.
7787 If it does have an inner loop construct combined with it and the
7788 iteration count isn't known constant, store values from counts array
7789 into its _looptemp_ temporaries instead. */
7790
7791 static void
7792 expand_omp_for_init_vars (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
7793 tree *counts, gimple *inner_stmt, tree startvar)
7794 {
7795 int i;
7796 if (gimple_omp_for_combined_p (fd->for_stmt))
7797 {
7798 /* If fd->loop.n2 is constant, then no propagation of the counts
7799 is needed, they are constant. */
7800 if (TREE_CODE (fd->loop.n2) == INTEGER_CST)
7801 return;
7802
7803 tree clauses = gimple_code (inner_stmt) != GIMPLE_OMP_FOR
7804 ? gimple_omp_taskreg_clauses (inner_stmt)
7805 : gimple_omp_for_clauses (inner_stmt);
7806 /* First two _looptemp_ clauses are for istart/iend, counts[0]
7807 isn't supposed to be handled, as the inner loop doesn't
7808 use it. */
7809 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
7810 gcc_assert (innerc);
7811 for (i = 0; i < fd->collapse; i++)
7812 {
7813 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7814 OMP_CLAUSE__LOOPTEMP_);
7815 gcc_assert (innerc);
7816 if (i)
7817 {
7818 tree tem = OMP_CLAUSE_DECL (innerc);
7819 tree t = fold_convert (TREE_TYPE (tem), counts[i]);
7820 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
7821 false, GSI_CONTINUE_LINKING);
7822 gassign *stmt = gimple_build_assign (tem, t);
7823 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7824 }
7825 }
7826 return;
7827 }
7828
7829 tree type = TREE_TYPE (fd->loop.v);
7830 tree tem = create_tmp_reg (type, ".tem");
7831 gassign *stmt = gimple_build_assign (tem, startvar);
7832 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7833
7834 for (i = fd->collapse - 1; i >= 0; i--)
7835 {
7836 tree vtype = TREE_TYPE (fd->loops[i].v), itype, t;
7837 itype = vtype;
7838 if (POINTER_TYPE_P (vtype))
7839 itype = signed_type_for (vtype);
7840 if (i != 0)
7841 t = fold_build2 (TRUNC_MOD_EXPR, type, tem, counts[i]);
7842 else
7843 t = tem;
7844 t = fold_convert (itype, t);
7845 t = fold_build2 (MULT_EXPR, itype, t,
7846 fold_convert (itype, fd->loops[i].step));
7847 if (POINTER_TYPE_P (vtype))
7848 t = fold_build_pointer_plus (fd->loops[i].n1, t);
7849 else
7850 t = fold_build2 (PLUS_EXPR, itype, fd->loops[i].n1, t);
7851 t = force_gimple_operand_gsi (gsi, t,
7852 DECL_P (fd->loops[i].v)
7853 && TREE_ADDRESSABLE (fd->loops[i].v),
7854 NULL_TREE, false,
7855 GSI_CONTINUE_LINKING);
7856 stmt = gimple_build_assign (fd->loops[i].v, t);
7857 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7858 if (i != 0)
7859 {
7860 t = fold_build2 (TRUNC_DIV_EXPR, type, tem, counts[i]);
7861 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
7862 false, GSI_CONTINUE_LINKING);
7863 stmt = gimple_build_assign (tem, t);
7864 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7865 }
7866 }
7867 }
7868
7869
7870 /* Helper function for expand_omp_for_*. Generate code like:
7871 L10:
7872 V3 += STEP3;
7873 if (V3 cond3 N32) goto BODY_BB; else goto L11;
7874 L11:
7875 V3 = N31;
7876 V2 += STEP2;
7877 if (V2 cond2 N22) goto BODY_BB; else goto L12;
7878 L12:
7879 V2 = N21;
7880 V1 += STEP1;
7881 goto BODY_BB; */
7882
7883 static basic_block
7884 extract_omp_for_update_vars (struct omp_for_data *fd, basic_block cont_bb,
7885 basic_block body_bb)
7886 {
7887 basic_block last_bb, bb, collapse_bb = NULL;
7888 int i;
7889 gimple_stmt_iterator gsi;
7890 edge e;
7891 tree t;
7892 gimple *stmt;
7893
7894 last_bb = cont_bb;
7895 for (i = fd->collapse - 1; i >= 0; i--)
7896 {
7897 tree vtype = TREE_TYPE (fd->loops[i].v);
7898
7899 bb = create_empty_bb (last_bb);
7900 add_bb_to_loop (bb, last_bb->loop_father);
7901 gsi = gsi_start_bb (bb);
7902
7903 if (i < fd->collapse - 1)
7904 {
7905 e = make_edge (last_bb, bb, EDGE_FALSE_VALUE);
7906 e->probability = REG_BR_PROB_BASE / 8;
7907
7908 t = fd->loops[i + 1].n1;
7909 t = force_gimple_operand_gsi (&gsi, t,
7910 DECL_P (fd->loops[i + 1].v)
7911 && TREE_ADDRESSABLE (fd->loops[i
7912 + 1].v),
7913 NULL_TREE, false,
7914 GSI_CONTINUE_LINKING);
7915 stmt = gimple_build_assign (fd->loops[i + 1].v, t);
7916 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7917 }
7918 else
7919 collapse_bb = bb;
7920
7921 set_immediate_dominator (CDI_DOMINATORS, bb, last_bb);
7922
7923 if (POINTER_TYPE_P (vtype))
7924 t = fold_build_pointer_plus (fd->loops[i].v, fd->loops[i].step);
7925 else
7926 t = fold_build2 (PLUS_EXPR, vtype, fd->loops[i].v, fd->loops[i].step);
7927 t = force_gimple_operand_gsi (&gsi, t,
7928 DECL_P (fd->loops[i].v)
7929 && TREE_ADDRESSABLE (fd->loops[i].v),
7930 NULL_TREE, false, GSI_CONTINUE_LINKING);
7931 stmt = gimple_build_assign (fd->loops[i].v, t);
7932 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7933
7934 if (i > 0)
7935 {
7936 t = fd->loops[i].n2;
7937 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7938 false, GSI_CONTINUE_LINKING);
7939 tree v = fd->loops[i].v;
7940 if (DECL_P (v) && TREE_ADDRESSABLE (v))
7941 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
7942 false, GSI_CONTINUE_LINKING);
7943 t = fold_build2 (fd->loops[i].cond_code, boolean_type_node, v, t);
7944 stmt = gimple_build_cond_empty (t);
7945 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7946 e = make_edge (bb, body_bb, EDGE_TRUE_VALUE);
7947 e->probability = REG_BR_PROB_BASE * 7 / 8;
7948 }
7949 else
7950 make_edge (bb, body_bb, EDGE_FALLTHRU);
7951 last_bb = bb;
7952 }
7953
7954 return collapse_bb;
7955 }
7956
7957
7958 /* Expand #pragma omp ordered depend(source). */
7959
7960 static void
7961 expand_omp_ordered_source (gimple_stmt_iterator *gsi, struct omp_for_data *fd,
7962 tree *counts, location_t loc)
7963 {
7964 enum built_in_function source_ix
7965 = fd->iter_type == long_integer_type_node
7966 ? BUILT_IN_GOMP_DOACROSS_POST : BUILT_IN_GOMP_DOACROSS_ULL_POST;
7967 gimple *g
7968 = gimple_build_call (builtin_decl_explicit (source_ix), 1,
7969 build_fold_addr_expr (counts[fd->ordered]));
7970 gimple_set_location (g, loc);
7971 gsi_insert_before (gsi, g, GSI_SAME_STMT);
7972 }
7973
7974 /* Expand a single depend from #pragma omp ordered depend(sink:...). */
7975
7976 static void
7977 expand_omp_ordered_sink (gimple_stmt_iterator *gsi, struct omp_for_data *fd,
7978 tree *counts, tree c, location_t loc)
7979 {
7980 auto_vec<tree, 10> args;
7981 enum built_in_function sink_ix
7982 = fd->iter_type == long_integer_type_node
7983 ? BUILT_IN_GOMP_DOACROSS_WAIT : BUILT_IN_GOMP_DOACROSS_ULL_WAIT;
7984 tree t, off, coff = NULL_TREE, deps = OMP_CLAUSE_DECL (c), cond = NULL_TREE;
7985 int i;
7986 gimple_stmt_iterator gsi2 = *gsi;
7987 bool warned_step = false;
7988
7989 for (i = 0; i < fd->ordered; i++)
7990 {
7991 off = TREE_PURPOSE (deps);
7992 if (!integer_zerop (off))
7993 {
7994 gcc_assert (fd->loops[i].cond_code == LT_EXPR
7995 || fd->loops[i].cond_code == GT_EXPR);
7996 bool forward = fd->loops[i].cond_code == LT_EXPR;
7997 if (forward ^ OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
7998 warning_at (loc, 0, "%<depend(sink)%> clause waiting for "
7999 "lexically later iteration");
8000 break;
8001 }
8002 deps = TREE_CHAIN (deps);
8003 }
8004 /* If all offsets corresponding to the collapsed loops are zero,
8005 this depend clause can be ignored. FIXME: but there is still a
8006 flush needed. We need to emit one __sync_synchronize () for it
8007 though (perhaps conditionally)? Solve this together with the
8008 conservative dependence folding optimization.
8009 if (i >= fd->collapse)
8010 return; */
8011
8012 deps = OMP_CLAUSE_DECL (c);
8013 gsi_prev (&gsi2);
8014 edge e1 = split_block (gsi_bb (gsi2), gsi_stmt (gsi2));
8015 edge e2 = split_block_after_labels (e1->dest);
8016
8017 *gsi = gsi_after_labels (e1->dest);
8018 for (i = 0; i < fd->ordered; i++)
8019 {
8020 tree itype = TREE_TYPE (fd->loops[i].v);
8021 if (POINTER_TYPE_P (itype))
8022 itype = sizetype;
8023 if (i)
8024 deps = TREE_CHAIN (deps);
8025 off = TREE_PURPOSE (deps);
8026 tree s = fold_convert_loc (loc, itype, fd->loops[i].step);
8027
8028 if (integer_zerop (off))
8029 t = boolean_true_node;
8030 else
8031 {
8032 tree a;
8033 tree co = fold_convert_loc (loc, itype, off);
8034 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
8035 {
8036 if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
8037 co = fold_build1_loc (loc, NEGATE_EXPR, itype, co);
8038 a = fold_build2_loc (loc, POINTER_PLUS_EXPR,
8039 TREE_TYPE (fd->loops[i].v), fd->loops[i].v,
8040 co);
8041 }
8042 else if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
8043 a = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (fd->loops[i].v),
8044 fd->loops[i].v, co);
8045 else
8046 a = fold_build2_loc (loc, PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
8047 fd->loops[i].v, co);
8048 if (fd->loops[i].cond_code == LT_EXPR)
8049 {
8050 if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
8051 t = fold_build2_loc (loc, GE_EXPR, boolean_type_node, a,
8052 fd->loops[i].n1);
8053 else
8054 t = fold_build2_loc (loc, LT_EXPR, boolean_type_node, a,
8055 fd->loops[i].n2);
8056 }
8057 else if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
8058 t = fold_build2_loc (loc, GT_EXPR, boolean_type_node, a,
8059 fd->loops[i].n2);
8060 else
8061 t = fold_build2_loc (loc, LE_EXPR, boolean_type_node, a,
8062 fd->loops[i].n1);
8063 }
8064 if (cond)
8065 cond = fold_build2_loc (loc, BIT_AND_EXPR, boolean_type_node, cond, t);
8066 else
8067 cond = t;
8068
8069 off = fold_convert_loc (loc, itype, off);
8070
8071 if (fd->loops[i].cond_code == LT_EXPR
8072 ? !integer_onep (fd->loops[i].step)
8073 : !integer_minus_onep (fd->loops[i].step))
8074 {
8075 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
8076 t = fold_build2_loc (loc, TRUNC_MOD_EXPR, itype, off,
8077 fold_build1_loc (loc, NEGATE_EXPR, itype,
8078 s));
8079 else
8080 t = fold_build2_loc (loc, TRUNC_MOD_EXPR, itype, off, s);
8081 t = fold_build2_loc (loc, EQ_EXPR, boolean_type_node, t,
8082 build_int_cst (itype, 0));
8083 if (integer_zerop (t) && !warned_step)
8084 {
8085 warning_at (loc, 0, "%<depend(sink)%> refers to iteration never "
8086 "in the iteration space");
8087 warned_step = true;
8088 }
8089 cond = fold_build2_loc (loc, BIT_AND_EXPR, boolean_type_node,
8090 cond, t);
8091 }
8092
8093 if (i <= fd->collapse - 1 && fd->collapse > 1)
8094 t = fd->loop.v;
8095 else if (counts[i])
8096 t = counts[i];
8097 else
8098 {
8099 t = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (fd->loops[i].v),
8100 fd->loops[i].v, fd->loops[i].n1);
8101 t = fold_convert_loc (loc, fd->iter_type, t);
8102 }
8103 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
8104 off = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, off,
8105 fold_build1_loc (loc, NEGATE_EXPR, itype,
8106 s));
8107 else
8108 off = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, off, s);
8109 if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
8110 off = fold_build1_loc (loc, NEGATE_EXPR, itype, off);
8111 off = fold_convert_loc (loc, fd->iter_type, off);
8112 if (i <= fd->collapse - 1 && fd->collapse > 1)
8113 {
8114 if (i)
8115 off = fold_build2_loc (loc, PLUS_EXPR, fd->iter_type, coff,
8116 off);
8117 if (i < fd->collapse - 1)
8118 {
8119 coff = fold_build2_loc (loc, MULT_EXPR, fd->iter_type, off,
8120 counts[i]);
8121 continue;
8122 }
8123 }
8124 off = unshare_expr (off);
8125 t = fold_build2_loc (loc, PLUS_EXPR, fd->iter_type, t, off);
8126 t = force_gimple_operand_gsi (gsi, t, true, NULL_TREE,
8127 true, GSI_SAME_STMT);
8128 args.safe_push (t);
8129 }
8130 gimple *g = gimple_build_call_vec (builtin_decl_explicit (sink_ix), args);
8131 gimple_set_location (g, loc);
8132 gsi_insert_before (gsi, g, GSI_SAME_STMT);
8133
8134 *gsi = gsi_last_bb (e1->src);
8135 cond = unshare_expr (cond);
8136 cond = force_gimple_operand_gsi (gsi, cond, true, NULL_TREE, false,
8137 GSI_CONTINUE_LINKING);
8138 gsi_insert_after (gsi, gimple_build_cond_empty (cond), GSI_NEW_STMT);
8139 edge e3 = make_edge (e1->src, e2->dest, EDGE_FALSE_VALUE);
8140 e3->probability = REG_BR_PROB_BASE / 8;
8141 e1->probability = REG_BR_PROB_BASE - e3->probability;
8142 e1->flags = EDGE_TRUE_VALUE;
8143 set_immediate_dominator (CDI_DOMINATORS, e2->dest, e1->src);
8144
8145 *gsi = gsi_after_labels (e2->dest);
8146 }
8147
8148 /* Expand all #pragma omp ordered depend(source) and
8149 #pragma omp ordered depend(sink:...) constructs in the current
8150 #pragma omp for ordered(n) region. */
8151
8152 static void
8153 expand_omp_ordered_source_sink (struct omp_region *region,
8154 struct omp_for_data *fd, tree *counts,
8155 basic_block cont_bb)
8156 {
8157 struct omp_region *inner;
8158 int i;
8159 for (i = fd->collapse - 1; i < fd->ordered; i++)
8160 if (i == fd->collapse - 1 && fd->collapse > 1)
8161 counts[i] = NULL_TREE;
8162 else if (i >= fd->collapse && !cont_bb)
8163 counts[i] = build_zero_cst (fd->iter_type);
8164 else if (!POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v))
8165 && integer_onep (fd->loops[i].step))
8166 counts[i] = NULL_TREE;
8167 else
8168 counts[i] = create_tmp_var (fd->iter_type, ".orditer");
8169 tree atype
8170 = build_array_type_nelts (fd->iter_type, fd->ordered - fd->collapse + 1);
8171 counts[fd->ordered] = create_tmp_var (atype, ".orditera");
8172 TREE_ADDRESSABLE (counts[fd->ordered]) = 1;
8173
8174 for (inner = region->inner; inner; inner = inner->next)
8175 if (inner->type == GIMPLE_OMP_ORDERED)
8176 {
8177 gomp_ordered *ord_stmt = inner->ord_stmt;
8178 gimple_stmt_iterator gsi = gsi_for_stmt (ord_stmt);
8179 location_t loc = gimple_location (ord_stmt);
8180 tree c;
8181 for (c = gimple_omp_ordered_clauses (ord_stmt);
8182 c; c = OMP_CLAUSE_CHAIN (c))
8183 if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE)
8184 break;
8185 if (c)
8186 expand_omp_ordered_source (&gsi, fd, counts, loc);
8187 for (c = gimple_omp_ordered_clauses (ord_stmt);
8188 c; c = OMP_CLAUSE_CHAIN (c))
8189 if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK)
8190 expand_omp_ordered_sink (&gsi, fd, counts, c, loc);
8191 gsi_remove (&gsi, true);
8192 }
8193 }
8194
8195 /* Wrap the body into fd->ordered - fd->collapse loops that aren't
8196 collapsed. */
8197
8198 static basic_block
8199 expand_omp_for_ordered_loops (struct omp_for_data *fd, tree *counts,
8200 basic_block cont_bb, basic_block body_bb,
8201 bool ordered_lastprivate)
8202 {
8203 if (fd->ordered == fd->collapse)
8204 return cont_bb;
8205
8206 if (!cont_bb)
8207 {
8208 gimple_stmt_iterator gsi = gsi_after_labels (body_bb);
8209 for (int i = fd->collapse; i < fd->ordered; i++)
8210 {
8211 tree type = TREE_TYPE (fd->loops[i].v);
8212 tree n1 = fold_convert (type, fd->loops[i].n1);
8213 expand_omp_build_assign (&gsi, fd->loops[i].v, n1);
8214 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8215 size_int (i - fd->collapse + 1),
8216 NULL_TREE, NULL_TREE);
8217 expand_omp_build_assign (&gsi, aref, build_zero_cst (fd->iter_type));
8218 }
8219 return NULL;
8220 }
8221
8222 for (int i = fd->ordered - 1; i >= fd->collapse; i--)
8223 {
8224 tree t, type = TREE_TYPE (fd->loops[i].v);
8225 gimple_stmt_iterator gsi = gsi_after_labels (body_bb);
8226 expand_omp_build_assign (&gsi, fd->loops[i].v,
8227 fold_convert (type, fd->loops[i].n1));
8228 if (counts[i])
8229 expand_omp_build_assign (&gsi, counts[i],
8230 build_zero_cst (fd->iter_type));
8231 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8232 size_int (i - fd->collapse + 1),
8233 NULL_TREE, NULL_TREE);
8234 expand_omp_build_assign (&gsi, aref, build_zero_cst (fd->iter_type));
8235 if (!gsi_end_p (gsi))
8236 gsi_prev (&gsi);
8237 else
8238 gsi = gsi_last_bb (body_bb);
8239 edge e1 = split_block (body_bb, gsi_stmt (gsi));
8240 basic_block new_body = e1->dest;
8241 if (body_bb == cont_bb)
8242 cont_bb = new_body;
8243 edge e2 = NULL;
8244 basic_block new_header;
8245 if (EDGE_COUNT (cont_bb->preds) > 0)
8246 {
8247 gsi = gsi_last_bb (cont_bb);
8248 if (POINTER_TYPE_P (type))
8249 t = fold_build_pointer_plus (fd->loops[i].v,
8250 fold_convert (sizetype,
8251 fd->loops[i].step));
8252 else
8253 t = fold_build2 (PLUS_EXPR, type, fd->loops[i].v,
8254 fold_convert (type, fd->loops[i].step));
8255 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
8256 if (counts[i])
8257 {
8258 t = fold_build2 (PLUS_EXPR, fd->iter_type, counts[i],
8259 build_int_cst (fd->iter_type, 1));
8260 expand_omp_build_assign (&gsi, counts[i], t);
8261 t = counts[i];
8262 }
8263 else
8264 {
8265 t = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->loops[i].v),
8266 fd->loops[i].v, fd->loops[i].n1);
8267 t = fold_convert (fd->iter_type, t);
8268 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8269 true, GSI_SAME_STMT);
8270 }
8271 aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8272 size_int (i - fd->collapse + 1),
8273 NULL_TREE, NULL_TREE);
8274 expand_omp_build_assign (&gsi, aref, t);
8275 gsi_prev (&gsi);
8276 e2 = split_block (cont_bb, gsi_stmt (gsi));
8277 new_header = e2->dest;
8278 }
8279 else
8280 new_header = cont_bb;
8281 gsi = gsi_after_labels (new_header);
8282 tree v = force_gimple_operand_gsi (&gsi, fd->loops[i].v, true, NULL_TREE,
8283 true, GSI_SAME_STMT);
8284 tree n2
8285 = force_gimple_operand_gsi (&gsi, fold_convert (type, fd->loops[i].n2),
8286 true, NULL_TREE, true, GSI_SAME_STMT);
8287 t = build2 (fd->loops[i].cond_code, boolean_type_node, v, n2);
8288 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_NEW_STMT);
8289 edge e3 = split_block (new_header, gsi_stmt (gsi));
8290 cont_bb = e3->dest;
8291 remove_edge (e1);
8292 make_edge (body_bb, new_header, EDGE_FALLTHRU);
8293 e3->flags = EDGE_FALSE_VALUE;
8294 e3->probability = REG_BR_PROB_BASE / 8;
8295 e1 = make_edge (new_header, new_body, EDGE_TRUE_VALUE);
8296 e1->probability = REG_BR_PROB_BASE - e3->probability;
8297
8298 set_immediate_dominator (CDI_DOMINATORS, new_header, body_bb);
8299 set_immediate_dominator (CDI_DOMINATORS, new_body, new_header);
8300
8301 if (e2)
8302 {
8303 struct loop *loop = alloc_loop ();
8304 loop->header = new_header;
8305 loop->latch = e2->src;
8306 add_loop (loop, body_bb->loop_father);
8307 }
8308 }
8309
8310 /* If there are any lastprivate clauses and it is possible some loops
8311 might have zero iterations, ensure all the decls are initialized,
8312 otherwise we could crash evaluating C++ class iterators with lastprivate
8313 clauses. */
8314 bool need_inits = false;
8315 for (int i = fd->collapse; ordered_lastprivate && i < fd->ordered; i++)
8316 if (need_inits)
8317 {
8318 tree type = TREE_TYPE (fd->loops[i].v);
8319 gimple_stmt_iterator gsi = gsi_after_labels (body_bb);
8320 expand_omp_build_assign (&gsi, fd->loops[i].v,
8321 fold_convert (type, fd->loops[i].n1));
8322 }
8323 else
8324 {
8325 tree type = TREE_TYPE (fd->loops[i].v);
8326 tree this_cond = fold_build2 (fd->loops[i].cond_code,
8327 boolean_type_node,
8328 fold_convert (type, fd->loops[i].n1),
8329 fold_convert (type, fd->loops[i].n2));
8330 if (!integer_onep (this_cond))
8331 need_inits = true;
8332 }
8333
8334 return cont_bb;
8335 }
8336
8337
8338 /* A subroutine of expand_omp_for. Generate code for a parallel
8339 loop with any schedule. Given parameters:
8340
8341 for (V = N1; V cond N2; V += STEP) BODY;
8342
8343 where COND is "<" or ">", we generate pseudocode
8344
8345 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
8346 if (more) goto L0; else goto L3;
8347 L0:
8348 V = istart0;
8349 iend = iend0;
8350 L1:
8351 BODY;
8352 V += STEP;
8353 if (V cond iend) goto L1; else goto L2;
8354 L2:
8355 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
8356 L3:
8357
8358 If this is a combined omp parallel loop, instead of the call to
8359 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
8360 If this is gimple_omp_for_combined_p loop, then instead of assigning
8361 V and iend in L0 we assign the first two _looptemp_ clause decls of the
8362 inner GIMPLE_OMP_FOR and V += STEP; and
8363 if (V cond iend) goto L1; else goto L2; are removed.
8364
8365 For collapsed loops, given parameters:
8366 collapse(3)
8367 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
8368 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
8369 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
8370 BODY;
8371
8372 we generate pseudocode
8373
8374 if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
8375 if (cond3 is <)
8376 adj = STEP3 - 1;
8377 else
8378 adj = STEP3 + 1;
8379 count3 = (adj + N32 - N31) / STEP3;
8380 if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
8381 if (cond2 is <)
8382 adj = STEP2 - 1;
8383 else
8384 adj = STEP2 + 1;
8385 count2 = (adj + N22 - N21) / STEP2;
8386 if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
8387 if (cond1 is <)
8388 adj = STEP1 - 1;
8389 else
8390 adj = STEP1 + 1;
8391 count1 = (adj + N12 - N11) / STEP1;
8392 count = count1 * count2 * count3;
8393 goto Z1;
8394 Z0:
8395 count = 0;
8396 Z1:
8397 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
8398 if (more) goto L0; else goto L3;
8399 L0:
8400 V = istart0;
8401 T = V;
8402 V3 = N31 + (T % count3) * STEP3;
8403 T = T / count3;
8404 V2 = N21 + (T % count2) * STEP2;
8405 T = T / count2;
8406 V1 = N11 + T * STEP1;
8407 iend = iend0;
8408 L1:
8409 BODY;
8410 V += 1;
8411 if (V < iend) goto L10; else goto L2;
8412 L10:
8413 V3 += STEP3;
8414 if (V3 cond3 N32) goto L1; else goto L11;
8415 L11:
8416 V3 = N31;
8417 V2 += STEP2;
8418 if (V2 cond2 N22) goto L1; else goto L12;
8419 L12:
8420 V2 = N21;
8421 V1 += STEP1;
8422 goto L1;
8423 L2:
8424 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
8425 L3:
8426
8427 */
8428
8429 static void
8430 expand_omp_for_generic (struct omp_region *region,
8431 struct omp_for_data *fd,
8432 enum built_in_function start_fn,
8433 enum built_in_function next_fn,
8434 gimple *inner_stmt)
8435 {
8436 tree type, istart0, iend0, iend;
8437 tree t, vmain, vback, bias = NULL_TREE;
8438 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, collapse_bb;
8439 basic_block l2_bb = NULL, l3_bb = NULL;
8440 gimple_stmt_iterator gsi;
8441 gassign *assign_stmt;
8442 bool in_combined_parallel = is_combined_parallel (region);
8443 bool broken_loop = region->cont == NULL;
8444 edge e, ne;
8445 tree *counts = NULL;
8446 int i;
8447 bool ordered_lastprivate = false;
8448
8449 gcc_assert (!broken_loop || !in_combined_parallel);
8450 gcc_assert (fd->iter_type == long_integer_type_node
8451 || !in_combined_parallel);
8452
8453 entry_bb = region->entry;
8454 cont_bb = region->cont;
8455 collapse_bb = NULL;
8456 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
8457 gcc_assert (broken_loop
8458 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
8459 l0_bb = split_edge (FALLTHRU_EDGE (entry_bb));
8460 l1_bb = single_succ (l0_bb);
8461 if (!broken_loop)
8462 {
8463 l2_bb = create_empty_bb (cont_bb);
8464 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb
8465 || (single_succ_edge (BRANCH_EDGE (cont_bb)->dest)->dest
8466 == l1_bb));
8467 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
8468 }
8469 else
8470 l2_bb = NULL;
8471 l3_bb = BRANCH_EDGE (entry_bb)->dest;
8472 exit_bb = region->exit;
8473
8474 gsi = gsi_last_bb (entry_bb);
8475
8476 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
8477 if (fd->ordered
8478 && find_omp_clause (gimple_omp_for_clauses (gsi_stmt (gsi)),
8479 OMP_CLAUSE_LASTPRIVATE))
8480 ordered_lastprivate = false;
8481 if (fd->collapse > 1 || fd->ordered)
8482 {
8483 int first_zero_iter1 = -1, first_zero_iter2 = -1;
8484 basic_block zero_iter1_bb = NULL, zero_iter2_bb = NULL, l2_dom_bb = NULL;
8485
8486 counts = XALLOCAVEC (tree, fd->ordered ? fd->ordered + 1 : fd->collapse);
8487 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
8488 zero_iter1_bb, first_zero_iter1,
8489 zero_iter2_bb, first_zero_iter2, l2_dom_bb);
8490
8491 if (zero_iter1_bb)
8492 {
8493 /* Some counts[i] vars might be uninitialized if
8494 some loop has zero iterations. But the body shouldn't
8495 be executed in that case, so just avoid uninit warnings. */
8496 for (i = first_zero_iter1;
8497 i < (fd->ordered ? fd->ordered : fd->collapse); i++)
8498 if (SSA_VAR_P (counts[i]))
8499 TREE_NO_WARNING (counts[i]) = 1;
8500 gsi_prev (&gsi);
8501 e = split_block (entry_bb, gsi_stmt (gsi));
8502 entry_bb = e->dest;
8503 make_edge (zero_iter1_bb, entry_bb, EDGE_FALLTHRU);
8504 gsi = gsi_last_bb (entry_bb);
8505 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
8506 get_immediate_dominator (CDI_DOMINATORS,
8507 zero_iter1_bb));
8508 }
8509 if (zero_iter2_bb)
8510 {
8511 /* Some counts[i] vars might be uninitialized if
8512 some loop has zero iterations. But the body shouldn't
8513 be executed in that case, so just avoid uninit warnings. */
8514 for (i = first_zero_iter2; i < fd->ordered; i++)
8515 if (SSA_VAR_P (counts[i]))
8516 TREE_NO_WARNING (counts[i]) = 1;
8517 if (zero_iter1_bb)
8518 make_edge (zero_iter2_bb, entry_bb, EDGE_FALLTHRU);
8519 else
8520 {
8521 gsi_prev (&gsi);
8522 e = split_block (entry_bb, gsi_stmt (gsi));
8523 entry_bb = e->dest;
8524 make_edge (zero_iter2_bb, entry_bb, EDGE_FALLTHRU);
8525 gsi = gsi_last_bb (entry_bb);
8526 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
8527 get_immediate_dominator
8528 (CDI_DOMINATORS, zero_iter2_bb));
8529 }
8530 }
8531 if (fd->collapse == 1)
8532 {
8533 counts[0] = fd->loop.n2;
8534 fd->loop = fd->loops[0];
8535 }
8536 }
8537
8538 type = TREE_TYPE (fd->loop.v);
8539 istart0 = create_tmp_var (fd->iter_type, ".istart0");
8540 iend0 = create_tmp_var (fd->iter_type, ".iend0");
8541 TREE_ADDRESSABLE (istart0) = 1;
8542 TREE_ADDRESSABLE (iend0) = 1;
8543
8544 /* See if we need to bias by LLONG_MIN. */
8545 if (fd->iter_type == long_long_unsigned_type_node
8546 && TREE_CODE (type) == INTEGER_TYPE
8547 && !TYPE_UNSIGNED (type)
8548 && fd->ordered == 0)
8549 {
8550 tree n1, n2;
8551
8552 if (fd->loop.cond_code == LT_EXPR)
8553 {
8554 n1 = fd->loop.n1;
8555 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
8556 }
8557 else
8558 {
8559 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
8560 n2 = fd->loop.n1;
8561 }
8562 if (TREE_CODE (n1) != INTEGER_CST
8563 || TREE_CODE (n2) != INTEGER_CST
8564 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
8565 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
8566 }
8567
8568 gimple_stmt_iterator gsif = gsi;
8569 gsi_prev (&gsif);
8570
8571 tree arr = NULL_TREE;
8572 if (in_combined_parallel)
8573 {
8574 gcc_assert (fd->ordered == 0);
8575 /* In a combined parallel loop, emit a call to
8576 GOMP_loop_foo_next. */
8577 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
8578 build_fold_addr_expr (istart0),
8579 build_fold_addr_expr (iend0));
8580 }
8581 else
8582 {
8583 tree t0, t1, t2, t3, t4;
8584 /* If this is not a combined parallel loop, emit a call to
8585 GOMP_loop_foo_start in ENTRY_BB. */
8586 t4 = build_fold_addr_expr (iend0);
8587 t3 = build_fold_addr_expr (istart0);
8588 if (fd->ordered)
8589 {
8590 t0 = build_int_cst (unsigned_type_node,
8591 fd->ordered - fd->collapse + 1);
8592 arr = create_tmp_var (build_array_type_nelts (fd->iter_type,
8593 fd->ordered
8594 - fd->collapse + 1),
8595 ".omp_counts");
8596 DECL_NAMELESS (arr) = 1;
8597 TREE_ADDRESSABLE (arr) = 1;
8598 TREE_STATIC (arr) = 1;
8599 vec<constructor_elt, va_gc> *v;
8600 vec_alloc (v, fd->ordered - fd->collapse + 1);
8601 int idx;
8602
8603 for (idx = 0; idx < fd->ordered - fd->collapse + 1; idx++)
8604 {
8605 tree c;
8606 if (idx == 0 && fd->collapse > 1)
8607 c = fd->loop.n2;
8608 else
8609 c = counts[idx + fd->collapse - 1];
8610 tree purpose = size_int (idx);
8611 CONSTRUCTOR_APPEND_ELT (v, purpose, c);
8612 if (TREE_CODE (c) != INTEGER_CST)
8613 TREE_STATIC (arr) = 0;
8614 }
8615
8616 DECL_INITIAL (arr) = build_constructor (TREE_TYPE (arr), v);
8617 if (!TREE_STATIC (arr))
8618 force_gimple_operand_gsi (&gsi, build1 (DECL_EXPR,
8619 void_type_node, arr),
8620 true, NULL_TREE, true, GSI_SAME_STMT);
8621 t1 = build_fold_addr_expr (arr);
8622 t2 = NULL_TREE;
8623 }
8624 else
8625 {
8626 t2 = fold_convert (fd->iter_type, fd->loop.step);
8627 t1 = fd->loop.n2;
8628 t0 = fd->loop.n1;
8629 if (gimple_omp_for_combined_into_p (fd->for_stmt))
8630 {
8631 tree innerc
8632 = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
8633 OMP_CLAUSE__LOOPTEMP_);
8634 gcc_assert (innerc);
8635 t0 = OMP_CLAUSE_DECL (innerc);
8636 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
8637 OMP_CLAUSE__LOOPTEMP_);
8638 gcc_assert (innerc);
8639 t1 = OMP_CLAUSE_DECL (innerc);
8640 }
8641 if (POINTER_TYPE_P (TREE_TYPE (t0))
8642 && TYPE_PRECISION (TREE_TYPE (t0))
8643 != TYPE_PRECISION (fd->iter_type))
8644 {
8645 /* Avoid casting pointers to integer of a different size. */
8646 tree itype = signed_type_for (type);
8647 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
8648 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
8649 }
8650 else
8651 {
8652 t1 = fold_convert (fd->iter_type, t1);
8653 t0 = fold_convert (fd->iter_type, t0);
8654 }
8655 if (bias)
8656 {
8657 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
8658 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
8659 }
8660 }
8661 if (fd->iter_type == long_integer_type_node || fd->ordered)
8662 {
8663 if (fd->chunk_size)
8664 {
8665 t = fold_convert (fd->iter_type, fd->chunk_size);
8666 t = omp_adjust_chunk_size (t, fd->simd_schedule);
8667 if (fd->ordered)
8668 t = build_call_expr (builtin_decl_explicit (start_fn),
8669 5, t0, t1, t, t3, t4);
8670 else
8671 t = build_call_expr (builtin_decl_explicit (start_fn),
8672 6, t0, t1, t2, t, t3, t4);
8673 }
8674 else if (fd->ordered)
8675 t = build_call_expr (builtin_decl_explicit (start_fn),
8676 4, t0, t1, t3, t4);
8677 else
8678 t = build_call_expr (builtin_decl_explicit (start_fn),
8679 5, t0, t1, t2, t3, t4);
8680 }
8681 else
8682 {
8683 tree t5;
8684 tree c_bool_type;
8685 tree bfn_decl;
8686
8687 /* The GOMP_loop_ull_*start functions have additional boolean
8688 argument, true for < loops and false for > loops.
8689 In Fortran, the C bool type can be different from
8690 boolean_type_node. */
8691 bfn_decl = builtin_decl_explicit (start_fn);
8692 c_bool_type = TREE_TYPE (TREE_TYPE (bfn_decl));
8693 t5 = build_int_cst (c_bool_type,
8694 fd->loop.cond_code == LT_EXPR ? 1 : 0);
8695 if (fd->chunk_size)
8696 {
8697 tree bfn_decl = builtin_decl_explicit (start_fn);
8698 t = fold_convert (fd->iter_type, fd->chunk_size);
8699 t = omp_adjust_chunk_size (t, fd->simd_schedule);
8700 t = build_call_expr (bfn_decl, 7, t5, t0, t1, t2, t, t3, t4);
8701 }
8702 else
8703 t = build_call_expr (builtin_decl_explicit (start_fn),
8704 6, t5, t0, t1, t2, t3, t4);
8705 }
8706 }
8707 if (TREE_TYPE (t) != boolean_type_node)
8708 t = fold_build2 (NE_EXPR, boolean_type_node,
8709 t, build_int_cst (TREE_TYPE (t), 0));
8710 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8711 true, GSI_SAME_STMT);
8712 if (arr && !TREE_STATIC (arr))
8713 {
8714 tree clobber = build_constructor (TREE_TYPE (arr), NULL);
8715 TREE_THIS_VOLATILE (clobber) = 1;
8716 gsi_insert_before (&gsi, gimple_build_assign (arr, clobber),
8717 GSI_SAME_STMT);
8718 }
8719 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
8720
8721 /* Remove the GIMPLE_OMP_FOR statement. */
8722 gsi_remove (&gsi, true);
8723
8724 if (gsi_end_p (gsif))
8725 gsif = gsi_after_labels (gsi_bb (gsif));
8726 gsi_next (&gsif);
8727
8728 /* Iteration setup for sequential loop goes in L0_BB. */
8729 tree startvar = fd->loop.v;
8730 tree endvar = NULL_TREE;
8731
8732 if (gimple_omp_for_combined_p (fd->for_stmt))
8733 {
8734 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_FOR
8735 && gimple_omp_for_kind (inner_stmt)
8736 == GF_OMP_FOR_KIND_SIMD);
8737 tree innerc = find_omp_clause (gimple_omp_for_clauses (inner_stmt),
8738 OMP_CLAUSE__LOOPTEMP_);
8739 gcc_assert (innerc);
8740 startvar = OMP_CLAUSE_DECL (innerc);
8741 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
8742 OMP_CLAUSE__LOOPTEMP_);
8743 gcc_assert (innerc);
8744 endvar = OMP_CLAUSE_DECL (innerc);
8745 }
8746
8747 gsi = gsi_start_bb (l0_bb);
8748 t = istart0;
8749 if (fd->ordered && fd->collapse == 1)
8750 t = fold_build2 (MULT_EXPR, fd->iter_type, t,
8751 fold_convert (fd->iter_type, fd->loop.step));
8752 else if (bias)
8753 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
8754 if (fd->ordered && fd->collapse == 1)
8755 {
8756 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8757 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (startvar),
8758 fd->loop.n1, fold_convert (sizetype, t));
8759 else
8760 {
8761 t = fold_convert (TREE_TYPE (startvar), t);
8762 t = fold_build2 (PLUS_EXPR, TREE_TYPE (startvar),
8763 fd->loop.n1, t);
8764 }
8765 }
8766 else
8767 {
8768 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8769 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
8770 t = fold_convert (TREE_TYPE (startvar), t);
8771 }
8772 t = force_gimple_operand_gsi (&gsi, t,
8773 DECL_P (startvar)
8774 && TREE_ADDRESSABLE (startvar),
8775 NULL_TREE, false, GSI_CONTINUE_LINKING);
8776 assign_stmt = gimple_build_assign (startvar, t);
8777 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
8778
8779 t = iend0;
8780 if (fd->ordered && fd->collapse == 1)
8781 t = fold_build2 (MULT_EXPR, fd->iter_type, t,
8782 fold_convert (fd->iter_type, fd->loop.step));
8783 else if (bias)
8784 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
8785 if (fd->ordered && fd->collapse == 1)
8786 {
8787 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8788 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (startvar),
8789 fd->loop.n1, fold_convert (sizetype, t));
8790 else
8791 {
8792 t = fold_convert (TREE_TYPE (startvar), t);
8793 t = fold_build2 (PLUS_EXPR, TREE_TYPE (startvar),
8794 fd->loop.n1, t);
8795 }
8796 }
8797 else
8798 {
8799 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8800 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
8801 t = fold_convert (TREE_TYPE (startvar), t);
8802 }
8803 iend = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8804 false, GSI_CONTINUE_LINKING);
8805 if (endvar)
8806 {
8807 assign_stmt = gimple_build_assign (endvar, iend);
8808 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
8809 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (iend)))
8810 assign_stmt = gimple_build_assign (fd->loop.v, iend);
8811 else
8812 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, iend);
8813 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
8814 }
8815 /* Handle linear clause adjustments. */
8816 tree itercnt = NULL_TREE;
8817 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_FOR)
8818 for (tree c = gimple_omp_for_clauses (fd->for_stmt);
8819 c; c = OMP_CLAUSE_CHAIN (c))
8820 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
8821 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
8822 {
8823 tree d = OMP_CLAUSE_DECL (c);
8824 bool is_ref = is_reference (d);
8825 tree t = d, a, dest;
8826 if (is_ref)
8827 t = build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c), t);
8828 tree type = TREE_TYPE (t);
8829 if (POINTER_TYPE_P (type))
8830 type = sizetype;
8831 dest = unshare_expr (t);
8832 tree v = create_tmp_var (TREE_TYPE (t), NULL);
8833 expand_omp_build_assign (&gsif, v, t);
8834 if (itercnt == NULL_TREE)
8835 {
8836 itercnt = startvar;
8837 tree n1 = fd->loop.n1;
8838 if (POINTER_TYPE_P (TREE_TYPE (itercnt)))
8839 {
8840 itercnt
8841 = fold_convert (signed_type_for (TREE_TYPE (itercnt)),
8842 itercnt);
8843 n1 = fold_convert (TREE_TYPE (itercnt), n1);
8844 }
8845 itercnt = fold_build2 (MINUS_EXPR, TREE_TYPE (itercnt),
8846 itercnt, n1);
8847 itercnt = fold_build2 (EXACT_DIV_EXPR, TREE_TYPE (itercnt),
8848 itercnt, fd->loop.step);
8849 itercnt = force_gimple_operand_gsi (&gsi, itercnt, true,
8850 NULL_TREE, false,
8851 GSI_CONTINUE_LINKING);
8852 }
8853 a = fold_build2 (MULT_EXPR, type,
8854 fold_convert (type, itercnt),
8855 fold_convert (type, OMP_CLAUSE_LINEAR_STEP (c)));
8856 t = fold_build2 (type == TREE_TYPE (t) ? PLUS_EXPR
8857 : POINTER_PLUS_EXPR, TREE_TYPE (t), v, a);
8858 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8859 false, GSI_CONTINUE_LINKING);
8860 assign_stmt = gimple_build_assign (dest, t);
8861 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
8862 }
8863 if (fd->collapse > 1)
8864 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
8865
8866 if (fd->ordered)
8867 {
8868 /* Until now, counts array contained number of iterations or
8869 variable containing it for ith loop. From now on, we need
8870 those counts only for collapsed loops, and only for the 2nd
8871 till the last collapsed one. Move those one element earlier,
8872 we'll use counts[fd->collapse - 1] for the first source/sink
8873 iteration counter and so on and counts[fd->ordered]
8874 as the array holding the current counter values for
8875 depend(source). */
8876 if (fd->collapse > 1)
8877 memmove (counts, counts + 1, (fd->collapse - 1) * sizeof (counts[0]));
8878 if (broken_loop)
8879 {
8880 int i;
8881 for (i = fd->collapse; i < fd->ordered; i++)
8882 {
8883 tree type = TREE_TYPE (fd->loops[i].v);
8884 tree this_cond
8885 = fold_build2 (fd->loops[i].cond_code, boolean_type_node,
8886 fold_convert (type, fd->loops[i].n1),
8887 fold_convert (type, fd->loops[i].n2));
8888 if (!integer_onep (this_cond))
8889 break;
8890 }
8891 if (i < fd->ordered)
8892 {
8893 cont_bb
8894 = create_empty_bb (EXIT_BLOCK_PTR_FOR_FN (cfun)->prev_bb);
8895 add_bb_to_loop (cont_bb, l1_bb->loop_father);
8896 gimple_stmt_iterator gsi = gsi_after_labels (cont_bb);
8897 gimple *g = gimple_build_omp_continue (fd->loop.v, fd->loop.v);
8898 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
8899 make_edge (cont_bb, l3_bb, EDGE_FALLTHRU);
8900 make_edge (cont_bb, l1_bb, 0);
8901 l2_bb = create_empty_bb (cont_bb);
8902 broken_loop = false;
8903 }
8904 }
8905 expand_omp_ordered_source_sink (region, fd, counts, cont_bb);
8906 cont_bb = expand_omp_for_ordered_loops (fd, counts, cont_bb, l1_bb,
8907 ordered_lastprivate);
8908 if (counts[fd->collapse - 1])
8909 {
8910 gcc_assert (fd->collapse == 1);
8911 gsi = gsi_last_bb (l0_bb);
8912 expand_omp_build_assign (&gsi, counts[fd->collapse - 1],
8913 istart0, true);
8914 gsi = gsi_last_bb (cont_bb);
8915 t = fold_build2 (PLUS_EXPR, fd->iter_type, counts[fd->collapse - 1],
8916 build_int_cst (fd->iter_type, 1));
8917 expand_omp_build_assign (&gsi, counts[fd->collapse - 1], t);
8918 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8919 size_zero_node, NULL_TREE, NULL_TREE);
8920 expand_omp_build_assign (&gsi, aref, counts[fd->collapse - 1]);
8921 t = counts[fd->collapse - 1];
8922 }
8923 else if (fd->collapse > 1)
8924 t = fd->loop.v;
8925 else
8926 {
8927 t = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->loops[0].v),
8928 fd->loops[0].v, fd->loops[0].n1);
8929 t = fold_convert (fd->iter_type, t);
8930 }
8931 gsi = gsi_last_bb (l0_bb);
8932 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8933 size_zero_node, NULL_TREE, NULL_TREE);
8934 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8935 false, GSI_CONTINUE_LINKING);
8936 expand_omp_build_assign (&gsi, aref, t, true);
8937 }
8938
8939 if (!broken_loop)
8940 {
8941 /* Code to control the increment and predicate for the sequential
8942 loop goes in the CONT_BB. */
8943 gsi = gsi_last_bb (cont_bb);
8944 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
8945 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
8946 vmain = gimple_omp_continue_control_use (cont_stmt);
8947 vback = gimple_omp_continue_control_def (cont_stmt);
8948
8949 if (!gimple_omp_for_combined_p (fd->for_stmt))
8950 {
8951 if (POINTER_TYPE_P (type))
8952 t = fold_build_pointer_plus (vmain, fd->loop.step);
8953 else
8954 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
8955 t = force_gimple_operand_gsi (&gsi, t,
8956 DECL_P (vback)
8957 && TREE_ADDRESSABLE (vback),
8958 NULL_TREE, true, GSI_SAME_STMT);
8959 assign_stmt = gimple_build_assign (vback, t);
8960 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
8961
8962 if (fd->ordered && counts[fd->collapse - 1] == NULL_TREE)
8963 {
8964 if (fd->collapse > 1)
8965 t = fd->loop.v;
8966 else
8967 {
8968 t = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->loops[0].v),
8969 fd->loops[0].v, fd->loops[0].n1);
8970 t = fold_convert (fd->iter_type, t);
8971 }
8972 tree aref = build4 (ARRAY_REF, fd->iter_type,
8973 counts[fd->ordered], size_zero_node,
8974 NULL_TREE, NULL_TREE);
8975 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8976 true, GSI_SAME_STMT);
8977 expand_omp_build_assign (&gsi, aref, t);
8978 }
8979
8980 t = build2 (fd->loop.cond_code, boolean_type_node,
8981 DECL_P (vback) && TREE_ADDRESSABLE (vback) ? t : vback,
8982 iend);
8983 gcond *cond_stmt = gimple_build_cond_empty (t);
8984 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
8985 }
8986
8987 /* Remove GIMPLE_OMP_CONTINUE. */
8988 gsi_remove (&gsi, true);
8989
8990 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
8991 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, l1_bb);
8992
8993 /* Emit code to get the next parallel iteration in L2_BB. */
8994 gsi = gsi_start_bb (l2_bb);
8995
8996 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
8997 build_fold_addr_expr (istart0),
8998 build_fold_addr_expr (iend0));
8999 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9000 false, GSI_CONTINUE_LINKING);
9001 if (TREE_TYPE (t) != boolean_type_node)
9002 t = fold_build2 (NE_EXPR, boolean_type_node,
9003 t, build_int_cst (TREE_TYPE (t), 0));
9004 gcond *cond_stmt = gimple_build_cond_empty (t);
9005 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
9006 }
9007
9008 /* Add the loop cleanup function. */
9009 gsi = gsi_last_bb (exit_bb);
9010 if (gimple_omp_return_nowait_p (gsi_stmt (gsi)))
9011 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
9012 else if (gimple_omp_return_lhs (gsi_stmt (gsi)))
9013 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL);
9014 else
9015 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END);
9016 gcall *call_stmt = gimple_build_call (t, 0);
9017 if (gimple_omp_return_lhs (gsi_stmt (gsi)))
9018 gimple_call_set_lhs (call_stmt, gimple_omp_return_lhs (gsi_stmt (gsi)));
9019 gsi_insert_after (&gsi, call_stmt, GSI_SAME_STMT);
9020 if (fd->ordered)
9021 {
9022 tree arr = counts[fd->ordered];
9023 tree clobber = build_constructor (TREE_TYPE (arr), NULL);
9024 TREE_THIS_VOLATILE (clobber) = 1;
9025 gsi_insert_after (&gsi, gimple_build_assign (arr, clobber),
9026 GSI_SAME_STMT);
9027 }
9028 gsi_remove (&gsi, true);
9029
9030 /* Connect the new blocks. */
9031 find_edge (entry_bb, l0_bb)->flags = EDGE_TRUE_VALUE;
9032 find_edge (entry_bb, l3_bb)->flags = EDGE_FALSE_VALUE;
9033
9034 if (!broken_loop)
9035 {
9036 gimple_seq phis;
9037
9038 e = find_edge (cont_bb, l3_bb);
9039 ne = make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
9040
9041 phis = phi_nodes (l3_bb);
9042 for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi))
9043 {
9044 gimple *phi = gsi_stmt (gsi);
9045 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, ne),
9046 PHI_ARG_DEF_FROM_EDGE (phi, e));
9047 }
9048 remove_edge (e);
9049
9050 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
9051 e = find_edge (cont_bb, l1_bb);
9052 if (e == NULL)
9053 {
9054 e = BRANCH_EDGE (cont_bb);
9055 gcc_assert (single_succ (e->dest) == l1_bb);
9056 }
9057 if (gimple_omp_for_combined_p (fd->for_stmt))
9058 {
9059 remove_edge (e);
9060 e = NULL;
9061 }
9062 else if (fd->collapse > 1)
9063 {
9064 remove_edge (e);
9065 e = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
9066 }
9067 else
9068 e->flags = EDGE_TRUE_VALUE;
9069 if (e)
9070 {
9071 e->probability = REG_BR_PROB_BASE * 7 / 8;
9072 find_edge (cont_bb, l2_bb)->probability = REG_BR_PROB_BASE / 8;
9073 }
9074 else
9075 {
9076 e = find_edge (cont_bb, l2_bb);
9077 e->flags = EDGE_FALLTHRU;
9078 }
9079 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
9080
9081 if (gimple_in_ssa_p (cfun))
9082 {
9083 /* Add phis to the outer loop that connect to the phis in the inner,
9084 original loop, and move the loop entry value of the inner phi to
9085 the loop entry value of the outer phi. */
9086 gphi_iterator psi;
9087 for (psi = gsi_start_phis (l3_bb); !gsi_end_p (psi); gsi_next (&psi))
9088 {
9089 source_location locus;
9090 gphi *nphi;
9091 gphi *exit_phi = psi.phi ();
9092
9093 edge l2_to_l3 = find_edge (l2_bb, l3_bb);
9094 tree exit_res = PHI_ARG_DEF_FROM_EDGE (exit_phi, l2_to_l3);
9095
9096 basic_block latch = BRANCH_EDGE (cont_bb)->dest;
9097 edge latch_to_l1 = find_edge (latch, l1_bb);
9098 gphi *inner_phi
9099 = find_phi_with_arg_on_edge (exit_res, latch_to_l1);
9100
9101 tree t = gimple_phi_result (exit_phi);
9102 tree new_res = copy_ssa_name (t, NULL);
9103 nphi = create_phi_node (new_res, l0_bb);
9104
9105 edge l0_to_l1 = find_edge (l0_bb, l1_bb);
9106 t = PHI_ARG_DEF_FROM_EDGE (inner_phi, l0_to_l1);
9107 locus = gimple_phi_arg_location_from_edge (inner_phi, l0_to_l1);
9108 edge entry_to_l0 = find_edge (entry_bb, l0_bb);
9109 add_phi_arg (nphi, t, entry_to_l0, locus);
9110
9111 edge l2_to_l0 = find_edge (l2_bb, l0_bb);
9112 add_phi_arg (nphi, exit_res, l2_to_l0, UNKNOWN_LOCATION);
9113
9114 add_phi_arg (inner_phi, new_res, l0_to_l1, UNKNOWN_LOCATION);
9115 };
9116 }
9117
9118 set_immediate_dominator (CDI_DOMINATORS, l2_bb,
9119 recompute_dominator (CDI_DOMINATORS, l2_bb));
9120 set_immediate_dominator (CDI_DOMINATORS, l3_bb,
9121 recompute_dominator (CDI_DOMINATORS, l3_bb));
9122 set_immediate_dominator (CDI_DOMINATORS, l0_bb,
9123 recompute_dominator (CDI_DOMINATORS, l0_bb));
9124 set_immediate_dominator (CDI_DOMINATORS, l1_bb,
9125 recompute_dominator (CDI_DOMINATORS, l1_bb));
9126
9127 /* We enter expand_omp_for_generic with a loop. This original loop may
9128 have its own loop struct, or it may be part of an outer loop struct
9129 (which may be the fake loop). */
9130 struct loop *outer_loop = entry_bb->loop_father;
9131 bool orig_loop_has_loop_struct = l1_bb->loop_father != outer_loop;
9132
9133 add_bb_to_loop (l2_bb, outer_loop);
9134
9135 /* We've added a new loop around the original loop. Allocate the
9136 corresponding loop struct. */
9137 struct loop *new_loop = alloc_loop ();
9138 new_loop->header = l0_bb;
9139 new_loop->latch = l2_bb;
9140 add_loop (new_loop, outer_loop);
9141
9142 /* Allocate a loop structure for the original loop unless we already
9143 had one. */
9144 if (!orig_loop_has_loop_struct
9145 && !gimple_omp_for_combined_p (fd->for_stmt))
9146 {
9147 struct loop *orig_loop = alloc_loop ();
9148 orig_loop->header = l1_bb;
9149 /* The loop may have multiple latches. */
9150 add_loop (orig_loop, new_loop);
9151 }
9152 }
9153 }
9154
9155
9156 /* A subroutine of expand_omp_for. Generate code for a parallel
9157 loop with static schedule and no specified chunk size. Given
9158 parameters:
9159
9160 for (V = N1; V cond N2; V += STEP) BODY;
9161
9162 where COND is "<" or ">", we generate pseudocode
9163
9164 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
9165 if (cond is <)
9166 adj = STEP - 1;
9167 else
9168 adj = STEP + 1;
9169 if ((__typeof (V)) -1 > 0 && cond is >)
9170 n = -(adj + N2 - N1) / -STEP;
9171 else
9172 n = (adj + N2 - N1) / STEP;
9173 q = n / nthreads;
9174 tt = n % nthreads;
9175 if (threadid < tt) goto L3; else goto L4;
9176 L3:
9177 tt = 0;
9178 q = q + 1;
9179 L4:
9180 s0 = q * threadid + tt;
9181 e0 = s0 + q;
9182 V = s0 * STEP + N1;
9183 if (s0 >= e0) goto L2; else goto L0;
9184 L0:
9185 e = e0 * STEP + N1;
9186 L1:
9187 BODY;
9188 V += STEP;
9189 if (V cond e) goto L1;
9190 L2:
9191 */
9192
9193 static void
9194 expand_omp_for_static_nochunk (struct omp_region *region,
9195 struct omp_for_data *fd,
9196 gimple *inner_stmt)
9197 {
9198 tree n, q, s0, e0, e, t, tt, nthreads, threadid;
9199 tree type, itype, vmain, vback;
9200 basic_block entry_bb, second_bb, third_bb, exit_bb, seq_start_bb;
9201 basic_block body_bb, cont_bb, collapse_bb = NULL;
9202 basic_block fin_bb;
9203 gimple_stmt_iterator gsi;
9204 edge ep;
9205 bool broken_loop = region->cont == NULL;
9206 tree *counts = NULL;
9207 tree n1, n2, step;
9208
9209 itype = type = TREE_TYPE (fd->loop.v);
9210 if (POINTER_TYPE_P (type))
9211 itype = signed_type_for (type);
9212
9213 entry_bb = region->entry;
9214 cont_bb = region->cont;
9215 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
9216 fin_bb = BRANCH_EDGE (entry_bb)->dest;
9217 gcc_assert (broken_loop
9218 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
9219 seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb));
9220 body_bb = single_succ (seq_start_bb);
9221 if (!broken_loop)
9222 {
9223 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb
9224 || single_succ (BRANCH_EDGE (cont_bb)->dest) == body_bb);
9225 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
9226 }
9227 exit_bb = region->exit;
9228
9229 /* Iteration space partitioning goes in ENTRY_BB. */
9230 gsi = gsi_last_bb (entry_bb);
9231 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
9232
9233 if (fd->collapse > 1)
9234 {
9235 int first_zero_iter = -1, dummy = -1;
9236 basic_block l2_dom_bb = NULL, dummy_bb = NULL;
9237
9238 counts = XALLOCAVEC (tree, fd->collapse);
9239 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
9240 fin_bb, first_zero_iter,
9241 dummy_bb, dummy, l2_dom_bb);
9242 t = NULL_TREE;
9243 }
9244 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
9245 t = integer_one_node;
9246 else
9247 t = fold_binary (fd->loop.cond_code, boolean_type_node,
9248 fold_convert (type, fd->loop.n1),
9249 fold_convert (type, fd->loop.n2));
9250 if (fd->collapse == 1
9251 && TYPE_UNSIGNED (type)
9252 && (t == NULL_TREE || !integer_onep (t)))
9253 {
9254 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
9255 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
9256 true, GSI_SAME_STMT);
9257 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
9258 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
9259 true, GSI_SAME_STMT);
9260 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
9261 NULL_TREE, NULL_TREE);
9262 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
9263 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
9264 expand_omp_regimplify_p, NULL, NULL)
9265 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
9266 expand_omp_regimplify_p, NULL, NULL))
9267 {
9268 gsi = gsi_for_stmt (cond_stmt);
9269 gimple_regimplify_operands (cond_stmt, &gsi);
9270 }
9271 ep = split_block (entry_bb, cond_stmt);
9272 ep->flags = EDGE_TRUE_VALUE;
9273 entry_bb = ep->dest;
9274 ep->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
9275 ep = make_edge (ep->src, fin_bb, EDGE_FALSE_VALUE);
9276 ep->probability = REG_BR_PROB_BASE / 2000 - 1;
9277 if (gimple_in_ssa_p (cfun))
9278 {
9279 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
9280 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
9281 !gsi_end_p (gpi); gsi_next (&gpi))
9282 {
9283 gphi *phi = gpi.phi ();
9284 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
9285 ep, UNKNOWN_LOCATION);
9286 }
9287 }
9288 gsi = gsi_last_bb (entry_bb);
9289 }
9290
9291 switch (gimple_omp_for_kind (fd->for_stmt))
9292 {
9293 case GF_OMP_FOR_KIND_FOR:
9294 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
9295 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
9296 break;
9297 case GF_OMP_FOR_KIND_DISTRIBUTE:
9298 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
9299 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
9300 break;
9301 default:
9302 gcc_unreachable ();
9303 }
9304 nthreads = build_call_expr (nthreads, 0);
9305 nthreads = fold_convert (itype, nthreads);
9306 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
9307 true, GSI_SAME_STMT);
9308 threadid = build_call_expr (threadid, 0);
9309 threadid = fold_convert (itype, threadid);
9310 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
9311 true, GSI_SAME_STMT);
9312
9313 n1 = fd->loop.n1;
9314 n2 = fd->loop.n2;
9315 step = fd->loop.step;
9316 if (gimple_omp_for_combined_into_p (fd->for_stmt))
9317 {
9318 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
9319 OMP_CLAUSE__LOOPTEMP_);
9320 gcc_assert (innerc);
9321 n1 = OMP_CLAUSE_DECL (innerc);
9322 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9323 OMP_CLAUSE__LOOPTEMP_);
9324 gcc_assert (innerc);
9325 n2 = OMP_CLAUSE_DECL (innerc);
9326 }
9327 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
9328 true, NULL_TREE, true, GSI_SAME_STMT);
9329 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
9330 true, NULL_TREE, true, GSI_SAME_STMT);
9331 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
9332 true, NULL_TREE, true, GSI_SAME_STMT);
9333
9334 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
9335 t = fold_build2 (PLUS_EXPR, itype, step, t);
9336 t = fold_build2 (PLUS_EXPR, itype, t, n2);
9337 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
9338 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
9339 t = fold_build2 (TRUNC_DIV_EXPR, itype,
9340 fold_build1 (NEGATE_EXPR, itype, t),
9341 fold_build1 (NEGATE_EXPR, itype, step));
9342 else
9343 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
9344 t = fold_convert (itype, t);
9345 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
9346
9347 q = create_tmp_reg (itype, "q");
9348 t = fold_build2 (TRUNC_DIV_EXPR, itype, n, nthreads);
9349 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
9350 gsi_insert_before (&gsi, gimple_build_assign (q, t), GSI_SAME_STMT);
9351
9352 tt = create_tmp_reg (itype, "tt");
9353 t = fold_build2 (TRUNC_MOD_EXPR, itype, n, nthreads);
9354 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
9355 gsi_insert_before (&gsi, gimple_build_assign (tt, t), GSI_SAME_STMT);
9356
9357 t = build2 (LT_EXPR, boolean_type_node, threadid, tt);
9358 gcond *cond_stmt = gimple_build_cond_empty (t);
9359 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
9360
9361 second_bb = split_block (entry_bb, cond_stmt)->dest;
9362 gsi = gsi_last_bb (second_bb);
9363 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
9364
9365 gsi_insert_before (&gsi, gimple_build_assign (tt, build_int_cst (itype, 0)),
9366 GSI_SAME_STMT);
9367 gassign *assign_stmt
9368 = gimple_build_assign (q, PLUS_EXPR, q, build_int_cst (itype, 1));
9369 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
9370
9371 third_bb = split_block (second_bb, assign_stmt)->dest;
9372 gsi = gsi_last_bb (third_bb);
9373 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
9374
9375 t = build2 (MULT_EXPR, itype, q, threadid);
9376 t = build2 (PLUS_EXPR, itype, t, tt);
9377 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
9378
9379 t = fold_build2 (PLUS_EXPR, itype, s0, q);
9380 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
9381
9382 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
9383 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
9384
9385 /* Remove the GIMPLE_OMP_FOR statement. */
9386 gsi_remove (&gsi, true);
9387
9388 /* Setup code for sequential iteration goes in SEQ_START_BB. */
9389 gsi = gsi_start_bb (seq_start_bb);
9390
9391 tree startvar = fd->loop.v;
9392 tree endvar = NULL_TREE;
9393
9394 if (gimple_omp_for_combined_p (fd->for_stmt))
9395 {
9396 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
9397 ? gimple_omp_parallel_clauses (inner_stmt)
9398 : gimple_omp_for_clauses (inner_stmt);
9399 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
9400 gcc_assert (innerc);
9401 startvar = OMP_CLAUSE_DECL (innerc);
9402 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9403 OMP_CLAUSE__LOOPTEMP_);
9404 gcc_assert (innerc);
9405 endvar = OMP_CLAUSE_DECL (innerc);
9406 if (fd->collapse > 1 && TREE_CODE (fd->loop.n2) != INTEGER_CST
9407 && gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
9408 {
9409 int i;
9410 for (i = 1; i < fd->collapse; i++)
9411 {
9412 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9413 OMP_CLAUSE__LOOPTEMP_);
9414 gcc_assert (innerc);
9415 }
9416 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9417 OMP_CLAUSE__LOOPTEMP_);
9418 if (innerc)
9419 {
9420 /* If needed (distribute parallel for with lastprivate),
9421 propagate down the total number of iterations. */
9422 tree t = fold_convert (TREE_TYPE (OMP_CLAUSE_DECL (innerc)),
9423 fd->loop.n2);
9424 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, false,
9425 GSI_CONTINUE_LINKING);
9426 assign_stmt = gimple_build_assign (OMP_CLAUSE_DECL (innerc), t);
9427 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9428 }
9429 }
9430 }
9431 t = fold_convert (itype, s0);
9432 t = fold_build2 (MULT_EXPR, itype, t, step);
9433 if (POINTER_TYPE_P (type))
9434 t = fold_build_pointer_plus (n1, t);
9435 else
9436 t = fold_build2 (PLUS_EXPR, type, t, n1);
9437 t = fold_convert (TREE_TYPE (startvar), t);
9438 t = force_gimple_operand_gsi (&gsi, t,
9439 DECL_P (startvar)
9440 && TREE_ADDRESSABLE (startvar),
9441 NULL_TREE, false, GSI_CONTINUE_LINKING);
9442 assign_stmt = gimple_build_assign (startvar, t);
9443 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9444
9445 t = fold_convert (itype, e0);
9446 t = fold_build2 (MULT_EXPR, itype, t, step);
9447 if (POINTER_TYPE_P (type))
9448 t = fold_build_pointer_plus (n1, t);
9449 else
9450 t = fold_build2 (PLUS_EXPR, type, t, n1);
9451 t = fold_convert (TREE_TYPE (startvar), t);
9452 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9453 false, GSI_CONTINUE_LINKING);
9454 if (endvar)
9455 {
9456 assign_stmt = gimple_build_assign (endvar, e);
9457 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9458 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
9459 assign_stmt = gimple_build_assign (fd->loop.v, e);
9460 else
9461 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
9462 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9463 }
9464 /* Handle linear clause adjustments. */
9465 tree itercnt = NULL_TREE;
9466 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_FOR)
9467 for (tree c = gimple_omp_for_clauses (fd->for_stmt);
9468 c; c = OMP_CLAUSE_CHAIN (c))
9469 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
9470 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
9471 {
9472 tree d = OMP_CLAUSE_DECL (c);
9473 bool is_ref = is_reference (d);
9474 tree t = d, a, dest;
9475 if (is_ref)
9476 t = build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c), t);
9477 if (itercnt == NULL_TREE)
9478 {
9479 if (gimple_omp_for_combined_into_p (fd->for_stmt))
9480 {
9481 itercnt = fold_build2 (MINUS_EXPR, itype,
9482 fold_convert (itype, n1),
9483 fold_convert (itype, fd->loop.n1));
9484 itercnt = fold_build2 (EXACT_DIV_EXPR, itype, itercnt, step);
9485 itercnt = fold_build2 (PLUS_EXPR, itype, itercnt, s0);
9486 itercnt = force_gimple_operand_gsi (&gsi, itercnt, true,
9487 NULL_TREE, false,
9488 GSI_CONTINUE_LINKING);
9489 }
9490 else
9491 itercnt = s0;
9492 }
9493 tree type = TREE_TYPE (t);
9494 if (POINTER_TYPE_P (type))
9495 type = sizetype;
9496 a = fold_build2 (MULT_EXPR, type,
9497 fold_convert (type, itercnt),
9498 fold_convert (type, OMP_CLAUSE_LINEAR_STEP (c)));
9499 dest = unshare_expr (t);
9500 t = fold_build2 (type == TREE_TYPE (t) ? PLUS_EXPR
9501 : POINTER_PLUS_EXPR, TREE_TYPE (t), t, a);
9502 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9503 false, GSI_CONTINUE_LINKING);
9504 assign_stmt = gimple_build_assign (dest, t);
9505 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9506 }
9507 if (fd->collapse > 1)
9508 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
9509
9510 if (!broken_loop)
9511 {
9512 /* The code controlling the sequential loop replaces the
9513 GIMPLE_OMP_CONTINUE. */
9514 gsi = gsi_last_bb (cont_bb);
9515 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
9516 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
9517 vmain = gimple_omp_continue_control_use (cont_stmt);
9518 vback = gimple_omp_continue_control_def (cont_stmt);
9519
9520 if (!gimple_omp_for_combined_p (fd->for_stmt))
9521 {
9522 if (POINTER_TYPE_P (type))
9523 t = fold_build_pointer_plus (vmain, step);
9524 else
9525 t = fold_build2 (PLUS_EXPR, type, vmain, step);
9526 t = force_gimple_operand_gsi (&gsi, t,
9527 DECL_P (vback)
9528 && TREE_ADDRESSABLE (vback),
9529 NULL_TREE, true, GSI_SAME_STMT);
9530 assign_stmt = gimple_build_assign (vback, t);
9531 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
9532
9533 t = build2 (fd->loop.cond_code, boolean_type_node,
9534 DECL_P (vback) && TREE_ADDRESSABLE (vback)
9535 ? t : vback, e);
9536 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
9537 }
9538
9539 /* Remove the GIMPLE_OMP_CONTINUE statement. */
9540 gsi_remove (&gsi, true);
9541
9542 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
9543 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
9544 }
9545
9546 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
9547 gsi = gsi_last_bb (exit_bb);
9548 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
9549 {
9550 t = gimple_omp_return_lhs (gsi_stmt (gsi));
9551 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
9552 }
9553 gsi_remove (&gsi, true);
9554
9555 /* Connect all the blocks. */
9556 ep = make_edge (entry_bb, third_bb, EDGE_FALSE_VALUE);
9557 ep->probability = REG_BR_PROB_BASE / 4 * 3;
9558 ep = find_edge (entry_bb, second_bb);
9559 ep->flags = EDGE_TRUE_VALUE;
9560 ep->probability = REG_BR_PROB_BASE / 4;
9561 find_edge (third_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
9562 find_edge (third_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
9563
9564 if (!broken_loop)
9565 {
9566 ep = find_edge (cont_bb, body_bb);
9567 if (ep == NULL)
9568 {
9569 ep = BRANCH_EDGE (cont_bb);
9570 gcc_assert (single_succ (ep->dest) == body_bb);
9571 }
9572 if (gimple_omp_for_combined_p (fd->for_stmt))
9573 {
9574 remove_edge (ep);
9575 ep = NULL;
9576 }
9577 else if (fd->collapse > 1)
9578 {
9579 remove_edge (ep);
9580 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
9581 }
9582 else
9583 ep->flags = EDGE_TRUE_VALUE;
9584 find_edge (cont_bb, fin_bb)->flags
9585 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
9586 }
9587
9588 set_immediate_dominator (CDI_DOMINATORS, second_bb, entry_bb);
9589 set_immediate_dominator (CDI_DOMINATORS, third_bb, entry_bb);
9590 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, third_bb);
9591
9592 set_immediate_dominator (CDI_DOMINATORS, body_bb,
9593 recompute_dominator (CDI_DOMINATORS, body_bb));
9594 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
9595 recompute_dominator (CDI_DOMINATORS, fin_bb));
9596
9597 struct loop *loop = body_bb->loop_father;
9598 if (loop != entry_bb->loop_father)
9599 {
9600 gcc_assert (loop->header == body_bb);
9601 gcc_assert (broken_loop
9602 || loop->latch == region->cont
9603 || single_pred (loop->latch) == region->cont);
9604 return;
9605 }
9606
9607 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
9608 {
9609 loop = alloc_loop ();
9610 loop->header = body_bb;
9611 if (collapse_bb == NULL)
9612 loop->latch = cont_bb;
9613 add_loop (loop, body_bb->loop_father);
9614 }
9615 }
9616
9617 /* Return phi in E->DEST with ARG on edge E. */
9618
9619 static gphi *
9620 find_phi_with_arg_on_edge (tree arg, edge e)
9621 {
9622 basic_block bb = e->dest;
9623
9624 for (gphi_iterator gpi = gsi_start_phis (bb);
9625 !gsi_end_p (gpi);
9626 gsi_next (&gpi))
9627 {
9628 gphi *phi = gpi.phi ();
9629 if (PHI_ARG_DEF_FROM_EDGE (phi, e) == arg)
9630 return phi;
9631 }
9632
9633 return NULL;
9634 }
9635
9636 /* A subroutine of expand_omp_for. Generate code for a parallel
9637 loop with static schedule and a specified chunk size. Given
9638 parameters:
9639
9640 for (V = N1; V cond N2; V += STEP) BODY;
9641
9642 where COND is "<" or ">", we generate pseudocode
9643
9644 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
9645 if (cond is <)
9646 adj = STEP - 1;
9647 else
9648 adj = STEP + 1;
9649 if ((__typeof (V)) -1 > 0 && cond is >)
9650 n = -(adj + N2 - N1) / -STEP;
9651 else
9652 n = (adj + N2 - N1) / STEP;
9653 trip = 0;
9654 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
9655 here so that V is defined
9656 if the loop is not entered
9657 L0:
9658 s0 = (trip * nthreads + threadid) * CHUNK;
9659 e0 = min(s0 + CHUNK, n);
9660 if (s0 < n) goto L1; else goto L4;
9661 L1:
9662 V = s0 * STEP + N1;
9663 e = e0 * STEP + N1;
9664 L2:
9665 BODY;
9666 V += STEP;
9667 if (V cond e) goto L2; else goto L3;
9668 L3:
9669 trip += 1;
9670 goto L0;
9671 L4:
9672 */
9673
9674 static void
9675 expand_omp_for_static_chunk (struct omp_region *region,
9676 struct omp_for_data *fd, gimple *inner_stmt)
9677 {
9678 tree n, s0, e0, e, t;
9679 tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
9680 tree type, itype, vmain, vback, vextra;
9681 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
9682 basic_block trip_update_bb = NULL, cont_bb, collapse_bb = NULL, fin_bb;
9683 gimple_stmt_iterator gsi;
9684 edge se;
9685 bool broken_loop = region->cont == NULL;
9686 tree *counts = NULL;
9687 tree n1, n2, step;
9688
9689 itype = type = TREE_TYPE (fd->loop.v);
9690 if (POINTER_TYPE_P (type))
9691 itype = signed_type_for (type);
9692
9693 entry_bb = region->entry;
9694 se = split_block (entry_bb, last_stmt (entry_bb));
9695 entry_bb = se->src;
9696 iter_part_bb = se->dest;
9697 cont_bb = region->cont;
9698 gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
9699 fin_bb = BRANCH_EDGE (iter_part_bb)->dest;
9700 gcc_assert (broken_loop
9701 || fin_bb == FALLTHRU_EDGE (cont_bb)->dest);
9702 seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
9703 body_bb = single_succ (seq_start_bb);
9704 if (!broken_loop)
9705 {
9706 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb
9707 || single_succ (BRANCH_EDGE (cont_bb)->dest) == body_bb);
9708 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
9709 trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
9710 }
9711 exit_bb = region->exit;
9712
9713 /* Trip and adjustment setup goes in ENTRY_BB. */
9714 gsi = gsi_last_bb (entry_bb);
9715 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
9716
9717 if (fd->collapse > 1)
9718 {
9719 int first_zero_iter = -1, dummy = -1;
9720 basic_block l2_dom_bb = NULL, dummy_bb = NULL;
9721
9722 counts = XALLOCAVEC (tree, fd->collapse);
9723 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
9724 fin_bb, first_zero_iter,
9725 dummy_bb, dummy, l2_dom_bb);
9726 t = NULL_TREE;
9727 }
9728 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
9729 t = integer_one_node;
9730 else
9731 t = fold_binary (fd->loop.cond_code, boolean_type_node,
9732 fold_convert (type, fd->loop.n1),
9733 fold_convert (type, fd->loop.n2));
9734 if (fd->collapse == 1
9735 && TYPE_UNSIGNED (type)
9736 && (t == NULL_TREE || !integer_onep (t)))
9737 {
9738 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
9739 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
9740 true, GSI_SAME_STMT);
9741 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
9742 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
9743 true, GSI_SAME_STMT);
9744 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
9745 NULL_TREE, NULL_TREE);
9746 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
9747 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
9748 expand_omp_regimplify_p, NULL, NULL)
9749 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
9750 expand_omp_regimplify_p, NULL, NULL))
9751 {
9752 gsi = gsi_for_stmt (cond_stmt);
9753 gimple_regimplify_operands (cond_stmt, &gsi);
9754 }
9755 se = split_block (entry_bb, cond_stmt);
9756 se->flags = EDGE_TRUE_VALUE;
9757 entry_bb = se->dest;
9758 se->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
9759 se = make_edge (se->src, fin_bb, EDGE_FALSE_VALUE);
9760 se->probability = REG_BR_PROB_BASE / 2000 - 1;
9761 if (gimple_in_ssa_p (cfun))
9762 {
9763 int dest_idx = find_edge (iter_part_bb, fin_bb)->dest_idx;
9764 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
9765 !gsi_end_p (gpi); gsi_next (&gpi))
9766 {
9767 gphi *phi = gpi.phi ();
9768 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
9769 se, UNKNOWN_LOCATION);
9770 }
9771 }
9772 gsi = gsi_last_bb (entry_bb);
9773 }
9774
9775 switch (gimple_omp_for_kind (fd->for_stmt))
9776 {
9777 case GF_OMP_FOR_KIND_FOR:
9778 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
9779 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
9780 break;
9781 case GF_OMP_FOR_KIND_DISTRIBUTE:
9782 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
9783 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
9784 break;
9785 default:
9786 gcc_unreachable ();
9787 }
9788 nthreads = build_call_expr (nthreads, 0);
9789 nthreads = fold_convert (itype, nthreads);
9790 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
9791 true, GSI_SAME_STMT);
9792 threadid = build_call_expr (threadid, 0);
9793 threadid = fold_convert (itype, threadid);
9794 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
9795 true, GSI_SAME_STMT);
9796
9797 n1 = fd->loop.n1;
9798 n2 = fd->loop.n2;
9799 step = fd->loop.step;
9800 if (gimple_omp_for_combined_into_p (fd->for_stmt))
9801 {
9802 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
9803 OMP_CLAUSE__LOOPTEMP_);
9804 gcc_assert (innerc);
9805 n1 = OMP_CLAUSE_DECL (innerc);
9806 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9807 OMP_CLAUSE__LOOPTEMP_);
9808 gcc_assert (innerc);
9809 n2 = OMP_CLAUSE_DECL (innerc);
9810 }
9811 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
9812 true, NULL_TREE, true, GSI_SAME_STMT);
9813 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
9814 true, NULL_TREE, true, GSI_SAME_STMT);
9815 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
9816 true, NULL_TREE, true, GSI_SAME_STMT);
9817 tree chunk_size = fold_convert (itype, fd->chunk_size);
9818 chunk_size = omp_adjust_chunk_size (chunk_size, fd->simd_schedule);
9819 chunk_size
9820 = force_gimple_operand_gsi (&gsi, chunk_size, true, NULL_TREE, true,
9821 GSI_SAME_STMT);
9822
9823 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
9824 t = fold_build2 (PLUS_EXPR, itype, step, t);
9825 t = fold_build2 (PLUS_EXPR, itype, t, n2);
9826 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
9827 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
9828 t = fold_build2 (TRUNC_DIV_EXPR, itype,
9829 fold_build1 (NEGATE_EXPR, itype, t),
9830 fold_build1 (NEGATE_EXPR, itype, step));
9831 else
9832 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
9833 t = fold_convert (itype, t);
9834 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9835 true, GSI_SAME_STMT);
9836
9837 trip_var = create_tmp_reg (itype, ".trip");
9838 if (gimple_in_ssa_p (cfun))
9839 {
9840 trip_init = make_ssa_name (trip_var);
9841 trip_main = make_ssa_name (trip_var);
9842 trip_back = make_ssa_name (trip_var);
9843 }
9844 else
9845 {
9846 trip_init = trip_var;
9847 trip_main = trip_var;
9848 trip_back = trip_var;
9849 }
9850
9851 gassign *assign_stmt
9852 = gimple_build_assign (trip_init, build_int_cst (itype, 0));
9853 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
9854
9855 t = fold_build2 (MULT_EXPR, itype, threadid, chunk_size);
9856 t = fold_build2 (MULT_EXPR, itype, t, step);
9857 if (POINTER_TYPE_P (type))
9858 t = fold_build_pointer_plus (n1, t);
9859 else
9860 t = fold_build2 (PLUS_EXPR, type, t, n1);
9861 vextra = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9862 true, GSI_SAME_STMT);
9863
9864 /* Remove the GIMPLE_OMP_FOR. */
9865 gsi_remove (&gsi, true);
9866
9867 gimple_stmt_iterator gsif = gsi;
9868
9869 /* Iteration space partitioning goes in ITER_PART_BB. */
9870 gsi = gsi_last_bb (iter_part_bb);
9871
9872 t = fold_build2 (MULT_EXPR, itype, trip_main, nthreads);
9873 t = fold_build2 (PLUS_EXPR, itype, t, threadid);
9874 t = fold_build2 (MULT_EXPR, itype, t, chunk_size);
9875 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9876 false, GSI_CONTINUE_LINKING);
9877
9878 t = fold_build2 (PLUS_EXPR, itype, s0, chunk_size);
9879 t = fold_build2 (MIN_EXPR, itype, t, n);
9880 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9881 false, GSI_CONTINUE_LINKING);
9882
9883 t = build2 (LT_EXPR, boolean_type_node, s0, n);
9884 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_CONTINUE_LINKING);
9885
9886 /* Setup code for sequential iteration goes in SEQ_START_BB. */
9887 gsi = gsi_start_bb (seq_start_bb);
9888
9889 tree startvar = fd->loop.v;
9890 tree endvar = NULL_TREE;
9891
9892 if (gimple_omp_for_combined_p (fd->for_stmt))
9893 {
9894 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
9895 ? gimple_omp_parallel_clauses (inner_stmt)
9896 : gimple_omp_for_clauses (inner_stmt);
9897 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
9898 gcc_assert (innerc);
9899 startvar = OMP_CLAUSE_DECL (innerc);
9900 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9901 OMP_CLAUSE__LOOPTEMP_);
9902 gcc_assert (innerc);
9903 endvar = OMP_CLAUSE_DECL (innerc);
9904 if (fd->collapse > 1 && TREE_CODE (fd->loop.n2) != INTEGER_CST
9905 && gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
9906 {
9907 int i;
9908 for (i = 1; i < fd->collapse; i++)
9909 {
9910 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9911 OMP_CLAUSE__LOOPTEMP_);
9912 gcc_assert (innerc);
9913 }
9914 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9915 OMP_CLAUSE__LOOPTEMP_);
9916 if (innerc)
9917 {
9918 /* If needed (distribute parallel for with lastprivate),
9919 propagate down the total number of iterations. */
9920 tree t = fold_convert (TREE_TYPE (OMP_CLAUSE_DECL (innerc)),
9921 fd->loop.n2);
9922 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, false,
9923 GSI_CONTINUE_LINKING);
9924 assign_stmt = gimple_build_assign (OMP_CLAUSE_DECL (innerc), t);
9925 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9926 }
9927 }
9928 }
9929
9930 t = fold_convert (itype, s0);
9931 t = fold_build2 (MULT_EXPR, itype, t, step);
9932 if (POINTER_TYPE_P (type))
9933 t = fold_build_pointer_plus (n1, t);
9934 else
9935 t = fold_build2 (PLUS_EXPR, type, t, n1);
9936 t = fold_convert (TREE_TYPE (startvar), t);
9937 t = force_gimple_operand_gsi (&gsi, t,
9938 DECL_P (startvar)
9939 && TREE_ADDRESSABLE (startvar),
9940 NULL_TREE, false, GSI_CONTINUE_LINKING);
9941 assign_stmt = gimple_build_assign (startvar, t);
9942 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9943
9944 t = fold_convert (itype, e0);
9945 t = fold_build2 (MULT_EXPR, itype, t, step);
9946 if (POINTER_TYPE_P (type))
9947 t = fold_build_pointer_plus (n1, t);
9948 else
9949 t = fold_build2 (PLUS_EXPR, type, t, n1);
9950 t = fold_convert (TREE_TYPE (startvar), t);
9951 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9952 false, GSI_CONTINUE_LINKING);
9953 if (endvar)
9954 {
9955 assign_stmt = gimple_build_assign (endvar, e);
9956 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9957 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
9958 assign_stmt = gimple_build_assign (fd->loop.v, e);
9959 else
9960 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
9961 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9962 }
9963 /* Handle linear clause adjustments. */
9964 tree itercnt = NULL_TREE, itercntbias = NULL_TREE;
9965 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_FOR)
9966 for (tree c = gimple_omp_for_clauses (fd->for_stmt);
9967 c; c = OMP_CLAUSE_CHAIN (c))
9968 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
9969 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
9970 {
9971 tree d = OMP_CLAUSE_DECL (c);
9972 bool is_ref = is_reference (d);
9973 tree t = d, a, dest;
9974 if (is_ref)
9975 t = build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c), t);
9976 tree type = TREE_TYPE (t);
9977 if (POINTER_TYPE_P (type))
9978 type = sizetype;
9979 dest = unshare_expr (t);
9980 tree v = create_tmp_var (TREE_TYPE (t), NULL);
9981 expand_omp_build_assign (&gsif, v, t);
9982 if (itercnt == NULL_TREE)
9983 {
9984 if (gimple_omp_for_combined_into_p (fd->for_stmt))
9985 {
9986 itercntbias
9987 = fold_build2 (MINUS_EXPR, itype, fold_convert (itype, n1),
9988 fold_convert (itype, fd->loop.n1));
9989 itercntbias = fold_build2 (EXACT_DIV_EXPR, itype,
9990 itercntbias, step);
9991 itercntbias
9992 = force_gimple_operand_gsi (&gsif, itercntbias, true,
9993 NULL_TREE, true,
9994 GSI_SAME_STMT);
9995 itercnt = fold_build2 (PLUS_EXPR, itype, itercntbias, s0);
9996 itercnt = force_gimple_operand_gsi (&gsi, itercnt, true,
9997 NULL_TREE, false,
9998 GSI_CONTINUE_LINKING);
9999 }
10000 else
10001 itercnt = s0;
10002 }
10003 a = fold_build2 (MULT_EXPR, type,
10004 fold_convert (type, itercnt),
10005 fold_convert (type, OMP_CLAUSE_LINEAR_STEP (c)));
10006 t = fold_build2 (type == TREE_TYPE (t) ? PLUS_EXPR
10007 : POINTER_PLUS_EXPR, TREE_TYPE (t), v, a);
10008 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
10009 false, GSI_CONTINUE_LINKING);
10010 assign_stmt = gimple_build_assign (dest, t);
10011 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10012 }
10013 if (fd->collapse > 1)
10014 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
10015
10016 if (!broken_loop)
10017 {
10018 /* The code controlling the sequential loop goes in CONT_BB,
10019 replacing the GIMPLE_OMP_CONTINUE. */
10020 gsi = gsi_last_bb (cont_bb);
10021 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
10022 vmain = gimple_omp_continue_control_use (cont_stmt);
10023 vback = gimple_omp_continue_control_def (cont_stmt);
10024
10025 if (!gimple_omp_for_combined_p (fd->for_stmt))
10026 {
10027 if (POINTER_TYPE_P (type))
10028 t = fold_build_pointer_plus (vmain, step);
10029 else
10030 t = fold_build2 (PLUS_EXPR, type, vmain, step);
10031 if (DECL_P (vback) && TREE_ADDRESSABLE (vback))
10032 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
10033 true, GSI_SAME_STMT);
10034 assign_stmt = gimple_build_assign (vback, t);
10035 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
10036
10037 if (tree_int_cst_equal (fd->chunk_size, integer_one_node))
10038 t = build2 (EQ_EXPR, boolean_type_node,
10039 build_int_cst (itype, 0),
10040 build_int_cst (itype, 1));
10041 else
10042 t = build2 (fd->loop.cond_code, boolean_type_node,
10043 DECL_P (vback) && TREE_ADDRESSABLE (vback)
10044 ? t : vback, e);
10045 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
10046 }
10047
10048 /* Remove GIMPLE_OMP_CONTINUE. */
10049 gsi_remove (&gsi, true);
10050
10051 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
10052 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
10053
10054 /* Trip update code goes into TRIP_UPDATE_BB. */
10055 gsi = gsi_start_bb (trip_update_bb);
10056
10057 t = build_int_cst (itype, 1);
10058 t = build2 (PLUS_EXPR, itype, trip_main, t);
10059 assign_stmt = gimple_build_assign (trip_back, t);
10060 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10061 }
10062
10063 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
10064 gsi = gsi_last_bb (exit_bb);
10065 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
10066 {
10067 t = gimple_omp_return_lhs (gsi_stmt (gsi));
10068 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
10069 }
10070 gsi_remove (&gsi, true);
10071
10072 /* Connect the new blocks. */
10073 find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
10074 find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
10075
10076 if (!broken_loop)
10077 {
10078 se = find_edge (cont_bb, body_bb);
10079 if (se == NULL)
10080 {
10081 se = BRANCH_EDGE (cont_bb);
10082 gcc_assert (single_succ (se->dest) == body_bb);
10083 }
10084 if (gimple_omp_for_combined_p (fd->for_stmt))
10085 {
10086 remove_edge (se);
10087 se = NULL;
10088 }
10089 else if (fd->collapse > 1)
10090 {
10091 remove_edge (se);
10092 se = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
10093 }
10094 else
10095 se->flags = EDGE_TRUE_VALUE;
10096 find_edge (cont_bb, trip_update_bb)->flags
10097 = se ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
10098
10099 redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb);
10100 }
10101
10102 if (gimple_in_ssa_p (cfun))
10103 {
10104 gphi_iterator psi;
10105 gphi *phi;
10106 edge re, ene;
10107 edge_var_map *vm;
10108 size_t i;
10109
10110 gcc_assert (fd->collapse == 1 && !broken_loop);
10111
10112 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
10113 remove arguments of the phi nodes in fin_bb. We need to create
10114 appropriate phi nodes in iter_part_bb instead. */
10115 se = find_edge (iter_part_bb, fin_bb);
10116 re = single_succ_edge (trip_update_bb);
10117 vec<edge_var_map> *head = redirect_edge_var_map_vector (re);
10118 ene = single_succ_edge (entry_bb);
10119
10120 psi = gsi_start_phis (fin_bb);
10121 for (i = 0; !gsi_end_p (psi) && head->iterate (i, &vm);
10122 gsi_next (&psi), ++i)
10123 {
10124 gphi *nphi;
10125 source_location locus;
10126
10127 phi = psi.phi ();
10128 t = gimple_phi_result (phi);
10129 gcc_assert (t == redirect_edge_var_map_result (vm));
10130
10131 if (!single_pred_p (fin_bb))
10132 t = copy_ssa_name (t, phi);
10133
10134 nphi = create_phi_node (t, iter_part_bb);
10135
10136 t = PHI_ARG_DEF_FROM_EDGE (phi, se);
10137 locus = gimple_phi_arg_location_from_edge (phi, se);
10138
10139 /* A special case -- fd->loop.v is not yet computed in
10140 iter_part_bb, we need to use vextra instead. */
10141 if (t == fd->loop.v)
10142 t = vextra;
10143 add_phi_arg (nphi, t, ene, locus);
10144 locus = redirect_edge_var_map_location (vm);
10145 tree back_arg = redirect_edge_var_map_def (vm);
10146 add_phi_arg (nphi, back_arg, re, locus);
10147 edge ce = find_edge (cont_bb, body_bb);
10148 if (ce == NULL)
10149 {
10150 ce = BRANCH_EDGE (cont_bb);
10151 gcc_assert (single_succ (ce->dest) == body_bb);
10152 ce = single_succ_edge (ce->dest);
10153 }
10154 gphi *inner_loop_phi = find_phi_with_arg_on_edge (back_arg, ce);
10155 gcc_assert (inner_loop_phi != NULL);
10156 add_phi_arg (inner_loop_phi, gimple_phi_result (nphi),
10157 find_edge (seq_start_bb, body_bb), locus);
10158
10159 if (!single_pred_p (fin_bb))
10160 add_phi_arg (phi, gimple_phi_result (nphi), se, locus);
10161 }
10162 gcc_assert (gsi_end_p (psi) && (head == NULL || i == head->length ()));
10163 redirect_edge_var_map_clear (re);
10164 if (single_pred_p (fin_bb))
10165 while (1)
10166 {
10167 psi = gsi_start_phis (fin_bb);
10168 if (gsi_end_p (psi))
10169 break;
10170 remove_phi_node (&psi, false);
10171 }
10172
10173 /* Make phi node for trip. */
10174 phi = create_phi_node (trip_main, iter_part_bb);
10175 add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb),
10176 UNKNOWN_LOCATION);
10177 add_phi_arg (phi, trip_init, single_succ_edge (entry_bb),
10178 UNKNOWN_LOCATION);
10179 }
10180
10181 if (!broken_loop)
10182 set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
10183 set_immediate_dominator (CDI_DOMINATORS, iter_part_bb,
10184 recompute_dominator (CDI_DOMINATORS, iter_part_bb));
10185 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
10186 recompute_dominator (CDI_DOMINATORS, fin_bb));
10187 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb,
10188 recompute_dominator (CDI_DOMINATORS, seq_start_bb));
10189 set_immediate_dominator (CDI_DOMINATORS, body_bb,
10190 recompute_dominator (CDI_DOMINATORS, body_bb));
10191
10192 if (!broken_loop)
10193 {
10194 struct loop *loop = body_bb->loop_father;
10195 struct loop *trip_loop = alloc_loop ();
10196 trip_loop->header = iter_part_bb;
10197 trip_loop->latch = trip_update_bb;
10198 add_loop (trip_loop, iter_part_bb->loop_father);
10199
10200 if (loop != entry_bb->loop_father)
10201 {
10202 gcc_assert (loop->header == body_bb);
10203 gcc_assert (loop->latch == region->cont
10204 || single_pred (loop->latch) == region->cont);
10205 trip_loop->inner = loop;
10206 return;
10207 }
10208
10209 if (!gimple_omp_for_combined_p (fd->for_stmt))
10210 {
10211 loop = alloc_loop ();
10212 loop->header = body_bb;
10213 if (collapse_bb == NULL)
10214 loop->latch = cont_bb;
10215 add_loop (loop, trip_loop);
10216 }
10217 }
10218 }
10219
10220 /* A subroutine of expand_omp_for. Generate code for _Cilk_for loop.
10221 Given parameters:
10222 for (V = N1; V cond N2; V += STEP) BODY;
10223
10224 where COND is "<" or ">" or "!=", we generate pseudocode
10225
10226 for (ind_var = low; ind_var < high; ind_var++)
10227 {
10228 V = n1 + (ind_var * STEP)
10229
10230 <BODY>
10231 }
10232
10233 In the above pseudocode, low and high are function parameters of the
10234 child function. In the function below, we are inserting a temp.
10235 variable that will be making a call to two OMP functions that will not be
10236 found in the body of _Cilk_for (since OMP_FOR cannot be mixed
10237 with _Cilk_for). These functions are replaced with low and high
10238 by the function that handles taskreg. */
10239
10240
10241 static void
10242 expand_cilk_for (struct omp_region *region, struct omp_for_data *fd)
10243 {
10244 bool broken_loop = region->cont == NULL;
10245 basic_block entry_bb = region->entry;
10246 basic_block cont_bb = region->cont;
10247
10248 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
10249 gcc_assert (broken_loop
10250 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
10251 basic_block l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
10252 basic_block l1_bb, l2_bb;
10253
10254 if (!broken_loop)
10255 {
10256 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
10257 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
10258 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
10259 l2_bb = BRANCH_EDGE (entry_bb)->dest;
10260 }
10261 else
10262 {
10263 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
10264 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
10265 l2_bb = single_succ (l1_bb);
10266 }
10267 basic_block exit_bb = region->exit;
10268 basic_block l2_dom_bb = NULL;
10269
10270 gimple_stmt_iterator gsi = gsi_last_bb (entry_bb);
10271
10272 /* Below statements until the "tree high_val = ..." are pseudo statements
10273 used to pass information to be used by expand_omp_taskreg.
10274 low_val and high_val will be replaced by the __low and __high
10275 parameter from the child function.
10276
10277 The call_exprs part is a place-holder, it is mainly used
10278 to distinctly identify to the top-level part that this is
10279 where we should put low and high (reasoning given in header
10280 comment). */
10281
10282 tree child_fndecl
10283 = gimple_omp_parallel_child_fn (
10284 as_a <gomp_parallel *> (last_stmt (region->outer->entry)));
10285 tree t, low_val = NULL_TREE, high_val = NULL_TREE;
10286 for (t = DECL_ARGUMENTS (child_fndecl); t; t = TREE_CHAIN (t))
10287 {
10288 if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__high"))
10289 high_val = t;
10290 else if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__low"))
10291 low_val = t;
10292 }
10293 gcc_assert (low_val && high_val);
10294
10295 tree type = TREE_TYPE (low_val);
10296 tree ind_var = create_tmp_reg (type, "__cilk_ind_var");
10297 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
10298
10299 /* Not needed in SSA form right now. */
10300 gcc_assert (!gimple_in_ssa_p (cfun));
10301 if (l2_dom_bb == NULL)
10302 l2_dom_bb = l1_bb;
10303
10304 tree n1 = low_val;
10305 tree n2 = high_val;
10306
10307 gimple *stmt = gimple_build_assign (ind_var, n1);
10308
10309 /* Replace the GIMPLE_OMP_FOR statement. */
10310 gsi_replace (&gsi, stmt, true);
10311
10312 if (!broken_loop)
10313 {
10314 /* Code to control the increment goes in the CONT_BB. */
10315 gsi = gsi_last_bb (cont_bb);
10316 stmt = gsi_stmt (gsi);
10317 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
10318 stmt = gimple_build_assign (ind_var, PLUS_EXPR, ind_var,
10319 build_one_cst (type));
10320
10321 /* Replace GIMPLE_OMP_CONTINUE. */
10322 gsi_replace (&gsi, stmt, true);
10323 }
10324
10325 /* Emit the condition in L1_BB. */
10326 gsi = gsi_after_labels (l1_bb);
10327 t = fold_build2 (MULT_EXPR, TREE_TYPE (fd->loop.step),
10328 fold_convert (TREE_TYPE (fd->loop.step), ind_var),
10329 fd->loop.step);
10330 if (POINTER_TYPE_P (TREE_TYPE (fd->loop.n1)))
10331 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (fd->loop.n1),
10332 fd->loop.n1, fold_convert (sizetype, t));
10333 else
10334 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loop.n1),
10335 fd->loop.n1, fold_convert (TREE_TYPE (fd->loop.n1), t));
10336 t = fold_convert (TREE_TYPE (fd->loop.v), t);
10337 expand_omp_build_assign (&gsi, fd->loop.v, t);
10338
10339 /* The condition is always '<' since the runtime will fill in the low
10340 and high values. */
10341 stmt = gimple_build_cond (LT_EXPR, ind_var, n2, NULL_TREE, NULL_TREE);
10342 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
10343
10344 /* Remove GIMPLE_OMP_RETURN. */
10345 gsi = gsi_last_bb (exit_bb);
10346 gsi_remove (&gsi, true);
10347
10348 /* Connect the new blocks. */
10349 remove_edge (FALLTHRU_EDGE (entry_bb));
10350
10351 edge e, ne;
10352 if (!broken_loop)
10353 {
10354 remove_edge (BRANCH_EDGE (entry_bb));
10355 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
10356
10357 e = BRANCH_EDGE (l1_bb);
10358 ne = FALLTHRU_EDGE (l1_bb);
10359 e->flags = EDGE_TRUE_VALUE;
10360 }
10361 else
10362 {
10363 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
10364
10365 ne = single_succ_edge (l1_bb);
10366 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
10367
10368 }
10369 ne->flags = EDGE_FALSE_VALUE;
10370 e->probability = REG_BR_PROB_BASE * 7 / 8;
10371 ne->probability = REG_BR_PROB_BASE / 8;
10372
10373 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
10374 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
10375 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
10376
10377 if (!broken_loop)
10378 {
10379 struct loop *loop = alloc_loop ();
10380 loop->header = l1_bb;
10381 loop->latch = cont_bb;
10382 add_loop (loop, l1_bb->loop_father);
10383 loop->safelen = INT_MAX;
10384 }
10385
10386 /* Pick the correct library function based on the precision of the
10387 induction variable type. */
10388 tree lib_fun = NULL_TREE;
10389 if (TYPE_PRECISION (type) == 32)
10390 lib_fun = cilk_for_32_fndecl;
10391 else if (TYPE_PRECISION (type) == 64)
10392 lib_fun = cilk_for_64_fndecl;
10393 else
10394 gcc_unreachable ();
10395
10396 gcc_assert (fd->sched_kind == OMP_CLAUSE_SCHEDULE_CILKFOR);
10397
10398 /* WS_ARGS contains the library function flavor to call:
10399 __libcilkrts_cilk_for_64 or __libcilkrts_cilk_for_32), and the
10400 user-defined grain value. If the user does not define one, then zero
10401 is passed in by the parser. */
10402 vec_alloc (region->ws_args, 2);
10403 region->ws_args->quick_push (lib_fun);
10404 region->ws_args->quick_push (fd->chunk_size);
10405 }
10406
10407 /* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
10408 loop. Given parameters:
10409
10410 for (V = N1; V cond N2; V += STEP) BODY;
10411
10412 where COND is "<" or ">", we generate pseudocode
10413
10414 V = N1;
10415 goto L1;
10416 L0:
10417 BODY;
10418 V += STEP;
10419 L1:
10420 if (V cond N2) goto L0; else goto L2;
10421 L2:
10422
10423 For collapsed loops, given parameters:
10424 collapse(3)
10425 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
10426 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
10427 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
10428 BODY;
10429
10430 we generate pseudocode
10431
10432 if (cond3 is <)
10433 adj = STEP3 - 1;
10434 else
10435 adj = STEP3 + 1;
10436 count3 = (adj + N32 - N31) / STEP3;
10437 if (cond2 is <)
10438 adj = STEP2 - 1;
10439 else
10440 adj = STEP2 + 1;
10441 count2 = (adj + N22 - N21) / STEP2;
10442 if (cond1 is <)
10443 adj = STEP1 - 1;
10444 else
10445 adj = STEP1 + 1;
10446 count1 = (adj + N12 - N11) / STEP1;
10447 count = count1 * count2 * count3;
10448 V = 0;
10449 V1 = N11;
10450 V2 = N21;
10451 V3 = N31;
10452 goto L1;
10453 L0:
10454 BODY;
10455 V += 1;
10456 V3 += STEP3;
10457 V2 += (V3 cond3 N32) ? 0 : STEP2;
10458 V3 = (V3 cond3 N32) ? V3 : N31;
10459 V1 += (V2 cond2 N22) ? 0 : STEP1;
10460 V2 = (V2 cond2 N22) ? V2 : N21;
10461 L1:
10462 if (V < count) goto L0; else goto L2;
10463 L2:
10464
10465 */
10466
10467 static void
10468 expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
10469 {
10470 tree type, t;
10471 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, l2_bb, l2_dom_bb;
10472 gimple_stmt_iterator gsi;
10473 gimple *stmt;
10474 gcond *cond_stmt;
10475 bool broken_loop = region->cont == NULL;
10476 edge e, ne;
10477 tree *counts = NULL;
10478 int i;
10479 tree safelen = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
10480 OMP_CLAUSE_SAFELEN);
10481 tree simduid = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
10482 OMP_CLAUSE__SIMDUID_);
10483 tree n1, n2;
10484
10485 type = TREE_TYPE (fd->loop.v);
10486 entry_bb = region->entry;
10487 cont_bb = region->cont;
10488 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
10489 gcc_assert (broken_loop
10490 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
10491 l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
10492 if (!broken_loop)
10493 {
10494 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
10495 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
10496 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
10497 l2_bb = BRANCH_EDGE (entry_bb)->dest;
10498 }
10499 else
10500 {
10501 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
10502 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
10503 l2_bb = single_succ (l1_bb);
10504 }
10505 exit_bb = region->exit;
10506 l2_dom_bb = NULL;
10507
10508 gsi = gsi_last_bb (entry_bb);
10509
10510 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
10511 /* Not needed in SSA form right now. */
10512 gcc_assert (!gimple_in_ssa_p (cfun));
10513 if (fd->collapse > 1)
10514 {
10515 int first_zero_iter = -1, dummy = -1;
10516 basic_block zero_iter_bb = l2_bb, dummy_bb = NULL;
10517
10518 counts = XALLOCAVEC (tree, fd->collapse);
10519 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
10520 zero_iter_bb, first_zero_iter,
10521 dummy_bb, dummy, l2_dom_bb);
10522 }
10523 if (l2_dom_bb == NULL)
10524 l2_dom_bb = l1_bb;
10525
10526 n1 = fd->loop.n1;
10527 n2 = fd->loop.n2;
10528 if (gimple_omp_for_combined_into_p (fd->for_stmt))
10529 {
10530 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
10531 OMP_CLAUSE__LOOPTEMP_);
10532 gcc_assert (innerc);
10533 n1 = OMP_CLAUSE_DECL (innerc);
10534 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
10535 OMP_CLAUSE__LOOPTEMP_);
10536 gcc_assert (innerc);
10537 n2 = OMP_CLAUSE_DECL (innerc);
10538 expand_omp_build_assign (&gsi, fd->loop.v,
10539 fold_convert (type, n1));
10540 if (fd->collapse > 1)
10541 {
10542 gsi_prev (&gsi);
10543 expand_omp_for_init_vars (fd, &gsi, counts, NULL, n1);
10544 gsi_next (&gsi);
10545 }
10546 }
10547 else
10548 {
10549 expand_omp_build_assign (&gsi, fd->loop.v,
10550 fold_convert (type, fd->loop.n1));
10551 if (fd->collapse > 1)
10552 for (i = 0; i < fd->collapse; i++)
10553 {
10554 tree itype = TREE_TYPE (fd->loops[i].v);
10555 if (POINTER_TYPE_P (itype))
10556 itype = signed_type_for (itype);
10557 t = fold_convert (TREE_TYPE (fd->loops[i].v), fd->loops[i].n1);
10558 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
10559 }
10560 }
10561
10562 /* Remove the GIMPLE_OMP_FOR statement. */
10563 gsi_remove (&gsi, true);
10564
10565 if (!broken_loop)
10566 {
10567 /* Code to control the increment goes in the CONT_BB. */
10568 gsi = gsi_last_bb (cont_bb);
10569 stmt = gsi_stmt (gsi);
10570 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
10571
10572 if (POINTER_TYPE_P (type))
10573 t = fold_build_pointer_plus (fd->loop.v, fd->loop.step);
10574 else
10575 t = fold_build2 (PLUS_EXPR, type, fd->loop.v, fd->loop.step);
10576 expand_omp_build_assign (&gsi, fd->loop.v, t);
10577
10578 if (fd->collapse > 1)
10579 {
10580 i = fd->collapse - 1;
10581 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
10582 {
10583 t = fold_convert (sizetype, fd->loops[i].step);
10584 t = fold_build_pointer_plus (fd->loops[i].v, t);
10585 }
10586 else
10587 {
10588 t = fold_convert (TREE_TYPE (fd->loops[i].v),
10589 fd->loops[i].step);
10590 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
10591 fd->loops[i].v, t);
10592 }
10593 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
10594
10595 for (i = fd->collapse - 1; i > 0; i--)
10596 {
10597 tree itype = TREE_TYPE (fd->loops[i].v);
10598 tree itype2 = TREE_TYPE (fd->loops[i - 1].v);
10599 if (POINTER_TYPE_P (itype2))
10600 itype2 = signed_type_for (itype2);
10601 t = build3 (COND_EXPR, itype2,
10602 build2 (fd->loops[i].cond_code, boolean_type_node,
10603 fd->loops[i].v,
10604 fold_convert (itype, fd->loops[i].n2)),
10605 build_int_cst (itype2, 0),
10606 fold_convert (itype2, fd->loops[i - 1].step));
10607 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i - 1].v)))
10608 t = fold_build_pointer_plus (fd->loops[i - 1].v, t);
10609 else
10610 t = fold_build2 (PLUS_EXPR, itype2, fd->loops[i - 1].v, t);
10611 expand_omp_build_assign (&gsi, fd->loops[i - 1].v, t);
10612
10613 t = build3 (COND_EXPR, itype,
10614 build2 (fd->loops[i].cond_code, boolean_type_node,
10615 fd->loops[i].v,
10616 fold_convert (itype, fd->loops[i].n2)),
10617 fd->loops[i].v,
10618 fold_convert (itype, fd->loops[i].n1));
10619 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
10620 }
10621 }
10622
10623 /* Remove GIMPLE_OMP_CONTINUE. */
10624 gsi_remove (&gsi, true);
10625 }
10626
10627 /* Emit the condition in L1_BB. */
10628 gsi = gsi_start_bb (l1_bb);
10629
10630 t = fold_convert (type, n2);
10631 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
10632 false, GSI_CONTINUE_LINKING);
10633 tree v = fd->loop.v;
10634 if (DECL_P (v) && TREE_ADDRESSABLE (v))
10635 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
10636 false, GSI_CONTINUE_LINKING);
10637 t = build2 (fd->loop.cond_code, boolean_type_node, v, t);
10638 cond_stmt = gimple_build_cond_empty (t);
10639 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
10640 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt), expand_omp_regimplify_p,
10641 NULL, NULL)
10642 || walk_tree (gimple_cond_rhs_ptr (cond_stmt), expand_omp_regimplify_p,
10643 NULL, NULL))
10644 {
10645 gsi = gsi_for_stmt (cond_stmt);
10646 gimple_regimplify_operands (cond_stmt, &gsi);
10647 }
10648
10649 /* Remove GIMPLE_OMP_RETURN. */
10650 gsi = gsi_last_bb (exit_bb);
10651 gsi_remove (&gsi, true);
10652
10653 /* Connect the new blocks. */
10654 remove_edge (FALLTHRU_EDGE (entry_bb));
10655
10656 if (!broken_loop)
10657 {
10658 remove_edge (BRANCH_EDGE (entry_bb));
10659 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
10660
10661 e = BRANCH_EDGE (l1_bb);
10662 ne = FALLTHRU_EDGE (l1_bb);
10663 e->flags = EDGE_TRUE_VALUE;
10664 }
10665 else
10666 {
10667 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
10668
10669 ne = single_succ_edge (l1_bb);
10670 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
10671
10672 }
10673 ne->flags = EDGE_FALSE_VALUE;
10674 e->probability = REG_BR_PROB_BASE * 7 / 8;
10675 ne->probability = REG_BR_PROB_BASE / 8;
10676
10677 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
10678 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
10679 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
10680
10681 if (!broken_loop)
10682 {
10683 struct loop *loop = alloc_loop ();
10684 loop->header = l1_bb;
10685 loop->latch = cont_bb;
10686 add_loop (loop, l1_bb->loop_father);
10687 if (safelen == NULL_TREE)
10688 loop->safelen = INT_MAX;
10689 else
10690 {
10691 safelen = OMP_CLAUSE_SAFELEN_EXPR (safelen);
10692 if (TREE_CODE (safelen) != INTEGER_CST)
10693 loop->safelen = 0;
10694 else if (!tree_fits_uhwi_p (safelen)
10695 || tree_to_uhwi (safelen) > INT_MAX)
10696 loop->safelen = INT_MAX;
10697 else
10698 loop->safelen = tree_to_uhwi (safelen);
10699 if (loop->safelen == 1)
10700 loop->safelen = 0;
10701 }
10702 if (simduid)
10703 {
10704 loop->simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
10705 cfun->has_simduid_loops = true;
10706 }
10707 /* If not -fno-tree-loop-vectorize, hint that we want to vectorize
10708 the loop. */
10709 if ((flag_tree_loop_vectorize
10710 || (!global_options_set.x_flag_tree_loop_vectorize
10711 && !global_options_set.x_flag_tree_vectorize))
10712 && flag_tree_loop_optimize
10713 && loop->safelen > 1)
10714 {
10715 loop->force_vectorize = true;
10716 cfun->has_force_vectorize_loops = true;
10717 }
10718 }
10719 else if (simduid)
10720 cfun->has_simduid_loops = true;
10721 }
10722
10723 /* Taskloop construct is represented after gimplification with
10724 two GIMPLE_OMP_FOR constructs with GIMPLE_OMP_TASK sandwiched
10725 in between them. This routine expands the outer GIMPLE_OMP_FOR,
10726 which should just compute all the needed loop temporaries
10727 for GIMPLE_OMP_TASK. */
10728
10729 static void
10730 expand_omp_taskloop_for_outer (struct omp_region *region,
10731 struct omp_for_data *fd,
10732 gimple *inner_stmt)
10733 {
10734 tree type, bias = NULL_TREE;
10735 basic_block entry_bb, cont_bb, exit_bb;
10736 gimple_stmt_iterator gsi;
10737 gassign *assign_stmt;
10738 tree *counts = NULL;
10739 int i;
10740
10741 gcc_assert (inner_stmt);
10742 gcc_assert (region->cont);
10743 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_TASK
10744 && gimple_omp_task_taskloop_p (inner_stmt));
10745 type = TREE_TYPE (fd->loop.v);
10746
10747 /* See if we need to bias by LLONG_MIN. */
10748 if (fd->iter_type == long_long_unsigned_type_node
10749 && TREE_CODE (type) == INTEGER_TYPE
10750 && !TYPE_UNSIGNED (type))
10751 {
10752 tree n1, n2;
10753
10754 if (fd->loop.cond_code == LT_EXPR)
10755 {
10756 n1 = fd->loop.n1;
10757 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
10758 }
10759 else
10760 {
10761 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
10762 n2 = fd->loop.n1;
10763 }
10764 if (TREE_CODE (n1) != INTEGER_CST
10765 || TREE_CODE (n2) != INTEGER_CST
10766 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
10767 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
10768 }
10769
10770 entry_bb = region->entry;
10771 cont_bb = region->cont;
10772 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
10773 gcc_assert (BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
10774 exit_bb = region->exit;
10775
10776 gsi = gsi_last_bb (entry_bb);
10777 gimple *for_stmt = gsi_stmt (gsi);
10778 gcc_assert (gimple_code (for_stmt) == GIMPLE_OMP_FOR);
10779 if (fd->collapse > 1)
10780 {
10781 int first_zero_iter = -1, dummy = -1;
10782 basic_block zero_iter_bb = NULL, dummy_bb = NULL, l2_dom_bb = NULL;
10783
10784 counts = XALLOCAVEC (tree, fd->collapse);
10785 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
10786 zero_iter_bb, first_zero_iter,
10787 dummy_bb, dummy, l2_dom_bb);
10788
10789 if (zero_iter_bb)
10790 {
10791 /* Some counts[i] vars might be uninitialized if
10792 some loop has zero iterations. But the body shouldn't
10793 be executed in that case, so just avoid uninit warnings. */
10794 for (i = first_zero_iter; i < fd->collapse; i++)
10795 if (SSA_VAR_P (counts[i]))
10796 TREE_NO_WARNING (counts[i]) = 1;
10797 gsi_prev (&gsi);
10798 edge e = split_block (entry_bb, gsi_stmt (gsi));
10799 entry_bb = e->dest;
10800 make_edge (zero_iter_bb, entry_bb, EDGE_FALLTHRU);
10801 gsi = gsi_last_bb (entry_bb);
10802 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
10803 get_immediate_dominator (CDI_DOMINATORS,
10804 zero_iter_bb));
10805 }
10806 }
10807
10808 tree t0, t1;
10809 t1 = fd->loop.n2;
10810 t0 = fd->loop.n1;
10811 if (POINTER_TYPE_P (TREE_TYPE (t0))
10812 && TYPE_PRECISION (TREE_TYPE (t0))
10813 != TYPE_PRECISION (fd->iter_type))
10814 {
10815 /* Avoid casting pointers to integer of a different size. */
10816 tree itype = signed_type_for (type);
10817 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
10818 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
10819 }
10820 else
10821 {
10822 t1 = fold_convert (fd->iter_type, t1);
10823 t0 = fold_convert (fd->iter_type, t0);
10824 }
10825 if (bias)
10826 {
10827 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
10828 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
10829 }
10830
10831 tree innerc = find_omp_clause (gimple_omp_task_clauses (inner_stmt),
10832 OMP_CLAUSE__LOOPTEMP_);
10833 gcc_assert (innerc);
10834 tree startvar = OMP_CLAUSE_DECL (innerc);
10835 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc), OMP_CLAUSE__LOOPTEMP_);
10836 gcc_assert (innerc);
10837 tree endvar = OMP_CLAUSE_DECL (innerc);
10838 if (fd->collapse > 1 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
10839 {
10840 gcc_assert (innerc);
10841 for (i = 1; i < fd->collapse; i++)
10842 {
10843 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
10844 OMP_CLAUSE__LOOPTEMP_);
10845 gcc_assert (innerc);
10846 }
10847 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
10848 OMP_CLAUSE__LOOPTEMP_);
10849 if (innerc)
10850 {
10851 /* If needed (inner taskloop has lastprivate clause), propagate
10852 down the total number of iterations. */
10853 tree t = force_gimple_operand_gsi (&gsi, fd->loop.n2, false,
10854 NULL_TREE, false,
10855 GSI_CONTINUE_LINKING);
10856 assign_stmt = gimple_build_assign (OMP_CLAUSE_DECL (innerc), t);
10857 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10858 }
10859 }
10860
10861 t0 = force_gimple_operand_gsi (&gsi, t0, false, NULL_TREE, false,
10862 GSI_CONTINUE_LINKING);
10863 assign_stmt = gimple_build_assign (startvar, t0);
10864 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10865
10866 t1 = force_gimple_operand_gsi (&gsi, t1, false, NULL_TREE, false,
10867 GSI_CONTINUE_LINKING);
10868 assign_stmt = gimple_build_assign (endvar, t1);
10869 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10870 if (fd->collapse > 1)
10871 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
10872
10873 /* Remove the GIMPLE_OMP_FOR statement. */
10874 gsi = gsi_for_stmt (for_stmt);
10875 gsi_remove (&gsi, true);
10876
10877 gsi = gsi_last_bb (cont_bb);
10878 gsi_remove (&gsi, true);
10879
10880 gsi = gsi_last_bb (exit_bb);
10881 gsi_remove (&gsi, true);
10882
10883 FALLTHRU_EDGE (entry_bb)->probability = REG_BR_PROB_BASE;
10884 remove_edge (BRANCH_EDGE (entry_bb));
10885 FALLTHRU_EDGE (cont_bb)->probability = REG_BR_PROB_BASE;
10886 remove_edge (BRANCH_EDGE (cont_bb));
10887 set_immediate_dominator (CDI_DOMINATORS, exit_bb, cont_bb);
10888 set_immediate_dominator (CDI_DOMINATORS, region->entry,
10889 recompute_dominator (CDI_DOMINATORS, region->entry));
10890 }
10891
10892 /* Taskloop construct is represented after gimplification with
10893 two GIMPLE_OMP_FOR constructs with GIMPLE_OMP_TASK sandwiched
10894 in between them. This routine expands the inner GIMPLE_OMP_FOR.
10895 GOMP_taskloop{,_ull} function arranges for each task to be given just
10896 a single range of iterations. */
10897
10898 static void
10899 expand_omp_taskloop_for_inner (struct omp_region *region,
10900 struct omp_for_data *fd,
10901 gimple *inner_stmt)
10902 {
10903 tree e, t, type, itype, vmain, vback, bias = NULL_TREE;
10904 basic_block entry_bb, exit_bb, body_bb, cont_bb, collapse_bb = NULL;
10905 basic_block fin_bb;
10906 gimple_stmt_iterator gsi;
10907 edge ep;
10908 bool broken_loop = region->cont == NULL;
10909 tree *counts = NULL;
10910 tree n1, n2, step;
10911
10912 itype = type = TREE_TYPE (fd->loop.v);
10913 if (POINTER_TYPE_P (type))
10914 itype = signed_type_for (type);
10915
10916 /* See if we need to bias by LLONG_MIN. */
10917 if (fd->iter_type == long_long_unsigned_type_node
10918 && TREE_CODE (type) == INTEGER_TYPE
10919 && !TYPE_UNSIGNED (type))
10920 {
10921 tree n1, n2;
10922
10923 if (fd->loop.cond_code == LT_EXPR)
10924 {
10925 n1 = fd->loop.n1;
10926 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
10927 }
10928 else
10929 {
10930 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
10931 n2 = fd->loop.n1;
10932 }
10933 if (TREE_CODE (n1) != INTEGER_CST
10934 || TREE_CODE (n2) != INTEGER_CST
10935 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
10936 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
10937 }
10938
10939 entry_bb = region->entry;
10940 cont_bb = region->cont;
10941 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
10942 fin_bb = BRANCH_EDGE (entry_bb)->dest;
10943 gcc_assert (broken_loop
10944 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
10945 body_bb = FALLTHRU_EDGE (entry_bb)->dest;
10946 if (!broken_loop)
10947 {
10948 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
10949 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
10950 }
10951 exit_bb = region->exit;
10952
10953 /* Iteration space partitioning goes in ENTRY_BB. */
10954 gsi = gsi_last_bb (entry_bb);
10955 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
10956
10957 if (fd->collapse > 1)
10958 {
10959 int first_zero_iter = -1, dummy = -1;
10960 basic_block l2_dom_bb = NULL, dummy_bb = NULL;
10961
10962 counts = XALLOCAVEC (tree, fd->collapse);
10963 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
10964 fin_bb, first_zero_iter,
10965 dummy_bb, dummy, l2_dom_bb);
10966 t = NULL_TREE;
10967 }
10968 else
10969 t = integer_one_node;
10970
10971 step = fd->loop.step;
10972 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
10973 OMP_CLAUSE__LOOPTEMP_);
10974 gcc_assert (innerc);
10975 n1 = OMP_CLAUSE_DECL (innerc);
10976 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc), OMP_CLAUSE__LOOPTEMP_);
10977 gcc_assert (innerc);
10978 n2 = OMP_CLAUSE_DECL (innerc);
10979 if (bias)
10980 {
10981 n1 = fold_build2 (PLUS_EXPR, fd->iter_type, n1, bias);
10982 n2 = fold_build2 (PLUS_EXPR, fd->iter_type, n2, bias);
10983 }
10984 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
10985 true, NULL_TREE, true, GSI_SAME_STMT);
10986 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
10987 true, NULL_TREE, true, GSI_SAME_STMT);
10988 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
10989 true, NULL_TREE, true, GSI_SAME_STMT);
10990
10991 tree startvar = fd->loop.v;
10992 tree endvar = NULL_TREE;
10993
10994 if (gimple_omp_for_combined_p (fd->for_stmt))
10995 {
10996 tree clauses = gimple_omp_for_clauses (inner_stmt);
10997 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
10998 gcc_assert (innerc);
10999 startvar = OMP_CLAUSE_DECL (innerc);
11000 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
11001 OMP_CLAUSE__LOOPTEMP_);
11002 gcc_assert (innerc);
11003 endvar = OMP_CLAUSE_DECL (innerc);
11004 }
11005 t = fold_convert (TREE_TYPE (startvar), n1);
11006 t = force_gimple_operand_gsi (&gsi, t,
11007 DECL_P (startvar)
11008 && TREE_ADDRESSABLE (startvar),
11009 NULL_TREE, false, GSI_CONTINUE_LINKING);
11010 gimple *assign_stmt = gimple_build_assign (startvar, t);
11011 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
11012
11013 t = fold_convert (TREE_TYPE (startvar), n2);
11014 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
11015 false, GSI_CONTINUE_LINKING);
11016 if (endvar)
11017 {
11018 assign_stmt = gimple_build_assign (endvar, e);
11019 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
11020 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
11021 assign_stmt = gimple_build_assign (fd->loop.v, e);
11022 else
11023 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
11024 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
11025 }
11026 if (fd->collapse > 1)
11027 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
11028
11029 if (!broken_loop)
11030 {
11031 /* The code controlling the sequential loop replaces the
11032 GIMPLE_OMP_CONTINUE. */
11033 gsi = gsi_last_bb (cont_bb);
11034 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
11035 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
11036 vmain = gimple_omp_continue_control_use (cont_stmt);
11037 vback = gimple_omp_continue_control_def (cont_stmt);
11038
11039 if (!gimple_omp_for_combined_p (fd->for_stmt))
11040 {
11041 if (POINTER_TYPE_P (type))
11042 t = fold_build_pointer_plus (vmain, step);
11043 else
11044 t = fold_build2 (PLUS_EXPR, type, vmain, step);
11045 t = force_gimple_operand_gsi (&gsi, t,
11046 DECL_P (vback)
11047 && TREE_ADDRESSABLE (vback),
11048 NULL_TREE, true, GSI_SAME_STMT);
11049 assign_stmt = gimple_build_assign (vback, t);
11050 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
11051
11052 t = build2 (fd->loop.cond_code, boolean_type_node,
11053 DECL_P (vback) && TREE_ADDRESSABLE (vback)
11054 ? t : vback, e);
11055 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
11056 }
11057
11058 /* Remove the GIMPLE_OMP_CONTINUE statement. */
11059 gsi_remove (&gsi, true);
11060
11061 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
11062 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
11063 }
11064
11065 /* Remove the GIMPLE_OMP_FOR statement. */
11066 gsi = gsi_for_stmt (fd->for_stmt);
11067 gsi_remove (&gsi, true);
11068
11069 /* Remove the GIMPLE_OMP_RETURN statement. */
11070 gsi = gsi_last_bb (exit_bb);
11071 gsi_remove (&gsi, true);
11072
11073 FALLTHRU_EDGE (entry_bb)->probability = REG_BR_PROB_BASE;
11074 if (!broken_loop)
11075 remove_edge (BRANCH_EDGE (entry_bb));
11076 else
11077 {
11078 remove_edge_and_dominated_blocks (BRANCH_EDGE (entry_bb));
11079 region->outer->cont = NULL;
11080 }
11081
11082 /* Connect all the blocks. */
11083 if (!broken_loop)
11084 {
11085 ep = find_edge (cont_bb, body_bb);
11086 if (gimple_omp_for_combined_p (fd->for_stmt))
11087 {
11088 remove_edge (ep);
11089 ep = NULL;
11090 }
11091 else if (fd->collapse > 1)
11092 {
11093 remove_edge (ep);
11094 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
11095 }
11096 else
11097 ep->flags = EDGE_TRUE_VALUE;
11098 find_edge (cont_bb, fin_bb)->flags
11099 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
11100 }
11101
11102 set_immediate_dominator (CDI_DOMINATORS, body_bb,
11103 recompute_dominator (CDI_DOMINATORS, body_bb));
11104 if (!broken_loop)
11105 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
11106 recompute_dominator (CDI_DOMINATORS, fin_bb));
11107
11108 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
11109 {
11110 struct loop *loop = alloc_loop ();
11111 loop->header = body_bb;
11112 if (collapse_bb == NULL)
11113 loop->latch = cont_bb;
11114 add_loop (loop, body_bb->loop_father);
11115 }
11116 }
11117
11118 /* A subroutine of expand_omp_for. Generate code for an OpenACC
11119 partitioned loop. The lowering here is abstracted, in that the
11120 loop parameters are passed through internal functions, which are
11121 further lowered by oacc_device_lower, once we get to the target
11122 compiler. The loop is of the form:
11123
11124 for (V = B; V LTGT E; V += S) {BODY}
11125
11126 where LTGT is < or >. We may have a specified chunking size, CHUNKING
11127 (constant 0 for no chunking) and we will have a GWV partitioning
11128 mask, specifying dimensions over which the loop is to be
11129 partitioned (see note below). We generate code that looks like:
11130
11131 <entry_bb> [incoming FALL->body, BRANCH->exit]
11132 typedef signedintify (typeof (V)) T; // underlying signed integral type
11133 T range = E - B;
11134 T chunk_no = 0;
11135 T DIR = LTGT == '<' ? +1 : -1;
11136 T chunk_max = GOACC_LOOP_CHUNK (dir, range, S, CHUNK_SIZE, GWV);
11137 T step = GOACC_LOOP_STEP (dir, range, S, CHUNK_SIZE, GWV);
11138
11139 <head_bb> [created by splitting end of entry_bb]
11140 T offset = GOACC_LOOP_OFFSET (dir, range, S, CHUNK_SIZE, GWV, chunk_no);
11141 T bound = GOACC_LOOP_BOUND (dir, range, S, CHUNK_SIZE, GWV, offset);
11142 if (!(offset LTGT bound)) goto bottom_bb;
11143
11144 <body_bb> [incoming]
11145 V = B + offset;
11146 {BODY}
11147
11148 <cont_bb> [incoming, may == body_bb FALL->exit_bb, BRANCH->body_bb]
11149 offset += step;
11150 if (offset LTGT bound) goto body_bb; [*]
11151
11152 <bottom_bb> [created by splitting start of exit_bb] insert BRANCH->head_bb
11153 chunk_no++;
11154 if (chunk < chunk_max) goto head_bb;
11155
11156 <exit_bb> [incoming]
11157 V = B + ((range -/+ 1) / S +/- 1) * S [*]
11158
11159 [*] Needed if V live at end of loop
11160
11161 Note: CHUNKING & GWV mask are specified explicitly here. This is a
11162 transition, and will be specified by a more general mechanism shortly.
11163 */
11164
11165 static void
11166 expand_oacc_for (struct omp_region *region, struct omp_for_data *fd)
11167 {
11168 tree v = fd->loop.v;
11169 enum tree_code cond_code = fd->loop.cond_code;
11170 enum tree_code plus_code = PLUS_EXPR;
11171
11172 tree chunk_size = integer_minus_one_node;
11173 tree gwv = integer_zero_node;
11174 tree iter_type = TREE_TYPE (v);
11175 tree diff_type = iter_type;
11176 tree plus_type = iter_type;
11177 struct oacc_collapse *counts = NULL;
11178
11179 gcc_checking_assert (gimple_omp_for_kind (fd->for_stmt)
11180 == GF_OMP_FOR_KIND_OACC_LOOP);
11181 gcc_assert (!gimple_omp_for_combined_into_p (fd->for_stmt));
11182 gcc_assert (cond_code == LT_EXPR || cond_code == GT_EXPR);
11183
11184 if (POINTER_TYPE_P (iter_type))
11185 {
11186 plus_code = POINTER_PLUS_EXPR;
11187 plus_type = sizetype;
11188 }
11189 if (POINTER_TYPE_P (diff_type) || TYPE_UNSIGNED (diff_type))
11190 diff_type = signed_type_for (diff_type);
11191
11192 basic_block entry_bb = region->entry; /* BB ending in OMP_FOR */
11193 basic_block exit_bb = region->exit; /* BB ending in OMP_RETURN */
11194 basic_block cont_bb = region->cont; /* BB ending in OMP_CONTINUE */
11195 basic_block bottom_bb = NULL;
11196
11197 /* entry_bb has two sucessors; the branch edge is to the exit
11198 block, fallthrough edge to body. */
11199 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2
11200 && BRANCH_EDGE (entry_bb)->dest == exit_bb);
11201
11202 /* If cont_bb non-NULL, it has 2 successors. The branch successor is
11203 body_bb, or to a block whose only successor is the body_bb. Its
11204 fallthrough successor is the final block (same as the branch
11205 successor of the entry_bb). */
11206 if (cont_bb)
11207 {
11208 basic_block body_bb = FALLTHRU_EDGE (entry_bb)->dest;
11209 basic_block bed = BRANCH_EDGE (cont_bb)->dest;
11210
11211 gcc_assert (FALLTHRU_EDGE (cont_bb)->dest == exit_bb);
11212 gcc_assert (bed == body_bb || single_succ_edge (bed)->dest == body_bb);
11213 }
11214 else
11215 gcc_assert (!gimple_in_ssa_p (cfun));
11216
11217 /* The exit block only has entry_bb and cont_bb as predecessors. */
11218 gcc_assert (EDGE_COUNT (exit_bb->preds) == 1 + (cont_bb != NULL));
11219
11220 tree chunk_no;
11221 tree chunk_max = NULL_TREE;
11222 tree bound, offset;
11223 tree step = create_tmp_var (diff_type, ".step");
11224 bool up = cond_code == LT_EXPR;
11225 tree dir = build_int_cst (diff_type, up ? +1 : -1);
11226 bool chunking = !gimple_in_ssa_p (cfun);;
11227 bool negating;
11228
11229 /* SSA instances. */
11230 tree offset_incr = NULL_TREE;
11231 tree offset_init = NULL_TREE;
11232
11233 gimple_stmt_iterator gsi;
11234 gassign *ass;
11235 gcall *call;
11236 gimple *stmt;
11237 tree expr;
11238 location_t loc;
11239 edge split, be, fte;
11240
11241 /* Split the end of entry_bb to create head_bb. */
11242 split = split_block (entry_bb, last_stmt (entry_bb));
11243 basic_block head_bb = split->dest;
11244 entry_bb = split->src;
11245
11246 /* Chunk setup goes at end of entry_bb, replacing the omp_for. */
11247 gsi = gsi_last_bb (entry_bb);
11248 gomp_for *for_stmt = as_a <gomp_for *> (gsi_stmt (gsi));
11249 loc = gimple_location (for_stmt);
11250
11251 if (gimple_in_ssa_p (cfun))
11252 {
11253 offset_init = gimple_omp_for_index (for_stmt, 0);
11254 gcc_assert (integer_zerop (fd->loop.n1));
11255 /* The SSA parallelizer does gang parallelism. */
11256 gwv = build_int_cst (integer_type_node, GOMP_DIM_MASK (GOMP_DIM_GANG));
11257 }
11258
11259 if (fd->collapse > 1)
11260 {
11261 counts = XALLOCAVEC (struct oacc_collapse, fd->collapse);
11262 tree total = expand_oacc_collapse_init (fd, &gsi, counts,
11263 TREE_TYPE (fd->loop.n2));
11264
11265 if (SSA_VAR_P (fd->loop.n2))
11266 {
11267 total = force_gimple_operand_gsi (&gsi, total, false, NULL_TREE,
11268 true, GSI_SAME_STMT);
11269 ass = gimple_build_assign (fd->loop.n2, total);
11270 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11271 }
11272
11273 }
11274
11275 tree b = fd->loop.n1;
11276 tree e = fd->loop.n2;
11277 tree s = fd->loop.step;
11278
11279 b = force_gimple_operand_gsi (&gsi, b, true, NULL_TREE, true, GSI_SAME_STMT);
11280 e = force_gimple_operand_gsi (&gsi, e, true, NULL_TREE, true, GSI_SAME_STMT);
11281
11282 /* Convert the step, avoiding possible unsigned->signed overflow. */
11283 negating = !up && TYPE_UNSIGNED (TREE_TYPE (s));
11284 if (negating)
11285 s = fold_build1 (NEGATE_EXPR, TREE_TYPE (s), s);
11286 s = fold_convert (diff_type, s);
11287 if (negating)
11288 s = fold_build1 (NEGATE_EXPR, diff_type, s);
11289 s = force_gimple_operand_gsi (&gsi, s, true, NULL_TREE, true, GSI_SAME_STMT);
11290
11291 if (!chunking)
11292 chunk_size = integer_zero_node;
11293 expr = fold_convert (diff_type, chunk_size);
11294 chunk_size = force_gimple_operand_gsi (&gsi, expr, true,
11295 NULL_TREE, true, GSI_SAME_STMT);
11296 /* Determine the range, avoiding possible unsigned->signed overflow. */
11297 negating = !up && TYPE_UNSIGNED (iter_type);
11298 expr = fold_build2 (MINUS_EXPR, plus_type,
11299 fold_convert (plus_type, negating ? b : e),
11300 fold_convert (plus_type, negating ? e : b));
11301 expr = fold_convert (diff_type, expr);
11302 if (negating)
11303 expr = fold_build1 (NEGATE_EXPR, diff_type, expr);
11304 tree range = force_gimple_operand_gsi (&gsi, expr, true,
11305 NULL_TREE, true, GSI_SAME_STMT);
11306
11307 chunk_no = build_int_cst (diff_type, 0);
11308 if (chunking)
11309 {
11310 gcc_assert (!gimple_in_ssa_p (cfun));
11311
11312 expr = chunk_no;
11313 chunk_max = create_tmp_var (diff_type, ".chunk_max");
11314 chunk_no = create_tmp_var (diff_type, ".chunk_no");
11315
11316 ass = gimple_build_assign (chunk_no, expr);
11317 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11318
11319 call = gimple_build_call_internal (IFN_GOACC_LOOP, 6,
11320 build_int_cst (integer_type_node,
11321 IFN_GOACC_LOOP_CHUNKS),
11322 dir, range, s, chunk_size, gwv);
11323 gimple_call_set_lhs (call, chunk_max);
11324 gimple_set_location (call, loc);
11325 gsi_insert_before (&gsi, call, GSI_SAME_STMT);
11326 }
11327 else
11328 chunk_size = chunk_no;
11329
11330 call = gimple_build_call_internal (IFN_GOACC_LOOP, 6,
11331 build_int_cst (integer_type_node,
11332 IFN_GOACC_LOOP_STEP),
11333 dir, range, s, chunk_size, gwv);
11334 gimple_call_set_lhs (call, step);
11335 gimple_set_location (call, loc);
11336 gsi_insert_before (&gsi, call, GSI_SAME_STMT);
11337
11338 /* Remove the GIMPLE_OMP_FOR. */
11339 gsi_remove (&gsi, true);
11340
11341 /* Fixup edges from head_bb */
11342 be = BRANCH_EDGE (head_bb);
11343 fte = FALLTHRU_EDGE (head_bb);
11344 be->flags |= EDGE_FALSE_VALUE;
11345 fte->flags ^= EDGE_FALLTHRU | EDGE_TRUE_VALUE;
11346
11347 basic_block body_bb = fte->dest;
11348
11349 if (gimple_in_ssa_p (cfun))
11350 {
11351 gsi = gsi_last_bb (cont_bb);
11352 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
11353
11354 offset = gimple_omp_continue_control_use (cont_stmt);
11355 offset_incr = gimple_omp_continue_control_def (cont_stmt);
11356 }
11357 else
11358 {
11359 offset = create_tmp_var (diff_type, ".offset");
11360 offset_init = offset_incr = offset;
11361 }
11362 bound = create_tmp_var (TREE_TYPE (offset), ".bound");
11363
11364 /* Loop offset & bound go into head_bb. */
11365 gsi = gsi_start_bb (head_bb);
11366
11367 call = gimple_build_call_internal (IFN_GOACC_LOOP, 7,
11368 build_int_cst (integer_type_node,
11369 IFN_GOACC_LOOP_OFFSET),
11370 dir, range, s,
11371 chunk_size, gwv, chunk_no);
11372 gimple_call_set_lhs (call, offset_init);
11373 gimple_set_location (call, loc);
11374 gsi_insert_after (&gsi, call, GSI_CONTINUE_LINKING);
11375
11376 call = gimple_build_call_internal (IFN_GOACC_LOOP, 7,
11377 build_int_cst (integer_type_node,
11378 IFN_GOACC_LOOP_BOUND),
11379 dir, range, s,
11380 chunk_size, gwv, offset_init);
11381 gimple_call_set_lhs (call, bound);
11382 gimple_set_location (call, loc);
11383 gsi_insert_after (&gsi, call, GSI_CONTINUE_LINKING);
11384
11385 expr = build2 (cond_code, boolean_type_node, offset_init, bound);
11386 gsi_insert_after (&gsi, gimple_build_cond_empty (expr),
11387 GSI_CONTINUE_LINKING);
11388
11389 /* V assignment goes into body_bb. */
11390 if (!gimple_in_ssa_p (cfun))
11391 {
11392 gsi = gsi_start_bb (body_bb);
11393
11394 expr = build2 (plus_code, iter_type, b,
11395 fold_convert (plus_type, offset));
11396 expr = force_gimple_operand_gsi (&gsi, expr, false, NULL_TREE,
11397 true, GSI_SAME_STMT);
11398 ass = gimple_build_assign (v, expr);
11399 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11400 if (fd->collapse > 1)
11401 expand_oacc_collapse_vars (fd, &gsi, counts, v);
11402 }
11403
11404 /* Loop increment goes into cont_bb. If this is not a loop, we
11405 will have spawned threads as if it was, and each one will
11406 execute one iteration. The specification is not explicit about
11407 whether such constructs are ill-formed or not, and they can
11408 occur, especially when noreturn routines are involved. */
11409 if (cont_bb)
11410 {
11411 gsi = gsi_last_bb (cont_bb);
11412 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
11413 loc = gimple_location (cont_stmt);
11414
11415 /* Increment offset. */
11416 if (gimple_in_ssa_p (cfun))
11417 expr= build2 (plus_code, iter_type, offset,
11418 fold_convert (plus_type, step));
11419 else
11420 expr = build2 (PLUS_EXPR, diff_type, offset, step);
11421 expr = force_gimple_operand_gsi (&gsi, expr, false, NULL_TREE,
11422 true, GSI_SAME_STMT);
11423 ass = gimple_build_assign (offset_incr, expr);
11424 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11425 expr = build2 (cond_code, boolean_type_node, offset_incr, bound);
11426 gsi_insert_before (&gsi, gimple_build_cond_empty (expr), GSI_SAME_STMT);
11427
11428 /* Remove the GIMPLE_OMP_CONTINUE. */
11429 gsi_remove (&gsi, true);
11430
11431 /* Fixup edges from cont_bb */
11432 be = BRANCH_EDGE (cont_bb);
11433 fte = FALLTHRU_EDGE (cont_bb);
11434 be->flags |= EDGE_TRUE_VALUE;
11435 fte->flags ^= EDGE_FALLTHRU | EDGE_FALSE_VALUE;
11436
11437 if (chunking)
11438 {
11439 /* Split the beginning of exit_bb to make bottom_bb. We
11440 need to insert a nop at the start, because splitting is
11441 after a stmt, not before. */
11442 gsi = gsi_start_bb (exit_bb);
11443 stmt = gimple_build_nop ();
11444 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
11445 split = split_block (exit_bb, stmt);
11446 bottom_bb = split->src;
11447 exit_bb = split->dest;
11448 gsi = gsi_last_bb (bottom_bb);
11449
11450 /* Chunk increment and test goes into bottom_bb. */
11451 expr = build2 (PLUS_EXPR, diff_type, chunk_no,
11452 build_int_cst (diff_type, 1));
11453 ass = gimple_build_assign (chunk_no, expr);
11454 gsi_insert_after (&gsi, ass, GSI_CONTINUE_LINKING);
11455
11456 /* Chunk test at end of bottom_bb. */
11457 expr = build2 (LT_EXPR, boolean_type_node, chunk_no, chunk_max);
11458 gsi_insert_after (&gsi, gimple_build_cond_empty (expr),
11459 GSI_CONTINUE_LINKING);
11460
11461 /* Fixup edges from bottom_bb. */
11462 split->flags ^= EDGE_FALLTHRU | EDGE_FALSE_VALUE;
11463 make_edge (bottom_bb, head_bb, EDGE_TRUE_VALUE);
11464 }
11465 }
11466
11467 gsi = gsi_last_bb (exit_bb);
11468 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
11469 loc = gimple_location (gsi_stmt (gsi));
11470
11471 if (!gimple_in_ssa_p (cfun))
11472 {
11473 /* Insert the final value of V, in case it is live. This is the
11474 value for the only thread that survives past the join. */
11475 expr = fold_build2 (MINUS_EXPR, diff_type, range, dir);
11476 expr = fold_build2 (PLUS_EXPR, diff_type, expr, s);
11477 expr = fold_build2 (TRUNC_DIV_EXPR, diff_type, expr, s);
11478 expr = fold_build2 (MULT_EXPR, diff_type, expr, s);
11479 expr = build2 (plus_code, iter_type, b, fold_convert (plus_type, expr));
11480 expr = force_gimple_operand_gsi (&gsi, expr, false, NULL_TREE,
11481 true, GSI_SAME_STMT);
11482 ass = gimple_build_assign (v, expr);
11483 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11484 }
11485
11486 /* Remove the OMP_RETURN. */
11487 gsi_remove (&gsi, true);
11488
11489 if (cont_bb)
11490 {
11491 /* We now have one or two nested loops. Update the loop
11492 structures. */
11493 struct loop *parent = entry_bb->loop_father;
11494 struct loop *body = body_bb->loop_father;
11495
11496 if (chunking)
11497 {
11498 struct loop *chunk_loop = alloc_loop ();
11499 chunk_loop->header = head_bb;
11500 chunk_loop->latch = bottom_bb;
11501 add_loop (chunk_loop, parent);
11502 parent = chunk_loop;
11503 }
11504 else if (parent != body)
11505 {
11506 gcc_assert (body->header == body_bb);
11507 gcc_assert (body->latch == cont_bb
11508 || single_pred (body->latch) == cont_bb);
11509 parent = NULL;
11510 }
11511
11512 if (parent)
11513 {
11514 struct loop *body_loop = alloc_loop ();
11515 body_loop->header = body_bb;
11516 body_loop->latch = cont_bb;
11517 add_loop (body_loop, parent);
11518 }
11519 }
11520 }
11521
11522 /* Expand the OMP loop defined by REGION. */
11523
11524 static void
11525 expand_omp_for (struct omp_region *region, gimple *inner_stmt)
11526 {
11527 struct omp_for_data fd;
11528 struct omp_for_data_loop *loops;
11529
11530 loops
11531 = (struct omp_for_data_loop *)
11532 alloca (gimple_omp_for_collapse (last_stmt (region->entry))
11533 * sizeof (struct omp_for_data_loop));
11534 extract_omp_for_data (as_a <gomp_for *> (last_stmt (region->entry)),
11535 &fd, loops);
11536 region->sched_kind = fd.sched_kind;
11537 region->sched_modifiers = fd.sched_modifiers;
11538
11539 gcc_assert (EDGE_COUNT (region->entry->succs) == 2);
11540 BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
11541 FALLTHRU_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
11542 if (region->cont)
11543 {
11544 gcc_assert (EDGE_COUNT (region->cont->succs) == 2);
11545 BRANCH_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
11546 FALLTHRU_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
11547 }
11548 else
11549 /* If there isn't a continue then this is a degerate case where
11550 the introduction of abnormal edges during lowering will prevent
11551 original loops from being detected. Fix that up. */
11552 loops_state_set (LOOPS_NEED_FIXUP);
11553
11554 if (gimple_omp_for_kind (fd.for_stmt) & GF_OMP_FOR_SIMD)
11555 expand_omp_simd (region, &fd);
11556 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
11557 expand_cilk_for (region, &fd);
11558 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
11559 {
11560 gcc_assert (!inner_stmt);
11561 expand_oacc_for (region, &fd);
11562 }
11563 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_TASKLOOP)
11564 {
11565 if (gimple_omp_for_combined_into_p (fd.for_stmt))
11566 expand_omp_taskloop_for_inner (region, &fd, inner_stmt);
11567 else
11568 expand_omp_taskloop_for_outer (region, &fd, inner_stmt);
11569 }
11570 else if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
11571 && !fd.have_ordered)
11572 {
11573 if (fd.chunk_size == NULL)
11574 expand_omp_for_static_nochunk (region, &fd, inner_stmt);
11575 else
11576 expand_omp_for_static_chunk (region, &fd, inner_stmt);
11577 }
11578 else
11579 {
11580 int fn_index, start_ix, next_ix;
11581
11582 gcc_assert (gimple_omp_for_kind (fd.for_stmt)
11583 == GF_OMP_FOR_KIND_FOR);
11584 if (fd.chunk_size == NULL
11585 && fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
11586 fd.chunk_size = integer_zero_node;
11587 gcc_assert (fd.sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
11588 switch (fd.sched_kind)
11589 {
11590 case OMP_CLAUSE_SCHEDULE_RUNTIME:
11591 fn_index = 3;
11592 break;
11593 case OMP_CLAUSE_SCHEDULE_DYNAMIC:
11594 case OMP_CLAUSE_SCHEDULE_GUIDED:
11595 if ((fd.sched_modifiers & OMP_CLAUSE_SCHEDULE_NONMONOTONIC)
11596 && !fd.ordered
11597 && !fd.have_ordered)
11598 {
11599 fn_index = 3 + fd.sched_kind;
11600 break;
11601 }
11602 /* FALLTHRU */
11603 default:
11604 fn_index = fd.sched_kind;
11605 break;
11606 }
11607 if (!fd.ordered)
11608 fn_index += fd.have_ordered * 6;
11609 if (fd.ordered)
11610 start_ix = ((int)BUILT_IN_GOMP_LOOP_DOACROSS_STATIC_START) + fn_index;
11611 else
11612 start_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_START) + fn_index;
11613 next_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT) + fn_index;
11614 if (fd.iter_type == long_long_unsigned_type_node)
11615 {
11616 start_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
11617 - (int)BUILT_IN_GOMP_LOOP_STATIC_START);
11618 next_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
11619 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT);
11620 }
11621 expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
11622 (enum built_in_function) next_ix, inner_stmt);
11623 }
11624
11625 if (gimple_in_ssa_p (cfun))
11626 update_ssa (TODO_update_ssa_only_virtuals);
11627 }
11628
11629
11630 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
11631
11632 v = GOMP_sections_start (n);
11633 L0:
11634 switch (v)
11635 {
11636 case 0:
11637 goto L2;
11638 case 1:
11639 section 1;
11640 goto L1;
11641 case 2:
11642 ...
11643 case n:
11644 ...
11645 default:
11646 abort ();
11647 }
11648 L1:
11649 v = GOMP_sections_next ();
11650 goto L0;
11651 L2:
11652 reduction;
11653
11654 If this is a combined parallel sections, replace the call to
11655 GOMP_sections_start with call to GOMP_sections_next. */
11656
11657 static void
11658 expand_omp_sections (struct omp_region *region)
11659 {
11660 tree t, u, vin = NULL, vmain, vnext, l2;
11661 unsigned len;
11662 basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
11663 gimple_stmt_iterator si, switch_si;
11664 gomp_sections *sections_stmt;
11665 gimple *stmt;
11666 gomp_continue *cont;
11667 edge_iterator ei;
11668 edge e;
11669 struct omp_region *inner;
11670 unsigned i, casei;
11671 bool exit_reachable = region->cont != NULL;
11672
11673 gcc_assert (region->exit != NULL);
11674 entry_bb = region->entry;
11675 l0_bb = single_succ (entry_bb);
11676 l1_bb = region->cont;
11677 l2_bb = region->exit;
11678 if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
11679 l2 = gimple_block_label (l2_bb);
11680 else
11681 {
11682 /* This can happen if there are reductions. */
11683 len = EDGE_COUNT (l0_bb->succs);
11684 gcc_assert (len > 0);
11685 e = EDGE_SUCC (l0_bb, len - 1);
11686 si = gsi_last_bb (e->dest);
11687 l2 = NULL_TREE;
11688 if (gsi_end_p (si)
11689 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
11690 l2 = gimple_block_label (e->dest);
11691 else
11692 FOR_EACH_EDGE (e, ei, l0_bb->succs)
11693 {
11694 si = gsi_last_bb (e->dest);
11695 if (gsi_end_p (si)
11696 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
11697 {
11698 l2 = gimple_block_label (e->dest);
11699 break;
11700 }
11701 }
11702 }
11703 if (exit_reachable)
11704 default_bb = create_empty_bb (l1_bb->prev_bb);
11705 else
11706 default_bb = create_empty_bb (l0_bb);
11707
11708 /* We will build a switch() with enough cases for all the
11709 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
11710 and a default case to abort if something goes wrong. */
11711 len = EDGE_COUNT (l0_bb->succs);
11712
11713 /* Use vec::quick_push on label_vec throughout, since we know the size
11714 in advance. */
11715 auto_vec<tree> label_vec (len);
11716
11717 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
11718 GIMPLE_OMP_SECTIONS statement. */
11719 si = gsi_last_bb (entry_bb);
11720 sections_stmt = as_a <gomp_sections *> (gsi_stmt (si));
11721 gcc_assert (gimple_code (sections_stmt) == GIMPLE_OMP_SECTIONS);
11722 vin = gimple_omp_sections_control (sections_stmt);
11723 if (!is_combined_parallel (region))
11724 {
11725 /* If we are not inside a combined parallel+sections region,
11726 call GOMP_sections_start. */
11727 t = build_int_cst (unsigned_type_node, len - 1);
11728 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START);
11729 stmt = gimple_build_call (u, 1, t);
11730 }
11731 else
11732 {
11733 /* Otherwise, call GOMP_sections_next. */
11734 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
11735 stmt = gimple_build_call (u, 0);
11736 }
11737 gimple_call_set_lhs (stmt, vin);
11738 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
11739 gsi_remove (&si, true);
11740
11741 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
11742 L0_BB. */
11743 switch_si = gsi_last_bb (l0_bb);
11744 gcc_assert (gimple_code (gsi_stmt (switch_si)) == GIMPLE_OMP_SECTIONS_SWITCH);
11745 if (exit_reachable)
11746 {
11747 cont = as_a <gomp_continue *> (last_stmt (l1_bb));
11748 gcc_assert (gimple_code (cont) == GIMPLE_OMP_CONTINUE);
11749 vmain = gimple_omp_continue_control_use (cont);
11750 vnext = gimple_omp_continue_control_def (cont);
11751 }
11752 else
11753 {
11754 vmain = vin;
11755 vnext = NULL_TREE;
11756 }
11757
11758 t = build_case_label (build_int_cst (unsigned_type_node, 0), NULL, l2);
11759 label_vec.quick_push (t);
11760 i = 1;
11761
11762 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
11763 for (inner = region->inner, casei = 1;
11764 inner;
11765 inner = inner->next, i++, casei++)
11766 {
11767 basic_block s_entry_bb, s_exit_bb;
11768
11769 /* Skip optional reduction region. */
11770 if (inner->type == GIMPLE_OMP_ATOMIC_LOAD)
11771 {
11772 --i;
11773 --casei;
11774 continue;
11775 }
11776
11777 s_entry_bb = inner->entry;
11778 s_exit_bb = inner->exit;
11779
11780 t = gimple_block_label (s_entry_bb);
11781 u = build_int_cst (unsigned_type_node, casei);
11782 u = build_case_label (u, NULL, t);
11783 label_vec.quick_push (u);
11784
11785 si = gsi_last_bb (s_entry_bb);
11786 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SECTION);
11787 gcc_assert (i < len || gimple_omp_section_last_p (gsi_stmt (si)));
11788 gsi_remove (&si, true);
11789 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
11790
11791 if (s_exit_bb == NULL)
11792 continue;
11793
11794 si = gsi_last_bb (s_exit_bb);
11795 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
11796 gsi_remove (&si, true);
11797
11798 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
11799 }
11800
11801 /* Error handling code goes in DEFAULT_BB. */
11802 t = gimple_block_label (default_bb);
11803 u = build_case_label (NULL, NULL, t);
11804 make_edge (l0_bb, default_bb, 0);
11805 add_bb_to_loop (default_bb, current_loops->tree_root);
11806
11807 stmt = gimple_build_switch (vmain, u, label_vec);
11808 gsi_insert_after (&switch_si, stmt, GSI_SAME_STMT);
11809 gsi_remove (&switch_si, true);
11810
11811 si = gsi_start_bb (default_bb);
11812 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
11813 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
11814
11815 if (exit_reachable)
11816 {
11817 tree bfn_decl;
11818
11819 /* Code to get the next section goes in L1_BB. */
11820 si = gsi_last_bb (l1_bb);
11821 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
11822
11823 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
11824 stmt = gimple_build_call (bfn_decl, 0);
11825 gimple_call_set_lhs (stmt, vnext);
11826 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
11827 gsi_remove (&si, true);
11828
11829 single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
11830 }
11831
11832 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
11833 si = gsi_last_bb (l2_bb);
11834 if (gimple_omp_return_nowait_p (gsi_stmt (si)))
11835 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
11836 else if (gimple_omp_return_lhs (gsi_stmt (si)))
11837 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL);
11838 else
11839 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
11840 stmt = gimple_build_call (t, 0);
11841 if (gimple_omp_return_lhs (gsi_stmt (si)))
11842 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (si)));
11843 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
11844 gsi_remove (&si, true);
11845
11846 set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
11847 }
11848
11849
11850 /* Expand code for an OpenMP single directive. We've already expanded
11851 much of the code, here we simply place the GOMP_barrier call. */
11852
11853 static void
11854 expand_omp_single (struct omp_region *region)
11855 {
11856 basic_block entry_bb, exit_bb;
11857 gimple_stmt_iterator si;
11858
11859 entry_bb = region->entry;
11860 exit_bb = region->exit;
11861
11862 si = gsi_last_bb (entry_bb);
11863 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE);
11864 gsi_remove (&si, true);
11865 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
11866
11867 si = gsi_last_bb (exit_bb);
11868 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
11869 {
11870 tree t = gimple_omp_return_lhs (gsi_stmt (si));
11871 gsi_insert_after (&si, build_omp_barrier (t), GSI_SAME_STMT);
11872 }
11873 gsi_remove (&si, true);
11874 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
11875 }
11876
11877
11878 /* Generic expansion for OpenMP synchronization directives: master,
11879 ordered and critical. All we need to do here is remove the entry
11880 and exit markers for REGION. */
11881
11882 static void
11883 expand_omp_synch (struct omp_region *region)
11884 {
11885 basic_block entry_bb, exit_bb;
11886 gimple_stmt_iterator si;
11887
11888 entry_bb = region->entry;
11889 exit_bb = region->exit;
11890
11891 si = gsi_last_bb (entry_bb);
11892 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE
11893 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASTER
11894 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TASKGROUP
11895 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ORDERED
11896 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CRITICAL
11897 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TEAMS);
11898 gsi_remove (&si, true);
11899 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
11900
11901 if (exit_bb)
11902 {
11903 si = gsi_last_bb (exit_bb);
11904 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
11905 gsi_remove (&si, true);
11906 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
11907 }
11908 }
11909
11910 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
11911 operation as a normal volatile load. */
11912
11913 static bool
11914 expand_omp_atomic_load (basic_block load_bb, tree addr,
11915 tree loaded_val, int index)
11916 {
11917 enum built_in_function tmpbase;
11918 gimple_stmt_iterator gsi;
11919 basic_block store_bb;
11920 location_t loc;
11921 gimple *stmt;
11922 tree decl, call, type, itype;
11923
11924 gsi = gsi_last_bb (load_bb);
11925 stmt = gsi_stmt (gsi);
11926 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
11927 loc = gimple_location (stmt);
11928
11929 /* ??? If the target does not implement atomic_load_optab[mode], and mode
11930 is smaller than word size, then expand_atomic_load assumes that the load
11931 is atomic. We could avoid the builtin entirely in this case. */
11932
11933 tmpbase = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
11934 decl = builtin_decl_explicit (tmpbase);
11935 if (decl == NULL_TREE)
11936 return false;
11937
11938 type = TREE_TYPE (loaded_val);
11939 itype = TREE_TYPE (TREE_TYPE (decl));
11940
11941 call = build_call_expr_loc (loc, decl, 2, addr,
11942 build_int_cst (NULL,
11943 gimple_omp_atomic_seq_cst_p (stmt)
11944 ? MEMMODEL_SEQ_CST
11945 : MEMMODEL_RELAXED));
11946 if (!useless_type_conversion_p (type, itype))
11947 call = fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
11948 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
11949
11950 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
11951 gsi_remove (&gsi, true);
11952
11953 store_bb = single_succ (load_bb);
11954 gsi = gsi_last_bb (store_bb);
11955 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
11956 gsi_remove (&gsi, true);
11957
11958 if (gimple_in_ssa_p (cfun))
11959 update_ssa (TODO_update_ssa_no_phi);
11960
11961 return true;
11962 }
11963
11964 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
11965 operation as a normal volatile store. */
11966
11967 static bool
11968 expand_omp_atomic_store (basic_block load_bb, tree addr,
11969 tree loaded_val, tree stored_val, int index)
11970 {
11971 enum built_in_function tmpbase;
11972 gimple_stmt_iterator gsi;
11973 basic_block store_bb = single_succ (load_bb);
11974 location_t loc;
11975 gimple *stmt;
11976 tree decl, call, type, itype;
11977 machine_mode imode;
11978 bool exchange;
11979
11980 gsi = gsi_last_bb (load_bb);
11981 stmt = gsi_stmt (gsi);
11982 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
11983
11984 /* If the load value is needed, then this isn't a store but an exchange. */
11985 exchange = gimple_omp_atomic_need_value_p (stmt);
11986
11987 gsi = gsi_last_bb (store_bb);
11988 stmt = gsi_stmt (gsi);
11989 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE);
11990 loc = gimple_location (stmt);
11991
11992 /* ??? If the target does not implement atomic_store_optab[mode], and mode
11993 is smaller than word size, then expand_atomic_store assumes that the store
11994 is atomic. We could avoid the builtin entirely in this case. */
11995
11996 tmpbase = (exchange ? BUILT_IN_ATOMIC_EXCHANGE_N : BUILT_IN_ATOMIC_STORE_N);
11997 tmpbase = (enum built_in_function) ((int) tmpbase + index + 1);
11998 decl = builtin_decl_explicit (tmpbase);
11999 if (decl == NULL_TREE)
12000 return false;
12001
12002 type = TREE_TYPE (stored_val);
12003
12004 /* Dig out the type of the function's second argument. */
12005 itype = TREE_TYPE (decl);
12006 itype = TYPE_ARG_TYPES (itype);
12007 itype = TREE_CHAIN (itype);
12008 itype = TREE_VALUE (itype);
12009 imode = TYPE_MODE (itype);
12010
12011 if (exchange && !can_atomic_exchange_p (imode, true))
12012 return false;
12013
12014 if (!useless_type_conversion_p (itype, type))
12015 stored_val = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, stored_val);
12016 call = build_call_expr_loc (loc, decl, 3, addr, stored_val,
12017 build_int_cst (NULL,
12018 gimple_omp_atomic_seq_cst_p (stmt)
12019 ? MEMMODEL_SEQ_CST
12020 : MEMMODEL_RELAXED));
12021 if (exchange)
12022 {
12023 if (!useless_type_conversion_p (type, itype))
12024 call = build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
12025 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
12026 }
12027
12028 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
12029 gsi_remove (&gsi, true);
12030
12031 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
12032 gsi = gsi_last_bb (load_bb);
12033 gsi_remove (&gsi, true);
12034
12035 if (gimple_in_ssa_p (cfun))
12036 update_ssa (TODO_update_ssa_no_phi);
12037
12038 return true;
12039 }
12040
12041 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
12042 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
12043 size of the data type, and thus usable to find the index of the builtin
12044 decl. Returns false if the expression is not of the proper form. */
12045
12046 static bool
12047 expand_omp_atomic_fetch_op (basic_block load_bb,
12048 tree addr, tree loaded_val,
12049 tree stored_val, int index)
12050 {
12051 enum built_in_function oldbase, newbase, tmpbase;
12052 tree decl, itype, call;
12053 tree lhs, rhs;
12054 basic_block store_bb = single_succ (load_bb);
12055 gimple_stmt_iterator gsi;
12056 gimple *stmt;
12057 location_t loc;
12058 enum tree_code code;
12059 bool need_old, need_new;
12060 machine_mode imode;
12061 bool seq_cst;
12062
12063 /* We expect to find the following sequences:
12064
12065 load_bb:
12066 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
12067
12068 store_bb:
12069 val = tmp OP something; (or: something OP tmp)
12070 GIMPLE_OMP_STORE (val)
12071
12072 ???FIXME: Allow a more flexible sequence.
12073 Perhaps use data flow to pick the statements.
12074
12075 */
12076
12077 gsi = gsi_after_labels (store_bb);
12078 stmt = gsi_stmt (gsi);
12079 loc = gimple_location (stmt);
12080 if (!is_gimple_assign (stmt))
12081 return false;
12082 gsi_next (&gsi);
12083 if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE)
12084 return false;
12085 need_new = gimple_omp_atomic_need_value_p (gsi_stmt (gsi));
12086 need_old = gimple_omp_atomic_need_value_p (last_stmt (load_bb));
12087 seq_cst = gimple_omp_atomic_seq_cst_p (last_stmt (load_bb));
12088 gcc_checking_assert (!need_old || !need_new);
12089
12090 if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
12091 return false;
12092
12093 /* Check for one of the supported fetch-op operations. */
12094 code = gimple_assign_rhs_code (stmt);
12095 switch (code)
12096 {
12097 case PLUS_EXPR:
12098 case POINTER_PLUS_EXPR:
12099 oldbase = BUILT_IN_ATOMIC_FETCH_ADD_N;
12100 newbase = BUILT_IN_ATOMIC_ADD_FETCH_N;
12101 break;
12102 case MINUS_EXPR:
12103 oldbase = BUILT_IN_ATOMIC_FETCH_SUB_N;
12104 newbase = BUILT_IN_ATOMIC_SUB_FETCH_N;
12105 break;
12106 case BIT_AND_EXPR:
12107 oldbase = BUILT_IN_ATOMIC_FETCH_AND_N;
12108 newbase = BUILT_IN_ATOMIC_AND_FETCH_N;
12109 break;
12110 case BIT_IOR_EXPR:
12111 oldbase = BUILT_IN_ATOMIC_FETCH_OR_N;
12112 newbase = BUILT_IN_ATOMIC_OR_FETCH_N;
12113 break;
12114 case BIT_XOR_EXPR:
12115 oldbase = BUILT_IN_ATOMIC_FETCH_XOR_N;
12116 newbase = BUILT_IN_ATOMIC_XOR_FETCH_N;
12117 break;
12118 default:
12119 return false;
12120 }
12121
12122 /* Make sure the expression is of the proper form. */
12123 if (operand_equal_p (gimple_assign_rhs1 (stmt), loaded_val, 0))
12124 rhs = gimple_assign_rhs2 (stmt);
12125 else if (commutative_tree_code (gimple_assign_rhs_code (stmt))
12126 && operand_equal_p (gimple_assign_rhs2 (stmt), loaded_val, 0))
12127 rhs = gimple_assign_rhs1 (stmt);
12128 else
12129 return false;
12130
12131 tmpbase = ((enum built_in_function)
12132 ((need_new ? newbase : oldbase) + index + 1));
12133 decl = builtin_decl_explicit (tmpbase);
12134 if (decl == NULL_TREE)
12135 return false;
12136 itype = TREE_TYPE (TREE_TYPE (decl));
12137 imode = TYPE_MODE (itype);
12138
12139 /* We could test all of the various optabs involved, but the fact of the
12140 matter is that (with the exception of i486 vs i586 and xadd) all targets
12141 that support any atomic operaton optab also implements compare-and-swap.
12142 Let optabs.c take care of expanding any compare-and-swap loop. */
12143 if (!can_compare_and_swap_p (imode, true))
12144 return false;
12145
12146 gsi = gsi_last_bb (load_bb);
12147 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
12148
12149 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
12150 It only requires that the operation happen atomically. Thus we can
12151 use the RELAXED memory model. */
12152 call = build_call_expr_loc (loc, decl, 3, addr,
12153 fold_convert_loc (loc, itype, rhs),
12154 build_int_cst (NULL,
12155 seq_cst ? MEMMODEL_SEQ_CST
12156 : MEMMODEL_RELAXED));
12157
12158 if (need_old || need_new)
12159 {
12160 lhs = need_old ? loaded_val : stored_val;
12161 call = fold_convert_loc (loc, TREE_TYPE (lhs), call);
12162 call = build2_loc (loc, MODIFY_EXPR, void_type_node, lhs, call);
12163 }
12164 else
12165 call = fold_convert_loc (loc, void_type_node, call);
12166 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
12167 gsi_remove (&gsi, true);
12168
12169 gsi = gsi_last_bb (store_bb);
12170 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
12171 gsi_remove (&gsi, true);
12172 gsi = gsi_last_bb (store_bb);
12173 stmt = gsi_stmt (gsi);
12174 gsi_remove (&gsi, true);
12175
12176 if (gimple_in_ssa_p (cfun))
12177 {
12178 release_defs (stmt);
12179 update_ssa (TODO_update_ssa_no_phi);
12180 }
12181
12182 return true;
12183 }
12184
12185 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
12186
12187 oldval = *addr;
12188 repeat:
12189 newval = rhs; // with oldval replacing *addr in rhs
12190 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
12191 if (oldval != newval)
12192 goto repeat;
12193
12194 INDEX is log2 of the size of the data type, and thus usable to find the
12195 index of the builtin decl. */
12196
12197 static bool
12198 expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
12199 tree addr, tree loaded_val, tree stored_val,
12200 int index)
12201 {
12202 tree loadedi, storedi, initial, new_storedi, old_vali;
12203 tree type, itype, cmpxchg, iaddr;
12204 gimple_stmt_iterator si;
12205 basic_block loop_header = single_succ (load_bb);
12206 gimple *phi, *stmt;
12207 edge e;
12208 enum built_in_function fncode;
12209
12210 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
12211 order to use the RELAXED memory model effectively. */
12212 fncode = (enum built_in_function)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
12213 + index + 1);
12214 cmpxchg = builtin_decl_explicit (fncode);
12215 if (cmpxchg == NULL_TREE)
12216 return false;
12217 type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
12218 itype = TREE_TYPE (TREE_TYPE (cmpxchg));
12219
12220 if (!can_compare_and_swap_p (TYPE_MODE (itype), true))
12221 return false;
12222
12223 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
12224 si = gsi_last_bb (load_bb);
12225 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
12226
12227 /* For floating-point values, we'll need to view-convert them to integers
12228 so that we can perform the atomic compare and swap. Simplify the
12229 following code by always setting up the "i"ntegral variables. */
12230 if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
12231 {
12232 tree iaddr_val;
12233
12234 iaddr = create_tmp_reg (build_pointer_type_for_mode (itype, ptr_mode,
12235 true));
12236 iaddr_val
12237 = force_gimple_operand_gsi (&si,
12238 fold_convert (TREE_TYPE (iaddr), addr),
12239 false, NULL_TREE, true, GSI_SAME_STMT);
12240 stmt = gimple_build_assign (iaddr, iaddr_val);
12241 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
12242 loadedi = create_tmp_var (itype);
12243 if (gimple_in_ssa_p (cfun))
12244 loadedi = make_ssa_name (loadedi);
12245 }
12246 else
12247 {
12248 iaddr = addr;
12249 loadedi = loaded_val;
12250 }
12251
12252 fncode = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
12253 tree loaddecl = builtin_decl_explicit (fncode);
12254 if (loaddecl)
12255 initial
12256 = fold_convert (TREE_TYPE (TREE_TYPE (iaddr)),
12257 build_call_expr (loaddecl, 2, iaddr,
12258 build_int_cst (NULL_TREE,
12259 MEMMODEL_RELAXED)));
12260 else
12261 initial = build2 (MEM_REF, TREE_TYPE (TREE_TYPE (iaddr)), iaddr,
12262 build_int_cst (TREE_TYPE (iaddr), 0));
12263
12264 initial
12265 = force_gimple_operand_gsi (&si, initial, true, NULL_TREE, true,
12266 GSI_SAME_STMT);
12267
12268 /* Move the value to the LOADEDI temporary. */
12269 if (gimple_in_ssa_p (cfun))
12270 {
12271 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header)));
12272 phi = create_phi_node (loadedi, loop_header);
12273 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)),
12274 initial);
12275 }
12276 else
12277 gsi_insert_before (&si,
12278 gimple_build_assign (loadedi, initial),
12279 GSI_SAME_STMT);
12280 if (loadedi != loaded_val)
12281 {
12282 gimple_stmt_iterator gsi2;
12283 tree x;
12284
12285 x = build1 (VIEW_CONVERT_EXPR, type, loadedi);
12286 gsi2 = gsi_start_bb (loop_header);
12287 if (gimple_in_ssa_p (cfun))
12288 {
12289 gassign *stmt;
12290 x = force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
12291 true, GSI_SAME_STMT);
12292 stmt = gimple_build_assign (loaded_val, x);
12293 gsi_insert_before (&gsi2, stmt, GSI_SAME_STMT);
12294 }
12295 else
12296 {
12297 x = build2 (MODIFY_EXPR, TREE_TYPE (loaded_val), loaded_val, x);
12298 force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
12299 true, GSI_SAME_STMT);
12300 }
12301 }
12302 gsi_remove (&si, true);
12303
12304 si = gsi_last_bb (store_bb);
12305 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
12306
12307 if (iaddr == addr)
12308 storedi = stored_val;
12309 else
12310 storedi =
12311 force_gimple_operand_gsi (&si,
12312 build1 (VIEW_CONVERT_EXPR, itype,
12313 stored_val), true, NULL_TREE, true,
12314 GSI_SAME_STMT);
12315
12316 /* Build the compare&swap statement. */
12317 new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi);
12318 new_storedi = force_gimple_operand_gsi (&si,
12319 fold_convert (TREE_TYPE (loadedi),
12320 new_storedi),
12321 true, NULL_TREE,
12322 true, GSI_SAME_STMT);
12323
12324 if (gimple_in_ssa_p (cfun))
12325 old_vali = loadedi;
12326 else
12327 {
12328 old_vali = create_tmp_var (TREE_TYPE (loadedi));
12329 stmt = gimple_build_assign (old_vali, loadedi);
12330 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
12331
12332 stmt = gimple_build_assign (loadedi, new_storedi);
12333 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
12334 }
12335
12336 /* Note that we always perform the comparison as an integer, even for
12337 floating point. This allows the atomic operation to properly
12338 succeed even with NaNs and -0.0. */
12339 stmt = gimple_build_cond_empty
12340 (build2 (NE_EXPR, boolean_type_node,
12341 new_storedi, old_vali));
12342 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
12343
12344 /* Update cfg. */
12345 e = single_succ_edge (store_bb);
12346 e->flags &= ~EDGE_FALLTHRU;
12347 e->flags |= EDGE_FALSE_VALUE;
12348
12349 e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE);
12350
12351 /* Copy the new value to loadedi (we already did that before the condition
12352 if we are not in SSA). */
12353 if (gimple_in_ssa_p (cfun))
12354 {
12355 phi = gimple_seq_first_stmt (phi_nodes (loop_header));
12356 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), new_storedi);
12357 }
12358
12359 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
12360 gsi_remove (&si, true);
12361
12362 struct loop *loop = alloc_loop ();
12363 loop->header = loop_header;
12364 loop->latch = store_bb;
12365 add_loop (loop, loop_header->loop_father);
12366
12367 if (gimple_in_ssa_p (cfun))
12368 update_ssa (TODO_update_ssa_no_phi);
12369
12370 return true;
12371 }
12372
12373 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
12374
12375 GOMP_atomic_start ();
12376 *addr = rhs;
12377 GOMP_atomic_end ();
12378
12379 The result is not globally atomic, but works so long as all parallel
12380 references are within #pragma omp atomic directives. According to
12381 responses received from omp@openmp.org, appears to be within spec.
12382 Which makes sense, since that's how several other compilers handle
12383 this situation as well.
12384 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
12385 expanding. STORED_VAL is the operand of the matching
12386 GIMPLE_OMP_ATOMIC_STORE.
12387
12388 We replace
12389 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
12390 loaded_val = *addr;
12391
12392 and replace
12393 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
12394 *addr = stored_val;
12395 */
12396
12397 static bool
12398 expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
12399 tree addr, tree loaded_val, tree stored_val)
12400 {
12401 gimple_stmt_iterator si;
12402 gassign *stmt;
12403 tree t;
12404
12405 si = gsi_last_bb (load_bb);
12406 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
12407
12408 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
12409 t = build_call_expr (t, 0);
12410 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
12411
12412 stmt = gimple_build_assign (loaded_val, build_simple_mem_ref (addr));
12413 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
12414 gsi_remove (&si, true);
12415
12416 si = gsi_last_bb (store_bb);
12417 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
12418
12419 stmt = gimple_build_assign (build_simple_mem_ref (unshare_expr (addr)),
12420 stored_val);
12421 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
12422
12423 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
12424 t = build_call_expr (t, 0);
12425 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
12426 gsi_remove (&si, true);
12427
12428 if (gimple_in_ssa_p (cfun))
12429 update_ssa (TODO_update_ssa_no_phi);
12430 return true;
12431 }
12432
12433 /* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
12434 using expand_omp_atomic_fetch_op. If it failed, we try to
12435 call expand_omp_atomic_pipeline, and if it fails too, the
12436 ultimate fallback is wrapping the operation in a mutex
12437 (expand_omp_atomic_mutex). REGION is the atomic region built
12438 by build_omp_regions_1(). */
12439
12440 static void
12441 expand_omp_atomic (struct omp_region *region)
12442 {
12443 basic_block load_bb = region->entry, store_bb = region->exit;
12444 gomp_atomic_load *load = as_a <gomp_atomic_load *> (last_stmt (load_bb));
12445 gomp_atomic_store *store = as_a <gomp_atomic_store *> (last_stmt (store_bb));
12446 tree loaded_val = gimple_omp_atomic_load_lhs (load);
12447 tree addr = gimple_omp_atomic_load_rhs (load);
12448 tree stored_val = gimple_omp_atomic_store_val (store);
12449 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
12450 HOST_WIDE_INT index;
12451
12452 /* Make sure the type is one of the supported sizes. */
12453 index = tree_to_uhwi (TYPE_SIZE_UNIT (type));
12454 index = exact_log2 (index);
12455 if (index >= 0 && index <= 4)
12456 {
12457 unsigned int align = TYPE_ALIGN_UNIT (type);
12458
12459 /* __sync builtins require strict data alignment. */
12460 if (exact_log2 (align) >= index)
12461 {
12462 /* Atomic load. */
12463 if (loaded_val == stored_val
12464 && (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
12465 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
12466 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
12467 && expand_omp_atomic_load (load_bb, addr, loaded_val, index))
12468 return;
12469
12470 /* Atomic store. */
12471 if ((GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
12472 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
12473 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
12474 && store_bb == single_succ (load_bb)
12475 && first_stmt (store_bb) == store
12476 && expand_omp_atomic_store (load_bb, addr, loaded_val,
12477 stored_val, index))
12478 return;
12479
12480 /* When possible, use specialized atomic update functions. */
12481 if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
12482 && store_bb == single_succ (load_bb)
12483 && expand_omp_atomic_fetch_op (load_bb, addr,
12484 loaded_val, stored_val, index))
12485 return;
12486
12487 /* If we don't have specialized __sync builtins, try and implement
12488 as a compare and swap loop. */
12489 if (expand_omp_atomic_pipeline (load_bb, store_bb, addr,
12490 loaded_val, stored_val, index))
12491 return;
12492 }
12493 }
12494
12495 /* The ultimate fallback is wrapping the operation in a mutex. */
12496 expand_omp_atomic_mutex (load_bb, store_bb, addr, loaded_val, stored_val);
12497 }
12498
12499
12500 /* Encode an oacc launch argument. This matches the GOMP_LAUNCH_PACK
12501 macro on gomp-constants.h. We do not check for overflow. */
12502
12503 static tree
12504 oacc_launch_pack (unsigned code, tree device, unsigned op)
12505 {
12506 tree res;
12507
12508 res = build_int_cst (unsigned_type_node, GOMP_LAUNCH_PACK (code, 0, op));
12509 if (device)
12510 {
12511 device = fold_build2 (LSHIFT_EXPR, unsigned_type_node,
12512 device, build_int_cst (unsigned_type_node,
12513 GOMP_LAUNCH_DEVICE_SHIFT));
12514 res = fold_build2 (BIT_IOR_EXPR, unsigned_type_node, res, device);
12515 }
12516 return res;
12517 }
12518
12519 /* Look for compute grid dimension clauses and convert to an attribute
12520 attached to FN. This permits the target-side code to (a) massage
12521 the dimensions, (b) emit that data and (c) optimize. Non-constant
12522 dimensions are pushed onto ARGS.
12523
12524 The attribute value is a TREE_LIST. A set of dimensions is
12525 represented as a list of INTEGER_CST. Those that are runtime
12526 exprs are represented as an INTEGER_CST of zero.
12527
12528 TOOO. Normally the attribute will just contain a single such list. If
12529 however it contains a list of lists, this will represent the use of
12530 device_type. Each member of the outer list is an assoc list of
12531 dimensions, keyed by the device type. The first entry will be the
12532 default. Well, that's the plan. */
12533
12534 #define OACC_FN_ATTRIB "oacc function"
12535
12536 /* Replace any existing oacc fn attribute with updated dimensions. */
12537
12538 void
12539 replace_oacc_fn_attrib (tree fn, tree dims)
12540 {
12541 tree ident = get_identifier (OACC_FN_ATTRIB);
12542 tree attribs = DECL_ATTRIBUTES (fn);
12543
12544 /* If we happen to be present as the first attrib, drop it. */
12545 if (attribs && TREE_PURPOSE (attribs) == ident)
12546 attribs = TREE_CHAIN (attribs);
12547 DECL_ATTRIBUTES (fn) = tree_cons (ident, dims, attribs);
12548 }
12549
12550 /* Scan CLAUSES for launch dimensions and attach them to the oacc
12551 function attribute. Push any that are non-constant onto the ARGS
12552 list, along with an appropriate GOMP_LAUNCH_DIM tag. IS_KERNEL is
12553 true, if these are for a kernels region offload function. */
12554
12555 void
12556 set_oacc_fn_attrib (tree fn, tree clauses, bool is_kernel, vec<tree> *args)
12557 {
12558 /* Must match GOMP_DIM ordering. */
12559 static const omp_clause_code ids[]
12560 = { OMP_CLAUSE_NUM_GANGS, OMP_CLAUSE_NUM_WORKERS,
12561 OMP_CLAUSE_VECTOR_LENGTH };
12562 unsigned ix;
12563 tree dims[GOMP_DIM_MAX];
12564 tree attr = NULL_TREE;
12565 unsigned non_const = 0;
12566
12567 for (ix = GOMP_DIM_MAX; ix--;)
12568 {
12569 tree clause = find_omp_clause (clauses, ids[ix]);
12570 tree dim = NULL_TREE;
12571
12572 if (clause)
12573 dim = OMP_CLAUSE_EXPR (clause, ids[ix]);
12574 dims[ix] = dim;
12575 if (dim && TREE_CODE (dim) != INTEGER_CST)
12576 {
12577 dim = integer_zero_node;
12578 non_const |= GOMP_DIM_MASK (ix);
12579 }
12580 attr = tree_cons (NULL_TREE, dim, attr);
12581 /* Note kernelness with TREE_PUBLIC. */
12582 if (is_kernel)
12583 TREE_PUBLIC (attr) = 1;
12584 }
12585
12586 replace_oacc_fn_attrib (fn, attr);
12587
12588 if (non_const)
12589 {
12590 /* Push a dynamic argument set. */
12591 args->safe_push (oacc_launch_pack (GOMP_LAUNCH_DIM,
12592 NULL_TREE, non_const));
12593 for (unsigned ix = 0; ix != GOMP_DIM_MAX; ix++)
12594 if (non_const & GOMP_DIM_MASK (ix))
12595 args->safe_push (dims[ix]);
12596 }
12597 }
12598
12599 /* Process the routine's dimension clauess to generate an attribute
12600 value. Issue diagnostics as appropriate. We default to SEQ
12601 (OpenACC 2.5 clarifies this). All dimensions have a size of zero
12602 (dynamic). TREE_PURPOSE is set to indicate whether that dimension
12603 can have a loop partitioned on it. non-zero indicates
12604 yes, zero indicates no. By construction once a non-zero has been
12605 reached, further inner dimensions must also be non-zero. We set
12606 TREE_VALUE to zero for the dimensions that may be partitioned and
12607 1 for the other ones -- if a loop is (erroneously) spawned at
12608 an outer level, we don't want to try and partition it. */
12609
12610 tree
12611 build_oacc_routine_dims (tree clauses)
12612 {
12613 /* Must match GOMP_DIM ordering. */
12614 static const omp_clause_code ids[] =
12615 {OMP_CLAUSE_GANG, OMP_CLAUSE_WORKER, OMP_CLAUSE_VECTOR, OMP_CLAUSE_SEQ};
12616 int ix;
12617 int level = -1;
12618
12619 for (; clauses; clauses = OMP_CLAUSE_CHAIN (clauses))
12620 for (ix = GOMP_DIM_MAX + 1; ix--;)
12621 if (OMP_CLAUSE_CODE (clauses) == ids[ix])
12622 {
12623 if (level >= 0)
12624 error_at (OMP_CLAUSE_LOCATION (clauses),
12625 "multiple loop axes specified for routine");
12626 level = ix;
12627 break;
12628 }
12629
12630 /* Default to SEQ. */
12631 if (level < 0)
12632 level = GOMP_DIM_MAX;
12633
12634 tree dims = NULL_TREE;
12635
12636 for (ix = GOMP_DIM_MAX; ix--;)
12637 dims = tree_cons (build_int_cst (boolean_type_node, ix >= level),
12638 build_int_cst (integer_type_node, ix < level), dims);
12639
12640 return dims;
12641 }
12642
12643 /* Retrieve the oacc function attrib and return it. Non-oacc
12644 functions will return NULL. */
12645
12646 tree
12647 get_oacc_fn_attrib (tree fn)
12648 {
12649 return lookup_attribute (OACC_FN_ATTRIB, DECL_ATTRIBUTES (fn));
12650 }
12651
12652 /* Return true if this oacc fn attrib is for a kernels offload
12653 region. We use the TREE_PUBLIC flag of each dimension -- only
12654 need to check the first one. */
12655
12656 bool
12657 oacc_fn_attrib_kernels_p (tree attr)
12658 {
12659 return TREE_PUBLIC (TREE_VALUE (attr));
12660 }
12661
12662 /* Return level at which oacc routine may spawn a partitioned loop, or
12663 -1 if it is not a routine (i.e. is an offload fn). */
12664
12665 static int
12666 oacc_fn_attrib_level (tree attr)
12667 {
12668 tree pos = TREE_VALUE (attr);
12669
12670 if (!TREE_PURPOSE (pos))
12671 return -1;
12672
12673 int ix = 0;
12674 for (ix = 0; ix != GOMP_DIM_MAX;
12675 ix++, pos = TREE_CHAIN (pos))
12676 if (!integer_zerop (TREE_PURPOSE (pos)))
12677 break;
12678
12679 return ix;
12680 }
12681
12682 /* Extract an oacc execution dimension from FN. FN must be an
12683 offloaded function or routine that has already had its execution
12684 dimensions lowered to the target-specific values. */
12685
12686 int
12687 get_oacc_fn_dim_size (tree fn, int axis)
12688 {
12689 tree attrs = get_oacc_fn_attrib (fn);
12690
12691 gcc_assert (axis < GOMP_DIM_MAX);
12692
12693 tree dims = TREE_VALUE (attrs);
12694 while (axis--)
12695 dims = TREE_CHAIN (dims);
12696
12697 int size = TREE_INT_CST_LOW (TREE_VALUE (dims));
12698
12699 return size;
12700 }
12701
12702 /* Extract the dimension axis from an IFN_GOACC_DIM_POS or
12703 IFN_GOACC_DIM_SIZE call. */
12704
12705 int
12706 get_oacc_ifn_dim_arg (const gimple *stmt)
12707 {
12708 gcc_checking_assert (gimple_call_internal_fn (stmt) == IFN_GOACC_DIM_SIZE
12709 || gimple_call_internal_fn (stmt) == IFN_GOACC_DIM_POS);
12710 tree arg = gimple_call_arg (stmt, 0);
12711 HOST_WIDE_INT axis = TREE_INT_CST_LOW (arg);
12712
12713 gcc_checking_assert (axis >= 0 && axis < GOMP_DIM_MAX);
12714 return (int) axis;
12715 }
12716
12717 /* Mark the loops inside the kernels region starting at REGION_ENTRY and ending
12718 at REGION_EXIT. */
12719
12720 static void
12721 mark_loops_in_oacc_kernels_region (basic_block region_entry,
12722 basic_block region_exit)
12723 {
12724 struct loop *outer = region_entry->loop_father;
12725 gcc_assert (region_exit == NULL || outer == region_exit->loop_father);
12726
12727 /* Don't parallelize the kernels region if it contains more than one outer
12728 loop. */
12729 unsigned int nr_outer_loops = 0;
12730 struct loop *single_outer = NULL;
12731 for (struct loop *loop = outer->inner; loop != NULL; loop = loop->next)
12732 {
12733 gcc_assert (loop_outer (loop) == outer);
12734
12735 if (!dominated_by_p (CDI_DOMINATORS, loop->header, region_entry))
12736 continue;
12737
12738 if (region_exit != NULL
12739 && dominated_by_p (CDI_DOMINATORS, loop->header, region_exit))
12740 continue;
12741
12742 nr_outer_loops++;
12743 single_outer = loop;
12744 }
12745 if (nr_outer_loops != 1)
12746 return;
12747
12748 for (struct loop *loop = single_outer->inner; loop != NULL; loop = loop->inner)
12749 if (loop->next)
12750 return;
12751
12752 /* Mark the loops in the region. */
12753 for (struct loop *loop = single_outer; loop != NULL; loop = loop->inner)
12754 loop->in_oacc_kernels_region = true;
12755 }
12756
12757 /* Types used to pass grid and wortkgroup sizes to kernel invocation. */
12758
12759 struct GTY(()) grid_launch_attributes_trees
12760 {
12761 tree kernel_dim_array_type;
12762 tree kernel_lattrs_dimnum_decl;
12763 tree kernel_lattrs_grid_decl;
12764 tree kernel_lattrs_group_decl;
12765 tree kernel_launch_attributes_type;
12766 };
12767
12768 static GTY(()) struct grid_launch_attributes_trees *grid_attr_trees;
12769
12770 /* Create types used to pass kernel launch attributes to target. */
12771
12772 static void
12773 grid_create_kernel_launch_attr_types (void)
12774 {
12775 if (grid_attr_trees)
12776 return;
12777 grid_attr_trees = ggc_alloc <grid_launch_attributes_trees> ();
12778
12779 tree dim_arr_index_type
12780 = build_index_type (build_int_cst (integer_type_node, 2));
12781 grid_attr_trees->kernel_dim_array_type
12782 = build_array_type (uint32_type_node, dim_arr_index_type);
12783
12784 grid_attr_trees->kernel_launch_attributes_type = make_node (RECORD_TYPE);
12785 grid_attr_trees->kernel_lattrs_dimnum_decl
12786 = build_decl (BUILTINS_LOCATION, FIELD_DECL, get_identifier ("ndim"),
12787 uint32_type_node);
12788 DECL_CHAIN (grid_attr_trees->kernel_lattrs_dimnum_decl) = NULL_TREE;
12789
12790 grid_attr_trees->kernel_lattrs_grid_decl
12791 = build_decl (BUILTINS_LOCATION, FIELD_DECL, get_identifier ("grid_size"),
12792 grid_attr_trees->kernel_dim_array_type);
12793 DECL_CHAIN (grid_attr_trees->kernel_lattrs_grid_decl)
12794 = grid_attr_trees->kernel_lattrs_dimnum_decl;
12795 grid_attr_trees->kernel_lattrs_group_decl
12796 = build_decl (BUILTINS_LOCATION, FIELD_DECL, get_identifier ("group_size"),
12797 grid_attr_trees->kernel_dim_array_type);
12798 DECL_CHAIN (grid_attr_trees->kernel_lattrs_group_decl)
12799 = grid_attr_trees->kernel_lattrs_grid_decl;
12800 finish_builtin_struct (grid_attr_trees->kernel_launch_attributes_type,
12801 "__gomp_kernel_launch_attributes",
12802 grid_attr_trees->kernel_lattrs_group_decl, NULL_TREE);
12803 }
12804
12805 /* Insert before the current statement in GSI a store of VALUE to INDEX of
12806 array (of type kernel_dim_array_type) FLD_DECL of RANGE_VAR. VALUE must be
12807 of type uint32_type_node. */
12808
12809 static void
12810 grid_insert_store_range_dim (gimple_stmt_iterator *gsi, tree range_var,
12811 tree fld_decl, int index, tree value)
12812 {
12813 tree ref = build4 (ARRAY_REF, uint32_type_node,
12814 build3 (COMPONENT_REF,
12815 grid_attr_trees->kernel_dim_array_type,
12816 range_var, fld_decl, NULL_TREE),
12817 build_int_cst (integer_type_node, index),
12818 NULL_TREE, NULL_TREE);
12819 gsi_insert_before (gsi, gimple_build_assign (ref, value), GSI_SAME_STMT);
12820 }
12821
12822 /* Return a tree representation of a pointer to a structure with grid and
12823 work-group size information. Statements filling that information will be
12824 inserted before GSI, TGT_STMT is the target statement which has the
12825 necessary information in it. */
12826
12827 static tree
12828 grid_get_kernel_launch_attributes (gimple_stmt_iterator *gsi,
12829 gomp_target *tgt_stmt)
12830 {
12831 grid_create_kernel_launch_attr_types ();
12832 tree u32_one = build_one_cst (uint32_type_node);
12833 tree lattrs = create_tmp_var (grid_attr_trees->kernel_launch_attributes_type,
12834 "__kernel_launch_attrs");
12835
12836 unsigned max_dim = 0;
12837 for (tree clause = gimple_omp_target_clauses (tgt_stmt);
12838 clause;
12839 clause = OMP_CLAUSE_CHAIN (clause))
12840 {
12841 if (OMP_CLAUSE_CODE (clause) != OMP_CLAUSE__GRIDDIM_)
12842 continue;
12843
12844 unsigned dim = OMP_CLAUSE__GRIDDIM__DIMENSION (clause);
12845 max_dim = MAX (dim, max_dim);
12846
12847 grid_insert_store_range_dim (gsi, lattrs,
12848 grid_attr_trees->kernel_lattrs_grid_decl,
12849 dim, OMP_CLAUSE__GRIDDIM__SIZE (clause));
12850 grid_insert_store_range_dim (gsi, lattrs,
12851 grid_attr_trees->kernel_lattrs_group_decl,
12852 dim, OMP_CLAUSE__GRIDDIM__GROUP (clause));
12853 }
12854
12855 tree dimref = build3 (COMPONENT_REF, uint32_type_node, lattrs,
12856 grid_attr_trees->kernel_lattrs_dimnum_decl, NULL_TREE);
12857 /* At this moment we cannot gridify a loop with a collapse clause. */
12858 /* TODO: Adjust when we support bigger collapse. */
12859 gcc_assert (max_dim == 0);
12860 gsi_insert_before (gsi, gimple_build_assign (dimref, u32_one), GSI_SAME_STMT);
12861 TREE_ADDRESSABLE (lattrs) = 1;
12862 return build_fold_addr_expr (lattrs);
12863 }
12864
12865 /* Build target argument identifier from the DEVICE identifier, value
12866 identifier ID and whether the element also has a SUBSEQUENT_PARAM. */
12867
12868 static tree
12869 get_target_argument_identifier_1 (int device, bool subseqent_param, int id)
12870 {
12871 tree t = build_int_cst (integer_type_node, device);
12872 if (subseqent_param)
12873 t = fold_build2 (BIT_IOR_EXPR, integer_type_node, t,
12874 build_int_cst (integer_type_node,
12875 GOMP_TARGET_ARG_SUBSEQUENT_PARAM));
12876 t = fold_build2 (BIT_IOR_EXPR, integer_type_node, t,
12877 build_int_cst (integer_type_node, id));
12878 return t;
12879 }
12880
12881 /* Like above but return it in type that can be directly stored as an element
12882 of the argument array. */
12883
12884 static tree
12885 get_target_argument_identifier (int device, bool subseqent_param, int id)
12886 {
12887 tree t = get_target_argument_identifier_1 (device, subseqent_param, id);
12888 return fold_convert (ptr_type_node, t);
12889 }
12890
12891 /* Return a target argument consisting of DEVICE identifier, value identifier
12892 ID, and the actual VALUE. */
12893
12894 static tree
12895 get_target_argument_value (gimple_stmt_iterator *gsi, int device, int id,
12896 tree value)
12897 {
12898 tree t = fold_build2 (LSHIFT_EXPR, integer_type_node,
12899 fold_convert (integer_type_node, value),
12900 build_int_cst (unsigned_type_node,
12901 GOMP_TARGET_ARG_VALUE_SHIFT));
12902 t = fold_build2 (BIT_IOR_EXPR, integer_type_node, t,
12903 get_target_argument_identifier_1 (device, false, id));
12904 t = fold_convert (ptr_type_node, t);
12905 return force_gimple_operand_gsi (gsi, t, true, NULL, true, GSI_SAME_STMT);
12906 }
12907
12908 /* If VALUE is an integer constant greater than -2^15 and smaller than 2^15,
12909 push one argument to ARGS with both the DEVICE, ID and VALUE embedded in it,
12910 otherwise push an identifier (with DEVICE and ID) and the VALUE in two
12911 arguments. */
12912
12913 static void
12914 push_target_argument_according_to_value (gimple_stmt_iterator *gsi, int device,
12915 int id, tree value, vec <tree> *args)
12916 {
12917 if (tree_fits_shwi_p (value)
12918 && tree_to_shwi (value) > -(1 << 15)
12919 && tree_to_shwi (value) < (1 << 15))
12920 args->quick_push (get_target_argument_value (gsi, device, id, value));
12921 else
12922 {
12923 args->quick_push (get_target_argument_identifier (device, true, id));
12924 value = fold_convert (ptr_type_node, value);
12925 value = force_gimple_operand_gsi (gsi, value, true, NULL, true,
12926 GSI_SAME_STMT);
12927 args->quick_push (value);
12928 }
12929 }
12930
12931 /* Create an array of arguments that is then passed to GOMP_target. */
12932
12933 static tree
12934 get_target_arguments (gimple_stmt_iterator *gsi, gomp_target *tgt_stmt)
12935 {
12936 auto_vec <tree, 6> args;
12937 tree clauses = gimple_omp_target_clauses (tgt_stmt);
12938 tree t, c = find_omp_clause (clauses, OMP_CLAUSE_NUM_TEAMS);
12939 if (c)
12940 t = OMP_CLAUSE_NUM_TEAMS_EXPR (c);
12941 else
12942 t = integer_minus_one_node;
12943 push_target_argument_according_to_value (gsi, GOMP_TARGET_ARG_DEVICE_ALL,
12944 GOMP_TARGET_ARG_NUM_TEAMS, t, &args);
12945
12946 c = find_omp_clause (clauses, OMP_CLAUSE_THREAD_LIMIT);
12947 if (c)
12948 t = OMP_CLAUSE_THREAD_LIMIT_EXPR (c);
12949 else
12950 t = integer_minus_one_node;
12951 push_target_argument_according_to_value (gsi, GOMP_TARGET_ARG_DEVICE_ALL,
12952 GOMP_TARGET_ARG_THREAD_LIMIT, t,
12953 &args);
12954
12955 /* Add HSA-specific grid sizes, if available. */
12956 if (find_omp_clause (gimple_omp_target_clauses (tgt_stmt),
12957 OMP_CLAUSE__GRIDDIM_))
12958 {
12959 t = get_target_argument_identifier (GOMP_DEVICE_HSA, true,
12960 GOMP_TARGET_ARG_HSA_KERNEL_ATTRIBUTES);
12961 args.quick_push (t);
12962 args.quick_push (grid_get_kernel_launch_attributes (gsi, tgt_stmt));
12963 }
12964
12965 /* Produce more, perhaps device specific, arguments here. */
12966
12967 tree argarray = create_tmp_var (build_array_type_nelts (ptr_type_node,
12968 args.length () + 1),
12969 ".omp_target_args");
12970 for (unsigned i = 0; i < args.length (); i++)
12971 {
12972 tree ref = build4 (ARRAY_REF, ptr_type_node, argarray,
12973 build_int_cst (integer_type_node, i),
12974 NULL_TREE, NULL_TREE);
12975 gsi_insert_before (gsi, gimple_build_assign (ref, args[i]),
12976 GSI_SAME_STMT);
12977 }
12978 tree ref = build4 (ARRAY_REF, ptr_type_node, argarray,
12979 build_int_cst (integer_type_node, args.length ()),
12980 NULL_TREE, NULL_TREE);
12981 gsi_insert_before (gsi, gimple_build_assign (ref, null_pointer_node),
12982 GSI_SAME_STMT);
12983 TREE_ADDRESSABLE (argarray) = 1;
12984 return build_fold_addr_expr (argarray);
12985 }
12986
12987 /* Expand the GIMPLE_OMP_TARGET starting at REGION. */
12988
12989 static void
12990 expand_omp_target (struct omp_region *region)
12991 {
12992 basic_block entry_bb, exit_bb, new_bb;
12993 struct function *child_cfun;
12994 tree child_fn, block, t;
12995 gimple_stmt_iterator gsi;
12996 gomp_target *entry_stmt;
12997 gimple *stmt;
12998 edge e;
12999 bool offloaded, data_region;
13000
13001 entry_stmt = as_a <gomp_target *> (last_stmt (region->entry));
13002 new_bb = region->entry;
13003
13004 offloaded = is_gimple_omp_offloaded (entry_stmt);
13005 switch (gimple_omp_target_kind (entry_stmt))
13006 {
13007 case GF_OMP_TARGET_KIND_REGION:
13008 case GF_OMP_TARGET_KIND_UPDATE:
13009 case GF_OMP_TARGET_KIND_ENTER_DATA:
13010 case GF_OMP_TARGET_KIND_EXIT_DATA:
13011 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
13012 case GF_OMP_TARGET_KIND_OACC_KERNELS:
13013 case GF_OMP_TARGET_KIND_OACC_UPDATE:
13014 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
13015 case GF_OMP_TARGET_KIND_OACC_DECLARE:
13016 data_region = false;
13017 break;
13018 case GF_OMP_TARGET_KIND_DATA:
13019 case GF_OMP_TARGET_KIND_OACC_DATA:
13020 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
13021 data_region = true;
13022 break;
13023 default:
13024 gcc_unreachable ();
13025 }
13026
13027 child_fn = NULL_TREE;
13028 child_cfun = NULL;
13029 if (offloaded)
13030 {
13031 child_fn = gimple_omp_target_child_fn (entry_stmt);
13032 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
13033 }
13034
13035 /* Supported by expand_omp_taskreg, but not here. */
13036 if (child_cfun != NULL)
13037 gcc_checking_assert (!child_cfun->cfg);
13038 gcc_checking_assert (!gimple_in_ssa_p (cfun));
13039
13040 entry_bb = region->entry;
13041 exit_bb = region->exit;
13042
13043 if (gimple_omp_target_kind (entry_stmt) == GF_OMP_TARGET_KIND_OACC_KERNELS)
13044 mark_loops_in_oacc_kernels_region (region->entry, region->exit);
13045
13046 if (offloaded)
13047 {
13048 unsigned srcidx, dstidx, num;
13049
13050 /* If the offloading region needs data sent from the parent
13051 function, then the very first statement (except possible
13052 tree profile counter updates) of the offloading body
13053 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
13054 &.OMP_DATA_O is passed as an argument to the child function,
13055 we need to replace it with the argument as seen by the child
13056 function.
13057
13058 In most cases, this will end up being the identity assignment
13059 .OMP_DATA_I = .OMP_DATA_I. However, if the offloading body had
13060 a function call that has been inlined, the original PARM_DECL
13061 .OMP_DATA_I may have been converted into a different local
13062 variable. In which case, we need to keep the assignment. */
13063 tree data_arg = gimple_omp_target_data_arg (entry_stmt);
13064 if (data_arg)
13065 {
13066 basic_block entry_succ_bb = single_succ (entry_bb);
13067 gimple_stmt_iterator gsi;
13068 tree arg;
13069 gimple *tgtcopy_stmt = NULL;
13070 tree sender = TREE_VEC_ELT (data_arg, 0);
13071
13072 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
13073 {
13074 gcc_assert (!gsi_end_p (gsi));
13075 stmt = gsi_stmt (gsi);
13076 if (gimple_code (stmt) != GIMPLE_ASSIGN)
13077 continue;
13078
13079 if (gimple_num_ops (stmt) == 2)
13080 {
13081 tree arg = gimple_assign_rhs1 (stmt);
13082
13083 /* We're ignoring the subcode because we're
13084 effectively doing a STRIP_NOPS. */
13085
13086 if (TREE_CODE (arg) == ADDR_EXPR
13087 && TREE_OPERAND (arg, 0) == sender)
13088 {
13089 tgtcopy_stmt = stmt;
13090 break;
13091 }
13092 }
13093 }
13094
13095 gcc_assert (tgtcopy_stmt != NULL);
13096 arg = DECL_ARGUMENTS (child_fn);
13097
13098 gcc_assert (gimple_assign_lhs (tgtcopy_stmt) == arg);
13099 gsi_remove (&gsi, true);
13100 }
13101
13102 /* Declare local variables needed in CHILD_CFUN. */
13103 block = DECL_INITIAL (child_fn);
13104 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
13105 /* The gimplifier could record temporaries in the offloading block
13106 rather than in containing function's local_decls chain,
13107 which would mean cgraph missed finalizing them. Do it now. */
13108 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
13109 if (TREE_CODE (t) == VAR_DECL
13110 && TREE_STATIC (t)
13111 && !DECL_EXTERNAL (t))
13112 varpool_node::finalize_decl (t);
13113 DECL_SAVED_TREE (child_fn) = NULL;
13114 /* We'll create a CFG for child_fn, so no gimple body is needed. */
13115 gimple_set_body (child_fn, NULL);
13116 TREE_USED (block) = 1;
13117
13118 /* Reset DECL_CONTEXT on function arguments. */
13119 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
13120 DECL_CONTEXT (t) = child_fn;
13121
13122 /* Split ENTRY_BB at GIMPLE_*,
13123 so that it can be moved to the child function. */
13124 gsi = gsi_last_bb (entry_bb);
13125 stmt = gsi_stmt (gsi);
13126 gcc_assert (stmt
13127 && gimple_code (stmt) == gimple_code (entry_stmt));
13128 e = split_block (entry_bb, stmt);
13129 gsi_remove (&gsi, true);
13130 entry_bb = e->dest;
13131 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
13132
13133 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
13134 if (exit_bb)
13135 {
13136 gsi = gsi_last_bb (exit_bb);
13137 gcc_assert (!gsi_end_p (gsi)
13138 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
13139 stmt = gimple_build_return (NULL);
13140 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
13141 gsi_remove (&gsi, true);
13142 }
13143
13144 /* Move the offloading region into CHILD_CFUN. */
13145
13146 block = gimple_block (entry_stmt);
13147
13148 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
13149 if (exit_bb)
13150 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
13151 /* When the OMP expansion process cannot guarantee an up-to-date
13152 loop tree arrange for the child function to fixup loops. */
13153 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
13154 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
13155
13156 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
13157 num = vec_safe_length (child_cfun->local_decls);
13158 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
13159 {
13160 t = (*child_cfun->local_decls)[srcidx];
13161 if (DECL_CONTEXT (t) == cfun->decl)
13162 continue;
13163 if (srcidx != dstidx)
13164 (*child_cfun->local_decls)[dstidx] = t;
13165 dstidx++;
13166 }
13167 if (dstidx != num)
13168 vec_safe_truncate (child_cfun->local_decls, dstidx);
13169
13170 /* Inform the callgraph about the new function. */
13171 child_cfun->curr_properties = cfun->curr_properties;
13172 child_cfun->has_simduid_loops |= cfun->has_simduid_loops;
13173 child_cfun->has_force_vectorize_loops |= cfun->has_force_vectorize_loops;
13174 cgraph_node *node = cgraph_node::get_create (child_fn);
13175 node->parallelized_function = 1;
13176 cgraph_node::add_new_function (child_fn, true);
13177
13178 /* Add the new function to the offload table. */
13179 if (ENABLE_OFFLOADING)
13180 vec_safe_push (offload_funcs, child_fn);
13181
13182 bool need_asm = DECL_ASSEMBLER_NAME_SET_P (current_function_decl)
13183 && !DECL_ASSEMBLER_NAME_SET_P (child_fn);
13184
13185 /* Fix the callgraph edges for child_cfun. Those for cfun will be
13186 fixed in a following pass. */
13187 push_cfun (child_cfun);
13188 if (need_asm)
13189 assign_assembler_name_if_neeeded (child_fn);
13190 cgraph_edge::rebuild_edges ();
13191
13192 /* Some EH regions might become dead, see PR34608. If
13193 pass_cleanup_cfg isn't the first pass to happen with the
13194 new child, these dead EH edges might cause problems.
13195 Clean them up now. */
13196 if (flag_exceptions)
13197 {
13198 basic_block bb;
13199 bool changed = false;
13200
13201 FOR_EACH_BB_FN (bb, cfun)
13202 changed |= gimple_purge_dead_eh_edges (bb);
13203 if (changed)
13204 cleanup_tree_cfg ();
13205 }
13206 if (flag_checking && !loops_state_satisfies_p (LOOPS_NEED_FIXUP))
13207 verify_loop_structure ();
13208 pop_cfun ();
13209
13210 if (dump_file && !gimple_in_ssa_p (cfun))
13211 {
13212 omp_any_child_fn_dumped = true;
13213 dump_function_header (dump_file, child_fn, dump_flags);
13214 dump_function_to_file (child_fn, dump_file, dump_flags);
13215 }
13216 }
13217
13218 /* Emit a library call to launch the offloading region, or do data
13219 transfers. */
13220 tree t1, t2, t3, t4, device, cond, depend, c, clauses;
13221 enum built_in_function start_ix;
13222 location_t clause_loc;
13223 unsigned int flags_i = 0;
13224 bool oacc_kernels_p = false;
13225
13226 switch (gimple_omp_target_kind (entry_stmt))
13227 {
13228 case GF_OMP_TARGET_KIND_REGION:
13229 start_ix = BUILT_IN_GOMP_TARGET;
13230 break;
13231 case GF_OMP_TARGET_KIND_DATA:
13232 start_ix = BUILT_IN_GOMP_TARGET_DATA;
13233 break;
13234 case GF_OMP_TARGET_KIND_UPDATE:
13235 start_ix = BUILT_IN_GOMP_TARGET_UPDATE;
13236 break;
13237 case GF_OMP_TARGET_KIND_ENTER_DATA:
13238 start_ix = BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA;
13239 break;
13240 case GF_OMP_TARGET_KIND_EXIT_DATA:
13241 start_ix = BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA;
13242 flags_i |= GOMP_TARGET_FLAG_EXIT_DATA;
13243 break;
13244 case GF_OMP_TARGET_KIND_OACC_KERNELS:
13245 oacc_kernels_p = true;
13246 /* FALLTHROUGH */
13247 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
13248 start_ix = BUILT_IN_GOACC_PARALLEL;
13249 break;
13250 case GF_OMP_TARGET_KIND_OACC_DATA:
13251 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
13252 start_ix = BUILT_IN_GOACC_DATA_START;
13253 break;
13254 case GF_OMP_TARGET_KIND_OACC_UPDATE:
13255 start_ix = BUILT_IN_GOACC_UPDATE;
13256 break;
13257 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
13258 start_ix = BUILT_IN_GOACC_ENTER_EXIT_DATA;
13259 break;
13260 case GF_OMP_TARGET_KIND_OACC_DECLARE:
13261 start_ix = BUILT_IN_GOACC_DECLARE;
13262 break;
13263 default:
13264 gcc_unreachable ();
13265 }
13266
13267 clauses = gimple_omp_target_clauses (entry_stmt);
13268
13269 /* By default, the value of DEVICE is GOMP_DEVICE_ICV (let runtime
13270 library choose) and there is no conditional. */
13271 cond = NULL_TREE;
13272 device = build_int_cst (integer_type_node, GOMP_DEVICE_ICV);
13273
13274 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
13275 if (c)
13276 cond = OMP_CLAUSE_IF_EXPR (c);
13277
13278 c = find_omp_clause (clauses, OMP_CLAUSE_DEVICE);
13279 if (c)
13280 {
13281 /* Even if we pass it to all library function calls, it is currently only
13282 defined/used for the OpenMP target ones. */
13283 gcc_checking_assert (start_ix == BUILT_IN_GOMP_TARGET
13284 || start_ix == BUILT_IN_GOMP_TARGET_DATA
13285 || start_ix == BUILT_IN_GOMP_TARGET_UPDATE
13286 || start_ix == BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA);
13287
13288 device = OMP_CLAUSE_DEVICE_ID (c);
13289 clause_loc = OMP_CLAUSE_LOCATION (c);
13290 }
13291 else
13292 clause_loc = gimple_location (entry_stmt);
13293
13294 c = find_omp_clause (clauses, OMP_CLAUSE_NOWAIT);
13295 if (c)
13296 flags_i |= GOMP_TARGET_FLAG_NOWAIT;
13297
13298 /* Ensure 'device' is of the correct type. */
13299 device = fold_convert_loc (clause_loc, integer_type_node, device);
13300
13301 /* If we found the clause 'if (cond)', build
13302 (cond ? device : GOMP_DEVICE_HOST_FALLBACK). */
13303 if (cond)
13304 {
13305 cond = gimple_boolify (cond);
13306
13307 basic_block cond_bb, then_bb, else_bb;
13308 edge e;
13309 tree tmp_var;
13310
13311 tmp_var = create_tmp_var (TREE_TYPE (device));
13312 if (offloaded)
13313 e = split_block_after_labels (new_bb);
13314 else
13315 {
13316 gsi = gsi_last_bb (new_bb);
13317 gsi_prev (&gsi);
13318 e = split_block (new_bb, gsi_stmt (gsi));
13319 }
13320 cond_bb = e->src;
13321 new_bb = e->dest;
13322 remove_edge (e);
13323
13324 then_bb = create_empty_bb (cond_bb);
13325 else_bb = create_empty_bb (then_bb);
13326 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
13327 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
13328
13329 stmt = gimple_build_cond_empty (cond);
13330 gsi = gsi_last_bb (cond_bb);
13331 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
13332
13333 gsi = gsi_start_bb (then_bb);
13334 stmt = gimple_build_assign (tmp_var, device);
13335 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
13336
13337 gsi = gsi_start_bb (else_bb);
13338 stmt = gimple_build_assign (tmp_var,
13339 build_int_cst (integer_type_node,
13340 GOMP_DEVICE_HOST_FALLBACK));
13341 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
13342
13343 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
13344 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
13345 add_bb_to_loop (then_bb, cond_bb->loop_father);
13346 add_bb_to_loop (else_bb, cond_bb->loop_father);
13347 make_edge (then_bb, new_bb, EDGE_FALLTHRU);
13348 make_edge (else_bb, new_bb, EDGE_FALLTHRU);
13349
13350 device = tmp_var;
13351 }
13352
13353 gsi = gsi_last_bb (new_bb);
13354 t = gimple_omp_target_data_arg (entry_stmt);
13355 if (t == NULL)
13356 {
13357 t1 = size_zero_node;
13358 t2 = build_zero_cst (ptr_type_node);
13359 t3 = t2;
13360 t4 = t2;
13361 }
13362 else
13363 {
13364 t1 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t, 1))));
13365 t1 = size_binop (PLUS_EXPR, t1, size_int (1));
13366 t2 = build_fold_addr_expr (TREE_VEC_ELT (t, 0));
13367 t3 = build_fold_addr_expr (TREE_VEC_ELT (t, 1));
13368 t4 = build_fold_addr_expr (TREE_VEC_ELT (t, 2));
13369 }
13370
13371 gimple *g;
13372 bool tagging = false;
13373 /* The maximum number used by any start_ix, without varargs. */
13374 auto_vec<tree, 11> args;
13375 args.quick_push (device);
13376 if (offloaded)
13377 args.quick_push (build_fold_addr_expr (child_fn));
13378 args.quick_push (t1);
13379 args.quick_push (t2);
13380 args.quick_push (t3);
13381 args.quick_push (t4);
13382 switch (start_ix)
13383 {
13384 case BUILT_IN_GOACC_DATA_START:
13385 case BUILT_IN_GOACC_DECLARE:
13386 case BUILT_IN_GOMP_TARGET_DATA:
13387 break;
13388 case BUILT_IN_GOMP_TARGET:
13389 case BUILT_IN_GOMP_TARGET_UPDATE:
13390 case BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA:
13391 args.quick_push (build_int_cst (unsigned_type_node, flags_i));
13392 c = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
13393 if (c)
13394 depend = OMP_CLAUSE_DECL (c);
13395 else
13396 depend = build_int_cst (ptr_type_node, 0);
13397 args.quick_push (depend);
13398 if (start_ix == BUILT_IN_GOMP_TARGET)
13399 args.quick_push (get_target_arguments (&gsi, entry_stmt));
13400 break;
13401 case BUILT_IN_GOACC_PARALLEL:
13402 {
13403 set_oacc_fn_attrib (child_fn, clauses, oacc_kernels_p, &args);
13404 tagging = true;
13405 }
13406 /* FALLTHRU */
13407 case BUILT_IN_GOACC_ENTER_EXIT_DATA:
13408 case BUILT_IN_GOACC_UPDATE:
13409 {
13410 tree t_async = NULL_TREE;
13411
13412 /* If present, use the value specified by the respective
13413 clause, making sure that is of the correct type. */
13414 c = find_omp_clause (clauses, OMP_CLAUSE_ASYNC);
13415 if (c)
13416 t_async = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
13417 integer_type_node,
13418 OMP_CLAUSE_ASYNC_EXPR (c));
13419 else if (!tagging)
13420 /* Default values for t_async. */
13421 t_async = fold_convert_loc (gimple_location (entry_stmt),
13422 integer_type_node,
13423 build_int_cst (integer_type_node,
13424 GOMP_ASYNC_SYNC));
13425 if (tagging && t_async)
13426 {
13427 unsigned HOST_WIDE_INT i_async = GOMP_LAUNCH_OP_MAX;
13428
13429 if (TREE_CODE (t_async) == INTEGER_CST)
13430 {
13431 /* See if we can pack the async arg in to the tag's
13432 operand. */
13433 i_async = TREE_INT_CST_LOW (t_async);
13434 if (i_async < GOMP_LAUNCH_OP_MAX)
13435 t_async = NULL_TREE;
13436 else
13437 i_async = GOMP_LAUNCH_OP_MAX;
13438 }
13439 args.safe_push (oacc_launch_pack (GOMP_LAUNCH_ASYNC, NULL_TREE,
13440 i_async));
13441 }
13442 if (t_async)
13443 args.safe_push (t_async);
13444
13445 /* Save the argument index, and ... */
13446 unsigned t_wait_idx = args.length ();
13447 unsigned num_waits = 0;
13448 c = find_omp_clause (clauses, OMP_CLAUSE_WAIT);
13449 if (!tagging || c)
13450 /* ... push a placeholder. */
13451 args.safe_push (integer_zero_node);
13452
13453 for (; c; c = OMP_CLAUSE_CHAIN (c))
13454 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_WAIT)
13455 {
13456 args.safe_push (fold_convert_loc (OMP_CLAUSE_LOCATION (c),
13457 integer_type_node,
13458 OMP_CLAUSE_WAIT_EXPR (c)));
13459 num_waits++;
13460 }
13461
13462 if (!tagging || num_waits)
13463 {
13464 tree len;
13465
13466 /* Now that we know the number, update the placeholder. */
13467 if (tagging)
13468 len = oacc_launch_pack (GOMP_LAUNCH_WAIT, NULL_TREE, num_waits);
13469 else
13470 len = build_int_cst (integer_type_node, num_waits);
13471 len = fold_convert_loc (gimple_location (entry_stmt),
13472 unsigned_type_node, len);
13473 args[t_wait_idx] = len;
13474 }
13475 }
13476 break;
13477 default:
13478 gcc_unreachable ();
13479 }
13480 if (tagging)
13481 /* Push terminal marker - zero. */
13482 args.safe_push (oacc_launch_pack (0, NULL_TREE, 0));
13483
13484 g = gimple_build_call_vec (builtin_decl_explicit (start_ix), args);
13485 gimple_set_location (g, gimple_location (entry_stmt));
13486 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
13487 if (!offloaded)
13488 {
13489 g = gsi_stmt (gsi);
13490 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_TARGET);
13491 gsi_remove (&gsi, true);
13492 }
13493 if (data_region && region->exit)
13494 {
13495 gsi = gsi_last_bb (region->exit);
13496 g = gsi_stmt (gsi);
13497 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_RETURN);
13498 gsi_remove (&gsi, true);
13499 }
13500 }
13501
13502 /* Expand KFOR loop as a GPGPU kernel, i.e. as a body only with iteration
13503 variable derived from the thread number. */
13504
13505 static void
13506 grid_expand_omp_for_loop (struct omp_region *kfor)
13507 {
13508 tree t, threadid;
13509 tree type, itype;
13510 gimple_stmt_iterator gsi;
13511 tree n1, step;
13512 struct omp_for_data fd;
13513
13514 gomp_for *for_stmt = as_a <gomp_for *> (last_stmt (kfor->entry));
13515 gcc_checking_assert (gimple_omp_for_kind (for_stmt)
13516 == GF_OMP_FOR_KIND_GRID_LOOP);
13517 basic_block body_bb = FALLTHRU_EDGE (kfor->entry)->dest;
13518
13519 gcc_assert (gimple_omp_for_collapse (for_stmt) == 1);
13520 gcc_assert (kfor->cont);
13521 extract_omp_for_data (for_stmt, &fd, NULL);
13522
13523 itype = type = TREE_TYPE (fd.loop.v);
13524 if (POINTER_TYPE_P (type))
13525 itype = signed_type_for (type);
13526
13527 gsi = gsi_start_bb (body_bb);
13528
13529 n1 = fd.loop.n1;
13530 step = fd.loop.step;
13531 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
13532 true, NULL_TREE, true, GSI_SAME_STMT);
13533 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
13534 true, NULL_TREE, true, GSI_SAME_STMT);
13535 threadid = build_call_expr (builtin_decl_explicit
13536 (BUILT_IN_OMP_GET_THREAD_NUM), 0);
13537 threadid = fold_convert (itype, threadid);
13538 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
13539 true, GSI_SAME_STMT);
13540
13541 tree startvar = fd.loop.v;
13542 t = fold_build2 (MULT_EXPR, itype, threadid, step);
13543 if (POINTER_TYPE_P (type))
13544 t = fold_build_pointer_plus (n1, t);
13545 else
13546 t = fold_build2 (PLUS_EXPR, type, t, n1);
13547 t = fold_convert (type, t);
13548 t = force_gimple_operand_gsi (&gsi, t,
13549 DECL_P (startvar)
13550 && TREE_ADDRESSABLE (startvar),
13551 NULL_TREE, true, GSI_SAME_STMT);
13552 gassign *assign_stmt = gimple_build_assign (startvar, t);
13553 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
13554
13555 /* Remove the omp for statement */
13556 gsi = gsi_last_bb (kfor->entry);
13557 gsi_remove (&gsi, true);
13558
13559 /* Remove the GIMPLE_OMP_CONTINUE statement. */
13560 gsi = gsi_last_bb (kfor->cont);
13561 gcc_assert (!gsi_end_p (gsi)
13562 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_CONTINUE);
13563 gsi_remove (&gsi, true);
13564
13565 /* Replace the GIMPLE_OMP_RETURN with a real return. */
13566 gsi = gsi_last_bb (kfor->exit);
13567 gcc_assert (!gsi_end_p (gsi)
13568 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
13569 gsi_remove (&gsi, true);
13570
13571 /* Fixup the much simpler CFG. */
13572 remove_edge (find_edge (kfor->cont, body_bb));
13573
13574 if (kfor->cont != body_bb)
13575 set_immediate_dominator (CDI_DOMINATORS, kfor->cont, body_bb);
13576 set_immediate_dominator (CDI_DOMINATORS, kfor->exit, kfor->cont);
13577 }
13578
13579 /* Structure passed to grid_remap_kernel_arg_accesses so that it can remap
13580 argument_decls. */
13581
13582 struct grid_arg_decl_map
13583 {
13584 tree old_arg;
13585 tree new_arg;
13586 };
13587
13588 /* Invoked through walk_gimple_op, will remap all PARM_DECLs to the ones
13589 pertaining to kernel function. */
13590
13591 static tree
13592 grid_remap_kernel_arg_accesses (tree *tp, int *walk_subtrees, void *data)
13593 {
13594 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
13595 struct grid_arg_decl_map *adm = (struct grid_arg_decl_map *) wi->info;
13596 tree t = *tp;
13597
13598 if (t == adm->old_arg)
13599 *tp = adm->new_arg;
13600 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
13601 return NULL_TREE;
13602 }
13603
13604 static void expand_omp (struct omp_region *region);
13605
13606 /* If TARGET region contains a kernel body for loop, remove its region from the
13607 TARGET and expand it in GPGPU kernel fashion. */
13608
13609 static void
13610 grid_expand_target_grid_body (struct omp_region *target)
13611 {
13612 if (!hsa_gen_requested_p ())
13613 return;
13614
13615 gomp_target *tgt_stmt = as_a <gomp_target *> (last_stmt (target->entry));
13616 struct omp_region **pp;
13617
13618 for (pp = &target->inner; *pp; pp = &(*pp)->next)
13619 if ((*pp)->type == GIMPLE_OMP_GRID_BODY)
13620 break;
13621
13622 struct omp_region *gpukernel = *pp;
13623
13624 tree orig_child_fndecl = gimple_omp_target_child_fn (tgt_stmt);
13625 if (!gpukernel)
13626 {
13627 /* HSA cannot handle OACC stuff. */
13628 if (gimple_omp_target_kind (tgt_stmt) != GF_OMP_TARGET_KIND_REGION)
13629 return;
13630 gcc_checking_assert (orig_child_fndecl);
13631 gcc_assert (!find_omp_clause (gimple_omp_target_clauses (tgt_stmt),
13632 OMP_CLAUSE__GRIDDIM_));
13633 cgraph_node *n = cgraph_node::get (orig_child_fndecl);
13634
13635 hsa_register_kernel (n);
13636 return;
13637 }
13638
13639 gcc_assert (find_omp_clause (gimple_omp_target_clauses (tgt_stmt),
13640 OMP_CLAUSE__GRIDDIM_));
13641 tree inside_block = gimple_block (first_stmt (single_succ (gpukernel->entry)));
13642 *pp = gpukernel->next;
13643 for (pp = &gpukernel->inner; *pp; pp = &(*pp)->next)
13644 if ((*pp)->type == GIMPLE_OMP_FOR)
13645 break;
13646
13647 struct omp_region *kfor = *pp;
13648 gcc_assert (kfor);
13649 gcc_assert (gimple_omp_for_kind (last_stmt ((kfor)->entry))
13650 == GF_OMP_FOR_KIND_GRID_LOOP);
13651 *pp = kfor->next;
13652 if (kfor->inner)
13653 expand_omp (kfor->inner);
13654 if (gpukernel->inner)
13655 expand_omp (gpukernel->inner);
13656
13657 tree kern_fndecl = copy_node (orig_child_fndecl);
13658 DECL_NAME (kern_fndecl) = clone_function_name (kern_fndecl, "kernel");
13659 SET_DECL_ASSEMBLER_NAME (kern_fndecl, DECL_NAME (kern_fndecl));
13660 tree tgtblock = gimple_block (tgt_stmt);
13661 tree fniniblock = make_node (BLOCK);
13662 BLOCK_ABSTRACT_ORIGIN (fniniblock) = tgtblock;
13663 BLOCK_SOURCE_LOCATION (fniniblock) = BLOCK_SOURCE_LOCATION (tgtblock);
13664 BLOCK_SOURCE_END_LOCATION (fniniblock) = BLOCK_SOURCE_END_LOCATION (tgtblock);
13665 DECL_INITIAL (kern_fndecl) = fniniblock;
13666 push_struct_function (kern_fndecl);
13667 cfun->function_end_locus = gimple_location (tgt_stmt);
13668 init_tree_ssa (cfun);
13669 pop_cfun ();
13670
13671 tree old_parm_decl = DECL_ARGUMENTS (kern_fndecl);
13672 gcc_assert (!DECL_CHAIN (old_parm_decl));
13673 tree new_parm_decl = copy_node (DECL_ARGUMENTS (kern_fndecl));
13674 DECL_CONTEXT (new_parm_decl) = kern_fndecl;
13675 DECL_ARGUMENTS (kern_fndecl) = new_parm_decl;
13676 gcc_assert (VOID_TYPE_P (TREE_TYPE (DECL_RESULT (kern_fndecl))));
13677 DECL_RESULT (kern_fndecl) = copy_node (DECL_RESULT (kern_fndecl));
13678 DECL_CONTEXT (DECL_RESULT (kern_fndecl)) = kern_fndecl;
13679 struct function *kern_cfun = DECL_STRUCT_FUNCTION (kern_fndecl);
13680 kern_cfun->curr_properties = cfun->curr_properties;
13681
13682 remove_edge (BRANCH_EDGE (kfor->entry));
13683 grid_expand_omp_for_loop (kfor);
13684
13685 /* Remove the omp for statement */
13686 gimple_stmt_iterator gsi = gsi_last_bb (gpukernel->entry);
13687 gsi_remove (&gsi, true);
13688 /* Replace the GIMPLE_OMP_RETURN at the end of the kernel region with a real
13689 return. */
13690 gsi = gsi_last_bb (gpukernel->exit);
13691 gcc_assert (!gsi_end_p (gsi)
13692 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
13693 gimple *ret_stmt = gimple_build_return (NULL);
13694 gsi_insert_after (&gsi, ret_stmt, GSI_SAME_STMT);
13695 gsi_remove (&gsi, true);
13696
13697 /* Statements in the first BB in the target construct have been produced by
13698 target lowering and must be copied inside the GPUKERNEL, with the two
13699 exceptions of the first OMP statement and the OMP_DATA assignment
13700 statement. */
13701 gsi = gsi_start_bb (single_succ (gpukernel->entry));
13702 tree data_arg = gimple_omp_target_data_arg (tgt_stmt);
13703 tree sender = data_arg ? TREE_VEC_ELT (data_arg, 0) : NULL;
13704 for (gimple_stmt_iterator tsi = gsi_start_bb (single_succ (target->entry));
13705 !gsi_end_p (tsi); gsi_next (&tsi))
13706 {
13707 gimple *stmt = gsi_stmt (tsi);
13708 if (is_gimple_omp (stmt))
13709 break;
13710 if (sender
13711 && is_gimple_assign (stmt)
13712 && TREE_CODE (gimple_assign_rhs1 (stmt)) == ADDR_EXPR
13713 && TREE_OPERAND (gimple_assign_rhs1 (stmt), 0) == sender)
13714 continue;
13715 gimple *copy = gimple_copy (stmt);
13716 gsi_insert_before (&gsi, copy, GSI_SAME_STMT);
13717 gimple_set_block (copy, fniniblock);
13718 }
13719
13720 move_sese_region_to_fn (kern_cfun, single_succ (gpukernel->entry),
13721 gpukernel->exit, inside_block);
13722
13723 cgraph_node *kcn = cgraph_node::get_create (kern_fndecl);
13724 kcn->mark_force_output ();
13725 cgraph_node *orig_child = cgraph_node::get (orig_child_fndecl);
13726
13727 hsa_register_kernel (kcn, orig_child);
13728
13729 cgraph_node::add_new_function (kern_fndecl, true);
13730 push_cfun (kern_cfun);
13731 cgraph_edge::rebuild_edges ();
13732
13733 /* Re-map any mention of the PARM_DECL of the original function to the
13734 PARM_DECL of the new one.
13735
13736 TODO: It would be great if lowering produced references into the GPU
13737 kernel decl straight away and we did not have to do this. */
13738 struct grid_arg_decl_map adm;
13739 adm.old_arg = old_parm_decl;
13740 adm.new_arg = new_parm_decl;
13741 basic_block bb;
13742 FOR_EACH_BB_FN (bb, kern_cfun)
13743 {
13744 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
13745 {
13746 gimple *stmt = gsi_stmt (gsi);
13747 struct walk_stmt_info wi;
13748 memset (&wi, 0, sizeof (wi));
13749 wi.info = &adm;
13750 walk_gimple_op (stmt, grid_remap_kernel_arg_accesses, &wi);
13751 }
13752 }
13753 pop_cfun ();
13754
13755 return;
13756 }
13757
13758 /* Expand the parallel region tree rooted at REGION. Expansion
13759 proceeds in depth-first order. Innermost regions are expanded
13760 first. This way, parallel regions that require a new function to
13761 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
13762 internal dependencies in their body. */
13763
13764 static void
13765 expand_omp (struct omp_region *region)
13766 {
13767 omp_any_child_fn_dumped = false;
13768 while (region)
13769 {
13770 location_t saved_location;
13771 gimple *inner_stmt = NULL;
13772
13773 /* First, determine whether this is a combined parallel+workshare
13774 region. */
13775 if (region->type == GIMPLE_OMP_PARALLEL)
13776 determine_parallel_type (region);
13777 else if (region->type == GIMPLE_OMP_TARGET)
13778 grid_expand_target_grid_body (region);
13779
13780 if (region->type == GIMPLE_OMP_FOR
13781 && gimple_omp_for_combined_p (last_stmt (region->entry)))
13782 inner_stmt = last_stmt (region->inner->entry);
13783
13784 if (region->inner)
13785 expand_omp (region->inner);
13786
13787 saved_location = input_location;
13788 if (gimple_has_location (last_stmt (region->entry)))
13789 input_location = gimple_location (last_stmt (region->entry));
13790
13791 switch (region->type)
13792 {
13793 case GIMPLE_OMP_PARALLEL:
13794 case GIMPLE_OMP_TASK:
13795 expand_omp_taskreg (region);
13796 break;
13797
13798 case GIMPLE_OMP_FOR:
13799 expand_omp_for (region, inner_stmt);
13800 break;
13801
13802 case GIMPLE_OMP_SECTIONS:
13803 expand_omp_sections (region);
13804 break;
13805
13806 case GIMPLE_OMP_SECTION:
13807 /* Individual omp sections are handled together with their
13808 parent GIMPLE_OMP_SECTIONS region. */
13809 break;
13810
13811 case GIMPLE_OMP_SINGLE:
13812 expand_omp_single (region);
13813 break;
13814
13815 case GIMPLE_OMP_ORDERED:
13816 {
13817 gomp_ordered *ord_stmt
13818 = as_a <gomp_ordered *> (last_stmt (region->entry));
13819 if (find_omp_clause (gimple_omp_ordered_clauses (ord_stmt),
13820 OMP_CLAUSE_DEPEND))
13821 {
13822 /* We'll expand these when expanding corresponding
13823 worksharing region with ordered(n) clause. */
13824 gcc_assert (region->outer
13825 && region->outer->type == GIMPLE_OMP_FOR);
13826 region->ord_stmt = ord_stmt;
13827 break;
13828 }
13829 }
13830 /* FALLTHRU */
13831 case GIMPLE_OMP_MASTER:
13832 case GIMPLE_OMP_TASKGROUP:
13833 case GIMPLE_OMP_CRITICAL:
13834 case GIMPLE_OMP_TEAMS:
13835 expand_omp_synch (region);
13836 break;
13837
13838 case GIMPLE_OMP_ATOMIC_LOAD:
13839 expand_omp_atomic (region);
13840 break;
13841
13842 case GIMPLE_OMP_TARGET:
13843 expand_omp_target (region);
13844 break;
13845
13846 default:
13847 gcc_unreachable ();
13848 }
13849
13850 input_location = saved_location;
13851 region = region->next;
13852 }
13853 if (omp_any_child_fn_dumped)
13854 {
13855 if (dump_file)
13856 dump_function_header (dump_file, current_function_decl, dump_flags);
13857 omp_any_child_fn_dumped = false;
13858 }
13859 }
13860
13861
13862 /* Helper for build_omp_regions. Scan the dominator tree starting at
13863 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
13864 true, the function ends once a single tree is built (otherwise, whole
13865 forest of OMP constructs may be built). */
13866
13867 static void
13868 build_omp_regions_1 (basic_block bb, struct omp_region *parent,
13869 bool single_tree)
13870 {
13871 gimple_stmt_iterator gsi;
13872 gimple *stmt;
13873 basic_block son;
13874
13875 gsi = gsi_last_bb (bb);
13876 if (!gsi_end_p (gsi) && is_gimple_omp (gsi_stmt (gsi)))
13877 {
13878 struct omp_region *region;
13879 enum gimple_code code;
13880
13881 stmt = gsi_stmt (gsi);
13882 code = gimple_code (stmt);
13883 if (code == GIMPLE_OMP_RETURN)
13884 {
13885 /* STMT is the return point out of region PARENT. Mark it
13886 as the exit point and make PARENT the immediately
13887 enclosing region. */
13888 gcc_assert (parent);
13889 region = parent;
13890 region->exit = bb;
13891 parent = parent->outer;
13892 }
13893 else if (code == GIMPLE_OMP_ATOMIC_STORE)
13894 {
13895 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
13896 GIMPLE_OMP_RETURN, but matches with
13897 GIMPLE_OMP_ATOMIC_LOAD. */
13898 gcc_assert (parent);
13899 gcc_assert (parent->type == GIMPLE_OMP_ATOMIC_LOAD);
13900 region = parent;
13901 region->exit = bb;
13902 parent = parent->outer;
13903 }
13904 else if (code == GIMPLE_OMP_CONTINUE)
13905 {
13906 gcc_assert (parent);
13907 parent->cont = bb;
13908 }
13909 else if (code == GIMPLE_OMP_SECTIONS_SWITCH)
13910 {
13911 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
13912 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
13913 }
13914 else
13915 {
13916 region = new_omp_region (bb, code, parent);
13917 /* Otherwise... */
13918 if (code == GIMPLE_OMP_TARGET)
13919 {
13920 switch (gimple_omp_target_kind (stmt))
13921 {
13922 case GF_OMP_TARGET_KIND_REGION:
13923 case GF_OMP_TARGET_KIND_DATA:
13924 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
13925 case GF_OMP_TARGET_KIND_OACC_KERNELS:
13926 case GF_OMP_TARGET_KIND_OACC_DATA:
13927 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
13928 break;
13929 case GF_OMP_TARGET_KIND_UPDATE:
13930 case GF_OMP_TARGET_KIND_ENTER_DATA:
13931 case GF_OMP_TARGET_KIND_EXIT_DATA:
13932 case GF_OMP_TARGET_KIND_OACC_UPDATE:
13933 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
13934 case GF_OMP_TARGET_KIND_OACC_DECLARE:
13935 /* ..., other than for those stand-alone directives... */
13936 region = NULL;
13937 break;
13938 default:
13939 gcc_unreachable ();
13940 }
13941 }
13942 else if (code == GIMPLE_OMP_ORDERED
13943 && find_omp_clause (gimple_omp_ordered_clauses
13944 (as_a <gomp_ordered *> (stmt)),
13945 OMP_CLAUSE_DEPEND))
13946 /* #pragma omp ordered depend is also just a stand-alone
13947 directive. */
13948 region = NULL;
13949 /* ..., this directive becomes the parent for a new region. */
13950 if (region)
13951 parent = region;
13952 }
13953 }
13954
13955 if (single_tree && !parent)
13956 return;
13957
13958 for (son = first_dom_son (CDI_DOMINATORS, bb);
13959 son;
13960 son = next_dom_son (CDI_DOMINATORS, son))
13961 build_omp_regions_1 (son, parent, single_tree);
13962 }
13963
13964 /* Builds the tree of OMP regions rooted at ROOT, storing it to
13965 root_omp_region. */
13966
13967 static void
13968 build_omp_regions_root (basic_block root)
13969 {
13970 gcc_assert (root_omp_region == NULL);
13971 build_omp_regions_1 (root, NULL, true);
13972 gcc_assert (root_omp_region != NULL);
13973 }
13974
13975 /* Expands omp construct (and its subconstructs) starting in HEAD. */
13976
13977 void
13978 omp_expand_local (basic_block head)
13979 {
13980 build_omp_regions_root (head);
13981 if (dump_file && (dump_flags & TDF_DETAILS))
13982 {
13983 fprintf (dump_file, "\nOMP region tree\n\n");
13984 dump_omp_region (dump_file, root_omp_region, 0);
13985 fprintf (dump_file, "\n");
13986 }
13987
13988 remove_exit_barriers (root_omp_region);
13989 expand_omp (root_omp_region);
13990
13991 free_omp_regions ();
13992 }
13993
13994 /* Scan the CFG and build a tree of OMP regions. Return the root of
13995 the OMP region tree. */
13996
13997 static void
13998 build_omp_regions (void)
13999 {
14000 gcc_assert (root_omp_region == NULL);
14001 calculate_dominance_info (CDI_DOMINATORS);
14002 build_omp_regions_1 (ENTRY_BLOCK_PTR_FOR_FN (cfun), NULL, false);
14003 }
14004
14005 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
14006
14007 static unsigned int
14008 execute_expand_omp (void)
14009 {
14010 build_omp_regions ();
14011
14012 if (!root_omp_region)
14013 return 0;
14014
14015 if (dump_file)
14016 {
14017 fprintf (dump_file, "\nOMP region tree\n\n");
14018 dump_omp_region (dump_file, root_omp_region, 0);
14019 fprintf (dump_file, "\n");
14020 }
14021
14022 remove_exit_barriers (root_omp_region);
14023
14024 expand_omp (root_omp_region);
14025
14026 if (flag_checking && !loops_state_satisfies_p (LOOPS_NEED_FIXUP))
14027 verify_loop_structure ();
14028 cleanup_tree_cfg ();
14029
14030 free_omp_regions ();
14031
14032 return 0;
14033 }
14034
14035 /* OMP expansion -- the default pass, run before creation of SSA form. */
14036
14037 namespace {
14038
14039 const pass_data pass_data_expand_omp =
14040 {
14041 GIMPLE_PASS, /* type */
14042 "ompexp", /* name */
14043 OPTGROUP_NONE, /* optinfo_flags */
14044 TV_NONE, /* tv_id */
14045 PROP_gimple_any, /* properties_required */
14046 PROP_gimple_eomp, /* properties_provided */
14047 0, /* properties_destroyed */
14048 0, /* todo_flags_start */
14049 0, /* todo_flags_finish */
14050 };
14051
14052 class pass_expand_omp : public gimple_opt_pass
14053 {
14054 public:
14055 pass_expand_omp (gcc::context *ctxt)
14056 : gimple_opt_pass (pass_data_expand_omp, ctxt)
14057 {}
14058
14059 /* opt_pass methods: */
14060 virtual unsigned int execute (function *)
14061 {
14062 bool gate = ((flag_cilkplus != 0 || flag_openacc != 0 || flag_openmp != 0
14063 || flag_openmp_simd != 0)
14064 && !seen_error ());
14065
14066 /* This pass always runs, to provide PROP_gimple_eomp.
14067 But often, there is nothing to do. */
14068 if (!gate)
14069 return 0;
14070
14071 return execute_expand_omp ();
14072 }
14073
14074 }; // class pass_expand_omp
14075
14076 } // anon namespace
14077
14078 gimple_opt_pass *
14079 make_pass_expand_omp (gcc::context *ctxt)
14080 {
14081 return new pass_expand_omp (ctxt);
14082 }
14083
14084 namespace {
14085
14086 const pass_data pass_data_expand_omp_ssa =
14087 {
14088 GIMPLE_PASS, /* type */
14089 "ompexpssa", /* name */
14090 OPTGROUP_NONE, /* optinfo_flags */
14091 TV_NONE, /* tv_id */
14092 PROP_cfg | PROP_ssa, /* properties_required */
14093 PROP_gimple_eomp, /* properties_provided */
14094 0, /* properties_destroyed */
14095 0, /* todo_flags_start */
14096 TODO_cleanup_cfg | TODO_rebuild_alias, /* todo_flags_finish */
14097 };
14098
14099 class pass_expand_omp_ssa : public gimple_opt_pass
14100 {
14101 public:
14102 pass_expand_omp_ssa (gcc::context *ctxt)
14103 : gimple_opt_pass (pass_data_expand_omp_ssa, ctxt)
14104 {}
14105
14106 /* opt_pass methods: */
14107 virtual bool gate (function *fun)
14108 {
14109 return !(fun->curr_properties & PROP_gimple_eomp);
14110 }
14111 virtual unsigned int execute (function *) { return execute_expand_omp (); }
14112 opt_pass * clone () { return new pass_expand_omp_ssa (m_ctxt); }
14113
14114 }; // class pass_expand_omp_ssa
14115
14116 } // anon namespace
14117
14118 gimple_opt_pass *
14119 make_pass_expand_omp_ssa (gcc::context *ctxt)
14120 {
14121 return new pass_expand_omp_ssa (ctxt);
14122 }
14123 \f
14124 /* Routines to lower OMP directives into OMP-GIMPLE. */
14125
14126 /* If ctx is a worksharing context inside of a cancellable parallel
14127 region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
14128 and conditional branch to parallel's cancel_label to handle
14129 cancellation in the implicit barrier. */
14130
14131 static void
14132 maybe_add_implicit_barrier_cancel (omp_context *ctx, gimple_seq *body)
14133 {
14134 gimple *omp_return = gimple_seq_last_stmt (*body);
14135 gcc_assert (gimple_code (omp_return) == GIMPLE_OMP_RETURN);
14136 if (gimple_omp_return_nowait_p (omp_return))
14137 return;
14138 if (ctx->outer
14139 && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_PARALLEL
14140 && ctx->outer->cancellable)
14141 {
14142 tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL);
14143 tree c_bool_type = TREE_TYPE (TREE_TYPE (fndecl));
14144 tree lhs = create_tmp_var (c_bool_type);
14145 gimple_omp_return_set_lhs (omp_return, lhs);
14146 tree fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
14147 gimple *g = gimple_build_cond (NE_EXPR, lhs,
14148 fold_convert (c_bool_type,
14149 boolean_false_node),
14150 ctx->outer->cancel_label, fallthru_label);
14151 gimple_seq_add_stmt (body, g);
14152 gimple_seq_add_stmt (body, gimple_build_label (fallthru_label));
14153 }
14154 }
14155
14156 /* Lower the OpenMP sections directive in the current statement in GSI_P.
14157 CTX is the enclosing OMP context for the current statement. */
14158
14159 static void
14160 lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14161 {
14162 tree block, control;
14163 gimple_stmt_iterator tgsi;
14164 gomp_sections *stmt;
14165 gimple *t;
14166 gbind *new_stmt, *bind;
14167 gimple_seq ilist, dlist, olist, new_body;
14168
14169 stmt = as_a <gomp_sections *> (gsi_stmt (*gsi_p));
14170
14171 push_gimplify_context ();
14172
14173 dlist = NULL;
14174 ilist = NULL;
14175 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
14176 &ilist, &dlist, ctx, NULL);
14177
14178 new_body = gimple_omp_body (stmt);
14179 gimple_omp_set_body (stmt, NULL);
14180 tgsi = gsi_start (new_body);
14181 for (; !gsi_end_p (tgsi); gsi_next (&tgsi))
14182 {
14183 omp_context *sctx;
14184 gimple *sec_start;
14185
14186 sec_start = gsi_stmt (tgsi);
14187 sctx = maybe_lookup_ctx (sec_start);
14188 gcc_assert (sctx);
14189
14190 lower_omp (gimple_omp_body_ptr (sec_start), sctx);
14191 gsi_insert_seq_after (&tgsi, gimple_omp_body (sec_start),
14192 GSI_CONTINUE_LINKING);
14193 gimple_omp_set_body (sec_start, NULL);
14194
14195 if (gsi_one_before_end_p (tgsi))
14196 {
14197 gimple_seq l = NULL;
14198 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
14199 &l, ctx);
14200 gsi_insert_seq_after (&tgsi, l, GSI_CONTINUE_LINKING);
14201 gimple_omp_section_set_last (sec_start);
14202 }
14203
14204 gsi_insert_after (&tgsi, gimple_build_omp_return (false),
14205 GSI_CONTINUE_LINKING);
14206 }
14207
14208 block = make_node (BLOCK);
14209 bind = gimple_build_bind (NULL, new_body, block);
14210
14211 olist = NULL;
14212 lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist, ctx);
14213
14214 block = make_node (BLOCK);
14215 new_stmt = gimple_build_bind (NULL, NULL, block);
14216 gsi_replace (gsi_p, new_stmt, true);
14217
14218 pop_gimplify_context (new_stmt);
14219 gimple_bind_append_vars (new_stmt, ctx->block_vars);
14220 BLOCK_VARS (block) = gimple_bind_vars (bind);
14221 if (BLOCK_VARS (block))
14222 TREE_USED (block) = 1;
14223
14224 new_body = NULL;
14225 gimple_seq_add_seq (&new_body, ilist);
14226 gimple_seq_add_stmt (&new_body, stmt);
14227 gimple_seq_add_stmt (&new_body, gimple_build_omp_sections_switch ());
14228 gimple_seq_add_stmt (&new_body, bind);
14229
14230 control = create_tmp_var (unsigned_type_node, ".section");
14231 t = gimple_build_omp_continue (control, control);
14232 gimple_omp_sections_set_control (stmt, control);
14233 gimple_seq_add_stmt (&new_body, t);
14234
14235 gimple_seq_add_seq (&new_body, olist);
14236 if (ctx->cancellable)
14237 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
14238 gimple_seq_add_seq (&new_body, dlist);
14239
14240 new_body = maybe_catch_exception (new_body);
14241
14242 t = gimple_build_omp_return
14243 (!!find_omp_clause (gimple_omp_sections_clauses (stmt),
14244 OMP_CLAUSE_NOWAIT));
14245 gimple_seq_add_stmt (&new_body, t);
14246 maybe_add_implicit_barrier_cancel (ctx, &new_body);
14247
14248 gimple_bind_set_body (new_stmt, new_body);
14249 }
14250
14251
14252 /* A subroutine of lower_omp_single. Expand the simple form of
14253 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
14254
14255 if (GOMP_single_start ())
14256 BODY;
14257 [ GOMP_barrier (); ] -> unless 'nowait' is present.
14258
14259 FIXME. It may be better to delay expanding the logic of this until
14260 pass_expand_omp. The expanded logic may make the job more difficult
14261 to a synchronization analysis pass. */
14262
14263 static void
14264 lower_omp_single_simple (gomp_single *single_stmt, gimple_seq *pre_p)
14265 {
14266 location_t loc = gimple_location (single_stmt);
14267 tree tlabel = create_artificial_label (loc);
14268 tree flabel = create_artificial_label (loc);
14269 gimple *call, *cond;
14270 tree lhs, decl;
14271
14272 decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START);
14273 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)));
14274 call = gimple_build_call (decl, 0);
14275 gimple_call_set_lhs (call, lhs);
14276 gimple_seq_add_stmt (pre_p, call);
14277
14278 cond = gimple_build_cond (EQ_EXPR, lhs,
14279 fold_convert_loc (loc, TREE_TYPE (lhs),
14280 boolean_true_node),
14281 tlabel, flabel);
14282 gimple_seq_add_stmt (pre_p, cond);
14283 gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
14284 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
14285 gimple_seq_add_stmt (pre_p, gimple_build_label (flabel));
14286 }
14287
14288
14289 /* A subroutine of lower_omp_single. Expand the simple form of
14290 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
14291
14292 #pragma omp single copyprivate (a, b, c)
14293
14294 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
14295
14296 {
14297 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
14298 {
14299 BODY;
14300 copyout.a = a;
14301 copyout.b = b;
14302 copyout.c = c;
14303 GOMP_single_copy_end (&copyout);
14304 }
14305 else
14306 {
14307 a = copyout_p->a;
14308 b = copyout_p->b;
14309 c = copyout_p->c;
14310 }
14311 GOMP_barrier ();
14312 }
14313
14314 FIXME. It may be better to delay expanding the logic of this until
14315 pass_expand_omp. The expanded logic may make the job more difficult
14316 to a synchronization analysis pass. */
14317
14318 static void
14319 lower_omp_single_copy (gomp_single *single_stmt, gimple_seq *pre_p,
14320 omp_context *ctx)
14321 {
14322 tree ptr_type, t, l0, l1, l2, bfn_decl;
14323 gimple_seq copyin_seq;
14324 location_t loc = gimple_location (single_stmt);
14325
14326 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
14327
14328 ptr_type = build_pointer_type (ctx->record_type);
14329 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
14330
14331 l0 = create_artificial_label (loc);
14332 l1 = create_artificial_label (loc);
14333 l2 = create_artificial_label (loc);
14334
14335 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START);
14336 t = build_call_expr_loc (loc, bfn_decl, 0);
14337 t = fold_convert_loc (loc, ptr_type, t);
14338 gimplify_assign (ctx->receiver_decl, t, pre_p);
14339
14340 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
14341 build_int_cst (ptr_type, 0));
14342 t = build3 (COND_EXPR, void_type_node, t,
14343 build_and_jump (&l0), build_and_jump (&l1));
14344 gimplify_and_add (t, pre_p);
14345
14346 gimple_seq_add_stmt (pre_p, gimple_build_label (l0));
14347
14348 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
14349
14350 copyin_seq = NULL;
14351 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
14352 &copyin_seq, ctx);
14353
14354 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
14355 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END);
14356 t = build_call_expr_loc (loc, bfn_decl, 1, t);
14357 gimplify_and_add (t, pre_p);
14358
14359 t = build_and_jump (&l2);
14360 gimplify_and_add (t, pre_p);
14361
14362 gimple_seq_add_stmt (pre_p, gimple_build_label (l1));
14363
14364 gimple_seq_add_seq (pre_p, copyin_seq);
14365
14366 gimple_seq_add_stmt (pre_p, gimple_build_label (l2));
14367 }
14368
14369
14370 /* Expand code for an OpenMP single directive. */
14371
14372 static void
14373 lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14374 {
14375 tree block;
14376 gimple *t;
14377 gomp_single *single_stmt = as_a <gomp_single *> (gsi_stmt (*gsi_p));
14378 gbind *bind;
14379 gimple_seq bind_body, bind_body_tail = NULL, dlist;
14380
14381 push_gimplify_context ();
14382
14383 block = make_node (BLOCK);
14384 bind = gimple_build_bind (NULL, NULL, block);
14385 gsi_replace (gsi_p, bind, true);
14386 bind_body = NULL;
14387 dlist = NULL;
14388 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt),
14389 &bind_body, &dlist, ctx, NULL);
14390 lower_omp (gimple_omp_body_ptr (single_stmt), ctx);
14391
14392 gimple_seq_add_stmt (&bind_body, single_stmt);
14393
14394 if (ctx->record_type)
14395 lower_omp_single_copy (single_stmt, &bind_body, ctx);
14396 else
14397 lower_omp_single_simple (single_stmt, &bind_body);
14398
14399 gimple_omp_set_body (single_stmt, NULL);
14400
14401 gimple_seq_add_seq (&bind_body, dlist);
14402
14403 bind_body = maybe_catch_exception (bind_body);
14404
14405 t = gimple_build_omp_return
14406 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt),
14407 OMP_CLAUSE_NOWAIT));
14408 gimple_seq_add_stmt (&bind_body_tail, t);
14409 maybe_add_implicit_barrier_cancel (ctx, &bind_body_tail);
14410 if (ctx->record_type)
14411 {
14412 gimple_stmt_iterator gsi = gsi_start (bind_body_tail);
14413 tree clobber = build_constructor (ctx->record_type, NULL);
14414 TREE_THIS_VOLATILE (clobber) = 1;
14415 gsi_insert_after (&gsi, gimple_build_assign (ctx->sender_decl,
14416 clobber), GSI_SAME_STMT);
14417 }
14418 gimple_seq_add_seq (&bind_body, bind_body_tail);
14419 gimple_bind_set_body (bind, bind_body);
14420
14421 pop_gimplify_context (bind);
14422
14423 gimple_bind_append_vars (bind, ctx->block_vars);
14424 BLOCK_VARS (block) = ctx->block_vars;
14425 if (BLOCK_VARS (block))
14426 TREE_USED (block) = 1;
14427 }
14428
14429
14430 /* Expand code for an OpenMP master directive. */
14431
14432 static void
14433 lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14434 {
14435 tree block, lab = NULL, x, bfn_decl;
14436 gimple *stmt = gsi_stmt (*gsi_p);
14437 gbind *bind;
14438 location_t loc = gimple_location (stmt);
14439 gimple_seq tseq;
14440
14441 push_gimplify_context ();
14442
14443 block = make_node (BLOCK);
14444 bind = gimple_build_bind (NULL, NULL, block);
14445 gsi_replace (gsi_p, bind, true);
14446 gimple_bind_add_stmt (bind, stmt);
14447
14448 bfn_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
14449 x = build_call_expr_loc (loc, bfn_decl, 0);
14450 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
14451 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
14452 tseq = NULL;
14453 gimplify_and_add (x, &tseq);
14454 gimple_bind_add_seq (bind, tseq);
14455
14456 lower_omp (gimple_omp_body_ptr (stmt), ctx);
14457 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
14458 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
14459 gimple_omp_set_body (stmt, NULL);
14460
14461 gimple_bind_add_stmt (bind, gimple_build_label (lab));
14462
14463 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
14464
14465 pop_gimplify_context (bind);
14466
14467 gimple_bind_append_vars (bind, ctx->block_vars);
14468 BLOCK_VARS (block) = ctx->block_vars;
14469 }
14470
14471
14472 /* Expand code for an OpenMP taskgroup directive. */
14473
14474 static void
14475 lower_omp_taskgroup (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14476 {
14477 gimple *stmt = gsi_stmt (*gsi_p);
14478 gcall *x;
14479 gbind *bind;
14480 tree block = make_node (BLOCK);
14481
14482 bind = gimple_build_bind (NULL, NULL, block);
14483 gsi_replace (gsi_p, bind, true);
14484 gimple_bind_add_stmt (bind, stmt);
14485
14486 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START),
14487 0);
14488 gimple_bind_add_stmt (bind, x);
14489
14490 lower_omp (gimple_omp_body_ptr (stmt), ctx);
14491 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
14492 gimple_omp_set_body (stmt, NULL);
14493
14494 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
14495
14496 gimple_bind_append_vars (bind, ctx->block_vars);
14497 BLOCK_VARS (block) = ctx->block_vars;
14498 }
14499
14500
14501 /* Fold the OMP_ORDERED_CLAUSES for the OMP_ORDERED in STMT if possible. */
14502
14503 static void
14504 lower_omp_ordered_clauses (gimple_stmt_iterator *gsi_p, gomp_ordered *ord_stmt,
14505 omp_context *ctx)
14506 {
14507 struct omp_for_data fd;
14508 if (!ctx->outer || gimple_code (ctx->outer->stmt) != GIMPLE_OMP_FOR)
14509 return;
14510
14511 unsigned int len = gimple_omp_for_collapse (ctx->outer->stmt);
14512 struct omp_for_data_loop *loops = XALLOCAVEC (struct omp_for_data_loop, len);
14513 extract_omp_for_data (as_a <gomp_for *> (ctx->outer->stmt), &fd, loops);
14514 if (!fd.ordered)
14515 return;
14516
14517 tree *list_p = gimple_omp_ordered_clauses_ptr (ord_stmt);
14518 tree c = gimple_omp_ordered_clauses (ord_stmt);
14519 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
14520 && OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK)
14521 {
14522 /* Merge depend clauses from multiple adjacent
14523 #pragma omp ordered depend(sink:...) constructs
14524 into one #pragma omp ordered depend(sink:...), so that
14525 we can optimize them together. */
14526 gimple_stmt_iterator gsi = *gsi_p;
14527 gsi_next (&gsi);
14528 while (!gsi_end_p (gsi))
14529 {
14530 gimple *stmt = gsi_stmt (gsi);
14531 if (is_gimple_debug (stmt)
14532 || gimple_code (stmt) == GIMPLE_NOP)
14533 {
14534 gsi_next (&gsi);
14535 continue;
14536 }
14537 if (gimple_code (stmt) != GIMPLE_OMP_ORDERED)
14538 break;
14539 gomp_ordered *ord_stmt2 = as_a <gomp_ordered *> (stmt);
14540 c = gimple_omp_ordered_clauses (ord_stmt2);
14541 if (c == NULL_TREE
14542 || OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND
14543 || OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_SINK)
14544 break;
14545 while (*list_p)
14546 list_p = &OMP_CLAUSE_CHAIN (*list_p);
14547 *list_p = c;
14548 gsi_remove (&gsi, true);
14549 }
14550 }
14551
14552 /* Canonicalize sink dependence clauses into one folded clause if
14553 possible.
14554
14555 The basic algorithm is to create a sink vector whose first
14556 element is the GCD of all the first elements, and whose remaining
14557 elements are the minimum of the subsequent columns.
14558
14559 We ignore dependence vectors whose first element is zero because
14560 such dependencies are known to be executed by the same thread.
14561
14562 We take into account the direction of the loop, so a minimum
14563 becomes a maximum if the loop is iterating forwards. We also
14564 ignore sink clauses where the loop direction is unknown, or where
14565 the offsets are clearly invalid because they are not a multiple
14566 of the loop increment.
14567
14568 For example:
14569
14570 #pragma omp for ordered(2)
14571 for (i=0; i < N; ++i)
14572 for (j=0; j < M; ++j)
14573 {
14574 #pragma omp ordered \
14575 depend(sink:i-8,j-2) \
14576 depend(sink:i,j-1) \ // Completely ignored because i+0.
14577 depend(sink:i-4,j-3) \
14578 depend(sink:i-6,j-4)
14579 #pragma omp ordered depend(source)
14580 }
14581
14582 Folded clause is:
14583
14584 depend(sink:-gcd(8,4,6),-min(2,3,4))
14585 -or-
14586 depend(sink:-2,-2)
14587 */
14588
14589 /* FIXME: Computing GCD's where the first element is zero is
14590 non-trivial in the presence of collapsed loops. Do this later. */
14591 if (fd.collapse > 1)
14592 return;
14593
14594 wide_int *folded_deps = XALLOCAVEC (wide_int, 2 * len - 1);
14595 memset (folded_deps, 0, sizeof (*folded_deps) * (2 * len - 1));
14596 tree folded_dep = NULL_TREE;
14597 /* TRUE if the first dimension's offset is negative. */
14598 bool neg_offset_p = false;
14599
14600 list_p = gimple_omp_ordered_clauses_ptr (ord_stmt);
14601 unsigned int i;
14602 while ((c = *list_p) != NULL)
14603 {
14604 bool remove = false;
14605
14606 gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND);
14607 if (OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_SINK)
14608 goto next_ordered_clause;
14609
14610 tree vec;
14611 for (vec = OMP_CLAUSE_DECL (c), i = 0;
14612 vec && TREE_CODE (vec) == TREE_LIST;
14613 vec = TREE_CHAIN (vec), ++i)
14614 {
14615 gcc_assert (i < len);
14616
14617 /* extract_omp_for_data has canonicalized the condition. */
14618 gcc_assert (fd.loops[i].cond_code == LT_EXPR
14619 || fd.loops[i].cond_code == GT_EXPR);
14620 bool forward = fd.loops[i].cond_code == LT_EXPR;
14621 bool maybe_lexically_later = true;
14622
14623 /* While the committee makes up its mind, bail if we have any
14624 non-constant steps. */
14625 if (TREE_CODE (fd.loops[i].step) != INTEGER_CST)
14626 goto lower_omp_ordered_ret;
14627
14628 tree itype = TREE_TYPE (TREE_VALUE (vec));
14629 if (POINTER_TYPE_P (itype))
14630 itype = sizetype;
14631 wide_int offset = wide_int::from (TREE_PURPOSE (vec),
14632 TYPE_PRECISION (itype),
14633 TYPE_SIGN (itype));
14634
14635 /* Ignore invalid offsets that are not multiples of the step. */
14636 if (!wi::multiple_of_p
14637 (wi::abs (offset), wi::abs ((wide_int) fd.loops[i].step),
14638 UNSIGNED))
14639 {
14640 warning_at (OMP_CLAUSE_LOCATION (c), 0,
14641 "ignoring sink clause with offset that is not "
14642 "a multiple of the loop step");
14643 remove = true;
14644 goto next_ordered_clause;
14645 }
14646
14647 /* Calculate the first dimension. The first dimension of
14648 the folded dependency vector is the GCD of the first
14649 elements, while ignoring any first elements whose offset
14650 is 0. */
14651 if (i == 0)
14652 {
14653 /* Ignore dependence vectors whose first dimension is 0. */
14654 if (offset == 0)
14655 {
14656 remove = true;
14657 goto next_ordered_clause;
14658 }
14659 else
14660 {
14661 if (!TYPE_UNSIGNED (itype) && (forward ^ wi::neg_p (offset)))
14662 {
14663 error_at (OMP_CLAUSE_LOCATION (c),
14664 "first offset must be in opposite direction "
14665 "of loop iterations");
14666 goto lower_omp_ordered_ret;
14667 }
14668 if (forward)
14669 offset = -offset;
14670 neg_offset_p = forward;
14671 /* Initialize the first time around. */
14672 if (folded_dep == NULL_TREE)
14673 {
14674 folded_dep = c;
14675 folded_deps[0] = offset;
14676 }
14677 else
14678 folded_deps[0] = wi::gcd (folded_deps[0],
14679 offset, UNSIGNED);
14680 }
14681 }
14682 /* Calculate minimum for the remaining dimensions. */
14683 else
14684 {
14685 folded_deps[len + i - 1] = offset;
14686 if (folded_dep == c)
14687 folded_deps[i] = offset;
14688 else if (maybe_lexically_later
14689 && !wi::eq_p (folded_deps[i], offset))
14690 {
14691 if (forward ^ wi::gts_p (folded_deps[i], offset))
14692 {
14693 unsigned int j;
14694 folded_dep = c;
14695 for (j = 1; j <= i; j++)
14696 folded_deps[j] = folded_deps[len + j - 1];
14697 }
14698 else
14699 maybe_lexically_later = false;
14700 }
14701 }
14702 }
14703 gcc_assert (i == len);
14704
14705 remove = true;
14706
14707 next_ordered_clause:
14708 if (remove)
14709 *list_p = OMP_CLAUSE_CHAIN (c);
14710 else
14711 list_p = &OMP_CLAUSE_CHAIN (c);
14712 }
14713
14714 if (folded_dep)
14715 {
14716 if (neg_offset_p)
14717 folded_deps[0] = -folded_deps[0];
14718
14719 tree itype = TREE_TYPE (TREE_VALUE (OMP_CLAUSE_DECL (folded_dep)));
14720 if (POINTER_TYPE_P (itype))
14721 itype = sizetype;
14722
14723 TREE_PURPOSE (OMP_CLAUSE_DECL (folded_dep))
14724 = wide_int_to_tree (itype, folded_deps[0]);
14725 OMP_CLAUSE_CHAIN (folded_dep) = gimple_omp_ordered_clauses (ord_stmt);
14726 *gimple_omp_ordered_clauses_ptr (ord_stmt) = folded_dep;
14727 }
14728
14729 lower_omp_ordered_ret:
14730
14731 /* Ordered without clauses is #pragma omp threads, while we want
14732 a nop instead if we remove all clauses. */
14733 if (gimple_omp_ordered_clauses (ord_stmt) == NULL_TREE)
14734 gsi_replace (gsi_p, gimple_build_nop (), true);
14735 }
14736
14737
14738 /* Expand code for an OpenMP ordered directive. */
14739
14740 static void
14741 lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14742 {
14743 tree block;
14744 gimple *stmt = gsi_stmt (*gsi_p);
14745 gomp_ordered *ord_stmt = as_a <gomp_ordered *> (stmt);
14746 gcall *x;
14747 gbind *bind;
14748 bool simd = find_omp_clause (gimple_omp_ordered_clauses (ord_stmt),
14749 OMP_CLAUSE_SIMD);
14750 bool threads = find_omp_clause (gimple_omp_ordered_clauses (ord_stmt),
14751 OMP_CLAUSE_THREADS);
14752
14753 if (find_omp_clause (gimple_omp_ordered_clauses (ord_stmt),
14754 OMP_CLAUSE_DEPEND))
14755 {
14756 /* FIXME: This is needs to be moved to the expansion to verify various
14757 conditions only testable on cfg with dominators computed, and also
14758 all the depend clauses to be merged still might need to be available
14759 for the runtime checks. */
14760 if (0)
14761 lower_omp_ordered_clauses (gsi_p, ord_stmt, ctx);
14762 return;
14763 }
14764
14765 push_gimplify_context ();
14766
14767 block = make_node (BLOCK);
14768 bind = gimple_build_bind (NULL, NULL, block);
14769 gsi_replace (gsi_p, bind, true);
14770 gimple_bind_add_stmt (bind, stmt);
14771
14772 if (simd)
14773 {
14774 x = gimple_build_call_internal (IFN_GOMP_SIMD_ORDERED_START, 1,
14775 build_int_cst (NULL_TREE, threads));
14776 cfun->has_simduid_loops = true;
14777 }
14778 else
14779 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START),
14780 0);
14781 gimple_bind_add_stmt (bind, x);
14782
14783 lower_omp (gimple_omp_body_ptr (stmt), ctx);
14784 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
14785 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
14786 gimple_omp_set_body (stmt, NULL);
14787
14788 if (simd)
14789 x = gimple_build_call_internal (IFN_GOMP_SIMD_ORDERED_END, 1,
14790 build_int_cst (NULL_TREE, threads));
14791 else
14792 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END),
14793 0);
14794 gimple_bind_add_stmt (bind, x);
14795
14796 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
14797
14798 pop_gimplify_context (bind);
14799
14800 gimple_bind_append_vars (bind, ctx->block_vars);
14801 BLOCK_VARS (block) = gimple_bind_vars (bind);
14802 }
14803
14804
14805 /* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
14806 substitution of a couple of function calls. But in the NAMED case,
14807 requires that languages coordinate a symbol name. It is therefore
14808 best put here in common code. */
14809
14810 static GTY(()) hash_map<tree, tree> *critical_name_mutexes;
14811
14812 static void
14813 lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14814 {
14815 tree block;
14816 tree name, lock, unlock;
14817 gomp_critical *stmt = as_a <gomp_critical *> (gsi_stmt (*gsi_p));
14818 gbind *bind;
14819 location_t loc = gimple_location (stmt);
14820 gimple_seq tbody;
14821
14822 name = gimple_omp_critical_name (stmt);
14823 if (name)
14824 {
14825 tree decl;
14826
14827 if (!critical_name_mutexes)
14828 critical_name_mutexes = hash_map<tree, tree>::create_ggc (10);
14829
14830 tree *n = critical_name_mutexes->get (name);
14831 if (n == NULL)
14832 {
14833 char *new_str;
14834
14835 decl = create_tmp_var_raw (ptr_type_node);
14836
14837 new_str = ACONCAT ((".gomp_critical_user_",
14838 IDENTIFIER_POINTER (name), NULL));
14839 DECL_NAME (decl) = get_identifier (new_str);
14840 TREE_PUBLIC (decl) = 1;
14841 TREE_STATIC (decl) = 1;
14842 DECL_COMMON (decl) = 1;
14843 DECL_ARTIFICIAL (decl) = 1;
14844 DECL_IGNORED_P (decl) = 1;
14845
14846 varpool_node::finalize_decl (decl);
14847
14848 critical_name_mutexes->put (name, decl);
14849 }
14850 else
14851 decl = *n;
14852
14853 /* If '#pragma omp critical' is inside offloaded region or
14854 inside function marked as offloadable, the symbol must be
14855 marked as offloadable too. */
14856 omp_context *octx;
14857 if (cgraph_node::get (current_function_decl)->offloadable)
14858 varpool_node::get_create (decl)->offloadable = 1;
14859 else
14860 for (octx = ctx->outer; octx; octx = octx->outer)
14861 if (is_gimple_omp_offloaded (octx->stmt))
14862 {
14863 varpool_node::get_create (decl)->offloadable = 1;
14864 break;
14865 }
14866
14867 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START);
14868 lock = build_call_expr_loc (loc, lock, 1, build_fold_addr_expr_loc (loc, decl));
14869
14870 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END);
14871 unlock = build_call_expr_loc (loc, unlock, 1,
14872 build_fold_addr_expr_loc (loc, decl));
14873 }
14874 else
14875 {
14876 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START);
14877 lock = build_call_expr_loc (loc, lock, 0);
14878
14879 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END);
14880 unlock = build_call_expr_loc (loc, unlock, 0);
14881 }
14882
14883 push_gimplify_context ();
14884
14885 block = make_node (BLOCK);
14886 bind = gimple_build_bind (NULL, NULL, block);
14887 gsi_replace (gsi_p, bind, true);
14888 gimple_bind_add_stmt (bind, stmt);
14889
14890 tbody = gimple_bind_body (bind);
14891 gimplify_and_add (lock, &tbody);
14892 gimple_bind_set_body (bind, tbody);
14893
14894 lower_omp (gimple_omp_body_ptr (stmt), ctx);
14895 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
14896 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
14897 gimple_omp_set_body (stmt, NULL);
14898
14899 tbody = gimple_bind_body (bind);
14900 gimplify_and_add (unlock, &tbody);
14901 gimple_bind_set_body (bind, tbody);
14902
14903 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
14904
14905 pop_gimplify_context (bind);
14906 gimple_bind_append_vars (bind, ctx->block_vars);
14907 BLOCK_VARS (block) = gimple_bind_vars (bind);
14908 }
14909
14910
14911 /* A subroutine of lower_omp_for. Generate code to emit the predicate
14912 for a lastprivate clause. Given a loop control predicate of (V
14913 cond N2), we gate the clause on (!(V cond N2)). The lowered form
14914 is appended to *DLIST, iterator initialization is appended to
14915 *BODY_P. */
14916
14917 static void
14918 lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
14919 gimple_seq *dlist, struct omp_context *ctx)
14920 {
14921 tree clauses, cond, vinit;
14922 enum tree_code cond_code;
14923 gimple_seq stmts;
14924
14925 cond_code = fd->loop.cond_code;
14926 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
14927
14928 /* When possible, use a strict equality expression. This can let VRP
14929 type optimizations deduce the value and remove a copy. */
14930 if (tree_fits_shwi_p (fd->loop.step))
14931 {
14932 HOST_WIDE_INT step = tree_to_shwi (fd->loop.step);
14933 if (step == 1 || step == -1)
14934 cond_code = EQ_EXPR;
14935 }
14936
14937 tree n2 = fd->loop.n2;
14938 if (fd->collapse > 1
14939 && TREE_CODE (n2) != INTEGER_CST
14940 && gimple_omp_for_combined_into_p (fd->for_stmt))
14941 {
14942 struct omp_context *taskreg_ctx = NULL;
14943 if (gimple_code (ctx->outer->stmt) == GIMPLE_OMP_FOR)
14944 {
14945 gomp_for *gfor = as_a <gomp_for *> (ctx->outer->stmt);
14946 if (gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_FOR
14947 || gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_DISTRIBUTE)
14948 {
14949 if (gimple_omp_for_combined_into_p (gfor))
14950 {
14951 gcc_assert (ctx->outer->outer
14952 && is_parallel_ctx (ctx->outer->outer));
14953 taskreg_ctx = ctx->outer->outer;
14954 }
14955 else
14956 {
14957 struct omp_for_data outer_fd;
14958 extract_omp_for_data (gfor, &outer_fd, NULL);
14959 n2 = fold_convert (TREE_TYPE (n2), outer_fd.loop.n2);
14960 }
14961 }
14962 else if (gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_TASKLOOP)
14963 taskreg_ctx = ctx->outer->outer;
14964 }
14965 else if (is_taskreg_ctx (ctx->outer))
14966 taskreg_ctx = ctx->outer;
14967 if (taskreg_ctx)
14968 {
14969 int i;
14970 tree innerc
14971 = find_omp_clause (gimple_omp_taskreg_clauses (taskreg_ctx->stmt),
14972 OMP_CLAUSE__LOOPTEMP_);
14973 gcc_assert (innerc);
14974 for (i = 0; i < fd->collapse; i++)
14975 {
14976 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
14977 OMP_CLAUSE__LOOPTEMP_);
14978 gcc_assert (innerc);
14979 }
14980 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
14981 OMP_CLAUSE__LOOPTEMP_);
14982 if (innerc)
14983 n2 = fold_convert (TREE_TYPE (n2),
14984 lookup_decl (OMP_CLAUSE_DECL (innerc),
14985 taskreg_ctx));
14986 }
14987 }
14988 cond = build2 (cond_code, boolean_type_node, fd->loop.v, n2);
14989
14990 clauses = gimple_omp_for_clauses (fd->for_stmt);
14991 stmts = NULL;
14992 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
14993 if (!gimple_seq_empty_p (stmts))
14994 {
14995 gimple_seq_add_seq (&stmts, *dlist);
14996 *dlist = stmts;
14997
14998 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
14999 vinit = fd->loop.n1;
15000 if (cond_code == EQ_EXPR
15001 && tree_fits_shwi_p (fd->loop.n2)
15002 && ! integer_zerop (fd->loop.n2))
15003 vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0);
15004 else
15005 vinit = unshare_expr (vinit);
15006
15007 /* Initialize the iterator variable, so that threads that don't execute
15008 any iterations don't execute the lastprivate clauses by accident. */
15009 gimplify_assign (fd->loop.v, vinit, body_p);
15010 }
15011 }
15012
15013
15014 /* Lower code for an OMP loop directive. */
15015
15016 static void
15017 lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
15018 {
15019 tree *rhs_p, block;
15020 struct omp_for_data fd, *fdp = NULL;
15021 gomp_for *stmt = as_a <gomp_for *> (gsi_stmt (*gsi_p));
15022 gbind *new_stmt;
15023 gimple_seq omp_for_body, body, dlist;
15024 gimple_seq oacc_head = NULL, oacc_tail = NULL;
15025 size_t i;
15026
15027 push_gimplify_context ();
15028
15029 lower_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
15030
15031 block = make_node (BLOCK);
15032 new_stmt = gimple_build_bind (NULL, NULL, block);
15033 /* Replace at gsi right away, so that 'stmt' is no member
15034 of a sequence anymore as we're going to add to a different
15035 one below. */
15036 gsi_replace (gsi_p, new_stmt, true);
15037
15038 /* Move declaration of temporaries in the loop body before we make
15039 it go away. */
15040 omp_for_body = gimple_omp_body (stmt);
15041 if (!gimple_seq_empty_p (omp_for_body)
15042 && gimple_code (gimple_seq_first_stmt (omp_for_body)) == GIMPLE_BIND)
15043 {
15044 gbind *inner_bind
15045 = as_a <gbind *> (gimple_seq_first_stmt (omp_for_body));
15046 tree vars = gimple_bind_vars (inner_bind);
15047 gimple_bind_append_vars (new_stmt, vars);
15048 /* bind_vars/BLOCK_VARS are being moved to new_stmt/block, don't
15049 keep them on the inner_bind and it's block. */
15050 gimple_bind_set_vars (inner_bind, NULL_TREE);
15051 if (gimple_bind_block (inner_bind))
15052 BLOCK_VARS (gimple_bind_block (inner_bind)) = NULL_TREE;
15053 }
15054
15055 if (gimple_omp_for_combined_into_p (stmt))
15056 {
15057 extract_omp_for_data (stmt, &fd, NULL);
15058 fdp = &fd;
15059
15060 /* We need two temporaries with fd.loop.v type (istart/iend)
15061 and then (fd.collapse - 1) temporaries with the same
15062 type for count2 ... countN-1 vars if not constant. */
15063 size_t count = 2;
15064 tree type = fd.iter_type;
15065 if (fd.collapse > 1
15066 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
15067 count += fd.collapse - 1;
15068 bool taskreg_for
15069 = (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR
15070 || gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_TASKLOOP);
15071 tree outerc = NULL, *pc = gimple_omp_for_clauses_ptr (stmt);
15072 tree clauses = *pc;
15073 if (taskreg_for)
15074 outerc
15075 = find_omp_clause (gimple_omp_taskreg_clauses (ctx->outer->stmt),
15076 OMP_CLAUSE__LOOPTEMP_);
15077 for (i = 0; i < count; i++)
15078 {
15079 tree temp;
15080 if (taskreg_for)
15081 {
15082 gcc_assert (outerc);
15083 temp = lookup_decl (OMP_CLAUSE_DECL (outerc), ctx->outer);
15084 outerc = find_omp_clause (OMP_CLAUSE_CHAIN (outerc),
15085 OMP_CLAUSE__LOOPTEMP_);
15086 }
15087 else
15088 {
15089 temp = create_tmp_var (type);
15090 insert_decl_map (&ctx->outer->cb, temp, temp);
15091 }
15092 *pc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
15093 OMP_CLAUSE_DECL (*pc) = temp;
15094 pc = &OMP_CLAUSE_CHAIN (*pc);
15095 }
15096 *pc = clauses;
15097 }
15098
15099 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
15100 dlist = NULL;
15101 body = NULL;
15102 lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx,
15103 fdp);
15104 gimple_seq_add_seq (&body, gimple_omp_for_pre_body (stmt));
15105
15106 lower_omp (gimple_omp_body_ptr (stmt), ctx);
15107
15108 /* Lower the header expressions. At this point, we can assume that
15109 the header is of the form:
15110
15111 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
15112
15113 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
15114 using the .omp_data_s mapping, if needed. */
15115 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
15116 {
15117 rhs_p = gimple_omp_for_initial_ptr (stmt, i);
15118 if (!is_gimple_min_invariant (*rhs_p))
15119 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
15120
15121 rhs_p = gimple_omp_for_final_ptr (stmt, i);
15122 if (!is_gimple_min_invariant (*rhs_p))
15123 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
15124
15125 rhs_p = &TREE_OPERAND (gimple_omp_for_incr (stmt, i), 1);
15126 if (!is_gimple_min_invariant (*rhs_p))
15127 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
15128 }
15129
15130 /* Once lowered, extract the bounds and clauses. */
15131 extract_omp_for_data (stmt, &fd, NULL);
15132
15133 if (is_gimple_omp_oacc (ctx->stmt)
15134 && !ctx_in_oacc_kernels_region (ctx))
15135 lower_oacc_head_tail (gimple_location (stmt),
15136 gimple_omp_for_clauses (stmt),
15137 &oacc_head, &oacc_tail, ctx);
15138
15139 /* Add OpenACC partitioning and reduction markers just before the loop */
15140 if (oacc_head)
15141 gimple_seq_add_seq (&body, oacc_head);
15142
15143 lower_omp_for_lastprivate (&fd, &body, &dlist, ctx);
15144
15145 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR)
15146 for (tree c = gimple_omp_for_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
15147 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
15148 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
15149 {
15150 OMP_CLAUSE_DECL (c) = lookup_decl (OMP_CLAUSE_DECL (c), ctx);
15151 if (DECL_P (OMP_CLAUSE_LINEAR_STEP (c)))
15152 OMP_CLAUSE_LINEAR_STEP (c)
15153 = maybe_lookup_decl_in_outer_ctx (OMP_CLAUSE_LINEAR_STEP (c),
15154 ctx);
15155 }
15156
15157 if (!gimple_omp_for_grid_phony (stmt))
15158 gimple_seq_add_stmt (&body, stmt);
15159 gimple_seq_add_seq (&body, gimple_omp_body (stmt));
15160
15161 if (!gimple_omp_for_grid_phony (stmt))
15162 gimple_seq_add_stmt (&body, gimple_build_omp_continue (fd.loop.v,
15163 fd.loop.v));
15164
15165 /* After the loop, add exit clauses. */
15166 lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, ctx);
15167
15168 if (ctx->cancellable)
15169 gimple_seq_add_stmt (&body, gimple_build_label (ctx->cancel_label));
15170
15171 gimple_seq_add_seq (&body, dlist);
15172
15173 body = maybe_catch_exception (body);
15174
15175 if (!gimple_omp_for_grid_phony (stmt))
15176 {
15177 /* Region exit marker goes at the end of the loop body. */
15178 gimple_seq_add_stmt (&body, gimple_build_omp_return (fd.have_nowait));
15179 maybe_add_implicit_barrier_cancel (ctx, &body);
15180 }
15181
15182 /* Add OpenACC joining and reduction markers just after the loop. */
15183 if (oacc_tail)
15184 gimple_seq_add_seq (&body, oacc_tail);
15185
15186 pop_gimplify_context (new_stmt);
15187
15188 gimple_bind_append_vars (new_stmt, ctx->block_vars);
15189 BLOCK_VARS (block) = gimple_bind_vars (new_stmt);
15190 if (BLOCK_VARS (block))
15191 TREE_USED (block) = 1;
15192
15193 gimple_bind_set_body (new_stmt, body);
15194 gimple_omp_set_body (stmt, NULL);
15195 gimple_omp_for_set_pre_body (stmt, NULL);
15196 }
15197
15198 /* Callback for walk_stmts. Check if the current statement only contains
15199 GIMPLE_OMP_FOR or GIMPLE_OMP_SECTIONS. */
15200
15201 static tree
15202 check_combined_parallel (gimple_stmt_iterator *gsi_p,
15203 bool *handled_ops_p,
15204 struct walk_stmt_info *wi)
15205 {
15206 int *info = (int *) wi->info;
15207 gimple *stmt = gsi_stmt (*gsi_p);
15208
15209 *handled_ops_p = true;
15210 switch (gimple_code (stmt))
15211 {
15212 WALK_SUBSTMTS;
15213
15214 case GIMPLE_OMP_FOR:
15215 case GIMPLE_OMP_SECTIONS:
15216 *info = *info == 0 ? 1 : -1;
15217 break;
15218 default:
15219 *info = -1;
15220 break;
15221 }
15222 return NULL;
15223 }
15224
15225 struct omp_taskcopy_context
15226 {
15227 /* This field must be at the beginning, as we do "inheritance": Some
15228 callback functions for tree-inline.c (e.g., omp_copy_decl)
15229 receive a copy_body_data pointer that is up-casted to an
15230 omp_context pointer. */
15231 copy_body_data cb;
15232 omp_context *ctx;
15233 };
15234
15235 static tree
15236 task_copyfn_copy_decl (tree var, copy_body_data *cb)
15237 {
15238 struct omp_taskcopy_context *tcctx = (struct omp_taskcopy_context *) cb;
15239
15240 if (splay_tree_lookup (tcctx->ctx->sfield_map, (splay_tree_key) var))
15241 return create_tmp_var (TREE_TYPE (var));
15242
15243 return var;
15244 }
15245
15246 static tree
15247 task_copyfn_remap_type (struct omp_taskcopy_context *tcctx, tree orig_type)
15248 {
15249 tree name, new_fields = NULL, type, f;
15250
15251 type = lang_hooks.types.make_type (RECORD_TYPE);
15252 name = DECL_NAME (TYPE_NAME (orig_type));
15253 name = build_decl (gimple_location (tcctx->ctx->stmt),
15254 TYPE_DECL, name, type);
15255 TYPE_NAME (type) = name;
15256
15257 for (f = TYPE_FIELDS (orig_type); f ; f = TREE_CHAIN (f))
15258 {
15259 tree new_f = copy_node (f);
15260 DECL_CONTEXT (new_f) = type;
15261 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &tcctx->cb);
15262 TREE_CHAIN (new_f) = new_fields;
15263 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &tcctx->cb, NULL);
15264 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r, &tcctx->cb, NULL);
15265 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
15266 &tcctx->cb, NULL);
15267 new_fields = new_f;
15268 tcctx->cb.decl_map->put (f, new_f);
15269 }
15270 TYPE_FIELDS (type) = nreverse (new_fields);
15271 layout_type (type);
15272 return type;
15273 }
15274
15275 /* Create task copyfn. */
15276
15277 static void
15278 create_task_copyfn (gomp_task *task_stmt, omp_context *ctx)
15279 {
15280 struct function *child_cfun;
15281 tree child_fn, t, c, src, dst, f, sf, arg, sarg, decl;
15282 tree record_type, srecord_type, bind, list;
15283 bool record_needs_remap = false, srecord_needs_remap = false;
15284 splay_tree_node n;
15285 struct omp_taskcopy_context tcctx;
15286 location_t loc = gimple_location (task_stmt);
15287
15288 child_fn = gimple_omp_task_copy_fn (task_stmt);
15289 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
15290 gcc_assert (child_cfun->cfg == NULL);
15291 DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
15292
15293 /* Reset DECL_CONTEXT on function arguments. */
15294 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
15295 DECL_CONTEXT (t) = child_fn;
15296
15297 /* Populate the function. */
15298 push_gimplify_context ();
15299 push_cfun (child_cfun);
15300
15301 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
15302 TREE_SIDE_EFFECTS (bind) = 1;
15303 list = NULL;
15304 DECL_SAVED_TREE (child_fn) = bind;
15305 DECL_SOURCE_LOCATION (child_fn) = gimple_location (task_stmt);
15306
15307 /* Remap src and dst argument types if needed. */
15308 record_type = ctx->record_type;
15309 srecord_type = ctx->srecord_type;
15310 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
15311 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
15312 {
15313 record_needs_remap = true;
15314 break;
15315 }
15316 for (f = TYPE_FIELDS (srecord_type); f ; f = DECL_CHAIN (f))
15317 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
15318 {
15319 srecord_needs_remap = true;
15320 break;
15321 }
15322
15323 if (record_needs_remap || srecord_needs_remap)
15324 {
15325 memset (&tcctx, '\0', sizeof (tcctx));
15326 tcctx.cb.src_fn = ctx->cb.src_fn;
15327 tcctx.cb.dst_fn = child_fn;
15328 tcctx.cb.src_node = cgraph_node::get (tcctx.cb.src_fn);
15329 gcc_checking_assert (tcctx.cb.src_node);
15330 tcctx.cb.dst_node = tcctx.cb.src_node;
15331 tcctx.cb.src_cfun = ctx->cb.src_cfun;
15332 tcctx.cb.copy_decl = task_copyfn_copy_decl;
15333 tcctx.cb.eh_lp_nr = 0;
15334 tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
15335 tcctx.cb.decl_map = new hash_map<tree, tree>;
15336 tcctx.ctx = ctx;
15337
15338 if (record_needs_remap)
15339 record_type = task_copyfn_remap_type (&tcctx, record_type);
15340 if (srecord_needs_remap)
15341 srecord_type = task_copyfn_remap_type (&tcctx, srecord_type);
15342 }
15343 else
15344 tcctx.cb.decl_map = NULL;
15345
15346 arg = DECL_ARGUMENTS (child_fn);
15347 TREE_TYPE (arg) = build_pointer_type (record_type);
15348 sarg = DECL_CHAIN (arg);
15349 TREE_TYPE (sarg) = build_pointer_type (srecord_type);
15350
15351 /* First pass: initialize temporaries used in record_type and srecord_type
15352 sizes and field offsets. */
15353 if (tcctx.cb.decl_map)
15354 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
15355 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
15356 {
15357 tree *p;
15358
15359 decl = OMP_CLAUSE_DECL (c);
15360 p = tcctx.cb.decl_map->get (decl);
15361 if (p == NULL)
15362 continue;
15363 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
15364 sf = (tree) n->value;
15365 sf = *tcctx.cb.decl_map->get (sf);
15366 src = build_simple_mem_ref_loc (loc, sarg);
15367 src = omp_build_component_ref (src, sf);
15368 t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
15369 append_to_statement_list (t, &list);
15370 }
15371
15372 /* Second pass: copy shared var pointers and copy construct non-VLA
15373 firstprivate vars. */
15374 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
15375 switch (OMP_CLAUSE_CODE (c))
15376 {
15377 splay_tree_key key;
15378 case OMP_CLAUSE_SHARED:
15379 decl = OMP_CLAUSE_DECL (c);
15380 key = (splay_tree_key) decl;
15381 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
15382 key = (splay_tree_key) &DECL_UID (decl);
15383 n = splay_tree_lookup (ctx->field_map, key);
15384 if (n == NULL)
15385 break;
15386 f = (tree) n->value;
15387 if (tcctx.cb.decl_map)
15388 f = *tcctx.cb.decl_map->get (f);
15389 n = splay_tree_lookup (ctx->sfield_map, key);
15390 sf = (tree) n->value;
15391 if (tcctx.cb.decl_map)
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 dst = build_simple_mem_ref_loc (loc, arg);
15396 dst = omp_build_component_ref (dst, f);
15397 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
15398 append_to_statement_list (t, &list);
15399 break;
15400 case OMP_CLAUSE_FIRSTPRIVATE:
15401 decl = OMP_CLAUSE_DECL (c);
15402 if (is_variable_sized (decl))
15403 break;
15404 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
15405 if (n == NULL)
15406 break;
15407 f = (tree) n->value;
15408 if (tcctx.cb.decl_map)
15409 f = *tcctx.cb.decl_map->get (f);
15410 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
15411 if (n != NULL)
15412 {
15413 sf = (tree) n->value;
15414 if (tcctx.cb.decl_map)
15415 sf = *tcctx.cb.decl_map->get (sf);
15416 src = build_simple_mem_ref_loc (loc, sarg);
15417 src = omp_build_component_ref (src, sf);
15418 if (use_pointer_for_field (decl, NULL) || is_reference (decl))
15419 src = build_simple_mem_ref_loc (loc, src);
15420 }
15421 else
15422 src = decl;
15423 dst = build_simple_mem_ref_loc (loc, arg);
15424 dst = omp_build_component_ref (dst, f);
15425 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
15426 append_to_statement_list (t, &list);
15427 break;
15428 case OMP_CLAUSE_PRIVATE:
15429 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c))
15430 break;
15431 decl = OMP_CLAUSE_DECL (c);
15432 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
15433 f = (tree) n->value;
15434 if (tcctx.cb.decl_map)
15435 f = *tcctx.cb.decl_map->get (f);
15436 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
15437 if (n != NULL)
15438 {
15439 sf = (tree) n->value;
15440 if (tcctx.cb.decl_map)
15441 sf = *tcctx.cb.decl_map->get (sf);
15442 src = build_simple_mem_ref_loc (loc, sarg);
15443 src = omp_build_component_ref (src, sf);
15444 if (use_pointer_for_field (decl, NULL))
15445 src = build_simple_mem_ref_loc (loc, src);
15446 }
15447 else
15448 src = decl;
15449 dst = build_simple_mem_ref_loc (loc, arg);
15450 dst = omp_build_component_ref (dst, f);
15451 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
15452 append_to_statement_list (t, &list);
15453 break;
15454 default:
15455 break;
15456 }
15457
15458 /* Last pass: handle VLA firstprivates. */
15459 if (tcctx.cb.decl_map)
15460 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
15461 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
15462 {
15463 tree ind, ptr, df;
15464
15465 decl = OMP_CLAUSE_DECL (c);
15466 if (!is_variable_sized (decl))
15467 continue;
15468 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
15469 if (n == NULL)
15470 continue;
15471 f = (tree) n->value;
15472 f = *tcctx.cb.decl_map->get (f);
15473 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
15474 ind = DECL_VALUE_EXPR (decl);
15475 gcc_assert (TREE_CODE (ind) == INDIRECT_REF);
15476 gcc_assert (DECL_P (TREE_OPERAND (ind, 0)));
15477 n = splay_tree_lookup (ctx->sfield_map,
15478 (splay_tree_key) TREE_OPERAND (ind, 0));
15479 sf = (tree) n->value;
15480 sf = *tcctx.cb.decl_map->get (sf);
15481 src = build_simple_mem_ref_loc (loc, sarg);
15482 src = omp_build_component_ref (src, sf);
15483 src = build_simple_mem_ref_loc (loc, src);
15484 dst = build_simple_mem_ref_loc (loc, arg);
15485 dst = omp_build_component_ref (dst, f);
15486 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
15487 append_to_statement_list (t, &list);
15488 n = splay_tree_lookup (ctx->field_map,
15489 (splay_tree_key) TREE_OPERAND (ind, 0));
15490 df = (tree) n->value;
15491 df = *tcctx.cb.decl_map->get (df);
15492 ptr = build_simple_mem_ref_loc (loc, arg);
15493 ptr = omp_build_component_ref (ptr, df);
15494 t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
15495 build_fold_addr_expr_loc (loc, dst));
15496 append_to_statement_list (t, &list);
15497 }
15498
15499 t = build1 (RETURN_EXPR, void_type_node, NULL);
15500 append_to_statement_list (t, &list);
15501
15502 if (tcctx.cb.decl_map)
15503 delete tcctx.cb.decl_map;
15504 pop_gimplify_context (NULL);
15505 BIND_EXPR_BODY (bind) = list;
15506 pop_cfun ();
15507 }
15508
15509 static void
15510 lower_depend_clauses (tree *pclauses, gimple_seq *iseq, gimple_seq *oseq)
15511 {
15512 tree c, clauses;
15513 gimple *g;
15514 size_t n_in = 0, n_out = 0, idx = 2, i;
15515
15516 clauses = find_omp_clause (*pclauses, OMP_CLAUSE_DEPEND);
15517 gcc_assert (clauses);
15518 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
15519 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
15520 switch (OMP_CLAUSE_DEPEND_KIND (c))
15521 {
15522 case OMP_CLAUSE_DEPEND_IN:
15523 n_in++;
15524 break;
15525 case OMP_CLAUSE_DEPEND_OUT:
15526 case OMP_CLAUSE_DEPEND_INOUT:
15527 n_out++;
15528 break;
15529 case OMP_CLAUSE_DEPEND_SOURCE:
15530 case OMP_CLAUSE_DEPEND_SINK:
15531 /* FALLTHRU */
15532 default:
15533 gcc_unreachable ();
15534 }
15535 tree type = build_array_type_nelts (ptr_type_node, n_in + n_out + 2);
15536 tree array = create_tmp_var (type);
15537 TREE_ADDRESSABLE (array) = 1;
15538 tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
15539 NULL_TREE);
15540 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_in + n_out));
15541 gimple_seq_add_stmt (iseq, g);
15542 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
15543 NULL_TREE);
15544 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_out));
15545 gimple_seq_add_stmt (iseq, g);
15546 for (i = 0; i < 2; i++)
15547 {
15548 if ((i ? n_in : n_out) == 0)
15549 continue;
15550 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
15551 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
15552 && ((OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_IN) ^ i))
15553 {
15554 tree t = OMP_CLAUSE_DECL (c);
15555 t = fold_convert (ptr_type_node, t);
15556 gimplify_expr (&t, iseq, NULL, is_gimple_val, fb_rvalue);
15557 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (idx++),
15558 NULL_TREE, NULL_TREE);
15559 g = gimple_build_assign (r, t);
15560 gimple_seq_add_stmt (iseq, g);
15561 }
15562 }
15563 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
15564 OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
15565 OMP_CLAUSE_CHAIN (c) = *pclauses;
15566 *pclauses = c;
15567 tree clobber = build_constructor (type, NULL);
15568 TREE_THIS_VOLATILE (clobber) = 1;
15569 g = gimple_build_assign (array, clobber);
15570 gimple_seq_add_stmt (oseq, g);
15571 }
15572
15573 /* Lower the OpenMP parallel or task directive in the current statement
15574 in GSI_P. CTX holds context information for the directive. */
15575
15576 static void
15577 lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
15578 {
15579 tree clauses;
15580 tree child_fn, t;
15581 gimple *stmt = gsi_stmt (*gsi_p);
15582 gbind *par_bind, *bind, *dep_bind = NULL;
15583 gimple_seq par_body, olist, ilist, par_olist, par_rlist, par_ilist, new_body;
15584 location_t loc = gimple_location (stmt);
15585
15586 clauses = gimple_omp_taskreg_clauses (stmt);
15587 par_bind
15588 = as_a <gbind *> (gimple_seq_first_stmt (gimple_omp_body (stmt)));
15589 par_body = gimple_bind_body (par_bind);
15590 child_fn = ctx->cb.dst_fn;
15591 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
15592 && !gimple_omp_parallel_combined_p (stmt))
15593 {
15594 struct walk_stmt_info wi;
15595 int ws_num = 0;
15596
15597 memset (&wi, 0, sizeof (wi));
15598 wi.info = &ws_num;
15599 wi.val_only = true;
15600 walk_gimple_seq (par_body, check_combined_parallel, NULL, &wi);
15601 if (ws_num == 1)
15602 gimple_omp_parallel_set_combined_p (stmt, true);
15603 }
15604 gimple_seq dep_ilist = NULL;
15605 gimple_seq dep_olist = NULL;
15606 if (gimple_code (stmt) == GIMPLE_OMP_TASK
15607 && find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
15608 {
15609 push_gimplify_context ();
15610 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
15611 lower_depend_clauses (gimple_omp_task_clauses_ptr (stmt),
15612 &dep_ilist, &dep_olist);
15613 }
15614
15615 if (ctx->srecord_type)
15616 create_task_copyfn (as_a <gomp_task *> (stmt), ctx);
15617
15618 push_gimplify_context ();
15619
15620 par_olist = NULL;
15621 par_ilist = NULL;
15622 par_rlist = NULL;
15623 bool phony_construct = gimple_code (stmt) == GIMPLE_OMP_PARALLEL
15624 && gimple_omp_parallel_grid_phony (as_a <gomp_parallel *> (stmt));
15625 if (phony_construct && ctx->record_type)
15626 {
15627 gcc_checking_assert (!ctx->receiver_decl);
15628 ctx->receiver_decl = create_tmp_var
15629 (build_reference_type (ctx->record_type), ".omp_rec");
15630 }
15631 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx, NULL);
15632 lower_omp (&par_body, ctx);
15633 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL)
15634 lower_reduction_clauses (clauses, &par_rlist, ctx);
15635
15636 /* Declare all the variables created by mapping and the variables
15637 declared in the scope of the parallel body. */
15638 record_vars_into (ctx->block_vars, child_fn);
15639 record_vars_into (gimple_bind_vars (par_bind), child_fn);
15640
15641 if (ctx->record_type)
15642 {
15643 ctx->sender_decl
15644 = create_tmp_var (ctx->srecord_type ? ctx->srecord_type
15645 : ctx->record_type, ".omp_data_o");
15646 DECL_NAMELESS (ctx->sender_decl) = 1;
15647 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
15648 gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl);
15649 }
15650
15651 olist = NULL;
15652 ilist = NULL;
15653 lower_send_clauses (clauses, &ilist, &olist, ctx);
15654 lower_send_shared_vars (&ilist, &olist, ctx);
15655
15656 if (ctx->record_type)
15657 {
15658 tree clobber = build_constructor (TREE_TYPE (ctx->sender_decl), NULL);
15659 TREE_THIS_VOLATILE (clobber) = 1;
15660 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
15661 clobber));
15662 }
15663
15664 /* Once all the expansions are done, sequence all the different
15665 fragments inside gimple_omp_body. */
15666
15667 new_body = NULL;
15668
15669 if (ctx->record_type)
15670 {
15671 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
15672 /* fixup_child_record_type might have changed receiver_decl's type. */
15673 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
15674 gimple_seq_add_stmt (&new_body,
15675 gimple_build_assign (ctx->receiver_decl, t));
15676 }
15677
15678 gimple_seq_add_seq (&new_body, par_ilist);
15679 gimple_seq_add_seq (&new_body, par_body);
15680 gimple_seq_add_seq (&new_body, par_rlist);
15681 if (ctx->cancellable)
15682 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
15683 gimple_seq_add_seq (&new_body, par_olist);
15684 new_body = maybe_catch_exception (new_body);
15685 if (gimple_code (stmt) == GIMPLE_OMP_TASK)
15686 gimple_seq_add_stmt (&new_body,
15687 gimple_build_omp_continue (integer_zero_node,
15688 integer_zero_node));
15689 if (!phony_construct)
15690 {
15691 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
15692 gimple_omp_set_body (stmt, new_body);
15693 }
15694
15695 bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
15696 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
15697 gimple_bind_add_seq (bind, ilist);
15698 if (!phony_construct)
15699 gimple_bind_add_stmt (bind, stmt);
15700 else
15701 gimple_bind_add_seq (bind, new_body);
15702 gimple_bind_add_seq (bind, olist);
15703
15704 pop_gimplify_context (NULL);
15705
15706 if (dep_bind)
15707 {
15708 gimple_bind_add_seq (dep_bind, dep_ilist);
15709 gimple_bind_add_stmt (dep_bind, bind);
15710 gimple_bind_add_seq (dep_bind, dep_olist);
15711 pop_gimplify_context (dep_bind);
15712 }
15713 }
15714
15715 /* Lower the GIMPLE_OMP_TARGET in the current statement
15716 in GSI_P. CTX holds context information for the directive. */
15717
15718 static void
15719 lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
15720 {
15721 tree clauses;
15722 tree child_fn, t, c;
15723 gomp_target *stmt = as_a <gomp_target *> (gsi_stmt (*gsi_p));
15724 gbind *tgt_bind, *bind, *dep_bind = NULL;
15725 gimple_seq tgt_body, olist, ilist, fplist, new_body;
15726 location_t loc = gimple_location (stmt);
15727 bool offloaded, data_region;
15728 unsigned int map_cnt = 0;
15729
15730 offloaded = is_gimple_omp_offloaded (stmt);
15731 switch (gimple_omp_target_kind (stmt))
15732 {
15733 case GF_OMP_TARGET_KIND_REGION:
15734 case GF_OMP_TARGET_KIND_UPDATE:
15735 case GF_OMP_TARGET_KIND_ENTER_DATA:
15736 case GF_OMP_TARGET_KIND_EXIT_DATA:
15737 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
15738 case GF_OMP_TARGET_KIND_OACC_KERNELS:
15739 case GF_OMP_TARGET_KIND_OACC_UPDATE:
15740 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
15741 case GF_OMP_TARGET_KIND_OACC_DECLARE:
15742 data_region = false;
15743 break;
15744 case GF_OMP_TARGET_KIND_DATA:
15745 case GF_OMP_TARGET_KIND_OACC_DATA:
15746 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
15747 data_region = true;
15748 break;
15749 default:
15750 gcc_unreachable ();
15751 }
15752
15753 clauses = gimple_omp_target_clauses (stmt);
15754
15755 gimple_seq dep_ilist = NULL;
15756 gimple_seq dep_olist = NULL;
15757 if (find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
15758 {
15759 push_gimplify_context ();
15760 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
15761 lower_depend_clauses (gimple_omp_target_clauses_ptr (stmt),
15762 &dep_ilist, &dep_olist);
15763 }
15764
15765 tgt_bind = NULL;
15766 tgt_body = NULL;
15767 if (offloaded)
15768 {
15769 tgt_bind = gimple_seq_first_stmt_as_a_bind (gimple_omp_body (stmt));
15770 tgt_body = gimple_bind_body (tgt_bind);
15771 }
15772 else if (data_region)
15773 tgt_body = gimple_omp_body (stmt);
15774 child_fn = ctx->cb.dst_fn;
15775
15776 push_gimplify_context ();
15777 fplist = NULL;
15778
15779 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
15780 switch (OMP_CLAUSE_CODE (c))
15781 {
15782 tree var, x;
15783
15784 default:
15785 break;
15786 case OMP_CLAUSE_MAP:
15787 #if CHECKING_P
15788 /* First check what we're prepared to handle in the following. */
15789 switch (OMP_CLAUSE_MAP_KIND (c))
15790 {
15791 case GOMP_MAP_ALLOC:
15792 case GOMP_MAP_TO:
15793 case GOMP_MAP_FROM:
15794 case GOMP_MAP_TOFROM:
15795 case GOMP_MAP_POINTER:
15796 case GOMP_MAP_TO_PSET:
15797 case GOMP_MAP_DELETE:
15798 case GOMP_MAP_RELEASE:
15799 case GOMP_MAP_ALWAYS_TO:
15800 case GOMP_MAP_ALWAYS_FROM:
15801 case GOMP_MAP_ALWAYS_TOFROM:
15802 case GOMP_MAP_FIRSTPRIVATE_POINTER:
15803 case GOMP_MAP_FIRSTPRIVATE_REFERENCE:
15804 case GOMP_MAP_STRUCT:
15805 case GOMP_MAP_ALWAYS_POINTER:
15806 break;
15807 case GOMP_MAP_FORCE_ALLOC:
15808 case GOMP_MAP_FORCE_TO:
15809 case GOMP_MAP_FORCE_FROM:
15810 case GOMP_MAP_FORCE_TOFROM:
15811 case GOMP_MAP_FORCE_PRESENT:
15812 case GOMP_MAP_FORCE_DEVICEPTR:
15813 case GOMP_MAP_DEVICE_RESIDENT:
15814 case GOMP_MAP_LINK:
15815 gcc_assert (is_gimple_omp_oacc (stmt));
15816 break;
15817 default:
15818 gcc_unreachable ();
15819 }
15820 #endif
15821 /* FALLTHRU */
15822 case OMP_CLAUSE_TO:
15823 case OMP_CLAUSE_FROM:
15824 oacc_firstprivate:
15825 var = OMP_CLAUSE_DECL (c);
15826 if (!DECL_P (var))
15827 {
15828 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
15829 || (!OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
15830 && (OMP_CLAUSE_MAP_KIND (c)
15831 != GOMP_MAP_FIRSTPRIVATE_POINTER)))
15832 map_cnt++;
15833 continue;
15834 }
15835
15836 if (DECL_SIZE (var)
15837 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
15838 {
15839 tree var2 = DECL_VALUE_EXPR (var);
15840 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
15841 var2 = TREE_OPERAND (var2, 0);
15842 gcc_assert (DECL_P (var2));
15843 var = var2;
15844 }
15845
15846 if (offloaded
15847 && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
15848 && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
15849 || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_REFERENCE))
15850 {
15851 if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
15852 {
15853 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx))
15854 && varpool_node::get_create (var)->offloadable)
15855 continue;
15856
15857 tree type = build_pointer_type (TREE_TYPE (var));
15858 tree new_var = lookup_decl (var, ctx);
15859 x = create_tmp_var_raw (type, get_name (new_var));
15860 gimple_add_tmp_var (x);
15861 x = build_simple_mem_ref (x);
15862 SET_DECL_VALUE_EXPR (new_var, x);
15863 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15864 }
15865 continue;
15866 }
15867
15868 if (!maybe_lookup_field (var, ctx))
15869 continue;
15870
15871 /* Don't remap oacc parallel reduction variables, because the
15872 intermediate result must be local to each gang. */
15873 if (offloaded && !(OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
15874 && OMP_CLAUSE_MAP_IN_REDUCTION (c)))
15875 {
15876 x = build_receiver_ref (var, true, ctx);
15877 tree new_var = lookup_decl (var, ctx);
15878
15879 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
15880 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
15881 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
15882 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
15883 x = build_simple_mem_ref (x);
15884 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
15885 {
15886 gcc_assert (is_gimple_omp_oacc (ctx->stmt));
15887 if (is_reference (new_var))
15888 {
15889 /* Create a local object to hold the instance
15890 value. */
15891 tree type = TREE_TYPE (TREE_TYPE (new_var));
15892 const char *id = IDENTIFIER_POINTER (DECL_NAME (new_var));
15893 tree inst = create_tmp_var (type, id);
15894 gimplify_assign (inst, fold_indirect_ref (x), &fplist);
15895 x = build_fold_addr_expr (inst);
15896 }
15897 gimplify_assign (new_var, x, &fplist);
15898 }
15899 else if (DECL_P (new_var))
15900 {
15901 SET_DECL_VALUE_EXPR (new_var, x);
15902 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15903 }
15904 else
15905 gcc_unreachable ();
15906 }
15907 map_cnt++;
15908 break;
15909
15910 case OMP_CLAUSE_FIRSTPRIVATE:
15911 if (is_oacc_parallel (ctx))
15912 goto oacc_firstprivate;
15913 map_cnt++;
15914 var = OMP_CLAUSE_DECL (c);
15915 if (!is_reference (var)
15916 && !is_gimple_reg_type (TREE_TYPE (var)))
15917 {
15918 tree new_var = lookup_decl (var, ctx);
15919 if (is_variable_sized (var))
15920 {
15921 tree pvar = DECL_VALUE_EXPR (var);
15922 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15923 pvar = TREE_OPERAND (pvar, 0);
15924 gcc_assert (DECL_P (pvar));
15925 tree new_pvar = lookup_decl (pvar, ctx);
15926 x = build_fold_indirect_ref (new_pvar);
15927 TREE_THIS_NOTRAP (x) = 1;
15928 }
15929 else
15930 x = build_receiver_ref (var, true, ctx);
15931 SET_DECL_VALUE_EXPR (new_var, x);
15932 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15933 }
15934 break;
15935
15936 case OMP_CLAUSE_PRIVATE:
15937 if (is_gimple_omp_oacc (ctx->stmt))
15938 break;
15939 var = OMP_CLAUSE_DECL (c);
15940 if (is_variable_sized (var))
15941 {
15942 tree new_var = lookup_decl (var, ctx);
15943 tree pvar = DECL_VALUE_EXPR (var);
15944 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15945 pvar = TREE_OPERAND (pvar, 0);
15946 gcc_assert (DECL_P (pvar));
15947 tree new_pvar = lookup_decl (pvar, ctx);
15948 x = build_fold_indirect_ref (new_pvar);
15949 TREE_THIS_NOTRAP (x) = 1;
15950 SET_DECL_VALUE_EXPR (new_var, x);
15951 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15952 }
15953 break;
15954
15955 case OMP_CLAUSE_USE_DEVICE_PTR:
15956 case OMP_CLAUSE_IS_DEVICE_PTR:
15957 var = OMP_CLAUSE_DECL (c);
15958 map_cnt++;
15959 if (is_variable_sized (var))
15960 {
15961 tree new_var = lookup_decl (var, ctx);
15962 tree pvar = DECL_VALUE_EXPR (var);
15963 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15964 pvar = TREE_OPERAND (pvar, 0);
15965 gcc_assert (DECL_P (pvar));
15966 tree new_pvar = lookup_decl (pvar, ctx);
15967 x = build_fold_indirect_ref (new_pvar);
15968 TREE_THIS_NOTRAP (x) = 1;
15969 SET_DECL_VALUE_EXPR (new_var, x);
15970 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15971 }
15972 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
15973 {
15974 tree new_var = lookup_decl (var, ctx);
15975 tree type = build_pointer_type (TREE_TYPE (var));
15976 x = create_tmp_var_raw (type, get_name (new_var));
15977 gimple_add_tmp_var (x);
15978 x = build_simple_mem_ref (x);
15979 SET_DECL_VALUE_EXPR (new_var, x);
15980 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15981 }
15982 else
15983 {
15984 tree new_var = lookup_decl (var, ctx);
15985 x = create_tmp_var_raw (TREE_TYPE (new_var), get_name (new_var));
15986 gimple_add_tmp_var (x);
15987 SET_DECL_VALUE_EXPR (new_var, x);
15988 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15989 }
15990 break;
15991 }
15992
15993 if (offloaded)
15994 {
15995 target_nesting_level++;
15996 lower_omp (&tgt_body, ctx);
15997 target_nesting_level--;
15998 }
15999 else if (data_region)
16000 lower_omp (&tgt_body, ctx);
16001
16002 if (offloaded)
16003 {
16004 /* Declare all the variables created by mapping and the variables
16005 declared in the scope of the target body. */
16006 record_vars_into (ctx->block_vars, child_fn);
16007 record_vars_into (gimple_bind_vars (tgt_bind), child_fn);
16008 }
16009
16010 olist = NULL;
16011 ilist = NULL;
16012 if (ctx->record_type)
16013 {
16014 ctx->sender_decl
16015 = create_tmp_var (ctx->record_type, ".omp_data_arr");
16016 DECL_NAMELESS (ctx->sender_decl) = 1;
16017 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
16018 t = make_tree_vec (3);
16019 TREE_VEC_ELT (t, 0) = ctx->sender_decl;
16020 TREE_VEC_ELT (t, 1)
16021 = create_tmp_var (build_array_type_nelts (size_type_node, map_cnt),
16022 ".omp_data_sizes");
16023 DECL_NAMELESS (TREE_VEC_ELT (t, 1)) = 1;
16024 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 1)) = 1;
16025 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 1;
16026 tree tkind_type = short_unsigned_type_node;
16027 int talign_shift = 8;
16028 TREE_VEC_ELT (t, 2)
16029 = create_tmp_var (build_array_type_nelts (tkind_type, map_cnt),
16030 ".omp_data_kinds");
16031 DECL_NAMELESS (TREE_VEC_ELT (t, 2)) = 1;
16032 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 2)) = 1;
16033 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 1;
16034 gimple_omp_target_set_data_arg (stmt, t);
16035
16036 vec<constructor_elt, va_gc> *vsize;
16037 vec<constructor_elt, va_gc> *vkind;
16038 vec_alloc (vsize, map_cnt);
16039 vec_alloc (vkind, map_cnt);
16040 unsigned int map_idx = 0;
16041
16042 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
16043 switch (OMP_CLAUSE_CODE (c))
16044 {
16045 tree ovar, nc, s, purpose, var, x, type;
16046 unsigned int talign;
16047
16048 default:
16049 break;
16050
16051 case OMP_CLAUSE_MAP:
16052 case OMP_CLAUSE_TO:
16053 case OMP_CLAUSE_FROM:
16054 oacc_firstprivate_map:
16055 nc = c;
16056 ovar = OMP_CLAUSE_DECL (c);
16057 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
16058 && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
16059 || (OMP_CLAUSE_MAP_KIND (c)
16060 == GOMP_MAP_FIRSTPRIVATE_REFERENCE)))
16061 break;
16062 if (!DECL_P (ovar))
16063 {
16064 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
16065 && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
16066 {
16067 gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c))
16068 == get_base_address (ovar));
16069 nc = OMP_CLAUSE_CHAIN (c);
16070 ovar = OMP_CLAUSE_DECL (nc);
16071 }
16072 else
16073 {
16074 tree x = build_sender_ref (ovar, ctx);
16075 tree v
16076 = build_fold_addr_expr_with_type (ovar, ptr_type_node);
16077 gimplify_assign (x, v, &ilist);
16078 nc = NULL_TREE;
16079 }
16080 }
16081 else
16082 {
16083 if (DECL_SIZE (ovar)
16084 && TREE_CODE (DECL_SIZE (ovar)) != INTEGER_CST)
16085 {
16086 tree ovar2 = DECL_VALUE_EXPR (ovar);
16087 gcc_assert (TREE_CODE (ovar2) == INDIRECT_REF);
16088 ovar2 = TREE_OPERAND (ovar2, 0);
16089 gcc_assert (DECL_P (ovar2));
16090 ovar = ovar2;
16091 }
16092 if (!maybe_lookup_field (ovar, ctx))
16093 continue;
16094 }
16095
16096 talign = TYPE_ALIGN_UNIT (TREE_TYPE (ovar));
16097 if (DECL_P (ovar) && DECL_ALIGN_UNIT (ovar) > talign)
16098 talign = DECL_ALIGN_UNIT (ovar);
16099 if (nc)
16100 {
16101 var = lookup_decl_in_outer_ctx (ovar, ctx);
16102 x = build_sender_ref (ovar, ctx);
16103
16104 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
16105 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
16106 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
16107 && TREE_CODE (TREE_TYPE (ovar)) == ARRAY_TYPE)
16108 {
16109 gcc_assert (offloaded);
16110 tree avar
16111 = create_tmp_var (TREE_TYPE (TREE_TYPE (x)));
16112 mark_addressable (avar);
16113 gimplify_assign (avar, build_fold_addr_expr (var), &ilist);
16114 talign = DECL_ALIGN_UNIT (avar);
16115 avar = build_fold_addr_expr (avar);
16116 gimplify_assign (x, avar, &ilist);
16117 }
16118 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
16119 {
16120 gcc_assert (is_gimple_omp_oacc (ctx->stmt));
16121 if (!is_reference (var))
16122 {
16123 if (is_gimple_reg (var)
16124 && OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c))
16125 TREE_NO_WARNING (var) = 1;
16126 var = build_fold_addr_expr (var);
16127 }
16128 else
16129 talign = TYPE_ALIGN_UNIT (TREE_TYPE (TREE_TYPE (ovar)));
16130 gimplify_assign (x, var, &ilist);
16131 }
16132 else if (is_gimple_reg (var))
16133 {
16134 gcc_assert (offloaded);
16135 tree avar = create_tmp_var (TREE_TYPE (var));
16136 mark_addressable (avar);
16137 enum gomp_map_kind map_kind = OMP_CLAUSE_MAP_KIND (c);
16138 if (GOMP_MAP_COPY_TO_P (map_kind)
16139 || map_kind == GOMP_MAP_POINTER
16140 || map_kind == GOMP_MAP_TO_PSET
16141 || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
16142 {
16143 /* If we need to initialize a temporary
16144 with VAR because it is not addressable, and
16145 the variable hasn't been initialized yet, then
16146 we'll get a warning for the store to avar.
16147 Don't warn in that case, the mapping might
16148 be implicit. */
16149 TREE_NO_WARNING (var) = 1;
16150 gimplify_assign (avar, var, &ilist);
16151 }
16152 avar = build_fold_addr_expr (avar);
16153 gimplify_assign (x, avar, &ilist);
16154 if ((GOMP_MAP_COPY_FROM_P (map_kind)
16155 || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
16156 && !TYPE_READONLY (TREE_TYPE (var)))
16157 {
16158 x = unshare_expr (x);
16159 x = build_simple_mem_ref (x);
16160 gimplify_assign (var, x, &olist);
16161 }
16162 }
16163 else
16164 {
16165 var = build_fold_addr_expr (var);
16166 gimplify_assign (x, var, &ilist);
16167 }
16168 }
16169 s = NULL_TREE;
16170 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
16171 {
16172 gcc_checking_assert (is_gimple_omp_oacc (ctx->stmt));
16173 s = TREE_TYPE (ovar);
16174 if (TREE_CODE (s) == REFERENCE_TYPE)
16175 s = TREE_TYPE (s);
16176 s = TYPE_SIZE_UNIT (s);
16177 }
16178 else
16179 s = OMP_CLAUSE_SIZE (c);
16180 if (s == NULL_TREE)
16181 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
16182 s = fold_convert (size_type_node, s);
16183 purpose = size_int (map_idx++);
16184 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
16185 if (TREE_CODE (s) != INTEGER_CST)
16186 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
16187
16188 unsigned HOST_WIDE_INT tkind, tkind_zero;
16189 switch (OMP_CLAUSE_CODE (c))
16190 {
16191 case OMP_CLAUSE_MAP:
16192 tkind = OMP_CLAUSE_MAP_KIND (c);
16193 tkind_zero = tkind;
16194 if (OMP_CLAUSE_MAP_MAYBE_ZERO_LENGTH_ARRAY_SECTION (c))
16195 switch (tkind)
16196 {
16197 case GOMP_MAP_ALLOC:
16198 case GOMP_MAP_TO:
16199 case GOMP_MAP_FROM:
16200 case GOMP_MAP_TOFROM:
16201 case GOMP_MAP_ALWAYS_TO:
16202 case GOMP_MAP_ALWAYS_FROM:
16203 case GOMP_MAP_ALWAYS_TOFROM:
16204 case GOMP_MAP_RELEASE:
16205 tkind_zero = GOMP_MAP_ZERO_LEN_ARRAY_SECTION;
16206 break;
16207 case GOMP_MAP_DELETE:
16208 tkind_zero = GOMP_MAP_DELETE_ZERO_LEN_ARRAY_SECTION;
16209 default:
16210 break;
16211 }
16212 if (tkind_zero != tkind)
16213 {
16214 if (integer_zerop (s))
16215 tkind = tkind_zero;
16216 else if (integer_nonzerop (s))
16217 tkind_zero = tkind;
16218 }
16219 break;
16220 case OMP_CLAUSE_FIRSTPRIVATE:
16221 gcc_checking_assert (is_gimple_omp_oacc (ctx->stmt));
16222 tkind = GOMP_MAP_TO;
16223 tkind_zero = tkind;
16224 break;
16225 case OMP_CLAUSE_TO:
16226 tkind = GOMP_MAP_TO;
16227 tkind_zero = tkind;
16228 break;
16229 case OMP_CLAUSE_FROM:
16230 tkind = GOMP_MAP_FROM;
16231 tkind_zero = tkind;
16232 break;
16233 default:
16234 gcc_unreachable ();
16235 }
16236 gcc_checking_assert (tkind
16237 < (HOST_WIDE_INT_C (1U) << talign_shift));
16238 gcc_checking_assert (tkind_zero
16239 < (HOST_WIDE_INT_C (1U) << talign_shift));
16240 talign = ceil_log2 (talign);
16241 tkind |= talign << talign_shift;
16242 tkind_zero |= talign << talign_shift;
16243 gcc_checking_assert (tkind
16244 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
16245 gcc_checking_assert (tkind_zero
16246 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
16247 if (tkind == tkind_zero)
16248 x = build_int_cstu (tkind_type, tkind);
16249 else
16250 {
16251 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 0;
16252 x = build3 (COND_EXPR, tkind_type,
16253 fold_build2 (EQ_EXPR, boolean_type_node,
16254 unshare_expr (s), size_zero_node),
16255 build_int_cstu (tkind_type, tkind_zero),
16256 build_int_cstu (tkind_type, tkind));
16257 }
16258 CONSTRUCTOR_APPEND_ELT (vkind, purpose, x);
16259 if (nc && nc != c)
16260 c = nc;
16261 break;
16262
16263 case OMP_CLAUSE_FIRSTPRIVATE:
16264 if (is_oacc_parallel (ctx))
16265 goto oacc_firstprivate_map;
16266 ovar = OMP_CLAUSE_DECL (c);
16267 if (is_reference (ovar))
16268 talign = TYPE_ALIGN_UNIT (TREE_TYPE (TREE_TYPE (ovar)));
16269 else
16270 talign = DECL_ALIGN_UNIT (ovar);
16271 var = lookup_decl_in_outer_ctx (ovar, ctx);
16272 x = build_sender_ref (ovar, ctx);
16273 tkind = GOMP_MAP_FIRSTPRIVATE;
16274 type = TREE_TYPE (ovar);
16275 if (is_reference (ovar))
16276 type = TREE_TYPE (type);
16277 if ((INTEGRAL_TYPE_P (type)
16278 && TYPE_PRECISION (type) <= POINTER_SIZE)
16279 || TREE_CODE (type) == POINTER_TYPE)
16280 {
16281 tkind = GOMP_MAP_FIRSTPRIVATE_INT;
16282 tree t = var;
16283 if (is_reference (var))
16284 t = build_simple_mem_ref (var);
16285 else if (OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c))
16286 TREE_NO_WARNING (var) = 1;
16287 if (TREE_CODE (type) != POINTER_TYPE)
16288 t = fold_convert (pointer_sized_int_node, t);
16289 t = fold_convert (TREE_TYPE (x), t);
16290 gimplify_assign (x, t, &ilist);
16291 }
16292 else if (is_reference (var))
16293 gimplify_assign (x, var, &ilist);
16294 else if (is_gimple_reg (var))
16295 {
16296 tree avar = create_tmp_var (TREE_TYPE (var));
16297 mark_addressable (avar);
16298 if (OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c))
16299 TREE_NO_WARNING (var) = 1;
16300 gimplify_assign (avar, var, &ilist);
16301 avar = build_fold_addr_expr (avar);
16302 gimplify_assign (x, avar, &ilist);
16303 }
16304 else
16305 {
16306 var = build_fold_addr_expr (var);
16307 gimplify_assign (x, var, &ilist);
16308 }
16309 if (tkind == GOMP_MAP_FIRSTPRIVATE_INT)
16310 s = size_int (0);
16311 else if (is_reference (var))
16312 s = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (ovar)));
16313 else
16314 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
16315 s = fold_convert (size_type_node, s);
16316 purpose = size_int (map_idx++);
16317 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
16318 if (TREE_CODE (s) != INTEGER_CST)
16319 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
16320
16321 gcc_checking_assert (tkind
16322 < (HOST_WIDE_INT_C (1U) << talign_shift));
16323 talign = ceil_log2 (talign);
16324 tkind |= talign << talign_shift;
16325 gcc_checking_assert (tkind
16326 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
16327 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
16328 build_int_cstu (tkind_type, tkind));
16329 break;
16330
16331 case OMP_CLAUSE_USE_DEVICE_PTR:
16332 case OMP_CLAUSE_IS_DEVICE_PTR:
16333 ovar = OMP_CLAUSE_DECL (c);
16334 var = lookup_decl_in_outer_ctx (ovar, ctx);
16335 x = build_sender_ref (ovar, ctx);
16336 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_PTR)
16337 tkind = GOMP_MAP_USE_DEVICE_PTR;
16338 else
16339 tkind = GOMP_MAP_FIRSTPRIVATE_INT;
16340 type = TREE_TYPE (ovar);
16341 if (TREE_CODE (type) == ARRAY_TYPE)
16342 var = build_fold_addr_expr (var);
16343 else
16344 {
16345 if (is_reference (ovar))
16346 {
16347 type = TREE_TYPE (type);
16348 if (TREE_CODE (type) != ARRAY_TYPE)
16349 var = build_simple_mem_ref (var);
16350 var = fold_convert (TREE_TYPE (x), var);
16351 }
16352 }
16353 gimplify_assign (x, var, &ilist);
16354 s = size_int (0);
16355 purpose = size_int (map_idx++);
16356 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
16357 gcc_checking_assert (tkind
16358 < (HOST_WIDE_INT_C (1U) << talign_shift));
16359 gcc_checking_assert (tkind
16360 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
16361 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
16362 build_int_cstu (tkind_type, tkind));
16363 break;
16364 }
16365
16366 gcc_assert (map_idx == map_cnt);
16367
16368 DECL_INITIAL (TREE_VEC_ELT (t, 1))
16369 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)), vsize);
16370 DECL_INITIAL (TREE_VEC_ELT (t, 2))
16371 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 2)), vkind);
16372 for (int i = 1; i <= 2; i++)
16373 if (!TREE_STATIC (TREE_VEC_ELT (t, i)))
16374 {
16375 gimple_seq initlist = NULL;
16376 force_gimple_operand (build1 (DECL_EXPR, void_type_node,
16377 TREE_VEC_ELT (t, i)),
16378 &initlist, true, NULL_TREE);
16379 gimple_seq_add_seq (&ilist, initlist);
16380
16381 tree clobber = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, i)),
16382 NULL);
16383 TREE_THIS_VOLATILE (clobber) = 1;
16384 gimple_seq_add_stmt (&olist,
16385 gimple_build_assign (TREE_VEC_ELT (t, i),
16386 clobber));
16387 }
16388
16389 tree clobber = build_constructor (ctx->record_type, NULL);
16390 TREE_THIS_VOLATILE (clobber) = 1;
16391 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
16392 clobber));
16393 }
16394
16395 /* Once all the expansions are done, sequence all the different
16396 fragments inside gimple_omp_body. */
16397
16398 new_body = NULL;
16399
16400 if (offloaded
16401 && ctx->record_type)
16402 {
16403 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
16404 /* fixup_child_record_type might have changed receiver_decl's type. */
16405 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
16406 gimple_seq_add_stmt (&new_body,
16407 gimple_build_assign (ctx->receiver_decl, t));
16408 }
16409 gimple_seq_add_seq (&new_body, fplist);
16410
16411 if (offloaded || data_region)
16412 {
16413 tree prev = NULL_TREE;
16414 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
16415 switch (OMP_CLAUSE_CODE (c))
16416 {
16417 tree var, x;
16418 default:
16419 break;
16420 case OMP_CLAUSE_FIRSTPRIVATE:
16421 if (is_gimple_omp_oacc (ctx->stmt))
16422 break;
16423 var = OMP_CLAUSE_DECL (c);
16424 if (is_reference (var)
16425 || is_gimple_reg_type (TREE_TYPE (var)))
16426 {
16427 tree new_var = lookup_decl (var, ctx);
16428 tree type;
16429 type = TREE_TYPE (var);
16430 if (is_reference (var))
16431 type = TREE_TYPE (type);
16432 if ((INTEGRAL_TYPE_P (type)
16433 && TYPE_PRECISION (type) <= POINTER_SIZE)
16434 || TREE_CODE (type) == POINTER_TYPE)
16435 {
16436 x = build_receiver_ref (var, false, ctx);
16437 if (TREE_CODE (type) != POINTER_TYPE)
16438 x = fold_convert (pointer_sized_int_node, x);
16439 x = fold_convert (type, x);
16440 gimplify_expr (&x, &new_body, NULL, is_gimple_val,
16441 fb_rvalue);
16442 if (is_reference (var))
16443 {
16444 tree v = create_tmp_var_raw (type, get_name (var));
16445 gimple_add_tmp_var (v);
16446 TREE_ADDRESSABLE (v) = 1;
16447 gimple_seq_add_stmt (&new_body,
16448 gimple_build_assign (v, x));
16449 x = build_fold_addr_expr (v);
16450 }
16451 gimple_seq_add_stmt (&new_body,
16452 gimple_build_assign (new_var, x));
16453 }
16454 else
16455 {
16456 x = build_receiver_ref (var, !is_reference (var), ctx);
16457 gimplify_expr (&x, &new_body, NULL, is_gimple_val,
16458 fb_rvalue);
16459 gimple_seq_add_stmt (&new_body,
16460 gimple_build_assign (new_var, x));
16461 }
16462 }
16463 else if (is_variable_sized (var))
16464 {
16465 tree pvar = DECL_VALUE_EXPR (var);
16466 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
16467 pvar = TREE_OPERAND (pvar, 0);
16468 gcc_assert (DECL_P (pvar));
16469 tree new_var = lookup_decl (pvar, ctx);
16470 x = build_receiver_ref (var, false, ctx);
16471 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16472 gimple_seq_add_stmt (&new_body,
16473 gimple_build_assign (new_var, x));
16474 }
16475 break;
16476 case OMP_CLAUSE_PRIVATE:
16477 if (is_gimple_omp_oacc (ctx->stmt))
16478 break;
16479 var = OMP_CLAUSE_DECL (c);
16480 if (is_reference (var))
16481 {
16482 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
16483 tree new_var = lookup_decl (var, ctx);
16484 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
16485 if (TREE_CONSTANT (x))
16486 {
16487 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
16488 get_name (var));
16489 gimple_add_tmp_var (x);
16490 TREE_ADDRESSABLE (x) = 1;
16491 x = build_fold_addr_expr_loc (clause_loc, x);
16492 }
16493 else
16494 break;
16495
16496 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
16497 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16498 gimple_seq_add_stmt (&new_body,
16499 gimple_build_assign (new_var, x));
16500 }
16501 break;
16502 case OMP_CLAUSE_USE_DEVICE_PTR:
16503 case OMP_CLAUSE_IS_DEVICE_PTR:
16504 var = OMP_CLAUSE_DECL (c);
16505 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_PTR)
16506 x = build_sender_ref (var, ctx);
16507 else
16508 x = build_receiver_ref (var, false, ctx);
16509 if (is_variable_sized (var))
16510 {
16511 tree pvar = DECL_VALUE_EXPR (var);
16512 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
16513 pvar = TREE_OPERAND (pvar, 0);
16514 gcc_assert (DECL_P (pvar));
16515 tree new_var = lookup_decl (pvar, ctx);
16516 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16517 gimple_seq_add_stmt (&new_body,
16518 gimple_build_assign (new_var, x));
16519 }
16520 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
16521 {
16522 tree new_var = lookup_decl (var, ctx);
16523 new_var = DECL_VALUE_EXPR (new_var);
16524 gcc_assert (TREE_CODE (new_var) == MEM_REF);
16525 new_var = TREE_OPERAND (new_var, 0);
16526 gcc_assert (DECL_P (new_var));
16527 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16528 gimple_seq_add_stmt (&new_body,
16529 gimple_build_assign (new_var, x));
16530 }
16531 else
16532 {
16533 tree type = TREE_TYPE (var);
16534 tree new_var = lookup_decl (var, ctx);
16535 if (is_reference (var))
16536 {
16537 type = TREE_TYPE (type);
16538 if (TREE_CODE (type) != ARRAY_TYPE)
16539 {
16540 tree v = create_tmp_var_raw (type, get_name (var));
16541 gimple_add_tmp_var (v);
16542 TREE_ADDRESSABLE (v) = 1;
16543 x = fold_convert (type, x);
16544 gimplify_expr (&x, &new_body, NULL, is_gimple_val,
16545 fb_rvalue);
16546 gimple_seq_add_stmt (&new_body,
16547 gimple_build_assign (v, x));
16548 x = build_fold_addr_expr (v);
16549 }
16550 }
16551 new_var = DECL_VALUE_EXPR (new_var);
16552 x = fold_convert (TREE_TYPE (new_var), x);
16553 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16554 gimple_seq_add_stmt (&new_body,
16555 gimple_build_assign (new_var, x));
16556 }
16557 break;
16558 }
16559 /* Handle GOMP_MAP_FIRSTPRIVATE_{POINTER,REFERENCE} in second pass,
16560 so that firstprivate vars holding OMP_CLAUSE_SIZE if needed
16561 are already handled. Similarly OMP_CLAUSE_PRIVATE for VLAs
16562 or references to VLAs. */
16563 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
16564 switch (OMP_CLAUSE_CODE (c))
16565 {
16566 tree var;
16567 default:
16568 break;
16569 case OMP_CLAUSE_MAP:
16570 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
16571 || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_REFERENCE)
16572 {
16573 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
16574 HOST_WIDE_INT offset = 0;
16575 gcc_assert (prev);
16576 var = OMP_CLAUSE_DECL (c);
16577 if (DECL_P (var)
16578 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
16579 && is_global_var (maybe_lookup_decl_in_outer_ctx (var,
16580 ctx))
16581 && varpool_node::get_create (var)->offloadable)
16582 break;
16583 if (TREE_CODE (var) == INDIRECT_REF
16584 && TREE_CODE (TREE_OPERAND (var, 0)) == COMPONENT_REF)
16585 var = TREE_OPERAND (var, 0);
16586 if (TREE_CODE (var) == COMPONENT_REF)
16587 {
16588 var = get_addr_base_and_unit_offset (var, &offset);
16589 gcc_assert (var != NULL_TREE && DECL_P (var));
16590 }
16591 else if (DECL_SIZE (var)
16592 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
16593 {
16594 tree var2 = DECL_VALUE_EXPR (var);
16595 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
16596 var2 = TREE_OPERAND (var2, 0);
16597 gcc_assert (DECL_P (var2));
16598 var = var2;
16599 }
16600 tree new_var = lookup_decl (var, ctx), x;
16601 tree type = TREE_TYPE (new_var);
16602 bool is_ref;
16603 if (TREE_CODE (OMP_CLAUSE_DECL (c)) == INDIRECT_REF
16604 && (TREE_CODE (TREE_OPERAND (OMP_CLAUSE_DECL (c), 0))
16605 == COMPONENT_REF))
16606 {
16607 type = TREE_TYPE (TREE_OPERAND (OMP_CLAUSE_DECL (c), 0));
16608 is_ref = true;
16609 new_var = build2 (MEM_REF, type,
16610 build_fold_addr_expr (new_var),
16611 build_int_cst (build_pointer_type (type),
16612 offset));
16613 }
16614 else if (TREE_CODE (OMP_CLAUSE_DECL (c)) == COMPONENT_REF)
16615 {
16616 type = TREE_TYPE (OMP_CLAUSE_DECL (c));
16617 is_ref = TREE_CODE (type) == REFERENCE_TYPE;
16618 new_var = build2 (MEM_REF, type,
16619 build_fold_addr_expr (new_var),
16620 build_int_cst (build_pointer_type (type),
16621 offset));
16622 }
16623 else
16624 is_ref = is_reference (var);
16625 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_REFERENCE)
16626 is_ref = false;
16627 bool ref_to_array = false;
16628 if (is_ref)
16629 {
16630 type = TREE_TYPE (type);
16631 if (TREE_CODE (type) == ARRAY_TYPE)
16632 {
16633 type = build_pointer_type (type);
16634 ref_to_array = true;
16635 }
16636 }
16637 else if (TREE_CODE (type) == ARRAY_TYPE)
16638 {
16639 tree decl2 = DECL_VALUE_EXPR (new_var);
16640 gcc_assert (TREE_CODE (decl2) == MEM_REF);
16641 decl2 = TREE_OPERAND (decl2, 0);
16642 gcc_assert (DECL_P (decl2));
16643 new_var = decl2;
16644 type = TREE_TYPE (new_var);
16645 }
16646 x = build_receiver_ref (OMP_CLAUSE_DECL (prev), false, ctx);
16647 x = fold_convert_loc (clause_loc, type, x);
16648 if (!integer_zerop (OMP_CLAUSE_SIZE (c)))
16649 {
16650 tree bias = OMP_CLAUSE_SIZE (c);
16651 if (DECL_P (bias))
16652 bias = lookup_decl (bias, ctx);
16653 bias = fold_convert_loc (clause_loc, sizetype, bias);
16654 bias = fold_build1_loc (clause_loc, NEGATE_EXPR, sizetype,
16655 bias);
16656 x = fold_build2_loc (clause_loc, POINTER_PLUS_EXPR,
16657 TREE_TYPE (x), x, bias);
16658 }
16659 if (ref_to_array)
16660 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
16661 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16662 if (is_ref && !ref_to_array)
16663 {
16664 tree t = create_tmp_var_raw (type, get_name (var));
16665 gimple_add_tmp_var (t);
16666 TREE_ADDRESSABLE (t) = 1;
16667 gimple_seq_add_stmt (&new_body,
16668 gimple_build_assign (t, x));
16669 x = build_fold_addr_expr_loc (clause_loc, t);
16670 }
16671 gimple_seq_add_stmt (&new_body,
16672 gimple_build_assign (new_var, x));
16673 prev = NULL_TREE;
16674 }
16675 else if (OMP_CLAUSE_CHAIN (c)
16676 && OMP_CLAUSE_CODE (OMP_CLAUSE_CHAIN (c))
16677 == OMP_CLAUSE_MAP
16678 && (OMP_CLAUSE_MAP_KIND (OMP_CLAUSE_CHAIN (c))
16679 == GOMP_MAP_FIRSTPRIVATE_POINTER
16680 || (OMP_CLAUSE_MAP_KIND (OMP_CLAUSE_CHAIN (c))
16681 == GOMP_MAP_FIRSTPRIVATE_REFERENCE)))
16682 prev = c;
16683 break;
16684 case OMP_CLAUSE_PRIVATE:
16685 var = OMP_CLAUSE_DECL (c);
16686 if (is_variable_sized (var))
16687 {
16688 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
16689 tree new_var = lookup_decl (var, ctx);
16690 tree pvar = DECL_VALUE_EXPR (var);
16691 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
16692 pvar = TREE_OPERAND (pvar, 0);
16693 gcc_assert (DECL_P (pvar));
16694 tree new_pvar = lookup_decl (pvar, ctx);
16695 tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
16696 tree al = size_int (DECL_ALIGN (var));
16697 tree x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
16698 x = build_call_expr_loc (clause_loc, atmp, 2, x, al);
16699 x = fold_convert_loc (clause_loc, TREE_TYPE (new_pvar), x);
16700 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16701 gimple_seq_add_stmt (&new_body,
16702 gimple_build_assign (new_pvar, x));
16703 }
16704 else if (is_reference (var) && !is_gimple_omp_oacc (ctx->stmt))
16705 {
16706 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
16707 tree new_var = lookup_decl (var, ctx);
16708 tree x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
16709 if (TREE_CONSTANT (x))
16710 break;
16711 else
16712 {
16713 tree atmp
16714 = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
16715 tree rtype = TREE_TYPE (TREE_TYPE (new_var));
16716 tree al = size_int (TYPE_ALIGN (rtype));
16717 x = build_call_expr_loc (clause_loc, atmp, 2, x, al);
16718 }
16719
16720 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
16721 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16722 gimple_seq_add_stmt (&new_body,
16723 gimple_build_assign (new_var, x));
16724 }
16725 break;
16726 }
16727
16728 gimple_seq fork_seq = NULL;
16729 gimple_seq join_seq = NULL;
16730
16731 if (is_oacc_parallel (ctx))
16732 {
16733 /* If there are reductions on the offloaded region itself, treat
16734 them as a dummy GANG loop. */
16735 tree level = build_int_cst (integer_type_node, GOMP_DIM_GANG);
16736
16737 lower_oacc_reductions (gimple_location (ctx->stmt), clauses, level,
16738 false, NULL, NULL, &fork_seq, &join_seq, ctx);
16739 }
16740
16741 gimple_seq_add_seq (&new_body, fork_seq);
16742 gimple_seq_add_seq (&new_body, tgt_body);
16743 gimple_seq_add_seq (&new_body, join_seq);
16744
16745 if (offloaded)
16746 new_body = maybe_catch_exception (new_body);
16747
16748 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
16749 gimple_omp_set_body (stmt, new_body);
16750 }
16751
16752 bind = gimple_build_bind (NULL, NULL,
16753 tgt_bind ? gimple_bind_block (tgt_bind)
16754 : NULL_TREE);
16755 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
16756 gimple_bind_add_seq (bind, ilist);
16757 gimple_bind_add_stmt (bind, stmt);
16758 gimple_bind_add_seq (bind, olist);
16759
16760 pop_gimplify_context (NULL);
16761
16762 if (dep_bind)
16763 {
16764 gimple_bind_add_seq (dep_bind, dep_ilist);
16765 gimple_bind_add_stmt (dep_bind, bind);
16766 gimple_bind_add_seq (dep_bind, dep_olist);
16767 pop_gimplify_context (dep_bind);
16768 }
16769 }
16770
16771 /* Expand code for an OpenMP teams directive. */
16772
16773 static void
16774 lower_omp_teams (gimple_stmt_iterator *gsi_p, omp_context *ctx)
16775 {
16776 gomp_teams *teams_stmt = as_a <gomp_teams *> (gsi_stmt (*gsi_p));
16777 push_gimplify_context ();
16778
16779 tree block = make_node (BLOCK);
16780 gbind *bind = gimple_build_bind (NULL, NULL, block);
16781 gsi_replace (gsi_p, bind, true);
16782 gimple_seq bind_body = NULL;
16783 gimple_seq dlist = NULL;
16784 gimple_seq olist = NULL;
16785
16786 tree num_teams = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
16787 OMP_CLAUSE_NUM_TEAMS);
16788 if (num_teams == NULL_TREE)
16789 num_teams = build_int_cst (unsigned_type_node, 0);
16790 else
16791 {
16792 num_teams = OMP_CLAUSE_NUM_TEAMS_EXPR (num_teams);
16793 num_teams = fold_convert (unsigned_type_node, num_teams);
16794 gimplify_expr (&num_teams, &bind_body, NULL, is_gimple_val, fb_rvalue);
16795 }
16796 tree thread_limit = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
16797 OMP_CLAUSE_THREAD_LIMIT);
16798 if (thread_limit == NULL_TREE)
16799 thread_limit = build_int_cst (unsigned_type_node, 0);
16800 else
16801 {
16802 thread_limit = OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit);
16803 thread_limit = fold_convert (unsigned_type_node, thread_limit);
16804 gimplify_expr (&thread_limit, &bind_body, NULL, is_gimple_val,
16805 fb_rvalue);
16806 }
16807
16808 lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt),
16809 &bind_body, &dlist, ctx, NULL);
16810 lower_omp (gimple_omp_body_ptr (teams_stmt), ctx);
16811 lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt), &olist, ctx);
16812 if (!gimple_omp_teams_grid_phony (teams_stmt))
16813 {
16814 gimple_seq_add_stmt (&bind_body, teams_stmt);
16815 location_t loc = gimple_location (teams_stmt);
16816 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TEAMS);
16817 gimple *call = gimple_build_call (decl, 2, num_teams, thread_limit);
16818 gimple_set_location (call, loc);
16819 gimple_seq_add_stmt (&bind_body, call);
16820 }
16821
16822 gimple_seq_add_seq (&bind_body, gimple_omp_body (teams_stmt));
16823 gimple_omp_set_body (teams_stmt, NULL);
16824 gimple_seq_add_seq (&bind_body, olist);
16825 gimple_seq_add_seq (&bind_body, dlist);
16826 if (!gimple_omp_teams_grid_phony (teams_stmt))
16827 gimple_seq_add_stmt (&bind_body, gimple_build_omp_return (true));
16828 gimple_bind_set_body (bind, bind_body);
16829
16830 pop_gimplify_context (bind);
16831
16832 gimple_bind_append_vars (bind, ctx->block_vars);
16833 BLOCK_VARS (block) = ctx->block_vars;
16834 if (BLOCK_VARS (block))
16835 TREE_USED (block) = 1;
16836 }
16837
16838 /* Expand code within an artificial GIMPLE_OMP_GRID_BODY OMP construct. */
16839
16840 static void
16841 lower_omp_grid_body (gimple_stmt_iterator *gsi_p, omp_context *ctx)
16842 {
16843 gimple *stmt = gsi_stmt (*gsi_p);
16844 lower_omp (gimple_omp_body_ptr (stmt), ctx);
16845 gimple_seq_add_stmt (gimple_omp_body_ptr (stmt),
16846 gimple_build_omp_return (false));
16847 }
16848
16849
16850 /* Callback for lower_omp_1. Return non-NULL if *tp needs to be
16851 regimplified. If DATA is non-NULL, lower_omp_1 is outside
16852 of OMP context, but with task_shared_vars set. */
16853
16854 static tree
16855 lower_omp_regimplify_p (tree *tp, int *walk_subtrees,
16856 void *data)
16857 {
16858 tree t = *tp;
16859
16860 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
16861 if (TREE_CODE (t) == VAR_DECL && data == NULL && DECL_HAS_VALUE_EXPR_P (t))
16862 return t;
16863
16864 if (task_shared_vars
16865 && DECL_P (t)
16866 && bitmap_bit_p (task_shared_vars, DECL_UID (t)))
16867 return t;
16868
16869 /* If a global variable has been privatized, TREE_CONSTANT on
16870 ADDR_EXPR might be wrong. */
16871 if (data == NULL && TREE_CODE (t) == ADDR_EXPR)
16872 recompute_tree_invariant_for_addr_expr (t);
16873
16874 *walk_subtrees = !IS_TYPE_OR_DECL_P (t);
16875 return NULL_TREE;
16876 }
16877
16878 /* Data to be communicated between lower_omp_regimplify_operands and
16879 lower_omp_regimplify_operands_p. */
16880
16881 struct lower_omp_regimplify_operands_data
16882 {
16883 omp_context *ctx;
16884 vec<tree> *decls;
16885 };
16886
16887 /* Helper function for lower_omp_regimplify_operands. Find
16888 omp_member_access_dummy_var vars and adjust temporarily their
16889 DECL_VALUE_EXPRs if needed. */
16890
16891 static tree
16892 lower_omp_regimplify_operands_p (tree *tp, int *walk_subtrees,
16893 void *data)
16894 {
16895 tree t = omp_member_access_dummy_var (*tp);
16896 if (t)
16897 {
16898 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
16899 lower_omp_regimplify_operands_data *ldata
16900 = (lower_omp_regimplify_operands_data *) wi->info;
16901 tree o = maybe_lookup_decl (t, ldata->ctx);
16902 if (o != t)
16903 {
16904 ldata->decls->safe_push (DECL_VALUE_EXPR (*tp));
16905 ldata->decls->safe_push (*tp);
16906 tree v = unshare_and_remap (DECL_VALUE_EXPR (*tp), t, o);
16907 SET_DECL_VALUE_EXPR (*tp, v);
16908 }
16909 }
16910 *walk_subtrees = !IS_TYPE_OR_DECL_P (*tp);
16911 return NULL_TREE;
16912 }
16913
16914 /* Wrapper around gimple_regimplify_operands that adjusts DECL_VALUE_EXPRs
16915 of omp_member_access_dummy_var vars during regimplification. */
16916
16917 static void
16918 lower_omp_regimplify_operands (omp_context *ctx, gimple *stmt,
16919 gimple_stmt_iterator *gsi_p)
16920 {
16921 auto_vec<tree, 10> decls;
16922 if (ctx)
16923 {
16924 struct walk_stmt_info wi;
16925 memset (&wi, '\0', sizeof (wi));
16926 struct lower_omp_regimplify_operands_data data;
16927 data.ctx = ctx;
16928 data.decls = &decls;
16929 wi.info = &data;
16930 walk_gimple_op (stmt, lower_omp_regimplify_operands_p, &wi);
16931 }
16932 gimple_regimplify_operands (stmt, gsi_p);
16933 while (!decls.is_empty ())
16934 {
16935 tree t = decls.pop ();
16936 tree v = decls.pop ();
16937 SET_DECL_VALUE_EXPR (t, v);
16938 }
16939 }
16940
16941 static void
16942 lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
16943 {
16944 gimple *stmt = gsi_stmt (*gsi_p);
16945 struct walk_stmt_info wi;
16946 gcall *call_stmt;
16947
16948 if (gimple_has_location (stmt))
16949 input_location = gimple_location (stmt);
16950
16951 if (task_shared_vars)
16952 memset (&wi, '\0', sizeof (wi));
16953
16954 /* If we have issued syntax errors, avoid doing any heavy lifting.
16955 Just replace the OMP directives with a NOP to avoid
16956 confusing RTL expansion. */
16957 if (seen_error () && is_gimple_omp (stmt))
16958 {
16959 gsi_replace (gsi_p, gimple_build_nop (), true);
16960 return;
16961 }
16962
16963 switch (gimple_code (stmt))
16964 {
16965 case GIMPLE_COND:
16966 {
16967 gcond *cond_stmt = as_a <gcond *> (stmt);
16968 if ((ctx || task_shared_vars)
16969 && (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
16970 lower_omp_regimplify_p,
16971 ctx ? NULL : &wi, NULL)
16972 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
16973 lower_omp_regimplify_p,
16974 ctx ? NULL : &wi, NULL)))
16975 lower_omp_regimplify_operands (ctx, cond_stmt, gsi_p);
16976 }
16977 break;
16978 case GIMPLE_CATCH:
16979 lower_omp (gimple_catch_handler_ptr (as_a <gcatch *> (stmt)), ctx);
16980 break;
16981 case GIMPLE_EH_FILTER:
16982 lower_omp (gimple_eh_filter_failure_ptr (stmt), ctx);
16983 break;
16984 case GIMPLE_TRY:
16985 lower_omp (gimple_try_eval_ptr (stmt), ctx);
16986 lower_omp (gimple_try_cleanup_ptr (stmt), ctx);
16987 break;
16988 case GIMPLE_TRANSACTION:
16989 lower_omp (gimple_transaction_body_ptr (
16990 as_a <gtransaction *> (stmt)),
16991 ctx);
16992 break;
16993 case GIMPLE_BIND:
16994 lower_omp (gimple_bind_body_ptr (as_a <gbind *> (stmt)), ctx);
16995 break;
16996 case GIMPLE_OMP_PARALLEL:
16997 case GIMPLE_OMP_TASK:
16998 ctx = maybe_lookup_ctx (stmt);
16999 gcc_assert (ctx);
17000 if (ctx->cancellable)
17001 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
17002 lower_omp_taskreg (gsi_p, ctx);
17003 break;
17004 case GIMPLE_OMP_FOR:
17005 ctx = maybe_lookup_ctx (stmt);
17006 gcc_assert (ctx);
17007 if (ctx->cancellable)
17008 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
17009 lower_omp_for (gsi_p, ctx);
17010 break;
17011 case GIMPLE_OMP_SECTIONS:
17012 ctx = maybe_lookup_ctx (stmt);
17013 gcc_assert (ctx);
17014 if (ctx->cancellable)
17015 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
17016 lower_omp_sections (gsi_p, ctx);
17017 break;
17018 case GIMPLE_OMP_SINGLE:
17019 ctx = maybe_lookup_ctx (stmt);
17020 gcc_assert (ctx);
17021 lower_omp_single (gsi_p, ctx);
17022 break;
17023 case GIMPLE_OMP_MASTER:
17024 ctx = maybe_lookup_ctx (stmt);
17025 gcc_assert (ctx);
17026 lower_omp_master (gsi_p, ctx);
17027 break;
17028 case GIMPLE_OMP_TASKGROUP:
17029 ctx = maybe_lookup_ctx (stmt);
17030 gcc_assert (ctx);
17031 lower_omp_taskgroup (gsi_p, ctx);
17032 break;
17033 case GIMPLE_OMP_ORDERED:
17034 ctx = maybe_lookup_ctx (stmt);
17035 gcc_assert (ctx);
17036 lower_omp_ordered (gsi_p, ctx);
17037 break;
17038 case GIMPLE_OMP_CRITICAL:
17039 ctx = maybe_lookup_ctx (stmt);
17040 gcc_assert (ctx);
17041 lower_omp_critical (gsi_p, ctx);
17042 break;
17043 case GIMPLE_OMP_ATOMIC_LOAD:
17044 if ((ctx || task_shared_vars)
17045 && walk_tree (gimple_omp_atomic_load_rhs_ptr (
17046 as_a <gomp_atomic_load *> (stmt)),
17047 lower_omp_regimplify_p, ctx ? NULL : &wi, NULL))
17048 lower_omp_regimplify_operands (ctx, stmt, gsi_p);
17049 break;
17050 case GIMPLE_OMP_TARGET:
17051 ctx = maybe_lookup_ctx (stmt);
17052 gcc_assert (ctx);
17053 lower_omp_target (gsi_p, ctx);
17054 break;
17055 case GIMPLE_OMP_TEAMS:
17056 ctx = maybe_lookup_ctx (stmt);
17057 gcc_assert (ctx);
17058 lower_omp_teams (gsi_p, ctx);
17059 break;
17060 case GIMPLE_OMP_GRID_BODY:
17061 ctx = maybe_lookup_ctx (stmt);
17062 gcc_assert (ctx);
17063 lower_omp_grid_body (gsi_p, ctx);
17064 break;
17065 case GIMPLE_CALL:
17066 tree fndecl;
17067 call_stmt = as_a <gcall *> (stmt);
17068 fndecl = gimple_call_fndecl (call_stmt);
17069 if (fndecl
17070 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
17071 switch (DECL_FUNCTION_CODE (fndecl))
17072 {
17073 case BUILT_IN_GOMP_BARRIER:
17074 if (ctx == NULL)
17075 break;
17076 /* FALLTHRU */
17077 case BUILT_IN_GOMP_CANCEL:
17078 case BUILT_IN_GOMP_CANCELLATION_POINT:
17079 omp_context *cctx;
17080 cctx = ctx;
17081 if (gimple_code (cctx->stmt) == GIMPLE_OMP_SECTION)
17082 cctx = cctx->outer;
17083 gcc_assert (gimple_call_lhs (call_stmt) == NULL_TREE);
17084 if (!cctx->cancellable)
17085 {
17086 if (DECL_FUNCTION_CODE (fndecl)
17087 == BUILT_IN_GOMP_CANCELLATION_POINT)
17088 {
17089 stmt = gimple_build_nop ();
17090 gsi_replace (gsi_p, stmt, false);
17091 }
17092 break;
17093 }
17094 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
17095 {
17096 fndecl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL);
17097 gimple_call_set_fndecl (call_stmt, fndecl);
17098 gimple_call_set_fntype (call_stmt, TREE_TYPE (fndecl));
17099 }
17100 tree lhs;
17101 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (fndecl)));
17102 gimple_call_set_lhs (call_stmt, lhs);
17103 tree fallthru_label;
17104 fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
17105 gimple *g;
17106 g = gimple_build_label (fallthru_label);
17107 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
17108 g = gimple_build_cond (NE_EXPR, lhs,
17109 fold_convert (TREE_TYPE (lhs),
17110 boolean_false_node),
17111 cctx->cancel_label, fallthru_label);
17112 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
17113 break;
17114 default:
17115 break;
17116 }
17117 /* FALLTHRU */
17118 default:
17119 if ((ctx || task_shared_vars)
17120 && walk_gimple_op (stmt, lower_omp_regimplify_p,
17121 ctx ? NULL : &wi))
17122 {
17123 /* Just remove clobbers, this should happen only if we have
17124 "privatized" local addressable variables in SIMD regions,
17125 the clobber isn't needed in that case and gimplifying address
17126 of the ARRAY_REF into a pointer and creating MEM_REF based
17127 clobber would create worse code than we get with the clobber
17128 dropped. */
17129 if (gimple_clobber_p (stmt))
17130 {
17131 gsi_replace (gsi_p, gimple_build_nop (), true);
17132 break;
17133 }
17134 lower_omp_regimplify_operands (ctx, stmt, gsi_p);
17135 }
17136 break;
17137 }
17138 }
17139
17140 static void
17141 lower_omp (gimple_seq *body, omp_context *ctx)
17142 {
17143 location_t saved_location = input_location;
17144 gimple_stmt_iterator gsi;
17145 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
17146 lower_omp_1 (&gsi, ctx);
17147 /* During gimplification, we haven't folded statments inside offloading
17148 or taskreg regions (gimplify.c:maybe_fold_stmt); do that now. */
17149 if (target_nesting_level || taskreg_nesting_level)
17150 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
17151 fold_stmt (&gsi);
17152 input_location = saved_location;
17153 }
17154
17155 /* Returen true if STMT is an assignment of a register-type into a local
17156 VAR_DECL. */
17157
17158 static bool
17159 grid_reg_assignment_to_local_var_p (gimple *stmt)
17160 {
17161 gassign *assign = dyn_cast <gassign *> (stmt);
17162 if (!assign)
17163 return false;
17164 tree lhs = gimple_assign_lhs (assign);
17165 if (TREE_CODE (lhs) != VAR_DECL
17166 || !is_gimple_reg_type (TREE_TYPE (lhs))
17167 || is_global_var (lhs))
17168 return false;
17169 return true;
17170 }
17171
17172 /* Return true if all statements in SEQ are assignments to local register-type
17173 variables. */
17174
17175 static bool
17176 grid_seq_only_contains_local_assignments (gimple_seq seq)
17177 {
17178 if (!seq)
17179 return true;
17180
17181 gimple_stmt_iterator gsi;
17182 for (gsi = gsi_start (seq); !gsi_end_p (gsi); gsi_next (&gsi))
17183 if (!grid_reg_assignment_to_local_var_p (gsi_stmt (gsi)))
17184 return false;
17185 return true;
17186 }
17187
17188 /* Scan statements in SEQ and call itself recursively on any bind. If during
17189 whole search only assignments to register-type local variables and one
17190 single OMP statement is encountered, return true, otherwise return false.
17191 RET is where we store any OMP statement encountered. TARGET_LOC and NAME
17192 are used for dumping a note about a failure. */
17193
17194 static bool
17195 grid_find_single_omp_among_assignments_1 (gimple_seq seq, location_t target_loc,
17196 const char *name, gimple **ret)
17197 {
17198 gimple_stmt_iterator gsi;
17199 for (gsi = gsi_start (seq); !gsi_end_p (gsi); gsi_next (&gsi))
17200 {
17201 gimple *stmt = gsi_stmt (gsi);
17202
17203 if (grid_reg_assignment_to_local_var_p (stmt))
17204 continue;
17205 if (gbind *bind = dyn_cast <gbind *> (stmt))
17206 {
17207 if (!grid_find_single_omp_among_assignments_1 (gimple_bind_body (bind),
17208 target_loc, name, ret))
17209 return false;
17210 }
17211 else if (is_gimple_omp (stmt))
17212 {
17213 if (*ret)
17214 {
17215 if (dump_enabled_p ())
17216 dump_printf_loc (MSG_NOTE, target_loc,
17217 "Will not turn target construct into a simple "
17218 "GPGPU kernel because %s construct contains "
17219 "multiple OpenMP constructs\n", name);
17220 return false;
17221 }
17222 *ret = stmt;
17223 }
17224 else
17225 {
17226 if (dump_enabled_p ())
17227 dump_printf_loc (MSG_NOTE, target_loc,
17228 "Will not turn target construct into a simple "
17229 "GPGPU kernel because %s construct contains "
17230 "a complex statement\n", name);
17231 return false;
17232 }
17233 }
17234 return true;
17235 }
17236
17237 /* Scan statements in SEQ and make sure that it and any binds in it contain
17238 only assignments to local register-type variables and one OMP construct. If
17239 so, return that construct, otherwise return NULL. If dumping is enabled and
17240 function fails, use TARGET_LOC and NAME to dump a note with the reason for
17241 failure. */
17242
17243 static gimple *
17244 grid_find_single_omp_among_assignments (gimple_seq seq, location_t target_loc,
17245 const char *name)
17246 {
17247 if (!seq)
17248 {
17249 if (dump_enabled_p ())
17250 dump_printf_loc (MSG_NOTE, target_loc,
17251 "Will not turn target construct into a simple "
17252 "GPGPU kernel because %s construct has empty "
17253 "body\n",
17254 name);
17255 return NULL;
17256 }
17257
17258 gimple *ret = NULL;
17259 if (grid_find_single_omp_among_assignments_1 (seq, target_loc, name, &ret))
17260 {
17261 if (!ret && dump_enabled_p ())
17262 dump_printf_loc (MSG_NOTE, target_loc,
17263 "Will not turn target construct into a simple "
17264 "GPGPU kernel because %s construct does not contain"
17265 "any other OpenMP construct\n", name);
17266 return ret;
17267 }
17268 else
17269 return NULL;
17270 }
17271
17272 /* Walker function looking for statements there is no point gridifying (and for
17273 noreturn function calls which we cannot do). Return non-NULL if such a
17274 function is found. */
17275
17276 static tree
17277 grid_find_ungridifiable_statement (gimple_stmt_iterator *gsi,
17278 bool *handled_ops_p,
17279 struct walk_stmt_info *wi)
17280 {
17281 *handled_ops_p = false;
17282 gimple *stmt = gsi_stmt (*gsi);
17283 switch (gimple_code (stmt))
17284 {
17285 case GIMPLE_CALL:
17286 if (gimple_call_noreturn_p (as_a <gcall *> (stmt)))
17287 {
17288 *handled_ops_p = true;
17289 wi->info = stmt;
17290 return error_mark_node;
17291 }
17292 break;
17293
17294 /* We may reduce the following list if we find a way to implement the
17295 clauses, but now there is no point trying further. */
17296 case GIMPLE_OMP_CRITICAL:
17297 case GIMPLE_OMP_TASKGROUP:
17298 case GIMPLE_OMP_TASK:
17299 case GIMPLE_OMP_SECTION:
17300 case GIMPLE_OMP_SECTIONS:
17301 case GIMPLE_OMP_SECTIONS_SWITCH:
17302 case GIMPLE_OMP_TARGET:
17303 case GIMPLE_OMP_ORDERED:
17304 *handled_ops_p = true;
17305 wi->info = stmt;
17306 return error_mark_node;
17307
17308 case GIMPLE_OMP_FOR:
17309 if ((gimple_omp_for_kind (stmt) & GF_OMP_FOR_SIMD)
17310 && gimple_omp_for_combined_into_p (stmt))
17311 {
17312 *handled_ops_p = true;
17313 wi->info = stmt;
17314 return error_mark_node;
17315 }
17316 break;
17317
17318 default:
17319 break;
17320 }
17321 return NULL;
17322 }
17323
17324
17325 /* If TARGET follows a pattern that can be turned into a gridified GPGPU
17326 kernel, return true, otherwise return false. In the case of success, also
17327 fill in GROUP_SIZE_P with the requested group size or NULL if there is
17328 none. */
17329
17330 static bool
17331 grid_target_follows_gridifiable_pattern (gomp_target *target, tree *group_size_p)
17332 {
17333 if (gimple_omp_target_kind (target) != GF_OMP_TARGET_KIND_REGION)
17334 return false;
17335
17336 location_t tloc = gimple_location (target);
17337 gimple *stmt
17338 = grid_find_single_omp_among_assignments (gimple_omp_body (target),
17339 tloc, "target");
17340 if (!stmt)
17341 return false;
17342 gomp_teams *teams = dyn_cast <gomp_teams *> (stmt);
17343 tree group_size = NULL;
17344 if (!teams)
17345 {
17346 dump_printf_loc (MSG_NOTE, tloc,
17347 "Will not turn target construct into a simple "
17348 "GPGPU kernel because it does not have a sole teams "
17349 "construct in it.\n");
17350 return false;
17351 }
17352
17353 tree clauses = gimple_omp_teams_clauses (teams);
17354 while (clauses)
17355 {
17356 switch (OMP_CLAUSE_CODE (clauses))
17357 {
17358 case OMP_CLAUSE_NUM_TEAMS:
17359 if (dump_enabled_p ())
17360 dump_printf_loc (MSG_NOTE, tloc,
17361 "Will not turn target construct into a "
17362 "gridified GPGPU kernel because we cannot "
17363 "handle num_teams clause of teams "
17364 "construct\n ");
17365 return false;
17366
17367 case OMP_CLAUSE_REDUCTION:
17368 if (dump_enabled_p ())
17369 dump_printf_loc (MSG_NOTE, tloc,
17370 "Will not turn target construct into a "
17371 "gridified GPGPU kernel because a reduction "
17372 "clause is present\n ");
17373 return false;
17374
17375 case OMP_CLAUSE_LASTPRIVATE:
17376 if (dump_enabled_p ())
17377 dump_printf_loc (MSG_NOTE, tloc,
17378 "Will not turn target construct into a "
17379 "gridified GPGPU kernel because a lastprivate "
17380 "clause is present\n ");
17381 return false;
17382
17383 case OMP_CLAUSE_THREAD_LIMIT:
17384 group_size = OMP_CLAUSE_OPERAND (clauses, 0);
17385 break;
17386
17387 default:
17388 break;
17389 }
17390 clauses = OMP_CLAUSE_CHAIN (clauses);
17391 }
17392
17393 stmt = grid_find_single_omp_among_assignments (gimple_omp_body (teams), tloc,
17394 "teams");
17395 if (!stmt)
17396 return false;
17397 gomp_for *dist = dyn_cast <gomp_for *> (stmt);
17398 if (!dist)
17399 {
17400 dump_printf_loc (MSG_NOTE, tloc,
17401 "Will not turn target construct into a simple "
17402 "GPGPU kernel because the teams construct does not have "
17403 "a sole distribute construct in it.\n");
17404 return false;
17405 }
17406
17407 gcc_assert (gimple_omp_for_kind (dist) == GF_OMP_FOR_KIND_DISTRIBUTE);
17408 if (!gimple_omp_for_combined_p (dist))
17409 {
17410 if (dump_enabled_p ())
17411 dump_printf_loc (MSG_NOTE, tloc,
17412 "Will not turn target construct into a gridified GPGPU "
17413 "kernel because we cannot handle a standalone "
17414 "distribute construct\n ");
17415 return false;
17416 }
17417 if (dist->collapse > 1)
17418 {
17419 if (dump_enabled_p ())
17420 dump_printf_loc (MSG_NOTE, tloc,
17421 "Will not turn target construct into a gridified GPGPU "
17422 "kernel because the distribute construct contains "
17423 "collapse clause\n");
17424 return false;
17425 }
17426 struct omp_for_data fd;
17427 extract_omp_for_data (dist, &fd, NULL);
17428 if (fd.chunk_size)
17429 {
17430 if (group_size && !operand_equal_p (group_size, fd.chunk_size, 0))
17431 {
17432 if (dump_enabled_p ())
17433 dump_printf_loc (MSG_NOTE, tloc,
17434 "Will not turn target construct into a "
17435 "gridified GPGPU kernel because the teams "
17436 "thread limit is different from distribute "
17437 "schedule chunk\n");
17438 return false;
17439 }
17440 group_size = fd.chunk_size;
17441 }
17442 stmt = grid_find_single_omp_among_assignments (gimple_omp_body (dist), tloc,
17443 "distribute");
17444 gomp_parallel *par;
17445 if (!stmt || !(par = dyn_cast <gomp_parallel *> (stmt)))
17446 return false;
17447
17448 clauses = gimple_omp_parallel_clauses (par);
17449 while (clauses)
17450 {
17451 switch (OMP_CLAUSE_CODE (clauses))
17452 {
17453 case OMP_CLAUSE_NUM_THREADS:
17454 if (dump_enabled_p ())
17455 dump_printf_loc (MSG_NOTE, tloc,
17456 "Will not turn target construct into a gridified"
17457 "GPGPU kernel because there is a num_threads "
17458 "clause of the parallel construct\n");
17459 return false;
17460
17461 case OMP_CLAUSE_REDUCTION:
17462 if (dump_enabled_p ())
17463 dump_printf_loc (MSG_NOTE, tloc,
17464 "Will not turn target construct into a "
17465 "gridified GPGPU kernel because a reduction "
17466 "clause is present\n ");
17467 return false;
17468
17469 case OMP_CLAUSE_LASTPRIVATE:
17470 if (dump_enabled_p ())
17471 dump_printf_loc (MSG_NOTE, tloc,
17472 "Will not turn target construct into a "
17473 "gridified GPGPU kernel because a lastprivate "
17474 "clause is present\n ");
17475 return false;
17476
17477 default:
17478 break;
17479 }
17480 clauses = OMP_CLAUSE_CHAIN (clauses);
17481 }
17482
17483 stmt = grid_find_single_omp_among_assignments (gimple_omp_body (par), tloc,
17484 "parallel");
17485 gomp_for *gfor;
17486 if (!stmt || !(gfor = dyn_cast <gomp_for *> (stmt)))
17487 return false;
17488
17489 if (gimple_omp_for_kind (gfor) != GF_OMP_FOR_KIND_FOR)
17490 {
17491 if (dump_enabled_p ())
17492 dump_printf_loc (MSG_NOTE, tloc,
17493 "Will not turn target construct into a gridified GPGPU "
17494 "kernel because the inner loop is not a simple for "
17495 "loop\n");
17496 return false;
17497 }
17498 if (gfor->collapse > 1)
17499 {
17500 if (dump_enabled_p ())
17501 dump_printf_loc (MSG_NOTE, tloc,
17502 "Will not turn target construct into a gridified GPGPU "
17503 "kernel because the inner loop contains collapse "
17504 "clause\n");
17505 return false;
17506 }
17507
17508 if (!grid_seq_only_contains_local_assignments (gimple_omp_for_pre_body (gfor)))
17509 {
17510 if (dump_enabled_p ())
17511 dump_printf_loc (MSG_NOTE, tloc,
17512 "Will not turn target construct into a gridified GPGPU "
17513 "kernel because the inner loop pre_body contains"
17514 "a complex instruction\n");
17515 return false;
17516 }
17517
17518 clauses = gimple_omp_for_clauses (gfor);
17519 while (clauses)
17520 {
17521 switch (OMP_CLAUSE_CODE (clauses))
17522 {
17523 case OMP_CLAUSE_SCHEDULE:
17524 if (OMP_CLAUSE_SCHEDULE_KIND (clauses) != OMP_CLAUSE_SCHEDULE_AUTO)
17525 {
17526 if (dump_enabled_p ())
17527 dump_printf_loc (MSG_NOTE, tloc,
17528 "Will not turn target construct into a "
17529 "gridified GPGPU kernel because the inner "
17530 "loop has a non-automatic scheduling clause\n");
17531 return false;
17532 }
17533 break;
17534
17535 case OMP_CLAUSE_REDUCTION:
17536 if (dump_enabled_p ())
17537 dump_printf_loc (MSG_NOTE, tloc,
17538 "Will not turn target construct into a "
17539 "gridified GPGPU kernel because a reduction "
17540 "clause is present\n ");
17541 return false;
17542
17543 case OMP_CLAUSE_LASTPRIVATE:
17544 if (dump_enabled_p ())
17545 dump_printf_loc (MSG_NOTE, tloc,
17546 "Will not turn target construct into a "
17547 "gridified GPGPU kernel because a lastprivate "
17548 "clause is present\n ");
17549 return false;
17550
17551 default:
17552 break;
17553 }
17554 clauses = OMP_CLAUSE_CHAIN (clauses);
17555 }
17556
17557 struct walk_stmt_info wi;
17558 memset (&wi, 0, sizeof (wi));
17559 if (walk_gimple_seq (gimple_omp_body (gfor),
17560 grid_find_ungridifiable_statement,
17561 NULL, &wi))
17562 {
17563 gimple *bad = (gimple *) wi.info;
17564 if (dump_enabled_p ())
17565 {
17566 if (is_gimple_call (bad))
17567 dump_printf_loc (MSG_NOTE, tloc,
17568 "Will not turn target construct into a gridified "
17569 " GPGPU kernel because the inner loop contains "
17570 "call to a noreturn function\n");
17571 if (gimple_code (bad) == GIMPLE_OMP_FOR)
17572 dump_printf_loc (MSG_NOTE, tloc,
17573 "Will not turn target construct into a gridified "
17574 " GPGPU kernel because the inner loop contains "
17575 "a simd construct\n");
17576 else
17577 dump_printf_loc (MSG_NOTE, tloc,
17578 "Will not turn target construct into a gridified "
17579 "GPGPU kernel because the inner loop contains "
17580 "statement %s which cannot be transformed\n",
17581 gimple_code_name[(int) gimple_code (bad)]);
17582 }
17583 return false;
17584 }
17585
17586 *group_size_p = group_size;
17587 return true;
17588 }
17589
17590 /* Operand walker, used to remap pre-body declarations according to a hash map
17591 provided in DATA. */
17592
17593 static tree
17594 grid_remap_prebody_decls (tree *tp, int *walk_subtrees, void *data)
17595 {
17596 tree t = *tp;
17597
17598 if (DECL_P (t) || TYPE_P (t))
17599 *walk_subtrees = 0;
17600 else
17601 *walk_subtrees = 1;
17602
17603 if (TREE_CODE (t) == VAR_DECL)
17604 {
17605 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
17606 hash_map<tree, tree> *declmap = (hash_map<tree, tree> *) wi->info;
17607 tree *repl = declmap->get (t);
17608 if (repl)
17609 *tp = *repl;
17610 }
17611 return NULL_TREE;
17612 }
17613
17614 /* Copy leading register-type assignments to local variables in SRC to just
17615 before DST, Creating temporaries, adjusting mapping of operands in WI and
17616 remapping operands as necessary. Add any new temporaries to TGT_BIND.
17617 Return the first statement that does not conform to
17618 grid_reg_assignment_to_local_var_p or NULL. */
17619
17620 static gimple *
17621 grid_copy_leading_local_assignments (gimple_seq src, gimple_stmt_iterator *dst,
17622 gbind *tgt_bind, struct walk_stmt_info *wi)
17623 {
17624 hash_map<tree, tree> *declmap = (hash_map<tree, tree> *) wi->info;
17625 gimple_stmt_iterator gsi;
17626 for (gsi = gsi_start (src); !gsi_end_p (gsi); gsi_next (&gsi))
17627 {
17628 gimple *stmt = gsi_stmt (gsi);
17629 if (gbind *bind = dyn_cast <gbind *> (stmt))
17630 {
17631 gimple *r = grid_copy_leading_local_assignments
17632 (gimple_bind_body (bind), dst, tgt_bind, wi);
17633 if (r)
17634 return r;
17635 else
17636 continue;
17637 }
17638 if (!grid_reg_assignment_to_local_var_p (stmt))
17639 return stmt;
17640 tree lhs = gimple_assign_lhs (as_a <gassign *> (stmt));
17641 tree repl = copy_var_decl (lhs, create_tmp_var_name (NULL),
17642 TREE_TYPE (lhs));
17643 DECL_CONTEXT (repl) = current_function_decl;
17644 gimple_bind_append_vars (tgt_bind, repl);
17645
17646 declmap->put (lhs, repl);
17647 gassign *copy = as_a <gassign *> (gimple_copy (stmt));
17648 walk_gimple_op (copy, grid_remap_prebody_decls, wi);
17649 gsi_insert_before (dst, copy, GSI_SAME_STMT);
17650 }
17651 return NULL;
17652 }
17653
17654 /* Given freshly copied top level kernel SEQ, identify the individual OMP
17655 components, mark them as part of kernel and return the inner loop, and copy
17656 assignment leading to them just before DST, remapping them using WI and
17657 adding new temporaries to TGT_BIND. */
17658
17659 static gomp_for *
17660 grid_process_kernel_body_copy (gimple_seq seq, gimple_stmt_iterator *dst,
17661 gbind *tgt_bind, struct walk_stmt_info *wi)
17662 {
17663 gimple *stmt = grid_copy_leading_local_assignments (seq, dst, tgt_bind, wi);
17664 gomp_teams *teams = dyn_cast <gomp_teams *> (stmt);
17665 gcc_assert (teams);
17666 gimple_omp_teams_set_grid_phony (teams, true);
17667 stmt = grid_copy_leading_local_assignments (gimple_omp_body (teams), dst,
17668 tgt_bind, wi);
17669 gcc_checking_assert (stmt);
17670 gomp_for *dist = dyn_cast <gomp_for *> (stmt);
17671 gcc_assert (dist);
17672 gimple_seq prebody = gimple_omp_for_pre_body (dist);
17673 if (prebody)
17674 grid_copy_leading_local_assignments (prebody, dst, tgt_bind, wi);
17675 gimple_omp_for_set_grid_phony (dist, true);
17676 stmt = grid_copy_leading_local_assignments (gimple_omp_body (dist), dst,
17677 tgt_bind, wi);
17678 gcc_checking_assert (stmt);
17679
17680 gomp_parallel *parallel = as_a <gomp_parallel *> (stmt);
17681 gimple_omp_parallel_set_grid_phony (parallel, true);
17682 stmt = grid_copy_leading_local_assignments (gimple_omp_body (parallel), dst,
17683 tgt_bind, wi);
17684 gomp_for *inner_loop = as_a <gomp_for *> (stmt);
17685 gimple_omp_for_set_kind (inner_loop, GF_OMP_FOR_KIND_GRID_LOOP);
17686 prebody = gimple_omp_for_pre_body (inner_loop);
17687 if (prebody)
17688 grid_copy_leading_local_assignments (prebody, dst, tgt_bind, wi);
17689
17690 return inner_loop;
17691 }
17692
17693 /* If TARGET points to a GOMP_TARGET which follows a gridifiable pattern,
17694 create a GPU kernel for it. GSI must point to the same statement, TGT_BIND
17695 is the bind into which temporaries inserted before TARGET should be
17696 added. */
17697
17698 static void
17699 grid_attempt_target_gridification (gomp_target *target,
17700 gimple_stmt_iterator *gsi,
17701 gbind *tgt_bind)
17702 {
17703 tree group_size;
17704 if (!target || !grid_target_follows_gridifiable_pattern (target, &group_size))
17705 return;
17706
17707 location_t loc = gimple_location (target);
17708 if (dump_enabled_p ())
17709 dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc,
17710 "Target construct will be turned into a gridified GPGPU "
17711 "kernel\n");
17712
17713 /* Copy target body to a GPUKERNEL construct: */
17714 gimple_seq kernel_seq = copy_gimple_seq_and_replace_locals
17715 (gimple_omp_body (target));
17716
17717 hash_map<tree, tree> *declmap = new hash_map<tree, tree>;
17718 struct walk_stmt_info wi;
17719 memset (&wi, 0, sizeof (struct walk_stmt_info));
17720 wi.info = declmap;
17721
17722 /* Copy assignments in between OMP statements before target, mark OMP
17723 statements within copy appropriatly. */
17724 gomp_for *inner_loop = grid_process_kernel_body_copy (kernel_seq, gsi,
17725 tgt_bind, &wi);
17726
17727 gbind *old_bind = as_a <gbind *> (gimple_seq_first (gimple_omp_body (target)));
17728 gbind *new_bind = as_a <gbind *> (gimple_seq_first (kernel_seq));
17729 tree new_block = gimple_bind_block (new_bind);
17730 tree enc_block = BLOCK_SUPERCONTEXT (gimple_bind_block (old_bind));
17731 BLOCK_CHAIN (new_block) = BLOCK_SUBBLOCKS (enc_block);
17732 BLOCK_SUBBLOCKS (enc_block) = new_block;
17733 BLOCK_SUPERCONTEXT (new_block) = enc_block;
17734 gimple *gpukernel = gimple_build_omp_grid_body (kernel_seq);
17735 gimple_seq_add_stmt
17736 (gimple_bind_body_ptr (as_a <gbind *> (gimple_omp_body (target))),
17737 gpukernel);
17738
17739 walk_tree (&group_size, grid_remap_prebody_decls, &wi, NULL);
17740 push_gimplify_context ();
17741 size_t collapse = gimple_omp_for_collapse (inner_loop);
17742 for (size_t i = 0; i < collapse; i++)
17743 {
17744 tree itype, type = TREE_TYPE (gimple_omp_for_index (inner_loop, i));
17745 if (POINTER_TYPE_P (type))
17746 itype = signed_type_for (type);
17747 else
17748 itype = type;
17749
17750 enum tree_code cond_code = gimple_omp_for_cond (inner_loop, i);
17751 tree n1 = unshare_expr (gimple_omp_for_initial (inner_loop, i));
17752 walk_tree (&n1, grid_remap_prebody_decls, &wi, NULL);
17753 tree n2 = unshare_expr (gimple_omp_for_final (inner_loop, i));
17754 walk_tree (&n2, grid_remap_prebody_decls, &wi, NULL);
17755 adjust_for_condition (loc, &cond_code, &n2);
17756 tree step;
17757 step = get_omp_for_step_from_incr (loc,
17758 gimple_omp_for_incr (inner_loop, i));
17759 gimple_seq tmpseq = NULL;
17760 n1 = fold_convert (itype, n1);
17761 n2 = fold_convert (itype, n2);
17762 tree t = build_int_cst (itype, (cond_code == LT_EXPR ? -1 : 1));
17763 t = fold_build2 (PLUS_EXPR, itype, step, t);
17764 t = fold_build2 (PLUS_EXPR, itype, t, n2);
17765 t = fold_build2 (MINUS_EXPR, itype, t, n1);
17766 if (TYPE_UNSIGNED (itype) && cond_code == GT_EXPR)
17767 t = fold_build2 (TRUNC_DIV_EXPR, itype,
17768 fold_build1 (NEGATE_EXPR, itype, t),
17769 fold_build1 (NEGATE_EXPR, itype, step));
17770 else
17771 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
17772 tree gs = fold_convert (uint32_type_node, t);
17773 gimplify_expr (&gs, &tmpseq, NULL, is_gimple_val, fb_rvalue);
17774 if (!gimple_seq_empty_p (tmpseq))
17775 gsi_insert_seq_before (gsi, tmpseq, GSI_SAME_STMT);
17776
17777 tree ws;
17778 if (i == 0 && group_size)
17779 {
17780 ws = fold_convert (uint32_type_node, group_size);
17781 tmpseq = NULL;
17782 gimplify_expr (&ws, &tmpseq, NULL, is_gimple_val, fb_rvalue);
17783 if (!gimple_seq_empty_p (tmpseq))
17784 gsi_insert_seq_before (gsi, tmpseq, GSI_SAME_STMT);
17785 }
17786 else
17787 ws = build_zero_cst (uint32_type_node);
17788
17789 tree c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__GRIDDIM_);
17790 OMP_CLAUSE__GRIDDIM__DIMENSION (c) = i;
17791 OMP_CLAUSE__GRIDDIM__SIZE (c) = gs;
17792 OMP_CLAUSE__GRIDDIM__GROUP (c) = ws;
17793 OMP_CLAUSE_CHAIN (c) = gimple_omp_target_clauses (target);
17794 gimple_omp_target_set_clauses (target, c);
17795 }
17796 pop_gimplify_context (tgt_bind);
17797 delete declmap;
17798 return;
17799 }
17800
17801 /* Walker function doing all the work for create_target_kernels. */
17802
17803 static tree
17804 grid_gridify_all_targets_stmt (gimple_stmt_iterator *gsi,
17805 bool *handled_ops_p,
17806 struct walk_stmt_info *incoming)
17807 {
17808 *handled_ops_p = false;
17809
17810 gimple *stmt = gsi_stmt (*gsi);
17811 gomp_target *target = dyn_cast <gomp_target *> (stmt);
17812 if (target)
17813 {
17814 gbind *tgt_bind = (gbind *) incoming->info;
17815 gcc_checking_assert (tgt_bind);
17816 grid_attempt_target_gridification (target, gsi, tgt_bind);
17817 return NULL_TREE;
17818 }
17819 gbind *bind = dyn_cast <gbind *> (stmt);
17820 if (bind)
17821 {
17822 *handled_ops_p = true;
17823 struct walk_stmt_info wi;
17824 memset (&wi, 0, sizeof (wi));
17825 wi.info = bind;
17826 walk_gimple_seq_mod (gimple_bind_body_ptr (bind),
17827 grid_gridify_all_targets_stmt, NULL, &wi);
17828 }
17829 return NULL_TREE;
17830 }
17831
17832 /* Attempt to gridify all target constructs in BODY_P. All such targets will
17833 have their bodies duplicated, with the new copy being put into a
17834 gimple_omp_grid_body statement. All kernel-related construct within the
17835 grid_body will be marked with phony flags or kernel kinds. Moreover, some
17836 re-structuring is often needed, such as copying pre-bodies before the target
17837 construct so that kernel grid sizes can be computed. */
17838
17839 static void
17840 grid_gridify_all_targets (gimple_seq *body_p)
17841 {
17842 struct walk_stmt_info wi;
17843 memset (&wi, 0, sizeof (wi));
17844 walk_gimple_seq_mod (body_p, grid_gridify_all_targets_stmt, NULL, &wi);
17845 }
17846 \f
17847
17848 /* Main entry point. */
17849
17850 static unsigned int
17851 execute_lower_omp (void)
17852 {
17853 gimple_seq body;
17854 int i;
17855 omp_context *ctx;
17856
17857 /* This pass always runs, to provide PROP_gimple_lomp.
17858 But often, there is nothing to do. */
17859 if (flag_cilkplus == 0 && flag_openacc == 0 && flag_openmp == 0
17860 && flag_openmp_simd == 0)
17861 return 0;
17862
17863 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
17864 delete_omp_context);
17865
17866 body = gimple_body (current_function_decl);
17867
17868 if (hsa_gen_requested_p ())
17869 grid_gridify_all_targets (&body);
17870
17871 scan_omp (&body, NULL);
17872 gcc_assert (taskreg_nesting_level == 0);
17873 FOR_EACH_VEC_ELT (taskreg_contexts, i, ctx)
17874 finish_taskreg_scan (ctx);
17875 taskreg_contexts.release ();
17876
17877 if (all_contexts->root)
17878 {
17879 if (task_shared_vars)
17880 push_gimplify_context ();
17881 lower_omp (&body, NULL);
17882 if (task_shared_vars)
17883 pop_gimplify_context (NULL);
17884 }
17885
17886 if (all_contexts)
17887 {
17888 splay_tree_delete (all_contexts);
17889 all_contexts = NULL;
17890 }
17891 BITMAP_FREE (task_shared_vars);
17892 return 0;
17893 }
17894
17895 namespace {
17896
17897 const pass_data pass_data_lower_omp =
17898 {
17899 GIMPLE_PASS, /* type */
17900 "omplower", /* name */
17901 OPTGROUP_NONE, /* optinfo_flags */
17902 TV_NONE, /* tv_id */
17903 PROP_gimple_any, /* properties_required */
17904 PROP_gimple_lomp, /* properties_provided */
17905 0, /* properties_destroyed */
17906 0, /* todo_flags_start */
17907 0, /* todo_flags_finish */
17908 };
17909
17910 class pass_lower_omp : public gimple_opt_pass
17911 {
17912 public:
17913 pass_lower_omp (gcc::context *ctxt)
17914 : gimple_opt_pass (pass_data_lower_omp, ctxt)
17915 {}
17916
17917 /* opt_pass methods: */
17918 virtual unsigned int execute (function *) { return execute_lower_omp (); }
17919
17920 }; // class pass_lower_omp
17921
17922 } // anon namespace
17923
17924 gimple_opt_pass *
17925 make_pass_lower_omp (gcc::context *ctxt)
17926 {
17927 return new pass_lower_omp (ctxt);
17928 }
17929 \f
17930 /* The following is a utility to diagnose structured block violations.
17931 It is not part of the "omplower" pass, as that's invoked too late. It
17932 should be invoked by the respective front ends after gimplification. */
17933
17934 static splay_tree all_labels;
17935
17936 /* Check for mismatched contexts and generate an error if needed. Return
17937 true if an error is detected. */
17938
17939 static bool
17940 diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
17941 gimple *branch_ctx, gimple *label_ctx)
17942 {
17943 gcc_checking_assert (!branch_ctx || is_gimple_omp (branch_ctx));
17944 gcc_checking_assert (!label_ctx || is_gimple_omp (label_ctx));
17945
17946 if (label_ctx == branch_ctx)
17947 return false;
17948
17949 const char* kind = NULL;
17950
17951 if (flag_cilkplus)
17952 {
17953 if ((branch_ctx
17954 && gimple_code (branch_ctx) == GIMPLE_OMP_FOR
17955 && gimple_omp_for_kind (branch_ctx) == GF_OMP_FOR_KIND_CILKSIMD)
17956 || (label_ctx
17957 && gimple_code (label_ctx) == GIMPLE_OMP_FOR
17958 && gimple_omp_for_kind (label_ctx) == GF_OMP_FOR_KIND_CILKSIMD))
17959 kind = "Cilk Plus";
17960 }
17961 if (flag_openacc)
17962 {
17963 if ((branch_ctx && is_gimple_omp_oacc (branch_ctx))
17964 || (label_ctx && is_gimple_omp_oacc (label_ctx)))
17965 {
17966 gcc_checking_assert (kind == NULL);
17967 kind = "OpenACC";
17968 }
17969 }
17970 if (kind == NULL)
17971 {
17972 gcc_checking_assert (flag_openmp);
17973 kind = "OpenMP";
17974 }
17975
17976 /*
17977 Previously we kept track of the label's entire context in diagnose_sb_[12]
17978 so we could traverse it and issue a correct "exit" or "enter" error
17979 message upon a structured block violation.
17980
17981 We built the context by building a list with tree_cons'ing, but there is
17982 no easy counterpart in gimple tuples. It seems like far too much work
17983 for issuing exit/enter error messages. If someone really misses the
17984 distinct error message... patches welcome.
17985 */
17986
17987 #if 0
17988 /* Try to avoid confusing the user by producing and error message
17989 with correct "exit" or "enter" verbiage. We prefer "exit"
17990 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
17991 if (branch_ctx == NULL)
17992 exit_p = false;
17993 else
17994 {
17995 while (label_ctx)
17996 {
17997 if (TREE_VALUE (label_ctx) == branch_ctx)
17998 {
17999 exit_p = false;
18000 break;
18001 }
18002 label_ctx = TREE_CHAIN (label_ctx);
18003 }
18004 }
18005
18006 if (exit_p)
18007 error ("invalid exit from %s structured block", kind);
18008 else
18009 error ("invalid entry to %s structured block", kind);
18010 #endif
18011
18012 /* If it's obvious we have an invalid entry, be specific about the error. */
18013 if (branch_ctx == NULL)
18014 error ("invalid entry to %s structured block", kind);
18015 else
18016 {
18017 /* Otherwise, be vague and lazy, but efficient. */
18018 error ("invalid branch to/from %s structured block", kind);
18019 }
18020
18021 gsi_replace (gsi_p, gimple_build_nop (), false);
18022 return true;
18023 }
18024
18025 /* Pass 1: Create a minimal tree of structured blocks, and record
18026 where each label is found. */
18027
18028 static tree
18029 diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
18030 struct walk_stmt_info *wi)
18031 {
18032 gimple *context = (gimple *) wi->info;
18033 gimple *inner_context;
18034 gimple *stmt = gsi_stmt (*gsi_p);
18035
18036 *handled_ops_p = true;
18037
18038 switch (gimple_code (stmt))
18039 {
18040 WALK_SUBSTMTS;
18041
18042 case GIMPLE_OMP_PARALLEL:
18043 case GIMPLE_OMP_TASK:
18044 case GIMPLE_OMP_SECTIONS:
18045 case GIMPLE_OMP_SINGLE:
18046 case GIMPLE_OMP_SECTION:
18047 case GIMPLE_OMP_MASTER:
18048 case GIMPLE_OMP_ORDERED:
18049 case GIMPLE_OMP_CRITICAL:
18050 case GIMPLE_OMP_TARGET:
18051 case GIMPLE_OMP_TEAMS:
18052 case GIMPLE_OMP_TASKGROUP:
18053 /* The minimal context here is just the current OMP construct. */
18054 inner_context = stmt;
18055 wi->info = inner_context;
18056 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
18057 wi->info = context;
18058 break;
18059
18060 case GIMPLE_OMP_FOR:
18061 inner_context = stmt;
18062 wi->info = inner_context;
18063 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
18064 walk them. */
18065 walk_gimple_seq (gimple_omp_for_pre_body (stmt),
18066 diagnose_sb_1, NULL, wi);
18067 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
18068 wi->info = context;
18069 break;
18070
18071 case GIMPLE_LABEL:
18072 splay_tree_insert (all_labels,
18073 (splay_tree_key) gimple_label_label (
18074 as_a <glabel *> (stmt)),
18075 (splay_tree_value) context);
18076 break;
18077
18078 default:
18079 break;
18080 }
18081
18082 return NULL_TREE;
18083 }
18084
18085 /* Pass 2: Check each branch and see if its context differs from that of
18086 the destination label's context. */
18087
18088 static tree
18089 diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
18090 struct walk_stmt_info *wi)
18091 {
18092 gimple *context = (gimple *) wi->info;
18093 splay_tree_node n;
18094 gimple *stmt = gsi_stmt (*gsi_p);
18095
18096 *handled_ops_p = true;
18097
18098 switch (gimple_code (stmt))
18099 {
18100 WALK_SUBSTMTS;
18101
18102 case GIMPLE_OMP_PARALLEL:
18103 case GIMPLE_OMP_TASK:
18104 case GIMPLE_OMP_SECTIONS:
18105 case GIMPLE_OMP_SINGLE:
18106 case GIMPLE_OMP_SECTION:
18107 case GIMPLE_OMP_MASTER:
18108 case GIMPLE_OMP_ORDERED:
18109 case GIMPLE_OMP_CRITICAL:
18110 case GIMPLE_OMP_TARGET:
18111 case GIMPLE_OMP_TEAMS:
18112 case GIMPLE_OMP_TASKGROUP:
18113 wi->info = stmt;
18114 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
18115 wi->info = context;
18116 break;
18117
18118 case GIMPLE_OMP_FOR:
18119 wi->info = stmt;
18120 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
18121 walk them. */
18122 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt),
18123 diagnose_sb_2, NULL, wi);
18124 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
18125 wi->info = context;
18126 break;
18127
18128 case GIMPLE_COND:
18129 {
18130 gcond *cond_stmt = as_a <gcond *> (stmt);
18131 tree lab = gimple_cond_true_label (cond_stmt);
18132 if (lab)
18133 {
18134 n = splay_tree_lookup (all_labels,
18135 (splay_tree_key) lab);
18136 diagnose_sb_0 (gsi_p, context,
18137 n ? (gimple *) n->value : NULL);
18138 }
18139 lab = gimple_cond_false_label (cond_stmt);
18140 if (lab)
18141 {
18142 n = splay_tree_lookup (all_labels,
18143 (splay_tree_key) lab);
18144 diagnose_sb_0 (gsi_p, context,
18145 n ? (gimple *) n->value : NULL);
18146 }
18147 }
18148 break;
18149
18150 case GIMPLE_GOTO:
18151 {
18152 tree lab = gimple_goto_dest (stmt);
18153 if (TREE_CODE (lab) != LABEL_DECL)
18154 break;
18155
18156 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
18157 diagnose_sb_0 (gsi_p, context, n ? (gimple *) n->value : NULL);
18158 }
18159 break;
18160
18161 case GIMPLE_SWITCH:
18162 {
18163 gswitch *switch_stmt = as_a <gswitch *> (stmt);
18164 unsigned int i;
18165 for (i = 0; i < gimple_switch_num_labels (switch_stmt); ++i)
18166 {
18167 tree lab = CASE_LABEL (gimple_switch_label (switch_stmt, i));
18168 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
18169 if (n && diagnose_sb_0 (gsi_p, context, (gimple *) n->value))
18170 break;
18171 }
18172 }
18173 break;
18174
18175 case GIMPLE_RETURN:
18176 diagnose_sb_0 (gsi_p, context, NULL);
18177 break;
18178
18179 default:
18180 break;
18181 }
18182
18183 return NULL_TREE;
18184 }
18185
18186 /* Called from tree-cfg.c::make_edges to create cfg edges for all relevant
18187 GIMPLE_* codes. */
18188 bool
18189 make_gimple_omp_edges (basic_block bb, struct omp_region **region,
18190 int *region_idx)
18191 {
18192 gimple *last = last_stmt (bb);
18193 enum gimple_code code = gimple_code (last);
18194 struct omp_region *cur_region = *region;
18195 bool fallthru = false;
18196
18197 switch (code)
18198 {
18199 case GIMPLE_OMP_PARALLEL:
18200 case GIMPLE_OMP_TASK:
18201 case GIMPLE_OMP_FOR:
18202 case GIMPLE_OMP_SINGLE:
18203 case GIMPLE_OMP_TEAMS:
18204 case GIMPLE_OMP_MASTER:
18205 case GIMPLE_OMP_TASKGROUP:
18206 case GIMPLE_OMP_CRITICAL:
18207 case GIMPLE_OMP_SECTION:
18208 case GIMPLE_OMP_GRID_BODY:
18209 cur_region = new_omp_region (bb, code, cur_region);
18210 fallthru = true;
18211 break;
18212
18213 case GIMPLE_OMP_ORDERED:
18214 cur_region = new_omp_region (bb, code, cur_region);
18215 fallthru = true;
18216 if (find_omp_clause (gimple_omp_ordered_clauses
18217 (as_a <gomp_ordered *> (last)),
18218 OMP_CLAUSE_DEPEND))
18219 cur_region = cur_region->outer;
18220 break;
18221
18222 case GIMPLE_OMP_TARGET:
18223 cur_region = new_omp_region (bb, code, cur_region);
18224 fallthru = true;
18225 switch (gimple_omp_target_kind (last))
18226 {
18227 case GF_OMP_TARGET_KIND_REGION:
18228 case GF_OMP_TARGET_KIND_DATA:
18229 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
18230 case GF_OMP_TARGET_KIND_OACC_KERNELS:
18231 case GF_OMP_TARGET_KIND_OACC_DATA:
18232 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
18233 break;
18234 case GF_OMP_TARGET_KIND_UPDATE:
18235 case GF_OMP_TARGET_KIND_ENTER_DATA:
18236 case GF_OMP_TARGET_KIND_EXIT_DATA:
18237 case GF_OMP_TARGET_KIND_OACC_UPDATE:
18238 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
18239 case GF_OMP_TARGET_KIND_OACC_DECLARE:
18240 cur_region = cur_region->outer;
18241 break;
18242 default:
18243 gcc_unreachable ();
18244 }
18245 break;
18246
18247 case GIMPLE_OMP_SECTIONS:
18248 cur_region = new_omp_region (bb, code, cur_region);
18249 fallthru = true;
18250 break;
18251
18252 case GIMPLE_OMP_SECTIONS_SWITCH:
18253 fallthru = false;
18254 break;
18255
18256 case GIMPLE_OMP_ATOMIC_LOAD:
18257 case GIMPLE_OMP_ATOMIC_STORE:
18258 fallthru = true;
18259 break;
18260
18261 case GIMPLE_OMP_RETURN:
18262 /* In the case of a GIMPLE_OMP_SECTION, the edge will go
18263 somewhere other than the next block. This will be
18264 created later. */
18265 cur_region->exit = bb;
18266 if (cur_region->type == GIMPLE_OMP_TASK)
18267 /* Add an edge corresponding to not scheduling the task
18268 immediately. */
18269 make_edge (cur_region->entry, bb, EDGE_ABNORMAL);
18270 fallthru = cur_region->type != GIMPLE_OMP_SECTION;
18271 cur_region = cur_region->outer;
18272 break;
18273
18274 case GIMPLE_OMP_CONTINUE:
18275 cur_region->cont = bb;
18276 switch (cur_region->type)
18277 {
18278 case GIMPLE_OMP_FOR:
18279 /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
18280 succs edges as abnormal to prevent splitting
18281 them. */
18282 single_succ_edge (cur_region->entry)->flags |= EDGE_ABNORMAL;
18283 /* Make the loopback edge. */
18284 make_edge (bb, single_succ (cur_region->entry),
18285 EDGE_ABNORMAL);
18286
18287 /* Create an edge from GIMPLE_OMP_FOR to exit, which
18288 corresponds to the case that the body of the loop
18289 is not executed at all. */
18290 make_edge (cur_region->entry, bb->next_bb, EDGE_ABNORMAL);
18291 make_edge (bb, bb->next_bb, EDGE_FALLTHRU | EDGE_ABNORMAL);
18292 fallthru = false;
18293 break;
18294
18295 case GIMPLE_OMP_SECTIONS:
18296 /* Wire up the edges into and out of the nested sections. */
18297 {
18298 basic_block switch_bb = single_succ (cur_region->entry);
18299
18300 struct omp_region *i;
18301 for (i = cur_region->inner; i ; i = i->next)
18302 {
18303 gcc_assert (i->type == GIMPLE_OMP_SECTION);
18304 make_edge (switch_bb, i->entry, 0);
18305 make_edge (i->exit, bb, EDGE_FALLTHRU);
18306 }
18307
18308 /* Make the loopback edge to the block with
18309 GIMPLE_OMP_SECTIONS_SWITCH. */
18310 make_edge (bb, switch_bb, 0);
18311
18312 /* Make the edge from the switch to exit. */
18313 make_edge (switch_bb, bb->next_bb, 0);
18314 fallthru = false;
18315 }
18316 break;
18317
18318 case GIMPLE_OMP_TASK:
18319 fallthru = true;
18320 break;
18321
18322 default:
18323 gcc_unreachable ();
18324 }
18325 break;
18326
18327 default:
18328 gcc_unreachable ();
18329 }
18330
18331 if (*region != cur_region)
18332 {
18333 *region = cur_region;
18334 if (cur_region)
18335 *region_idx = cur_region->entry->index;
18336 else
18337 *region_idx = 0;
18338 }
18339
18340 return fallthru;
18341 }
18342
18343 static unsigned int
18344 diagnose_omp_structured_block_errors (void)
18345 {
18346 struct walk_stmt_info wi;
18347 gimple_seq body = gimple_body (current_function_decl);
18348
18349 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
18350
18351 memset (&wi, 0, sizeof (wi));
18352 walk_gimple_seq (body, diagnose_sb_1, NULL, &wi);
18353
18354 memset (&wi, 0, sizeof (wi));
18355 wi.want_locations = true;
18356 walk_gimple_seq_mod (&body, diagnose_sb_2, NULL, &wi);
18357
18358 gimple_set_body (current_function_decl, body);
18359
18360 splay_tree_delete (all_labels);
18361 all_labels = NULL;
18362
18363 return 0;
18364 }
18365
18366 namespace {
18367
18368 const pass_data pass_data_diagnose_omp_blocks =
18369 {
18370 GIMPLE_PASS, /* type */
18371 "*diagnose_omp_blocks", /* name */
18372 OPTGROUP_NONE, /* optinfo_flags */
18373 TV_NONE, /* tv_id */
18374 PROP_gimple_any, /* properties_required */
18375 0, /* properties_provided */
18376 0, /* properties_destroyed */
18377 0, /* todo_flags_start */
18378 0, /* todo_flags_finish */
18379 };
18380
18381 class pass_diagnose_omp_blocks : public gimple_opt_pass
18382 {
18383 public:
18384 pass_diagnose_omp_blocks (gcc::context *ctxt)
18385 : gimple_opt_pass (pass_data_diagnose_omp_blocks, ctxt)
18386 {}
18387
18388 /* opt_pass methods: */
18389 virtual bool gate (function *)
18390 {
18391 return flag_cilkplus || flag_openacc || flag_openmp;
18392 }
18393 virtual unsigned int execute (function *)
18394 {
18395 return diagnose_omp_structured_block_errors ();
18396 }
18397
18398 }; // class pass_diagnose_omp_blocks
18399
18400 } // anon namespace
18401
18402 gimple_opt_pass *
18403 make_pass_diagnose_omp_blocks (gcc::context *ctxt)
18404 {
18405 return new pass_diagnose_omp_blocks (ctxt);
18406 }
18407 \f
18408 /* Helper function for omp_finish_file routine. Takes decls from V_DECLS and
18409 adds their addresses and sizes to constructor-vector V_CTOR. */
18410 static void
18411 add_decls_addresses_to_decl_constructor (vec<tree, va_gc> *v_decls,
18412 vec<constructor_elt, va_gc> *v_ctor)
18413 {
18414 unsigned len = vec_safe_length (v_decls);
18415 for (unsigned i = 0; i < len; i++)
18416 {
18417 tree it = (*v_decls)[i];
18418 bool is_var = TREE_CODE (it) == VAR_DECL;
18419 bool is_link_var
18420 = is_var
18421 #ifdef ACCEL_COMPILER
18422 && DECL_HAS_VALUE_EXPR_P (it)
18423 #endif
18424 && lookup_attribute ("omp declare target link", DECL_ATTRIBUTES (it));
18425
18426 tree size = NULL_TREE;
18427 if (is_var)
18428 size = fold_convert (const_ptr_type_node, DECL_SIZE_UNIT (it));
18429
18430 tree addr;
18431 if (!is_link_var)
18432 addr = build_fold_addr_expr (it);
18433 else
18434 {
18435 #ifdef ACCEL_COMPILER
18436 /* For "omp declare target link" vars add address of the pointer to
18437 the target table, instead of address of the var. */
18438 tree value_expr = DECL_VALUE_EXPR (it);
18439 tree link_ptr_decl = TREE_OPERAND (value_expr, 0);
18440 varpool_node::finalize_decl (link_ptr_decl);
18441 addr = build_fold_addr_expr (link_ptr_decl);
18442 #else
18443 addr = build_fold_addr_expr (it);
18444 #endif
18445
18446 /* Most significant bit of the size marks "omp declare target link"
18447 vars in host and target tables. */
18448 unsigned HOST_WIDE_INT isize = tree_to_uhwi (size);
18449 isize |= 1ULL << (int_size_in_bytes (const_ptr_type_node)
18450 * BITS_PER_UNIT - 1);
18451 size = wide_int_to_tree (const_ptr_type_node, isize);
18452 }
18453
18454 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE, addr);
18455 if (is_var)
18456 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE, size);
18457 }
18458 }
18459
18460 /* Create new symbols containing (address, size) pairs for global variables,
18461 marked with "omp declare target" attribute, as well as addresses for the
18462 functions, which are outlined offloading regions. */
18463 void
18464 omp_finish_file (void)
18465 {
18466 unsigned num_funcs = vec_safe_length (offload_funcs);
18467 unsigned num_vars = vec_safe_length (offload_vars);
18468
18469 if (num_funcs == 0 && num_vars == 0)
18470 return;
18471
18472 if (targetm_common.have_named_sections)
18473 {
18474 vec<constructor_elt, va_gc> *v_f, *v_v;
18475 vec_alloc (v_f, num_funcs);
18476 vec_alloc (v_v, num_vars * 2);
18477
18478 add_decls_addresses_to_decl_constructor (offload_funcs, v_f);
18479 add_decls_addresses_to_decl_constructor (offload_vars, v_v);
18480
18481 tree vars_decl_type = build_array_type_nelts (pointer_sized_int_node,
18482 num_vars * 2);
18483 tree funcs_decl_type = build_array_type_nelts (pointer_sized_int_node,
18484 num_funcs);
18485 SET_TYPE_ALIGN (vars_decl_type, TYPE_ALIGN (pointer_sized_int_node));
18486 SET_TYPE_ALIGN (funcs_decl_type, TYPE_ALIGN (pointer_sized_int_node));
18487 tree ctor_v = build_constructor (vars_decl_type, v_v);
18488 tree ctor_f = build_constructor (funcs_decl_type, v_f);
18489 TREE_CONSTANT (ctor_v) = TREE_CONSTANT (ctor_f) = 1;
18490 TREE_STATIC (ctor_v) = TREE_STATIC (ctor_f) = 1;
18491 tree funcs_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
18492 get_identifier (".offload_func_table"),
18493 funcs_decl_type);
18494 tree vars_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
18495 get_identifier (".offload_var_table"),
18496 vars_decl_type);
18497 TREE_STATIC (funcs_decl) = TREE_STATIC (vars_decl) = 1;
18498 /* Do not align tables more than TYPE_ALIGN (pointer_sized_int_node),
18499 otherwise a joint table in a binary will contain padding between
18500 tables from multiple object files. */
18501 DECL_USER_ALIGN (funcs_decl) = DECL_USER_ALIGN (vars_decl) = 1;
18502 SET_DECL_ALIGN (funcs_decl, TYPE_ALIGN (funcs_decl_type));
18503 SET_DECL_ALIGN (vars_decl, TYPE_ALIGN (vars_decl_type));
18504 DECL_INITIAL (funcs_decl) = ctor_f;
18505 DECL_INITIAL (vars_decl) = ctor_v;
18506 set_decl_section_name (funcs_decl, OFFLOAD_FUNC_TABLE_SECTION_NAME);
18507 set_decl_section_name (vars_decl, OFFLOAD_VAR_TABLE_SECTION_NAME);
18508
18509 varpool_node::finalize_decl (vars_decl);
18510 varpool_node::finalize_decl (funcs_decl);
18511 }
18512 else
18513 {
18514 for (unsigned i = 0; i < num_funcs; i++)
18515 {
18516 tree it = (*offload_funcs)[i];
18517 targetm.record_offload_symbol (it);
18518 }
18519 for (unsigned i = 0; i < num_vars; i++)
18520 {
18521 tree it = (*offload_vars)[i];
18522 targetm.record_offload_symbol (it);
18523 }
18524 }
18525 }
18526
18527 /* Find the number of threads (POS = false), or thread number (POS =
18528 true) for an OpenACC region partitioned as MASK. Setup code
18529 required for the calculation is added to SEQ. */
18530
18531 static tree
18532 oacc_thread_numbers (bool pos, int mask, gimple_seq *seq)
18533 {
18534 tree res = pos ? NULL_TREE : build_int_cst (unsigned_type_node, 1);
18535 unsigned ix;
18536
18537 /* Start at gang level, and examine relevant dimension indices. */
18538 for (ix = GOMP_DIM_GANG; ix != GOMP_DIM_MAX; ix++)
18539 if (GOMP_DIM_MASK (ix) & mask)
18540 {
18541 tree arg = build_int_cst (unsigned_type_node, ix);
18542
18543 if (res)
18544 {
18545 /* We had an outer index, so scale that by the size of
18546 this dimension. */
18547 tree n = create_tmp_var (integer_type_node);
18548 gimple *call
18549 = gimple_build_call_internal (IFN_GOACC_DIM_SIZE, 1, arg);
18550
18551 gimple_call_set_lhs (call, n);
18552 gimple_seq_add_stmt (seq, call);
18553 res = fold_build2 (MULT_EXPR, integer_type_node, res, n);
18554 }
18555 if (pos)
18556 {
18557 /* Determine index in this dimension. */
18558 tree id = create_tmp_var (integer_type_node);
18559 gimple *call = gimple_build_call_internal
18560 (IFN_GOACC_DIM_POS, 1, arg);
18561
18562 gimple_call_set_lhs (call, id);
18563 gimple_seq_add_stmt (seq, call);
18564 if (res)
18565 res = fold_build2 (PLUS_EXPR, integer_type_node, res, id);
18566 else
18567 res = id;
18568 }
18569 }
18570
18571 if (res == NULL_TREE)
18572 res = integer_zero_node;
18573
18574 return res;
18575 }
18576
18577 /* Transform IFN_GOACC_LOOP calls to actual code. See
18578 expand_oacc_for for where these are generated. At the vector
18579 level, we stride loops, such that each member of a warp will
18580 operate on adjacent iterations. At the worker and gang level,
18581 each gang/warp executes a set of contiguous iterations. Chunking
18582 can override this such that each iteration engine executes a
18583 contiguous chunk, and then moves on to stride to the next chunk. */
18584
18585 static void
18586 oacc_xform_loop (gcall *call)
18587 {
18588 gimple_stmt_iterator gsi = gsi_for_stmt (call);
18589 enum ifn_goacc_loop_kind code
18590 = (enum ifn_goacc_loop_kind) TREE_INT_CST_LOW (gimple_call_arg (call, 0));
18591 tree dir = gimple_call_arg (call, 1);
18592 tree range = gimple_call_arg (call, 2);
18593 tree step = gimple_call_arg (call, 3);
18594 tree chunk_size = NULL_TREE;
18595 unsigned mask = (unsigned) TREE_INT_CST_LOW (gimple_call_arg (call, 5));
18596 tree lhs = gimple_call_lhs (call);
18597 tree type = TREE_TYPE (lhs);
18598 tree diff_type = TREE_TYPE (range);
18599 tree r = NULL_TREE;
18600 gimple_seq seq = NULL;
18601 bool chunking = false, striding = true;
18602 unsigned outer_mask = mask & (~mask + 1); // Outermost partitioning
18603 unsigned inner_mask = mask & ~outer_mask; // Inner partitioning (if any)
18604
18605 #ifdef ACCEL_COMPILER
18606 chunk_size = gimple_call_arg (call, 4);
18607 if (integer_minus_onep (chunk_size) /* Force static allocation. */
18608 || integer_zerop (chunk_size)) /* Default (also static). */
18609 {
18610 /* If we're at the gang level, we want each to execute a
18611 contiguous run of iterations. Otherwise we want each element
18612 to stride. */
18613 striding = !(outer_mask & GOMP_DIM_MASK (GOMP_DIM_GANG));
18614 chunking = false;
18615 }
18616 else
18617 {
18618 /* Chunk of size 1 is striding. */
18619 striding = integer_onep (chunk_size);
18620 chunking = !striding;
18621 }
18622 #endif
18623
18624 /* striding=true, chunking=true
18625 -> invalid.
18626 striding=true, chunking=false
18627 -> chunks=1
18628 striding=false,chunking=true
18629 -> chunks=ceil (range/(chunksize*threads*step))
18630 striding=false,chunking=false
18631 -> chunk_size=ceil(range/(threads*step)),chunks=1 */
18632 push_gimplify_context (true);
18633
18634 switch (code)
18635 {
18636 default: gcc_unreachable ();
18637
18638 case IFN_GOACC_LOOP_CHUNKS:
18639 if (!chunking)
18640 r = build_int_cst (type, 1);
18641 else
18642 {
18643 /* chunk_max
18644 = (range - dir) / (chunks * step * num_threads) + dir */
18645 tree per = oacc_thread_numbers (false, mask, &seq);
18646 per = fold_convert (type, per);
18647 chunk_size = fold_convert (type, chunk_size);
18648 per = fold_build2 (MULT_EXPR, type, per, chunk_size);
18649 per = fold_build2 (MULT_EXPR, type, per, step);
18650 r = build2 (MINUS_EXPR, type, range, dir);
18651 r = build2 (PLUS_EXPR, type, r, per);
18652 r = build2 (TRUNC_DIV_EXPR, type, r, per);
18653 }
18654 break;
18655
18656 case IFN_GOACC_LOOP_STEP:
18657 {
18658 /* If striding, step by the entire compute volume, otherwise
18659 step by the inner volume. */
18660 unsigned volume = striding ? mask : inner_mask;
18661
18662 r = oacc_thread_numbers (false, volume, &seq);
18663 r = build2 (MULT_EXPR, type, fold_convert (type, r), step);
18664 }
18665 break;
18666
18667 case IFN_GOACC_LOOP_OFFSET:
18668 if (striding)
18669 {
18670 r = oacc_thread_numbers (true, mask, &seq);
18671 r = fold_convert (diff_type, r);
18672 }
18673 else
18674 {
18675 tree inner_size = oacc_thread_numbers (false, inner_mask, &seq);
18676 tree outer_size = oacc_thread_numbers (false, outer_mask, &seq);
18677 tree volume = fold_build2 (MULT_EXPR, TREE_TYPE (inner_size),
18678 inner_size, outer_size);
18679
18680 volume = fold_convert (diff_type, volume);
18681 if (chunking)
18682 chunk_size = fold_convert (diff_type, chunk_size);
18683 else
18684 {
18685 tree per = fold_build2 (MULT_EXPR, diff_type, volume, step);
18686
18687 chunk_size = build2 (MINUS_EXPR, diff_type, range, dir);
18688 chunk_size = build2 (PLUS_EXPR, diff_type, chunk_size, per);
18689 chunk_size = build2 (TRUNC_DIV_EXPR, diff_type, chunk_size, per);
18690 }
18691
18692 tree span = build2 (MULT_EXPR, diff_type, chunk_size,
18693 fold_convert (diff_type, inner_size));
18694 r = oacc_thread_numbers (true, outer_mask, &seq);
18695 r = fold_convert (diff_type, r);
18696 r = build2 (MULT_EXPR, diff_type, r, span);
18697
18698 tree inner = oacc_thread_numbers (true, inner_mask, &seq);
18699 inner = fold_convert (diff_type, inner);
18700 r = fold_build2 (PLUS_EXPR, diff_type, r, inner);
18701
18702 if (chunking)
18703 {
18704 tree chunk = fold_convert (diff_type, gimple_call_arg (call, 6));
18705 tree per
18706 = fold_build2 (MULT_EXPR, diff_type, volume, chunk_size);
18707 per = build2 (MULT_EXPR, diff_type, per, chunk);
18708
18709 r = build2 (PLUS_EXPR, diff_type, r, per);
18710 }
18711 }
18712 r = fold_build2 (MULT_EXPR, diff_type, r, step);
18713 if (type != diff_type)
18714 r = fold_convert (type, r);
18715 break;
18716
18717 case IFN_GOACC_LOOP_BOUND:
18718 if (striding)
18719 r = range;
18720 else
18721 {
18722 tree inner_size = oacc_thread_numbers (false, inner_mask, &seq);
18723 tree outer_size = oacc_thread_numbers (false, outer_mask, &seq);
18724 tree volume = fold_build2 (MULT_EXPR, TREE_TYPE (inner_size),
18725 inner_size, outer_size);
18726
18727 volume = fold_convert (diff_type, volume);
18728 if (chunking)
18729 chunk_size = fold_convert (diff_type, chunk_size);
18730 else
18731 {
18732 tree per = fold_build2 (MULT_EXPR, diff_type, volume, step);
18733
18734 chunk_size = build2 (MINUS_EXPR, diff_type, range, dir);
18735 chunk_size = build2 (PLUS_EXPR, diff_type, chunk_size, per);
18736 chunk_size = build2 (TRUNC_DIV_EXPR, diff_type, chunk_size, per);
18737 }
18738
18739 tree span = build2 (MULT_EXPR, diff_type, chunk_size,
18740 fold_convert (diff_type, inner_size));
18741
18742 r = fold_build2 (MULT_EXPR, diff_type, span, step);
18743
18744 tree offset = gimple_call_arg (call, 6);
18745 r = build2 (PLUS_EXPR, diff_type, r,
18746 fold_convert (diff_type, offset));
18747 r = build2 (integer_onep (dir) ? MIN_EXPR : MAX_EXPR,
18748 diff_type, r, range);
18749 }
18750 if (diff_type != type)
18751 r = fold_convert (type, r);
18752 break;
18753 }
18754
18755 gimplify_assign (lhs, r, &seq);
18756
18757 pop_gimplify_context (NULL);
18758
18759 gsi_replace_with_seq (&gsi, seq, true);
18760 }
18761
18762 /* Default partitioned and minimum partitioned dimensions. */
18763
18764 static int oacc_default_dims[GOMP_DIM_MAX];
18765 static int oacc_min_dims[GOMP_DIM_MAX];
18766
18767 /* Parse the default dimension parameter. This is a set of
18768 :-separated optional compute dimensions. Each specified dimension
18769 is a positive integer. When device type support is added, it is
18770 planned to be a comma separated list of such compute dimensions,
18771 with all but the first prefixed by the colon-terminated device
18772 type. */
18773
18774 static void
18775 oacc_parse_default_dims (const char *dims)
18776 {
18777 int ix;
18778
18779 for (ix = GOMP_DIM_MAX; ix--;)
18780 {
18781 oacc_default_dims[ix] = -1;
18782 oacc_min_dims[ix] = 1;
18783 }
18784
18785 #ifndef ACCEL_COMPILER
18786 /* Cannot be overridden on the host. */
18787 dims = NULL;
18788 #endif
18789 if (dims)
18790 {
18791 const char *pos = dims;
18792
18793 for (ix = 0; *pos && ix != GOMP_DIM_MAX; ix++)
18794 {
18795 if (ix)
18796 {
18797 if (*pos != ':')
18798 goto malformed;
18799 pos++;
18800 }
18801
18802 if (*pos != ':')
18803 {
18804 long val;
18805 const char *eptr;
18806
18807 errno = 0;
18808 val = strtol (pos, CONST_CAST (char **, &eptr), 10);
18809 if (errno || val <= 0 || (int) val != val)
18810 goto malformed;
18811 pos = eptr;
18812 oacc_default_dims[ix] = (int) val;
18813 }
18814 }
18815 if (*pos)
18816 {
18817 malformed:
18818 error_at (UNKNOWN_LOCATION,
18819 "-fopenacc-dim operand is malformed at '%s'", pos);
18820 }
18821 }
18822
18823 /* Allow the backend to validate the dimensions. */
18824 targetm.goacc.validate_dims (NULL_TREE, oacc_default_dims, -1);
18825 targetm.goacc.validate_dims (NULL_TREE, oacc_min_dims, -2);
18826 }
18827
18828 /* Validate and update the dimensions for offloaded FN. ATTRS is the
18829 raw attribute. DIMS is an array of dimensions, which is filled in.
18830 LEVEL is the partitioning level of a routine, or -1 for an offload
18831 region itself. USED is the mask of partitioned execution in the
18832 function. */
18833
18834 static void
18835 oacc_validate_dims (tree fn, tree attrs, int *dims, int level, unsigned used)
18836 {
18837 tree purpose[GOMP_DIM_MAX];
18838 unsigned ix;
18839 tree pos = TREE_VALUE (attrs);
18840 bool is_kernel = oacc_fn_attrib_kernels_p (attrs);
18841
18842 /* Make sure the attribute creator attached the dimension
18843 information. */
18844 gcc_assert (pos);
18845
18846 for (ix = 0; ix != GOMP_DIM_MAX; ix++)
18847 {
18848 purpose[ix] = TREE_PURPOSE (pos);
18849 tree val = TREE_VALUE (pos);
18850 dims[ix] = val ? TREE_INT_CST_LOW (val) : -1;
18851 pos = TREE_CHAIN (pos);
18852 }
18853
18854 bool changed = targetm.goacc.validate_dims (fn, dims, level);
18855
18856 /* Default anything left to 1 or a partitioned default. */
18857 for (ix = 0; ix != GOMP_DIM_MAX; ix++)
18858 if (dims[ix] < 0)
18859 {
18860 /* The OpenACC spec says 'If the [num_gangs] clause is not
18861 specified, an implementation-defined default will be used;
18862 the default may depend on the code within the construct.'
18863 (2.5.6). Thus an implementation is free to choose
18864 non-unity default for a parallel region that doesn't have
18865 any gang-partitioned loops. However, it appears that there
18866 is a sufficient body of user code that expects non-gang
18867 partitioned regions to not execute in gang-redundant mode.
18868 So we (a) don't warn about the non-portability and (b) pick
18869 the minimum permissible dimension size when there is no
18870 partitioned execution. Otherwise we pick the global
18871 default for the dimension, which the user can control. The
18872 same wording and logic applies to num_workers and
18873 vector_length, however the worker- or vector- single
18874 execution doesn't have the same impact as gang-redundant
18875 execution. (If the minimum gang-level partioning is not 1,
18876 the target is probably too confusing.) */
18877 dims[ix] = (used & GOMP_DIM_MASK (ix)
18878 ? oacc_default_dims[ix] : oacc_min_dims[ix]);
18879 changed = true;
18880 }
18881
18882 if (changed)
18883 {
18884 /* Replace the attribute with new values. */
18885 pos = NULL_TREE;
18886 for (ix = GOMP_DIM_MAX; ix--;)
18887 {
18888 pos = tree_cons (purpose[ix],
18889 build_int_cst (integer_type_node, dims[ix]),
18890 pos);
18891 if (is_kernel)
18892 TREE_PUBLIC (pos) = 1;
18893 }
18894 replace_oacc_fn_attrib (fn, pos);
18895 }
18896 }
18897
18898 /* Create an empty OpenACC loop structure at LOC. */
18899
18900 static oacc_loop *
18901 new_oacc_loop_raw (oacc_loop *parent, location_t loc)
18902 {
18903 oacc_loop *loop = XCNEW (oacc_loop);
18904
18905 loop->parent = parent;
18906 loop->child = loop->sibling = NULL;
18907
18908 if (parent)
18909 {
18910 loop->sibling = parent->child;
18911 parent->child = loop;
18912 }
18913
18914 loop->loc = loc;
18915 loop->marker = NULL;
18916 memset (loop->heads, 0, sizeof (loop->heads));
18917 memset (loop->tails, 0, sizeof (loop->tails));
18918 loop->routine = NULL_TREE;
18919
18920 loop->mask = loop->flags = loop->inner = 0;
18921 loop->ifns = 0;
18922 loop->chunk_size = 0;
18923 loop->head_end = NULL;
18924
18925 return loop;
18926 }
18927
18928 /* Create an outermost, dummy OpenACC loop for offloaded function
18929 DECL. */
18930
18931 static oacc_loop *
18932 new_oacc_loop_outer (tree decl)
18933 {
18934 return new_oacc_loop_raw (NULL, DECL_SOURCE_LOCATION (decl));
18935 }
18936
18937 /* Start a new OpenACC loop structure beginning at head marker HEAD.
18938 Link into PARENT loop. Return the new loop. */
18939
18940 static oacc_loop *
18941 new_oacc_loop (oacc_loop *parent, gcall *marker)
18942 {
18943 oacc_loop *loop = new_oacc_loop_raw (parent, gimple_location (marker));
18944
18945 loop->marker = marker;
18946
18947 /* TODO: This is where device_type flattening would occur for the loop
18948 flags. */
18949
18950 loop->flags = TREE_INT_CST_LOW (gimple_call_arg (marker, 3));
18951
18952 tree chunk_size = integer_zero_node;
18953 if (loop->flags & OLF_GANG_STATIC)
18954 chunk_size = gimple_call_arg (marker, 4);
18955 loop->chunk_size = chunk_size;
18956
18957 return loop;
18958 }
18959
18960 /* Create a dummy loop encompassing a call to a openACC routine.
18961 Extract the routine's partitioning requirements. */
18962
18963 static void
18964 new_oacc_loop_routine (oacc_loop *parent, gcall *call, tree decl, tree attrs)
18965 {
18966 oacc_loop *loop = new_oacc_loop_raw (parent, gimple_location (call));
18967 int level = oacc_fn_attrib_level (attrs);
18968
18969 gcc_assert (level >= 0);
18970
18971 loop->marker = call;
18972 loop->routine = decl;
18973 loop->mask = ((GOMP_DIM_MASK (GOMP_DIM_MAX) - 1)
18974 ^ (GOMP_DIM_MASK (level) - 1));
18975 }
18976
18977 /* Finish off the current OpenACC loop ending at tail marker TAIL.
18978 Return the parent loop. */
18979
18980 static oacc_loop *
18981 finish_oacc_loop (oacc_loop *loop)
18982 {
18983 /* If the loop has been collapsed, don't partition it. */
18984 if (!loop->ifns)
18985 loop->mask = loop->flags = 0;
18986 return loop->parent;
18987 }
18988
18989 /* Free all OpenACC loop structures within LOOP (inclusive). */
18990
18991 static void
18992 free_oacc_loop (oacc_loop *loop)
18993 {
18994 if (loop->sibling)
18995 free_oacc_loop (loop->sibling);
18996 if (loop->child)
18997 free_oacc_loop (loop->child);
18998
18999 free (loop);
19000 }
19001
19002 /* Dump out the OpenACC loop head or tail beginning at FROM. */
19003
19004 static void
19005 dump_oacc_loop_part (FILE *file, gcall *from, int depth,
19006 const char *title, int level)
19007 {
19008 enum ifn_unique_kind kind
19009 = (enum ifn_unique_kind) TREE_INT_CST_LOW (gimple_call_arg (from, 0));
19010
19011 fprintf (file, "%*s%s-%d:\n", depth * 2, "", title, level);
19012 for (gimple_stmt_iterator gsi = gsi_for_stmt (from);;)
19013 {
19014 gimple *stmt = gsi_stmt (gsi);
19015
19016 if (is_gimple_call (stmt)
19017 && gimple_call_internal_p (stmt)
19018 && gimple_call_internal_fn (stmt) == IFN_UNIQUE)
19019 {
19020 enum ifn_unique_kind k
19021 = ((enum ifn_unique_kind) TREE_INT_CST_LOW
19022 (gimple_call_arg (stmt, 0)));
19023
19024 if (k == kind && stmt != from)
19025 break;
19026 }
19027 print_gimple_stmt (file, stmt, depth * 2 + 2, 0);
19028
19029 gsi_next (&gsi);
19030 while (gsi_end_p (gsi))
19031 gsi = gsi_start_bb (single_succ (gsi_bb (gsi)));
19032 }
19033 }
19034
19035 /* Dump OpenACC loops LOOP, its siblings and its children. */
19036
19037 static void
19038 dump_oacc_loop (FILE *file, oacc_loop *loop, int depth)
19039 {
19040 int ix;
19041
19042 fprintf (file, "%*sLoop %x(%x) %s:%u\n", depth * 2, "",
19043 loop->flags, loop->mask,
19044 LOCATION_FILE (loop->loc), LOCATION_LINE (loop->loc));
19045
19046 if (loop->marker)
19047 print_gimple_stmt (file, loop->marker, depth * 2, 0);
19048
19049 if (loop->routine)
19050 fprintf (file, "%*sRoutine %s:%u:%s\n",
19051 depth * 2, "", DECL_SOURCE_FILE (loop->routine),
19052 DECL_SOURCE_LINE (loop->routine),
19053 IDENTIFIER_POINTER (DECL_NAME (loop->routine)));
19054
19055 for (ix = GOMP_DIM_GANG; ix != GOMP_DIM_MAX; ix++)
19056 if (loop->heads[ix])
19057 dump_oacc_loop_part (file, loop->heads[ix], depth, "Head", ix);
19058 for (ix = GOMP_DIM_MAX; ix--;)
19059 if (loop->tails[ix])
19060 dump_oacc_loop_part (file, loop->tails[ix], depth, "Tail", ix);
19061
19062 if (loop->child)
19063 dump_oacc_loop (file, loop->child, depth + 1);
19064 if (loop->sibling)
19065 dump_oacc_loop (file, loop->sibling, depth);
19066 }
19067
19068 void debug_oacc_loop (oacc_loop *);
19069
19070 /* Dump loops to stderr. */
19071
19072 DEBUG_FUNCTION void
19073 debug_oacc_loop (oacc_loop *loop)
19074 {
19075 dump_oacc_loop (stderr, loop, 0);
19076 }
19077
19078 /* DFS walk of basic blocks BB onwards, creating OpenACC loop
19079 structures as we go. By construction these loops are properly
19080 nested. */
19081
19082 static void
19083 oacc_loop_discover_walk (oacc_loop *loop, basic_block bb)
19084 {
19085 int marker = 0;
19086 int remaining = 0;
19087
19088 if (bb->flags & BB_VISITED)
19089 return;
19090
19091 follow:
19092 bb->flags |= BB_VISITED;
19093
19094 /* Scan for loop markers. */
19095 for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);
19096 gsi_next (&gsi))
19097 {
19098 gimple *stmt = gsi_stmt (gsi);
19099
19100 if (!is_gimple_call (stmt))
19101 continue;
19102
19103 gcall *call = as_a <gcall *> (stmt);
19104
19105 /* If this is a routine, make a dummy loop for it. */
19106 if (tree decl = gimple_call_fndecl (call))
19107 if (tree attrs = get_oacc_fn_attrib (decl))
19108 {
19109 gcc_assert (!marker);
19110 new_oacc_loop_routine (loop, call, decl, attrs);
19111 }
19112
19113 if (!gimple_call_internal_p (call))
19114 continue;
19115
19116 switch (gimple_call_internal_fn (call))
19117 {
19118 default:
19119 break;
19120
19121 case IFN_GOACC_LOOP:
19122 /* Count the goacc loop abstraction fns, to determine if the
19123 loop was collapsed already. */
19124 loop->ifns++;
19125 break;
19126
19127 case IFN_UNIQUE:
19128 enum ifn_unique_kind kind
19129 = (enum ifn_unique_kind) (TREE_INT_CST_LOW
19130 (gimple_call_arg (call, 0)));
19131 if (kind == IFN_UNIQUE_OACC_HEAD_MARK
19132 || kind == IFN_UNIQUE_OACC_TAIL_MARK)
19133 {
19134 if (gimple_call_num_args (call) == 2)
19135 {
19136 gcc_assert (marker && !remaining);
19137 marker = 0;
19138 if (kind == IFN_UNIQUE_OACC_TAIL_MARK)
19139 loop = finish_oacc_loop (loop);
19140 else
19141 loop->head_end = call;
19142 }
19143 else
19144 {
19145 int count = TREE_INT_CST_LOW (gimple_call_arg (call, 2));
19146
19147 if (!marker)
19148 {
19149 if (kind == IFN_UNIQUE_OACC_HEAD_MARK)
19150 loop = new_oacc_loop (loop, call);
19151 remaining = count;
19152 }
19153 gcc_assert (count == remaining);
19154 if (remaining)
19155 {
19156 remaining--;
19157 if (kind == IFN_UNIQUE_OACC_HEAD_MARK)
19158 loop->heads[marker] = call;
19159 else
19160 loop->tails[remaining] = call;
19161 }
19162 marker++;
19163 }
19164 }
19165 }
19166 }
19167 if (remaining || marker)
19168 {
19169 bb = single_succ (bb);
19170 gcc_assert (single_pred_p (bb) && !(bb->flags & BB_VISITED));
19171 goto follow;
19172 }
19173
19174 /* Walk successor blocks. */
19175 edge e;
19176 edge_iterator ei;
19177
19178 FOR_EACH_EDGE (e, ei, bb->succs)
19179 oacc_loop_discover_walk (loop, e->dest);
19180 }
19181
19182 /* LOOP is the first sibling. Reverse the order in place and return
19183 the new first sibling. Recurse to child loops. */
19184
19185 static oacc_loop *
19186 oacc_loop_sibling_nreverse (oacc_loop *loop)
19187 {
19188 oacc_loop *last = NULL;
19189 do
19190 {
19191 if (loop->child)
19192 loop->child = oacc_loop_sibling_nreverse (loop->child);
19193
19194 oacc_loop *next = loop->sibling;
19195 loop->sibling = last;
19196 last = loop;
19197 loop = next;
19198 }
19199 while (loop);
19200
19201 return last;
19202 }
19203
19204 /* Discover the OpenACC loops marked up by HEAD and TAIL markers for
19205 the current function. */
19206
19207 static oacc_loop *
19208 oacc_loop_discovery ()
19209 {
19210 basic_block bb;
19211
19212 oacc_loop *top = new_oacc_loop_outer (current_function_decl);
19213 oacc_loop_discover_walk (top, ENTRY_BLOCK_PTR_FOR_FN (cfun));
19214
19215 /* The siblings were constructed in reverse order, reverse them so
19216 that diagnostics come out in an unsurprising order. */
19217 top = oacc_loop_sibling_nreverse (top);
19218
19219 /* Reset the visited flags. */
19220 FOR_ALL_BB_FN (bb, cfun)
19221 bb->flags &= ~BB_VISITED;
19222
19223 return top;
19224 }
19225
19226 /* Transform the abstract internal function markers starting at FROM
19227 to be for partitioning level LEVEL. Stop when we meet another HEAD
19228 or TAIL marker. */
19229
19230 static void
19231 oacc_loop_xform_head_tail (gcall *from, int level)
19232 {
19233 enum ifn_unique_kind kind
19234 = (enum ifn_unique_kind) TREE_INT_CST_LOW (gimple_call_arg (from, 0));
19235 tree replacement = build_int_cst (unsigned_type_node, level);
19236
19237 for (gimple_stmt_iterator gsi = gsi_for_stmt (from);;)
19238 {
19239 gimple *stmt = gsi_stmt (gsi);
19240
19241 if (is_gimple_call (stmt)
19242 && gimple_call_internal_p (stmt)
19243 && gimple_call_internal_fn (stmt) == IFN_UNIQUE)
19244 {
19245 enum ifn_unique_kind k
19246 = ((enum ifn_unique_kind)
19247 TREE_INT_CST_LOW (gimple_call_arg (stmt, 0)));
19248
19249 if (k == IFN_UNIQUE_OACC_FORK || k == IFN_UNIQUE_OACC_JOIN)
19250 *gimple_call_arg_ptr (stmt, 2) = replacement;
19251 else if (k == kind && stmt != from)
19252 break;
19253 }
19254 else if (is_gimple_call (stmt)
19255 && gimple_call_internal_p (stmt)
19256 && gimple_call_internal_fn (stmt) == IFN_GOACC_REDUCTION)
19257 *gimple_call_arg_ptr (stmt, 3) = replacement;
19258
19259 gsi_next (&gsi);
19260 while (gsi_end_p (gsi))
19261 gsi = gsi_start_bb (single_succ (gsi_bb (gsi)));
19262 }
19263 }
19264
19265 /* Transform the IFN_GOACC_LOOP internal functions by providing the
19266 determined partitioning mask and chunking argument. END_MARKER
19267 points at the end IFN_HEAD_TAIL call intgroducing the loop. IFNS
19268 is the number of IFN_GOACC_LOOP calls for the loop. MASK_ARG is
19269 the replacement partitioning mask and CHUNK_ARG is the replacement
19270 chunking arg. */
19271
19272 static void
19273 oacc_loop_xform_loop (gcall *end_marker, unsigned ifns,
19274 tree mask_arg, tree chunk_arg)
19275 {
19276 gimple_stmt_iterator gsi = gsi_for_stmt (end_marker);
19277
19278 gcc_checking_assert (ifns);
19279 for (;;)
19280 {
19281 for (; !gsi_end_p (gsi); gsi_next (&gsi))
19282 {
19283 gimple *stmt = gsi_stmt (gsi);
19284
19285 if (!is_gimple_call (stmt))
19286 continue;
19287
19288 gcall *call = as_a <gcall *> (stmt);
19289
19290 if (!gimple_call_internal_p (call))
19291 continue;
19292
19293 if (gimple_call_internal_fn (call) != IFN_GOACC_LOOP)
19294 continue;
19295
19296 *gimple_call_arg_ptr (call, 5) = mask_arg;
19297 *gimple_call_arg_ptr (call, 4) = chunk_arg;
19298 ifns--;
19299 if (!ifns)
19300 return;
19301 }
19302
19303 /* The LOOP_BOUND ifn could be in the single successor
19304 block. */
19305 basic_block bb = single_succ (gsi_bb (gsi));
19306 gsi = gsi_start_bb (bb);
19307 }
19308 }
19309
19310 /* Process the discovered OpenACC loops, setting the correct
19311 partitioning level etc. */
19312
19313 static void
19314 oacc_loop_process (oacc_loop *loop)
19315 {
19316 if (loop->child)
19317 oacc_loop_process (loop->child);
19318
19319 if (loop->mask && !loop->routine)
19320 {
19321 int ix;
19322 unsigned mask = loop->mask;
19323 unsigned dim = GOMP_DIM_GANG;
19324 tree mask_arg = build_int_cst (unsigned_type_node, mask);
19325 tree chunk_arg = loop->chunk_size;
19326
19327 oacc_loop_xform_loop (loop->head_end, loop->ifns, mask_arg, chunk_arg);
19328
19329 for (ix = 0; ix != GOMP_DIM_MAX && mask; ix++)
19330 {
19331 while (!(GOMP_DIM_MASK (dim) & mask))
19332 dim++;
19333
19334 oacc_loop_xform_head_tail (loop->heads[ix], dim);
19335 oacc_loop_xform_head_tail (loop->tails[ix], dim);
19336
19337 mask ^= GOMP_DIM_MASK (dim);
19338 }
19339 }
19340
19341 if (loop->sibling)
19342 oacc_loop_process (loop->sibling);
19343 }
19344
19345 /* Walk the OpenACC loop heirarchy checking and assigning the
19346 programmer-specified partitionings. OUTER_MASK is the partitioning
19347 this loop is contained within. Return mask of partitioning
19348 encountered. If any auto loops are discovered, set GOMP_DIM_MAX
19349 bit. */
19350
19351 static unsigned
19352 oacc_loop_fixed_partitions (oacc_loop *loop, unsigned outer_mask)
19353 {
19354 unsigned this_mask = loop->mask;
19355 unsigned mask_all = 0;
19356 bool noisy = true;
19357
19358 #ifdef ACCEL_COMPILER
19359 /* When device_type is supported, we want the device compiler to be
19360 noisy, if the loop parameters are device_type-specific. */
19361 noisy = false;
19362 #endif
19363
19364 if (!loop->routine)
19365 {
19366 bool auto_par = (loop->flags & OLF_AUTO) != 0;
19367 bool seq_par = (loop->flags & OLF_SEQ) != 0;
19368
19369 this_mask = ((loop->flags >> OLF_DIM_BASE)
19370 & (GOMP_DIM_MASK (GOMP_DIM_MAX) - 1));
19371
19372 if ((this_mask != 0) + auto_par + seq_par > 1)
19373 {
19374 if (noisy)
19375 error_at (loop->loc,
19376 seq_par
19377 ? "%<seq%> overrides other OpenACC loop specifiers"
19378 : "%<auto%> conflicts with other OpenACC loop specifiers");
19379 auto_par = false;
19380 loop->flags &= ~OLF_AUTO;
19381 if (seq_par)
19382 {
19383 loop->flags &=
19384 ~((GOMP_DIM_MASK (GOMP_DIM_MAX) - 1) << OLF_DIM_BASE);
19385 this_mask = 0;
19386 }
19387 }
19388 if (auto_par && (loop->flags & OLF_INDEPENDENT))
19389 mask_all |= GOMP_DIM_MASK (GOMP_DIM_MAX);
19390 }
19391
19392 if (this_mask & outer_mask)
19393 {
19394 const oacc_loop *outer;
19395 for (outer = loop->parent; outer; outer = outer->parent)
19396 if (outer->mask & this_mask)
19397 break;
19398
19399 if (noisy)
19400 {
19401 if (outer)
19402 {
19403 error_at (loop->loc,
19404 "%s uses same OpenACC parallelism as containing loop",
19405 loop->routine ? "routine call" : "inner loop");
19406 inform (outer->loc, "containing loop here");
19407 }
19408 else
19409 error_at (loop->loc,
19410 "%s uses OpenACC parallelism disallowed by containing routine",
19411 loop->routine ? "routine call" : "loop");
19412
19413 if (loop->routine)
19414 inform (DECL_SOURCE_LOCATION (loop->routine),
19415 "routine %qD declared here", loop->routine);
19416 }
19417 this_mask &= ~outer_mask;
19418 }
19419 else
19420 {
19421 unsigned outermost = this_mask & -this_mask;
19422
19423 if (outermost && outermost <= outer_mask)
19424 {
19425 if (noisy)
19426 {
19427 error_at (loop->loc,
19428 "incorrectly nested OpenACC loop parallelism");
19429
19430 const oacc_loop *outer;
19431 for (outer = loop->parent;
19432 outer->flags && outer->flags < outermost;
19433 outer = outer->parent)
19434 continue;
19435 inform (outer->loc, "containing loop here");
19436 }
19437
19438 this_mask &= ~outermost;
19439 }
19440 }
19441
19442 loop->mask = this_mask;
19443 mask_all |= this_mask;
19444
19445 if (loop->child)
19446 {
19447 loop->inner = oacc_loop_fixed_partitions (loop->child,
19448 outer_mask | this_mask);
19449 mask_all |= loop->inner;
19450 }
19451
19452 if (loop->sibling)
19453 mask_all |= oacc_loop_fixed_partitions (loop->sibling, outer_mask);
19454
19455 return mask_all;
19456 }
19457
19458 /* Walk the OpenACC loop heirarchy to assign auto-partitioned loops.
19459 OUTER_MASK is the partitioning this loop is contained within.
19460 Return the cumulative partitioning used by this loop, siblings and
19461 children. */
19462
19463 static unsigned
19464 oacc_loop_auto_partitions (oacc_loop *loop, unsigned outer_mask)
19465 {
19466 bool assign = (loop->flags & OLF_AUTO) && (loop->flags & OLF_INDEPENDENT);
19467 bool noisy = true;
19468
19469 #ifdef ACCEL_COMPILER
19470 /* When device_type is supported, we want the device compiler to be
19471 noisy, if the loop parameters are device_type-specific. */
19472 noisy = false;
19473 #endif
19474
19475 if (assign && outer_mask < GOMP_DIM_MASK (GOMP_DIM_MAX - 1))
19476 {
19477 /* Allocate the outermost loop at the outermost available
19478 level. */
19479 unsigned this_mask = outer_mask + 1;
19480
19481 if (!(this_mask & loop->inner))
19482 loop->mask = this_mask;
19483 }
19484
19485 if (loop->child)
19486 {
19487 unsigned child_mask = outer_mask | loop->mask;
19488
19489 if (loop->mask || assign)
19490 child_mask |= GOMP_DIM_MASK (GOMP_DIM_MAX);
19491
19492 loop->inner = oacc_loop_auto_partitions (loop->child, child_mask);
19493 }
19494
19495 if (assign && !loop->mask)
19496 {
19497 /* Allocate the loop at the innermost available level. */
19498 unsigned this_mask = 0;
19499
19500 /* Determine the outermost partitioning used within this loop. */
19501 this_mask = loop->inner | GOMP_DIM_MASK (GOMP_DIM_MAX);
19502 this_mask = (this_mask & -this_mask);
19503
19504 /* Pick the partitioning just inside that one. */
19505 this_mask >>= 1;
19506
19507 /* And avoid picking one use by an outer loop. */
19508 this_mask &= ~outer_mask;
19509
19510 if (!this_mask && noisy)
19511 warning_at (loop->loc, 0,
19512 "insufficient partitioning available to parallelize loop");
19513
19514 loop->mask = this_mask;
19515 }
19516
19517 if (assign && dump_file)
19518 fprintf (dump_file, "Auto loop %s:%d assigned %d\n",
19519 LOCATION_FILE (loop->loc), LOCATION_LINE (loop->loc),
19520 loop->mask);
19521
19522 unsigned inner_mask = 0;
19523
19524 if (loop->sibling)
19525 inner_mask |= oacc_loop_auto_partitions (loop->sibling, outer_mask);
19526
19527 inner_mask |= loop->inner | loop->mask;
19528
19529 return inner_mask;
19530 }
19531
19532 /* Walk the OpenACC loop heirarchy to check and assign partitioning
19533 axes. Return mask of partitioning. */
19534
19535 static unsigned
19536 oacc_loop_partition (oacc_loop *loop, unsigned outer_mask)
19537 {
19538 unsigned mask_all = oacc_loop_fixed_partitions (loop, outer_mask);
19539
19540 if (mask_all & GOMP_DIM_MASK (GOMP_DIM_MAX))
19541 {
19542 mask_all ^= GOMP_DIM_MASK (GOMP_DIM_MAX);
19543 mask_all |= oacc_loop_auto_partitions (loop, outer_mask);
19544 }
19545 return mask_all;
19546 }
19547
19548 /* Default fork/join early expander. Delete the function calls if
19549 there is no RTL expander. */
19550
19551 bool
19552 default_goacc_fork_join (gcall *ARG_UNUSED (call),
19553 const int *ARG_UNUSED (dims), bool is_fork)
19554 {
19555 if (is_fork)
19556 return targetm.have_oacc_fork ();
19557 else
19558 return targetm.have_oacc_join ();
19559 }
19560
19561 /* Default goacc.reduction early expander.
19562
19563 LHS-opt = IFN_REDUCTION (KIND, RES_PTR, VAR, LEVEL, OP, OFFSET)
19564 If RES_PTR is not integer-zerop:
19565 SETUP - emit 'LHS = *RES_PTR', LHS = NULL
19566 TEARDOWN - emit '*RES_PTR = VAR'
19567 If LHS is not NULL
19568 emit 'LHS = VAR' */
19569
19570 void
19571 default_goacc_reduction (gcall *call)
19572 {
19573 unsigned code = (unsigned)TREE_INT_CST_LOW (gimple_call_arg (call, 0));
19574 gimple_stmt_iterator gsi = gsi_for_stmt (call);
19575 tree lhs = gimple_call_lhs (call);
19576 tree var = gimple_call_arg (call, 2);
19577 gimple_seq seq = NULL;
19578
19579 if (code == IFN_GOACC_REDUCTION_SETUP
19580 || code == IFN_GOACC_REDUCTION_TEARDOWN)
19581 {
19582 /* Setup and Teardown need to copy from/to the receiver object,
19583 if there is one. */
19584 tree ref_to_res = gimple_call_arg (call, 1);
19585
19586 if (!integer_zerop (ref_to_res))
19587 {
19588 tree dst = build_simple_mem_ref (ref_to_res);
19589 tree src = var;
19590
19591 if (code == IFN_GOACC_REDUCTION_SETUP)
19592 {
19593 src = dst;
19594 dst = lhs;
19595 lhs = NULL;
19596 }
19597 gimple_seq_add_stmt (&seq, gimple_build_assign (dst, src));
19598 }
19599 }
19600
19601 /* Copy VAR to LHS, if there is an LHS. */
19602 if (lhs)
19603 gimple_seq_add_stmt (&seq, gimple_build_assign (lhs, var));
19604
19605 gsi_replace_with_seq (&gsi, seq, true);
19606 }
19607
19608 /* Main entry point for oacc transformations which run on the device
19609 compiler after LTO, so we know what the target device is at this
19610 point (including the host fallback). */
19611
19612 static unsigned int
19613 execute_oacc_device_lower ()
19614 {
19615 tree attrs = get_oacc_fn_attrib (current_function_decl);
19616
19617 if (!attrs)
19618 /* Not an offloaded function. */
19619 return 0;
19620
19621 /* Parse the default dim argument exactly once. */
19622 if ((const void *)flag_openacc_dims != &flag_openacc_dims)
19623 {
19624 oacc_parse_default_dims (flag_openacc_dims);
19625 flag_openacc_dims = (char *)&flag_openacc_dims;
19626 }
19627
19628 /* Discover, partition and process the loops. */
19629 oacc_loop *loops = oacc_loop_discovery ();
19630 int fn_level = oacc_fn_attrib_level (attrs);
19631
19632 if (dump_file)
19633 fprintf (dump_file, oacc_fn_attrib_kernels_p (attrs)
19634 ? "Function is kernels offload\n"
19635 : fn_level < 0 ? "Function is parallel offload\n"
19636 : "Function is routine level %d\n", fn_level);
19637
19638 unsigned outer_mask = fn_level >= 0 ? GOMP_DIM_MASK (fn_level) - 1 : 0;
19639 unsigned used_mask = oacc_loop_partition (loops, outer_mask);
19640 int dims[GOMP_DIM_MAX];
19641
19642 oacc_validate_dims (current_function_decl, attrs, dims, fn_level, used_mask);
19643
19644 if (dump_file)
19645 {
19646 const char *comma = "Compute dimensions [";
19647 for (int ix = 0; ix != GOMP_DIM_MAX; ix++, comma = ", ")
19648 fprintf (dump_file, "%s%d", comma, dims[ix]);
19649 fprintf (dump_file, "]\n");
19650 }
19651
19652 oacc_loop_process (loops);
19653 if (dump_file)
19654 {
19655 fprintf (dump_file, "OpenACC loops\n");
19656 dump_oacc_loop (dump_file, loops, 0);
19657 fprintf (dump_file, "\n");
19658 }
19659
19660 /* Offloaded targets may introduce new basic blocks, which require
19661 dominance information to update SSA. */
19662 calculate_dominance_info (CDI_DOMINATORS);
19663
19664 /* Now lower internal loop functions to target-specific code
19665 sequences. */
19666 basic_block bb;
19667 FOR_ALL_BB_FN (bb, cfun)
19668 for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);)
19669 {
19670 gimple *stmt = gsi_stmt (gsi);
19671 if (!is_gimple_call (stmt))
19672 {
19673 gsi_next (&gsi);
19674 continue;
19675 }
19676
19677 gcall *call = as_a <gcall *> (stmt);
19678 if (!gimple_call_internal_p (call))
19679 {
19680 gsi_next (&gsi);
19681 continue;
19682 }
19683
19684 /* Rewind to allow rescan. */
19685 gsi_prev (&gsi);
19686 bool rescan = false, remove = false;
19687 enum internal_fn ifn_code = gimple_call_internal_fn (call);
19688
19689 switch (ifn_code)
19690 {
19691 default: break;
19692
19693 case IFN_GOACC_LOOP:
19694 oacc_xform_loop (call);
19695 rescan = true;
19696 break;
19697
19698 case IFN_GOACC_REDUCTION:
19699 /* Mark the function for SSA renaming. */
19700 mark_virtual_operands_for_renaming (cfun);
19701
19702 /* If the level is -1, this ended up being an unused
19703 axis. Handle as a default. */
19704 if (integer_minus_onep (gimple_call_arg (call, 3)))
19705 default_goacc_reduction (call);
19706 else
19707 targetm.goacc.reduction (call);
19708 rescan = true;
19709 break;
19710
19711 case IFN_UNIQUE:
19712 {
19713 enum ifn_unique_kind kind
19714 = ((enum ifn_unique_kind)
19715 TREE_INT_CST_LOW (gimple_call_arg (call, 0)));
19716
19717 switch (kind)
19718 {
19719 default:
19720 gcc_unreachable ();
19721
19722 case IFN_UNIQUE_OACC_FORK:
19723 case IFN_UNIQUE_OACC_JOIN:
19724 if (integer_minus_onep (gimple_call_arg (call, 2)))
19725 remove = true;
19726 else if (!targetm.goacc.fork_join
19727 (call, dims, kind == IFN_UNIQUE_OACC_FORK))
19728 remove = true;
19729 break;
19730
19731 case IFN_UNIQUE_OACC_HEAD_MARK:
19732 case IFN_UNIQUE_OACC_TAIL_MARK:
19733 remove = true;
19734 break;
19735 }
19736 break;
19737 }
19738 }
19739
19740 if (gsi_end_p (gsi))
19741 /* We rewound past the beginning of the BB. */
19742 gsi = gsi_start_bb (bb);
19743 else
19744 /* Undo the rewind. */
19745 gsi_next (&gsi);
19746
19747 if (remove)
19748 {
19749 if (gimple_vdef (call))
19750 replace_uses_by (gimple_vdef (call), gimple_vuse (call));
19751 if (gimple_call_lhs (call))
19752 {
19753 /* Propagate the data dependency var. */
19754 gimple *ass = gimple_build_assign (gimple_call_lhs (call),
19755 gimple_call_arg (call, 1));
19756 gsi_replace (&gsi, ass, false);
19757 }
19758 else
19759 gsi_remove (&gsi, true);
19760 }
19761 else if (!rescan)
19762 /* If not rescanning, advance over the call. */
19763 gsi_next (&gsi);
19764 }
19765
19766 free_oacc_loop (loops);
19767
19768 return 0;
19769 }
19770
19771 /* Default launch dimension validator. Force everything to 1. A
19772 backend that wants to provide larger dimensions must override this
19773 hook. */
19774
19775 bool
19776 default_goacc_validate_dims (tree ARG_UNUSED (decl), int *dims,
19777 int ARG_UNUSED (fn_level))
19778 {
19779 bool changed = false;
19780
19781 for (unsigned ix = 0; ix != GOMP_DIM_MAX; ix++)
19782 {
19783 if (dims[ix] != 1)
19784 {
19785 dims[ix] = 1;
19786 changed = true;
19787 }
19788 }
19789
19790 return changed;
19791 }
19792
19793 /* Default dimension bound is unknown on accelerator and 1 on host. */
19794
19795 int
19796 default_goacc_dim_limit (int ARG_UNUSED (axis))
19797 {
19798 #ifdef ACCEL_COMPILER
19799 return 0;
19800 #else
19801 return 1;
19802 #endif
19803 }
19804
19805 namespace {
19806
19807 const pass_data pass_data_oacc_device_lower =
19808 {
19809 GIMPLE_PASS, /* type */
19810 "oaccdevlow", /* name */
19811 OPTGROUP_NONE, /* optinfo_flags */
19812 TV_NONE, /* tv_id */
19813 PROP_cfg, /* properties_required */
19814 0 /* Possibly PROP_gimple_eomp. */, /* properties_provided */
19815 0, /* properties_destroyed */
19816 0, /* todo_flags_start */
19817 TODO_update_ssa | TODO_cleanup_cfg, /* todo_flags_finish */
19818 };
19819
19820 class pass_oacc_device_lower : public gimple_opt_pass
19821 {
19822 public:
19823 pass_oacc_device_lower (gcc::context *ctxt)
19824 : gimple_opt_pass (pass_data_oacc_device_lower, ctxt)
19825 {}
19826
19827 /* opt_pass methods: */
19828 virtual unsigned int execute (function *)
19829 {
19830 bool gate = flag_openacc != 0;
19831
19832 if (!gate)
19833 return 0;
19834
19835 return execute_oacc_device_lower ();
19836 }
19837
19838 }; // class pass_oacc_device_lower
19839
19840 } // anon namespace
19841
19842 gimple_opt_pass *
19843 make_pass_oacc_device_lower (gcc::context *ctxt)
19844 {
19845 return new pass_oacc_device_lower (ctxt);
19846 }
19847
19848 /* "omp declare target link" handling pass. */
19849
19850 namespace {
19851
19852 const pass_data pass_data_omp_target_link =
19853 {
19854 GIMPLE_PASS, /* type */
19855 "omptargetlink", /* name */
19856 OPTGROUP_NONE, /* optinfo_flags */
19857 TV_NONE, /* tv_id */
19858 PROP_ssa, /* properties_required */
19859 0, /* properties_provided */
19860 0, /* properties_destroyed */
19861 0, /* todo_flags_start */
19862 TODO_update_ssa, /* todo_flags_finish */
19863 };
19864
19865 class pass_omp_target_link : public gimple_opt_pass
19866 {
19867 public:
19868 pass_omp_target_link (gcc::context *ctxt)
19869 : gimple_opt_pass (pass_data_omp_target_link, ctxt)
19870 {}
19871
19872 /* opt_pass methods: */
19873 virtual bool gate (function *fun)
19874 {
19875 #ifdef ACCEL_COMPILER
19876 tree attrs = DECL_ATTRIBUTES (fun->decl);
19877 return lookup_attribute ("omp declare target", attrs)
19878 || lookup_attribute ("omp target entrypoint", attrs);
19879 #else
19880 (void) fun;
19881 return false;
19882 #endif
19883 }
19884
19885 virtual unsigned execute (function *);
19886 };
19887
19888 /* Callback for walk_gimple_stmt used to scan for link var operands. */
19889
19890 static tree
19891 find_link_var_op (tree *tp, int *walk_subtrees, void *)
19892 {
19893 tree t = *tp;
19894
19895 if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t)
19896 && lookup_attribute ("omp declare target link", DECL_ATTRIBUTES (t)))
19897 {
19898 *walk_subtrees = 0;
19899 return t;
19900 }
19901
19902 return NULL_TREE;
19903 }
19904
19905 unsigned
19906 pass_omp_target_link::execute (function *fun)
19907 {
19908 basic_block bb;
19909 FOR_EACH_BB_FN (bb, fun)
19910 {
19911 gimple_stmt_iterator gsi;
19912 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
19913 if (walk_gimple_stmt (&gsi, NULL, find_link_var_op, NULL))
19914 gimple_regimplify_operands (gsi_stmt (gsi), &gsi);
19915 }
19916
19917 return 0;
19918 }
19919
19920 } // anon namespace
19921
19922 gimple_opt_pass *
19923 make_pass_omp_target_link (gcc::context *ctxt)
19924 {
19925 return new pass_omp_target_link (ctxt);
19926 }
19927
19928 #include "gt-omp-low.h"