]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/omp-low.c
Daily bump.
[thirdparty/gcc.git] / gcc / omp-low.c
CommitLineData
ca4c3545 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
1e8e9920 5 Contributed by Diego Novillo <dnovillo@redhat.com>
6
f1717362 7 Copyright (C) 2005-2016 Free Software Foundation, Inc.
1e8e9920 8
9This file is part of GCC.
10
11GCC is free software; you can redistribute it and/or modify it under
12the terms of the GNU General Public License as published by the Free
8c4c00c1 13Software Foundation; either version 3, or (at your option) any later
1e8e9920 14version.
15
16GCC is distributed in the hope that it will be useful, but WITHOUT ANY
17WARRANTY; without even the implied warranty of MERCHANTABILITY or
18FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19for more details.
20
21You should have received a copy of the GNU General Public License
8c4c00c1 22along with GCC; see the file COPYING3. If not see
23<http://www.gnu.org/licenses/>. */
1e8e9920 24
25#include "config.h"
26#include "system.h"
27#include "coretypes.h"
9ef16211 28#include "backend.h"
7c29e30e 29#include "target.h"
30#include "rtl.h"
1e8e9920 31#include "tree.h"
9ef16211 32#include "gimple.h"
7c29e30e 33#include "cfghooks.h"
34#include "alloc-pool.h"
35#include "tree-pass.h"
9ef16211 36#include "ssa.h"
7c29e30e 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"
9ef16211 43#include "alias.h"
b20a8bb4 44#include "fold-const.h"
9ed99284 45#include "stor-layout.h"
94ea8568 46#include "cfganal.h"
bc61cadb 47#include "internal-fn.h"
48#include "gimple-fold.h"
a8783bee 49#include "gimplify.h"
dcf1a1ec 50#include "gimple-iterator.h"
e795d6e1 51#include "gimplify-me.h"
dcf1a1ec 52#include "gimple-walk.h"
75a70cf9 53#include "tree-iterator.h"
1e8e9920 54#include "tree-inline.h"
55#include "langhooks.h"
073c1fd5 56#include "tree-cfg.h"
073c1fd5 57#include "tree-into-ssa.h"
d53441c8 58#include "flags.h"
d53441c8 59#include "dojump.h"
60#include "explow.h"
61#include "calls.h"
d53441c8 62#include "varasm.h"
63#include "stmt.h"
9ed99284 64#include "expr.h"
073c1fd5 65#include "tree-dfa.h"
69ee5dbb 66#include "tree-ssa.h"
1e8e9920 67#include "except.h"
e3022db7 68#include "splay-tree.h"
cb7f680b 69#include "cfgloop.h"
dccabdd1 70#include "common/common-target.h"
7740abd8 71#include "omp-low.h"
424a4a92 72#include "gimple-low.h"
73#include "tree-cfgcleanup.h"
2cc80ac3 74#include "symbol-summary.h"
d09768a4 75#include "ipa-prop.h"
e797f49f 76#include "tree-nested.h"
d09768a4 77#include "tree-eh.h"
40750995 78#include "cilk.h"
b0c5e347 79#include "context.h"
dccabdd1 80#include "lto-section-names.h"
ca4c3545 81#include "gomp-constants.h"
cbba99a0 82#include "gimple-pretty-print.h"
56686608 83#include "symbol-summary.h"
84#include "hsa.h"
85#include "params.h"
1e8e9920 86
ca4c3545 87/* Lowering of OMP parallel and workshare constructs proceeds in two
1e8e9920 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
334ec2d8 91 re-gimplifying things when variables have been replaced with complex
1e8e9920 92 expressions.
93
d134bccc 94 Final code generation is done by pass_expand_omp. The flowgraph is
ca4c3545 95 scanned for regions which are then moved to a new
96 function, to be invoked by the thread library, or offloaded. */
1e8e9920 97
ca4c3545 98/* OMP region information. Every parallel and workshare
7740abd8 99 directive is enclosed between two markers, the OMP_* directive
43895be5 100 and a corresponding GIMPLE_OMP_RETURN statement. */
7740abd8 101
102struct 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
43895be5 116 /* Block containing the GIMPLE_OMP_RETURN as its last stmt. */
7740abd8 117 basic_block exit;
118
43895be5 119 /* Block containing the GIMPLE_OMP_CONTINUE as its last stmt. */
7740abd8 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
43895be5 130 /* Schedule kind, only used for GIMPLE_OMP_FOR type regions. */
7740abd8 131 enum omp_clause_schedule_kind sched_kind;
132
9561765e 133 /* Schedule modifiers. */
134 unsigned char sched_modifiers;
135
7740abd8 136 /* True if this is a combined parallel+workshare region. */
137 bool is_combined_parallel;
43895be5 138
139 /* The ordered stmt if type is GIMPLE_OMP_ORDERED and it has
140 a depend clause. */
141 gomp_ordered *ord_stmt;
7740abd8 142};
143
1e8e9920 144/* Context structure. Used to store information about each parallel
145 directive in the code. */
146
6dc50383 147struct omp_context
1e8e9920 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;
42acab1c 157 gimple *stmt;
1e8e9920 158
48e1416a 159 /* Map variables to fields in a structure that allows communication
1e8e9920 160 between sending and receiving threads. */
161 splay_tree field_map;
162 tree record_type;
163 tree sender_decl;
164 tree receiver_decl;
165
fd6481cf 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
1e8e9920 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
bc7bff74 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
1e8e9920 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
1e8e9920 191 /* True if this parallel directive is nested within another. */
192 bool is_nested;
bc7bff74 193
194 /* True if this construct can be cancelled. */
195 bool cancellable;
6dc50383 196};
1e8e9920 197
ca4c3545 198/* A structure holding the elements of:
199 for (V = N1; V cond N2; V += STEP) [...] */
1e8e9920 200
fd6481cf 201struct omp_for_data_loop
202{
203 tree v, n1, n2, step;
204 enum tree_code cond_code;
205};
206
773c5ba7 207/* A structure describing the main elements of a parallel loop. */
1e8e9920 208
773c5ba7 209struct omp_for_data
1e8e9920 210{
fd6481cf 211 struct omp_for_data_loop loop;
75a70cf9 212 tree chunk_size;
1a91d914 213 gomp_for *for_stmt;
fd6481cf 214 tree pre, iter_type;
215 int collapse;
43895be5 216 int ordered;
217 bool have_nowait, have_ordered, simd_schedule;
9561765e 218 unsigned char sched_modifiers;
1e8e9920 219 enum omp_clause_schedule_kind sched_kind;
fd6481cf 220 struct omp_for_data_loop *loops;
1e8e9920 221};
222
cbba99a0 223/* Describe the OpenACC looping structure of a function. The entire
224 function is held in a 'NULL' loop. */
225
226struct 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. */
584fba4b 244 unsigned flags; /* Partitioning flags. */
245 unsigned ifns; /* Contained loop abstraction functions. */
246 tree chunk_size; /* Chunk size. */
cbba99a0 247 gcall *head_end; /* Final marker of head sequence. */
248};
249
250/* Flags for an OpenACC loop. */
251
252enum oacc_loop_flags {
253 OLF_SEQ = 1u << 0, /* Explicitly sequential */
254 OLF_AUTO = 1u << 1, /* Compiler chooses axes. */
255 OLF_INDEPENDENT = 1u << 2, /* Iterations are known independent. */
256 OLF_GANG_STATIC = 1u << 3, /* Gang partitioning is static (has op). */
257
258 /* Explicitly specified loop axes. */
259 OLF_DIM_BASE = 4,
260 OLF_DIM_GANG = 1u << (OLF_DIM_BASE + GOMP_DIM_GANG),
261 OLF_DIM_WORKER = 1u << (OLF_DIM_BASE + GOMP_DIM_WORKER),
262 OLF_DIM_VECTOR = 1u << (OLF_DIM_BASE + GOMP_DIM_VECTOR),
263
264 OLF_MAX = OLF_DIM_BASE + GOMP_DIM_MAX
265};
266
773c5ba7 267
1e8e9920 268static splay_tree all_contexts;
fd6481cf 269static int taskreg_nesting_level;
bc7bff74 270static int target_nesting_level;
7740abd8 271static struct omp_region *root_omp_region;
fd6481cf 272static bitmap task_shared_vars;
37eaded9 273static vec<omp_context *> taskreg_contexts;
9561765e 274static bool omp_any_child_fn_dumped;
1e8e9920 275
ab129075 276static void scan_omp (gimple_seq *, omp_context *);
75a70cf9 277static tree scan_omp_1_op (tree *, int *, void *);
2131a1a9 278static gphi *find_phi_with_arg_on_edge (tree, edge);
75a70cf9 279
280#define WALK_SUBSTMTS \
281 case GIMPLE_BIND: \
282 case GIMPLE_TRY: \
283 case GIMPLE_CATCH: \
284 case GIMPLE_EH_FILTER: \
4c0315d0 285 case GIMPLE_TRANSACTION: \
75a70cf9 286 /* The sub-statements for these should be walked. */ \
287 *handled_ops_p = false; \
288 break;
289
a8e785ba 290/* Return true if CTX corresponds to an oacc parallel region. */
291
292static bool
293is_oacc_parallel (omp_context *ctx)
294{
295 enum gimple_code outer_type = gimple_code (ctx->stmt);
296 return ((outer_type == GIMPLE_OMP_TARGET)
297 && (gimple_omp_target_kind (ctx->stmt)
298 == GF_OMP_TARGET_KIND_OACC_PARALLEL));
299}
300
301/* Return true if CTX corresponds to an oacc kernels region. */
302
303static bool
304is_oacc_kernels (omp_context *ctx)
305{
306 enum gimple_code outer_type = gimple_code (ctx->stmt);
307 return ((outer_type == GIMPLE_OMP_TARGET)
308 && (gimple_omp_target_kind (ctx->stmt)
309 == GF_OMP_TARGET_KIND_OACC_KERNELS));
310}
311
43895be5 312/* If DECL is the artificial dummy VAR_DECL created for non-static
313 data member privatization, return the underlying "this" parameter,
314 otherwise return NULL. */
315
316tree
317omp_member_access_dummy_var (tree decl)
318{
319 if (!VAR_P (decl)
320 || !DECL_ARTIFICIAL (decl)
321 || !DECL_IGNORED_P (decl)
322 || !DECL_HAS_VALUE_EXPR_P (decl)
323 || !lang_hooks.decls.omp_disregard_value_expr (decl, false))
324 return NULL_TREE;
325
326 tree v = DECL_VALUE_EXPR (decl);
327 if (TREE_CODE (v) != COMPONENT_REF)
328 return NULL_TREE;
329
330 while (1)
331 switch (TREE_CODE (v))
332 {
333 case COMPONENT_REF:
334 case MEM_REF:
335 case INDIRECT_REF:
336 CASE_CONVERT:
337 case POINTER_PLUS_EXPR:
338 v = TREE_OPERAND (v, 0);
339 continue;
340 case PARM_DECL:
341 if (DECL_CONTEXT (v) == current_function_decl
342 && DECL_ARTIFICIAL (v)
343 && TREE_CODE (TREE_TYPE (v)) == POINTER_TYPE)
344 return v;
345 return NULL_TREE;
346 default:
347 return NULL_TREE;
348 }
349}
350
351/* Helper for unshare_and_remap, called through walk_tree. */
352
353static tree
354unshare_and_remap_1 (tree *tp, int *walk_subtrees, void *data)
355{
356 tree *pair = (tree *) data;
357 if (*tp == pair[0])
358 {
359 *tp = unshare_expr (pair[1]);
360 *walk_subtrees = 0;
361 }
362 else if (IS_TYPE_OR_DECL_P (*tp))
363 *walk_subtrees = 0;
364 return NULL_TREE;
365}
366
367/* Return unshare_expr (X) with all occurrences of FROM
368 replaced with TO. */
369
370static tree
371unshare_and_remap (tree x, tree from, tree to)
372{
373 tree pair[2] = { from, to };
374 x = unshare_expr (x);
375 walk_tree (&x, unshare_and_remap_1, pair, NULL);
376 return x;
377}
378
dccabdd1 379/* Holds offload tables with decls. */
380vec<tree, va_gc> *offload_funcs, *offload_vars;
381
75a70cf9 382/* Convenience function for calling scan_omp_1_op on tree operands. */
383
384static inline tree
385scan_omp_op (tree *tp, omp_context *ctx)
386{
387 struct walk_stmt_info wi;
388
389 memset (&wi, 0, sizeof (wi));
390 wi.info = ctx;
391 wi.want_locations = true;
392
393 return walk_tree (tp, scan_omp_1_op, &wi, NULL);
394}
395
e3a19533 396static void lower_omp (gimple_seq *, omp_context *);
f49d7bb5 397static tree lookup_decl_in_outer_ctx (tree, omp_context *);
398static tree maybe_lookup_decl_in_outer_ctx (tree, omp_context *);
1e8e9920 399
ca4c3545 400/* Find an OMP clause of type KIND within CLAUSES. */
1e8e9920 401
79acaae1 402tree
590c3166 403find_omp_clause (tree clauses, enum omp_clause_code kind)
1e8e9920 404{
405 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
55d6e7cd 406 if (OMP_CLAUSE_CODE (clauses) == kind)
1e8e9920 407 return clauses;
408
409 return NULL_TREE;
410}
411
412/* Return true if CTX is for an omp parallel. */
413
414static inline bool
415is_parallel_ctx (omp_context *ctx)
416{
75a70cf9 417 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL;
1e8e9920 418}
419
773c5ba7 420
fd6481cf 421/* Return true if CTX is for an omp task. */
422
423static inline bool
424is_task_ctx (omp_context *ctx)
425{
75a70cf9 426 return gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
fd6481cf 427}
428
429
43895be5 430/* Return true if CTX is for an omp taskloop. */
431
432static inline bool
433is_taskloop_ctx (omp_context *ctx)
434{
435 return gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
436 && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_TASKLOOP;
437}
438
439
fd6481cf 440/* Return true if CTX is for an omp parallel or omp task. */
441
442static inline bool
443is_taskreg_ctx (omp_context *ctx)
444{
43895be5 445 return is_parallel_ctx (ctx) || is_task_ctx (ctx);
fd6481cf 446}
447
448
773c5ba7 449/* Return true if REGION is a combined parallel+workshare region. */
1e8e9920 450
451static inline bool
773c5ba7 452is_combined_parallel (struct omp_region *region)
453{
454 return region->is_combined_parallel;
455}
456
56686608 457/* Adjust *COND_CODE and *N2 so that the former is either LT_EXPR or
458 GT_EXPR. */
459
460static void
461adjust_for_condition (location_t loc, enum tree_code *cond_code, tree *n2)
462{
463 switch (*cond_code)
464 {
465 case LT_EXPR:
466 case GT_EXPR:
467 case NE_EXPR:
468 break;
469 case LE_EXPR:
470 if (POINTER_TYPE_P (TREE_TYPE (*n2)))
471 *n2 = fold_build_pointer_plus_hwi_loc (loc, *n2, 1);
472 else
473 *n2 = fold_build2_loc (loc, PLUS_EXPR, TREE_TYPE (*n2), *n2,
474 build_int_cst (TREE_TYPE (*n2), 1));
475 *cond_code = LT_EXPR;
476 break;
477 case GE_EXPR:
478 if (POINTER_TYPE_P (TREE_TYPE (*n2)))
479 *n2 = fold_build_pointer_plus_hwi_loc (loc, *n2, -1);
480 else
481 *n2 = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (*n2), *n2,
482 build_int_cst (TREE_TYPE (*n2), 1));
483 *cond_code = GT_EXPR;
484 break;
485 default:
486 gcc_unreachable ();
487 }
488}
489
490/* Return the looping step from INCR, extracted from the step of a gimple omp
491 for statement. */
492
493static tree
494get_omp_for_step_from_incr (location_t loc, tree incr)
495{
496 tree step;
497 switch (TREE_CODE (incr))
498 {
499 case PLUS_EXPR:
500 step = TREE_OPERAND (incr, 1);
501 break;
502 case POINTER_PLUS_EXPR:
503 step = fold_convert (ssizetype, TREE_OPERAND (incr, 1));
504 break;
505 case MINUS_EXPR:
506 step = TREE_OPERAND (incr, 1);
507 step = fold_build1_loc (loc, NEGATE_EXPR, TREE_TYPE (step), step);
508 break;
509 default:
510 gcc_unreachable ();
511 }
512 return step;
513}
773c5ba7 514
515/* Extract the header elements of parallel loop FOR_STMT and store
516 them into *FD. */
517
518static void
1a91d914 519extract_omp_for_data (gomp_for *for_stmt, struct omp_for_data *fd,
fd6481cf 520 struct omp_for_data_loop *loops)
773c5ba7 521{
fd6481cf 522 tree t, var, *collapse_iter, *collapse_count;
523 tree count = NULL_TREE, iter_type = long_integer_type_node;
524 struct omp_for_data_loop *loop;
525 int i;
526 struct omp_for_data_loop dummy_loop;
389dd41b 527 location_t loc = gimple_location (for_stmt);
10c55644 528 bool simd = gimple_omp_for_kind (for_stmt) & GF_OMP_FOR_SIMD;
bc7bff74 529 bool distribute = gimple_omp_for_kind (for_stmt)
530 == GF_OMP_FOR_KIND_DISTRIBUTE;
43895be5 531 bool taskloop = gimple_omp_for_kind (for_stmt)
532 == GF_OMP_FOR_KIND_TASKLOOP;
533 tree iterv, countv;
773c5ba7 534
535 fd->for_stmt = for_stmt;
536 fd->pre = NULL;
43895be5 537 if (gimple_omp_for_collapse (for_stmt) > 1)
fd6481cf 538 fd->loops = loops;
539 else
540 fd->loops = &fd->loop;
773c5ba7 541
bc7bff74 542 fd->have_nowait = distribute || simd;
543 fd->have_ordered = false;
43895be5 544 fd->collapse = 1;
545 fd->ordered = 0;
773c5ba7 546 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
9561765e 547 fd->sched_modifiers = 0;
773c5ba7 548 fd->chunk_size = NULL_TREE;
43895be5 549 fd->simd_schedule = false;
40750995 550 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
551 fd->sched_kind = OMP_CLAUSE_SCHEDULE_CILKFOR;
fd6481cf 552 collapse_iter = NULL;
553 collapse_count = NULL;
773c5ba7 554
75a70cf9 555 for (t = gimple_omp_for_clauses (for_stmt); t ; t = OMP_CLAUSE_CHAIN (t))
55d6e7cd 556 switch (OMP_CLAUSE_CODE (t))
773c5ba7 557 {
558 case OMP_CLAUSE_NOWAIT:
559 fd->have_nowait = true;
560 break;
561 case OMP_CLAUSE_ORDERED:
562 fd->have_ordered = true;
43895be5 563 if (OMP_CLAUSE_ORDERED_EXPR (t))
564 fd->ordered = tree_to_shwi (OMP_CLAUSE_ORDERED_EXPR (t));
773c5ba7 565 break;
566 case OMP_CLAUSE_SCHEDULE:
43895be5 567 gcc_assert (!distribute && !taskloop);
9561765e 568 fd->sched_kind
569 = (enum omp_clause_schedule_kind)
570 (OMP_CLAUSE_SCHEDULE_KIND (t) & OMP_CLAUSE_SCHEDULE_MASK);
571 fd->sched_modifiers = (OMP_CLAUSE_SCHEDULE_KIND (t)
572 & ~OMP_CLAUSE_SCHEDULE_MASK);
773c5ba7 573 fd->chunk_size = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t);
43895be5 574 fd->simd_schedule = OMP_CLAUSE_SCHEDULE_SIMD (t);
773c5ba7 575 break;
bc7bff74 576 case OMP_CLAUSE_DIST_SCHEDULE:
577 gcc_assert (distribute);
578 fd->chunk_size = OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (t);
579 break;
fd6481cf 580 case OMP_CLAUSE_COLLAPSE:
43895be5 581 fd->collapse = tree_to_shwi (OMP_CLAUSE_COLLAPSE_EXPR (t));
fd6481cf 582 if (fd->collapse > 1)
583 {
584 collapse_iter = &OMP_CLAUSE_COLLAPSE_ITERVAR (t);
585 collapse_count = &OMP_CLAUSE_COLLAPSE_COUNT (t);
586 }
757abb46 587 break;
773c5ba7 588 default:
589 break;
590 }
43895be5 591 if (fd->ordered && fd->collapse == 1 && loops != NULL)
592 {
593 fd->loops = loops;
594 iterv = NULL_TREE;
595 countv = NULL_TREE;
596 collapse_iter = &iterv;
597 collapse_count = &countv;
598 }
773c5ba7 599
fd6481cf 600 /* FIXME: for now map schedule(auto) to schedule(static).
601 There should be analysis to determine whether all iterations
602 are approximately the same amount of work (then schedule(static)
bde357c8 603 is best) or if it varies (then schedule(dynamic,N) is better). */
fd6481cf 604 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_AUTO)
605 {
606 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
607 gcc_assert (fd->chunk_size == NULL);
608 }
609 gcc_assert (fd->collapse == 1 || collapse_iter != NULL);
43895be5 610 if (taskloop)
611 fd->sched_kind = OMP_CLAUSE_SCHEDULE_RUNTIME;
773c5ba7 612 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
613 gcc_assert (fd->chunk_size == NULL);
614 else if (fd->chunk_size == NULL)
615 {
616 /* We only need to compute a default chunk size for ordered
617 static loops and dynamic loops. */
fd6481cf 618 if (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
bc7bff74 619 || fd->have_ordered)
773c5ba7 620 fd->chunk_size = (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
621 ? integer_zero_node : integer_one_node;
622 }
fd6481cf 623
43895be5 624 int cnt = fd->ordered ? fd->ordered : fd->collapse;
625 for (i = 0; i < cnt; i++)
fd6481cf 626 {
43895be5 627 if (i == 0 && fd->collapse == 1 && (fd->ordered == 0 || loops == NULL))
fd6481cf 628 loop = &fd->loop;
629 else if (loops != NULL)
630 loop = loops + i;
631 else
632 loop = &dummy_loop;
633
75a70cf9 634 loop->v = gimple_omp_for_index (for_stmt, i);
fd6481cf 635 gcc_assert (SSA_VAR_P (loop->v));
636 gcc_assert (TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
637 || TREE_CODE (TREE_TYPE (loop->v)) == POINTER_TYPE);
638 var = TREE_CODE (loop->v) == SSA_NAME ? SSA_NAME_VAR (loop->v) : loop->v;
75a70cf9 639 loop->n1 = gimple_omp_for_initial (for_stmt, i);
fd6481cf 640
75a70cf9 641 loop->cond_code = gimple_omp_for_cond (for_stmt, i);
642 loop->n2 = gimple_omp_for_final (for_stmt, i);
56686608 643 gcc_assert (loop->cond_code != NE_EXPR
644 || gimple_omp_for_kind (for_stmt) == GF_OMP_FOR_KIND_CILKSIMD
645 || gimple_omp_for_kind (for_stmt) == GF_OMP_FOR_KIND_CILKFOR);
646 adjust_for_condition (loc, &loop->cond_code, &loop->n2);
fd6481cf 647
75a70cf9 648 t = gimple_omp_for_incr (for_stmt, i);
fd6481cf 649 gcc_assert (TREE_OPERAND (t, 0) == var);
56686608 650 loop->step = get_omp_for_step_from_incr (loc, t);
fd6481cf 651
bc7bff74 652 if (simd
653 || (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
654 && !fd->have_ordered))
3d483a94 655 {
656 if (fd->collapse == 1)
657 iter_type = TREE_TYPE (loop->v);
658 else if (i == 0
659 || TYPE_PRECISION (iter_type)
660 < TYPE_PRECISION (TREE_TYPE (loop->v)))
661 iter_type
662 = build_nonstandard_integer_type
bc7bff74 663 (TYPE_PRECISION (TREE_TYPE (loop->v)), 1);
3d483a94 664 }
665 else if (iter_type != long_long_unsigned_type_node)
fd6481cf 666 {
667 if (POINTER_TYPE_P (TREE_TYPE (loop->v)))
668 iter_type = long_long_unsigned_type_node;
669 else if (TYPE_UNSIGNED (TREE_TYPE (loop->v))
670 && TYPE_PRECISION (TREE_TYPE (loop->v))
671 >= TYPE_PRECISION (iter_type))
672 {
673 tree n;
674
675 if (loop->cond_code == LT_EXPR)
389dd41b 676 n = fold_build2_loc (loc,
677 PLUS_EXPR, TREE_TYPE (loop->v),
fd6481cf 678 loop->n2, loop->step);
679 else
680 n = loop->n1;
681 if (TREE_CODE (n) != INTEGER_CST
682 || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type), n))
683 iter_type = long_long_unsigned_type_node;
684 }
685 else if (TYPE_PRECISION (TREE_TYPE (loop->v))
686 > TYPE_PRECISION (iter_type))
687 {
688 tree n1, n2;
689
690 if (loop->cond_code == LT_EXPR)
691 {
692 n1 = loop->n1;
389dd41b 693 n2 = fold_build2_loc (loc,
694 PLUS_EXPR, TREE_TYPE (loop->v),
fd6481cf 695 loop->n2, loop->step);
696 }
697 else
698 {
389dd41b 699 n1 = fold_build2_loc (loc,
700 MINUS_EXPR, TREE_TYPE (loop->v),
fd6481cf 701 loop->n2, loop->step);
702 n2 = loop->n1;
703 }
704 if (TREE_CODE (n1) != INTEGER_CST
705 || TREE_CODE (n2) != INTEGER_CST
706 || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type), n1)
707 || !tree_int_cst_lt (n2, TYPE_MAX_VALUE (iter_type)))
708 iter_type = long_long_unsigned_type_node;
709 }
710 }
711
43895be5 712 if (i >= fd->collapse)
713 continue;
714
fd6481cf 715 if (collapse_count && *collapse_count == NULL)
716 {
8e6b4515 717 t = fold_binary (loop->cond_code, boolean_type_node,
718 fold_convert (TREE_TYPE (loop->v), loop->n1),
719 fold_convert (TREE_TYPE (loop->v), loop->n2));
720 if (t && integer_zerop (t))
721 count = build_zero_cst (long_long_unsigned_type_node);
722 else if ((i == 0 || count != NULL_TREE)
723 && TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
724 && TREE_CONSTANT (loop->n1)
725 && TREE_CONSTANT (loop->n2)
726 && TREE_CODE (loop->step) == INTEGER_CST)
fd6481cf 727 {
728 tree itype = TREE_TYPE (loop->v);
729
730 if (POINTER_TYPE_P (itype))
3cea8318 731 itype = signed_type_for (itype);
fd6481cf 732 t = build_int_cst (itype, (loop->cond_code == LT_EXPR ? -1 : 1));
389dd41b 733 t = fold_build2_loc (loc,
734 PLUS_EXPR, itype,
735 fold_convert_loc (loc, itype, loop->step), t);
736 t = fold_build2_loc (loc, PLUS_EXPR, itype, t,
737 fold_convert_loc (loc, itype, loop->n2));
738 t = fold_build2_loc (loc, MINUS_EXPR, itype, t,
739 fold_convert_loc (loc, itype, loop->n1));
fd6481cf 740 if (TYPE_UNSIGNED (itype) && loop->cond_code == GT_EXPR)
389dd41b 741 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype,
742 fold_build1_loc (loc, NEGATE_EXPR, itype, t),
743 fold_build1_loc (loc, NEGATE_EXPR, itype,
744 fold_convert_loc (loc, itype,
745 loop->step)));
fd6481cf 746 else
389dd41b 747 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, t,
748 fold_convert_loc (loc, itype, loop->step));
749 t = fold_convert_loc (loc, long_long_unsigned_type_node, t);
fd6481cf 750 if (count != NULL_TREE)
389dd41b 751 count = fold_build2_loc (loc,
752 MULT_EXPR, long_long_unsigned_type_node,
fd6481cf 753 count, t);
754 else
755 count = t;
756 if (TREE_CODE (count) != INTEGER_CST)
757 count = NULL_TREE;
758 }
8e6b4515 759 else if (count && !integer_zerop (count))
fd6481cf 760 count = NULL_TREE;
761 }
762 }
763
3d483a94 764 if (count
bc7bff74 765 && !simd
766 && (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
767 || fd->have_ordered))
fd6481cf 768 {
769 if (!tree_int_cst_lt (count, TYPE_MAX_VALUE (long_integer_type_node)))
770 iter_type = long_long_unsigned_type_node;
771 else
772 iter_type = long_integer_type_node;
773 }
774 else if (collapse_iter && *collapse_iter != NULL)
775 iter_type = TREE_TYPE (*collapse_iter);
776 fd->iter_type = iter_type;
777 if (collapse_iter && *collapse_iter == NULL)
778 *collapse_iter = create_tmp_var (iter_type, ".iter");
779 if (collapse_count && *collapse_count == NULL)
780 {
781 if (count)
389dd41b 782 *collapse_count = fold_convert_loc (loc, iter_type, count);
fd6481cf 783 else
784 *collapse_count = create_tmp_var (iter_type, ".count");
785 }
786
43895be5 787 if (fd->collapse > 1 || (fd->ordered && loops))
fd6481cf 788 {
789 fd->loop.v = *collapse_iter;
790 fd->loop.n1 = build_int_cst (TREE_TYPE (fd->loop.v), 0);
791 fd->loop.n2 = *collapse_count;
792 fd->loop.step = build_int_cst (TREE_TYPE (fd->loop.v), 1);
793 fd->loop.cond_code = LT_EXPR;
794 }
43895be5 795 else if (loops)
796 loops[0] = fd->loop;
773c5ba7 797}
798
799
800/* Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB
801 is the immediate dominator of PAR_ENTRY_BB, return true if there
802 are no data dependencies that would prevent expanding the parallel
803 directive at PAR_ENTRY_BB as a combined parallel+workshare region.
804
805 When expanding a combined parallel+workshare region, the call to
806 the child function may need additional arguments in the case of
75a70cf9 807 GIMPLE_OMP_FOR regions. In some cases, these arguments are
808 computed out of variables passed in from the parent to the child
809 via 'struct .omp_data_s'. For instance:
773c5ba7 810
811 #pragma omp parallel for schedule (guided, i * 4)
812 for (j ...)
813
814 Is lowered into:
815
816 # BLOCK 2 (PAR_ENTRY_BB)
817 .omp_data_o.i = i;
818 #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
48e1416a 819
773c5ba7 820 # BLOCK 3 (WS_ENTRY_BB)
821 .omp_data_i = &.omp_data_o;
822 D.1667 = .omp_data_i->i;
823 D.1598 = D.1667 * 4;
824 #pragma omp for schedule (guided, D.1598)
825
826 When we outline the parallel region, the call to the child function
827 'bar.omp_fn.0' will need the value D.1598 in its argument list, but
828 that value is computed *after* the call site. So, in principle we
829 cannot do the transformation.
830
831 To see whether the code in WS_ENTRY_BB blocks the combined
832 parallel+workshare call, we collect all the variables used in the
75a70cf9 833 GIMPLE_OMP_FOR header check whether they appear on the LHS of any
773c5ba7 834 statement in WS_ENTRY_BB. If so, then we cannot emit the combined
835 call.
836
837 FIXME. If we had the SSA form built at this point, we could merely
838 hoist the code in block 3 into block 2 and be done with it. But at
839 this point we don't have dataflow information and though we could
840 hack something up here, it is really not worth the aggravation. */
841
842static bool
f018d957 843workshare_safe_to_combine_p (basic_block ws_entry_bb)
773c5ba7 844{
845 struct omp_for_data fd;
42acab1c 846 gimple *ws_stmt = last_stmt (ws_entry_bb);
773c5ba7 847
75a70cf9 848 if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
773c5ba7 849 return true;
850
75a70cf9 851 gcc_assert (gimple_code (ws_stmt) == GIMPLE_OMP_FOR);
773c5ba7 852
1a91d914 853 extract_omp_for_data (as_a <gomp_for *> (ws_stmt), &fd, NULL);
fd6481cf 854
855 if (fd.collapse > 1 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
856 return false;
857 if (fd.iter_type != long_integer_type_node)
858 return false;
773c5ba7 859
860 /* FIXME. We give up too easily here. If any of these arguments
861 are not constants, they will likely involve variables that have
862 been mapped into fields of .omp_data_s for sharing with the child
863 function. With appropriate data flow, it would be possible to
864 see through this. */
fd6481cf 865 if (!is_gimple_min_invariant (fd.loop.n1)
866 || !is_gimple_min_invariant (fd.loop.n2)
867 || !is_gimple_min_invariant (fd.loop.step)
773c5ba7 868 || (fd.chunk_size && !is_gimple_min_invariant (fd.chunk_size)))
869 return false;
870
871 return true;
872}
873
874
43895be5 875static int omp_max_vf (void);
876
877/* Adjust CHUNK_SIZE from SCHEDULE clause, depending on simd modifier
878 presence (SIMD_SCHEDULE). */
879
880static tree
881omp_adjust_chunk_size (tree chunk_size, bool simd_schedule)
882{
883 if (!simd_schedule)
884 return chunk_size;
885
886 int vf = omp_max_vf ();
887 if (vf == 1)
888 return chunk_size;
889
890 tree type = TREE_TYPE (chunk_size);
891 chunk_size = fold_build2 (PLUS_EXPR, type, chunk_size,
892 build_int_cst (type, vf - 1));
893 return fold_build2 (BIT_AND_EXPR, type, chunk_size,
894 build_int_cst (type, -vf));
895}
896
897
773c5ba7 898/* Collect additional arguments needed to emit a combined
899 parallel+workshare call. WS_STMT is the workshare directive being
900 expanded. */
901
f1f41a6c 902static vec<tree, va_gc> *
42acab1c 903get_ws_args_for (gimple *par_stmt, gimple *ws_stmt)
773c5ba7 904{
905 tree t;
389dd41b 906 location_t loc = gimple_location (ws_stmt);
f1f41a6c 907 vec<tree, va_gc> *ws_args;
773c5ba7 908
1a91d914 909 if (gomp_for *for_stmt = dyn_cast <gomp_for *> (ws_stmt))
773c5ba7 910 {
911 struct omp_for_data fd;
bc7bff74 912 tree n1, n2;
773c5ba7 913
1a91d914 914 extract_omp_for_data (for_stmt, &fd, NULL);
bc7bff74 915 n1 = fd.loop.n1;
916 n2 = fd.loop.n2;
917
1a91d914 918 if (gimple_omp_for_combined_into_p (for_stmt))
bc7bff74 919 {
920 tree innerc
921 = find_omp_clause (gimple_omp_parallel_clauses (par_stmt),
922 OMP_CLAUSE__LOOPTEMP_);
923 gcc_assert (innerc);
924 n1 = OMP_CLAUSE_DECL (innerc);
925 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
926 OMP_CLAUSE__LOOPTEMP_);
927 gcc_assert (innerc);
928 n2 = OMP_CLAUSE_DECL (innerc);
929 }
773c5ba7 930
f1f41a6c 931 vec_alloc (ws_args, 3 + (fd.chunk_size != 0));
773c5ba7 932
bc7bff74 933 t = fold_convert_loc (loc, long_integer_type_node, n1);
f1f41a6c 934 ws_args->quick_push (t);
773c5ba7 935
bc7bff74 936 t = fold_convert_loc (loc, long_integer_type_node, n2);
f1f41a6c 937 ws_args->quick_push (t);
773c5ba7 938
414c3a2c 939 t = fold_convert_loc (loc, long_integer_type_node, fd.loop.step);
f1f41a6c 940 ws_args->quick_push (t);
414c3a2c 941
942 if (fd.chunk_size)
943 {
944 t = fold_convert_loc (loc, long_integer_type_node, fd.chunk_size);
43895be5 945 t = omp_adjust_chunk_size (t, fd.simd_schedule);
f1f41a6c 946 ws_args->quick_push (t);
414c3a2c 947 }
773c5ba7 948
949 return ws_args;
950 }
75a70cf9 951 else if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
773c5ba7 952 {
ac6e3339 953 /* Number of sections is equal to the number of edges from the
75a70cf9 954 GIMPLE_OMP_SECTIONS_SWITCH statement, except for the one to
955 the exit of the sections region. */
956 basic_block bb = single_succ (gimple_bb (ws_stmt));
ac6e3339 957 t = build_int_cst (unsigned_type_node, EDGE_COUNT (bb->succs) - 1);
f1f41a6c 958 vec_alloc (ws_args, 1);
959 ws_args->quick_push (t);
414c3a2c 960 return ws_args;
773c5ba7 961 }
962
963 gcc_unreachable ();
964}
965
966
967/* Discover whether REGION is a combined parallel+workshare region. */
968
969static void
970determine_parallel_type (struct omp_region *region)
1e8e9920 971{
773c5ba7 972 basic_block par_entry_bb, par_exit_bb;
973 basic_block ws_entry_bb, ws_exit_bb;
974
03ed154b 975 if (region == NULL || region->inner == NULL
ac6e3339 976 || region->exit == NULL || region->inner->exit == NULL
977 || region->inner->cont == NULL)
773c5ba7 978 return;
979
980 /* We only support parallel+for and parallel+sections. */
75a70cf9 981 if (region->type != GIMPLE_OMP_PARALLEL
982 || (region->inner->type != GIMPLE_OMP_FOR
983 && region->inner->type != GIMPLE_OMP_SECTIONS))
773c5ba7 984 return;
985
986 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
987 WS_EXIT_BB -> PAR_EXIT_BB. */
61e47ac8 988 par_entry_bb = region->entry;
989 par_exit_bb = region->exit;
990 ws_entry_bb = region->inner->entry;
991 ws_exit_bb = region->inner->exit;
773c5ba7 992
993 if (single_succ (par_entry_bb) == ws_entry_bb
994 && single_succ (ws_exit_bb) == par_exit_bb
f018d957 995 && workshare_safe_to_combine_p (ws_entry_bb)
75a70cf9 996 && (gimple_omp_parallel_combined_p (last_stmt (par_entry_bb))
de7ef844 997 || (last_and_only_stmt (ws_entry_bb)
998 && last_and_only_stmt (par_exit_bb))))
773c5ba7 999 {
42acab1c 1000 gimple *par_stmt = last_stmt (par_entry_bb);
1001 gimple *ws_stmt = last_stmt (ws_entry_bb);
61e47ac8 1002
75a70cf9 1003 if (region->inner->type == GIMPLE_OMP_FOR)
773c5ba7 1004 {
1005 /* If this is a combined parallel loop, we need to determine
1006 whether or not to use the combined library calls. There
1007 are two cases where we do not apply the transformation:
1008 static loops and any kind of ordered loop. In the first
1009 case, we already open code the loop so there is no need
1010 to do anything else. In the latter case, the combined
1011 parallel loop call would still need extra synchronization
1012 to implement ordered semantics, so there would not be any
1013 gain in using the combined call. */
75a70cf9 1014 tree clauses = gimple_omp_for_clauses (ws_stmt);
773c5ba7 1015 tree c = find_omp_clause (clauses, OMP_CLAUSE_SCHEDULE);
1016 if (c == NULL
9561765e 1017 || ((OMP_CLAUSE_SCHEDULE_KIND (c) & OMP_CLAUSE_SCHEDULE_MASK)
1018 == OMP_CLAUSE_SCHEDULE_STATIC)
773c5ba7 1019 || find_omp_clause (clauses, OMP_CLAUSE_ORDERED))
1020 {
1021 region->is_combined_parallel = false;
1022 region->inner->is_combined_parallel = false;
1023 return;
1024 }
1025 }
1026
1027 region->is_combined_parallel = true;
1028 region->inner->is_combined_parallel = true;
bc7bff74 1029 region->ws_args = get_ws_args_for (par_stmt, ws_stmt);
773c5ba7 1030 }
1e8e9920 1031}
1032
773c5ba7 1033
1e8e9920 1034/* Return true if EXPR is variable sized. */
1035
1036static inline bool
1f1872fd 1037is_variable_sized (const_tree expr)
1e8e9920 1038{
1039 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr)));
1040}
1041
1042/* Return true if DECL is a reference type. */
1043
1044static inline bool
1045is_reference (tree decl)
1046{
1047 return lang_hooks.decls.omp_privatize_by_reference (decl);
1048}
1049
ca4c3545 1050/* Return the type of a decl. If the decl is reference type,
1051 return its base type. */
1052static inline tree
1053get_base_type (tree decl)
1054{
1055 tree type = TREE_TYPE (decl);
1056 if (is_reference (decl))
1057 type = TREE_TYPE (type);
1058 return type;
1059}
1060
1061/* Lookup variables. The "maybe" form
1e8e9920 1062 allows for the variable form to not have been entered, otherwise we
1063 assert that the variable must have been entered. */
1064
1065static inline tree
1066lookup_decl (tree var, omp_context *ctx)
1067{
06ecf488 1068 tree *n = ctx->cb.decl_map->get (var);
e3022db7 1069 return *n;
1e8e9920 1070}
1071
1072static inline tree
e8a588af 1073maybe_lookup_decl (const_tree var, omp_context *ctx)
1e8e9920 1074{
06ecf488 1075 tree *n = ctx->cb.decl_map->get (const_cast<tree> (var));
e3022db7 1076 return n ? *n : NULL_TREE;
1e8e9920 1077}
1078
1079static inline tree
1080lookup_field (tree var, omp_context *ctx)
1081{
1082 splay_tree_node n;
1083 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
1084 return (tree) n->value;
1085}
1086
fd6481cf 1087static inline tree
43895be5 1088lookup_sfield (splay_tree_key key, omp_context *ctx)
fd6481cf 1089{
1090 splay_tree_node n;
1091 n = splay_tree_lookup (ctx->sfield_map
43895be5 1092 ? ctx->sfield_map : ctx->field_map, key);
fd6481cf 1093 return (tree) n->value;
1094}
1095
1e8e9920 1096static inline tree
43895be5 1097lookup_sfield (tree var, omp_context *ctx)
1098{
1099 return lookup_sfield ((splay_tree_key) var, ctx);
1100}
1101
1102static inline tree
1103maybe_lookup_field (splay_tree_key key, omp_context *ctx)
1e8e9920 1104{
1105 splay_tree_node n;
43895be5 1106 n = splay_tree_lookup (ctx->field_map, key);
1e8e9920 1107 return n ? (tree) n->value : NULL_TREE;
1108}
1109
43895be5 1110static inline tree
1111maybe_lookup_field (tree var, omp_context *ctx)
1112{
1113 return maybe_lookup_field ((splay_tree_key) var, ctx);
1114}
1115
e8a588af 1116/* Return true if DECL should be copied by pointer. SHARED_CTX is
1117 the parallel context if DECL is to be shared. */
1e8e9920 1118
1119static bool
fd6481cf 1120use_pointer_for_field (tree decl, omp_context *shared_ctx)
1e8e9920 1121{
1122 if (AGGREGATE_TYPE_P (TREE_TYPE (decl)))
1123 return true;
1124
554f2707 1125 /* We can only use copy-in/copy-out semantics for shared variables
1e8e9920 1126 when we know the value is not accessible from an outer scope. */
e8a588af 1127 if (shared_ctx)
1e8e9920 1128 {
ca4c3545 1129 gcc_assert (!is_gimple_omp_oacc (shared_ctx->stmt));
1130
1e8e9920 1131 /* ??? Trivially accessible from anywhere. But why would we even
1132 be passing an address in this case? Should we simply assert
1133 this to be false, or should we have a cleanup pass that removes
1134 these from the list of mappings? */
1135 if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
1136 return true;
1137
1138 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
1139 without analyzing the expression whether or not its location
1140 is accessible to anyone else. In the case of nested parallel
1141 regions it certainly may be. */
df2c34fc 1142 if (TREE_CODE (decl) != RESULT_DECL && DECL_HAS_VALUE_EXPR_P (decl))
1e8e9920 1143 return true;
1144
1145 /* Do not use copy-in/copy-out for variables that have their
1146 address taken. */
1147 if (TREE_ADDRESSABLE (decl))
1148 return true;
e8a588af 1149
b8214689 1150 /* lower_send_shared_vars only uses copy-in, but not copy-out
1151 for these. */
1152 if (TREE_READONLY (decl)
1153 || ((TREE_CODE (decl) == RESULT_DECL
1154 || TREE_CODE (decl) == PARM_DECL)
1155 && DECL_BY_REFERENCE (decl)))
1156 return false;
1157
e8a588af 1158 /* Disallow copy-in/out in nested parallel if
1159 decl is shared in outer parallel, otherwise
1160 each thread could store the shared variable
1161 in its own copy-in location, making the
1162 variable no longer really shared. */
b8214689 1163 if (shared_ctx->is_nested)
e8a588af 1164 {
1165 omp_context *up;
1166
1167 for (up = shared_ctx->outer; up; up = up->outer)
0cb159ec 1168 if (is_taskreg_ctx (up) && maybe_lookup_decl (decl, up))
e8a588af 1169 break;
1170
0cb159ec 1171 if (up)
e8a588af 1172 {
1173 tree c;
1174
75a70cf9 1175 for (c = gimple_omp_taskreg_clauses (up->stmt);
e8a588af 1176 c; c = OMP_CLAUSE_CHAIN (c))
1177 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
1178 && OMP_CLAUSE_DECL (c) == decl)
1179 break;
1180
1181 if (c)
784ad964 1182 goto maybe_mark_addressable_and_ret;
e8a588af 1183 }
1184 }
fd6481cf 1185
b8214689 1186 /* For tasks avoid using copy-in/out. As tasks can be
fd6481cf 1187 deferred or executed in different thread, when GOMP_task
1188 returns, the task hasn't necessarily terminated. */
b8214689 1189 if (is_task_ctx (shared_ctx))
fd6481cf 1190 {
784ad964 1191 tree outer;
1192 maybe_mark_addressable_and_ret:
1193 outer = maybe_lookup_decl_in_outer_ctx (decl, shared_ctx);
43895be5 1194 if (is_gimple_reg (outer) && !omp_member_access_dummy_var (outer))
fd6481cf 1195 {
1196 /* Taking address of OUTER in lower_send_shared_vars
1197 might need regimplification of everything that uses the
1198 variable. */
1199 if (!task_shared_vars)
1200 task_shared_vars = BITMAP_ALLOC (NULL);
1201 bitmap_set_bit (task_shared_vars, DECL_UID (outer));
1202 TREE_ADDRESSABLE (outer) = 1;
1203 }
1204 return true;
1205 }
1e8e9920 1206 }
1207
1208 return false;
1209}
1210
79acaae1 1211/* Construct a new automatic decl similar to VAR. */
1212
1213static tree
1214omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx)
1215{
1216 tree copy = copy_var_decl (var, name, type);
1217
1218 DECL_CONTEXT (copy) = current_function_decl;
1767a056 1219 DECL_CHAIN (copy) = ctx->block_vars;
43895be5 1220 /* If VAR is listed in task_shared_vars, it means it wasn't
1221 originally addressable and is just because task needs to take
1222 it's address. But we don't need to take address of privatizations
1223 from that var. */
1224 if (TREE_ADDRESSABLE (var)
1225 && task_shared_vars
1226 && bitmap_bit_p (task_shared_vars, DECL_UID (var)))
1227 TREE_ADDRESSABLE (copy) = 0;
1e8e9920 1228 ctx->block_vars = copy;
1229
1230 return copy;
1231}
1232
1233static tree
1234omp_copy_decl_1 (tree var, omp_context *ctx)
1235{
1236 return omp_copy_decl_2 (var, DECL_NAME (var), TREE_TYPE (var), ctx);
1237}
1238
445d06b6 1239/* Build COMPONENT_REF and set TREE_THIS_VOLATILE and TREE_READONLY on it
1240 as appropriate. */
1241static tree
1242omp_build_component_ref (tree obj, tree field)
1243{
1244 tree ret = build3 (COMPONENT_REF, TREE_TYPE (field), obj, field, NULL);
1245 if (TREE_THIS_VOLATILE (field))
1246 TREE_THIS_VOLATILE (ret) |= 1;
1247 if (TREE_READONLY (field))
1248 TREE_READONLY (ret) |= 1;
1249 return ret;
1250}
1251
1e8e9920 1252/* Build tree nodes to access the field for VAR on the receiver side. */
1253
1254static tree
1255build_receiver_ref (tree var, bool by_ref, omp_context *ctx)
1256{
1257 tree x, field = lookup_field (var, ctx);
1258
1259 /* If the receiver record type was remapped in the child function,
1260 remap the field into the new record type. */
1261 x = maybe_lookup_field (field, ctx);
1262 if (x != NULL)
1263 field = x;
1264
182cf5a9 1265 x = build_simple_mem_ref (ctx->receiver_decl);
75c20a2e 1266 TREE_THIS_NOTRAP (x) = 1;
445d06b6 1267 x = omp_build_component_ref (x, field);
1e8e9920 1268 if (by_ref)
b16d27b9 1269 {
1270 x = build_simple_mem_ref (x);
1271 TREE_THIS_NOTRAP (x) = 1;
1272 }
1e8e9920 1273
1274 return x;
1275}
1276
1277/* Build tree nodes to access VAR in the scope outer to CTX. In the case
1278 of a parallel, this is a component reference; for workshare constructs
1279 this is some variable. */
1280
1281static tree
43895be5 1282build_outer_var_ref (tree var, omp_context *ctx, bool lastprivate = false)
1e8e9920 1283{
1284 tree x;
1285
f49d7bb5 1286 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx)))
1e8e9920 1287 x = var;
1288 else if (is_variable_sized (var))
1289 {
1290 x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
43895be5 1291 x = build_outer_var_ref (x, ctx, lastprivate);
182cf5a9 1292 x = build_simple_mem_ref (x);
1e8e9920 1293 }
fd6481cf 1294 else if (is_taskreg_ctx (ctx))
1e8e9920 1295 {
e8a588af 1296 bool by_ref = use_pointer_for_field (var, NULL);
1e8e9920 1297 x = build_receiver_ref (var, by_ref, ctx);
1298 }
3d483a94 1299 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
10c55644 1300 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3d483a94 1301 {
1302 /* #pragma omp simd isn't a worksharing construct, and can reference even
1303 private vars in its linear etc. clauses. */
1304 x = NULL_TREE;
1305 if (ctx->outer && is_taskreg_ctx (ctx))
1306 x = lookup_decl (var, ctx->outer);
1307 else if (ctx->outer)
84cb1020 1308 x = maybe_lookup_decl_in_outer_ctx (var, ctx);
3d483a94 1309 if (x == NULL_TREE)
1310 x = var;
1311 }
43895be5 1312 else if (lastprivate && is_taskloop_ctx (ctx))
1313 {
1314 gcc_assert (ctx->outer);
1315 splay_tree_node n
1316 = splay_tree_lookup (ctx->outer->field_map,
1317 (splay_tree_key) &DECL_UID (var));
1318 if (n == NULL)
1319 {
1320 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx->outer)))
1321 x = var;
1322 else
1323 x = lookup_decl (var, ctx->outer);
1324 }
1325 else
1326 {
1327 tree field = (tree) n->value;
1328 /* If the receiver record type was remapped in the child function,
1329 remap the field into the new record type. */
1330 x = maybe_lookup_field (field, ctx->outer);
1331 if (x != NULL)
1332 field = x;
1333
1334 x = build_simple_mem_ref (ctx->outer->receiver_decl);
1335 x = omp_build_component_ref (x, field);
1336 if (use_pointer_for_field (var, ctx->outer))
1337 x = build_simple_mem_ref (x);
1338 }
1339 }
1e8e9920 1340 else if (ctx->outer)
56686608 1341 {
1342 omp_context *outer = ctx->outer;
1343 if (gimple_code (outer->stmt) == GIMPLE_OMP_GRID_BODY)
1344 {
1345 outer = outer->outer;
1346 gcc_assert (outer
1347 && gimple_code (outer->stmt) != GIMPLE_OMP_GRID_BODY);
1348 }
1349 x = lookup_decl (var, outer);
1350 }
9438af57 1351 else if (is_reference (var))
1352 /* This can happen with orphaned constructs. If var is reference, it is
1353 possible it is shared and as such valid. */
1354 x = var;
43895be5 1355 else if (omp_member_access_dummy_var (var))
1356 x = var;
1e8e9920 1357 else
1358 gcc_unreachable ();
1359
43895be5 1360 if (x == var)
1361 {
1362 tree t = omp_member_access_dummy_var (var);
1363 if (t)
1364 {
1365 x = DECL_VALUE_EXPR (var);
1366 tree o = maybe_lookup_decl_in_outer_ctx (t, ctx);
1367 if (o != t)
1368 x = unshare_and_remap (x, t, o);
1369 else
1370 x = unshare_expr (x);
1371 }
1372 }
1373
1e8e9920 1374 if (is_reference (var))
182cf5a9 1375 x = build_simple_mem_ref (x);
1e8e9920 1376
1377 return x;
1378}
1379
1380/* Build tree nodes to access the field for VAR on the sender side. */
1381
1382static tree
43895be5 1383build_sender_ref (splay_tree_key key, omp_context *ctx)
1e8e9920 1384{
43895be5 1385 tree field = lookup_sfield (key, ctx);
445d06b6 1386 return omp_build_component_ref (ctx->sender_decl, field);
1e8e9920 1387}
1388
43895be5 1389static tree
1390build_sender_ref (tree var, omp_context *ctx)
1391{
1392 return build_sender_ref ((splay_tree_key) var, ctx);
1393}
1394
12dc9a16 1395/* Add a new field for VAR inside the structure CTX->SENDER_DECL. If
1396 BASE_POINTERS_RESTRICT, declare the field with restrict. */
1e8e9920 1397
1398static void
12dc9a16 1399install_var_field (tree var, bool by_ref, int mask, omp_context *ctx,
1400 bool base_pointers_restrict = false)
1e8e9920 1401{
fd6481cf 1402 tree field, type, sfield = NULL_TREE;
43895be5 1403 splay_tree_key key = (splay_tree_key) var;
1e8e9920 1404
43895be5 1405 if ((mask & 8) != 0)
1406 {
1407 key = (splay_tree_key) &DECL_UID (var);
1408 gcc_checking_assert (key != (splay_tree_key) var);
1409 }
fd6481cf 1410 gcc_assert ((mask & 1) == 0
43895be5 1411 || !splay_tree_lookup (ctx->field_map, key));
fd6481cf 1412 gcc_assert ((mask & 2) == 0 || !ctx->sfield_map
43895be5 1413 || !splay_tree_lookup (ctx->sfield_map, key));
ca4c3545 1414 gcc_assert ((mask & 3) == 3
1415 || !is_gimple_omp_oacc (ctx->stmt));
1e8e9920 1416
1417 type = TREE_TYPE (var);
44c0112f 1418 /* Prevent redeclaring the var in the split-off function with a restrict
1419 pointer type. Note that we only clear type itself, restrict qualifiers in
1420 the pointed-to type will be ignored by points-to analysis. */
1421 if (POINTER_TYPE_P (type)
1422 && TYPE_RESTRICT (type))
1423 type = build_qualified_type (type, TYPE_QUALS (type) & ~TYPE_QUAL_RESTRICT);
1424
bc7bff74 1425 if (mask & 4)
1426 {
1427 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
1428 type = build_pointer_type (build_pointer_type (type));
1429 }
1430 else if (by_ref)
12dc9a16 1431 {
1432 type = build_pointer_type (type);
1433 if (base_pointers_restrict)
1434 type = build_qualified_type (type, TYPE_QUAL_RESTRICT);
1435 }
fd6481cf 1436 else if ((mask & 3) == 1 && is_reference (var))
1437 type = TREE_TYPE (type);
1e8e9920 1438
e60a6f7b 1439 field = build_decl (DECL_SOURCE_LOCATION (var),
1440 FIELD_DECL, DECL_NAME (var), type);
1e8e9920 1441
1442 /* Remember what variable this field was created for. This does have a
1443 side effect of making dwarf2out ignore this member, so for helpful
1444 debugging we clear it later in delete_omp_context. */
1445 DECL_ABSTRACT_ORIGIN (field) = var;
fd6481cf 1446 if (type == TREE_TYPE (var))
1447 {
1448 DECL_ALIGN (field) = DECL_ALIGN (var);
1449 DECL_USER_ALIGN (field) = DECL_USER_ALIGN (var);
1450 TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (var);
1451 }
1452 else
1453 DECL_ALIGN (field) = TYPE_ALIGN (type);
1e8e9920 1454
fd6481cf 1455 if ((mask & 3) == 3)
1456 {
1457 insert_field_into_struct (ctx->record_type, field);
1458 if (ctx->srecord_type)
1459 {
e60a6f7b 1460 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1461 FIELD_DECL, DECL_NAME (var), type);
fd6481cf 1462 DECL_ABSTRACT_ORIGIN (sfield) = var;
1463 DECL_ALIGN (sfield) = DECL_ALIGN (field);
1464 DECL_USER_ALIGN (sfield) = DECL_USER_ALIGN (field);
1465 TREE_THIS_VOLATILE (sfield) = TREE_THIS_VOLATILE (field);
1466 insert_field_into_struct (ctx->srecord_type, sfield);
1467 }
1468 }
1469 else
1470 {
1471 if (ctx->srecord_type == NULL_TREE)
1472 {
1473 tree t;
1474
1475 ctx->srecord_type = lang_hooks.types.make_type (RECORD_TYPE);
1476 ctx->sfield_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1477 for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
1478 {
43895be5 1479 sfield = build_decl (DECL_SOURCE_LOCATION (t),
e60a6f7b 1480 FIELD_DECL, DECL_NAME (t), TREE_TYPE (t));
fd6481cf 1481 DECL_ABSTRACT_ORIGIN (sfield) = DECL_ABSTRACT_ORIGIN (t);
1482 insert_field_into_struct (ctx->srecord_type, sfield);
1483 splay_tree_insert (ctx->sfield_map,
1484 (splay_tree_key) DECL_ABSTRACT_ORIGIN (t),
1485 (splay_tree_value) sfield);
1486 }
1487 }
1488 sfield = field;
1489 insert_field_into_struct ((mask & 1) ? ctx->record_type
1490 : ctx->srecord_type, field);
1491 }
1e8e9920 1492
fd6481cf 1493 if (mask & 1)
43895be5 1494 splay_tree_insert (ctx->field_map, key, (splay_tree_value) field);
fd6481cf 1495 if ((mask & 2) && ctx->sfield_map)
43895be5 1496 splay_tree_insert (ctx->sfield_map, key, (splay_tree_value) sfield);
1e8e9920 1497}
1498
1499static tree
1500install_var_local (tree var, omp_context *ctx)
1501{
1502 tree new_var = omp_copy_decl_1 (var, ctx);
1503 insert_decl_map (&ctx->cb, var, new_var);
1504 return new_var;
1505}
1506
1507/* Adjust the replacement for DECL in CTX for the new context. This means
1508 copying the DECL_VALUE_EXPR, and fixing up the type. */
1509
1510static void
1511fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug)
1512{
1513 tree new_decl, size;
1514
1515 new_decl = lookup_decl (decl, ctx);
1516
1517 TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb);
1518
1519 if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug)
1520 && DECL_HAS_VALUE_EXPR_P (decl))
1521 {
1522 tree ve = DECL_VALUE_EXPR (decl);
75a70cf9 1523 walk_tree (&ve, copy_tree_body_r, &ctx->cb, NULL);
1e8e9920 1524 SET_DECL_VALUE_EXPR (new_decl, ve);
1525 DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
1526 }
1527
1528 if (!TREE_CONSTANT (DECL_SIZE (new_decl)))
1529 {
1530 size = remap_decl (DECL_SIZE (decl), &ctx->cb);
1531 if (size == error_mark_node)
1532 size = TYPE_SIZE (TREE_TYPE (new_decl));
1533 DECL_SIZE (new_decl) = size;
1534
1535 size = remap_decl (DECL_SIZE_UNIT (decl), &ctx->cb);
1536 if (size == error_mark_node)
1537 size = TYPE_SIZE_UNIT (TREE_TYPE (new_decl));
1538 DECL_SIZE_UNIT (new_decl) = size;
1539 }
1540}
1541
1542/* The callback for remap_decl. Search all containing contexts for a
1543 mapping of the variable; this avoids having to duplicate the splay
1544 tree ahead of time. We know a mapping doesn't already exist in the
1545 given context. Create new mappings to implement default semantics. */
1546
1547static tree
1548omp_copy_decl (tree var, copy_body_data *cb)
1549{
1550 omp_context *ctx = (omp_context *) cb;
1551 tree new_var;
1552
1e8e9920 1553 if (TREE_CODE (var) == LABEL_DECL)
1554 {
e60a6f7b 1555 new_var = create_artificial_label (DECL_SOURCE_LOCATION (var));
773c5ba7 1556 DECL_CONTEXT (new_var) = current_function_decl;
1e8e9920 1557 insert_decl_map (&ctx->cb, var, new_var);
1558 return new_var;
1559 }
1560
fd6481cf 1561 while (!is_taskreg_ctx (ctx))
1e8e9920 1562 {
1563 ctx = ctx->outer;
1564 if (ctx == NULL)
1565 return var;
1566 new_var = maybe_lookup_decl (var, ctx);
1567 if (new_var)
1568 return new_var;
1569 }
1570
f49d7bb5 1571 if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn)
1572 return var;
1573
1e8e9920 1574 return error_mark_node;
1575}
1576
773c5ba7 1577
773c5ba7 1578/* Debugging dumps for parallel regions. */
1579void dump_omp_region (FILE *, struct omp_region *, int);
1580void debug_omp_region (struct omp_region *);
1581void debug_all_omp_regions (void);
1582
1583/* Dump the parallel region tree rooted at REGION. */
1584
1585void
1586dump_omp_region (FILE *file, struct omp_region *region, int indent)
1587{
61e47ac8 1588 fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index,
75a70cf9 1589 gimple_code_name[region->type]);
773c5ba7 1590
1591 if (region->inner)
1592 dump_omp_region (file, region->inner, indent + 4);
1593
61e47ac8 1594 if (region->cont)
1595 {
75a70cf9 1596 fprintf (file, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent, "",
61e47ac8 1597 region->cont->index);
1598 }
48e1416a 1599
773c5ba7 1600 if (region->exit)
75a70cf9 1601 fprintf (file, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent, "",
61e47ac8 1602 region->exit->index);
773c5ba7 1603 else
61e47ac8 1604 fprintf (file, "%*s[no exit marker]\n", indent, "");
773c5ba7 1605
1606 if (region->next)
61e47ac8 1607 dump_omp_region (file, region->next, indent);
773c5ba7 1608}
1609
4b987fac 1610DEBUG_FUNCTION void
773c5ba7 1611debug_omp_region (struct omp_region *region)
1612{
1613 dump_omp_region (stderr, region, 0);
1614}
1615
4b987fac 1616DEBUG_FUNCTION void
773c5ba7 1617debug_all_omp_regions (void)
1618{
1619 dump_omp_region (stderr, root_omp_region, 0);
1620}
1621
1622
1623/* Create a new parallel region starting at STMT inside region PARENT. */
1624
7740abd8 1625static struct omp_region *
75a70cf9 1626new_omp_region (basic_block bb, enum gimple_code type,
1627 struct omp_region *parent)
773c5ba7 1628{
4077bf7a 1629 struct omp_region *region = XCNEW (struct omp_region);
773c5ba7 1630
1631 region->outer = parent;
61e47ac8 1632 region->entry = bb;
1633 region->type = type;
773c5ba7 1634
1635 if (parent)
1636 {
1637 /* This is a nested region. Add it to the list of inner
1638 regions in PARENT. */
1639 region->next = parent->inner;
1640 parent->inner = region;
1641 }
61e47ac8 1642 else
773c5ba7 1643 {
1644 /* This is a toplevel region. Add it to the list of toplevel
1645 regions in ROOT_OMP_REGION. */
1646 region->next = root_omp_region;
1647 root_omp_region = region;
1648 }
61e47ac8 1649
1650 return region;
1651}
1652
1653/* Release the memory associated with the region tree rooted at REGION. */
1654
1655static void
1656free_omp_region_1 (struct omp_region *region)
1657{
1658 struct omp_region *i, *n;
1659
1660 for (i = region->inner; i ; i = n)
773c5ba7 1661 {
61e47ac8 1662 n = i->next;
1663 free_omp_region_1 (i);
773c5ba7 1664 }
1665
61e47ac8 1666 free (region);
1667}
773c5ba7 1668
61e47ac8 1669/* Release the memory for the entire omp region tree. */
1670
1671void
1672free_omp_regions (void)
1673{
1674 struct omp_region *r, *n;
1675 for (r = root_omp_region; r ; r = n)
1676 {
1677 n = r->next;
1678 free_omp_region_1 (r);
1679 }
1680 root_omp_region = NULL;
773c5ba7 1681}
1682
1683
1e8e9920 1684/* Create a new context, with OUTER_CTX being the surrounding context. */
1685
1686static omp_context *
42acab1c 1687new_omp_context (gimple *stmt, omp_context *outer_ctx)
1e8e9920 1688{
1689 omp_context *ctx = XCNEW (omp_context);
1690
1691 splay_tree_insert (all_contexts, (splay_tree_key) stmt,
1692 (splay_tree_value) ctx);
1693 ctx->stmt = stmt;
1694
1695 if (outer_ctx)
1696 {
1697 ctx->outer = outer_ctx;
1698 ctx->cb = outer_ctx->cb;
1699 ctx->cb.block = NULL;
1700 ctx->depth = outer_ctx->depth + 1;
1701 }
1702 else
1703 {
1704 ctx->cb.src_fn = current_function_decl;
1705 ctx->cb.dst_fn = current_function_decl;
415d1b9a 1706 ctx->cb.src_node = cgraph_node::get (current_function_decl);
53f79206 1707 gcc_checking_assert (ctx->cb.src_node);
1e8e9920 1708 ctx->cb.dst_node = ctx->cb.src_node;
1709 ctx->cb.src_cfun = cfun;
1710 ctx->cb.copy_decl = omp_copy_decl;
e38def9c 1711 ctx->cb.eh_lp_nr = 0;
1e8e9920 1712 ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
1713 ctx->depth = 1;
1714 }
1715
06ecf488 1716 ctx->cb.decl_map = new hash_map<tree, tree>;
1e8e9920 1717
1718 return ctx;
1719}
1720
75a70cf9 1721static gimple_seq maybe_catch_exception (gimple_seq);
f6430caa 1722
1723/* Finalize task copyfn. */
1724
1725static void
1a91d914 1726finalize_task_copyfn (gomp_task *task_stmt)
f6430caa 1727{
1728 struct function *child_cfun;
9078126c 1729 tree child_fn;
e3a19533 1730 gimple_seq seq = NULL, new_seq;
1a91d914 1731 gbind *bind;
f6430caa 1732
75a70cf9 1733 child_fn = gimple_omp_task_copy_fn (task_stmt);
f6430caa 1734 if (child_fn == NULL_TREE)
1735 return;
1736
1737 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
82b40354 1738 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
f6430caa 1739
f6430caa 1740 push_cfun (child_cfun);
7e3aae05 1741 bind = gimplify_body (child_fn, false);
75a70cf9 1742 gimple_seq_add_stmt (&seq, bind);
1743 new_seq = maybe_catch_exception (seq);
1744 if (new_seq != seq)
1745 {
1746 bind = gimple_build_bind (NULL, new_seq, NULL);
e3a19533 1747 seq = NULL;
75a70cf9 1748 gimple_seq_add_stmt (&seq, bind);
1749 }
1750 gimple_set_body (child_fn, seq);
f6430caa 1751 pop_cfun ();
f6430caa 1752
82b40354 1753 /* Inform the callgraph about the new function. */
47300487 1754 cgraph_node *node = cgraph_node::get_create (child_fn);
1755 node->parallelized_function = 1;
415d1b9a 1756 cgraph_node::add_new_function (child_fn, false);
f6430caa 1757}
1758
1e8e9920 1759/* Destroy a omp_context data structures. Called through the splay tree
1760 value delete callback. */
1761
1762static void
1763delete_omp_context (splay_tree_value value)
1764{
1765 omp_context *ctx = (omp_context *) value;
1766
06ecf488 1767 delete ctx->cb.decl_map;
1e8e9920 1768
1769 if (ctx->field_map)
1770 splay_tree_delete (ctx->field_map);
fd6481cf 1771 if (ctx->sfield_map)
1772 splay_tree_delete (ctx->sfield_map);
1e8e9920 1773
1774 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
1775 it produces corrupt debug information. */
1776 if (ctx->record_type)
1777 {
1778 tree t;
1767a056 1779 for (t = TYPE_FIELDS (ctx->record_type); t ; t = DECL_CHAIN (t))
1e8e9920 1780 DECL_ABSTRACT_ORIGIN (t) = NULL;
1781 }
fd6481cf 1782 if (ctx->srecord_type)
1783 {
1784 tree t;
1767a056 1785 for (t = TYPE_FIELDS (ctx->srecord_type); t ; t = DECL_CHAIN (t))
fd6481cf 1786 DECL_ABSTRACT_ORIGIN (t) = NULL;
1787 }
1e8e9920 1788
f6430caa 1789 if (is_task_ctx (ctx))
1a91d914 1790 finalize_task_copyfn (as_a <gomp_task *> (ctx->stmt));
f6430caa 1791
1e8e9920 1792 XDELETE (ctx);
1793}
1794
1795/* Fix up RECEIVER_DECL with a type that has been remapped to the child
1796 context. */
1797
1798static void
1799fixup_child_record_type (omp_context *ctx)
1800{
1801 tree f, type = ctx->record_type;
1802
56686608 1803 if (!ctx->receiver_decl)
1804 return;
1e8e9920 1805 /* ??? It isn't sufficient to just call remap_type here, because
1806 variably_modified_type_p doesn't work the way we expect for
1807 record types. Testing each field for whether it needs remapping
1808 and creating a new record by hand works, however. */
1767a056 1809 for (f = TYPE_FIELDS (type); f ; f = DECL_CHAIN (f))
1e8e9920 1810 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
1811 break;
1812 if (f)
1813 {
1814 tree name, new_fields = NULL;
1815
1816 type = lang_hooks.types.make_type (RECORD_TYPE);
1817 name = DECL_NAME (TYPE_NAME (ctx->record_type));
e60a6f7b 1818 name = build_decl (DECL_SOURCE_LOCATION (ctx->receiver_decl),
1819 TYPE_DECL, name, type);
1e8e9920 1820 TYPE_NAME (type) = name;
1821
1767a056 1822 for (f = TYPE_FIELDS (ctx->record_type); f ; f = DECL_CHAIN (f))
1e8e9920 1823 {
1824 tree new_f = copy_node (f);
1825 DECL_CONTEXT (new_f) = type;
1826 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
1767a056 1827 DECL_CHAIN (new_f) = new_fields;
75a70cf9 1828 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &ctx->cb, NULL);
1829 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r,
1830 &ctx->cb, NULL);
1831 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
1832 &ctx->cb, NULL);
1e8e9920 1833 new_fields = new_f;
1834
1835 /* Arrange to be able to look up the receiver field
1836 given the sender field. */
1837 splay_tree_insert (ctx->field_map, (splay_tree_key) f,
1838 (splay_tree_value) new_f);
1839 }
1840 TYPE_FIELDS (type) = nreverse (new_fields);
1841 layout_type (type);
1842 }
1843
43895be5 1844 /* In a target region we never modify any of the pointers in *.omp_data_i,
1845 so attempt to help the optimizers. */
1846 if (is_gimple_omp_offloaded (ctx->stmt))
1847 type = build_qualified_type (type, TYPE_QUAL_CONST);
1848
5455b100 1849 TREE_TYPE (ctx->receiver_decl)
1850 = build_qualified_type (build_reference_type (type), TYPE_QUAL_RESTRICT);
1e8e9920 1851}
1852
1853/* Instantiate decls as necessary in CTX to satisfy the data sharing
12dc9a16 1854 specified by CLAUSES. If BASE_POINTERS_RESTRICT, install var field with
1855 restrict. */
1e8e9920 1856
1857static void
12dc9a16 1858scan_sharing_clauses (tree clauses, omp_context *ctx,
1859 bool base_pointers_restrict = false)
1e8e9920 1860{
1861 tree c, decl;
1862 bool scan_array_reductions = false;
1863
1864 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1865 {
1866 bool by_ref;
1867
55d6e7cd 1868 switch (OMP_CLAUSE_CODE (c))
1e8e9920 1869 {
1870 case OMP_CLAUSE_PRIVATE:
1871 decl = OMP_CLAUSE_DECL (c);
fd6481cf 1872 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
1873 goto do_private;
1874 else if (!is_variable_sized (decl))
1e8e9920 1875 install_var_local (decl, ctx);
1876 break;
1877
1878 case OMP_CLAUSE_SHARED:
5fddcf34 1879 decl = OMP_CLAUSE_DECL (c);
bc7bff74 1880 /* Ignore shared directives in teams construct. */
1881 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
5fddcf34 1882 {
1883 /* Global variables don't need to be copied,
1884 the receiver side will use them directly. */
1885 tree odecl = maybe_lookup_decl_in_outer_ctx (decl, ctx);
1886 if (is_global_var (odecl))
1887 break;
1888 insert_decl_map (&ctx->cb, decl, odecl);
1889 break;
1890 }
fd6481cf 1891 gcc_assert (is_taskreg_ctx (ctx));
e7327393 1892 gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl))
1893 || !is_variable_sized (decl));
f49d7bb5 1894 /* Global variables don't need to be copied,
1895 the receiver side will use them directly. */
1896 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1897 break;
43895be5 1898 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
98588013 1899 {
1900 use_pointer_for_field (decl, ctx);
1901 break;
1902 }
1903 by_ref = use_pointer_for_field (decl, NULL);
1904 if ((! TREE_READONLY (decl) && !OMP_CLAUSE_SHARED_READONLY (c))
1e8e9920 1905 || TREE_ADDRESSABLE (decl)
1906 || by_ref
1907 || is_reference (decl))
1908 {
98588013 1909 by_ref = use_pointer_for_field (decl, ctx);
fd6481cf 1910 install_var_field (decl, by_ref, 3, ctx);
1e8e9920 1911 install_var_local (decl, ctx);
1912 break;
1913 }
1914 /* We don't need to copy const scalar vars back. */
55d6e7cd 1915 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
1e8e9920 1916 goto do_private;
1917
43895be5 1918 case OMP_CLAUSE_REDUCTION:
1919 decl = OMP_CLAUSE_DECL (c);
1920 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1921 && TREE_CODE (decl) == MEM_REF)
1922 {
1923 tree t = TREE_OPERAND (decl, 0);
9561765e 1924 if (TREE_CODE (t) == POINTER_PLUS_EXPR)
1925 t = TREE_OPERAND (t, 0);
43895be5 1926 if (TREE_CODE (t) == INDIRECT_REF
1927 || TREE_CODE (t) == ADDR_EXPR)
1928 t = TREE_OPERAND (t, 0);
1929 install_var_local (t, ctx);
1930 if (is_taskreg_ctx (ctx)
1931 && !is_global_var (maybe_lookup_decl_in_outer_ctx (t, ctx))
1932 && !is_variable_sized (t))
1933 {
1934 by_ref = use_pointer_for_field (t, ctx);
1935 install_var_field (t, by_ref, 3, ctx);
1936 }
1937 break;
1938 }
1939 goto do_private;
1940
1e8e9920 1941 case OMP_CLAUSE_LASTPRIVATE:
1942 /* Let the corresponding firstprivate clause create
1943 the variable. */
1944 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1945 break;
1946 /* FALLTHRU */
1947
1948 case OMP_CLAUSE_FIRSTPRIVATE:
3d483a94 1949 case OMP_CLAUSE_LINEAR:
1e8e9920 1950 decl = OMP_CLAUSE_DECL (c);
1951 do_private:
43895be5 1952 if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
1953 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IS_DEVICE_PTR)
1954 && is_gimple_omp_offloaded (ctx->stmt))
1955 {
1956 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
1957 install_var_field (decl, !is_reference (decl), 3, ctx);
1958 else if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1959 install_var_field (decl, true, 3, ctx);
1960 else
1961 install_var_field (decl, false, 3, ctx);
1962 }
1e8e9920 1963 if (is_variable_sized (decl))
1e8e9920 1964 {
fd6481cf 1965 if (is_task_ctx (ctx))
1966 install_var_field (decl, false, 1, ctx);
1967 break;
1968 }
1969 else if (is_taskreg_ctx (ctx))
1970 {
1971 bool global
1972 = is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx));
e8a588af 1973 by_ref = use_pointer_for_field (decl, NULL);
fd6481cf 1974
1975 if (is_task_ctx (ctx)
1976 && (global || by_ref || is_reference (decl)))
1977 {
1978 install_var_field (decl, false, 1, ctx);
1979 if (!global)
1980 install_var_field (decl, by_ref, 2, ctx);
1981 }
1982 else if (!global)
1983 install_var_field (decl, by_ref, 3, ctx);
1e8e9920 1984 }
1985 install_var_local (decl, ctx);
1986 break;
1987
43895be5 1988 case OMP_CLAUSE_USE_DEVICE_PTR:
1989 decl = OMP_CLAUSE_DECL (c);
1990 if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1991 install_var_field (decl, true, 3, ctx);
1992 else
1993 install_var_field (decl, false, 3, ctx);
1994 if (DECL_SIZE (decl)
1995 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1996 {
1997 tree decl2 = DECL_VALUE_EXPR (decl);
1998 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1999 decl2 = TREE_OPERAND (decl2, 0);
2000 gcc_assert (DECL_P (decl2));
2001 install_var_local (decl2, ctx);
2002 }
2003 install_var_local (decl, ctx);
2004 break;
2005
2006 case OMP_CLAUSE_IS_DEVICE_PTR:
2007 decl = OMP_CLAUSE_DECL (c);
2008 goto do_private;
2009
bc7bff74 2010 case OMP_CLAUSE__LOOPTEMP_:
43895be5 2011 gcc_assert (is_taskreg_ctx (ctx));
bc7bff74 2012 decl = OMP_CLAUSE_DECL (c);
2013 install_var_field (decl, false, 3, ctx);
2014 install_var_local (decl, ctx);
2015 break;
2016
1e8e9920 2017 case OMP_CLAUSE_COPYPRIVATE:
1e8e9920 2018 case OMP_CLAUSE_COPYIN:
2019 decl = OMP_CLAUSE_DECL (c);
e8a588af 2020 by_ref = use_pointer_for_field (decl, NULL);
fd6481cf 2021 install_var_field (decl, by_ref, 3, ctx);
1e8e9920 2022 break;
2023
2024 case OMP_CLAUSE_DEFAULT:
2025 ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
2026 break;
2027
2169f33b 2028 case OMP_CLAUSE_FINAL:
1e8e9920 2029 case OMP_CLAUSE_IF:
2030 case OMP_CLAUSE_NUM_THREADS:
bc7bff74 2031 case OMP_CLAUSE_NUM_TEAMS:
2032 case OMP_CLAUSE_THREAD_LIMIT:
2033 case OMP_CLAUSE_DEVICE:
1e8e9920 2034 case OMP_CLAUSE_SCHEDULE:
bc7bff74 2035 case OMP_CLAUSE_DIST_SCHEDULE:
2036 case OMP_CLAUSE_DEPEND:
43895be5 2037 case OMP_CLAUSE_PRIORITY:
2038 case OMP_CLAUSE_GRAINSIZE:
2039 case OMP_CLAUSE_NUM_TASKS:
40750995 2040 case OMP_CLAUSE__CILK_FOR_COUNT_:
ca4c3545 2041 case OMP_CLAUSE_NUM_GANGS:
2042 case OMP_CLAUSE_NUM_WORKERS:
2043 case OMP_CLAUSE_VECTOR_LENGTH:
1e8e9920 2044 if (ctx->outer)
75a70cf9 2045 scan_omp_op (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
1e8e9920 2046 break;
2047
bc7bff74 2048 case OMP_CLAUSE_TO:
2049 case OMP_CLAUSE_FROM:
2050 case OMP_CLAUSE_MAP:
2051 if (ctx->outer)
2052 scan_omp_op (&OMP_CLAUSE_SIZE (c), ctx->outer);
2053 decl = OMP_CLAUSE_DECL (c);
2054 /* Global variables with "omp declare target" attribute
2055 don't need to be copied, the receiver side will use them
c0998828 2056 directly. However, global variables with "omp declare target link"
2057 attribute need to be copied. */
bc7bff74 2058 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
2059 && DECL_P (decl)
9561765e 2060 && ((OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_FIRSTPRIVATE_POINTER
2061 && (OMP_CLAUSE_MAP_KIND (c)
2062 != GOMP_MAP_FIRSTPRIVATE_REFERENCE))
43895be5 2063 || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
bc7bff74 2064 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
c0998828 2065 && varpool_node::get_create (decl)->offloadable
2066 && !lookup_attribute ("omp declare target link",
2067 DECL_ATTRIBUTES (decl)))
bc7bff74 2068 break;
2069 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
ca4c3545 2070 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER)
bc7bff74 2071 {
ca4c3545 2072 /* Ignore GOMP_MAP_POINTER kind for arrays in regions that are
2073 not offloaded; there is nothing to map for those. */
2074 if (!is_gimple_omp_offloaded (ctx->stmt)
c1a114c2 2075 && !POINTER_TYPE_P (TREE_TYPE (decl))
2076 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
bc7bff74 2077 break;
2078 }
43895be5 2079 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
9561765e 2080 && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
2081 || (OMP_CLAUSE_MAP_KIND (c)
2082 == GOMP_MAP_FIRSTPRIVATE_REFERENCE)))
43895be5 2083 {
2084 if (TREE_CODE (decl) == COMPONENT_REF
2085 || (TREE_CODE (decl) == INDIRECT_REF
2086 && TREE_CODE (TREE_OPERAND (decl, 0)) == COMPONENT_REF
2087 && (TREE_CODE (TREE_TYPE (TREE_OPERAND (decl, 0)))
2088 == REFERENCE_TYPE)))
2089 break;
2090 if (DECL_SIZE (decl)
2091 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
2092 {
2093 tree decl2 = DECL_VALUE_EXPR (decl);
2094 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2095 decl2 = TREE_OPERAND (decl2, 0);
2096 gcc_assert (DECL_P (decl2));
2097 install_var_local (decl2, ctx);
2098 }
2099 install_var_local (decl, ctx);
2100 break;
2101 }
bc7bff74 2102 if (DECL_P (decl))
2103 {
2104 if (DECL_SIZE (decl)
2105 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
2106 {
2107 tree decl2 = DECL_VALUE_EXPR (decl);
2108 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2109 decl2 = TREE_OPERAND (decl2, 0);
2110 gcc_assert (DECL_P (decl2));
9561765e 2111 install_var_field (decl2, true, 3, ctx);
bc7bff74 2112 install_var_local (decl2, ctx);
2113 install_var_local (decl, ctx);
2114 }
2115 else
2116 {
2117 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
ca4c3545 2118 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
bc7bff74 2119 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
2120 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
2121 install_var_field (decl, true, 7, ctx);
2122 else
12dc9a16 2123 install_var_field (decl, true, 3, ctx,
2124 base_pointers_restrict);
ca4c3545 2125 if (is_gimple_omp_offloaded (ctx->stmt))
bc7bff74 2126 install_var_local (decl, ctx);
2127 }
2128 }
2129 else
2130 {
2131 tree base = get_base_address (decl);
2132 tree nc = OMP_CLAUSE_CHAIN (c);
2133 if (DECL_P (base)
2134 && nc != NULL_TREE
2135 && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
2136 && OMP_CLAUSE_DECL (nc) == base
ca4c3545 2137 && OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_POINTER
bc7bff74 2138 && integer_zerop (OMP_CLAUSE_SIZE (nc)))
2139 {
2140 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c) = 1;
2141 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (nc) = 1;
2142 }
2143 else
2144 {
691447ab 2145 if (ctx->outer)
2146 {
2147 scan_omp_op (&OMP_CLAUSE_DECL (c), ctx->outer);
2148 decl = OMP_CLAUSE_DECL (c);
2149 }
bc7bff74 2150 gcc_assert (!splay_tree_lookup (ctx->field_map,
2151 (splay_tree_key) decl));
2152 tree field
2153 = build_decl (OMP_CLAUSE_LOCATION (c),
2154 FIELD_DECL, NULL_TREE, ptr_type_node);
2155 DECL_ALIGN (field) = TYPE_ALIGN (ptr_type_node);
2156 insert_field_into_struct (ctx->record_type, field);
2157 splay_tree_insert (ctx->field_map, (splay_tree_key) decl,
2158 (splay_tree_value) field);
2159 }
2160 }
2161 break;
2162
56686608 2163 case OMP_CLAUSE__GRIDDIM_:
2164 if (ctx->outer)
2165 {
2166 scan_omp_op (&OMP_CLAUSE__GRIDDIM__SIZE (c), ctx->outer);
2167 scan_omp_op (&OMP_CLAUSE__GRIDDIM__GROUP (c), ctx->outer);
2168 }
2169 break;
2170
1e8e9920 2171 case OMP_CLAUSE_NOWAIT:
2172 case OMP_CLAUSE_ORDERED:
fd6481cf 2173 case OMP_CLAUSE_COLLAPSE:
2174 case OMP_CLAUSE_UNTIED:
2169f33b 2175 case OMP_CLAUSE_MERGEABLE:
bc7bff74 2176 case OMP_CLAUSE_PROC_BIND:
3d483a94 2177 case OMP_CLAUSE_SAFELEN:
43895be5 2178 case OMP_CLAUSE_SIMDLEN:
2179 case OMP_CLAUSE_THREADS:
2180 case OMP_CLAUSE_SIMD:
2181 case OMP_CLAUSE_NOGROUP:
2182 case OMP_CLAUSE_DEFAULTMAP:
ca4c3545 2183 case OMP_CLAUSE_ASYNC:
2184 case OMP_CLAUSE_WAIT:
2185 case OMP_CLAUSE_GANG:
2186 case OMP_CLAUSE_WORKER:
2187 case OMP_CLAUSE_VECTOR:
ef014f95 2188 case OMP_CLAUSE_TILE:
f4f5b4b4 2189 case OMP_CLAUSE_INDEPENDENT:
2190 case OMP_CLAUSE_AUTO:
2191 case OMP_CLAUSE_SEQ:
1e8e9920 2192 break;
2193
bc7bff74 2194 case OMP_CLAUSE_ALIGNED:
2195 decl = OMP_CLAUSE_DECL (c);
2196 if (is_global_var (decl)
2197 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
2198 install_var_local (decl, ctx);
2199 break;
2200
ca4c3545 2201 case OMP_CLAUSE_DEVICE_RESIDENT:
ca4c3545 2202 case OMP_CLAUSE__CACHE_:
ca4c3545 2203 sorry ("Clause not supported yet");
2204 break;
2205
1e8e9920 2206 default:
2207 gcc_unreachable ();
2208 }
2209 }
2210
2211 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2212 {
55d6e7cd 2213 switch (OMP_CLAUSE_CODE (c))
1e8e9920 2214 {
2215 case OMP_CLAUSE_LASTPRIVATE:
2216 /* Let the corresponding firstprivate clause create
2217 the variable. */
75a70cf9 2218 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
fd6481cf 2219 scan_array_reductions = true;
1e8e9920 2220 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
2221 break;
2222 /* FALLTHRU */
2223
1e8e9920 2224 case OMP_CLAUSE_FIRSTPRIVATE:
ca4c3545 2225 case OMP_CLAUSE_PRIVATE:
3d483a94 2226 case OMP_CLAUSE_LINEAR:
43895be5 2227 case OMP_CLAUSE_IS_DEVICE_PTR:
1e8e9920 2228 decl = OMP_CLAUSE_DECL (c);
2229 if (is_variable_sized (decl))
43895be5 2230 {
2231 if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
2232 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IS_DEVICE_PTR)
2233 && is_gimple_omp_offloaded (ctx->stmt))
2234 {
2235 tree decl2 = DECL_VALUE_EXPR (decl);
2236 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2237 decl2 = TREE_OPERAND (decl2, 0);
2238 gcc_assert (DECL_P (decl2));
2239 install_var_local (decl2, ctx);
2240 fixup_remapped_decl (decl2, ctx, false);
2241 }
2242 install_var_local (decl, ctx);
2243 }
1e8e9920 2244 fixup_remapped_decl (decl, ctx,
55d6e7cd 2245 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
1e8e9920 2246 && OMP_CLAUSE_PRIVATE_DEBUG (c));
43895be5 2247 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
2248 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
1e8e9920 2249 scan_array_reductions = true;
43895be5 2250 break;
2251
2252 case OMP_CLAUSE_REDUCTION:
2253 decl = OMP_CLAUSE_DECL (c);
2254 if (TREE_CODE (decl) != MEM_REF)
2255 {
2256 if (is_variable_sized (decl))
2257 install_var_local (decl, ctx);
2258 fixup_remapped_decl (decl, ctx, false);
2259 }
2260 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2b536a17 2261 scan_array_reductions = true;
1e8e9920 2262 break;
2263
2264 case OMP_CLAUSE_SHARED:
bc7bff74 2265 /* Ignore shared directives in teams construct. */
2266 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
2267 break;
1e8e9920 2268 decl = OMP_CLAUSE_DECL (c);
43895be5 2269 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
2270 break;
2271 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
2272 {
2273 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl,
2274 ctx->outer)))
2275 break;
2276 bool by_ref = use_pointer_for_field (decl, ctx);
2277 install_var_field (decl, by_ref, 11, ctx);
2278 break;
2279 }
2280 fixup_remapped_decl (decl, ctx, false);
1e8e9920 2281 break;
2282
bc7bff74 2283 case OMP_CLAUSE_MAP:
ca4c3545 2284 if (!is_gimple_omp_offloaded (ctx->stmt))
bc7bff74 2285 break;
2286 decl = OMP_CLAUSE_DECL (c);
2287 if (DECL_P (decl)
9561765e 2288 && ((OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_FIRSTPRIVATE_POINTER
2289 && (OMP_CLAUSE_MAP_KIND (c)
2290 != GOMP_MAP_FIRSTPRIVATE_REFERENCE))
43895be5 2291 || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
bc7bff74 2292 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
b0c5e347 2293 && varpool_node::get_create (decl)->offloadable)
bc7bff74 2294 break;
2295 if (DECL_P (decl))
2296 {
43895be5 2297 if ((OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
2298 || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER)
bc7bff74 2299 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
2300 && !COMPLETE_TYPE_P (TREE_TYPE (decl)))
2301 {
2302 tree new_decl = lookup_decl (decl, ctx);
2303 TREE_TYPE (new_decl)
2304 = remap_type (TREE_TYPE (decl), &ctx->cb);
2305 }
2306 else if (DECL_SIZE (decl)
2307 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
2308 {
2309 tree decl2 = DECL_VALUE_EXPR (decl);
2310 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2311 decl2 = TREE_OPERAND (decl2, 0);
2312 gcc_assert (DECL_P (decl2));
2313 fixup_remapped_decl (decl2, ctx, false);
2314 fixup_remapped_decl (decl, ctx, true);
2315 }
2316 else
2317 fixup_remapped_decl (decl, ctx, false);
2318 }
2319 break;
2320
1e8e9920 2321 case OMP_CLAUSE_COPYPRIVATE:
2322 case OMP_CLAUSE_COPYIN:
2323 case OMP_CLAUSE_DEFAULT:
2324 case OMP_CLAUSE_IF:
2325 case OMP_CLAUSE_NUM_THREADS:
bc7bff74 2326 case OMP_CLAUSE_NUM_TEAMS:
2327 case OMP_CLAUSE_THREAD_LIMIT:
2328 case OMP_CLAUSE_DEVICE:
1e8e9920 2329 case OMP_CLAUSE_SCHEDULE:
bc7bff74 2330 case OMP_CLAUSE_DIST_SCHEDULE:
1e8e9920 2331 case OMP_CLAUSE_NOWAIT:
2332 case OMP_CLAUSE_ORDERED:
fd6481cf 2333 case OMP_CLAUSE_COLLAPSE:
2334 case OMP_CLAUSE_UNTIED:
2169f33b 2335 case OMP_CLAUSE_FINAL:
2336 case OMP_CLAUSE_MERGEABLE:
bc7bff74 2337 case OMP_CLAUSE_PROC_BIND:
3d483a94 2338 case OMP_CLAUSE_SAFELEN:
43895be5 2339 case OMP_CLAUSE_SIMDLEN:
bc7bff74 2340 case OMP_CLAUSE_ALIGNED:
2341 case OMP_CLAUSE_DEPEND:
2342 case OMP_CLAUSE__LOOPTEMP_:
2343 case OMP_CLAUSE_TO:
2344 case OMP_CLAUSE_FROM:
43895be5 2345 case OMP_CLAUSE_PRIORITY:
2346 case OMP_CLAUSE_GRAINSIZE:
2347 case OMP_CLAUSE_NUM_TASKS:
2348 case OMP_CLAUSE_THREADS:
2349 case OMP_CLAUSE_SIMD:
2350 case OMP_CLAUSE_NOGROUP:
2351 case OMP_CLAUSE_DEFAULTMAP:
2352 case OMP_CLAUSE_USE_DEVICE_PTR:
40750995 2353 case OMP_CLAUSE__CILK_FOR_COUNT_:
ca4c3545 2354 case OMP_CLAUSE_ASYNC:
2355 case OMP_CLAUSE_WAIT:
2356 case OMP_CLAUSE_NUM_GANGS:
2357 case OMP_CLAUSE_NUM_WORKERS:
2358 case OMP_CLAUSE_VECTOR_LENGTH:
2359 case OMP_CLAUSE_GANG:
2360 case OMP_CLAUSE_WORKER:
2361 case OMP_CLAUSE_VECTOR:
ef014f95 2362 case OMP_CLAUSE_TILE:
f4f5b4b4 2363 case OMP_CLAUSE_INDEPENDENT:
2364 case OMP_CLAUSE_AUTO:
2365 case OMP_CLAUSE_SEQ:
56686608 2366 case OMP_CLAUSE__GRIDDIM_:
ca4c3545 2367 break;
2368
2369 case OMP_CLAUSE_DEVICE_RESIDENT:
ca4c3545 2370 case OMP_CLAUSE__CACHE_:
ca4c3545 2371 sorry ("Clause not supported yet");
1e8e9920 2372 break;
2373
2374 default:
2375 gcc_unreachable ();
2376 }
2377 }
2378
ca4c3545 2379 gcc_checking_assert (!scan_array_reductions
2380 || !is_gimple_omp_oacc (ctx->stmt));
1e8e9920 2381 if (scan_array_reductions)
2382 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
55d6e7cd 2383 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1e8e9920 2384 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2385 {
ab129075 2386 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
2387 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
1e8e9920 2388 }
fd6481cf 2389 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
75a70cf9 2390 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
ab129075 2391 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
2b536a17 2392 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
2393 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
2394 scan_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
1e8e9920 2395}
2396
40750995 2397/* Create a new name for omp child function. Returns an identifier. If
2398 IS_CILK_FOR is true then the suffix for the child function is
2399 "_cilk_for_fn." */
1e8e9920 2400
1e8e9920 2401static tree
40750995 2402create_omp_child_function_name (bool task_copy, bool is_cilk_for)
1e8e9920 2403{
40750995 2404 if (is_cilk_for)
2405 return clone_function_name (current_function_decl, "_cilk_for_fn");
2406 return clone_function_name (current_function_decl,
2407 task_copy ? "_omp_cpyfn" : "_omp_fn");
2408}
2409
2410/* Returns the type of the induction variable for the child function for
2411 _Cilk_for and the types for _high and _low variables based on TYPE. */
2412
2413static tree
2414cilk_for_check_loop_diff_type (tree type)
2415{
2416 if (TYPE_PRECISION (type) <= TYPE_PRECISION (uint32_type_node))
2417 {
2418 if (TYPE_UNSIGNED (type))
2419 return uint32_type_node;
2420 else
2421 return integer_type_node;
2422 }
2423 else
2424 {
2425 if (TYPE_UNSIGNED (type))
2426 return uint64_type_node;
2427 else
2428 return long_long_integer_type_node;
2429 }
1e8e9920 2430}
2431
2432/* Build a decl for the omp child function. It'll not contain a body
2433 yet, just the bare decl. */
2434
2435static void
fd6481cf 2436create_omp_child_function (omp_context *ctx, bool task_copy)
1e8e9920 2437{
2438 tree decl, type, name, t;
2439
40750995 2440 tree cilk_for_count
2441 = (flag_cilkplus && gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2442 ? find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
2443 OMP_CLAUSE__CILK_FOR_COUNT_) : NULL_TREE;
2444 tree cilk_var_type = NULL_TREE;
2445
2446 name = create_omp_child_function_name (task_copy,
2447 cilk_for_count != NULL_TREE);
fd6481cf 2448 if (task_copy)
2449 type = build_function_type_list (void_type_node, ptr_type_node,
2450 ptr_type_node, NULL_TREE);
40750995 2451 else if (cilk_for_count)
2452 {
2453 type = TREE_TYPE (OMP_CLAUSE_OPERAND (cilk_for_count, 0));
2454 cilk_var_type = cilk_for_check_loop_diff_type (type);
2455 type = build_function_type_list (void_type_node, ptr_type_node,
2456 cilk_var_type, cilk_var_type, NULL_TREE);
2457 }
fd6481cf 2458 else
2459 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
1e8e9920 2460
40750995 2461 decl = build_decl (gimple_location (ctx->stmt), FUNCTION_DECL, name, type);
1e8e9920 2462
ca4c3545 2463 gcc_checking_assert (!is_gimple_omp_oacc (ctx->stmt)
2464 || !task_copy);
fd6481cf 2465 if (!task_copy)
2466 ctx->cb.dst_fn = decl;
2467 else
75a70cf9 2468 gimple_omp_task_set_copy_fn (ctx->stmt, decl);
1e8e9920 2469
2470 TREE_STATIC (decl) = 1;
2471 TREE_USED (decl) = 1;
2472 DECL_ARTIFICIAL (decl) = 1;
2473 DECL_IGNORED_P (decl) = 0;
2474 TREE_PUBLIC (decl) = 0;
2475 DECL_UNINLINABLE (decl) = 1;
2476 DECL_EXTERNAL (decl) = 0;
2477 DECL_CONTEXT (decl) = NULL_TREE;
773c5ba7 2478 DECL_INITIAL (decl) = make_node (BLOCK);
b0c5e347 2479 if (cgraph_node::get (current_function_decl)->offloadable)
2480 cgraph_node::get_create (decl)->offloadable = 1;
bc7bff74 2481 else
2482 {
2483 omp_context *octx;
2484 for (octx = ctx; octx; octx = octx->outer)
ca4c3545 2485 if (is_gimple_omp_offloaded (octx->stmt))
bc7bff74 2486 {
b0c5e347 2487 cgraph_node::get_create (decl)->offloadable = 1;
5f3001a9 2488 if (ENABLE_OFFLOADING)
2489 g->have_offload = true;
2490
bc7bff74 2491 break;
2492 }
2493 }
1e8e9920 2494
ec12b31a 2495 if (cgraph_node::get_create (decl)->offloadable
2496 && !lookup_attribute ("omp declare target",
2497 DECL_ATTRIBUTES (current_function_decl)))
2498 DECL_ATTRIBUTES (decl)
2499 = tree_cons (get_identifier ("omp target entrypoint"),
2500 NULL_TREE, DECL_ATTRIBUTES (decl));
2501
e60a6f7b 2502 t = build_decl (DECL_SOURCE_LOCATION (decl),
2503 RESULT_DECL, NULL_TREE, void_type_node);
1e8e9920 2504 DECL_ARTIFICIAL (t) = 1;
2505 DECL_IGNORED_P (t) = 1;
8e5b4ed6 2506 DECL_CONTEXT (t) = decl;
1e8e9920 2507 DECL_RESULT (decl) = t;
2508
40750995 2509 /* _Cilk_for's child function requires two extra parameters called
2510 __low and __high that are set the by Cilk runtime when it calls this
2511 function. */
2512 if (cilk_for_count)
2513 {
2514 t = build_decl (DECL_SOURCE_LOCATION (decl),
2515 PARM_DECL, get_identifier ("__high"), cilk_var_type);
2516 DECL_ARTIFICIAL (t) = 1;
2517 DECL_NAMELESS (t) = 1;
2518 DECL_ARG_TYPE (t) = ptr_type_node;
2519 DECL_CONTEXT (t) = current_function_decl;
2520 TREE_USED (t) = 1;
2521 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2522 DECL_ARGUMENTS (decl) = t;
2523
2524 t = build_decl (DECL_SOURCE_LOCATION (decl),
2525 PARM_DECL, get_identifier ("__low"), cilk_var_type);
2526 DECL_ARTIFICIAL (t) = 1;
2527 DECL_NAMELESS (t) = 1;
2528 DECL_ARG_TYPE (t) = ptr_type_node;
2529 DECL_CONTEXT (t) = current_function_decl;
2530 TREE_USED (t) = 1;
2531 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2532 DECL_ARGUMENTS (decl) = t;
2533 }
2534
2535 tree data_name = get_identifier (".omp_data_i");
2536 t = build_decl (DECL_SOURCE_LOCATION (decl), PARM_DECL, data_name,
2537 ptr_type_node);
1e8e9920 2538 DECL_ARTIFICIAL (t) = 1;
84bfaaeb 2539 DECL_NAMELESS (t) = 1;
1e8e9920 2540 DECL_ARG_TYPE (t) = ptr_type_node;
773c5ba7 2541 DECL_CONTEXT (t) = current_function_decl;
1e8e9920 2542 TREE_USED (t) = 1;
43895be5 2543 TREE_READONLY (t) = 1;
40750995 2544 if (cilk_for_count)
2545 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
1e8e9920 2546 DECL_ARGUMENTS (decl) = t;
fd6481cf 2547 if (!task_copy)
2548 ctx->receiver_decl = t;
2549 else
2550 {
e60a6f7b 2551 t = build_decl (DECL_SOURCE_LOCATION (decl),
2552 PARM_DECL, get_identifier (".omp_data_o"),
fd6481cf 2553 ptr_type_node);
2554 DECL_ARTIFICIAL (t) = 1;
84bfaaeb 2555 DECL_NAMELESS (t) = 1;
fd6481cf 2556 DECL_ARG_TYPE (t) = ptr_type_node;
2557 DECL_CONTEXT (t) = current_function_decl;
2558 TREE_USED (t) = 1;
86f2ad37 2559 TREE_ADDRESSABLE (t) = 1;
1767a056 2560 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
fd6481cf 2561 DECL_ARGUMENTS (decl) = t;
2562 }
1e8e9920 2563
48e1416a 2564 /* Allocate memory for the function structure. The call to
773c5ba7 2565 allocate_struct_function clobbers CFUN, so we need to restore
1e8e9920 2566 it afterward. */
87d4aa85 2567 push_struct_function (decl);
75a70cf9 2568 cfun->function_end_locus = gimple_location (ctx->stmt);
87d4aa85 2569 pop_cfun ();
1e8e9920 2570}
2571
bc7bff74 2572/* Callback for walk_gimple_seq. Check if combined parallel
2573 contains gimple_omp_for_combined_into_p OMP_FOR. */
2574
2575static tree
2576find_combined_for (gimple_stmt_iterator *gsi_p,
2577 bool *handled_ops_p,
2578 struct walk_stmt_info *wi)
2579{
42acab1c 2580 gimple *stmt = gsi_stmt (*gsi_p);
bc7bff74 2581
2582 *handled_ops_p = true;
2583 switch (gimple_code (stmt))
2584 {
2585 WALK_SUBSTMTS;
2586
2587 case GIMPLE_OMP_FOR:
2588 if (gimple_omp_for_combined_into_p (stmt)
43895be5 2589 && gimple_omp_for_kind (stmt)
2590 == *(const enum gf_mask *) (wi->info))
bc7bff74 2591 {
2592 wi->info = stmt;
2593 return integer_zero_node;
2594 }
2595 break;
2596 default:
2597 break;
2598 }
2599 return NULL;
2600}
2601
43895be5 2602/* Add _LOOPTEMP_ clauses on OpenMP parallel or task. */
2603
2604static void
2605add_taskreg_looptemp_clauses (enum gf_mask msk, gimple *stmt,
2606 omp_context *outer_ctx)
2607{
2608 struct walk_stmt_info wi;
2609
2610 memset (&wi, 0, sizeof (wi));
2611 wi.val_only = true;
2612 wi.info = (void *) &msk;
2613 walk_gimple_seq (gimple_omp_body (stmt), find_combined_for, NULL, &wi);
2614 if (wi.info != (void *) &msk)
2615 {
2616 gomp_for *for_stmt = as_a <gomp_for *> ((gimple *) wi.info);
2617 struct omp_for_data fd;
2618 extract_omp_for_data (for_stmt, &fd, NULL);
2619 /* We need two temporaries with fd.loop.v type (istart/iend)
2620 and then (fd.collapse - 1) temporaries with the same
2621 type for count2 ... countN-1 vars if not constant. */
2622 size_t count = 2, i;
2623 tree type = fd.iter_type;
2624 if (fd.collapse > 1
2625 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
2626 {
2627 count += fd.collapse - 1;
9561765e 2628 /* If there are lastprivate clauses on the inner
43895be5 2629 GIMPLE_OMP_FOR, add one more temporaries for the total number
2630 of iterations (product of count1 ... countN-1). */
9561765e 2631 if (find_omp_clause (gimple_omp_for_clauses (for_stmt),
2632 OMP_CLAUSE_LASTPRIVATE))
2633 count++;
2634 else if (msk == GF_OMP_FOR_KIND_FOR
2635 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
2636 OMP_CLAUSE_LASTPRIVATE))
43895be5 2637 count++;
2638 }
2639 for (i = 0; i < count; i++)
2640 {
2641 tree temp = create_tmp_var (type);
2642 tree c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
2643 insert_decl_map (&outer_ctx->cb, temp, temp);
2644 OMP_CLAUSE_DECL (c) = temp;
2645 OMP_CLAUSE_CHAIN (c) = gimple_omp_taskreg_clauses (stmt);
2646 gimple_omp_taskreg_set_clauses (stmt, c);
2647 }
2648 }
2649}
2650
1e8e9920 2651/* Scan an OpenMP parallel directive. */
2652
2653static void
75a70cf9 2654scan_omp_parallel (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
1e8e9920 2655{
2656 omp_context *ctx;
2657 tree name;
1a91d914 2658 gomp_parallel *stmt = as_a <gomp_parallel *> (gsi_stmt (*gsi));
1e8e9920 2659
2660 /* Ignore parallel directives with empty bodies, unless there
2661 are copyin clauses. */
2662 if (optimize > 0
75a70cf9 2663 && empty_body_p (gimple_omp_body (stmt))
2664 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
2665 OMP_CLAUSE_COPYIN) == NULL)
1e8e9920 2666 {
75a70cf9 2667 gsi_replace (gsi, gimple_build_nop (), false);
1e8e9920 2668 return;
2669 }
2670
bc7bff74 2671 if (gimple_omp_parallel_combined_p (stmt))
43895be5 2672 add_taskreg_looptemp_clauses (GF_OMP_FOR_KIND_FOR, stmt, outer_ctx);
bc7bff74 2673
75a70cf9 2674 ctx = new_omp_context (stmt, outer_ctx);
37eaded9 2675 taskreg_contexts.safe_push (ctx);
fd6481cf 2676 if (taskreg_nesting_level > 1)
773c5ba7 2677 ctx->is_nested = true;
1e8e9920 2678 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1e8e9920 2679 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2680 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
1e8e9920 2681 name = create_tmp_var_name (".omp_data_s");
e60a6f7b 2682 name = build_decl (gimple_location (stmt),
2683 TYPE_DECL, name, ctx->record_type);
84bfaaeb 2684 DECL_ARTIFICIAL (name) = 1;
2685 DECL_NAMELESS (name) = 1;
1e8e9920 2686 TYPE_NAME (ctx->record_type) = name;
240131b5 2687 TYPE_ARTIFICIAL (ctx->record_type) = 1;
56686608 2688 if (!gimple_omp_parallel_grid_phony (stmt))
2689 {
2690 create_omp_child_function (ctx, false);
2691 gimple_omp_parallel_set_child_fn (stmt, ctx->cb.dst_fn);
2692 }
1e8e9920 2693
75a70cf9 2694 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt), ctx);
ab129075 2695 scan_omp (gimple_omp_body_ptr (stmt), ctx);
1e8e9920 2696
2697 if (TYPE_FIELDS (ctx->record_type) == NULL)
2698 ctx->record_type = ctx->receiver_decl = NULL;
1e8e9920 2699}
2700
fd6481cf 2701/* Scan an OpenMP task directive. */
2702
2703static void
75a70cf9 2704scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
fd6481cf 2705{
2706 omp_context *ctx;
75a70cf9 2707 tree name, t;
1a91d914 2708 gomp_task *stmt = as_a <gomp_task *> (gsi_stmt (*gsi));
fd6481cf 2709
2710 /* Ignore task directives with empty bodies. */
2711 if (optimize > 0
75a70cf9 2712 && empty_body_p (gimple_omp_body (stmt)))
fd6481cf 2713 {
75a70cf9 2714 gsi_replace (gsi, gimple_build_nop (), false);
fd6481cf 2715 return;
2716 }
2717
43895be5 2718 if (gimple_omp_task_taskloop_p (stmt))
2719 add_taskreg_looptemp_clauses (GF_OMP_FOR_KIND_TASKLOOP, stmt, outer_ctx);
2720
75a70cf9 2721 ctx = new_omp_context (stmt, outer_ctx);
37eaded9 2722 taskreg_contexts.safe_push (ctx);
fd6481cf 2723 if (taskreg_nesting_level > 1)
2724 ctx->is_nested = true;
2725 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2726 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2727 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2728 name = create_tmp_var_name (".omp_data_s");
e60a6f7b 2729 name = build_decl (gimple_location (stmt),
2730 TYPE_DECL, name, ctx->record_type);
84bfaaeb 2731 DECL_ARTIFICIAL (name) = 1;
2732 DECL_NAMELESS (name) = 1;
fd6481cf 2733 TYPE_NAME (ctx->record_type) = name;
240131b5 2734 TYPE_ARTIFICIAL (ctx->record_type) = 1;
fd6481cf 2735 create_omp_child_function (ctx, false);
75a70cf9 2736 gimple_omp_task_set_child_fn (stmt, ctx->cb.dst_fn);
fd6481cf 2737
75a70cf9 2738 scan_sharing_clauses (gimple_omp_task_clauses (stmt), ctx);
fd6481cf 2739
2740 if (ctx->srecord_type)
2741 {
2742 name = create_tmp_var_name (".omp_data_a");
e60a6f7b 2743 name = build_decl (gimple_location (stmt),
2744 TYPE_DECL, name, ctx->srecord_type);
84bfaaeb 2745 DECL_ARTIFICIAL (name) = 1;
2746 DECL_NAMELESS (name) = 1;
fd6481cf 2747 TYPE_NAME (ctx->srecord_type) = name;
240131b5 2748 TYPE_ARTIFICIAL (ctx->srecord_type) = 1;
fd6481cf 2749 create_omp_child_function (ctx, true);
2750 }
2751
ab129075 2752 scan_omp (gimple_omp_body_ptr (stmt), ctx);
fd6481cf 2753
2754 if (TYPE_FIELDS (ctx->record_type) == NULL)
2755 {
2756 ctx->record_type = ctx->receiver_decl = NULL;
75a70cf9 2757 t = build_int_cst (long_integer_type_node, 0);
2758 gimple_omp_task_set_arg_size (stmt, t);
2759 t = build_int_cst (long_integer_type_node, 1);
2760 gimple_omp_task_set_arg_align (stmt, t);
fd6481cf 2761 }
37eaded9 2762}
2763
2764
2765/* If any decls have been made addressable during scan_omp,
2766 adjust their fields if needed, and layout record types
2767 of parallel/task constructs. */
2768
2769static void
2770finish_taskreg_scan (omp_context *ctx)
2771{
2772 if (ctx->record_type == NULL_TREE)
2773 return;
2774
2775 /* If any task_shared_vars were needed, verify all
2776 OMP_CLAUSE_SHARED clauses on GIMPLE_OMP_{PARALLEL,TASK}
2777 statements if use_pointer_for_field hasn't changed
2778 because of that. If it did, update field types now. */
2779 if (task_shared_vars)
2780 {
2781 tree c;
2782
2783 for (c = gimple_omp_taskreg_clauses (ctx->stmt);
2784 c; c = OMP_CLAUSE_CHAIN (c))
43895be5 2785 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
2786 && !OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
37eaded9 2787 {
2788 tree decl = OMP_CLAUSE_DECL (c);
2789
2790 /* Global variables don't need to be copied,
2791 the receiver side will use them directly. */
2792 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
2793 continue;
2794 if (!bitmap_bit_p (task_shared_vars, DECL_UID (decl))
2795 || !use_pointer_for_field (decl, ctx))
2796 continue;
2797 tree field = lookup_field (decl, ctx);
2798 if (TREE_CODE (TREE_TYPE (field)) == POINTER_TYPE
2799 && TREE_TYPE (TREE_TYPE (field)) == TREE_TYPE (decl))
2800 continue;
2801 TREE_TYPE (field) = build_pointer_type (TREE_TYPE (decl));
2802 TREE_THIS_VOLATILE (field) = 0;
2803 DECL_USER_ALIGN (field) = 0;
2804 DECL_ALIGN (field) = TYPE_ALIGN (TREE_TYPE (field));
2805 if (TYPE_ALIGN (ctx->record_type) < DECL_ALIGN (field))
2806 TYPE_ALIGN (ctx->record_type) = DECL_ALIGN (field);
2807 if (ctx->srecord_type)
2808 {
2809 tree sfield = lookup_sfield (decl, ctx);
2810 TREE_TYPE (sfield) = TREE_TYPE (field);
2811 TREE_THIS_VOLATILE (sfield) = 0;
2812 DECL_USER_ALIGN (sfield) = 0;
2813 DECL_ALIGN (sfield) = DECL_ALIGN (field);
2814 if (TYPE_ALIGN (ctx->srecord_type) < DECL_ALIGN (sfield))
2815 TYPE_ALIGN (ctx->srecord_type) = DECL_ALIGN (sfield);
2816 }
2817 }
2818 }
2819
2820 if (gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2821 {
2822 layout_type (ctx->record_type);
2823 fixup_child_record_type (ctx);
2824 }
fd6481cf 2825 else
2826 {
37eaded9 2827 location_t loc = gimple_location (ctx->stmt);
fd6481cf 2828 tree *p, vla_fields = NULL_TREE, *q = &vla_fields;
2829 /* Move VLA fields to the end. */
2830 p = &TYPE_FIELDS (ctx->record_type);
2831 while (*p)
2832 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p))
2833 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p))))
2834 {
2835 *q = *p;
2836 *p = TREE_CHAIN (*p);
2837 TREE_CHAIN (*q) = NULL_TREE;
2838 q = &TREE_CHAIN (*q);
2839 }
2840 else
1767a056 2841 p = &DECL_CHAIN (*p);
fd6481cf 2842 *p = vla_fields;
43895be5 2843 if (gimple_omp_task_taskloop_p (ctx->stmt))
2844 {
2845 /* Move fields corresponding to first and second _looptemp_
2846 clause first. There are filled by GOMP_taskloop
2847 and thus need to be in specific positions. */
2848 tree c1 = gimple_omp_task_clauses (ctx->stmt);
2849 c1 = find_omp_clause (c1, OMP_CLAUSE__LOOPTEMP_);
2850 tree c2 = find_omp_clause (OMP_CLAUSE_CHAIN (c1),
2851 OMP_CLAUSE__LOOPTEMP_);
2852 tree f1 = lookup_field (OMP_CLAUSE_DECL (c1), ctx);
2853 tree f2 = lookup_field (OMP_CLAUSE_DECL (c2), ctx);
2854 p = &TYPE_FIELDS (ctx->record_type);
2855 while (*p)
2856 if (*p == f1 || *p == f2)
2857 *p = DECL_CHAIN (*p);
2858 else
2859 p = &DECL_CHAIN (*p);
2860 DECL_CHAIN (f1) = f2;
2861 DECL_CHAIN (f2) = TYPE_FIELDS (ctx->record_type);
2862 TYPE_FIELDS (ctx->record_type) = f1;
2863 if (ctx->srecord_type)
2864 {
2865 f1 = lookup_sfield (OMP_CLAUSE_DECL (c1), ctx);
2866 f2 = lookup_sfield (OMP_CLAUSE_DECL (c2), ctx);
2867 p = &TYPE_FIELDS (ctx->srecord_type);
2868 while (*p)
2869 if (*p == f1 || *p == f2)
2870 *p = DECL_CHAIN (*p);
2871 else
2872 p = &DECL_CHAIN (*p);
2873 DECL_CHAIN (f1) = f2;
2874 DECL_CHAIN (f2) = TYPE_FIELDS (ctx->srecord_type);
2875 TYPE_FIELDS (ctx->srecord_type) = f1;
2876 }
2877 }
fd6481cf 2878 layout_type (ctx->record_type);
2879 fixup_child_record_type (ctx);
2880 if (ctx->srecord_type)
2881 layout_type (ctx->srecord_type);
37eaded9 2882 tree t = fold_convert_loc (loc, long_integer_type_node,
2883 TYPE_SIZE_UNIT (ctx->record_type));
2884 gimple_omp_task_set_arg_size (ctx->stmt, t);
75a70cf9 2885 t = build_int_cst (long_integer_type_node,
fd6481cf 2886 TYPE_ALIGN_UNIT (ctx->record_type));
37eaded9 2887 gimple_omp_task_set_arg_align (ctx->stmt, t);
fd6481cf 2888 }
2889}
2890
a8e785ba 2891/* Find the enclosing offload context. */
1e8e9920 2892
ca4c3545 2893static omp_context *
2894enclosing_target_ctx (omp_context *ctx)
2895{
a8e785ba 2896 for (; ctx; ctx = ctx->outer)
2897 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET)
2898 break;
2899
ca4c3545 2900 return ctx;
2901}
2902
a8e785ba 2903/* Return true if ctx is part of an oacc kernels region. */
2904
ca4c3545 2905static bool
a8e785ba 2906ctx_in_oacc_kernels_region (omp_context *ctx)
ca4c3545 2907{
a8e785ba 2908 for (;ctx != NULL; ctx = ctx->outer)
2909 {
2910 gimple *stmt = ctx->stmt;
2911 if (gimple_code (stmt) == GIMPLE_OMP_TARGET
2912 && gimple_omp_target_kind (stmt) == GF_OMP_TARGET_KIND_OACC_KERNELS)
2913 return true;
2914 }
2915
2916 return false;
2917}
2918
2919/* Check the parallelism clauses inside a kernels regions.
2920 Until kernels handling moves to use the same loop indirection
2921 scheme as parallel, we need to do this checking early. */
2922
2923static unsigned
2924check_oacc_kernel_gwv (gomp_for *stmt, omp_context *ctx)
2925{
2926 bool checking = true;
2927 unsigned outer_mask = 0;
2928 unsigned this_mask = 0;
2929 bool has_seq = false, has_auto = false;
2930
2931 if (ctx->outer)
2932 outer_mask = check_oacc_kernel_gwv (NULL, ctx->outer);
2933 if (!stmt)
2934 {
2935 checking = false;
2936 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR)
2937 return outer_mask;
2938 stmt = as_a <gomp_for *> (ctx->stmt);
2939 }
2940
2941 for (tree c = gimple_omp_for_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
2942 {
2943 switch (OMP_CLAUSE_CODE (c))
2944 {
2945 case OMP_CLAUSE_GANG:
2946 this_mask |= GOMP_DIM_MASK (GOMP_DIM_GANG);
2947 break;
2948 case OMP_CLAUSE_WORKER:
2949 this_mask |= GOMP_DIM_MASK (GOMP_DIM_WORKER);
2950 break;
2951 case OMP_CLAUSE_VECTOR:
2952 this_mask |= GOMP_DIM_MASK (GOMP_DIM_VECTOR);
2953 break;
2954 case OMP_CLAUSE_SEQ:
2955 has_seq = true;
2956 break;
2957 case OMP_CLAUSE_AUTO:
2958 has_auto = true;
2959 break;
2960 default:
2961 break;
2962 }
2963 }
2964
2965 if (checking)
2966 {
2967 if (has_seq && (this_mask || has_auto))
2968 error_at (gimple_location (stmt), "%<seq%> overrides other"
2969 " OpenACC loop specifiers");
2970 else if (has_auto && this_mask)
2971 error_at (gimple_location (stmt), "%<auto%> conflicts with other"
2972 " OpenACC loop specifiers");
2973
2974 if (this_mask & outer_mask)
2975 error_at (gimple_location (stmt), "inner loop uses same"
2976 " OpenACC parallelism as containing loop");
2977 }
2978
2979 return outer_mask | this_mask;
ca4c3545 2980}
2981
2982/* Scan a GIMPLE_OMP_FOR. */
1e8e9920 2983
2984static void
1a91d914 2985scan_omp_for (gomp_for *stmt, omp_context *outer_ctx)
1e8e9920 2986{
773c5ba7 2987 omp_context *ctx;
75a70cf9 2988 size_t i;
ca4c3545 2989 tree clauses = gimple_omp_for_clauses (stmt);
2990
773c5ba7 2991 ctx = new_omp_context (stmt, outer_ctx);
1e8e9920 2992
ca4c3545 2993 if (is_gimple_omp_oacc (stmt))
2994 {
a8e785ba 2995 omp_context *tgt = enclosing_target_ctx (outer_ctx);
2996
2997 if (!tgt || is_oacc_parallel (tgt))
2998 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2999 {
3000 char const *check = NULL;
3001
3002 switch (OMP_CLAUSE_CODE (c))
3003 {
3004 case OMP_CLAUSE_GANG:
3005 check = "gang";
3006 break;
3007
3008 case OMP_CLAUSE_WORKER:
3009 check = "worker";
3010 break;
3011
3012 case OMP_CLAUSE_VECTOR:
3013 check = "vector";
3014 break;
3015
3016 default:
3017 break;
3018 }
3019
3020 if (check && OMP_CLAUSE_OPERAND (c, 0))
3021 error_at (gimple_location (stmt),
3022 "argument not permitted on %qs clause in"
3023 " OpenACC %<parallel%>", check);
3024 }
3025
3026 if (tgt && is_oacc_kernels (tgt))
3027 {
3028 /* Strip out reductions, as they are not handled yet. */
3029 tree *prev_ptr = &clauses;
3030
3031 while (tree probe = *prev_ptr)
ca4c3545 3032 {
a8e785ba 3033 tree *next_ptr = &OMP_CLAUSE_CHAIN (probe);
3034
3035 if (OMP_CLAUSE_CODE (probe) == OMP_CLAUSE_REDUCTION)
3036 *prev_ptr = *next_ptr;
3037 else
3038 prev_ptr = next_ptr;
ca4c3545 3039 }
a8e785ba 3040
3041 gimple_omp_for_set_clauses (stmt, clauses);
3042 check_oacc_kernel_gwv (stmt, ctx);
ca4c3545 3043 }
3044 }
3045
3046 scan_sharing_clauses (clauses, ctx);
1e8e9920 3047
ab129075 3048 scan_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
75a70cf9 3049 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
fd6481cf 3050 {
75a70cf9 3051 scan_omp_op (gimple_omp_for_index_ptr (stmt, i), ctx);
3052 scan_omp_op (gimple_omp_for_initial_ptr (stmt, i), ctx);
3053 scan_omp_op (gimple_omp_for_final_ptr (stmt, i), ctx);
3054 scan_omp_op (gimple_omp_for_incr_ptr (stmt, i), ctx);
fd6481cf 3055 }
ab129075 3056 scan_omp (gimple_omp_body_ptr (stmt), ctx);
1e8e9920 3057}
3058
3059/* Scan an OpenMP sections directive. */
3060
3061static void
1a91d914 3062scan_omp_sections (gomp_sections *stmt, omp_context *outer_ctx)
1e8e9920 3063{
1e8e9920 3064 omp_context *ctx;
3065
3066 ctx = new_omp_context (stmt, outer_ctx);
75a70cf9 3067 scan_sharing_clauses (gimple_omp_sections_clauses (stmt), ctx);
ab129075 3068 scan_omp (gimple_omp_body_ptr (stmt), ctx);
1e8e9920 3069}
3070
3071/* Scan an OpenMP single directive. */
3072
3073static void
1a91d914 3074scan_omp_single (gomp_single *stmt, omp_context *outer_ctx)
1e8e9920 3075{
1e8e9920 3076 omp_context *ctx;
3077 tree name;
3078
3079 ctx = new_omp_context (stmt, outer_ctx);
3080 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
3081 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
3082 name = create_tmp_var_name (".omp_copy_s");
e60a6f7b 3083 name = build_decl (gimple_location (stmt),
3084 TYPE_DECL, name, ctx->record_type);
1e8e9920 3085 TYPE_NAME (ctx->record_type) = name;
3086
75a70cf9 3087 scan_sharing_clauses (gimple_omp_single_clauses (stmt), ctx);
ab129075 3088 scan_omp (gimple_omp_body_ptr (stmt), ctx);
1e8e9920 3089
3090 if (TYPE_FIELDS (ctx->record_type) == NULL)
3091 ctx->record_type = NULL;
3092 else
3093 layout_type (ctx->record_type);
3094}
3095
12dc9a16 3096/* Return true if the CLAUSES of an omp target guarantee that the base pointers
3097 used in the corresponding offloaded function are restrict. */
3098
3099static bool
3100omp_target_base_pointers_restrict_p (tree clauses)
3101{
3102 /* The analysis relies on the GOMP_MAP_FORCE_* mapping kinds, which are only
3103 used by OpenACC. */
3104 if (flag_openacc == 0)
3105 return false;
3106
3107 /* I. Basic example:
3108
3109 void foo (void)
3110 {
3111 unsigned int a[2], b[2];
3112
3113 #pragma acc kernels \
3114 copyout (a) \
3115 copyout (b)
3116 {
3117 a[0] = 0;
3118 b[0] = 1;
3119 }
3120 }
3121
3122 After gimplification, we have:
3123
3124 #pragma omp target oacc_kernels \
3125 map(force_from:a [len: 8]) \
3126 map(force_from:b [len: 8])
3127 {
3128 a[0] = 0;
3129 b[0] = 1;
3130 }
3131
3132 Because both mappings have the force prefix, we know that they will be
3133 allocated when calling the corresponding offloaded function, which means we
3134 can mark the base pointers for a and b in the offloaded function as
3135 restrict. */
3136
3137 tree c;
3138 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
3139 {
3140 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP)
3141 return false;
3142
3143 switch (OMP_CLAUSE_MAP_KIND (c))
3144 {
3145 case GOMP_MAP_FORCE_ALLOC:
3146 case GOMP_MAP_FORCE_TO:
3147 case GOMP_MAP_FORCE_FROM:
3148 case GOMP_MAP_FORCE_TOFROM:
3149 break;
3150 default:
3151 return false;
3152 }
3153 }
3154
3155 return true;
3156}
3157
ca4c3545 3158/* Scan a GIMPLE_OMP_TARGET. */
bc7bff74 3159
3160static void
1a91d914 3161scan_omp_target (gomp_target *stmt, omp_context *outer_ctx)
bc7bff74 3162{
3163 omp_context *ctx;
3164 tree name;
ca4c3545 3165 bool offloaded = is_gimple_omp_offloaded (stmt);
3166 tree clauses = gimple_omp_target_clauses (stmt);
bc7bff74 3167
3168 ctx = new_omp_context (stmt, outer_ctx);
3169 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
3170 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
3171 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
3172 name = create_tmp_var_name (".omp_data_t");
3173 name = build_decl (gimple_location (stmt),
3174 TYPE_DECL, name, ctx->record_type);
3175 DECL_ARTIFICIAL (name) = 1;
3176 DECL_NAMELESS (name) = 1;
3177 TYPE_NAME (ctx->record_type) = name;
240131b5 3178 TYPE_ARTIFICIAL (ctx->record_type) = 1;
12dc9a16 3179
3180 bool base_pointers_restrict = false;
ca4c3545 3181 if (offloaded)
bc7bff74 3182 {
3183 create_omp_child_function (ctx, false);
3184 gimple_omp_target_set_child_fn (stmt, ctx->cb.dst_fn);
12dc9a16 3185
3186 base_pointers_restrict = omp_target_base_pointers_restrict_p (clauses);
3187 if (base_pointers_restrict
3188 && dump_file && (dump_flags & TDF_DETAILS))
3189 fprintf (dump_file,
3190 "Base pointers in offloaded function are restrict\n");
bc7bff74 3191 }
3192
12dc9a16 3193 scan_sharing_clauses (clauses, ctx, base_pointers_restrict);
bc7bff74 3194 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3195
3196 if (TYPE_FIELDS (ctx->record_type) == NULL)
3197 ctx->record_type = ctx->receiver_decl = NULL;
3198 else
3199 {
3200 TYPE_FIELDS (ctx->record_type)
3201 = nreverse (TYPE_FIELDS (ctx->record_type));
382ecba7 3202 if (flag_checking)
3203 {
3204 unsigned int align = DECL_ALIGN (TYPE_FIELDS (ctx->record_type));
3205 for (tree field = TYPE_FIELDS (ctx->record_type);
3206 field;
3207 field = DECL_CHAIN (field))
3208 gcc_assert (DECL_ALIGN (field) == align);
3209 }
bc7bff74 3210 layout_type (ctx->record_type);
ca4c3545 3211 if (offloaded)
bc7bff74 3212 fixup_child_record_type (ctx);
3213 }
3214}
3215
3216/* Scan an OpenMP teams directive. */
3217
3218static void
1a91d914 3219scan_omp_teams (gomp_teams *stmt, omp_context *outer_ctx)
bc7bff74 3220{
3221 omp_context *ctx = new_omp_context (stmt, outer_ctx);
3222 scan_sharing_clauses (gimple_omp_teams_clauses (stmt), ctx);
3223 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3224}
1e8e9920 3225
ca4c3545 3226/* Check nesting restrictions. */
ab129075 3227static bool
42acab1c 3228check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx)
c1d127dd 3229{
43895be5 3230 tree c;
3231
56686608 3232 if (ctx && gimple_code (ctx->stmt) == GIMPLE_OMP_GRID_BODY)
3233 /* GRID_BODY is an artificial construct, nesting rules will be checked in
3234 the original copy of its contents. */
3235 return true;
3236
ca4c3545 3237 /* No nesting of non-OpenACC STMT (that is, an OpenMP one, or a GOMP builtin)
3238 inside an OpenACC CTX. */
3239 if (!(is_gimple_omp (stmt)
32f692e2 3240 && is_gimple_omp_oacc (stmt))
3241 /* Except for atomic codes that we share with OpenMP. */
3242 && !(gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD
3243 || gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE))
3244 {
3245 if (get_oacc_fn_attrib (cfun->decl) != NULL)
3246 {
3247 error_at (gimple_location (stmt),
3248 "non-OpenACC construct inside of OpenACC routine");
3249 return false;
3250 }
3251 else
3252 for (omp_context *octx = ctx; octx != NULL; octx = octx->outer)
3253 if (is_gimple_omp (octx->stmt)
3254 && is_gimple_omp_oacc (octx->stmt))
3255 {
3256 error_at (gimple_location (stmt),
3257 "non-OpenACC construct inside of OpenACC region");
3258 return false;
3259 }
ca4c3545 3260 }
3261
3d483a94 3262 if (ctx != NULL)
3263 {
3264 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
10c55644 3265 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3d483a94 3266 {
43895be5 3267 c = NULL_TREE;
3268 if (gimple_code (stmt) == GIMPLE_OMP_ORDERED)
3269 {
3270 c = gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt));
7821c1b5 3271 if (find_omp_clause (c, OMP_CLAUSE_SIMD))
3272 {
3273 if (find_omp_clause (c, OMP_CLAUSE_THREADS)
3274 && (ctx->outer == NULL
3275 || !gimple_omp_for_combined_into_p (ctx->stmt)
3276 || gimple_code (ctx->outer->stmt) != GIMPLE_OMP_FOR
3277 || (gimple_omp_for_kind (ctx->outer->stmt)
3278 != GF_OMP_FOR_KIND_FOR)
3279 || !gimple_omp_for_combined_p (ctx->outer->stmt)))
3280 {
3281 error_at (gimple_location (stmt),
3282 "%<ordered simd threads%> must be closely "
3283 "nested inside of %<for simd%> region");
3284 return false;
3285 }
3286 return true;
3287 }
43895be5 3288 }
3d483a94 3289 error_at (gimple_location (stmt),
43895be5 3290 "OpenMP constructs other than %<#pragma omp ordered simd%>"
7821c1b5 3291 " may not be nested inside %<simd%> region");
3d483a94 3292 return false;
3293 }
bc7bff74 3294 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3295 {
3296 if ((gimple_code (stmt) != GIMPLE_OMP_FOR
3297 || (gimple_omp_for_kind (stmt)
3298 != GF_OMP_FOR_KIND_DISTRIBUTE))
3299 && gimple_code (stmt) != GIMPLE_OMP_PARALLEL)
3300 {
3301 error_at (gimple_location (stmt),
7821c1b5 3302 "only %<distribute%> or %<parallel%> regions are "
3303 "allowed to be strictly nested inside %<teams%> "
3304 "region");
bc7bff74 3305 return false;
3306 }
3307 }
3d483a94 3308 }
75a70cf9 3309 switch (gimple_code (stmt))
c1d127dd 3310 {
75a70cf9 3311 case GIMPLE_OMP_FOR:
10c55644 3312 if (gimple_omp_for_kind (stmt) & GF_OMP_FOR_SIMD)
3d483a94 3313 return true;
bc7bff74 3314 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
3315 {
3316 if (ctx != NULL && gimple_code (ctx->stmt) != GIMPLE_OMP_TEAMS)
3317 {
3318 error_at (gimple_location (stmt),
7821c1b5 3319 "%<distribute%> region must be strictly nested "
3320 "inside %<teams%> construct");
bc7bff74 3321 return false;
3322 }
3323 return true;
3324 }
43895be5 3325 /* We split taskloop into task and nested taskloop in it. */
3326 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_TASKLOOP)
3327 return true;
7a1ed40d 3328 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
3329 {
3330 bool ok = false;
3331
3332 if (ctx)
3333 switch (gimple_code (ctx->stmt))
3334 {
3335 case GIMPLE_OMP_FOR:
3336 ok = (gimple_omp_for_kind (ctx->stmt)
3337 == GF_OMP_FOR_KIND_OACC_LOOP);
3338 break;
3339
3340 case GIMPLE_OMP_TARGET:
3341 switch (gimple_omp_target_kind (ctx->stmt))
3342 {
3343 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
3344 case GF_OMP_TARGET_KIND_OACC_KERNELS:
3345 ok = true;
3346 break;
3347
3348 default:
3349 break;
3350 }
3351
3352 default:
3353 break;
3354 }
3355 else if (get_oacc_fn_attrib (current_function_decl))
3356 ok = true;
3357 if (!ok)
3358 {
3359 error_at (gimple_location (stmt),
3360 "OpenACC loop directive must be associated with"
3361 " an OpenACC compute region");
3362 return false;
3363 }
3364 }
bc7bff74 3365 /* FALLTHRU */
3366 case GIMPLE_CALL:
3367 if (is_gimple_call (stmt)
3368 && (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3369 == BUILT_IN_GOMP_CANCEL
3370 || DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3371 == BUILT_IN_GOMP_CANCELLATION_POINT))
3372 {
3373 const char *bad = NULL;
3374 const char *kind = NULL;
7821c1b5 3375 const char *construct
3376 = (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3377 == BUILT_IN_GOMP_CANCEL)
3378 ? "#pragma omp cancel"
3379 : "#pragma omp cancellation point";
bc7bff74 3380 if (ctx == NULL)
3381 {
3382 error_at (gimple_location (stmt), "orphaned %qs construct",
7821c1b5 3383 construct);
bc7bff74 3384 return false;
3385 }
6b409616 3386 switch (tree_fits_shwi_p (gimple_call_arg (stmt, 0))
3387 ? tree_to_shwi (gimple_call_arg (stmt, 0))
bc7bff74 3388 : 0)
3389 {
3390 case 1:
3391 if (gimple_code (ctx->stmt) != GIMPLE_OMP_PARALLEL)
3392 bad = "#pragma omp parallel";
3393 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3394 == BUILT_IN_GOMP_CANCEL
3395 && !integer_zerop (gimple_call_arg (stmt, 1)))
3396 ctx->cancellable = true;
3397 kind = "parallel";
3398 break;
3399 case 2:
3400 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
3401 || gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR)
3402 bad = "#pragma omp for";
3403 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3404 == BUILT_IN_GOMP_CANCEL
3405 && !integer_zerop (gimple_call_arg (stmt, 1)))
3406 {
3407 ctx->cancellable = true;
3408 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3409 OMP_CLAUSE_NOWAIT))
3410 warning_at (gimple_location (stmt), 0,
3411 "%<#pragma omp cancel for%> inside "
3412 "%<nowait%> for construct");
3413 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3414 OMP_CLAUSE_ORDERED))
3415 warning_at (gimple_location (stmt), 0,
3416 "%<#pragma omp cancel for%> inside "
3417 "%<ordered%> for construct");
3418 }
3419 kind = "for";
3420 break;
3421 case 4:
3422 if (gimple_code (ctx->stmt) != GIMPLE_OMP_SECTIONS
3423 && gimple_code (ctx->stmt) != GIMPLE_OMP_SECTION)
3424 bad = "#pragma omp sections";
3425 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3426 == BUILT_IN_GOMP_CANCEL
3427 && !integer_zerop (gimple_call_arg (stmt, 1)))
3428 {
3429 if (gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS)
3430 {
3431 ctx->cancellable = true;
3432 if (find_omp_clause (gimple_omp_sections_clauses
3433 (ctx->stmt),
3434 OMP_CLAUSE_NOWAIT))
3435 warning_at (gimple_location (stmt), 0,
3436 "%<#pragma omp cancel sections%> inside "
3437 "%<nowait%> sections construct");
3438 }
3439 else
3440 {
3441 gcc_assert (ctx->outer
3442 && gimple_code (ctx->outer->stmt)
3443 == GIMPLE_OMP_SECTIONS);
3444 ctx->outer->cancellable = true;
3445 if (find_omp_clause (gimple_omp_sections_clauses
3446 (ctx->outer->stmt),
3447 OMP_CLAUSE_NOWAIT))
3448 warning_at (gimple_location (stmt), 0,
3449 "%<#pragma omp cancel sections%> inside "
3450 "%<nowait%> sections construct");
3451 }
3452 }
3453 kind = "sections";
3454 break;
3455 case 8:
3456 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TASK)
3457 bad = "#pragma omp task";
3458 else
7821c1b5 3459 {
3460 for (omp_context *octx = ctx->outer;
3461 octx; octx = octx->outer)
3462 {
3463 switch (gimple_code (octx->stmt))
3464 {
3465 case GIMPLE_OMP_TASKGROUP:
3466 break;
3467 case GIMPLE_OMP_TARGET:
3468 if (gimple_omp_target_kind (octx->stmt)
3469 != GF_OMP_TARGET_KIND_REGION)
3470 continue;
3471 /* FALLTHRU */
3472 case GIMPLE_OMP_PARALLEL:
3473 case GIMPLE_OMP_TEAMS:
3474 error_at (gimple_location (stmt),
3475 "%<%s taskgroup%> construct not closely "
3476 "nested inside of %<taskgroup%> region",
3477 construct);
3478 return false;
3479 default:
3480 continue;
3481 }
3482 break;
3483 }
3484 ctx->cancellable = true;
3485 }
bc7bff74 3486 kind = "taskgroup";
3487 break;
3488 default:
3489 error_at (gimple_location (stmt), "invalid arguments");
3490 return false;
3491 }
3492 if (bad)
3493 {
3494 error_at (gimple_location (stmt),
3495 "%<%s %s%> construct not closely nested inside of %qs",
7821c1b5 3496 construct, kind, bad);
bc7bff74 3497 return false;
3498 }
3499 }
3d483a94 3500 /* FALLTHRU */
75a70cf9 3501 case GIMPLE_OMP_SECTIONS:
3502 case GIMPLE_OMP_SINGLE:
c1d127dd 3503 for (; ctx != NULL; ctx = ctx->outer)
75a70cf9 3504 switch (gimple_code (ctx->stmt))
c1d127dd 3505 {
75a70cf9 3506 case GIMPLE_OMP_FOR:
7821c1b5 3507 if (gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR
3508 && gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_TASKLOOP)
3509 break;
3510 /* FALLTHRU */
75a70cf9 3511 case GIMPLE_OMP_SECTIONS:
3512 case GIMPLE_OMP_SINGLE:
3513 case GIMPLE_OMP_ORDERED:
3514 case GIMPLE_OMP_MASTER:
3515 case GIMPLE_OMP_TASK:
bc7bff74 3516 case GIMPLE_OMP_CRITICAL:
75a70cf9 3517 if (is_gimple_call (stmt))
fd6481cf 3518 {
bc7bff74 3519 if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3520 != BUILT_IN_GOMP_BARRIER)
3521 return true;
ab129075 3522 error_at (gimple_location (stmt),
3523 "barrier region may not be closely nested inside "
7821c1b5 3524 "of work-sharing, %<critical%>, %<ordered%>, "
3525 "%<master%>, explicit %<task%> or %<taskloop%> "
3526 "region");
ab129075 3527 return false;
fd6481cf 3528 }
ab129075 3529 error_at (gimple_location (stmt),
3530 "work-sharing region may not be closely nested inside "
7821c1b5 3531 "of work-sharing, %<critical%>, %<ordered%>, "
3532 "%<master%>, explicit %<task%> or %<taskloop%> region");
ab129075 3533 return false;
75a70cf9 3534 case GIMPLE_OMP_PARALLEL:
7821c1b5 3535 case GIMPLE_OMP_TEAMS:
ab129075 3536 return true;
7821c1b5 3537 case GIMPLE_OMP_TARGET:
3538 if (gimple_omp_target_kind (ctx->stmt)
3539 == GF_OMP_TARGET_KIND_REGION)
3540 return true;
3541 break;
c1d127dd 3542 default:
3543 break;
3544 }
3545 break;
75a70cf9 3546 case GIMPLE_OMP_MASTER:
c1d127dd 3547 for (; ctx != NULL; ctx = ctx->outer)
75a70cf9 3548 switch (gimple_code (ctx->stmt))
c1d127dd 3549 {
75a70cf9 3550 case GIMPLE_OMP_FOR:
7821c1b5 3551 if (gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR
3552 && gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_TASKLOOP)
3553 break;
3554 /* FALLTHRU */
75a70cf9 3555 case GIMPLE_OMP_SECTIONS:
3556 case GIMPLE_OMP_SINGLE:
3557 case GIMPLE_OMP_TASK:
ab129075 3558 error_at (gimple_location (stmt),
7821c1b5 3559 "%<master%> region may not be closely nested inside "
3560 "of work-sharing, explicit %<task%> or %<taskloop%> "
3561 "region");
ab129075 3562 return false;
75a70cf9 3563 case GIMPLE_OMP_PARALLEL:
7821c1b5 3564 case GIMPLE_OMP_TEAMS:
ab129075 3565 return true;
7821c1b5 3566 case GIMPLE_OMP_TARGET:
3567 if (gimple_omp_target_kind (ctx->stmt)
3568 == GF_OMP_TARGET_KIND_REGION)
3569 return true;
3570 break;
c1d127dd 3571 default:
3572 break;
3573 }
3574 break;
43895be5 3575 case GIMPLE_OMP_TASK:
3576 for (c = gimple_omp_task_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
3577 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
3578 && (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE
3579 || OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK))
3580 {
3581 enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c);
3582 error_at (OMP_CLAUSE_LOCATION (c),
3583 "%<depend(%s)%> is only allowed in %<omp ordered%>",
3584 kind == OMP_CLAUSE_DEPEND_SOURCE ? "source" : "sink");
3585 return false;
3586 }
3587 break;
75a70cf9 3588 case GIMPLE_OMP_ORDERED:
43895be5 3589 for (c = gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt));
3590 c; c = OMP_CLAUSE_CHAIN (c))
3591 {
3592 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND)
3593 {
3594 gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_THREADS
7821c1b5 3595 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SIMD);
43895be5 3596 continue;
3597 }
3598 enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c);
3599 if (kind == OMP_CLAUSE_DEPEND_SOURCE
3600 || kind == OMP_CLAUSE_DEPEND_SINK)
3601 {
3602 tree oclause;
3603 /* Look for containing ordered(N) loop. */
3604 if (ctx == NULL
3605 || gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
3606 || (oclause
3607 = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3608 OMP_CLAUSE_ORDERED)) == NULL_TREE)
3609 {
3610 error_at (OMP_CLAUSE_LOCATION (c),
7821c1b5 3611 "%<ordered%> construct with %<depend%> clause "
3612 "must be closely nested inside an %<ordered%> "
3613 "loop");
43895be5 3614 return false;
3615 }
3616 else if (OMP_CLAUSE_ORDERED_EXPR (oclause) == NULL_TREE)
3617 {
3618 error_at (OMP_CLAUSE_LOCATION (c),
7821c1b5 3619 "%<ordered%> construct with %<depend%> clause "
3620 "must be closely nested inside a loop with "
3621 "%<ordered%> clause with a parameter");
43895be5 3622 return false;
3623 }
3624 }
3625 else
3626 {
3627 error_at (OMP_CLAUSE_LOCATION (c),
7821c1b5 3628 "invalid depend kind in omp %<ordered%> %<depend%>");
3629 return false;
3630 }
3631 }
3632 c = gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt));
3633 if (find_omp_clause (c, OMP_CLAUSE_SIMD))
3634 {
3635 /* ordered simd must be closely nested inside of simd region,
3636 and simd region must not encounter constructs other than
3637 ordered simd, therefore ordered simd may be either orphaned,
3638 or ctx->stmt must be simd. The latter case is handled already
3639 earlier. */
3640 if (ctx != NULL)
3641 {
3642 error_at (gimple_location (stmt),
3643 "%<ordered%> %<simd%> must be closely nested inside "
3644 "%<simd%> region");
43895be5 3645 return false;
3646 }
3647 }
c1d127dd 3648 for (; ctx != NULL; ctx = ctx->outer)
75a70cf9 3649 switch (gimple_code (ctx->stmt))
c1d127dd 3650 {
75a70cf9 3651 case GIMPLE_OMP_CRITICAL:
3652 case GIMPLE_OMP_TASK:
7821c1b5 3653 case GIMPLE_OMP_ORDERED:
3654 ordered_in_taskloop:
ab129075 3655 error_at (gimple_location (stmt),
7821c1b5 3656 "%<ordered%> region may not be closely nested inside "
3657 "of %<critical%>, %<ordered%>, explicit %<task%> or "
3658 "%<taskloop%> region");
ab129075 3659 return false;
75a70cf9 3660 case GIMPLE_OMP_FOR:
7821c1b5 3661 if (gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_TASKLOOP)
3662 goto ordered_in_taskloop;
75a70cf9 3663 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
c1d127dd 3664 OMP_CLAUSE_ORDERED) == NULL)
ab129075 3665 {
3666 error_at (gimple_location (stmt),
7821c1b5 3667 "%<ordered%> region must be closely nested inside "
3668 "a loop region with an %<ordered%> clause");
ab129075 3669 return false;
3670 }
3671 return true;
7821c1b5 3672 case GIMPLE_OMP_TARGET:
3673 if (gimple_omp_target_kind (ctx->stmt)
3674 != GF_OMP_TARGET_KIND_REGION)
3675 break;
3676 /* FALLTHRU */
75a70cf9 3677 case GIMPLE_OMP_PARALLEL:
7821c1b5 3678 case GIMPLE_OMP_TEAMS:
bc7bff74 3679 error_at (gimple_location (stmt),
7821c1b5 3680 "%<ordered%> region must be closely nested inside "
3681 "a loop region with an %<ordered%> clause");
bc7bff74 3682 return false;
c1d127dd 3683 default:
3684 break;
3685 }
3686 break;
75a70cf9 3687 case GIMPLE_OMP_CRITICAL:
1a91d914 3688 {
3689 tree this_stmt_name
3690 = gimple_omp_critical_name (as_a <gomp_critical *> (stmt));
3691 for (; ctx != NULL; ctx = ctx->outer)
3692 if (gomp_critical *other_crit
3693 = dyn_cast <gomp_critical *> (ctx->stmt))
3694 if (this_stmt_name == gimple_omp_critical_name (other_crit))
3695 {
3696 error_at (gimple_location (stmt),
7821c1b5 3697 "%<critical%> region may not be nested inside "
3698 "a %<critical%> region with the same name");
1a91d914 3699 return false;
3700 }
3701 }
c1d127dd 3702 break;
bc7bff74 3703 case GIMPLE_OMP_TEAMS:
3704 if (ctx == NULL
3705 || gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET
3706 || gimple_omp_target_kind (ctx->stmt) != GF_OMP_TARGET_KIND_REGION)
3707 {
3708 error_at (gimple_location (stmt),
7821c1b5 3709 "%<teams%> construct not closely nested inside of "
3710 "%<target%> construct");
bc7bff74 3711 return false;
3712 }
3713 break;
691447ab 3714 case GIMPLE_OMP_TARGET:
43895be5 3715 for (c = gimple_omp_target_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
3716 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
3717 && (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE
3718 || OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK))
3719 {
3720 enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c);
3721 error_at (OMP_CLAUSE_LOCATION (c),
3722 "%<depend(%s)%> is only allowed in %<omp ordered%>",
3723 kind == OMP_CLAUSE_DEPEND_SOURCE ? "source" : "sink");
3724 return false;
3725 }
32f692e2 3726 if (is_gimple_omp_offloaded (stmt)
3727 && get_oacc_fn_attrib (cfun->decl) != NULL)
3728 {
3729 error_at (gimple_location (stmt),
3730 "OpenACC region inside of OpenACC routine, nested "
3731 "parallelism not supported yet");
3732 return false;
3733 }
691447ab 3734 for (; ctx != NULL; ctx = ctx->outer)
ca4c3545 3735 {
3736 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET)
3737 {
3738 if (is_gimple_omp (stmt)
3739 && is_gimple_omp_oacc (stmt)
3740 && is_gimple_omp (ctx->stmt))
3741 {
3742 error_at (gimple_location (stmt),
3743 "OpenACC construct inside of non-OpenACC region");
3744 return false;
3745 }
3746 continue;
3747 }
3748
3749 const char *stmt_name, *ctx_stmt_name;
3750 switch (gimple_omp_target_kind (stmt))
3751 {
3752 case GF_OMP_TARGET_KIND_REGION: stmt_name = "target"; break;
3753 case GF_OMP_TARGET_KIND_DATA: stmt_name = "target data"; break;
3754 case GF_OMP_TARGET_KIND_UPDATE: stmt_name = "target update"; break;
43895be5 3755 case GF_OMP_TARGET_KIND_ENTER_DATA:
3756 stmt_name = "target enter data"; break;
3757 case GF_OMP_TARGET_KIND_EXIT_DATA:
3758 stmt_name = "target exit data"; break;
ca4c3545 3759 case GF_OMP_TARGET_KIND_OACC_PARALLEL: stmt_name = "parallel"; break;
3760 case GF_OMP_TARGET_KIND_OACC_KERNELS: stmt_name = "kernels"; break;
3761 case GF_OMP_TARGET_KIND_OACC_DATA: stmt_name = "data"; break;
3762 case GF_OMP_TARGET_KIND_OACC_UPDATE: stmt_name = "update"; break;
43895be5 3763 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
3764 stmt_name = "enter/exit data"; break;
571b3486 3765 case GF_OMP_TARGET_KIND_OACC_HOST_DATA: stmt_name = "host_data";
3766 break;
ca4c3545 3767 default: gcc_unreachable ();
3768 }
3769 switch (gimple_omp_target_kind (ctx->stmt))
3770 {
3771 case GF_OMP_TARGET_KIND_REGION: ctx_stmt_name = "target"; break;
3772 case GF_OMP_TARGET_KIND_DATA: ctx_stmt_name = "target data"; break;
43895be5 3773 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
3774 ctx_stmt_name = "parallel"; break;
3775 case GF_OMP_TARGET_KIND_OACC_KERNELS:
3776 ctx_stmt_name = "kernels"; break;
ca4c3545 3777 case GF_OMP_TARGET_KIND_OACC_DATA: ctx_stmt_name = "data"; break;
571b3486 3778 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
3779 ctx_stmt_name = "host_data"; break;
ca4c3545 3780 default: gcc_unreachable ();
3781 }
3782
3783 /* OpenACC/OpenMP mismatch? */
3784 if (is_gimple_omp_oacc (stmt)
3785 != is_gimple_omp_oacc (ctx->stmt))
3786 {
3787 error_at (gimple_location (stmt),
7821c1b5 3788 "%s %qs construct inside of %s %qs region",
ca4c3545 3789 (is_gimple_omp_oacc (stmt)
3790 ? "OpenACC" : "OpenMP"), stmt_name,
3791 (is_gimple_omp_oacc (ctx->stmt)
3792 ? "OpenACC" : "OpenMP"), ctx_stmt_name);
3793 return false;
3794 }
3795 if (is_gimple_omp_offloaded (ctx->stmt))
3796 {
3797 /* No GIMPLE_OMP_TARGET inside offloaded OpenACC CTX. */
3798 if (is_gimple_omp_oacc (ctx->stmt))
3799 {
3800 error_at (gimple_location (stmt),
7821c1b5 3801 "%qs construct inside of %qs region",
ca4c3545 3802 stmt_name, ctx_stmt_name);
3803 return false;
3804 }
3805 else
3806 {
ca4c3545 3807 warning_at (gimple_location (stmt), 0,
7821c1b5 3808 "%qs construct inside of %qs region",
ca4c3545 3809 stmt_name, ctx_stmt_name);
3810 }
3811 }
3812 }
691447ab 3813 break;
c1d127dd 3814 default:
3815 break;
3816 }
ab129075 3817 return true;
c1d127dd 3818}
3819
3820
75a70cf9 3821/* Helper function scan_omp.
3822
3823 Callback for walk_tree or operators in walk_gimple_stmt used to
ca4c3545 3824 scan for OMP directives in TP. */
1e8e9920 3825
3826static tree
75a70cf9 3827scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
1e8e9920 3828{
4077bf7a 3829 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
3830 omp_context *ctx = (omp_context *) wi->info;
1e8e9920 3831 tree t = *tp;
3832
75a70cf9 3833 switch (TREE_CODE (t))
3834 {
3835 case VAR_DECL:
3836 case PARM_DECL:
3837 case LABEL_DECL:
3838 case RESULT_DECL:
3839 if (ctx)
56686608 3840 {
3841 tree repl = remap_decl (t, &ctx->cb);
3842 gcc_checking_assert (TREE_CODE (repl) != ERROR_MARK);
3843 *tp = repl;
3844 }
75a70cf9 3845 break;
3846
3847 default:
3848 if (ctx && TYPE_P (t))
3849 *tp = remap_type (t, &ctx->cb);
3850 else if (!DECL_P (t))
7cf869dd 3851 {
3852 *walk_subtrees = 1;
3853 if (ctx)
182cf5a9 3854 {
3855 tree tem = remap_type (TREE_TYPE (t), &ctx->cb);
3856 if (tem != TREE_TYPE (t))
3857 {
3858 if (TREE_CODE (t) == INTEGER_CST)
e913b5cd 3859 *tp = wide_int_to_tree (tem, t);
182cf5a9 3860 else
3861 TREE_TYPE (t) = tem;
3862 }
3863 }
7cf869dd 3864 }
75a70cf9 3865 break;
3866 }
3867
3868 return NULL_TREE;
3869}
3870
f2697631 3871/* Return true if FNDECL is a setjmp or a longjmp. */
3872
3873static bool
3874setjmp_or_longjmp_p (const_tree fndecl)
3875{
3876 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
3877 && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_SETJMP
3878 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LONGJMP))
3879 return true;
3880
3881 tree declname = DECL_NAME (fndecl);
3882 if (!declname)
3883 return false;
3884 const char *name = IDENTIFIER_POINTER (declname);
3885 return !strcmp (name, "setjmp") || !strcmp (name, "longjmp");
3886}
3887
75a70cf9 3888
3889/* Helper function for scan_omp.
3890
ca4c3545 3891 Callback for walk_gimple_stmt used to scan for OMP directives in
75a70cf9 3892 the current statement in GSI. */
3893
3894static tree
3895scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
3896 struct walk_stmt_info *wi)
3897{
42acab1c 3898 gimple *stmt = gsi_stmt (*gsi);
75a70cf9 3899 omp_context *ctx = (omp_context *) wi->info;
3900
3901 if (gimple_has_location (stmt))
3902 input_location = gimple_location (stmt);
1e8e9920 3903
ca4c3545 3904 /* Check the nesting restrictions. */
bc7bff74 3905 bool remove = false;
3906 if (is_gimple_omp (stmt))
3907 remove = !check_omp_nesting_restrictions (stmt, ctx);
3908 else if (is_gimple_call (stmt))
3909 {
3910 tree fndecl = gimple_call_fndecl (stmt);
f2697631 3911 if (fndecl)
3912 {
3913 if (setjmp_or_longjmp_p (fndecl)
3914 && ctx
3915 && gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
10c55644 3916 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
f2697631 3917 {
3918 remove = true;
3919 error_at (gimple_location (stmt),
3920 "setjmp/longjmp inside simd construct");
3921 }
3922 else if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
3923 switch (DECL_FUNCTION_CODE (fndecl))
3924 {
3925 case BUILT_IN_GOMP_BARRIER:
3926 case BUILT_IN_GOMP_CANCEL:
3927 case BUILT_IN_GOMP_CANCELLATION_POINT:
3928 case BUILT_IN_GOMP_TASKYIELD:
3929 case BUILT_IN_GOMP_TASKWAIT:
3930 case BUILT_IN_GOMP_TASKGROUP_START:
3931 case BUILT_IN_GOMP_TASKGROUP_END:
3932 remove = !check_omp_nesting_restrictions (stmt, ctx);
3933 break;
3934 default:
3935 break;
3936 }
3937 }
bc7bff74 3938 }
3939 if (remove)
3940 {
3941 stmt = gimple_build_nop ();
3942 gsi_replace (gsi, stmt, false);
fd6481cf 3943 }
c1d127dd 3944
75a70cf9 3945 *handled_ops_p = true;
3946
3947 switch (gimple_code (stmt))
1e8e9920 3948 {
75a70cf9 3949 case GIMPLE_OMP_PARALLEL:
fd6481cf 3950 taskreg_nesting_level++;
75a70cf9 3951 scan_omp_parallel (gsi, ctx);
fd6481cf 3952 taskreg_nesting_level--;
3953 break;
3954
75a70cf9 3955 case GIMPLE_OMP_TASK:
fd6481cf 3956 taskreg_nesting_level++;
75a70cf9 3957 scan_omp_task (gsi, ctx);
fd6481cf 3958 taskreg_nesting_level--;
1e8e9920 3959 break;
3960
75a70cf9 3961 case GIMPLE_OMP_FOR:
1a91d914 3962 scan_omp_for (as_a <gomp_for *> (stmt), ctx);
1e8e9920 3963 break;
3964
75a70cf9 3965 case GIMPLE_OMP_SECTIONS:
1a91d914 3966 scan_omp_sections (as_a <gomp_sections *> (stmt), ctx);
1e8e9920 3967 break;
3968
75a70cf9 3969 case GIMPLE_OMP_SINGLE:
1a91d914 3970 scan_omp_single (as_a <gomp_single *> (stmt), ctx);
1e8e9920 3971 break;
3972
75a70cf9 3973 case GIMPLE_OMP_SECTION:
3974 case GIMPLE_OMP_MASTER:
bc7bff74 3975 case GIMPLE_OMP_TASKGROUP:
75a70cf9 3976 case GIMPLE_OMP_ORDERED:
3977 case GIMPLE_OMP_CRITICAL:
56686608 3978 case GIMPLE_OMP_GRID_BODY:
75a70cf9 3979 ctx = new_omp_context (stmt, ctx);
ab129075 3980 scan_omp (gimple_omp_body_ptr (stmt), ctx);
1e8e9920 3981 break;
3982
bc7bff74 3983 case GIMPLE_OMP_TARGET:
1a91d914 3984 scan_omp_target (as_a <gomp_target *> (stmt), ctx);
bc7bff74 3985 break;
3986
3987 case GIMPLE_OMP_TEAMS:
1a91d914 3988 scan_omp_teams (as_a <gomp_teams *> (stmt), ctx);
bc7bff74 3989 break;
3990
75a70cf9 3991 case GIMPLE_BIND:
1e8e9920 3992 {
3993 tree var;
1e8e9920 3994
75a70cf9 3995 *handled_ops_p = false;
3996 if (ctx)
1a91d914 3997 for (var = gimple_bind_vars (as_a <gbind *> (stmt));
3998 var ;
3999 var = DECL_CHAIN (var))
75a70cf9 4000 insert_decl_map (&ctx->cb, var, var);
1e8e9920 4001 }
4002 break;
1e8e9920 4003 default:
75a70cf9 4004 *handled_ops_p = false;
1e8e9920 4005 break;
4006 }
4007
4008 return NULL_TREE;
4009}
4010
4011
75a70cf9 4012/* Scan all the statements starting at the current statement. CTX
ca4c3545 4013 contains context information about the OMP directives and
75a70cf9 4014 clauses found during the scan. */
1e8e9920 4015
4016static void
ab129075 4017scan_omp (gimple_seq *body_p, omp_context *ctx)
1e8e9920 4018{
4019 location_t saved_location;
4020 struct walk_stmt_info wi;
4021
4022 memset (&wi, 0, sizeof (wi));
1e8e9920 4023 wi.info = ctx;
1e8e9920 4024 wi.want_locations = true;
4025
4026 saved_location = input_location;
ab129075 4027 walk_gimple_seq_mod (body_p, scan_omp_1_stmt, scan_omp_1_op, &wi);
1e8e9920 4028 input_location = saved_location;
4029}
4030\f
4031/* Re-gimplification and code generation routines. */
4032
4033/* Build a call to GOMP_barrier. */
4034
42acab1c 4035static gimple *
bc7bff74 4036build_omp_barrier (tree lhs)
4037{
4038 tree fndecl = builtin_decl_explicit (lhs ? BUILT_IN_GOMP_BARRIER_CANCEL
4039 : BUILT_IN_GOMP_BARRIER);
1a91d914 4040 gcall *g = gimple_build_call (fndecl, 0);
bc7bff74 4041 if (lhs)
4042 gimple_call_set_lhs (g, lhs);
4043 return g;
1e8e9920 4044}
4045
4046/* If a context was created for STMT when it was scanned, return it. */
4047
4048static omp_context *
42acab1c 4049maybe_lookup_ctx (gimple *stmt)
1e8e9920 4050{
4051 splay_tree_node n;
4052 n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
4053 return n ? (omp_context *) n->value : NULL;
4054}
4055
773c5ba7 4056
4057/* Find the mapping for DECL in CTX or the immediately enclosing
4058 context that has a mapping for DECL.
4059
4060 If CTX is a nested parallel directive, we may have to use the decl
4061 mappings created in CTX's parent context. Suppose that we have the
4062 following parallel nesting (variable UIDs showed for clarity):
4063
4064 iD.1562 = 0;
4065 #omp parallel shared(iD.1562) -> outer parallel
4066 iD.1562 = iD.1562 + 1;
4067
4068 #omp parallel shared (iD.1562) -> inner parallel
4069 iD.1562 = iD.1562 - 1;
4070
4071 Each parallel structure will create a distinct .omp_data_s structure
4072 for copying iD.1562 in/out of the directive:
4073
4074 outer parallel .omp_data_s.1.i -> iD.1562
4075 inner parallel .omp_data_s.2.i -> iD.1562
4076
4077 A shared variable mapping will produce a copy-out operation before
4078 the parallel directive and a copy-in operation after it. So, in
4079 this case we would have:
4080
4081 iD.1562 = 0;
4082 .omp_data_o.1.i = iD.1562;
4083 #omp parallel shared(iD.1562) -> outer parallel
4084 .omp_data_i.1 = &.omp_data_o.1
4085 .omp_data_i.1->i = .omp_data_i.1->i + 1;
4086
4087 .omp_data_o.2.i = iD.1562; -> **
4088 #omp parallel shared(iD.1562) -> inner parallel
4089 .omp_data_i.2 = &.omp_data_o.2
4090 .omp_data_i.2->i = .omp_data_i.2->i - 1;
4091
4092
4093 ** This is a problem. The symbol iD.1562 cannot be referenced
4094 inside the body of the outer parallel region. But since we are
4095 emitting this copy operation while expanding the inner parallel
4096 directive, we need to access the CTX structure of the outer
4097 parallel directive to get the correct mapping:
4098
4099 .omp_data_o.2.i = .omp_data_i.1->i
4100
4101 Since there may be other workshare or parallel directives enclosing
4102 the parallel directive, it may be necessary to walk up the context
4103 parent chain. This is not a problem in general because nested
4104 parallelism happens only rarely. */
4105
4106static tree
4107lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
4108{
4109 tree t;
4110 omp_context *up;
4111
773c5ba7 4112 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
4113 t = maybe_lookup_decl (decl, up);
4114
87b31375 4115 gcc_assert (!ctx->is_nested || t || is_global_var (decl));
773c5ba7 4116
c37594c7 4117 return t ? t : decl;
773c5ba7 4118}
4119
4120
f49d7bb5 4121/* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
4122 in outer contexts. */
4123
4124static tree
4125maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
4126{
4127 tree t = NULL;
4128 omp_context *up;
4129
87b31375 4130 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
4131 t = maybe_lookup_decl (decl, up);
f49d7bb5 4132
4133 return t ? t : decl;
4134}
4135
4136
df67b98c 4137/* Construct the initialization value for reduction operation OP. */
1e8e9920 4138
4139tree
df67b98c 4140omp_reduction_init_op (location_t loc, enum tree_code op, tree type)
1e8e9920 4141{
df67b98c 4142 switch (op)
1e8e9920 4143 {
4144 case PLUS_EXPR:
4145 case MINUS_EXPR:
4146 case BIT_IOR_EXPR:
4147 case BIT_XOR_EXPR:
4148 case TRUTH_OR_EXPR:
4149 case TRUTH_ORIF_EXPR:
4150 case TRUTH_XOR_EXPR:
4151 case NE_EXPR:
385f3f36 4152 return build_zero_cst (type);
1e8e9920 4153
4154 case MULT_EXPR:
4155 case TRUTH_AND_EXPR:
4156 case TRUTH_ANDIF_EXPR:
4157 case EQ_EXPR:
389dd41b 4158 return fold_convert_loc (loc, type, integer_one_node);
1e8e9920 4159
4160 case BIT_AND_EXPR:
389dd41b 4161 return fold_convert_loc (loc, type, integer_minus_one_node);
1e8e9920 4162
4163 case MAX_EXPR:
4164 if (SCALAR_FLOAT_TYPE_P (type))
4165 {
4166 REAL_VALUE_TYPE max, min;
fe994837 4167 if (HONOR_INFINITIES (type))
1e8e9920 4168 {
4169 real_inf (&max);
4170 real_arithmetic (&min, NEGATE_EXPR, &max, NULL);
4171 }
4172 else
4173 real_maxval (&min, 1, TYPE_MODE (type));
4174 return build_real (type, min);
4175 }
5902cce5 4176 else if (POINTER_TYPE_P (type))
4177 {
4178 wide_int min
4179 = wi::min_value (TYPE_PRECISION (type), TYPE_SIGN (type));
4180 return wide_int_to_tree (type, min);
4181 }
1e8e9920 4182 else
4183 {
4184 gcc_assert (INTEGRAL_TYPE_P (type));
4185 return TYPE_MIN_VALUE (type);
4186 }
4187
4188 case MIN_EXPR:
4189 if (SCALAR_FLOAT_TYPE_P (type))
4190 {
4191 REAL_VALUE_TYPE max;
fe994837 4192 if (HONOR_INFINITIES (type))
1e8e9920 4193 real_inf (&max);
4194 else
4195 real_maxval (&max, 0, TYPE_MODE (type));
4196 return build_real (type, max);
4197 }
5902cce5 4198 else if (POINTER_TYPE_P (type))
4199 {
4200 wide_int max
4201 = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type));
4202 return wide_int_to_tree (type, max);
4203 }
1e8e9920 4204 else
4205 {
4206 gcc_assert (INTEGRAL_TYPE_P (type));
4207 return TYPE_MAX_VALUE (type);
4208 }
4209
4210 default:
4211 gcc_unreachable ();
4212 }
4213}
4214
df67b98c 4215/* Construct the initialization value for reduction CLAUSE. */
4216
4217tree
4218omp_reduction_init (tree clause, tree type)
4219{
4220 return omp_reduction_init_op (OMP_CLAUSE_LOCATION (clause),
4221 OMP_CLAUSE_REDUCTION_CODE (clause), type);
4222}
4223
bc7bff74 4224/* Return alignment to be assumed for var in CLAUSE, which should be
4225 OMP_CLAUSE_ALIGNED. */
4226
4227static tree
4228omp_clause_aligned_alignment (tree clause)
4229{
4230 if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause))
4231 return OMP_CLAUSE_ALIGNED_ALIGNMENT (clause);
4232
4233 /* Otherwise return implementation defined alignment. */
4234 unsigned int al = 1;
3754d046 4235 machine_mode mode, vmode;
bc7bff74 4236 int vs = targetm.vectorize.autovectorize_vector_sizes ();
4237 if (vs)
4238 vs = 1 << floor_log2 (vs);
4239 static enum mode_class classes[]
4240 = { MODE_INT, MODE_VECTOR_INT, MODE_FLOAT, MODE_VECTOR_FLOAT };
4241 for (int i = 0; i < 4; i += 2)
4242 for (mode = GET_CLASS_NARROWEST_MODE (classes[i]);
4243 mode != VOIDmode;
4244 mode = GET_MODE_WIDER_MODE (mode))
4245 {
4246 vmode = targetm.vectorize.preferred_simd_mode (mode);
4247 if (GET_MODE_CLASS (vmode) != classes[i + 1])
4248 continue;
4249 while (vs
4250 && GET_MODE_SIZE (vmode) < vs
4251 && GET_MODE_2XWIDER_MODE (vmode) != VOIDmode)
4252 vmode = GET_MODE_2XWIDER_MODE (vmode);
4253
4254 tree type = lang_hooks.types.type_for_mode (mode, 1);
4255 if (type == NULL_TREE || TYPE_MODE (type) != mode)
4256 continue;
4257 type = build_vector_type (type, GET_MODE_SIZE (vmode)
4258 / GET_MODE_SIZE (mode));
4259 if (TYPE_MODE (type) != vmode)
4260 continue;
4261 if (TYPE_ALIGN_UNIT (type) > al)
4262 al = TYPE_ALIGN_UNIT (type);
4263 }
4264 return build_int_cst (integer_type_node, al);
4265}
4266
3d483a94 4267/* Return maximum possible vectorization factor for the target. */
4268
4269static int
4270omp_max_vf (void)
4271{
4272 if (!optimize
4273 || optimize_debug
ad45e43e 4274 || !flag_tree_loop_optimize
043115ec 4275 || (!flag_tree_loop_vectorize
4276 && (global_options_set.x_flag_tree_loop_vectorize
4277 || global_options_set.x_flag_tree_vectorize)))
3d483a94 4278 return 1;
4279
4280 int vs = targetm.vectorize.autovectorize_vector_sizes ();
4281 if (vs)
4282 {
4283 vs = 1 << floor_log2 (vs);
4284 return vs;
4285 }
3754d046 4286 machine_mode vqimode = targetm.vectorize.preferred_simd_mode (QImode);
3d483a94 4287 if (GET_MODE_CLASS (vqimode) == MODE_VECTOR_INT)
4288 return GET_MODE_NUNITS (vqimode);
4289 return 1;
4290}
4291
4292/* Helper function of lower_rec_input_clauses, used for #pragma omp simd
4293 privatization. */
4294
4295static bool
4296lower_rec_simd_input_clauses (tree new_var, omp_context *ctx, int &max_vf,
4297 tree &idx, tree &lane, tree &ivar, tree &lvar)
4298{
4299 if (max_vf == 0)
4300 {
4301 max_vf = omp_max_vf ();
4302 if (max_vf > 1)
4303 {
4304 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
4305 OMP_CLAUSE_SAFELEN);
c3f3b68d 4306 if (c && TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) != INTEGER_CST)
4307 max_vf = 1;
4308 else if (c && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
4309 max_vf) == -1)
d85a2013 4310 max_vf = tree_to_shwi (OMP_CLAUSE_SAFELEN_EXPR (c));
3d483a94 4311 }
4312 if (max_vf > 1)
4313 {
f9e245b2 4314 idx = create_tmp_var (unsigned_type_node);
4315 lane = create_tmp_var (unsigned_type_node);
3d483a94 4316 }
4317 }
4318 if (max_vf == 1)
4319 return false;
4320
4321 tree atype = build_array_type_nelts (TREE_TYPE (new_var), max_vf);
f9e245b2 4322 tree avar = create_tmp_var_raw (atype);
3d483a94 4323 if (TREE_ADDRESSABLE (new_var))
4324 TREE_ADDRESSABLE (avar) = 1;
4325 DECL_ATTRIBUTES (avar)
4326 = tree_cons (get_identifier ("omp simd array"), NULL,
4327 DECL_ATTRIBUTES (avar));
4328 gimple_add_tmp_var (avar);
4329 ivar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, idx,
4330 NULL_TREE, NULL_TREE);
4331 lvar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, lane,
4332 NULL_TREE, NULL_TREE);
bc7bff74 4333 if (DECL_P (new_var))
4334 {
4335 SET_DECL_VALUE_EXPR (new_var, lvar);
4336 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4337 }
3d483a94 4338 return true;
4339}
4340
2712b6de 4341/* Helper function of lower_rec_input_clauses. For a reference
4342 in simd reduction, add an underlying variable it will reference. */
4343
4344static void
4345handle_simd_reference (location_t loc, tree new_vard, gimple_seq *ilist)
4346{
4347 tree z = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard)));
4348 if (TREE_CONSTANT (z))
4349 {
43895be5 4350 z = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_vard)),
4351 get_name (new_vard));
2712b6de 4352 gimple_add_tmp_var (z);
4353 TREE_ADDRESSABLE (z) = 1;
4354 z = build_fold_addr_expr_loc (loc, z);
4355 gimplify_assign (new_vard, z, ilist);
4356 }
4357}
4358
1e8e9920 4359/* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
4360 from the receiver (aka child) side and initializers for REFERENCE_TYPE
4361 private variables. Initialization statements go in ILIST, while calls
4362 to destructors go in DLIST. */
4363
4364static void
75a70cf9 4365lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
bc7bff74 4366 omp_context *ctx, struct omp_for_data *fd)
1e8e9920 4367{
c2f47e15 4368 tree c, dtor, copyin_seq, x, ptr;
1e8e9920 4369 bool copyin_by_ref = false;
f49d7bb5 4370 bool lastprivate_firstprivate = false;
bc7bff74 4371 bool reduction_omp_orig_ref = false;
1e8e9920 4372 int pass;
3d483a94 4373 bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
10c55644 4374 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD);
3d483a94 4375 int max_vf = 0;
4376 tree lane = NULL_TREE, idx = NULL_TREE;
4377 tree ivar = NULL_TREE, lvar = NULL_TREE;
4378 gimple_seq llist[2] = { NULL, NULL };
1e8e9920 4379
1e8e9920 4380 copyin_seq = NULL;
4381
3d483a94 4382 /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
4383 with data sharing clauses referencing variable sized vars. That
4384 is unnecessarily hard to support and very unlikely to result in
4385 vectorized code anyway. */
4386 if (is_simd)
4387 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4388 switch (OMP_CLAUSE_CODE (c))
4389 {
9580cb79 4390 case OMP_CLAUSE_LINEAR:
4391 if (OMP_CLAUSE_LINEAR_ARRAY (c))
4392 max_vf = 1;
4393 /* FALLTHRU */
3d483a94 4394 case OMP_CLAUSE_PRIVATE:
4395 case OMP_CLAUSE_FIRSTPRIVATE:
4396 case OMP_CLAUSE_LASTPRIVATE:
3d483a94 4397 if (is_variable_sized (OMP_CLAUSE_DECL (c)))
4398 max_vf = 1;
4399 break;
43895be5 4400 case OMP_CLAUSE_REDUCTION:
4401 if (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF
4402 || is_variable_sized (OMP_CLAUSE_DECL (c)))
4403 max_vf = 1;
4404 break;
3d483a94 4405 default:
4406 continue;
4407 }
4408
1e8e9920 4409 /* Do all the fixed sized types in the first pass, and the variable sized
4410 types in the second pass. This makes sure that the scalar arguments to
48e1416a 4411 the variable sized types are processed before we use them in the
1e8e9920 4412 variable sized operations. */
4413 for (pass = 0; pass < 2; ++pass)
4414 {
4415 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4416 {
55d6e7cd 4417 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
1e8e9920 4418 tree var, new_var;
4419 bool by_ref;
389dd41b 4420 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
1e8e9920 4421
4422 switch (c_kind)
4423 {
4424 case OMP_CLAUSE_PRIVATE:
4425 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
4426 continue;
4427 break;
4428 case OMP_CLAUSE_SHARED:
bc7bff74 4429 /* Ignore shared directives in teams construct. */
4430 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
4431 continue;
f49d7bb5 4432 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
4433 {
43895be5 4434 gcc_assert (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c)
4435 || is_global_var (OMP_CLAUSE_DECL (c)));
f49d7bb5 4436 continue;
4437 }
1e8e9920 4438 case OMP_CLAUSE_FIRSTPRIVATE:
1e8e9920 4439 case OMP_CLAUSE_COPYIN:
43895be5 4440 break;
bc7bff74 4441 case OMP_CLAUSE_LINEAR:
43895be5 4442 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c)
4443 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
4444 lastprivate_firstprivate = true;
bc7bff74 4445 break;
1e8e9920 4446 case OMP_CLAUSE_REDUCTION:
bc7bff74 4447 if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
4448 reduction_omp_orig_ref = true;
1e8e9920 4449 break;
bc7bff74 4450 case OMP_CLAUSE__LOOPTEMP_:
43895be5 4451 /* Handle _looptemp_ clauses only on parallel/task. */
bc7bff74 4452 if (fd)
4453 continue;
3d483a94 4454 break;
df2c34fc 4455 case OMP_CLAUSE_LASTPRIVATE:
f49d7bb5 4456 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4457 {
4458 lastprivate_firstprivate = true;
43895be5 4459 if (pass != 0 || is_taskloop_ctx (ctx))
f49d7bb5 4460 continue;
4461 }
cf5f881f 4462 /* Even without corresponding firstprivate, if
4463 decl is Fortran allocatable, it needs outer var
4464 reference. */
4465 else if (pass == 0
4466 && lang_hooks.decls.omp_private_outer_ref
4467 (OMP_CLAUSE_DECL (c)))
4468 lastprivate_firstprivate = true;
df2c34fc 4469 break;
bc7bff74 4470 case OMP_CLAUSE_ALIGNED:
4471 if (pass == 0)
4472 continue;
4473 var = OMP_CLAUSE_DECL (c);
4474 if (TREE_CODE (TREE_TYPE (var)) == POINTER_TYPE
4475 && !is_global_var (var))
4476 {
4477 new_var = maybe_lookup_decl (var, ctx);
4478 if (new_var == NULL_TREE)
4479 new_var = maybe_lookup_decl_in_outer_ctx (var, ctx);
4480 x = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
4481 x = build_call_expr_loc (clause_loc, x, 2, new_var,
4482 omp_clause_aligned_alignment (c));
4483 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
4484 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
4485 gimplify_and_add (x, ilist);
4486 }
4487 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
4488 && is_global_var (var))
4489 {
4490 tree ptype = build_pointer_type (TREE_TYPE (var)), t, t2;
4491 new_var = lookup_decl (var, ctx);
4492 t = maybe_lookup_decl_in_outer_ctx (var, ctx);
4493 t = build_fold_addr_expr_loc (clause_loc, t);
4494 t2 = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
4495 t = build_call_expr_loc (clause_loc, t2, 2, t,
4496 omp_clause_aligned_alignment (c));
4497 t = fold_convert_loc (clause_loc, ptype, t);
f9e245b2 4498 x = create_tmp_var (ptype);
bc7bff74 4499 t = build2 (MODIFY_EXPR, ptype, x, t);
4500 gimplify_and_add (t, ilist);
4501 t = build_simple_mem_ref_loc (clause_loc, x);
4502 SET_DECL_VALUE_EXPR (new_var, t);
4503 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4504 }
4505 continue;
1e8e9920 4506 default:
4507 continue;
4508 }
4509
4510 new_var = var = OMP_CLAUSE_DECL (c);
43895be5 4511 if (c_kind == OMP_CLAUSE_REDUCTION && TREE_CODE (var) == MEM_REF)
4512 {
4513 var = TREE_OPERAND (var, 0);
9561765e 4514 if (TREE_CODE (var) == POINTER_PLUS_EXPR)
4515 var = TREE_OPERAND (var, 0);
43895be5 4516 if (TREE_CODE (var) == INDIRECT_REF
4517 || TREE_CODE (var) == ADDR_EXPR)
4518 var = TREE_OPERAND (var, 0);
4519 if (is_variable_sized (var))
4520 {
4521 gcc_assert (DECL_HAS_VALUE_EXPR_P (var));
4522 var = DECL_VALUE_EXPR (var);
4523 gcc_assert (TREE_CODE (var) == INDIRECT_REF);
4524 var = TREE_OPERAND (var, 0);
4525 gcc_assert (DECL_P (var));
4526 }
4527 new_var = var;
4528 }
1e8e9920 4529 if (c_kind != OMP_CLAUSE_COPYIN)
4530 new_var = lookup_decl (var, ctx);
4531
4532 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
4533 {
4534 if (pass != 0)
4535 continue;
4536 }
43895be5 4537 /* C/C++ array section reductions. */
4538 else if (c_kind == OMP_CLAUSE_REDUCTION
4539 && var != OMP_CLAUSE_DECL (c))
1e8e9920 4540 {
4541 if (pass == 0)
4542 continue;
4543
9561765e 4544 tree bias = TREE_OPERAND (OMP_CLAUSE_DECL (c), 1);
43895be5 4545 tree orig_var = TREE_OPERAND (OMP_CLAUSE_DECL (c), 0);
9561765e 4546 if (TREE_CODE (orig_var) == POINTER_PLUS_EXPR)
4547 {
4548 tree b = TREE_OPERAND (orig_var, 1);
4549 b = maybe_lookup_decl (b, ctx);
4550 if (b == NULL)
4551 {
4552 b = TREE_OPERAND (orig_var, 1);
4553 b = maybe_lookup_decl_in_outer_ctx (b, ctx);
4554 }
4555 if (integer_zerop (bias))
4556 bias = b;
4557 else
4558 {
4559 bias = fold_convert_loc (clause_loc,
4560 TREE_TYPE (b), bias);
4561 bias = fold_build2_loc (clause_loc, PLUS_EXPR,
4562 TREE_TYPE (b), b, bias);
4563 }
4564 orig_var = TREE_OPERAND (orig_var, 0);
4565 }
43895be5 4566 if (TREE_CODE (orig_var) == INDIRECT_REF
4567 || TREE_CODE (orig_var) == ADDR_EXPR)
4568 orig_var = TREE_OPERAND (orig_var, 0);
4569 tree d = OMP_CLAUSE_DECL (c);
4570 tree type = TREE_TYPE (d);
4571 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
4572 tree v = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
4573 const char *name = get_name (orig_var);
4574 if (TREE_CONSTANT (v))
fd6481cf 4575 {
43895be5 4576 x = create_tmp_var_raw (type, name);
4577 gimple_add_tmp_var (x);
4578 TREE_ADDRESSABLE (x) = 1;
4579 x = build_fold_addr_expr_loc (clause_loc, x);
4580 }
4581 else
4582 {
4583 tree atmp
4584 = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
4585 tree t = maybe_lookup_decl (v, ctx);
4586 if (t)
4587 v = t;
4588 else
4589 v = maybe_lookup_decl_in_outer_ctx (v, ctx);
4590 gimplify_expr (&v, ilist, NULL, is_gimple_val, fb_rvalue);
4591 t = fold_build2_loc (clause_loc, PLUS_EXPR,
4592 TREE_TYPE (v), v,
4593 build_int_cst (TREE_TYPE (v), 1));
4594 t = fold_build2_loc (clause_loc, MULT_EXPR,
4595 TREE_TYPE (v), t,
4596 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4597 tree al = size_int (TYPE_ALIGN (TREE_TYPE (type)));
4598 x = build_call_expr_loc (clause_loc, atmp, 2, t, al);
4599 }
4600
4601 tree ptype = build_pointer_type (TREE_TYPE (type));
4602 x = fold_convert_loc (clause_loc, ptype, x);
4603 tree y = create_tmp_var (ptype, name);
4604 gimplify_assign (y, x, ilist);
4605 x = y;
9561765e 4606 tree yb = y;
4607
4608 if (!integer_zerop (bias))
4609 {
219e09fc 4610 bias = fold_convert_loc (clause_loc, pointer_sized_int_node,
4611 bias);
4612 yb = fold_convert_loc (clause_loc, pointer_sized_int_node,
4613 x);
4614 yb = fold_build2_loc (clause_loc, MINUS_EXPR,
4615 pointer_sized_int_node, yb, bias);
4616 x = fold_convert_loc (clause_loc, TREE_TYPE (x), yb);
9561765e 4617 yb = create_tmp_var (ptype, name);
4618 gimplify_assign (yb, x, ilist);
4619 x = yb;
4620 }
4621
4622 d = TREE_OPERAND (d, 0);
4623 if (TREE_CODE (d) == POINTER_PLUS_EXPR)
4624 d = TREE_OPERAND (d, 0);
4625 if (TREE_CODE (d) == ADDR_EXPR)
43895be5 4626 {
4627 if (orig_var != var)
4628 {
4629 gcc_assert (is_variable_sized (orig_var));
4630 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var),
4631 x);
4632 gimplify_assign (new_var, x, ilist);
4633 tree new_orig_var = lookup_decl (orig_var, ctx);
4634 tree t = build_fold_indirect_ref (new_var);
4635 DECL_IGNORED_P (new_var) = 0;
4636 TREE_THIS_NOTRAP (t);
4637 SET_DECL_VALUE_EXPR (new_orig_var, t);
4638 DECL_HAS_VALUE_EXPR_P (new_orig_var) = 1;
4639 }
4640 else
4641 {
4642 x = build2 (MEM_REF, TREE_TYPE (new_var), x,
4643 build_int_cst (ptype, 0));
4644 SET_DECL_VALUE_EXPR (new_var, x);
4645 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4646 }
4647 }
4648 else
4649 {
4650 gcc_assert (orig_var == var);
9561765e 4651 if (TREE_CODE (d) == INDIRECT_REF)
43895be5 4652 {
4653 x = create_tmp_var (ptype, name);
4654 TREE_ADDRESSABLE (x) = 1;
9561765e 4655 gimplify_assign (x, yb, ilist);
43895be5 4656 x = build_fold_addr_expr_loc (clause_loc, x);
4657 }
4658 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
4659 gimplify_assign (new_var, x, ilist);
4660 }
4661 tree y1 = create_tmp_var (ptype, NULL);
4662 gimplify_assign (y1, y, ilist);
4663 tree i2 = NULL_TREE, y2 = NULL_TREE;
4664 tree body2 = NULL_TREE, end2 = NULL_TREE;
4665 tree y3 = NULL_TREE, y4 = NULL_TREE;
4666 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) || is_simd)
4667 {
4668 y2 = create_tmp_var (ptype, NULL);
4669 gimplify_assign (y2, y, ilist);
4670 tree ref = build_outer_var_ref (var, ctx);
4671 /* For ref build_outer_var_ref already performs this. */
9561765e 4672 if (TREE_CODE (d) == INDIRECT_REF)
43895be5 4673 gcc_assert (is_reference (var));
9561765e 4674 else if (TREE_CODE (d) == ADDR_EXPR)
43895be5 4675 ref = build_fold_addr_expr (ref);
4676 else if (is_reference (var))
4677 ref = build_fold_addr_expr (ref);
4678 ref = fold_convert_loc (clause_loc, ptype, ref);
4679 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
4680 && OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
4681 {
4682 y3 = create_tmp_var (ptype, NULL);
4683 gimplify_assign (y3, unshare_expr (ref), ilist);
4684 }
4685 if (is_simd)
4686 {
4687 y4 = create_tmp_var (ptype, NULL);
4688 gimplify_assign (y4, ref, dlist);
4689 }
4690 }
4691 tree i = create_tmp_var (TREE_TYPE (v), NULL);
4692 gimplify_assign (i, build_int_cst (TREE_TYPE (v), 0), ilist);
4693 tree body = create_artificial_label (UNKNOWN_LOCATION);
4694 tree end = create_artificial_label (UNKNOWN_LOCATION);
4695 gimple_seq_add_stmt (ilist, gimple_build_label (body));
4696 if (y2)
4697 {
4698 i2 = create_tmp_var (TREE_TYPE (v), NULL);
4699 gimplify_assign (i2, build_int_cst (TREE_TYPE (v), 0), dlist);
4700 body2 = create_artificial_label (UNKNOWN_LOCATION);
4701 end2 = create_artificial_label (UNKNOWN_LOCATION);
4702 gimple_seq_add_stmt (dlist, gimple_build_label (body2));
4703 }
4704 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4705 {
4706 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
4707 tree decl_placeholder
4708 = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c);
4709 SET_DECL_VALUE_EXPR (decl_placeholder,
4710 build_simple_mem_ref (y1));
4711 DECL_HAS_VALUE_EXPR_P (decl_placeholder) = 1;
4712 SET_DECL_VALUE_EXPR (placeholder,
4713 y3 ? build_simple_mem_ref (y3)
4714 : error_mark_node);
4715 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
4716 x = lang_hooks.decls.omp_clause_default_ctor
4717 (c, build_simple_mem_ref (y1),
4718 y3 ? build_simple_mem_ref (y3) : NULL_TREE);
4719 if (x)
4720 gimplify_and_add (x, ilist);
4721 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
4722 {
4723 gimple_seq tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
4724 lower_omp (&tseq, ctx);
4725 gimple_seq_add_seq (ilist, tseq);
4726 }
4727 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
4728 if (is_simd)
4729 {
4730 SET_DECL_VALUE_EXPR (decl_placeholder,
4731 build_simple_mem_ref (y2));
4732 SET_DECL_VALUE_EXPR (placeholder,
4733 build_simple_mem_ref (y4));
4734 gimple_seq tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
4735 lower_omp (&tseq, ctx);
4736 gimple_seq_add_seq (dlist, tseq);
4737 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4738 }
4739 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
4740 DECL_HAS_VALUE_EXPR_P (decl_placeholder) = 0;
4741 x = lang_hooks.decls.omp_clause_dtor
4742 (c, build_simple_mem_ref (y2));
4743 if (x)
4744 {
4745 gimple_seq tseq = NULL;
4746 dtor = x;
4747 gimplify_stmt (&dtor, &tseq);
4748 gimple_seq_add_seq (dlist, tseq);
4749 }
4750 }
4751 else
4752 {
4753 x = omp_reduction_init (c, TREE_TYPE (type));
4754 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
4755
4756 /* reduction(-:var) sums up the partial results, so it
4757 acts identically to reduction(+:var). */
4758 if (code == MINUS_EXPR)
4759 code = PLUS_EXPR;
4760
4761 gimplify_assign (build_simple_mem_ref (y1), x, ilist);
4762 if (is_simd)
4763 {
4764 x = build2 (code, TREE_TYPE (type),
4765 build_simple_mem_ref (y4),
4766 build_simple_mem_ref (y2));
4767 gimplify_assign (build_simple_mem_ref (y4), x, dlist);
4768 }
4769 }
4770 gimple *g
4771 = gimple_build_assign (y1, POINTER_PLUS_EXPR, y1,
4772 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4773 gimple_seq_add_stmt (ilist, g);
4774 if (y3)
4775 {
4776 g = gimple_build_assign (y3, POINTER_PLUS_EXPR, y3,
4777 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4778 gimple_seq_add_stmt (ilist, g);
4779 }
4780 g = gimple_build_assign (i, PLUS_EXPR, i,
4781 build_int_cst (TREE_TYPE (i), 1));
4782 gimple_seq_add_stmt (ilist, g);
4783 g = gimple_build_cond (LE_EXPR, i, v, body, end);
4784 gimple_seq_add_stmt (ilist, g);
4785 gimple_seq_add_stmt (ilist, gimple_build_label (end));
4786 if (y2)
4787 {
4788 g = gimple_build_assign (y2, POINTER_PLUS_EXPR, y2,
4789 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4790 gimple_seq_add_stmt (dlist, g);
4791 if (y4)
4792 {
4793 g = gimple_build_assign
4794 (y4, POINTER_PLUS_EXPR, y4,
4795 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4796 gimple_seq_add_stmt (dlist, g);
4797 }
4798 g = gimple_build_assign (i2, PLUS_EXPR, i2,
4799 build_int_cst (TREE_TYPE (i2), 1));
4800 gimple_seq_add_stmt (dlist, g);
4801 g = gimple_build_cond (LE_EXPR, i2, v, body2, end2);
4802 gimple_seq_add_stmt (dlist, g);
4803 gimple_seq_add_stmt (dlist, gimple_build_label (end2));
4804 }
4805 continue;
4806 }
4807 else if (is_variable_sized (var))
4808 {
4809 /* For variable sized types, we need to allocate the
4810 actual storage here. Call alloca and store the
4811 result in the pointer decl that we created elsewhere. */
4812 if (pass == 0)
4813 continue;
4814
4815 if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
4816 {
4817 gcall *stmt;
4818 tree tmp, atmp;
4819
4820 ptr = DECL_VALUE_EXPR (new_var);
4821 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
4822 ptr = TREE_OPERAND (ptr, 0);
fd6481cf 4823 gcc_assert (DECL_P (ptr));
4824 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
75a70cf9 4825
4826 /* void *tmp = __builtin_alloca */
43895be5 4827 atmp = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
4828 stmt = gimple_build_call (atmp, 2, x,
4829 size_int (DECL_ALIGN (var)));
f9e245b2 4830 tmp = create_tmp_var_raw (ptr_type_node);
75a70cf9 4831 gimple_add_tmp_var (tmp);
4832 gimple_call_set_lhs (stmt, tmp);
4833
4834 gimple_seq_add_stmt (ilist, stmt);
4835
389dd41b 4836 x = fold_convert_loc (clause_loc, TREE_TYPE (ptr), tmp);
75a70cf9 4837 gimplify_assign (ptr, x, ilist);
fd6481cf 4838 }
1e8e9920 4839 }
b656be3a 4840 else if (is_reference (var) && !is_oacc_parallel (ctx))
1e8e9920 4841 {
773c5ba7 4842 /* For references that are being privatized for Fortran,
4843 allocate new backing storage for the new pointer
4844 variable. This allows us to avoid changing all the
4845 code that expects a pointer to something that expects
bc7bff74 4846 a direct variable. */
1e8e9920 4847 if (pass == 0)
4848 continue;
4849
4850 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
fd6481cf 4851 if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx))
4852 {
4853 x = build_receiver_ref (var, false, ctx);
389dd41b 4854 x = build_fold_addr_expr_loc (clause_loc, x);
fd6481cf 4855 }
4856 else if (TREE_CONSTANT (x))
1e8e9920 4857 {
2712b6de 4858 /* For reduction in SIMD loop, defer adding the
4859 initialization of the reference, because if we decide
4860 to use SIMD array for it, the initilization could cause
4861 expansion ICE. */
4862 if (c_kind == OMP_CLAUSE_REDUCTION && is_simd)
09d1c205 4863 x = NULL_TREE;
4864 else
4865 {
09d1c205 4866 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
43895be5 4867 get_name (var));
09d1c205 4868 gimple_add_tmp_var (x);
4869 TREE_ADDRESSABLE (x) = 1;
4870 x = build_fold_addr_expr_loc (clause_loc, x);
4871 }
1e8e9920 4872 }
4873 else
4874 {
43895be5 4875 tree atmp
4876 = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
4877 tree rtype = TREE_TYPE (TREE_TYPE (new_var));
4878 tree al = size_int (TYPE_ALIGN (rtype));
4879 x = build_call_expr_loc (clause_loc, atmp, 2, x, al);
1e8e9920 4880 }
4881
09d1c205 4882 if (x)
4883 {
4884 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
4885 gimplify_assign (new_var, x, ilist);
4886 }
1e8e9920 4887
182cf5a9 4888 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
1e8e9920 4889 }
4890 else if (c_kind == OMP_CLAUSE_REDUCTION
4891 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4892 {
4893 if (pass == 0)
4894 continue;
4895 }
4896 else if (pass != 0)
4897 continue;
4898
55d6e7cd 4899 switch (OMP_CLAUSE_CODE (c))
1e8e9920 4900 {
4901 case OMP_CLAUSE_SHARED:
bc7bff74 4902 /* Ignore shared directives in teams construct. */
4903 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
4904 continue;
f49d7bb5 4905 /* Shared global vars are just accessed directly. */
4906 if (is_global_var (new_var))
4907 break;
43895be5 4908 /* For taskloop firstprivate/lastprivate, represented
4909 as firstprivate and shared clause on the task, new_var
4910 is the firstprivate var. */
4911 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
4912 break;
1e8e9920 4913 /* Set up the DECL_VALUE_EXPR for shared variables now. This
4914 needs to be delayed until after fixup_child_record_type so
4915 that we get the correct type during the dereference. */
e8a588af 4916 by_ref = use_pointer_for_field (var, ctx);
1e8e9920 4917 x = build_receiver_ref (var, by_ref, ctx);
4918 SET_DECL_VALUE_EXPR (new_var, x);
4919 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4920
4921 /* ??? If VAR is not passed by reference, and the variable
4922 hasn't been initialized yet, then we'll get a warning for
4923 the store into the omp_data_s structure. Ideally, we'd be
48e1416a 4924 able to notice this and not store anything at all, but
1e8e9920 4925 we're generating code too early. Suppress the warning. */
4926 if (!by_ref)
4927 TREE_NO_WARNING (var) = 1;
4928 break;
4929
4930 case OMP_CLAUSE_LASTPRIVATE:
4931 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4932 break;
4933 /* FALLTHRU */
4934
4935 case OMP_CLAUSE_PRIVATE:
fd6481cf 4936 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE)
4937 x = build_outer_var_ref (var, ctx);
4938 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
4939 {
4940 if (is_task_ctx (ctx))
4941 x = build_receiver_ref (var, false, ctx);
4942 else
4943 x = build_outer_var_ref (var, ctx);
4944 }
4945 else
4946 x = NULL;
3d483a94 4947 do_private:
bc7bff74 4948 tree nx;
43895be5 4949 nx = lang_hooks.decls.omp_clause_default_ctor
4950 (c, unshare_expr (new_var), x);
3d483a94 4951 if (is_simd)
4952 {
4953 tree y = lang_hooks.decls.omp_clause_dtor (c, new_var);
bc7bff74 4954 if ((TREE_ADDRESSABLE (new_var) || nx || y
3d483a94 4955 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
4956 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4957 idx, lane, ivar, lvar))
4958 {
bc7bff74 4959 if (nx)
3d483a94 4960 x = lang_hooks.decls.omp_clause_default_ctor
4961 (c, unshare_expr (ivar), x);
bc7bff74 4962 if (nx && x)
3d483a94 4963 gimplify_and_add (x, &llist[0]);
4964 if (y)
4965 {
4966 y = lang_hooks.decls.omp_clause_dtor (c, ivar);
4967 if (y)
4968 {
4969 gimple_seq tseq = NULL;
4970
4971 dtor = y;
4972 gimplify_stmt (&dtor, &tseq);
4973 gimple_seq_add_seq (&llist[1], tseq);
4974 }
4975 }
4976 break;
4977 }
4978 }
bc7bff74 4979 if (nx)
4980 gimplify_and_add (nx, ilist);
1e8e9920 4981 /* FALLTHRU */
4982
4983 do_dtor:
4984 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
4985 if (x)
4986 {
75a70cf9 4987 gimple_seq tseq = NULL;
4988
1e8e9920 4989 dtor = x;
75a70cf9 4990 gimplify_stmt (&dtor, &tseq);
e3a19533 4991 gimple_seq_add_seq (dlist, tseq);
1e8e9920 4992 }
4993 break;
4994
3d483a94 4995 case OMP_CLAUSE_LINEAR:
4996 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c))
4997 goto do_firstprivate;
4998 if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
4999 x = NULL;
5000 else
5001 x = build_outer_var_ref (var, ctx);
5002 goto do_private;
5003
1e8e9920 5004 case OMP_CLAUSE_FIRSTPRIVATE:
fd6481cf 5005 if (is_task_ctx (ctx))
5006 {
5007 if (is_reference (var) || is_variable_sized (var))
5008 goto do_dtor;
5009 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var,
5010 ctx))
5011 || use_pointer_for_field (var, NULL))
5012 {
5013 x = build_receiver_ref (var, false, ctx);
5014 SET_DECL_VALUE_EXPR (new_var, x);
5015 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
5016 goto do_dtor;
5017 }
5018 }
3d483a94 5019 do_firstprivate:
1e8e9920 5020 x = build_outer_var_ref (var, ctx);
3d483a94 5021 if (is_simd)
5022 {
bc7bff74 5023 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
5024 && gimple_omp_for_combined_into_p (ctx->stmt))
5025 {
9580cb79 5026 tree t = OMP_CLAUSE_LINEAR_STEP (c);
5027 tree stept = TREE_TYPE (t);
5028 tree ct = find_omp_clause (clauses,
5029 OMP_CLAUSE__LOOPTEMP_);
5030 gcc_assert (ct);
5031 tree l = OMP_CLAUSE_DECL (ct);
e471cc6f 5032 tree n1 = fd->loop.n1;
5033 tree step = fd->loop.step;
5034 tree itype = TREE_TYPE (l);
5035 if (POINTER_TYPE_P (itype))
5036 itype = signed_type_for (itype);
5037 l = fold_build2 (MINUS_EXPR, itype, l, n1);
5038 if (TYPE_UNSIGNED (itype)
5039 && fd->loop.cond_code == GT_EXPR)
5040 l = fold_build2 (TRUNC_DIV_EXPR, itype,
5041 fold_build1 (NEGATE_EXPR, itype, l),
5042 fold_build1 (NEGATE_EXPR,
5043 itype, step));
5044 else
5045 l = fold_build2 (TRUNC_DIV_EXPR, itype, l, step);
bc7bff74 5046 t = fold_build2 (MULT_EXPR, stept,
5047 fold_convert (stept, l), t);
9580cb79 5048
5049 if (OMP_CLAUSE_LINEAR_ARRAY (c))
5050 {
5051 x = lang_hooks.decls.omp_clause_linear_ctor
5052 (c, new_var, x, t);
5053 gimplify_and_add (x, ilist);
5054 goto do_dtor;
5055 }
5056
bc7bff74 5057 if (POINTER_TYPE_P (TREE_TYPE (x)))
5058 x = fold_build2 (POINTER_PLUS_EXPR,
5059 TREE_TYPE (x), x, t);
5060 else
5061 x = fold_build2 (PLUS_EXPR, TREE_TYPE (x), x, t);
5062 }
5063
3d483a94 5064 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
5065 || TREE_ADDRESSABLE (new_var))
5066 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
5067 idx, lane, ivar, lvar))
5068 {
5069 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR)
5070 {
f9e245b2 5071 tree iv = create_tmp_var (TREE_TYPE (new_var));
3d483a94 5072 x = lang_hooks.decls.omp_clause_copy_ctor (c, iv, x);
5073 gimplify_and_add (x, ilist);
5074 gimple_stmt_iterator gsi
5075 = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
1a91d914 5076 gassign *g
3d483a94 5077 = gimple_build_assign (unshare_expr (lvar), iv);
5078 gsi_insert_before_without_update (&gsi, g,
5079 GSI_SAME_STMT);
9580cb79 5080 tree t = OMP_CLAUSE_LINEAR_STEP (c);
3d483a94 5081 enum tree_code code = PLUS_EXPR;
5082 if (POINTER_TYPE_P (TREE_TYPE (new_var)))
5083 code = POINTER_PLUS_EXPR;
e9cf809e 5084 g = gimple_build_assign (iv, code, iv, t);
3d483a94 5085 gsi_insert_before_without_update (&gsi, g,
5086 GSI_SAME_STMT);
5087 break;
5088 }
5089 x = lang_hooks.decls.omp_clause_copy_ctor
5090 (c, unshare_expr (ivar), x);
5091 gimplify_and_add (x, &llist[0]);
5092 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
5093 if (x)
5094 {
5095 gimple_seq tseq = NULL;
5096
5097 dtor = x;
5098 gimplify_stmt (&dtor, &tseq);
5099 gimple_seq_add_seq (&llist[1], tseq);
5100 }
5101 break;
5102 }
5103 }
43895be5 5104 x = lang_hooks.decls.omp_clause_copy_ctor
5105 (c, unshare_expr (new_var), x);
1e8e9920 5106 gimplify_and_add (x, ilist);
5107 goto do_dtor;
1e8e9920 5108
bc7bff74 5109 case OMP_CLAUSE__LOOPTEMP_:
43895be5 5110 gcc_assert (is_taskreg_ctx (ctx));
bc7bff74 5111 x = build_outer_var_ref (var, ctx);
5112 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
5113 gimplify_and_add (x, ilist);
5114 break;
5115
1e8e9920 5116 case OMP_CLAUSE_COPYIN:
e8a588af 5117 by_ref = use_pointer_for_field (var, NULL);
1e8e9920 5118 x = build_receiver_ref (var, by_ref, ctx);
5119 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
5120 append_to_statement_list (x, &copyin_seq);
5121 copyin_by_ref |= by_ref;
5122 break;
5123
5124 case OMP_CLAUSE_REDUCTION:
641a0fa1 5125 /* OpenACC reductions are initialized using the
5126 GOACC_REDUCTION internal function. */
5127 if (is_gimple_omp_oacc (ctx->stmt))
5128 break;
1e8e9920 5129 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
5130 {
fd6481cf 5131 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
42acab1c 5132 gimple *tseq;
fd6481cf 5133 x = build_outer_var_ref (var, ctx);
5134
bc7bff74 5135 if (is_reference (var)
5136 && !useless_type_conversion_p (TREE_TYPE (placeholder),
5137 TREE_TYPE (x)))
389dd41b 5138 x = build_fold_addr_expr_loc (clause_loc, x);
fd6481cf 5139 SET_DECL_VALUE_EXPR (placeholder, x);
5140 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
bc7bff74 5141 tree new_vard = new_var;
5142 if (is_reference (var))
5143 {
5144 gcc_assert (TREE_CODE (new_var) == MEM_REF);
5145 new_vard = TREE_OPERAND (new_var, 0);
5146 gcc_assert (DECL_P (new_vard));
5147 }
3d483a94 5148 if (is_simd
5149 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
5150 idx, lane, ivar, lvar))
5151 {
bc7bff74 5152 if (new_vard == new_var)
5153 {
5154 gcc_assert (DECL_VALUE_EXPR (new_var) == lvar);
5155 SET_DECL_VALUE_EXPR (new_var, ivar);
5156 }
5157 else
5158 {
5159 SET_DECL_VALUE_EXPR (new_vard,
5160 build_fold_addr_expr (ivar));
5161 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
5162 }
5163 x = lang_hooks.decls.omp_clause_default_ctor
5164 (c, unshare_expr (ivar),
5165 build_outer_var_ref (var, ctx));
5166 if (x)
5167 gimplify_and_add (x, &llist[0]);
5168 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
5169 {
5170 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
5171 lower_omp (&tseq, ctx);
5172 gimple_seq_add_seq (&llist[0], tseq);
5173 }
5174 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
5175 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
5176 lower_omp (&tseq, ctx);
5177 gimple_seq_add_seq (&llist[1], tseq);
5178 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
5179 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
5180 if (new_vard == new_var)
5181 SET_DECL_VALUE_EXPR (new_var, lvar);
5182 else
5183 SET_DECL_VALUE_EXPR (new_vard,
5184 build_fold_addr_expr (lvar));
5185 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
5186 if (x)
5187 {
5188 tseq = NULL;
5189 dtor = x;
5190 gimplify_stmt (&dtor, &tseq);
5191 gimple_seq_add_seq (&llist[1], tseq);
5192 }
5193 break;
5194 }
09d1c205 5195 /* If this is a reference to constant size reduction var
5196 with placeholder, we haven't emitted the initializer
5197 for it because it is undesirable if SIMD arrays are used.
5198 But if they aren't used, we need to emit the deferred
5199 initialization now. */
5200 else if (is_reference (var) && is_simd)
2712b6de 5201 handle_simd_reference (clause_loc, new_vard, ilist);
bc7bff74 5202 x = lang_hooks.decls.omp_clause_default_ctor
cf5f881f 5203 (c, unshare_expr (new_var),
5204 build_outer_var_ref (var, ctx));
bc7bff74 5205 if (x)
5206 gimplify_and_add (x, ilist);
5207 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
5208 {
5209 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
5210 lower_omp (&tseq, ctx);
5211 gimple_seq_add_seq (ilist, tseq);
5212 }
75a70cf9 5213 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
bc7bff74 5214 if (is_simd)
5215 {
5216 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
5217 lower_omp (&tseq, ctx);
5218 gimple_seq_add_seq (dlist, tseq);
5219 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
5220 }
fd6481cf 5221 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
bc7bff74 5222 goto do_dtor;
1e8e9920 5223 }
5224 else
5225 {
5226 x = omp_reduction_init (c, TREE_TYPE (new_var));
5227 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
c22ad515 5228 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
5229
5230 /* reduction(-:var) sums up the partial results, so it
5231 acts identically to reduction(+:var). */
5232 if (code == MINUS_EXPR)
5233 code = PLUS_EXPR;
5234
2712b6de 5235 tree new_vard = new_var;
5236 if (is_simd && is_reference (var))
5237 {
5238 gcc_assert (TREE_CODE (new_var) == MEM_REF);
5239 new_vard = TREE_OPERAND (new_var, 0);
5240 gcc_assert (DECL_P (new_vard));
5241 }
3d483a94 5242 if (is_simd
5243 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
5244 idx, lane, ivar, lvar))
5245 {
3d483a94 5246 tree ref = build_outer_var_ref (var, ctx);
5247
5248 gimplify_assign (unshare_expr (ivar), x, &llist[0]);
5249
3d483a94 5250 x = build2 (code, TREE_TYPE (ref), ref, ivar);
5251 ref = build_outer_var_ref (var, ctx);
5252 gimplify_assign (ref, x, &llist[1]);
2712b6de 5253
5254 if (new_vard != new_var)
5255 {
5256 SET_DECL_VALUE_EXPR (new_vard,
5257 build_fold_addr_expr (lvar));
5258 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
5259 }
3d483a94 5260 }
5261 else
5262 {
2712b6de 5263 if (is_reference (var) && is_simd)
5264 handle_simd_reference (clause_loc, new_vard, ilist);
3d483a94 5265 gimplify_assign (new_var, x, ilist);
5266 if (is_simd)
c22ad515 5267 {
5268 tree ref = build_outer_var_ref (var, ctx);
5269
5270 x = build2 (code, TREE_TYPE (ref), ref, new_var);
5271 ref = build_outer_var_ref (var, ctx);
5272 gimplify_assign (ref, x, dlist);
5273 }
3d483a94 5274 }
1e8e9920 5275 }
5276 break;
5277
5278 default:
5279 gcc_unreachable ();
5280 }
5281 }
5282 }
5283
3d483a94 5284 if (lane)
5285 {
5286 tree uid = create_tmp_var (ptr_type_node, "simduid");
8e1a382d 5287 /* Don't want uninit warnings on simduid, it is always uninitialized,
5288 but we use it not for the value, but for the DECL_UID only. */
5289 TREE_NO_WARNING (uid) = 1;
42acab1c 5290 gimple *g
3d483a94 5291 = gimple_build_call_internal (IFN_GOMP_SIMD_LANE, 1, uid);
5292 gimple_call_set_lhs (g, lane);
5293 gimple_stmt_iterator gsi = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
5294 gsi_insert_before_without_update (&gsi, g, GSI_SAME_STMT);
5295 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SIMDUID_);
5296 OMP_CLAUSE__SIMDUID__DECL (c) = uid;
5297 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
5298 gimple_omp_for_set_clauses (ctx->stmt, c);
e9cf809e 5299 g = gimple_build_assign (lane, INTEGER_CST,
5300 build_int_cst (unsigned_type_node, 0));
3d483a94 5301 gimple_seq_add_stmt (ilist, g);
5302 for (int i = 0; i < 2; i++)
5303 if (llist[i])
5304 {
f9e245b2 5305 tree vf = create_tmp_var (unsigned_type_node);
3d483a94 5306 g = gimple_build_call_internal (IFN_GOMP_SIMD_VF, 1, uid);
5307 gimple_call_set_lhs (g, vf);
5308 gimple_seq *seq = i == 0 ? ilist : dlist;
5309 gimple_seq_add_stmt (seq, g);
5310 tree t = build_int_cst (unsigned_type_node, 0);
e9cf809e 5311 g = gimple_build_assign (idx, INTEGER_CST, t);
3d483a94 5312 gimple_seq_add_stmt (seq, g);
5313 tree body = create_artificial_label (UNKNOWN_LOCATION);
5314 tree header = create_artificial_label (UNKNOWN_LOCATION);
5315 tree end = create_artificial_label (UNKNOWN_LOCATION);
5316 gimple_seq_add_stmt (seq, gimple_build_goto (header));
5317 gimple_seq_add_stmt (seq, gimple_build_label (body));
5318 gimple_seq_add_seq (seq, llist[i]);
5319 t = build_int_cst (unsigned_type_node, 1);
e9cf809e 5320 g = gimple_build_assign (idx, PLUS_EXPR, idx, t);
3d483a94 5321 gimple_seq_add_stmt (seq, g);
5322 gimple_seq_add_stmt (seq, gimple_build_label (header));
5323 g = gimple_build_cond (LT_EXPR, idx, vf, body, end);
5324 gimple_seq_add_stmt (seq, g);
5325 gimple_seq_add_stmt (seq, gimple_build_label (end));
5326 }
5327 }
5328
1e8e9920 5329 /* The copyin sequence is not to be executed by the main thread, since
5330 that would result in self-copies. Perhaps not visible to scalars,
5331 but it certainly is to C++ operator=. */
5332 if (copyin_seq)
5333 {
b9a16870 5334 x = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM),
5335 0);
1e8e9920 5336 x = build2 (NE_EXPR, boolean_type_node, x,
5337 build_int_cst (TREE_TYPE (x), 0));
5338 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
5339 gimplify_and_add (x, ilist);
5340 }
5341
5342 /* If any copyin variable is passed by reference, we must ensure the
5343 master thread doesn't modify it before it is copied over in all
f49d7bb5 5344 threads. Similarly for variables in both firstprivate and
5345 lastprivate clauses we need to ensure the lastprivate copying
bc7bff74 5346 happens after firstprivate copying in all threads. And similarly
5347 for UDRs if initializer expression refers to omp_orig. */
5348 if (copyin_by_ref || lastprivate_firstprivate || reduction_omp_orig_ref)
3d483a94 5349 {
5350 /* Don't add any barrier for #pragma omp simd or
5351 #pragma omp distribute. */
5352 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
7c01fa6c 5353 || gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_FOR)
bc7bff74 5354 gimple_seq_add_stmt (ilist, build_omp_barrier (NULL_TREE));
3d483a94 5355 }
5356
5357 /* If max_vf is non-zero, then we can use only a vectorization factor
5358 up to the max_vf we chose. So stick it into the safelen clause. */
5359 if (max_vf)
5360 {
5361 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
5362 OMP_CLAUSE_SAFELEN);
5363 if (c == NULL_TREE
c3f3b68d 5364 || (TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) == INTEGER_CST
5365 && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
5366 max_vf) == 1))
3d483a94 5367 {
5368 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_SAFELEN);
5369 OMP_CLAUSE_SAFELEN_EXPR (c) = build_int_cst (integer_type_node,
5370 max_vf);
5371 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
5372 gimple_omp_for_set_clauses (ctx->stmt, c);
5373 }
5374 }
1e8e9920 5375}
5376
773c5ba7 5377
1e8e9920 5378/* Generate code to implement the LASTPRIVATE clauses. This is used for
5379 both parallel and workshare constructs. PREDICATE may be NULL if it's
5380 always true. */
5381
5382static void
75a70cf9 5383lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
bc7bff74 5384 omp_context *ctx)
1e8e9920 5385{
3d483a94 5386 tree x, c, label = NULL, orig_clauses = clauses;
fd6481cf 5387 bool par_clauses = false;
3d483a94 5388 tree simduid = NULL, lastlane = NULL;
1e8e9920 5389
3d483a94 5390 /* Early exit if there are no lastprivate or linear clauses. */
5391 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
5392 if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LASTPRIVATE
5393 || (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LINEAR
5394 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses)))
5395 break;
1e8e9920 5396 if (clauses == NULL)
5397 {
5398 /* If this was a workshare clause, see if it had been combined
5399 with its parallel. In that case, look for the clauses on the
5400 parallel statement itself. */
5401 if (is_parallel_ctx (ctx))
5402 return;
5403
5404 ctx = ctx->outer;
5405 if (ctx == NULL || !is_parallel_ctx (ctx))
5406 return;
5407
75a70cf9 5408 clauses = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
1e8e9920 5409 OMP_CLAUSE_LASTPRIVATE);
5410 if (clauses == NULL)
5411 return;
fd6481cf 5412 par_clauses = true;
1e8e9920 5413 }
5414
75a70cf9 5415 if (predicate)
5416 {
1a91d914 5417 gcond *stmt;
75a70cf9 5418 tree label_true, arm1, arm2;
5419
e60a6f7b 5420 label = create_artificial_label (UNKNOWN_LOCATION);
5421 label_true = create_artificial_label (UNKNOWN_LOCATION);
75a70cf9 5422 arm1 = TREE_OPERAND (predicate, 0);
5423 arm2 = TREE_OPERAND (predicate, 1);
5424 gimplify_expr (&arm1, stmt_list, NULL, is_gimple_val, fb_rvalue);
5425 gimplify_expr (&arm2, stmt_list, NULL, is_gimple_val, fb_rvalue);
5426 stmt = gimple_build_cond (TREE_CODE (predicate), arm1, arm2,
5427 label_true, label);
5428 gimple_seq_add_stmt (stmt_list, stmt);
5429 gimple_seq_add_stmt (stmt_list, gimple_build_label (label_true));
5430 }
1e8e9920 5431
3d483a94 5432 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
10c55644 5433 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3d483a94 5434 {
5435 simduid = find_omp_clause (orig_clauses, OMP_CLAUSE__SIMDUID_);
5436 if (simduid)
5437 simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
5438 }
5439
fd6481cf 5440 for (c = clauses; c ;)
1e8e9920 5441 {
5442 tree var, new_var;
389dd41b 5443 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
1e8e9920 5444
3d483a94 5445 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5446 || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
5447 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
fd6481cf 5448 {
5449 var = OMP_CLAUSE_DECL (c);
43895be5 5450 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5451 && OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c)
5452 && is_taskloop_ctx (ctx))
5453 {
5454 gcc_checking_assert (ctx->outer && is_task_ctx (ctx->outer));
5455 new_var = lookup_decl (var, ctx->outer);
5456 }
5457 else
5458 new_var = lookup_decl (var, ctx);
1e8e9920 5459
3d483a94 5460 if (simduid && DECL_HAS_VALUE_EXPR_P (new_var))
5461 {
5462 tree val = DECL_VALUE_EXPR (new_var);
5463 if (TREE_CODE (val) == ARRAY_REF
5464 && VAR_P (TREE_OPERAND (val, 0))
5465 && lookup_attribute ("omp simd array",
5466 DECL_ATTRIBUTES (TREE_OPERAND (val,
5467 0))))
5468 {
5469 if (lastlane == NULL)
5470 {
f9e245b2 5471 lastlane = create_tmp_var (unsigned_type_node);
1a91d914 5472 gcall *g
3d483a94 5473 = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE,
5474 2, simduid,
5475 TREE_OPERAND (val, 1));
5476 gimple_call_set_lhs (g, lastlane);
5477 gimple_seq_add_stmt (stmt_list, g);
5478 }
5479 new_var = build4 (ARRAY_REF, TREE_TYPE (val),
5480 TREE_OPERAND (val, 0), lastlane,
5481 NULL_TREE, NULL_TREE);
5482 }
5483 }
5484
5485 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5486 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
75a70cf9 5487 {
e3a19533 5488 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
75a70cf9 5489 gimple_seq_add_seq (stmt_list,
5490 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
3d483a94 5491 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) = NULL;
75a70cf9 5492 }
2b536a17 5493 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
5494 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
5495 {
5496 lower_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
5497 gimple_seq_add_seq (stmt_list,
5498 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c));
5499 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c) = NULL;
5500 }
1e8e9920 5501
43895be5 5502 x = NULL_TREE;
5503 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5504 && OMP_CLAUSE_LASTPRIVATE_TASKLOOP_IV (c))
5505 {
5506 gcc_checking_assert (is_taskloop_ctx (ctx));
5507 tree ovar = maybe_lookup_decl_in_outer_ctx (var,
5508 ctx->outer->outer);
5509 if (is_global_var (ovar))
5510 x = ovar;
5511 }
5512 if (!x)
5513 x = build_outer_var_ref (var, ctx, true);
fd6481cf 5514 if (is_reference (var))
182cf5a9 5515 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
fd6481cf 5516 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
75a70cf9 5517 gimplify_and_add (x, stmt_list);
fd6481cf 5518 }
5519 c = OMP_CLAUSE_CHAIN (c);
5520 if (c == NULL && !par_clauses)
5521 {
5522 /* If this was a workshare clause, see if it had been combined
5523 with its parallel. In that case, continue looking for the
5524 clauses also on the parallel statement itself. */
5525 if (is_parallel_ctx (ctx))
5526 break;
5527
5528 ctx = ctx->outer;
5529 if (ctx == NULL || !is_parallel_ctx (ctx))
5530 break;
5531
75a70cf9 5532 c = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
fd6481cf 5533 OMP_CLAUSE_LASTPRIVATE);
5534 par_clauses = true;
5535 }
1e8e9920 5536 }
5537
75a70cf9 5538 if (label)
5539 gimple_seq_add_stmt (stmt_list, gimple_build_label (label));
1e8e9920 5540}
5541
641a0fa1 5542/* Lower the OpenACC reductions of CLAUSES for compute axis LEVEL
5543 (which might be a placeholder). INNER is true if this is an inner
5544 axis of a multi-axis loop. FORK and JOIN are (optional) fork and
5545 join markers. Generate the before-loop forking sequence in
5546 FORK_SEQ and the after-loop joining sequence to JOIN_SEQ. The
5547 general form of these sequences is
5548
5549 GOACC_REDUCTION_SETUP
5550 GOACC_FORK
5551 GOACC_REDUCTION_INIT
5552 ...
5553 GOACC_REDUCTION_FINI
5554 GOACC_JOIN
5555 GOACC_REDUCTION_TEARDOWN. */
5556
ca4c3545 5557static void
641a0fa1 5558lower_oacc_reductions (location_t loc, tree clauses, tree level, bool inner,
5559 gcall *fork, gcall *join, gimple_seq *fork_seq,
5560 gimple_seq *join_seq, omp_context *ctx)
ca4c3545 5561{
641a0fa1 5562 gimple_seq before_fork = NULL;
5563 gimple_seq after_fork = NULL;
5564 gimple_seq before_join = NULL;
5565 gimple_seq after_join = NULL;
5566 tree init_code = NULL_TREE, fini_code = NULL_TREE,
5567 setup_code = NULL_TREE, teardown_code = NULL_TREE;
5568 unsigned offset = 0;
5569
5570 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
5571 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
5572 {
5573 tree orig = OMP_CLAUSE_DECL (c);
5574 tree var = maybe_lookup_decl (orig, ctx);
5575 tree ref_to_res = NULL_TREE;
5576 tree incoming, outgoing;
5577
5578 enum tree_code rcode = OMP_CLAUSE_REDUCTION_CODE (c);
5579 if (rcode == MINUS_EXPR)
5580 rcode = PLUS_EXPR;
5581 else if (rcode == TRUTH_ANDIF_EXPR)
5582 rcode = BIT_AND_EXPR;
5583 else if (rcode == TRUTH_ORIF_EXPR)
5584 rcode = BIT_IOR_EXPR;
5585 tree op = build_int_cst (unsigned_type_node, rcode);
5586
5587 if (!var)
5588 var = orig;
5589 gcc_assert (!is_reference (var));
5590
5591 incoming = outgoing = var;
5592
5593 if (!inner)
5594 {
5595 /* See if an outer construct also reduces this variable. */
5596 omp_context *outer = ctx;
ca4c3545 5597
641a0fa1 5598 while (omp_context *probe = outer->outer)
5599 {
5600 enum gimple_code type = gimple_code (probe->stmt);
5601 tree cls;
ca4c3545 5602
641a0fa1 5603 switch (type)
5604 {
5605 case GIMPLE_OMP_FOR:
5606 cls = gimple_omp_for_clauses (probe->stmt);
5607 break;
ca4c3545 5608
641a0fa1 5609 case GIMPLE_OMP_TARGET:
5610 if (gimple_omp_target_kind (probe->stmt)
5611 != GF_OMP_TARGET_KIND_OACC_PARALLEL)
5612 goto do_lookup;
ca4c3545 5613
641a0fa1 5614 cls = gimple_omp_target_clauses (probe->stmt);
5615 break;
ca4c3545 5616
641a0fa1 5617 default:
5618 goto do_lookup;
5619 }
5620
5621 outer = probe;
5622 for (; cls; cls = OMP_CLAUSE_CHAIN (cls))
5623 if (OMP_CLAUSE_CODE (cls) == OMP_CLAUSE_REDUCTION
5624 && orig == OMP_CLAUSE_DECL (cls))
5625 goto has_outer_reduction;
5626 }
ca4c3545 5627
641a0fa1 5628 do_lookup:
5629 /* This is the outermost construct with this reduction,
5630 see if there's a mapping for it. */
5631 if (gimple_code (outer->stmt) == GIMPLE_OMP_TARGET
5632 && maybe_lookup_field (orig, outer))
5633 {
5634 ref_to_res = build_receiver_ref (orig, false, outer);
5635 if (is_reference (orig))
5636 ref_to_res = build_simple_mem_ref (ref_to_res);
ca4c3545 5637
641a0fa1 5638 outgoing = var;
5639 incoming = omp_reduction_init_op (loc, rcode, TREE_TYPE (var));
5640 }
5641 else
5642 incoming = outgoing = orig;
5643
5644 has_outer_reduction:;
5645 }
ca4c3545 5646
641a0fa1 5647 if (!ref_to_res)
5648 ref_to_res = integer_zero_node;
ca4c3545 5649
641a0fa1 5650 /* Determine position in reduction buffer, which may be used
5651 by target. */
5652 enum machine_mode mode = TYPE_MODE (TREE_TYPE (var));
5653 unsigned align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
5654 offset = (offset + align - 1) & ~(align - 1);
5655 tree off = build_int_cst (sizetype, offset);
5656 offset += GET_MODE_SIZE (mode);
ca4c3545 5657
641a0fa1 5658 if (!init_code)
5659 {
5660 init_code = build_int_cst (integer_type_node,
5661 IFN_GOACC_REDUCTION_INIT);
5662 fini_code = build_int_cst (integer_type_node,
5663 IFN_GOACC_REDUCTION_FINI);
5664 setup_code = build_int_cst (integer_type_node,
5665 IFN_GOACC_REDUCTION_SETUP);
5666 teardown_code = build_int_cst (integer_type_node,
5667 IFN_GOACC_REDUCTION_TEARDOWN);
5668 }
5669
5670 tree setup_call
5671 = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
5672 TREE_TYPE (var), 6, setup_code,
5673 unshare_expr (ref_to_res),
5674 incoming, level, op, off);
5675 tree init_call
5676 = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
5677 TREE_TYPE (var), 6, init_code,
5678 unshare_expr (ref_to_res),
5679 var, level, op, off);
5680 tree fini_call
5681 = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
5682 TREE_TYPE (var), 6, fini_code,
5683 unshare_expr (ref_to_res),
5684 var, level, op, off);
5685 tree teardown_call
5686 = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
5687 TREE_TYPE (var), 6, teardown_code,
5688 ref_to_res, var, level, op, off);
5689
5690 gimplify_assign (var, setup_call, &before_fork);
5691 gimplify_assign (var, init_call, &after_fork);
5692 gimplify_assign (var, fini_call, &before_join);
5693 gimplify_assign (outgoing, teardown_call, &after_join);
5694 }
5695
5696 /* Now stitch things together. */
5697 gimple_seq_add_seq (fork_seq, before_fork);
5698 if (fork)
5699 gimple_seq_add_stmt (fork_seq, fork);
5700 gimple_seq_add_seq (fork_seq, after_fork);
5701
5702 gimple_seq_add_seq (join_seq, before_join);
5703 if (join)
5704 gimple_seq_add_stmt (join_seq, join);
5705 gimple_seq_add_seq (join_seq, after_join);
ca4c3545 5706}
773c5ba7 5707
1e8e9920 5708/* Generate code to implement the REDUCTION clauses. */
5709
5710static void
75a70cf9 5711lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
1e8e9920 5712{
75a70cf9 5713 gimple_seq sub_seq = NULL;
42acab1c 5714 gimple *stmt;
f69b8a4c 5715 tree x, c;
1e8e9920 5716 int count = 0;
5717
641a0fa1 5718 /* OpenACC loop reductions are handled elsewhere. */
5719 if (is_gimple_omp_oacc (ctx->stmt))
5720 return;
5721
3d483a94 5722 /* SIMD reductions are handled in lower_rec_input_clauses. */
5723 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
10c55644 5724 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3d483a94 5725 return;
5726
1e8e9920 5727 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
5728 update in that case, otherwise use a lock. */
5729 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
55d6e7cd 5730 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
1e8e9920 5731 {
43895be5 5732 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
5733 || TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF)
1e8e9920 5734 {
bc7bff74 5735 /* Never use OMP_ATOMIC for array reductions or UDRs. */
1e8e9920 5736 count = -1;
5737 break;
5738 }
5739 count++;
5740 }
5741
5742 if (count == 0)
5743 return;
5744
5745 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
5746 {
43895be5 5747 tree var, ref, new_var, orig_var;
1e8e9920 5748 enum tree_code code;
389dd41b 5749 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
1e8e9920 5750
55d6e7cd 5751 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
1e8e9920 5752 continue;
5753
43895be5 5754 orig_var = var = OMP_CLAUSE_DECL (c);
5755 if (TREE_CODE (var) == MEM_REF)
5756 {
5757 var = TREE_OPERAND (var, 0);
9561765e 5758 if (TREE_CODE (var) == POINTER_PLUS_EXPR)
5759 var = TREE_OPERAND (var, 0);
43895be5 5760 if (TREE_CODE (var) == INDIRECT_REF
5761 || TREE_CODE (var) == ADDR_EXPR)
5762 var = TREE_OPERAND (var, 0);
5763 orig_var = var;
5764 if (is_variable_sized (var))
5765 {
5766 gcc_assert (DECL_HAS_VALUE_EXPR_P (var));
5767 var = DECL_VALUE_EXPR (var);
5768 gcc_assert (TREE_CODE (var) == INDIRECT_REF);
5769 var = TREE_OPERAND (var, 0);
5770 gcc_assert (DECL_P (var));
5771 }
5772 }
1e8e9920 5773 new_var = lookup_decl (var, ctx);
43895be5 5774 if (var == OMP_CLAUSE_DECL (c) && is_reference (var))
182cf5a9 5775 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
1e8e9920 5776 ref = build_outer_var_ref (var, ctx);
5777 code = OMP_CLAUSE_REDUCTION_CODE (c);
773c5ba7 5778
5779 /* reduction(-:var) sums up the partial results, so it acts
5780 identically to reduction(+:var). */
1e8e9920 5781 if (code == MINUS_EXPR)
5782 code = PLUS_EXPR;
5783
641a0fa1 5784 if (count == 1)
1e8e9920 5785 {
389dd41b 5786 tree addr = build_fold_addr_expr_loc (clause_loc, ref);
1e8e9920 5787
5788 addr = save_expr (addr);
5789 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
389dd41b 5790 x = fold_build2_loc (clause_loc, code, TREE_TYPE (ref), ref, new_var);
1e8e9920 5791 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
75a70cf9 5792 gimplify_and_add (x, stmt_seqp);
1e8e9920 5793 return;
5794 }
43895be5 5795 else if (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF)
5796 {
5797 tree d = OMP_CLAUSE_DECL (c);
5798 tree type = TREE_TYPE (d);
5799 tree v = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
5800 tree i = create_tmp_var (TREE_TYPE (v), NULL);
5801 tree ptype = build_pointer_type (TREE_TYPE (type));
9561765e 5802 tree bias = TREE_OPERAND (d, 1);
5803 d = TREE_OPERAND (d, 0);
5804 if (TREE_CODE (d) == POINTER_PLUS_EXPR)
5805 {
5806 tree b = TREE_OPERAND (d, 1);
5807 b = maybe_lookup_decl (b, ctx);
5808 if (b == NULL)
5809 {
5810 b = TREE_OPERAND (d, 1);
5811 b = maybe_lookup_decl_in_outer_ctx (b, ctx);
5812 }
5813 if (integer_zerop (bias))
5814 bias = b;
5815 else
5816 {
5817 bias = fold_convert_loc (clause_loc, TREE_TYPE (b), bias);
5818 bias = fold_build2_loc (clause_loc, PLUS_EXPR,
5819 TREE_TYPE (b), b, bias);
5820 }
5821 d = TREE_OPERAND (d, 0);
5822 }
43895be5 5823 /* For ref build_outer_var_ref already performs this, so
5824 only new_var needs a dereference. */
9561765e 5825 if (TREE_CODE (d) == INDIRECT_REF)
43895be5 5826 {
5827 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
5828 gcc_assert (is_reference (var) && var == orig_var);
5829 }
9561765e 5830 else if (TREE_CODE (d) == ADDR_EXPR)
43895be5 5831 {
5832 if (orig_var == var)
5833 {
5834 new_var = build_fold_addr_expr (new_var);
5835 ref = build_fold_addr_expr (ref);
5836 }
5837 }
5838 else
5839 {
5840 gcc_assert (orig_var == var);
5841 if (is_reference (var))
5842 ref = build_fold_addr_expr (ref);
5843 }
5844 if (DECL_P (v))
5845 {
5846 tree t = maybe_lookup_decl (v, ctx);
5847 if (t)
5848 v = t;
5849 else
5850 v = maybe_lookup_decl_in_outer_ctx (v, ctx);
5851 gimplify_expr (&v, stmt_seqp, NULL, is_gimple_val, fb_rvalue);
5852 }
9561765e 5853 if (!integer_zerop (bias))
5854 {
5855 bias = fold_convert_loc (clause_loc, sizetype, bias);
5856 new_var = fold_build2_loc (clause_loc, POINTER_PLUS_EXPR,
5857 TREE_TYPE (new_var), new_var,
5858 unshare_expr (bias));
5859 ref = fold_build2_loc (clause_loc, POINTER_PLUS_EXPR,
5860 TREE_TYPE (ref), ref, bias);
5861 }
43895be5 5862 new_var = fold_convert_loc (clause_loc, ptype, new_var);
5863 ref = fold_convert_loc (clause_loc, ptype, ref);
5864 tree m = create_tmp_var (ptype, NULL);
5865 gimplify_assign (m, new_var, stmt_seqp);
5866 new_var = m;
5867 m = create_tmp_var (ptype, NULL);
5868 gimplify_assign (m, ref, stmt_seqp);
5869 ref = m;
5870 gimplify_assign (i, build_int_cst (TREE_TYPE (v), 0), stmt_seqp);
5871 tree body = create_artificial_label (UNKNOWN_LOCATION);
5872 tree end = create_artificial_label (UNKNOWN_LOCATION);
5873 gimple_seq_add_stmt (&sub_seq, gimple_build_label (body));
5874 tree priv = build_simple_mem_ref_loc (clause_loc, new_var);
5875 tree out = build_simple_mem_ref_loc (clause_loc, ref);
5876 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
5877 {
5878 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
5879 tree decl_placeholder
5880 = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c);
5881 SET_DECL_VALUE_EXPR (placeholder, out);
5882 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
5883 SET_DECL_VALUE_EXPR (decl_placeholder, priv);
5884 DECL_HAS_VALUE_EXPR_P (decl_placeholder) = 1;
5885 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
5886 gimple_seq_add_seq (&sub_seq,
5887 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
5888 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
5889 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
5890 OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c) = NULL;
5891 }
5892 else
5893 {
5894 x = build2 (code, TREE_TYPE (out), out, priv);
5895 out = unshare_expr (out);
5896 gimplify_assign (out, x, &sub_seq);
5897 }
5898 gimple *g = gimple_build_assign (new_var, POINTER_PLUS_EXPR, new_var,
5899 TYPE_SIZE_UNIT (TREE_TYPE (type)));
5900 gimple_seq_add_stmt (&sub_seq, g);
5901 g = gimple_build_assign (ref, POINTER_PLUS_EXPR, ref,
5902 TYPE_SIZE_UNIT (TREE_TYPE (type)));
5903 gimple_seq_add_stmt (&sub_seq, g);
5904 g = gimple_build_assign (i, PLUS_EXPR, i,
5905 build_int_cst (TREE_TYPE (i), 1));
5906 gimple_seq_add_stmt (&sub_seq, g);
5907 g = gimple_build_cond (LE_EXPR, i, v, body, end);
5908 gimple_seq_add_stmt (&sub_seq, g);
5909 gimple_seq_add_stmt (&sub_seq, gimple_build_label (end));
5910 }
ca4c3545 5911 else if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1e8e9920 5912 {
5913 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
5914
bc7bff74 5915 if (is_reference (var)
5916 && !useless_type_conversion_p (TREE_TYPE (placeholder),
5917 TREE_TYPE (ref)))
389dd41b 5918 ref = build_fold_addr_expr_loc (clause_loc, ref);
1e8e9920 5919 SET_DECL_VALUE_EXPR (placeholder, ref);
5920 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
e3a19533 5921 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
75a70cf9 5922 gimple_seq_add_seq (&sub_seq, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
5923 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
1e8e9920 5924 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
5925 }
5926 else
5927 {
5928 x = build2 (code, TREE_TYPE (ref), ref, new_var);
5929 ref = build_outer_var_ref (var, ctx);
75a70cf9 5930 gimplify_assign (ref, x, &sub_seq);
1e8e9920 5931 }
5932 }
5933
ca4c3545 5934 if (is_gimple_omp_oacc (ctx->stmt))
5935 return;
5936
b9a16870 5937 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START),
5938 0);
75a70cf9 5939 gimple_seq_add_stmt (stmt_seqp, stmt);
1e8e9920 5940
75a70cf9 5941 gimple_seq_add_seq (stmt_seqp, sub_seq);
1e8e9920 5942
b9a16870 5943 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END),
5944 0);
75a70cf9 5945 gimple_seq_add_stmt (stmt_seqp, stmt);
1e8e9920 5946}
5947
773c5ba7 5948
1e8e9920 5949/* Generate code to implement the COPYPRIVATE clauses. */
5950
5951static void
75a70cf9 5952lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist,
1e8e9920 5953 omp_context *ctx)
5954{
5955 tree c;
5956
5957 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
5958 {
cb561506 5959 tree var, new_var, ref, x;
1e8e9920 5960 bool by_ref;
389dd41b 5961 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
1e8e9920 5962
55d6e7cd 5963 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
1e8e9920 5964 continue;
5965
5966 var = OMP_CLAUSE_DECL (c);
e8a588af 5967 by_ref = use_pointer_for_field (var, NULL);
1e8e9920 5968
5969 ref = build_sender_ref (var, ctx);
cb561506 5970 x = new_var = lookup_decl_in_outer_ctx (var, ctx);
5971 if (by_ref)
5972 {
5973 x = build_fold_addr_expr_loc (clause_loc, new_var);
5974 x = fold_convert_loc (clause_loc, TREE_TYPE (ref), x);
5975 }
75a70cf9 5976 gimplify_assign (ref, x, slist);
1e8e9920 5977
cb561506 5978 ref = build_receiver_ref (var, false, ctx);
5979 if (by_ref)
5980 {
5981 ref = fold_convert_loc (clause_loc,
5982 build_pointer_type (TREE_TYPE (new_var)),
5983 ref);
5984 ref = build_fold_indirect_ref_loc (clause_loc, ref);
5985 }
1e8e9920 5986 if (is_reference (var))
5987 {
cb561506 5988 ref = fold_convert_loc (clause_loc, TREE_TYPE (new_var), ref);
182cf5a9 5989 ref = build_simple_mem_ref_loc (clause_loc, ref);
5990 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
1e8e9920 5991 }
cb561506 5992 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, ref);
1e8e9920 5993 gimplify_and_add (x, rlist);
5994 }
5995}
5996
773c5ba7 5997
1e8e9920 5998/* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
5999 and REDUCTION from the sender (aka parent) side. */
6000
6001static void
75a70cf9 6002lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
6003 omp_context *ctx)
1e8e9920 6004{
43895be5 6005 tree c, t;
6006 int ignored_looptemp = 0;
6007 bool is_taskloop = false;
6008
6009 /* For taskloop, ignore first two _looptemp_ clauses, those are initialized
6010 by GOMP_taskloop. */
6011 if (is_task_ctx (ctx) && gimple_omp_task_taskloop_p (ctx->stmt))
6012 {
6013 ignored_looptemp = 2;
6014 is_taskloop = true;
6015 }
1e8e9920 6016
6017 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
6018 {
773c5ba7 6019 tree val, ref, x, var;
1e8e9920 6020 bool by_ref, do_in = false, do_out = false;
389dd41b 6021 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
1e8e9920 6022
55d6e7cd 6023 switch (OMP_CLAUSE_CODE (c))
1e8e9920 6024 {
fd6481cf 6025 case OMP_CLAUSE_PRIVATE:
6026 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
6027 break;
6028 continue;
1e8e9920 6029 case OMP_CLAUSE_FIRSTPRIVATE:
6030 case OMP_CLAUSE_COPYIN:
6031 case OMP_CLAUSE_LASTPRIVATE:
6032 case OMP_CLAUSE_REDUCTION:
43895be5 6033 break;
6034 case OMP_CLAUSE_SHARED:
6035 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
6036 break;
6037 continue;
bc7bff74 6038 case OMP_CLAUSE__LOOPTEMP_:
43895be5 6039 if (ignored_looptemp)
6040 {
6041 ignored_looptemp--;
6042 continue;
6043 }
1e8e9920 6044 break;
6045 default:
6046 continue;
6047 }
6048
87b31375 6049 val = OMP_CLAUSE_DECL (c);
43895be5 6050 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
6051 && TREE_CODE (val) == MEM_REF)
6052 {
6053 val = TREE_OPERAND (val, 0);
9561765e 6054 if (TREE_CODE (val) == POINTER_PLUS_EXPR)
6055 val = TREE_OPERAND (val, 0);
43895be5 6056 if (TREE_CODE (val) == INDIRECT_REF
6057 || TREE_CODE (val) == ADDR_EXPR)
6058 val = TREE_OPERAND (val, 0);
6059 if (is_variable_sized (val))
6060 continue;
6061 }
6062
6063 /* For OMP_CLAUSE_SHARED_FIRSTPRIVATE, look beyond the
6064 outer taskloop region. */
6065 omp_context *ctx_for_o = ctx;
6066 if (is_taskloop
6067 && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
6068 && OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
6069 ctx_for_o = ctx->outer;
6070
6071 var = lookup_decl_in_outer_ctx (val, ctx_for_o);
773c5ba7 6072
f49d7bb5 6073 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
6074 && is_global_var (var))
6075 continue;
43895be5 6076
6077 t = omp_member_access_dummy_var (var);
6078 if (t)
6079 {
6080 var = DECL_VALUE_EXPR (var);
6081 tree o = maybe_lookup_decl_in_outer_ctx (t, ctx_for_o);
6082 if (o != t)
6083 var = unshare_and_remap (var, t, o);
6084 else
6085 var = unshare_expr (var);
6086 }
6087
6088 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED)
6089 {
6090 /* Handle taskloop firstprivate/lastprivate, where the
6091 lastprivate on GIMPLE_OMP_TASK is represented as
6092 OMP_CLAUSE_SHARED_FIRSTPRIVATE. */
6093 tree f = lookup_sfield ((splay_tree_key) &DECL_UID (val), ctx);
6094 x = omp_build_component_ref (ctx->sender_decl, f);
6095 if (use_pointer_for_field (val, ctx))
6096 var = build_fold_addr_expr (var);
6097 gimplify_assign (x, var, ilist);
6098 DECL_ABSTRACT_ORIGIN (f) = NULL;
6099 continue;
6100 }
6101
6102 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION
6103 || val == OMP_CLAUSE_DECL (c))
6104 && is_variable_sized (val))
1e8e9920 6105 continue;
e8a588af 6106 by_ref = use_pointer_for_field (val, NULL);
1e8e9920 6107
55d6e7cd 6108 switch (OMP_CLAUSE_CODE (c))
1e8e9920 6109 {
fd6481cf 6110 case OMP_CLAUSE_PRIVATE:
1e8e9920 6111 case OMP_CLAUSE_FIRSTPRIVATE:
6112 case OMP_CLAUSE_COPYIN:
bc7bff74 6113 case OMP_CLAUSE__LOOPTEMP_:
1e8e9920 6114 do_in = true;
6115 break;
6116
6117 case OMP_CLAUSE_LASTPRIVATE:
6118 if (by_ref || is_reference (val))
6119 {
6120 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
6121 continue;
6122 do_in = true;
6123 }
6124 else
fd6481cf 6125 {
6126 do_out = true;
6127 if (lang_hooks.decls.omp_private_outer_ref (val))
6128 do_in = true;
6129 }
1e8e9920 6130 break;
6131
6132 case OMP_CLAUSE_REDUCTION:
6133 do_in = true;
43895be5 6134 if (val == OMP_CLAUSE_DECL (c))
6135 do_out = !(by_ref || is_reference (val));
6136 else
6137 by_ref = TREE_CODE (TREE_TYPE (val)) == ARRAY_TYPE;
1e8e9920 6138 break;
6139
6140 default:
6141 gcc_unreachable ();
6142 }
6143
6144 if (do_in)
6145 {
6146 ref = build_sender_ref (val, ctx);
389dd41b 6147 x = by_ref ? build_fold_addr_expr_loc (clause_loc, var) : var;
75a70cf9 6148 gimplify_assign (ref, x, ilist);
fd6481cf 6149 if (is_task_ctx (ctx))
6150 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref, 1)) = NULL;
1e8e9920 6151 }
773c5ba7 6152
1e8e9920 6153 if (do_out)
6154 {
6155 ref = build_sender_ref (val, ctx);
75a70cf9 6156 gimplify_assign (var, ref, olist);
1e8e9920 6157 }
6158 }
6159}
6160
75a70cf9 6161/* Generate code to implement SHARED from the sender (aka parent)
6162 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
6163 list things that got automatically shared. */
1e8e9920 6164
6165static void
75a70cf9 6166lower_send_shared_vars (gimple_seq *ilist, gimple_seq *olist, omp_context *ctx)
1e8e9920 6167{
43895be5 6168 tree var, ovar, nvar, t, f, x, record_type;
1e8e9920 6169
6170 if (ctx->record_type == NULL)
6171 return;
773c5ba7 6172
fd6481cf 6173 record_type = ctx->srecord_type ? ctx->srecord_type : ctx->record_type;
1767a056 6174 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
1e8e9920 6175 {
6176 ovar = DECL_ABSTRACT_ORIGIN (f);
43895be5 6177 if (!ovar || TREE_CODE (ovar) == FIELD_DECL)
6178 continue;
6179
1e8e9920 6180 nvar = maybe_lookup_decl (ovar, ctx);
6181 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
6182 continue;
6183
773c5ba7 6184 /* If CTX is a nested parallel directive. Find the immediately
6185 enclosing parallel or workshare construct that contains a
6186 mapping for OVAR. */
87b31375 6187 var = lookup_decl_in_outer_ctx (ovar, ctx);
773c5ba7 6188
43895be5 6189 t = omp_member_access_dummy_var (var);
6190 if (t)
6191 {
6192 var = DECL_VALUE_EXPR (var);
6193 tree o = maybe_lookup_decl_in_outer_ctx (t, ctx);
6194 if (o != t)
6195 var = unshare_and_remap (var, t, o);
6196 else
6197 var = unshare_expr (var);
6198 }
6199
e8a588af 6200 if (use_pointer_for_field (ovar, ctx))
1e8e9920 6201 {
6202 x = build_sender_ref (ovar, ctx);
773c5ba7 6203 var = build_fold_addr_expr (var);
75a70cf9 6204 gimplify_assign (x, var, ilist);
1e8e9920 6205 }
6206 else
6207 {
6208 x = build_sender_ref (ovar, ctx);
75a70cf9 6209 gimplify_assign (x, var, ilist);
1e8e9920 6210
d2263ebb 6211 if (!TREE_READONLY (var)
6212 /* We don't need to receive a new reference to a result
6213 or parm decl. In fact we may not store to it as we will
6214 invalidate any pending RSO and generate wrong gimple
6215 during inlining. */
6216 && !((TREE_CODE (var) == RESULT_DECL
6217 || TREE_CODE (var) == PARM_DECL)
6218 && DECL_BY_REFERENCE (var)))
fd6481cf 6219 {
6220 x = build_sender_ref (ovar, ctx);
75a70cf9 6221 gimplify_assign (var, x, olist);
fd6481cf 6222 }
1e8e9920 6223 }
6224 }
6225}
6226
a8e785ba 6227/* Emit an OpenACC head marker call, encapulating the partitioning and
6228 other information that must be processed by the target compiler.
6229 Return the maximum number of dimensions the associated loop might
6230 be partitioned over. */
6231
6232static unsigned
6233lower_oacc_head_mark (location_t loc, tree ddvar, tree clauses,
6234 gimple_seq *seq, omp_context *ctx)
6235{
6236 unsigned levels = 0;
6237 unsigned tag = 0;
6238 tree gang_static = NULL_TREE;
6239 auto_vec<tree, 5> args;
6240
6241 args.quick_push (build_int_cst
6242 (integer_type_node, IFN_UNIQUE_OACC_HEAD_MARK));
6243 args.quick_push (ddvar);
6244 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
6245 {
6246 switch (OMP_CLAUSE_CODE (c))
6247 {
6248 case OMP_CLAUSE_GANG:
6249 tag |= OLF_DIM_GANG;
6250 gang_static = OMP_CLAUSE_GANG_STATIC_EXPR (c);
6251 /* static:* is represented by -1, and we can ignore it, as
6252 scheduling is always static. */
6253 if (gang_static && integer_minus_onep (gang_static))
6254 gang_static = NULL_TREE;
6255 levels++;
6256 break;
6257
6258 case OMP_CLAUSE_WORKER:
6259 tag |= OLF_DIM_WORKER;
6260 levels++;
6261 break;
6262
6263 case OMP_CLAUSE_VECTOR:
6264 tag |= OLF_DIM_VECTOR;
6265 levels++;
6266 break;
6267
6268 case OMP_CLAUSE_SEQ:
6269 tag |= OLF_SEQ;
6270 break;
6271
6272 case OMP_CLAUSE_AUTO:
6273 tag |= OLF_AUTO;
6274 break;
6275
6276 case OMP_CLAUSE_INDEPENDENT:
6277 tag |= OLF_INDEPENDENT;
6278 break;
6279
6280 default:
6281 continue;
6282 }
6283 }
6284
6285 if (gang_static)
6286 {
6287 if (DECL_P (gang_static))
6288 gang_static = build_outer_var_ref (gang_static, ctx);
6289 tag |= OLF_GANG_STATIC;
6290 }
6291
6292 /* In a parallel region, loops are implicitly INDEPENDENT. */
6293 omp_context *tgt = enclosing_target_ctx (ctx);
6294 if (!tgt || is_oacc_parallel (tgt))
6295 tag |= OLF_INDEPENDENT;
6296
6297 /* A loop lacking SEQ, GANG, WORKER and/or VECTOR is implicitly AUTO. */
6298 if (!(tag & (((GOMP_DIM_MASK (GOMP_DIM_MAX) - 1) << OLF_DIM_BASE)
6299 | OLF_SEQ)))
6300 tag |= OLF_AUTO;
6301
6302 /* Ensure at least one level. */
6303 if (!levels)
6304 levels++;
6305
6306 args.quick_push (build_int_cst (integer_type_node, levels));
6307 args.quick_push (build_int_cst (integer_type_node, tag));
6308 if (gang_static)
6309 args.quick_push (gang_static);
6310
6311 gcall *call = gimple_build_call_internal_vec (IFN_UNIQUE, args);
6312 gimple_set_location (call, loc);
6313 gimple_set_lhs (call, ddvar);
6314 gimple_seq_add_stmt (seq, call);
6315
6316 return levels;
6317}
6318
6319/* Emit an OpenACC lopp head or tail marker to SEQ. LEVEL is the
6320 partitioning level of the enclosed region. */
6321
6322static void
6323lower_oacc_loop_marker (location_t loc, tree ddvar, bool head,
6324 tree tofollow, gimple_seq *seq)
6325{
6326 int marker_kind = (head ? IFN_UNIQUE_OACC_HEAD_MARK
6327 : IFN_UNIQUE_OACC_TAIL_MARK);
6328 tree marker = build_int_cst (integer_type_node, marker_kind);
6329 int nargs = 2 + (tofollow != NULL_TREE);
6330 gcall *call = gimple_build_call_internal (IFN_UNIQUE, nargs,
6331 marker, ddvar, tofollow);
6332 gimple_set_location (call, loc);
6333 gimple_set_lhs (call, ddvar);
6334 gimple_seq_add_stmt (seq, call);
6335}
6336
6337/* Generate the before and after OpenACC loop sequences. CLAUSES are
6338 the loop clauses, from which we extract reductions. Initialize
6339 HEAD and TAIL. */
6340
6341static void
6342lower_oacc_head_tail (location_t loc, tree clauses,
6343 gimple_seq *head, gimple_seq *tail, omp_context *ctx)
6344{
6345 bool inner = false;
6346 tree ddvar = create_tmp_var (integer_type_node, ".data_dep");
6347 gimple_seq_add_stmt (head, gimple_build_assign (ddvar, integer_zero_node));
6348
6349 unsigned count = lower_oacc_head_mark (loc, ddvar, clauses, head, ctx);
6350 if (!count)
6351 lower_oacc_loop_marker (loc, ddvar, false, integer_zero_node, tail);
6352
6353 tree fork_kind = build_int_cst (unsigned_type_node, IFN_UNIQUE_OACC_FORK);
6354 tree join_kind = build_int_cst (unsigned_type_node, IFN_UNIQUE_OACC_JOIN);
6355
6356 for (unsigned done = 1; count; count--, done++)
6357 {
6358 gimple_seq fork_seq = NULL;
6359 gimple_seq join_seq = NULL;
6360
6361 tree place = build_int_cst (integer_type_node, -1);
6362 gcall *fork = gimple_build_call_internal (IFN_UNIQUE, 3,
6363 fork_kind, ddvar, place);
6364 gimple_set_location (fork, loc);
6365 gimple_set_lhs (fork, ddvar);
6366
6367 gcall *join = gimple_build_call_internal (IFN_UNIQUE, 3,
6368 join_kind, ddvar, place);
6369 gimple_set_location (join, loc);
6370 gimple_set_lhs (join, ddvar);
6371
6372 /* Mark the beginning of this level sequence. */
6373 if (inner)
6374 lower_oacc_loop_marker (loc, ddvar, true,
6375 build_int_cst (integer_type_node, count),
6376 &fork_seq);
6377 lower_oacc_loop_marker (loc, ddvar, false,
6378 build_int_cst (integer_type_node, done),
6379 &join_seq);
6380
641a0fa1 6381 lower_oacc_reductions (loc, clauses, place, inner,
6382 fork, join, &fork_seq, &join_seq, ctx);
a8e785ba 6383
6384 /* Append this level to head. */
6385 gimple_seq_add_seq (head, fork_seq);
6386 /* Prepend it to tail. */
6387 gimple_seq_add_seq (&join_seq, *tail);
6388 *tail = join_seq;
6389
6390 inner = true;
6391 }
6392
6393 /* Mark the end of the sequence. */
6394 lower_oacc_loop_marker (loc, ddvar, true, NULL_TREE, head);
6395 lower_oacc_loop_marker (loc, ddvar, false, NULL_TREE, tail);
6396}
75a70cf9 6397
6398/* A convenience function to build an empty GIMPLE_COND with just the
6399 condition. */
6400
1a91d914 6401static gcond *
75a70cf9 6402gimple_build_cond_empty (tree cond)
6403{
6404 enum tree_code pred_code;
6405 tree lhs, rhs;
6406
6407 gimple_cond_get_ops_from_tree (cond, &pred_code, &lhs, &rhs);
6408 return gimple_build_cond (pred_code, lhs, rhs, NULL_TREE, NULL_TREE);
6409}
6410
56686608 6411/* Return true if a parallel REGION is within a declare target function or
6412 within a target region and is not a part of a gridified target. */
6413
6414static bool
6415parallel_needs_hsa_kernel_p (struct omp_region *region)
6416{
6417 bool indirect = false;
6418 for (region = region->outer; region; region = region->outer)
6419 {
6420 if (region->type == GIMPLE_OMP_PARALLEL)
6421 indirect = true;
6422 else if (region->type == GIMPLE_OMP_TARGET)
6423 {
6424 gomp_target *tgt_stmt
6425 = as_a <gomp_target *> (last_stmt (region->entry));
6426
6427 if (find_omp_clause (gimple_omp_target_clauses (tgt_stmt),
6428 OMP_CLAUSE__GRIDDIM_))
6429 return indirect;
6430 else
6431 return true;
6432 }
6433 }
6434
6435 if (lookup_attribute ("omp declare target",
6436 DECL_ATTRIBUTES (current_function_decl)))
6437 return true;
6438
6439 return false;
6440}
6441
43895be5 6442static void expand_omp_build_assign (gimple_stmt_iterator *, tree, tree,
6443 bool = false);
75a70cf9 6444
48e1416a 6445/* Build the function calls to GOMP_parallel_start etc to actually
773c5ba7 6446 generate the parallel operation. REGION is the parallel region
6447 being expanded. BB is the block where to insert the code. WS_ARGS
6448 will be set if this is a call to a combined parallel+workshare
6449 construct, it contains the list of additional arguments needed by
6450 the workshare construct. */
1e8e9920 6451
6452static void
61e47ac8 6453expand_parallel_call (struct omp_region *region, basic_block bb,
1a91d914 6454 gomp_parallel *entry_stmt,
6455 vec<tree, va_gc> *ws_args)
1e8e9920 6456{
bc7bff74 6457 tree t, t1, t2, val, cond, c, clauses, flags;
75a70cf9 6458 gimple_stmt_iterator gsi;
42acab1c 6459 gimple *stmt;
b9a16870 6460 enum built_in_function start_ix;
6461 int start_ix2;
389dd41b 6462 location_t clause_loc;
f1f41a6c 6463 vec<tree, va_gc> *args;
773c5ba7 6464
75a70cf9 6465 clauses = gimple_omp_parallel_clauses (entry_stmt);
773c5ba7 6466
bc7bff74 6467 /* Determine what flavor of GOMP_parallel we will be
773c5ba7 6468 emitting. */
bc7bff74 6469 start_ix = BUILT_IN_GOMP_PARALLEL;
773c5ba7 6470 if (is_combined_parallel (region))
6471 {
61e47ac8 6472 switch (region->inner->type)
773c5ba7 6473 {
75a70cf9 6474 case GIMPLE_OMP_FOR:
fd6481cf 6475 gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
9561765e 6476 switch (region->inner->sched_kind)
6477 {
6478 case OMP_CLAUSE_SCHEDULE_RUNTIME:
6479 start_ix2 = 3;
6480 break;
6481 case OMP_CLAUSE_SCHEDULE_DYNAMIC:
6482 case OMP_CLAUSE_SCHEDULE_GUIDED:
6483 if (region->inner->sched_modifiers
6484 & OMP_CLAUSE_SCHEDULE_NONMONOTONIC)
6485 {
6486 start_ix2 = 3 + region->inner->sched_kind;
6487 break;
6488 }
6489 /* FALLTHRU */
6490 default:
6491 start_ix2 = region->inner->sched_kind;
6492 break;
6493 }
6494 start_ix2 += (int) BUILT_IN_GOMP_PARALLEL_LOOP_STATIC;
6495 start_ix = (enum built_in_function) start_ix2;
61e47ac8 6496 break;
75a70cf9 6497 case GIMPLE_OMP_SECTIONS:
bc7bff74 6498 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS;
61e47ac8 6499 break;
6500 default:
6501 gcc_unreachable ();
773c5ba7 6502 }
773c5ba7 6503 }
1e8e9920 6504
6505 /* By default, the value of NUM_THREADS is zero (selected at run time)
6506 and there is no conditional. */
6507 cond = NULL_TREE;
6508 val = build_int_cst (unsigned_type_node, 0);
bc7bff74 6509 flags = build_int_cst (unsigned_type_node, 0);
1e8e9920 6510
6511 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
6512 if (c)
6513 cond = OMP_CLAUSE_IF_EXPR (c);
6514
6515 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
6516 if (c)
389dd41b 6517 {
6518 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
6519 clause_loc = OMP_CLAUSE_LOCATION (c);
6520 }
6521 else
6522 clause_loc = gimple_location (entry_stmt);
1e8e9920 6523
bc7bff74 6524 c = find_omp_clause (clauses, OMP_CLAUSE_PROC_BIND);
6525 if (c)
6526 flags = build_int_cst (unsigned_type_node, OMP_CLAUSE_PROC_BIND_KIND (c));
6527
1e8e9920 6528 /* Ensure 'val' is of the correct type. */
389dd41b 6529 val = fold_convert_loc (clause_loc, unsigned_type_node, val);
1e8e9920 6530
6531 /* If we found the clause 'if (cond)', build either
6532 (cond != 0) or (cond ? val : 1u). */
6533 if (cond)
6534 {
773c5ba7 6535 cond = gimple_boolify (cond);
6536
1e8e9920 6537 if (integer_zerop (val))
389dd41b 6538 val = fold_build2_loc (clause_loc,
6539 EQ_EXPR, unsigned_type_node, cond,
79acaae1 6540 build_int_cst (TREE_TYPE (cond), 0));
1e8e9920 6541 else
773c5ba7 6542 {
6543 basic_block cond_bb, then_bb, else_bb;
79acaae1 6544 edge e, e_then, e_else;
75a70cf9 6545 tree tmp_then, tmp_else, tmp_join, tmp_var;
79acaae1 6546
f9e245b2 6547 tmp_var = create_tmp_var (TREE_TYPE (val));
79acaae1 6548 if (gimple_in_ssa_p (cfun))
6549 {
f9e245b2 6550 tmp_then = make_ssa_name (tmp_var);
6551 tmp_else = make_ssa_name (tmp_var);
6552 tmp_join = make_ssa_name (tmp_var);
79acaae1 6553 }
6554 else
6555 {
6556 tmp_then = tmp_var;
6557 tmp_else = tmp_var;
6558 tmp_join = tmp_var;
6559 }
773c5ba7 6560
4302d619 6561 e = split_block_after_labels (bb);
773c5ba7 6562 cond_bb = e->src;
6563 bb = e->dest;
6564 remove_edge (e);
6565
6566 then_bb = create_empty_bb (cond_bb);
6567 else_bb = create_empty_bb (then_bb);
79acaae1 6568 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
6569 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
773c5ba7 6570
75a70cf9 6571 stmt = gimple_build_cond_empty (cond);
6572 gsi = gsi_start_bb (cond_bb);
6573 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
773c5ba7 6574
75a70cf9 6575 gsi = gsi_start_bb (then_bb);
43895be5 6576 expand_omp_build_assign (&gsi, tmp_then, val, true);
773c5ba7 6577
75a70cf9 6578 gsi = gsi_start_bb (else_bb);
43895be5 6579 expand_omp_build_assign (&gsi, tmp_else,
6580 build_int_cst (unsigned_type_node, 1),
6581 true);
773c5ba7 6582
6583 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
6584 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
b3083327 6585 add_bb_to_loop (then_bb, cond_bb->loop_father);
6586 add_bb_to_loop (else_bb, cond_bb->loop_father);
79acaae1 6587 e_then = make_edge (then_bb, bb, EDGE_FALLTHRU);
6588 e_else = make_edge (else_bb, bb, EDGE_FALLTHRU);
773c5ba7 6589
79acaae1 6590 if (gimple_in_ssa_p (cfun))
6591 {
1a91d914 6592 gphi *phi = create_phi_node (tmp_join, bb);
60d535d2 6593 add_phi_arg (phi, tmp_then, e_then, UNKNOWN_LOCATION);
6594 add_phi_arg (phi, tmp_else, e_else, UNKNOWN_LOCATION);
79acaae1 6595 }
6596
6597 val = tmp_join;
773c5ba7 6598 }
6599
75a70cf9 6600 gsi = gsi_start_bb (bb);
6601 val = force_gimple_operand_gsi (&gsi, val, true, NULL_TREE,
6602 false, GSI_CONTINUE_LINKING);
1e8e9920 6603 }
6604
75a70cf9 6605 gsi = gsi_last_bb (bb);
6606 t = gimple_omp_parallel_data_arg (entry_stmt);
1e8e9920 6607 if (t == NULL)
c2f47e15 6608 t1 = null_pointer_node;
1e8e9920 6609 else
c2f47e15 6610 t1 = build_fold_addr_expr (t);
56686608 6611 tree child_fndecl = gimple_omp_parallel_child_fn (entry_stmt);
6612 t2 = build_fold_addr_expr (child_fndecl);
773c5ba7 6613
bc7bff74 6614 vec_alloc (args, 4 + vec_safe_length (ws_args));
f1f41a6c 6615 args->quick_push (t2);
6616 args->quick_push (t1);
6617 args->quick_push (val);
6618 if (ws_args)
6619 args->splice (*ws_args);
bc7bff74 6620 args->quick_push (flags);
414c3a2c 6621
6622 t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
b9a16870 6623 builtin_decl_explicit (start_ix), args);
773c5ba7 6624
75a70cf9 6625 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6626 false, GSI_CONTINUE_LINKING);
56686608 6627
6628 if (hsa_gen_requested_p ()
6629 && parallel_needs_hsa_kernel_p (region))
6630 {
6631 cgraph_node *child_cnode = cgraph_node::get (child_fndecl);
6632 hsa_register_kernel (child_cnode);
6633 }
1e8e9920 6634}
6635
40750995 6636/* Insert a function call whose name is FUNC_NAME with the information from
6637 ENTRY_STMT into the basic_block BB. */
6638
6639static void
1a91d914 6640expand_cilk_for_call (basic_block bb, gomp_parallel *entry_stmt,
40750995 6641 vec <tree, va_gc> *ws_args)
6642{
6643 tree t, t1, t2;
6644 gimple_stmt_iterator gsi;
6645 vec <tree, va_gc> *args;
6646
6647 gcc_assert (vec_safe_length (ws_args) == 2);
6648 tree func_name = (*ws_args)[0];
6649 tree grain = (*ws_args)[1];
6650
6651 tree clauses = gimple_omp_parallel_clauses (entry_stmt);
6652 tree count = find_omp_clause (clauses, OMP_CLAUSE__CILK_FOR_COUNT_);
6653 gcc_assert (count != NULL_TREE);
6654 count = OMP_CLAUSE_OPERAND (count, 0);
6655
6656 gsi = gsi_last_bb (bb);
6657 t = gimple_omp_parallel_data_arg (entry_stmt);
6658 if (t == NULL)
6659 t1 = null_pointer_node;
6660 else
6661 t1 = build_fold_addr_expr (t);
6662 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
6663
6664 vec_alloc (args, 4);
6665 args->quick_push (t2);
6666 args->quick_push (t1);
6667 args->quick_push (count);
6668 args->quick_push (grain);
6669 t = build_call_expr_loc_vec (UNKNOWN_LOCATION, func_name, args);
6670
6671 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, false,
6672 GSI_CONTINUE_LINKING);
6673}
773c5ba7 6674
fd6481cf 6675/* Build the function call to GOMP_task to actually
6676 generate the task operation. BB is the block where to insert the code. */
6677
6678static void
43895be5 6679expand_task_call (struct omp_region *region, basic_block bb,
6680 gomp_task *entry_stmt)
fd6481cf 6681{
43895be5 6682 tree t1, t2, t3;
75a70cf9 6683 gimple_stmt_iterator gsi;
389dd41b 6684 location_t loc = gimple_location (entry_stmt);
fd6481cf 6685
43895be5 6686 tree clauses = gimple_omp_task_clauses (entry_stmt);
6687
6688 tree ifc = find_omp_clause (clauses, OMP_CLAUSE_IF);
6689 tree untied = find_omp_clause (clauses, OMP_CLAUSE_UNTIED);
6690 tree mergeable = find_omp_clause (clauses, OMP_CLAUSE_MERGEABLE);
6691 tree depend = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
6692 tree finalc = find_omp_clause (clauses, OMP_CLAUSE_FINAL);
6693 tree priority = find_omp_clause (clauses, OMP_CLAUSE_PRIORITY);
6694
6695 unsigned int iflags
6696 = (untied ? GOMP_TASK_FLAG_UNTIED : 0)
6697 | (mergeable ? GOMP_TASK_FLAG_MERGEABLE : 0)
6698 | (depend ? GOMP_TASK_FLAG_DEPEND : 0);
6699
6700 bool taskloop_p = gimple_omp_task_taskloop_p (entry_stmt);
6701 tree startvar = NULL_TREE, endvar = NULL_TREE, step = NULL_TREE;
6702 tree num_tasks = NULL_TREE;
6703 bool ull = false;
6704 if (taskloop_p)
6705 {
6706 gimple *g = last_stmt (region->outer->entry);
6707 gcc_assert (gimple_code (g) == GIMPLE_OMP_FOR
6708 && gimple_omp_for_kind (g) == GF_OMP_FOR_KIND_TASKLOOP);
6709 struct omp_for_data fd;
6710 extract_omp_for_data (as_a <gomp_for *> (g), &fd, NULL);
6711 startvar = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
6712 endvar = find_omp_clause (OMP_CLAUSE_CHAIN (startvar),
6713 OMP_CLAUSE__LOOPTEMP_);
6714 startvar = OMP_CLAUSE_DECL (startvar);
6715 endvar = OMP_CLAUSE_DECL (endvar);
6716 step = fold_convert_loc (loc, fd.iter_type, fd.loop.step);
6717 if (fd.loop.cond_code == LT_EXPR)
6718 iflags |= GOMP_TASK_FLAG_UP;
6719 tree tclauses = gimple_omp_for_clauses (g);
6720 num_tasks = find_omp_clause (tclauses, OMP_CLAUSE_NUM_TASKS);
6721 if (num_tasks)
6722 num_tasks = OMP_CLAUSE_NUM_TASKS_EXPR (num_tasks);
6723 else
6724 {
6725 num_tasks = find_omp_clause (tclauses, OMP_CLAUSE_GRAINSIZE);
6726 if (num_tasks)
6727 {
6728 iflags |= GOMP_TASK_FLAG_GRAINSIZE;
6729 num_tasks = OMP_CLAUSE_GRAINSIZE_EXPR (num_tasks);
6730 }
6731 else
6732 num_tasks = integer_zero_node;
6733 }
6734 num_tasks = fold_convert_loc (loc, long_integer_type_node, num_tasks);
6735 if (ifc == NULL_TREE)
6736 iflags |= GOMP_TASK_FLAG_IF;
6737 if (find_omp_clause (tclauses, OMP_CLAUSE_NOGROUP))
6738 iflags |= GOMP_TASK_FLAG_NOGROUP;
6739 ull = fd.iter_type == long_long_unsigned_type_node;
6740 }
6741 else if (priority)
6742 iflags |= GOMP_TASK_FLAG_PRIORITY;
fd6481cf 6743
43895be5 6744 tree flags = build_int_cst (unsigned_type_node, iflags);
fd6481cf 6745
43895be5 6746 tree cond = boolean_true_node;
6747 if (ifc)
6748 {
6749 if (taskloop_p)
6750 {
6751 tree t = gimple_boolify (OMP_CLAUSE_IF_EXPR (ifc));
6752 t = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, t,
6753 build_int_cst (unsigned_type_node,
6754 GOMP_TASK_FLAG_IF),
6755 build_int_cst (unsigned_type_node, 0));
6756 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node,
6757 flags, t);
6758 }
6759 else
6760 cond = gimple_boolify (OMP_CLAUSE_IF_EXPR (ifc));
6761 }
2169f33b 6762
43895be5 6763 if (finalc)
2169f33b 6764 {
43895be5 6765 tree t = gimple_boolify (OMP_CLAUSE_FINAL_EXPR (finalc));
6766 t = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, t,
6767 build_int_cst (unsigned_type_node,
6768 GOMP_TASK_FLAG_FINAL),
2169f33b 6769 build_int_cst (unsigned_type_node, 0));
43895be5 6770 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node, flags, t);
2169f33b 6771 }
bc7bff74 6772 if (depend)
6773 depend = OMP_CLAUSE_DECL (depend);
6774 else
6775 depend = build_int_cst (ptr_type_node, 0);
43895be5 6776 if (priority)
6777 priority = fold_convert (integer_type_node,
6778 OMP_CLAUSE_PRIORITY_EXPR (priority));
6779 else
6780 priority = integer_zero_node;
fd6481cf 6781
75a70cf9 6782 gsi = gsi_last_bb (bb);
43895be5 6783 tree t = gimple_omp_task_data_arg (entry_stmt);
fd6481cf 6784 if (t == NULL)
6785 t2 = null_pointer_node;
6786 else
389dd41b 6787 t2 = build_fold_addr_expr_loc (loc, t);
6788 t1 = build_fold_addr_expr_loc (loc, gimple_omp_task_child_fn (entry_stmt));
75a70cf9 6789 t = gimple_omp_task_copy_fn (entry_stmt);
fd6481cf 6790 if (t == NULL)
6791 t3 = null_pointer_node;
6792 else
389dd41b 6793 t3 = build_fold_addr_expr_loc (loc, t);
fd6481cf 6794
43895be5 6795 if (taskloop_p)
6796 t = build_call_expr (ull
6797 ? builtin_decl_explicit (BUILT_IN_GOMP_TASKLOOP_ULL)
6798 : builtin_decl_explicit (BUILT_IN_GOMP_TASKLOOP),
6799 11, t1, t2, t3,
6800 gimple_omp_task_arg_size (entry_stmt),
6801 gimple_omp_task_arg_align (entry_stmt), flags,
6802 num_tasks, priority, startvar, endvar, step);
6803 else
6804 t = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK),
6805 9, t1, t2, t3,
6806 gimple_omp_task_arg_size (entry_stmt),
6807 gimple_omp_task_arg_align (entry_stmt), cond, flags,
6808 depend, priority);
fd6481cf 6809
75a70cf9 6810 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6811 false, GSI_CONTINUE_LINKING);
fd6481cf 6812}
6813
6814
75a70cf9 6815/* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
6816 catch handler and return it. This prevents programs from violating the
6817 structured block semantics with throws. */
1e8e9920 6818
75a70cf9 6819static gimple_seq
6820maybe_catch_exception (gimple_seq body)
1e8e9920 6821{
42acab1c 6822 gimple *g;
e38def9c 6823 tree decl;
1e8e9920 6824
6825 if (!flag_exceptions)
75a70cf9 6826 return body;
1e8e9920 6827
596981c8 6828 if (lang_hooks.eh_protect_cleanup_actions != NULL)
6829 decl = lang_hooks.eh_protect_cleanup_actions ();
1e8e9920 6830 else
b9a16870 6831 decl = builtin_decl_explicit (BUILT_IN_TRAP);
75a70cf9 6832
e38def9c 6833 g = gimple_build_eh_must_not_throw (decl);
6834 g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g),
75a70cf9 6835 GIMPLE_TRY_CATCH);
1e8e9920 6836
e38def9c 6837 return gimple_seq_alloc_with_stmt (g);
1e8e9920 6838}
6839
773c5ba7 6840/* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
1e8e9920 6841
773c5ba7 6842static tree
f1f41a6c 6843vec2chain (vec<tree, va_gc> *v)
1e8e9920 6844{
2ab2ce89 6845 tree chain = NULL_TREE, t;
6846 unsigned ix;
1e8e9920 6847
f1f41a6c 6848 FOR_EACH_VEC_SAFE_ELT_REVERSE (v, ix, t)
773c5ba7 6849 {
1767a056 6850 DECL_CHAIN (t) = chain;
2ab2ce89 6851 chain = t;
773c5ba7 6852 }
1e8e9920 6853
2ab2ce89 6854 return chain;
773c5ba7 6855}
1e8e9920 6856
1e8e9920 6857
773c5ba7 6858/* Remove barriers in REGION->EXIT's block. Note that this is only
75a70cf9 6859 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
6860 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
6861 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
773c5ba7 6862 removed. */
1e8e9920 6863
773c5ba7 6864static void
6865remove_exit_barrier (struct omp_region *region)
6866{
75a70cf9 6867 gimple_stmt_iterator gsi;
773c5ba7 6868 basic_block exit_bb;
61e47ac8 6869 edge_iterator ei;
6870 edge e;
42acab1c 6871 gimple *stmt;
4a04f4b4 6872 int any_addressable_vars = -1;
1e8e9920 6873
61e47ac8 6874 exit_bb = region->exit;
1e8e9920 6875
5056ba1a 6876 /* If the parallel region doesn't return, we don't have REGION->EXIT
6877 block at all. */
6878 if (! exit_bb)
6879 return;
6880
75a70cf9 6881 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
6882 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
61e47ac8 6883 statements that can appear in between are extremely limited -- no
6884 memory operations at all. Here, we allow nothing at all, so the
75a70cf9 6885 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
6886 gsi = gsi_last_bb (exit_bb);
6887 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
6888 gsi_prev (&gsi);
6889 if (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
773c5ba7 6890 return;
1e8e9920 6891
61e47ac8 6892 FOR_EACH_EDGE (e, ei, exit_bb->preds)
6893 {
75a70cf9 6894 gsi = gsi_last_bb (e->src);
6895 if (gsi_end_p (gsi))
61e47ac8 6896 continue;
75a70cf9 6897 stmt = gsi_stmt (gsi);
4a04f4b4 6898 if (gimple_code (stmt) == GIMPLE_OMP_RETURN
6899 && !gimple_omp_return_nowait_p (stmt))
6900 {
6901 /* OpenMP 3.0 tasks unfortunately prevent this optimization
6902 in many cases. If there could be tasks queued, the barrier
6903 might be needed to let the tasks run before some local
6904 variable of the parallel that the task uses as shared
6905 runs out of scope. The task can be spawned either
6906 from within current function (this would be easy to check)
6907 or from some function it calls and gets passed an address
6908 of such a variable. */
6909 if (any_addressable_vars < 0)
6910 {
1a91d914 6911 gomp_parallel *parallel_stmt
6912 = as_a <gomp_parallel *> (last_stmt (region->entry));
4a04f4b4 6913 tree child_fun = gimple_omp_parallel_child_fn (parallel_stmt);
2ab2ce89 6914 tree local_decls, block, decl;
6915 unsigned ix;
4a04f4b4 6916
6917 any_addressable_vars = 0;
2ab2ce89 6918 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun), ix, decl)
6919 if (TREE_ADDRESSABLE (decl))
4a04f4b4 6920 {
6921 any_addressable_vars = 1;
6922 break;
6923 }
6924 for (block = gimple_block (stmt);
6925 !any_addressable_vars
6926 && block
6927 && TREE_CODE (block) == BLOCK;
6928 block = BLOCK_SUPERCONTEXT (block))
6929 {
6930 for (local_decls = BLOCK_VARS (block);
6931 local_decls;
1767a056 6932 local_decls = DECL_CHAIN (local_decls))
4a04f4b4 6933 if (TREE_ADDRESSABLE (local_decls))
6934 {
6935 any_addressable_vars = 1;
6936 break;
6937 }
6938 if (block == gimple_block (parallel_stmt))
6939 break;
6940 }
6941 }
6942 if (!any_addressable_vars)
6943 gimple_omp_return_set_nowait (stmt);
6944 }
61e47ac8 6945 }
1e8e9920 6946}
6947
61e47ac8 6948static void
6949remove_exit_barriers (struct omp_region *region)
6950{
75a70cf9 6951 if (region->type == GIMPLE_OMP_PARALLEL)
61e47ac8 6952 remove_exit_barrier (region);
6953
6954 if (region->inner)
6955 {
6956 region = region->inner;
6957 remove_exit_barriers (region);
6958 while (region->next)
6959 {
6960 region = region->next;
6961 remove_exit_barriers (region);
6962 }
6963 }
6964}
773c5ba7 6965
658b4427 6966/* Optimize omp_get_thread_num () and omp_get_num_threads ()
6967 calls. These can't be declared as const functions, but
6968 within one parallel body they are constant, so they can be
6969 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
fd6481cf 6970 which are declared const. Similarly for task body, except
6971 that in untied task omp_get_thread_num () can change at any task
6972 scheduling point. */
658b4427 6973
6974static void
42acab1c 6975optimize_omp_library_calls (gimple *entry_stmt)
658b4427 6976{
6977 basic_block bb;
75a70cf9 6978 gimple_stmt_iterator gsi;
b9a16870 6979 tree thr_num_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
6980 tree thr_num_id = DECL_ASSEMBLER_NAME (thr_num_tree);
6981 tree num_thr_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
6982 tree num_thr_id = DECL_ASSEMBLER_NAME (num_thr_tree);
75a70cf9 6983 bool untied_task = (gimple_code (entry_stmt) == GIMPLE_OMP_TASK
6984 && find_omp_clause (gimple_omp_task_clauses (entry_stmt),
fd6481cf 6985 OMP_CLAUSE_UNTIED) != NULL);
658b4427 6986
fc00614f 6987 FOR_EACH_BB_FN (bb, cfun)
75a70cf9 6988 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
658b4427 6989 {
42acab1c 6990 gimple *call = gsi_stmt (gsi);
658b4427 6991 tree decl;
6992
75a70cf9 6993 if (is_gimple_call (call)
6994 && (decl = gimple_call_fndecl (call))
658b4427 6995 && DECL_EXTERNAL (decl)
6996 && TREE_PUBLIC (decl)
6997 && DECL_INITIAL (decl) == NULL)
6998 {
6999 tree built_in;
7000
7001 if (DECL_NAME (decl) == thr_num_id)
fd6481cf 7002 {
7003 /* In #pragma omp task untied omp_get_thread_num () can change
7004 during the execution of the task region. */
7005 if (untied_task)
7006 continue;
b9a16870 7007 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
fd6481cf 7008 }
658b4427 7009 else if (DECL_NAME (decl) == num_thr_id)
b9a16870 7010 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
658b4427 7011 else
7012 continue;
7013
7014 if (DECL_ASSEMBLER_NAME (decl) != DECL_ASSEMBLER_NAME (built_in)
75a70cf9 7015 || gimple_call_num_args (call) != 0)
658b4427 7016 continue;
7017
7018 if (flag_exceptions && !TREE_NOTHROW (decl))
7019 continue;
7020
7021 if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
1ea6a73c 7022 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl)),
7023 TREE_TYPE (TREE_TYPE (built_in))))
658b4427 7024 continue;
7025
0acacf9e 7026 gimple_call_set_fndecl (call, built_in);
658b4427 7027 }
7028 }
7029}
7030
8e6b4515 7031/* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
7032 regimplified. */
7033
7034static tree
7035expand_omp_regimplify_p (tree *tp, int *walk_subtrees, void *)
7036{
7037 tree t = *tp;
7038
7039 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
7040 if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t))
7041 return t;
7042
7043 if (TREE_CODE (t) == ADDR_EXPR)
7044 recompute_tree_invariant_for_addr_expr (t);
7045
7046 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
7047 return NULL_TREE;
7048}
7049
43895be5 7050/* Prepend or append TO = FROM assignment before or after *GSI_P. */
3d483a94 7051
7052static void
43895be5 7053expand_omp_build_assign (gimple_stmt_iterator *gsi_p, tree to, tree from,
7054 bool after)
3d483a94 7055{
7056 bool simple_p = DECL_P (to) && TREE_ADDRESSABLE (to);
7057 from = force_gimple_operand_gsi (gsi_p, from, simple_p, NULL_TREE,
43895be5 7058 !after, after ? GSI_CONTINUE_LINKING
7059 : GSI_SAME_STMT);
42acab1c 7060 gimple *stmt = gimple_build_assign (to, from);
43895be5 7061 if (after)
7062 gsi_insert_after (gsi_p, stmt, GSI_CONTINUE_LINKING);
7063 else
7064 gsi_insert_before (gsi_p, stmt, GSI_SAME_STMT);
3d483a94 7065 if (walk_tree (&from, expand_omp_regimplify_p, NULL, NULL)
7066 || walk_tree (&to, expand_omp_regimplify_p, NULL, NULL))
7067 {
7068 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
7069 gimple_regimplify_operands (stmt, &gsi);
7070 }
7071}
7072
fd6481cf 7073/* Expand the OpenMP parallel or task directive starting at REGION. */
1e8e9920 7074
7075static void
fd6481cf 7076expand_omp_taskreg (struct omp_region *region)
1e8e9920 7077{
773c5ba7 7078 basic_block entry_bb, exit_bb, new_bb;
87d4aa85 7079 struct function *child_cfun;
414c3a2c 7080 tree child_fn, block, t;
75a70cf9 7081 gimple_stmt_iterator gsi;
42acab1c 7082 gimple *entry_stmt, *stmt;
773c5ba7 7083 edge e;
f1f41a6c 7084 vec<tree, va_gc> *ws_args;
773c5ba7 7085
61e47ac8 7086 entry_stmt = last_stmt (region->entry);
75a70cf9 7087 child_fn = gimple_omp_taskreg_child_fn (entry_stmt);
773c5ba7 7088 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
773c5ba7 7089
61e47ac8 7090 entry_bb = region->entry;
b25f70fd 7091 if (gimple_code (entry_stmt) == GIMPLE_OMP_TASK)
7092 exit_bb = region->cont;
7093 else
7094 exit_bb = region->exit;
773c5ba7 7095
40750995 7096 bool is_cilk_for
7097 = (flag_cilkplus
7098 && gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL
7099 && find_omp_clause (gimple_omp_parallel_clauses (entry_stmt),
7100 OMP_CLAUSE__CILK_FOR_COUNT_) != NULL_TREE);
7101
7102 if (is_cilk_for)
7103 /* If it is a _Cilk_for statement, it is modelled *like* a parallel for,
7104 and the inner statement contains the name of the built-in function
7105 and grain. */
7106 ws_args = region->inner->ws_args;
7107 else if (is_combined_parallel (region))
61e47ac8 7108 ws_args = region->ws_args;
773c5ba7 7109 else
414c3a2c 7110 ws_args = NULL;
1e8e9920 7111
61e47ac8 7112 if (child_cfun->cfg)
1e8e9920 7113 {
773c5ba7 7114 /* Due to inlining, it may happen that we have already outlined
7115 the region, in which case all we need to do is make the
7116 sub-graph unreachable and emit the parallel call. */
7117 edge entry_succ_e, exit_succ_e;
773c5ba7 7118
7119 entry_succ_e = single_succ_edge (entry_bb);
773c5ba7 7120
75a70cf9 7121 gsi = gsi_last_bb (entry_bb);
7122 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_PARALLEL
7123 || gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_TASK);
7124 gsi_remove (&gsi, true);
773c5ba7 7125
7126 new_bb = entry_bb;
03ed154b 7127 if (exit_bb)
7128 {
7129 exit_succ_e = single_succ_edge (exit_bb);
7130 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
7131 }
79acaae1 7132 remove_edge_and_dominated_blocks (entry_succ_e);
1e8e9920 7133 }
773c5ba7 7134 else
7135 {
501bdd19 7136 unsigned srcidx, dstidx, num;
2ab2ce89 7137
773c5ba7 7138 /* If the parallel region needs data sent from the parent
3480139d 7139 function, then the very first statement (except possible
7140 tree profile counter updates) of the parallel body
773c5ba7 7141 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
7142 &.OMP_DATA_O is passed as an argument to the child function,
7143 we need to replace it with the argument as seen by the child
7144 function.
7145
7146 In most cases, this will end up being the identity assignment
7147 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
7148 a function call that has been inlined, the original PARM_DECL
7149 .OMP_DATA_I may have been converted into a different local
7150 variable. In which case, we need to keep the assignment. */
75a70cf9 7151 if (gimple_omp_taskreg_data_arg (entry_stmt))
773c5ba7 7152 {
b25f70fd 7153 basic_block entry_succ_bb
7154 = single_succ_p (entry_bb) ? single_succ (entry_bb)
7155 : FALLTHRU_EDGE (entry_bb)->dest;
883f001d 7156 tree arg;
42acab1c 7157 gimple *parcopy_stmt = NULL;
1e8e9920 7158
75a70cf9 7159 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
3480139d 7160 {
42acab1c 7161 gimple *stmt;
3480139d 7162
75a70cf9 7163 gcc_assert (!gsi_end_p (gsi));
7164 stmt = gsi_stmt (gsi);
7165 if (gimple_code (stmt) != GIMPLE_ASSIGN)
cc6b725b 7166 continue;
7167
75a70cf9 7168 if (gimple_num_ops (stmt) == 2)
3480139d 7169 {
75a70cf9 7170 tree arg = gimple_assign_rhs1 (stmt);
7171
7172 /* We're ignore the subcode because we're
7173 effectively doing a STRIP_NOPS. */
7174
7175 if (TREE_CODE (arg) == ADDR_EXPR
7176 && TREE_OPERAND (arg, 0)
7177 == gimple_omp_taskreg_data_arg (entry_stmt))
7178 {
7179 parcopy_stmt = stmt;
7180 break;
7181 }
3480139d 7182 }
7183 }
79acaae1 7184
75a70cf9 7185 gcc_assert (parcopy_stmt != NULL);
79acaae1 7186 arg = DECL_ARGUMENTS (child_fn);
7187
7188 if (!gimple_in_ssa_p (cfun))
7189 {
75a70cf9 7190 if (gimple_assign_lhs (parcopy_stmt) == arg)
7191 gsi_remove (&gsi, true);
79acaae1 7192 else
75a70cf9 7193 {
7194 /* ?? Is setting the subcode really necessary ?? */
7195 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (arg));
7196 gimple_assign_set_rhs1 (parcopy_stmt, arg);
7197 }
79acaae1 7198 }
7199 else
7200 {
883f001d 7201 tree lhs = gimple_assign_lhs (parcopy_stmt);
7202 gcc_assert (SSA_NAME_VAR (lhs) == arg);
7203 /* We'd like to set the rhs to the default def in the child_fn,
7204 but it's too early to create ssa names in the child_fn.
7205 Instead, we set the rhs to the parm. In
7206 move_sese_region_to_fn, we introduce a default def for the
7207 parm, map the parm to it's default def, and once we encounter
7208 this stmt, replace the parm with the default def. */
7209 gimple_assign_set_rhs1 (parcopy_stmt, arg);
79acaae1 7210 update_stmt (parcopy_stmt);
7211 }
773c5ba7 7212 }
7213
7214 /* Declare local variables needed in CHILD_CFUN. */
7215 block = DECL_INITIAL (child_fn);
2ab2ce89 7216 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
e1a7ccb9 7217 /* The gimplifier could record temporaries in parallel/task block
7218 rather than in containing function's local_decls chain,
7219 which would mean cgraph missed finalizing them. Do it now. */
1767a056 7220 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
e1a7ccb9 7221 if (TREE_CODE (t) == VAR_DECL
7222 && TREE_STATIC (t)
7223 && !DECL_EXTERNAL (t))
97221fd7 7224 varpool_node::finalize_decl (t);
75a70cf9 7225 DECL_SAVED_TREE (child_fn) = NULL;
e3a19533 7226 /* We'll create a CFG for child_fn, so no gimple body is needed. */
7227 gimple_set_body (child_fn, NULL);
1d22f541 7228 TREE_USED (block) = 1;
773c5ba7 7229
79acaae1 7230 /* Reset DECL_CONTEXT on function arguments. */
1767a056 7231 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
773c5ba7 7232 DECL_CONTEXT (t) = child_fn;
7233
75a70cf9 7234 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
7235 so that it can be moved to the child function. */
7236 gsi = gsi_last_bb (entry_bb);
7237 stmt = gsi_stmt (gsi);
7238 gcc_assert (stmt && (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
7239 || gimple_code (stmt) == GIMPLE_OMP_TASK));
75a70cf9 7240 e = split_block (entry_bb, stmt);
923635e7 7241 gsi_remove (&gsi, true);
773c5ba7 7242 entry_bb = e->dest;
b25f70fd 7243 edge e2 = NULL;
7244 if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
7245 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7246 else
7247 {
7248 e2 = make_edge (e->src, BRANCH_EDGE (entry_bb)->dest, EDGE_ABNORMAL);
7249 gcc_assert (e2->dest == region->exit);
7250 remove_edge (BRANCH_EDGE (entry_bb));
7251 set_immediate_dominator (CDI_DOMINATORS, e2->dest, e->src);
7252 gsi = gsi_last_bb (region->exit);
7253 gcc_assert (!gsi_end_p (gsi)
7254 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
7255 gsi_remove (&gsi, true);
7256 }
773c5ba7 7257
b25f70fd 7258 /* Convert GIMPLE_OMP_{RETURN,CONTINUE} into a RETURN_EXPR. */
5056ba1a 7259 if (exit_bb)
7260 {
75a70cf9 7261 gsi = gsi_last_bb (exit_bb);
7262 gcc_assert (!gsi_end_p (gsi)
b25f70fd 7263 && (gimple_code (gsi_stmt (gsi))
7264 == (e2 ? GIMPLE_OMP_CONTINUE : GIMPLE_OMP_RETURN)));
75a70cf9 7265 stmt = gimple_build_return (NULL);
7266 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
7267 gsi_remove (&gsi, true);
5056ba1a 7268 }
79acaae1 7269
7270 /* Move the parallel region into CHILD_CFUN. */
48e1416a 7271
79acaae1 7272 if (gimple_in_ssa_p (cfun))
7273 {
bcaa2770 7274 init_tree_ssa (child_cfun);
5084b2e4 7275 init_ssa_operands (child_cfun);
7276 child_cfun->gimple_df->in_ssa_p = true;
1d22f541 7277 block = NULL_TREE;
79acaae1 7278 }
1d22f541 7279 else
75a70cf9 7280 block = gimple_block (entry_stmt);
1d22f541 7281
7282 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
79acaae1 7283 if (exit_bb)
7284 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
b25f70fd 7285 if (e2)
7286 {
7287 basic_block dest_bb = e2->dest;
7288 if (!exit_bb)
7289 make_edge (new_bb, dest_bb, EDGE_FALLTHRU);
7290 remove_edge (e2);
7291 set_immediate_dominator (CDI_DOMINATORS, dest_bb, new_bb);
7292 }
04c2922b 7293 /* When the OMP expansion process cannot guarantee an up-to-date
7294 loop tree arrange for the child function to fixup loops. */
7295 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
7296 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
79acaae1 7297
1d22f541 7298 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
f1f41a6c 7299 num = vec_safe_length (child_cfun->local_decls);
501bdd19 7300 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
7301 {
f1f41a6c 7302 t = (*child_cfun->local_decls)[srcidx];
501bdd19 7303 if (DECL_CONTEXT (t) == cfun->decl)
7304 continue;
7305 if (srcidx != dstidx)
f1f41a6c 7306 (*child_cfun->local_decls)[dstidx] = t;
501bdd19 7307 dstidx++;
7308 }
7309 if (dstidx != num)
f1f41a6c 7310 vec_safe_truncate (child_cfun->local_decls, dstidx);
1d22f541 7311
79acaae1 7312 /* Inform the callgraph about the new function. */
9918db44 7313 child_cfun->curr_properties = cfun->curr_properties;
7314 child_cfun->has_simduid_loops |= cfun->has_simduid_loops;
7315 child_cfun->has_force_vectorize_loops |= cfun->has_force_vectorize_loops;
47300487 7316 cgraph_node *node = cgraph_node::get_create (child_fn);
7317 node->parallelized_function = 1;
415d1b9a 7318 cgraph_node::add_new_function (child_fn, true);
79acaae1 7319
9561765e 7320 bool need_asm = DECL_ASSEMBLER_NAME_SET_P (current_function_decl)
7321 && !DECL_ASSEMBLER_NAME_SET_P (child_fn);
7322
79acaae1 7323 /* Fix the callgraph edges for child_cfun. Those for cfun will be
7324 fixed in a following pass. */
7325 push_cfun (child_cfun);
9561765e 7326 if (need_asm)
7327 assign_assembler_name_if_neeeded (child_fn);
7328
658b4427 7329 if (optimize)
fd6481cf 7330 optimize_omp_library_calls (entry_stmt);
35ee1c66 7331 cgraph_edge::rebuild_edges ();
fbe86b1b 7332
7333 /* Some EH regions might become dead, see PR34608. If
7334 pass_cleanup_cfg isn't the first pass to happen with the
7335 new child, these dead EH edges might cause problems.
7336 Clean them up now. */
7337 if (flag_exceptions)
7338 {
7339 basic_block bb;
fbe86b1b 7340 bool changed = false;
7341
fc00614f 7342 FOR_EACH_BB_FN (bb, cfun)
75a70cf9 7343 changed |= gimple_purge_dead_eh_edges (bb);
fbe86b1b 7344 if (changed)
7345 cleanup_tree_cfg ();
fbe86b1b 7346 }
dd277d48 7347 if (gimple_in_ssa_p (cfun))
7348 update_ssa (TODO_update_ssa);
382ecba7 7349 if (flag_checking && !loops_state_satisfies_p (LOOPS_NEED_FIXUP))
86a932e0 7350 verify_loop_structure ();
79acaae1 7351 pop_cfun ();
9561765e 7352
7353 if (dump_file && !gimple_in_ssa_p (cfun))
7354 {
7355 omp_any_child_fn_dumped = true;
7356 dump_function_header (dump_file, child_fn, dump_flags);
7357 dump_function_to_file (child_fn, dump_file, dump_flags);
7358 }
773c5ba7 7359 }
48e1416a 7360
773c5ba7 7361 /* Emit a library call to launch the children threads. */
40750995 7362 if (is_cilk_for)
1a91d914 7363 expand_cilk_for_call (new_bb,
7364 as_a <gomp_parallel *> (entry_stmt), ws_args);
40750995 7365 else if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
1a91d914 7366 expand_parallel_call (region, new_bb,
7367 as_a <gomp_parallel *> (entry_stmt), ws_args);
fd6481cf 7368 else
43895be5 7369 expand_task_call (region, new_bb, as_a <gomp_task *> (entry_stmt));
083152fb 7370 if (gimple_in_ssa_p (cfun))
7371 update_ssa (TODO_update_ssa_only_virtuals);
1e8e9920 7372}
7373
a8e785ba 7374/* Information about members of an OpenACC collapsed loop nest. */
7375
7376struct oacc_collapse
7377{
7378 tree base; /* Base value. */
7379 tree iters; /* Number of steps. */
7380 tree step; /* step size. */
7381};
7382
7383/* Helper for expand_oacc_for. Determine collapsed loop information.
7384 Fill in COUNTS array. Emit any initialization code before GSI.
7385 Return the calculated outer loop bound of BOUND_TYPE. */
7386
7387static tree
7388expand_oacc_collapse_init (const struct omp_for_data *fd,
7389 gimple_stmt_iterator *gsi,
7390 oacc_collapse *counts, tree bound_type)
7391{
7392 tree total = build_int_cst (bound_type, 1);
7393 int ix;
7394
7395 gcc_assert (integer_onep (fd->loop.step));
7396 gcc_assert (integer_zerop (fd->loop.n1));
7397
7398 for (ix = 0; ix != fd->collapse; ix++)
7399 {
7400 const omp_for_data_loop *loop = &fd->loops[ix];
7401
7402 tree iter_type = TREE_TYPE (loop->v);
7403 tree diff_type = iter_type;
7404 tree plus_type = iter_type;
7405
7406 gcc_assert (loop->cond_code == fd->loop.cond_code);
7407
7408 if (POINTER_TYPE_P (iter_type))
7409 plus_type = sizetype;
7410 if (POINTER_TYPE_P (diff_type) || TYPE_UNSIGNED (diff_type))
7411 diff_type = signed_type_for (diff_type);
7412
7413 tree b = loop->n1;
7414 tree e = loop->n2;
7415 tree s = loop->step;
7416 bool up = loop->cond_code == LT_EXPR;
7417 tree dir = build_int_cst (diff_type, up ? +1 : -1);
7418 bool negating;
7419 tree expr;
7420
7421 b = force_gimple_operand_gsi (gsi, b, true, NULL_TREE,
7422 true, GSI_SAME_STMT);
7423 e = force_gimple_operand_gsi (gsi, e, true, NULL_TREE,
7424 true, GSI_SAME_STMT);
7425
7426 /* Convert the step, avoiding possible unsigned->signed overflow. */
7427 negating = !up && TYPE_UNSIGNED (TREE_TYPE (s));
7428 if (negating)
7429 s = fold_build1 (NEGATE_EXPR, TREE_TYPE (s), s);
7430 s = fold_convert (diff_type, s);
7431 if (negating)
7432 s = fold_build1 (NEGATE_EXPR, diff_type, s);
7433 s = force_gimple_operand_gsi (gsi, s, true, NULL_TREE,
7434 true, GSI_SAME_STMT);
7435
7436 /* Determine the range, avoiding possible unsigned->signed overflow. */
7437 negating = !up && TYPE_UNSIGNED (iter_type);
7438 expr = fold_build2 (MINUS_EXPR, plus_type,
7439 fold_convert (plus_type, negating ? b : e),
7440 fold_convert (plus_type, negating ? e : b));
7441 expr = fold_convert (diff_type, expr);
7442 if (negating)
7443 expr = fold_build1 (NEGATE_EXPR, diff_type, expr);
7444 tree range = force_gimple_operand_gsi
7445 (gsi, expr, true, NULL_TREE, true, GSI_SAME_STMT);
7446
7447 /* Determine number of iterations. */
7448 expr = fold_build2 (MINUS_EXPR, diff_type, range, dir);
7449 expr = fold_build2 (PLUS_EXPR, diff_type, expr, s);
7450 expr = fold_build2 (TRUNC_DIV_EXPR, diff_type, expr, s);
7451
7452 tree iters = force_gimple_operand_gsi (gsi, expr, true, NULL_TREE,
7453 true, GSI_SAME_STMT);
7454
7455 counts[ix].base = b;
7456 counts[ix].iters = iters;
7457 counts[ix].step = s;
7458
7459 total = fold_build2 (MULT_EXPR, bound_type, total,
7460 fold_convert (bound_type, iters));
7461 }
7462
7463 return total;
7464}
7465
7466/* Emit initializers for collapsed loop members. IVAR is the outer
7467 loop iteration variable, from which collapsed loop iteration values
7468 are calculated. COUNTS array has been initialized by
7469 expand_oacc_collapse_inits. */
7470
7471static void
7472expand_oacc_collapse_vars (const struct omp_for_data *fd,
7473 gimple_stmt_iterator *gsi,
7474 const oacc_collapse *counts, tree ivar)
7475{
7476 tree ivar_type = TREE_TYPE (ivar);
7477
7478 /* The most rapidly changing iteration variable is the innermost
7479 one. */
7480 for (int ix = fd->collapse; ix--;)
7481 {
7482 const omp_for_data_loop *loop = &fd->loops[ix];
7483 const oacc_collapse *collapse = &counts[ix];
7484 tree iter_type = TREE_TYPE (loop->v);
7485 tree diff_type = TREE_TYPE (collapse->step);
7486 tree plus_type = iter_type;
7487 enum tree_code plus_code = PLUS_EXPR;
7488 tree expr;
7489
7490 if (POINTER_TYPE_P (iter_type))
7491 {
7492 plus_code = POINTER_PLUS_EXPR;
7493 plus_type = sizetype;
7494 }
7495
7496 expr = fold_build2 (TRUNC_MOD_EXPR, ivar_type, ivar,
7497 fold_convert (ivar_type, collapse->iters));
7498 expr = fold_build2 (MULT_EXPR, diff_type, fold_convert (diff_type, expr),
7499 collapse->step);
7500 expr = fold_build2 (plus_code, iter_type, collapse->base,
7501 fold_convert (plus_type, expr));
7502 expr = force_gimple_operand_gsi (gsi, expr, false, NULL_TREE,
7503 true, GSI_SAME_STMT);
7504 gassign *ass = gimple_build_assign (loop->v, expr);
7505 gsi_insert_before (gsi, ass, GSI_SAME_STMT);
7506
7507 if (ix)
7508 {
7509 expr = fold_build2 (TRUNC_DIV_EXPR, ivar_type, ivar,
7510 fold_convert (ivar_type, collapse->iters));
7511 ivar = force_gimple_operand_gsi (gsi, expr, true, NULL_TREE,
7512 true, GSI_SAME_STMT);
7513 }
7514 }
7515}
7516
773c5ba7 7517
3d483a94 7518/* Helper function for expand_omp_{for_*,simd}. If this is the outermost
7519 of the combined collapse > 1 loop constructs, generate code like:
7520 if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
7521 if (cond3 is <)
7522 adj = STEP3 - 1;
7523 else
7524 adj = STEP3 + 1;
7525 count3 = (adj + N32 - N31) / STEP3;
7526 if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
7527 if (cond2 is <)
7528 adj = STEP2 - 1;
7529 else
7530 adj = STEP2 + 1;
7531 count2 = (adj + N22 - N21) / STEP2;
7532 if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
7533 if (cond1 is <)
7534 adj = STEP1 - 1;
7535 else
7536 adj = STEP1 + 1;
7537 count1 = (adj + N12 - N11) / STEP1;
7538 count = count1 * count2 * count3;
7539 Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
7540 count = 0;
bc7bff74 7541 and set ZERO_ITER_BB to that bb. If this isn't the outermost
7542 of the combined loop constructs, just initialize COUNTS array
7543 from the _looptemp_ clauses. */
3d483a94 7544
7545/* NOTE: It *could* be better to moosh all of the BBs together,
7546 creating one larger BB with all the computation and the unexpected
7547 jump at the end. I.e.
7548
7549 bool zero3, zero2, zero1, zero;
7550
7551 zero3 = N32 c3 N31;
7552 count3 = (N32 - N31) /[cl] STEP3;
7553 zero2 = N22 c2 N21;
7554 count2 = (N22 - N21) /[cl] STEP2;
7555 zero1 = N12 c1 N11;
7556 count1 = (N12 - N11) /[cl] STEP1;
7557 zero = zero3 || zero2 || zero1;
7558 count = count1 * count2 * count3;
7559 if (__builtin_expect(zero, false)) goto zero_iter_bb;
7560
7561 After all, we expect the zero=false, and thus we expect to have to
7562 evaluate all of the comparison expressions, so short-circuiting
7563 oughtn't be a win. Since the condition isn't protecting a
7564 denominator, we're not concerned about divide-by-zero, so we can
7565 fully evaluate count even if a numerator turned out to be wrong.
7566
7567 It seems like putting this all together would create much better
7568 scheduling opportunities, and less pressure on the chip's branch
7569 predictor. */
7570
7571static void
7572expand_omp_for_init_counts (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
7573 basic_block &entry_bb, tree *counts,
43895be5 7574 basic_block &zero_iter1_bb, int &first_zero_iter1,
7575 basic_block &zero_iter2_bb, int &first_zero_iter2,
3d483a94 7576 basic_block &l2_dom_bb)
7577{
7578 tree t, type = TREE_TYPE (fd->loop.v);
3d483a94 7579 edge e, ne;
7580 int i;
7581
7582 /* Collapsed loops need work for expansion into SSA form. */
7583 gcc_assert (!gimple_in_ssa_p (cfun));
7584
bc7bff74 7585 if (gimple_omp_for_combined_into_p (fd->for_stmt)
7586 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
7587 {
43895be5 7588 gcc_assert (fd->ordered == 0);
bc7bff74 7589 /* First two _looptemp_ clauses are for istart/iend, counts[0]
7590 isn't supposed to be handled, as the inner loop doesn't
7591 use it. */
7592 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7593 OMP_CLAUSE__LOOPTEMP_);
7594 gcc_assert (innerc);
7595 for (i = 0; i < fd->collapse; i++)
7596 {
7597 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7598 OMP_CLAUSE__LOOPTEMP_);
7599 gcc_assert (innerc);
7600 if (i)
7601 counts[i] = OMP_CLAUSE_DECL (innerc);
7602 else
7603 counts[0] = NULL_TREE;
7604 }
7605 return;
7606 }
7607
43895be5 7608 for (i = fd->collapse; i < fd->ordered; i++)
7609 {
7610 tree itype = TREE_TYPE (fd->loops[i].v);
7611 counts[i] = NULL_TREE;
7612 t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
7613 fold_convert (itype, fd->loops[i].n1),
7614 fold_convert (itype, fd->loops[i].n2));
7615 if (t && integer_zerop (t))
7616 {
7617 for (i = fd->collapse; i < fd->ordered; i++)
7618 counts[i] = build_int_cst (type, 0);
7619 break;
7620 }
7621 }
7622 for (i = 0; i < (fd->ordered ? fd->ordered : fd->collapse); i++)
3d483a94 7623 {
7624 tree itype = TREE_TYPE (fd->loops[i].v);
7625
43895be5 7626 if (i >= fd->collapse && counts[i])
7627 continue;
7628 if ((SSA_VAR_P (fd->loop.n2) || i >= fd->collapse)
3d483a94 7629 && ((t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
7630 fold_convert (itype, fd->loops[i].n1),
7631 fold_convert (itype, fd->loops[i].n2)))
7632 == NULL_TREE || !integer_onep (t)))
7633 {
1a91d914 7634 gcond *cond_stmt;
3d483a94 7635 tree n1, n2;
7636 n1 = fold_convert (itype, unshare_expr (fd->loops[i].n1));
7637 n1 = force_gimple_operand_gsi (gsi, n1, true, NULL_TREE,
7638 true, GSI_SAME_STMT);
7639 n2 = fold_convert (itype, unshare_expr (fd->loops[i].n2));
7640 n2 = force_gimple_operand_gsi (gsi, n2, true, NULL_TREE,
7641 true, GSI_SAME_STMT);
1a91d914 7642 cond_stmt = gimple_build_cond (fd->loops[i].cond_code, n1, n2,
7643 NULL_TREE, NULL_TREE);
7644 gsi_insert_before (gsi, cond_stmt, GSI_SAME_STMT);
7645 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
3d483a94 7646 expand_omp_regimplify_p, NULL, NULL)
1a91d914 7647 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
3d483a94 7648 expand_omp_regimplify_p, NULL, NULL))
7649 {
1a91d914 7650 *gsi = gsi_for_stmt (cond_stmt);
7651 gimple_regimplify_operands (cond_stmt, gsi);
3d483a94 7652 }
1a91d914 7653 e = split_block (entry_bb, cond_stmt);
43895be5 7654 basic_block &zero_iter_bb
7655 = i < fd->collapse ? zero_iter1_bb : zero_iter2_bb;
7656 int &first_zero_iter
7657 = i < fd->collapse ? first_zero_iter1 : first_zero_iter2;
3d483a94 7658 if (zero_iter_bb == NULL)
7659 {
1a91d914 7660 gassign *assign_stmt;
3d483a94 7661 first_zero_iter = i;
7662 zero_iter_bb = create_empty_bb (entry_bb);
b3083327 7663 add_bb_to_loop (zero_iter_bb, entry_bb->loop_father);
3d483a94 7664 *gsi = gsi_after_labels (zero_iter_bb);
43895be5 7665 if (i < fd->collapse)
7666 assign_stmt = gimple_build_assign (fd->loop.n2,
7667 build_zero_cst (type));
7668 else
7669 {
7670 counts[i] = create_tmp_reg (type, ".count");
7671 assign_stmt
7672 = gimple_build_assign (counts[i], build_zero_cst (type));
7673 }
1a91d914 7674 gsi_insert_before (gsi, assign_stmt, GSI_SAME_STMT);
3d483a94 7675 set_immediate_dominator (CDI_DOMINATORS, zero_iter_bb,
7676 entry_bb);
7677 }
7678 ne = make_edge (entry_bb, zero_iter_bb, EDGE_FALSE_VALUE);
7679 ne->probability = REG_BR_PROB_BASE / 2000 - 1;
7680 e->flags = EDGE_TRUE_VALUE;
7681 e->probability = REG_BR_PROB_BASE - ne->probability;
7682 if (l2_dom_bb == NULL)
7683 l2_dom_bb = entry_bb;
7684 entry_bb = e->dest;
7685 *gsi = gsi_last_bb (entry_bb);
7686 }
7687
7688 if (POINTER_TYPE_P (itype))
7689 itype = signed_type_for (itype);
7690 t = build_int_cst (itype, (fd->loops[i].cond_code == LT_EXPR
7691 ? -1 : 1));
7692 t = fold_build2 (PLUS_EXPR, itype,
7693 fold_convert (itype, fd->loops[i].step), t);
7694 t = fold_build2 (PLUS_EXPR, itype, t,
7695 fold_convert (itype, fd->loops[i].n2));
7696 t = fold_build2 (MINUS_EXPR, itype, t,
7697 fold_convert (itype, fd->loops[i].n1));
7698 /* ?? We could probably use CEIL_DIV_EXPR instead of
7699 TRUNC_DIV_EXPR and adjusting by hand. Unless we can't
7700 generate the same code in the end because generically we
7701 don't know that the values involved must be negative for
7702 GT?? */
7703 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
7704 t = fold_build2 (TRUNC_DIV_EXPR, itype,
7705 fold_build1 (NEGATE_EXPR, itype, t),
7706 fold_build1 (NEGATE_EXPR, itype,
7707 fold_convert (itype,
7708 fd->loops[i].step)));
7709 else
7710 t = fold_build2 (TRUNC_DIV_EXPR, itype, t,
7711 fold_convert (itype, fd->loops[i].step));
7712 t = fold_convert (type, t);
7713 if (TREE_CODE (t) == INTEGER_CST)
7714 counts[i] = t;
7715 else
7716 {
43895be5 7717 if (i < fd->collapse || i != first_zero_iter2)
7718 counts[i] = create_tmp_reg (type, ".count");
3d483a94 7719 expand_omp_build_assign (gsi, counts[i], t);
7720 }
43895be5 7721 if (SSA_VAR_P (fd->loop.n2) && i < fd->collapse)
3d483a94 7722 {
7723 if (i == 0)
7724 t = counts[0];
7725 else
7726 t = fold_build2 (MULT_EXPR, type, fd->loop.n2, counts[i]);
7727 expand_omp_build_assign (gsi, fd->loop.n2, t);
7728 }
7729 }
7730}
7731
7732
7733/* Helper function for expand_omp_{for_*,simd}. Generate code like:
7734 T = V;
7735 V3 = N31 + (T % count3) * STEP3;
7736 T = T / count3;
7737 V2 = N21 + (T % count2) * STEP2;
7738 T = T / count2;
7739 V1 = N11 + T * STEP1;
bc7bff74 7740 if this loop doesn't have an inner loop construct combined with it.
7741 If it does have an inner loop construct combined with it and the
7742 iteration count isn't known constant, store values from counts array
7743 into its _looptemp_ temporaries instead. */
3d483a94 7744
7745static void
7746expand_omp_for_init_vars (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
42acab1c 7747 tree *counts, gimple *inner_stmt, tree startvar)
3d483a94 7748{
7749 int i;
bc7bff74 7750 if (gimple_omp_for_combined_p (fd->for_stmt))
7751 {
7752 /* If fd->loop.n2 is constant, then no propagation of the counts
7753 is needed, they are constant. */
7754 if (TREE_CODE (fd->loop.n2) == INTEGER_CST)
7755 return;
7756
43895be5 7757 tree clauses = gimple_code (inner_stmt) != GIMPLE_OMP_FOR
7758 ? gimple_omp_taskreg_clauses (inner_stmt)
bc7bff74 7759 : gimple_omp_for_clauses (inner_stmt);
7760 /* First two _looptemp_ clauses are for istart/iend, counts[0]
7761 isn't supposed to be handled, as the inner loop doesn't
7762 use it. */
7763 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
7764 gcc_assert (innerc);
7765 for (i = 0; i < fd->collapse; i++)
7766 {
7767 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7768 OMP_CLAUSE__LOOPTEMP_);
7769 gcc_assert (innerc);
7770 if (i)
7771 {
7772 tree tem = OMP_CLAUSE_DECL (innerc);
7773 tree t = fold_convert (TREE_TYPE (tem), counts[i]);
7774 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
7775 false, GSI_CONTINUE_LINKING);
1a91d914 7776 gassign *stmt = gimple_build_assign (tem, t);
bc7bff74 7777 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7778 }
7779 }
7780 return;
7781 }
7782
3d483a94 7783 tree type = TREE_TYPE (fd->loop.v);
7784 tree tem = create_tmp_reg (type, ".tem");
1a91d914 7785 gassign *stmt = gimple_build_assign (tem, startvar);
3d483a94 7786 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7787
7788 for (i = fd->collapse - 1; i >= 0; i--)
7789 {
7790 tree vtype = TREE_TYPE (fd->loops[i].v), itype, t;
7791 itype = vtype;
7792 if (POINTER_TYPE_P (vtype))
7793 itype = signed_type_for (vtype);
7794 if (i != 0)
7795 t = fold_build2 (TRUNC_MOD_EXPR, type, tem, counts[i]);
7796 else
7797 t = tem;
7798 t = fold_convert (itype, t);
7799 t = fold_build2 (MULT_EXPR, itype, t,
7800 fold_convert (itype, fd->loops[i].step));
7801 if (POINTER_TYPE_P (vtype))
7802 t = fold_build_pointer_plus (fd->loops[i].n1, t);
7803 else
7804 t = fold_build2 (PLUS_EXPR, itype, fd->loops[i].n1, t);
7805 t = force_gimple_operand_gsi (gsi, t,
7806 DECL_P (fd->loops[i].v)
7807 && TREE_ADDRESSABLE (fd->loops[i].v),
7808 NULL_TREE, false,
7809 GSI_CONTINUE_LINKING);
7810 stmt = gimple_build_assign (fd->loops[i].v, t);
7811 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7812 if (i != 0)
7813 {
7814 t = fold_build2 (TRUNC_DIV_EXPR, type, tem, counts[i]);
7815 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
7816 false, GSI_CONTINUE_LINKING);
7817 stmt = gimple_build_assign (tem, t);
7818 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7819 }
7820 }
7821}
7822
7823
7824/* Helper function for expand_omp_for_*. Generate code like:
7825 L10:
7826 V3 += STEP3;
7827 if (V3 cond3 N32) goto BODY_BB; else goto L11;
7828 L11:
7829 V3 = N31;
7830 V2 += STEP2;
7831 if (V2 cond2 N22) goto BODY_BB; else goto L12;
7832 L12:
7833 V2 = N21;
7834 V1 += STEP1;
7835 goto BODY_BB; */
7836
7837static basic_block
7838extract_omp_for_update_vars (struct omp_for_data *fd, basic_block cont_bb,
7839 basic_block body_bb)
7840{
7841 basic_block last_bb, bb, collapse_bb = NULL;
7842 int i;
7843 gimple_stmt_iterator gsi;
7844 edge e;
7845 tree t;
42acab1c 7846 gimple *stmt;
3d483a94 7847
7848 last_bb = cont_bb;
7849 for (i = fd->collapse - 1; i >= 0; i--)
7850 {
7851 tree vtype = TREE_TYPE (fd->loops[i].v);
7852
7853 bb = create_empty_bb (last_bb);
b3083327 7854 add_bb_to_loop (bb, last_bb->loop_father);
3d483a94 7855 gsi = gsi_start_bb (bb);
7856
7857 if (i < fd->collapse - 1)
7858 {
7859 e = make_edge (last_bb, bb, EDGE_FALSE_VALUE);
7860 e->probability = REG_BR_PROB_BASE / 8;
7861
7862 t = fd->loops[i + 1].n1;
7863 t = force_gimple_operand_gsi (&gsi, t,
7864 DECL_P (fd->loops[i + 1].v)
7865 && TREE_ADDRESSABLE (fd->loops[i
7866 + 1].v),
7867 NULL_TREE, false,
7868 GSI_CONTINUE_LINKING);
7869 stmt = gimple_build_assign (fd->loops[i + 1].v, t);
7870 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7871 }
7872 else
7873 collapse_bb = bb;
7874
7875 set_immediate_dominator (CDI_DOMINATORS, bb, last_bb);
7876
7877 if (POINTER_TYPE_P (vtype))
7878 t = fold_build_pointer_plus (fd->loops[i].v, fd->loops[i].step);
7879 else
7880 t = fold_build2 (PLUS_EXPR, vtype, fd->loops[i].v, fd->loops[i].step);
7881 t = force_gimple_operand_gsi (&gsi, t,
7882 DECL_P (fd->loops[i].v)
7883 && TREE_ADDRESSABLE (fd->loops[i].v),
7884 NULL_TREE, false, GSI_CONTINUE_LINKING);
7885 stmt = gimple_build_assign (fd->loops[i].v, t);
7886 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7887
7888 if (i > 0)
7889 {
7890 t = fd->loops[i].n2;
7891 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7892 false, GSI_CONTINUE_LINKING);
7893 tree v = fd->loops[i].v;
7894 if (DECL_P (v) && TREE_ADDRESSABLE (v))
7895 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
7896 false, GSI_CONTINUE_LINKING);
7897 t = fold_build2 (fd->loops[i].cond_code, boolean_type_node, v, t);
7898 stmt = gimple_build_cond_empty (t);
7899 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7900 e = make_edge (bb, body_bb, EDGE_TRUE_VALUE);
7901 e->probability = REG_BR_PROB_BASE * 7 / 8;
7902 }
7903 else
7904 make_edge (bb, body_bb, EDGE_FALLTHRU);
7905 last_bb = bb;
7906 }
7907
7908 return collapse_bb;
7909}
7910
7911
43895be5 7912/* Expand #pragma omp ordered depend(source). */
1e8e9920 7913
43895be5 7914static void
7915expand_omp_ordered_source (gimple_stmt_iterator *gsi, struct omp_for_data *fd,
7916 tree *counts, location_t loc)
7917{
7918 enum built_in_function source_ix
7919 = fd->iter_type == long_integer_type_node
7920 ? BUILT_IN_GOMP_DOACROSS_POST : BUILT_IN_GOMP_DOACROSS_ULL_POST;
7921 gimple *g
7922 = gimple_build_call (builtin_decl_explicit (source_ix), 1,
7923 build_fold_addr_expr (counts[fd->ordered]));
7924 gimple_set_location (g, loc);
7925 gsi_insert_before (gsi, g, GSI_SAME_STMT);
7926}
1e8e9920 7927
43895be5 7928/* Expand a single depend from #pragma omp ordered depend(sink:...). */
1e8e9920 7929
43895be5 7930static void
7931expand_omp_ordered_sink (gimple_stmt_iterator *gsi, struct omp_for_data *fd,
7932 tree *counts, tree c, location_t loc)
7933{
7934 auto_vec<tree, 10> args;
7935 enum built_in_function sink_ix
7936 = fd->iter_type == long_integer_type_node
7937 ? BUILT_IN_GOMP_DOACROSS_WAIT : BUILT_IN_GOMP_DOACROSS_ULL_WAIT;
7938 tree t, off, coff = NULL_TREE, deps = OMP_CLAUSE_DECL (c), cond = NULL_TREE;
7939 int i;
7940 gimple_stmt_iterator gsi2 = *gsi;
7941 bool warned_step = false;
fd6481cf 7942
43895be5 7943 for (i = 0; i < fd->ordered; i++)
7944 {
7945 off = TREE_PURPOSE (deps);
7946 if (!integer_zerop (off))
7947 {
7948 gcc_assert (fd->loops[i].cond_code == LT_EXPR
7949 || fd->loops[i].cond_code == GT_EXPR);
7950 bool forward = fd->loops[i].cond_code == LT_EXPR;
7951 if (forward ^ OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
7952 warning_at (loc, 0, "%<depend(sink)%> clause waiting for "
7953 "lexically later iteration");
7954 break;
7955 }
7956 deps = TREE_CHAIN (deps);
7957 }
7958 /* If all offsets corresponding to the collapsed loops are zero,
7959 this depend clause can be ignored. FIXME: but there is still a
7960 flush needed. We need to emit one __sync_synchronize () for it
7961 though (perhaps conditionally)? Solve this together with the
7962 conservative dependence folding optimization.
7963 if (i >= fd->collapse)
7964 return; */
fd6481cf 7965
43895be5 7966 deps = OMP_CLAUSE_DECL (c);
7967 gsi_prev (&gsi2);
7968 edge e1 = split_block (gsi_bb (gsi2), gsi_stmt (gsi2));
7969 edge e2 = split_block_after_labels (e1->dest);
fd6481cf 7970
43895be5 7971 *gsi = gsi_after_labels (e1->dest);
7972 for (i = 0; i < fd->ordered; i++)
7973 {
7974 tree itype = TREE_TYPE (fd->loops[i].v);
7975 if (POINTER_TYPE_P (itype))
7976 itype = sizetype;
7977 if (i)
7978 deps = TREE_CHAIN (deps);
7979 off = TREE_PURPOSE (deps);
7980 tree s = fold_convert_loc (loc, itype, fd->loops[i].step);
7981
7982 if (integer_zerop (off))
7983 t = boolean_true_node;
7984 else
7985 {
7986 tree a;
7987 tree co = fold_convert_loc (loc, itype, off);
7988 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
7989 {
7990 if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
7991 co = fold_build1_loc (loc, NEGATE_EXPR, itype, co);
7992 a = fold_build2_loc (loc, POINTER_PLUS_EXPR,
7993 TREE_TYPE (fd->loops[i].v), fd->loops[i].v,
7994 co);
7995 }
7996 else if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
7997 a = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (fd->loops[i].v),
7998 fd->loops[i].v, co);
7999 else
8000 a = fold_build2_loc (loc, PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
8001 fd->loops[i].v, co);
8002 if (fd->loops[i].cond_code == LT_EXPR)
8003 {
8004 if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
8005 t = fold_build2_loc (loc, GE_EXPR, boolean_type_node, a,
8006 fd->loops[i].n1);
8007 else
8008 t = fold_build2_loc (loc, LT_EXPR, boolean_type_node, a,
8009 fd->loops[i].n2);
8010 }
8011 else if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
8012 t = fold_build2_loc (loc, GT_EXPR, boolean_type_node, a,
8013 fd->loops[i].n2);
8014 else
8015 t = fold_build2_loc (loc, LE_EXPR, boolean_type_node, a,
8016 fd->loops[i].n1);
8017 }
8018 if (cond)
8019 cond = fold_build2_loc (loc, BIT_AND_EXPR, boolean_type_node, cond, t);
8020 else
8021 cond = t;
8022
8023 off = fold_convert_loc (loc, itype, off);
8024
8025 if (fd->loops[i].cond_code == LT_EXPR
8026 ? !integer_onep (fd->loops[i].step)
8027 : !integer_minus_onep (fd->loops[i].step))
8028 {
8029 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
8030 t = fold_build2_loc (loc, TRUNC_MOD_EXPR, itype, off,
8031 fold_build1_loc (loc, NEGATE_EXPR, itype,
8032 s));
8033 else
8034 t = fold_build2_loc (loc, TRUNC_MOD_EXPR, itype, off, s);
8035 t = fold_build2_loc (loc, EQ_EXPR, boolean_type_node, t,
8036 build_int_cst (itype, 0));
8037 if (integer_zerop (t) && !warned_step)
8038 {
8039 warning_at (loc, 0, "%<depend(sink)%> refers to iteration never "
8040 "in the iteration space");
8041 warned_step = true;
8042 }
8043 cond = fold_build2_loc (loc, BIT_AND_EXPR, boolean_type_node,
8044 cond, t);
8045 }
8046
8047 if (i <= fd->collapse - 1 && fd->collapse > 1)
8048 t = fd->loop.v;
8049 else if (counts[i])
8050 t = counts[i];
8051 else
8052 {
8053 t = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (fd->loops[i].v),
8054 fd->loops[i].v, fd->loops[i].n1);
8055 t = fold_convert_loc (loc, fd->iter_type, t);
8056 }
8057 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
8058 off = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, off,
8059 fold_build1_loc (loc, NEGATE_EXPR, itype,
8060 s));
8061 else
8062 off = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, off, s);
8063 if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
8064 off = fold_build1_loc (loc, NEGATE_EXPR, itype, off);
8065 off = fold_convert_loc (loc, fd->iter_type, off);
8066 if (i <= fd->collapse - 1 && fd->collapse > 1)
8067 {
8068 if (i)
8069 off = fold_build2_loc (loc, PLUS_EXPR, fd->iter_type, coff,
8070 off);
8071 if (i < fd->collapse - 1)
8072 {
8073 coff = fold_build2_loc (loc, MULT_EXPR, fd->iter_type, off,
8074 counts[i]);
8075 continue;
8076 }
8077 }
8078 off = unshare_expr (off);
8079 t = fold_build2_loc (loc, PLUS_EXPR, fd->iter_type, t, off);
8080 t = force_gimple_operand_gsi (gsi, t, true, NULL_TREE,
8081 true, GSI_SAME_STMT);
8082 args.safe_push (t);
8083 }
8084 gimple *g = gimple_build_call_vec (builtin_decl_explicit (sink_ix), args);
8085 gimple_set_location (g, loc);
8086 gsi_insert_before (gsi, g, GSI_SAME_STMT);
8087
8088 *gsi = gsi_last_bb (e1->src);
8089 cond = unshare_expr (cond);
8090 cond = force_gimple_operand_gsi (gsi, cond, true, NULL_TREE, false,
8091 GSI_CONTINUE_LINKING);
8092 gsi_insert_after (gsi, gimple_build_cond_empty (cond), GSI_NEW_STMT);
8093 edge e3 = make_edge (e1->src, e2->dest, EDGE_FALSE_VALUE);
8094 e3->probability = REG_BR_PROB_BASE / 8;
8095 e1->probability = REG_BR_PROB_BASE - e3->probability;
8096 e1->flags = EDGE_TRUE_VALUE;
8097 set_immediate_dominator (CDI_DOMINATORS, e2->dest, e1->src);
8098
8099 *gsi = gsi_after_labels (e2->dest);
8100}
8101
8102/* Expand all #pragma omp ordered depend(source) and
8103 #pragma omp ordered depend(sink:...) constructs in the current
8104 #pragma omp for ordered(n) region. */
8105
8106static void
8107expand_omp_ordered_source_sink (struct omp_region *region,
8108 struct omp_for_data *fd, tree *counts,
8109 basic_block cont_bb)
8110{
8111 struct omp_region *inner;
8112 int i;
8113 for (i = fd->collapse - 1; i < fd->ordered; i++)
8114 if (i == fd->collapse - 1 && fd->collapse > 1)
8115 counts[i] = NULL_TREE;
8116 else if (i >= fd->collapse && !cont_bb)
8117 counts[i] = build_zero_cst (fd->iter_type);
8118 else if (!POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v))
8119 && integer_onep (fd->loops[i].step))
8120 counts[i] = NULL_TREE;
8121 else
8122 counts[i] = create_tmp_var (fd->iter_type, ".orditer");
8123 tree atype
8124 = build_array_type_nelts (fd->iter_type, fd->ordered - fd->collapse + 1);
8125 counts[fd->ordered] = create_tmp_var (atype, ".orditera");
8126 TREE_ADDRESSABLE (counts[fd->ordered]) = 1;
8127
8128 for (inner = region->inner; inner; inner = inner->next)
8129 if (inner->type == GIMPLE_OMP_ORDERED)
8130 {
8131 gomp_ordered *ord_stmt = inner->ord_stmt;
8132 gimple_stmt_iterator gsi = gsi_for_stmt (ord_stmt);
8133 location_t loc = gimple_location (ord_stmt);
8134 tree c;
8135 for (c = gimple_omp_ordered_clauses (ord_stmt);
8136 c; c = OMP_CLAUSE_CHAIN (c))
8137 if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE)
8138 break;
8139 if (c)
8140 expand_omp_ordered_source (&gsi, fd, counts, loc);
8141 for (c = gimple_omp_ordered_clauses (ord_stmt);
8142 c; c = OMP_CLAUSE_CHAIN (c))
8143 if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK)
8144 expand_omp_ordered_sink (&gsi, fd, counts, c, loc);
8145 gsi_remove (&gsi, true);
8146 }
8147}
8148
8149/* Wrap the body into fd->ordered - fd->collapse loops that aren't
8150 collapsed. */
8151
8152static basic_block
8153expand_omp_for_ordered_loops (struct omp_for_data *fd, tree *counts,
8154 basic_block cont_bb, basic_block body_bb,
8155 bool ordered_lastprivate)
8156{
8157 if (fd->ordered == fd->collapse)
8158 return cont_bb;
8159
8160 if (!cont_bb)
8161 {
8162 gimple_stmt_iterator gsi = gsi_after_labels (body_bb);
8163 for (int i = fd->collapse; i < fd->ordered; i++)
8164 {
8165 tree type = TREE_TYPE (fd->loops[i].v);
8166 tree n1 = fold_convert (type, fd->loops[i].n1);
8167 expand_omp_build_assign (&gsi, fd->loops[i].v, n1);
8168 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8169 size_int (i - fd->collapse + 1),
8170 NULL_TREE, NULL_TREE);
8171 expand_omp_build_assign (&gsi, aref, build_zero_cst (fd->iter_type));
8172 }
8173 return NULL;
8174 }
8175
8176 for (int i = fd->ordered - 1; i >= fd->collapse; i--)
8177 {
8178 tree t, type = TREE_TYPE (fd->loops[i].v);
8179 gimple_stmt_iterator gsi = gsi_after_labels (body_bb);
8180 expand_omp_build_assign (&gsi, fd->loops[i].v,
8181 fold_convert (type, fd->loops[i].n1));
8182 if (counts[i])
8183 expand_omp_build_assign (&gsi, counts[i],
8184 build_zero_cst (fd->iter_type));
8185 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8186 size_int (i - fd->collapse + 1),
8187 NULL_TREE, NULL_TREE);
8188 expand_omp_build_assign (&gsi, aref, build_zero_cst (fd->iter_type));
8189 if (!gsi_end_p (gsi))
8190 gsi_prev (&gsi);
8191 else
8192 gsi = gsi_last_bb (body_bb);
8193 edge e1 = split_block (body_bb, gsi_stmt (gsi));
8194 basic_block new_body = e1->dest;
8195 if (body_bb == cont_bb)
8196 cont_bb = new_body;
8197 edge e2 = NULL;
8198 basic_block new_header;
8199 if (EDGE_COUNT (cont_bb->preds) > 0)
8200 {
8201 gsi = gsi_last_bb (cont_bb);
8202 if (POINTER_TYPE_P (type))
8203 t = fold_build_pointer_plus (fd->loops[i].v,
8204 fold_convert (sizetype,
8205 fd->loops[i].step));
8206 else
8207 t = fold_build2 (PLUS_EXPR, type, fd->loops[i].v,
8208 fold_convert (type, fd->loops[i].step));
8209 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
8210 if (counts[i])
8211 {
8212 t = fold_build2 (PLUS_EXPR, fd->iter_type, counts[i],
8213 build_int_cst (fd->iter_type, 1));
8214 expand_omp_build_assign (&gsi, counts[i], t);
8215 t = counts[i];
8216 }
8217 else
8218 {
8219 t = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->loops[i].v),
8220 fd->loops[i].v, fd->loops[i].n1);
8221 t = fold_convert (fd->iter_type, t);
8222 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8223 true, GSI_SAME_STMT);
8224 }
8225 aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8226 size_int (i - fd->collapse + 1),
8227 NULL_TREE, NULL_TREE);
8228 expand_omp_build_assign (&gsi, aref, t);
8229 gsi_prev (&gsi);
8230 e2 = split_block (cont_bb, gsi_stmt (gsi));
8231 new_header = e2->dest;
8232 }
8233 else
8234 new_header = cont_bb;
8235 gsi = gsi_after_labels (new_header);
8236 tree v = force_gimple_operand_gsi (&gsi, fd->loops[i].v, true, NULL_TREE,
8237 true, GSI_SAME_STMT);
8238 tree n2
8239 = force_gimple_operand_gsi (&gsi, fold_convert (type, fd->loops[i].n2),
8240 true, NULL_TREE, true, GSI_SAME_STMT);
8241 t = build2 (fd->loops[i].cond_code, boolean_type_node, v, n2);
8242 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_NEW_STMT);
8243 edge e3 = split_block (new_header, gsi_stmt (gsi));
8244 cont_bb = e3->dest;
8245 remove_edge (e1);
8246 make_edge (body_bb, new_header, EDGE_FALLTHRU);
8247 e3->flags = EDGE_FALSE_VALUE;
8248 e3->probability = REG_BR_PROB_BASE / 8;
8249 e1 = make_edge (new_header, new_body, EDGE_TRUE_VALUE);
8250 e1->probability = REG_BR_PROB_BASE - e3->probability;
8251
8252 set_immediate_dominator (CDI_DOMINATORS, new_header, body_bb);
8253 set_immediate_dominator (CDI_DOMINATORS, new_body, new_header);
8254
8255 if (e2)
8256 {
8257 struct loop *loop = alloc_loop ();
8258 loop->header = new_header;
8259 loop->latch = e2->src;
8260 add_loop (loop, body_bb->loop_father);
8261 }
8262 }
8263
8264 /* If there are any lastprivate clauses and it is possible some loops
8265 might have zero iterations, ensure all the decls are initialized,
8266 otherwise we could crash evaluating C++ class iterators with lastprivate
8267 clauses. */
8268 bool need_inits = false;
8269 for (int i = fd->collapse; ordered_lastprivate && i < fd->ordered; i++)
8270 if (need_inits)
8271 {
8272 tree type = TREE_TYPE (fd->loops[i].v);
8273 gimple_stmt_iterator gsi = gsi_after_labels (body_bb);
8274 expand_omp_build_assign (&gsi, fd->loops[i].v,
8275 fold_convert (type, fd->loops[i].n1));
8276 }
8277 else
8278 {
8279 tree type = TREE_TYPE (fd->loops[i].v);
8280 tree this_cond = fold_build2 (fd->loops[i].cond_code,
8281 boolean_type_node,
8282 fold_convert (type, fd->loops[i].n1),
8283 fold_convert (type, fd->loops[i].n2));
8284 if (!integer_onep (this_cond))
8285 need_inits = true;
8286 }
8287
8288 return cont_bb;
8289}
8290
8291
8292/* A subroutine of expand_omp_for. Generate code for a parallel
8293 loop with any schedule. Given parameters:
8294
8295 for (V = N1; V cond N2; V += STEP) BODY;
8296
8297 where COND is "<" or ">", we generate pseudocode
8298
8299 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
8300 if (more) goto L0; else goto L3;
8301 L0:
8302 V = istart0;
8303 iend = iend0;
8304 L1:
8305 BODY;
8306 V += STEP;
8307 if (V cond iend) goto L1; else goto L2;
8308 L2:
8309 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
8310 L3:
8311
8312 If this is a combined omp parallel loop, instead of the call to
8313 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
8314 If this is gimple_omp_for_combined_p loop, then instead of assigning
8315 V and iend in L0 we assign the first two _looptemp_ clause decls of the
8316 inner GIMPLE_OMP_FOR and V += STEP; and
8317 if (V cond iend) goto L1; else goto L2; are removed.
8318
8319 For collapsed loops, given parameters:
8320 collapse(3)
8321 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
8322 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
8323 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
8324 BODY;
8325
8326 we generate pseudocode
8327
8328 if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
8329 if (cond3 is <)
8330 adj = STEP3 - 1;
8331 else
8332 adj = STEP3 + 1;
8333 count3 = (adj + N32 - N31) / STEP3;
8334 if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
8335 if (cond2 is <)
8336 adj = STEP2 - 1;
8337 else
8338 adj = STEP2 + 1;
fd6481cf 8339 count2 = (adj + N22 - N21) / STEP2;
8e6b4515 8340 if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
fd6481cf 8341 if (cond1 is <)
8342 adj = STEP1 - 1;
8343 else
8344 adj = STEP1 + 1;
8345 count1 = (adj + N12 - N11) / STEP1;
8346 count = count1 * count2 * count3;
8e6b4515 8347 goto Z1;
8348 Z0:
8349 count = 0;
8350 Z1:
fd6481cf 8351 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
8352 if (more) goto L0; else goto L3;
8353 L0:
8354 V = istart0;
8355 T = V;
8356 V3 = N31 + (T % count3) * STEP3;
8357 T = T / count3;
8358 V2 = N21 + (T % count2) * STEP2;
8359 T = T / count2;
8360 V1 = N11 + T * STEP1;
8361 iend = iend0;
8362 L1:
8363 BODY;
8364 V += 1;
8365 if (V < iend) goto L10; else goto L2;
8366 L10:
8367 V3 += STEP3;
8368 if (V3 cond3 N32) goto L1; else goto L11;
8369 L11:
8370 V3 = N31;
8371 V2 += STEP2;
8372 if (V2 cond2 N22) goto L1; else goto L12;
8373 L12:
8374 V2 = N21;
8375 V1 += STEP1;
8376 goto L1;
8377 L2:
8378 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
8379 L3:
8380
8381 */
1e8e9920 8382
61e47ac8 8383static void
773c5ba7 8384expand_omp_for_generic (struct omp_region *region,
8385 struct omp_for_data *fd,
1e8e9920 8386 enum built_in_function start_fn,
bc7bff74 8387 enum built_in_function next_fn,
42acab1c 8388 gimple *inner_stmt)
1e8e9920 8389{
75a70cf9 8390 tree type, istart0, iend0, iend;
fd6481cf 8391 tree t, vmain, vback, bias = NULL_TREE;
8392 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, collapse_bb;
03ed154b 8393 basic_block l2_bb = NULL, l3_bb = NULL;
75a70cf9 8394 gimple_stmt_iterator gsi;
1a91d914 8395 gassign *assign_stmt;
773c5ba7 8396 bool in_combined_parallel = is_combined_parallel (region);
ac6e3339 8397 bool broken_loop = region->cont == NULL;
79acaae1 8398 edge e, ne;
fd6481cf 8399 tree *counts = NULL;
8400 int i;
43895be5 8401 bool ordered_lastprivate = false;
ac6e3339 8402
8403 gcc_assert (!broken_loop || !in_combined_parallel);
fd6481cf 8404 gcc_assert (fd->iter_type == long_integer_type_node
8405 || !in_combined_parallel);
1e8e9920 8406
61e47ac8 8407 entry_bb = region->entry;
03ed154b 8408 cont_bb = region->cont;
fd6481cf 8409 collapse_bb = NULL;
ac6e3339 8410 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
8411 gcc_assert (broken_loop
8412 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
8413 l0_bb = split_edge (FALLTHRU_EDGE (entry_bb));
8414 l1_bb = single_succ (l0_bb);
8415 if (!broken_loop)
03ed154b 8416 {
8417 l2_bb = create_empty_bb (cont_bb);
95cd5725 8418 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb
8419 || (single_succ_edge (BRANCH_EDGE (cont_bb)->dest)->dest
8420 == l1_bb));
ac6e3339 8421 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
03ed154b 8422 }
ac6e3339 8423 else
8424 l2_bb = NULL;
8425 l3_bb = BRANCH_EDGE (entry_bb)->dest;
8426 exit_bb = region->exit;
773c5ba7 8427
75a70cf9 8428 gsi = gsi_last_bb (entry_bb);
fd6481cf 8429
75a70cf9 8430 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
43895be5 8431 if (fd->ordered
8432 && find_omp_clause (gimple_omp_for_clauses (gsi_stmt (gsi)),
8433 OMP_CLAUSE_LASTPRIVATE))
8434 ordered_lastprivate = false;
8435 if (fd->collapse > 1 || fd->ordered)
fd6481cf 8436 {
43895be5 8437 int first_zero_iter1 = -1, first_zero_iter2 = -1;
8438 basic_block zero_iter1_bb = NULL, zero_iter2_bb = NULL, l2_dom_bb = NULL;
8e6b4515 8439
43895be5 8440 counts = XALLOCAVEC (tree, fd->ordered ? fd->ordered + 1 : fd->collapse);
3d483a94 8441 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
43895be5 8442 zero_iter1_bb, first_zero_iter1,
8443 zero_iter2_bb, first_zero_iter2, l2_dom_bb);
fd6481cf 8444
43895be5 8445 if (zero_iter1_bb)
8e6b4515 8446 {
8447 /* Some counts[i] vars might be uninitialized if
8448 some loop has zero iterations. But the body shouldn't
8449 be executed in that case, so just avoid uninit warnings. */
43895be5 8450 for (i = first_zero_iter1;
8451 i < (fd->ordered ? fd->ordered : fd->collapse); i++)
8e6b4515 8452 if (SSA_VAR_P (counts[i]))
8453 TREE_NO_WARNING (counts[i]) = 1;
8454 gsi_prev (&gsi);
8455 e = split_block (entry_bb, gsi_stmt (gsi));
8456 entry_bb = e->dest;
43895be5 8457 make_edge (zero_iter1_bb, entry_bb, EDGE_FALLTHRU);
8e6b4515 8458 gsi = gsi_last_bb (entry_bb);
8459 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
8460 get_immediate_dominator (CDI_DOMINATORS,
43895be5 8461 zero_iter1_bb));
8462 }
8463 if (zero_iter2_bb)
8464 {
8465 /* Some counts[i] vars might be uninitialized if
8466 some loop has zero iterations. But the body shouldn't
8467 be executed in that case, so just avoid uninit warnings. */
8468 for (i = first_zero_iter2; i < fd->ordered; i++)
8469 if (SSA_VAR_P (counts[i]))
8470 TREE_NO_WARNING (counts[i]) = 1;
8471 if (zero_iter1_bb)
8472 make_edge (zero_iter2_bb, entry_bb, EDGE_FALLTHRU);
8473 else
8474 {
8475 gsi_prev (&gsi);
8476 e = split_block (entry_bb, gsi_stmt (gsi));
8477 entry_bb = e->dest;
8478 make_edge (zero_iter2_bb, entry_bb, EDGE_FALLTHRU);
8479 gsi = gsi_last_bb (entry_bb);
8480 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
8481 get_immediate_dominator
8482 (CDI_DOMINATORS, zero_iter2_bb));
8483 }
8484 }
8485 if (fd->collapse == 1)
8486 {
8487 counts[0] = fd->loop.n2;
8488 fd->loop = fd->loops[0];
8489 }
8490 }
8491
8492 type = TREE_TYPE (fd->loop.v);
8493 istart0 = create_tmp_var (fd->iter_type, ".istart0");
8494 iend0 = create_tmp_var (fd->iter_type, ".iend0");
8495 TREE_ADDRESSABLE (istart0) = 1;
8496 TREE_ADDRESSABLE (iend0) = 1;
8497
8498 /* See if we need to bias by LLONG_MIN. */
8499 if (fd->iter_type == long_long_unsigned_type_node
8500 && TREE_CODE (type) == INTEGER_TYPE
8501 && !TYPE_UNSIGNED (type)
8502 && fd->ordered == 0)
8503 {
8504 tree n1, n2;
8505
8506 if (fd->loop.cond_code == LT_EXPR)
8507 {
8508 n1 = fd->loop.n1;
8509 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
8e6b4515 8510 }
43895be5 8511 else
8512 {
8513 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
8514 n2 = fd->loop.n1;
8515 }
8516 if (TREE_CODE (n1) != INTEGER_CST
8517 || TREE_CODE (n2) != INTEGER_CST
8518 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
8519 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
fd6481cf 8520 }
43895be5 8521
8522 gimple_stmt_iterator gsif = gsi;
8523 gsi_prev (&gsif);
8524
8525 tree arr = NULL_TREE;
79acaae1 8526 if (in_combined_parallel)
8527 {
43895be5 8528 gcc_assert (fd->ordered == 0);
79acaae1 8529 /* In a combined parallel loop, emit a call to
8530 GOMP_loop_foo_next. */
b9a16870 8531 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
79acaae1 8532 build_fold_addr_expr (istart0),
8533 build_fold_addr_expr (iend0));
8534 }
8535 else
1e8e9920 8536 {
c2f47e15 8537 tree t0, t1, t2, t3, t4;
773c5ba7 8538 /* If this is not a combined parallel loop, emit a call to
8539 GOMP_loop_foo_start in ENTRY_BB. */
c2f47e15 8540 t4 = build_fold_addr_expr (iend0);
8541 t3 = build_fold_addr_expr (istart0);
43895be5 8542 if (fd->ordered)
c799f233 8543 {
43895be5 8544 t0 = build_int_cst (unsigned_type_node,
8545 fd->ordered - fd->collapse + 1);
8546 arr = create_tmp_var (build_array_type_nelts (fd->iter_type,
8547 fd->ordered
8548 - fd->collapse + 1),
8549 ".omp_counts");
8550 DECL_NAMELESS (arr) = 1;
8551 TREE_ADDRESSABLE (arr) = 1;
8552 TREE_STATIC (arr) = 1;
8553 vec<constructor_elt, va_gc> *v;
8554 vec_alloc (v, fd->ordered - fd->collapse + 1);
8555 int idx;
8556
8557 for (idx = 0; idx < fd->ordered - fd->collapse + 1; idx++)
8558 {
8559 tree c;
8560 if (idx == 0 && fd->collapse > 1)
8561 c = fd->loop.n2;
8562 else
8563 c = counts[idx + fd->collapse - 1];
8564 tree purpose = size_int (idx);
8565 CONSTRUCTOR_APPEND_ELT (v, purpose, c);
8566 if (TREE_CODE (c) != INTEGER_CST)
8567 TREE_STATIC (arr) = 0;
8568 }
8569
8570 DECL_INITIAL (arr) = build_constructor (TREE_TYPE (arr), v);
8571 if (!TREE_STATIC (arr))
8572 force_gimple_operand_gsi (&gsi, build1 (DECL_EXPR,
8573 void_type_node, arr),
8574 true, NULL_TREE, true, GSI_SAME_STMT);
8575 t1 = build_fold_addr_expr (arr);
8576 t2 = NULL_TREE;
c799f233 8577 }
8578 else
8579 {
43895be5 8580 t2 = fold_convert (fd->iter_type, fd->loop.step);
8581 t1 = fd->loop.n2;
8582 t0 = fd->loop.n1;
8583 if (gimple_omp_for_combined_into_p (fd->for_stmt))
8584 {
8585 tree innerc
8586 = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
8587 OMP_CLAUSE__LOOPTEMP_);
8588 gcc_assert (innerc);
8589 t0 = OMP_CLAUSE_DECL (innerc);
8590 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
8591 OMP_CLAUSE__LOOPTEMP_);
8592 gcc_assert (innerc);
8593 t1 = OMP_CLAUSE_DECL (innerc);
8594 }
8595 if (POINTER_TYPE_P (TREE_TYPE (t0))
8596 && TYPE_PRECISION (TREE_TYPE (t0))
8597 != TYPE_PRECISION (fd->iter_type))
8598 {
8599 /* Avoid casting pointers to integer of a different size. */
8600 tree itype = signed_type_for (type);
8601 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
8602 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
8603 }
8604 else
8605 {
8606 t1 = fold_convert (fd->iter_type, t1);
8607 t0 = fold_convert (fd->iter_type, t0);
8608 }
8609 if (bias)
8610 {
8611 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
8612 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
8613 }
fd6481cf 8614 }
43895be5 8615 if (fd->iter_type == long_integer_type_node || fd->ordered)
fd6481cf 8616 {
8617 if (fd->chunk_size)
8618 {
8619 t = fold_convert (fd->iter_type, fd->chunk_size);
43895be5 8620 t = omp_adjust_chunk_size (t, fd->simd_schedule);
8621 if (fd->ordered)
8622 t = build_call_expr (builtin_decl_explicit (start_fn),
8623 5, t0, t1, t, t3, t4);
8624 else
8625 t = build_call_expr (builtin_decl_explicit (start_fn),
8626 6, t0, t1, t2, t, t3, t4);
fd6481cf 8627 }
43895be5 8628 else if (fd->ordered)
8629 t = build_call_expr (builtin_decl_explicit (start_fn),
8630 4, t0, t1, t3, t4);
fd6481cf 8631 else
b9a16870 8632 t = build_call_expr (builtin_decl_explicit (start_fn),
8633 5, t0, t1, t2, t3, t4);
1e8e9920 8634 }
c2f47e15 8635 else
fd6481cf 8636 {
8637 tree t5;
8638 tree c_bool_type;
b9a16870 8639 tree bfn_decl;
fd6481cf 8640
8641 /* The GOMP_loop_ull_*start functions have additional boolean
8642 argument, true for < loops and false for > loops.
8643 In Fortran, the C bool type can be different from
8644 boolean_type_node. */
b9a16870 8645 bfn_decl = builtin_decl_explicit (start_fn);
8646 c_bool_type = TREE_TYPE (TREE_TYPE (bfn_decl));
fd6481cf 8647 t5 = build_int_cst (c_bool_type,
8648 fd->loop.cond_code == LT_EXPR ? 1 : 0);
8649 if (fd->chunk_size)
8650 {
b9a16870 8651 tree bfn_decl = builtin_decl_explicit (start_fn);
fd6481cf 8652 t = fold_convert (fd->iter_type, fd->chunk_size);
43895be5 8653 t = omp_adjust_chunk_size (t, fd->simd_schedule);
b9a16870 8654 t = build_call_expr (bfn_decl, 7, t5, t0, t1, t2, t, t3, t4);
fd6481cf 8655 }
8656 else
b9a16870 8657 t = build_call_expr (builtin_decl_explicit (start_fn),
8658 6, t5, t0, t1, t2, t3, t4);
fd6481cf 8659 }
1e8e9920 8660 }
fd6481cf 8661 if (TREE_TYPE (t) != boolean_type_node)
8662 t = fold_build2 (NE_EXPR, boolean_type_node,
8663 t, build_int_cst (TREE_TYPE (t), 0));
75a70cf9 8664 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8665 true, GSI_SAME_STMT);
43895be5 8666 if (arr && !TREE_STATIC (arr))
8667 {
8668 tree clobber = build_constructor (TREE_TYPE (arr), NULL);
8669 TREE_THIS_VOLATILE (clobber) = 1;
8670 gsi_insert_before (&gsi, gimple_build_assign (arr, clobber),
8671 GSI_SAME_STMT);
8672 }
75a70cf9 8673 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
79acaae1 8674
75a70cf9 8675 /* Remove the GIMPLE_OMP_FOR statement. */
8676 gsi_remove (&gsi, true);
1e8e9920 8677
43895be5 8678 if (gsi_end_p (gsif))
8679 gsif = gsi_after_labels (gsi_bb (gsif));
8680 gsi_next (&gsif);
8681
773c5ba7 8682 /* Iteration setup for sequential loop goes in L0_BB. */
3d483a94 8683 tree startvar = fd->loop.v;
8684 tree endvar = NULL_TREE;
8685
bc7bff74 8686 if (gimple_omp_for_combined_p (fd->for_stmt))
8687 {
8688 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_FOR
8689 && gimple_omp_for_kind (inner_stmt)
8690 == GF_OMP_FOR_KIND_SIMD);
8691 tree innerc = find_omp_clause (gimple_omp_for_clauses (inner_stmt),
8692 OMP_CLAUSE__LOOPTEMP_);
8693 gcc_assert (innerc);
8694 startvar = OMP_CLAUSE_DECL (innerc);
8695 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
8696 OMP_CLAUSE__LOOPTEMP_);
8697 gcc_assert (innerc);
8698 endvar = OMP_CLAUSE_DECL (innerc);
8699 }
8700
75a70cf9 8701 gsi = gsi_start_bb (l0_bb);
1efcacec 8702 t = istart0;
43895be5 8703 if (fd->ordered && fd->collapse == 1)
8704 t = fold_build2 (MULT_EXPR, fd->iter_type, t,
8705 fold_convert (fd->iter_type, fd->loop.step));
8706 else if (bias)
1efcacec 8707 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
43895be5 8708 if (fd->ordered && fd->collapse == 1)
8709 {
8710 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8711 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (startvar),
8712 fd->loop.n1, fold_convert (sizetype, t));
8713 else
8714 {
8715 t = fold_convert (TREE_TYPE (startvar), t);
8716 t = fold_build2 (PLUS_EXPR, TREE_TYPE (startvar),
8717 fd->loop.n1, t);
8718 }
8719 }
8720 else
8721 {
8722 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8723 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
8724 t = fold_convert (TREE_TYPE (startvar), t);
8725 }
4abecb72 8726 t = force_gimple_operand_gsi (&gsi, t,
3d483a94 8727 DECL_P (startvar)
8728 && TREE_ADDRESSABLE (startvar),
4abecb72 8729 NULL_TREE, false, GSI_CONTINUE_LINKING);
1a91d914 8730 assign_stmt = gimple_build_assign (startvar, t);
8731 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
1e8e9920 8732
1efcacec 8733 t = iend0;
43895be5 8734 if (fd->ordered && fd->collapse == 1)
8735 t = fold_build2 (MULT_EXPR, fd->iter_type, t,
8736 fold_convert (fd->iter_type, fd->loop.step));
8737 else if (bias)
1efcacec 8738 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
43895be5 8739 if (fd->ordered && fd->collapse == 1)
fd6481cf 8740 {
43895be5 8741 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8742 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (startvar),
8743 fd->loop.n1, fold_convert (sizetype, t));
8744 else
8745 {
8746 t = fold_convert (TREE_TYPE (startvar), t);
8747 t = fold_build2 (PLUS_EXPR, TREE_TYPE (startvar),
8748 fd->loop.n1, t);
8749 }
8750 }
8751 else
8752 {
8753 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8754 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
8755 t = fold_convert (TREE_TYPE (startvar), t);
8756 }
8757 iend = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8758 false, GSI_CONTINUE_LINKING);
8759 if (endvar)
8760 {
8761 assign_stmt = gimple_build_assign (endvar, iend);
1a91d914 8762 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
d44f2f7c 8763 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (iend)))
1a91d914 8764 assign_stmt = gimple_build_assign (fd->loop.v, iend);
d44f2f7c 8765 else
e9cf809e 8766 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, iend);
1a91d914 8767 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
fd6481cf 8768 }
43895be5 8769 /* Handle linear clause adjustments. */
8770 tree itercnt = NULL_TREE;
8771 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_FOR)
8772 for (tree c = gimple_omp_for_clauses (fd->for_stmt);
8773 c; c = OMP_CLAUSE_CHAIN (c))
8774 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
8775 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
8776 {
8777 tree d = OMP_CLAUSE_DECL (c);
8778 bool is_ref = is_reference (d);
8779 tree t = d, a, dest;
8780 if (is_ref)
8781 t = build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c), t);
8782 tree type = TREE_TYPE (t);
8783 if (POINTER_TYPE_P (type))
8784 type = sizetype;
8785 dest = unshare_expr (t);
8786 tree v = create_tmp_var (TREE_TYPE (t), NULL);
8787 expand_omp_build_assign (&gsif, v, t);
8788 if (itercnt == NULL_TREE)
8789 {
8790 itercnt = startvar;
8791 tree n1 = fd->loop.n1;
8792 if (POINTER_TYPE_P (TREE_TYPE (itercnt)))
8793 {
8794 itercnt
8795 = fold_convert (signed_type_for (TREE_TYPE (itercnt)),
8796 itercnt);
8797 n1 = fold_convert (TREE_TYPE (itercnt), n1);
8798 }
8799 itercnt = fold_build2 (MINUS_EXPR, TREE_TYPE (itercnt),
8800 itercnt, n1);
8801 itercnt = fold_build2 (EXACT_DIV_EXPR, TREE_TYPE (itercnt),
8802 itercnt, fd->loop.step);
8803 itercnt = force_gimple_operand_gsi (&gsi, itercnt, true,
8804 NULL_TREE, false,
8805 GSI_CONTINUE_LINKING);
8806 }
8807 a = fold_build2 (MULT_EXPR, type,
8808 fold_convert (type, itercnt),
8809 fold_convert (type, OMP_CLAUSE_LINEAR_STEP (c)));
8810 t = fold_build2 (type == TREE_TYPE (t) ? PLUS_EXPR
8811 : POINTER_PLUS_EXPR, TREE_TYPE (t), v, a);
8812 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8813 false, GSI_CONTINUE_LINKING);
8814 assign_stmt = gimple_build_assign (dest, t);
8815 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
8816 }
3d483a94 8817 if (fd->collapse > 1)
bc7bff74 8818 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
773c5ba7 8819
43895be5 8820 if (fd->ordered)
8821 {
8822 /* Until now, counts array contained number of iterations or
8823 variable containing it for ith loop. From now on, we need
8824 those counts only for collapsed loops, and only for the 2nd
8825 till the last collapsed one. Move those one element earlier,
8826 we'll use counts[fd->collapse - 1] for the first source/sink
8827 iteration counter and so on and counts[fd->ordered]
8828 as the array holding the current counter values for
8829 depend(source). */
8830 if (fd->collapse > 1)
8831 memmove (counts, counts + 1, (fd->collapse - 1) * sizeof (counts[0]));
8832 if (broken_loop)
8833 {
8834 int i;
8835 for (i = fd->collapse; i < fd->ordered; i++)
8836 {
8837 tree type = TREE_TYPE (fd->loops[i].v);
8838 tree this_cond
8839 = fold_build2 (fd->loops[i].cond_code, boolean_type_node,
8840 fold_convert (type, fd->loops[i].n1),
8841 fold_convert (type, fd->loops[i].n2));
8842 if (!integer_onep (this_cond))
8843 break;
8844 }
8845 if (i < fd->ordered)
8846 {
8847 cont_bb
8848 = create_empty_bb (EXIT_BLOCK_PTR_FOR_FN (cfun)->prev_bb);
8849 add_bb_to_loop (cont_bb, l1_bb->loop_father);
8850 gimple_stmt_iterator gsi = gsi_after_labels (cont_bb);
8851 gimple *g = gimple_build_omp_continue (fd->loop.v, fd->loop.v);
8852 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
8853 make_edge (cont_bb, l3_bb, EDGE_FALLTHRU);
8854 make_edge (cont_bb, l1_bb, 0);
8855 l2_bb = create_empty_bb (cont_bb);
8856 broken_loop = false;
8857 }
8858 }
8859 expand_omp_ordered_source_sink (region, fd, counts, cont_bb);
8860 cont_bb = expand_omp_for_ordered_loops (fd, counts, cont_bb, l1_bb,
8861 ordered_lastprivate);
8862 if (counts[fd->collapse - 1])
8863 {
8864 gcc_assert (fd->collapse == 1);
8865 gsi = gsi_last_bb (l0_bb);
8866 expand_omp_build_assign (&gsi, counts[fd->collapse - 1],
8867 istart0, true);
8868 gsi = gsi_last_bb (cont_bb);
8869 t = fold_build2 (PLUS_EXPR, fd->iter_type, counts[fd->collapse - 1],
8870 build_int_cst (fd->iter_type, 1));
8871 expand_omp_build_assign (&gsi, counts[fd->collapse - 1], t);
8872 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8873 size_zero_node, NULL_TREE, NULL_TREE);
8874 expand_omp_build_assign (&gsi, aref, counts[fd->collapse - 1]);
8875 t = counts[fd->collapse - 1];
8876 }
8877 else if (fd->collapse > 1)
8878 t = fd->loop.v;
8879 else
8880 {
8881 t = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->loops[0].v),
8882 fd->loops[0].v, fd->loops[0].n1);
8883 t = fold_convert (fd->iter_type, t);
8884 }
8885 gsi = gsi_last_bb (l0_bb);
8886 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8887 size_zero_node, NULL_TREE, NULL_TREE);
8888 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8889 false, GSI_CONTINUE_LINKING);
8890 expand_omp_build_assign (&gsi, aref, t, true);
8891 }
8892
ac6e3339 8893 if (!broken_loop)
03ed154b 8894 {
ac6e3339 8895 /* Code to control the increment and predicate for the sequential
8896 loop goes in the CONT_BB. */
75a70cf9 8897 gsi = gsi_last_bb (cont_bb);
1a91d914 8898 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
8899 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
8900 vmain = gimple_omp_continue_control_use (cont_stmt);
8901 vback = gimple_omp_continue_control_def (cont_stmt);
79acaae1 8902
bc7bff74 8903 if (!gimple_omp_for_combined_p (fd->for_stmt))
3d483a94 8904 {
8905 if (POINTER_TYPE_P (type))
8906 t = fold_build_pointer_plus (vmain, fd->loop.step);
8907 else
8908 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
8909 t = force_gimple_operand_gsi (&gsi, t,
8910 DECL_P (vback)
8911 && TREE_ADDRESSABLE (vback),
8912 NULL_TREE, true, GSI_SAME_STMT);
1a91d914 8913 assign_stmt = gimple_build_assign (vback, t);
8914 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
3d483a94 8915
43895be5 8916 if (fd->ordered && counts[fd->collapse - 1] == NULL_TREE)
8917 {
8918 if (fd->collapse > 1)
8919 t = fd->loop.v;
8920 else
8921 {
8922 t = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->loops[0].v),
8923 fd->loops[0].v, fd->loops[0].n1);
8924 t = fold_convert (fd->iter_type, t);
8925 }
8926 tree aref = build4 (ARRAY_REF, fd->iter_type,
8927 counts[fd->ordered], size_zero_node,
8928 NULL_TREE, NULL_TREE);
8929 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8930 true, GSI_SAME_STMT);
8931 expand_omp_build_assign (&gsi, aref, t);
8932 }
8933
3d483a94 8934 t = build2 (fd->loop.cond_code, boolean_type_node,
8935 DECL_P (vback) && TREE_ADDRESSABLE (vback) ? t : vback,
8936 iend);
1a91d914 8937 gcond *cond_stmt = gimple_build_cond_empty (t);
8938 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
3d483a94 8939 }
773c5ba7 8940
75a70cf9 8941 /* Remove GIMPLE_OMP_CONTINUE. */
8942 gsi_remove (&gsi, true);
773c5ba7 8943
bc7bff74 8944 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
3d483a94 8945 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, l1_bb);
fd6481cf 8946
ac6e3339 8947 /* Emit code to get the next parallel iteration in L2_BB. */
75a70cf9 8948 gsi = gsi_start_bb (l2_bb);
773c5ba7 8949
b9a16870 8950 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
ac6e3339 8951 build_fold_addr_expr (istart0),
8952 build_fold_addr_expr (iend0));
75a70cf9 8953 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8954 false, GSI_CONTINUE_LINKING);
fd6481cf 8955 if (TREE_TYPE (t) != boolean_type_node)
8956 t = fold_build2 (NE_EXPR, boolean_type_node,
8957 t, build_int_cst (TREE_TYPE (t), 0));
1a91d914 8958 gcond *cond_stmt = gimple_build_cond_empty (t);
8959 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
ac6e3339 8960 }
1e8e9920 8961
61e47ac8 8962 /* Add the loop cleanup function. */
75a70cf9 8963 gsi = gsi_last_bb (exit_bb);
8964 if (gimple_omp_return_nowait_p (gsi_stmt (gsi)))
b9a16870 8965 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
bc7bff74 8966 else if (gimple_omp_return_lhs (gsi_stmt (gsi)))
8967 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL);
61e47ac8 8968 else
b9a16870 8969 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END);
1a91d914 8970 gcall *call_stmt = gimple_build_call (t, 0);
bc7bff74 8971 if (gimple_omp_return_lhs (gsi_stmt (gsi)))
1a91d914 8972 gimple_call_set_lhs (call_stmt, gimple_omp_return_lhs (gsi_stmt (gsi)));
8973 gsi_insert_after (&gsi, call_stmt, GSI_SAME_STMT);
43895be5 8974 if (fd->ordered)
8975 {
8976 tree arr = counts[fd->ordered];
8977 tree clobber = build_constructor (TREE_TYPE (arr), NULL);
8978 TREE_THIS_VOLATILE (clobber) = 1;
8979 gsi_insert_after (&gsi, gimple_build_assign (arr, clobber),
8980 GSI_SAME_STMT);
8981 }
75a70cf9 8982 gsi_remove (&gsi, true);
773c5ba7 8983
8984 /* Connect the new blocks. */
79acaae1 8985 find_edge (entry_bb, l0_bb)->flags = EDGE_TRUE_VALUE;
8986 find_edge (entry_bb, l3_bb)->flags = EDGE_FALSE_VALUE;
1e8e9920 8987
ac6e3339 8988 if (!broken_loop)
8989 {
75a70cf9 8990 gimple_seq phis;
8991
79acaae1 8992 e = find_edge (cont_bb, l3_bb);
8993 ne = make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
8994
75a70cf9 8995 phis = phi_nodes (l3_bb);
8996 for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi))
8997 {
42acab1c 8998 gimple *phi = gsi_stmt (gsi);
75a70cf9 8999 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, ne),
9000 PHI_ARG_DEF_FROM_EDGE (phi, e));
9001 }
79acaae1 9002 remove_edge (e);
9003
ac6e3339 9004 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
3d483a94 9005 e = find_edge (cont_bb, l1_bb);
95cd5725 9006 if (e == NULL)
9007 {
9008 e = BRANCH_EDGE (cont_bb);
9009 gcc_assert (single_succ (e->dest) == l1_bb);
9010 }
bc7bff74 9011 if (gimple_omp_for_combined_p (fd->for_stmt))
9012 {
9013 remove_edge (e);
9014 e = NULL;
9015 }
3d483a94 9016 else if (fd->collapse > 1)
fd6481cf 9017 {
fd6481cf 9018 remove_edge (e);
9019 e = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
9020 }
9021 else
3d483a94 9022 e->flags = EDGE_TRUE_VALUE;
9023 if (e)
fd6481cf 9024 {
3d483a94 9025 e->probability = REG_BR_PROB_BASE * 7 / 8;
9026 find_edge (cont_bb, l2_bb)->probability = REG_BR_PROB_BASE / 8;
9027 }
9028 else
9029 {
9030 e = find_edge (cont_bb, l2_bb);
9031 e->flags = EDGE_FALLTHRU;
fd6481cf 9032 }
ac6e3339 9033 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
79acaae1 9034
2131a1a9 9035 if (gimple_in_ssa_p (cfun))
9036 {
9037 /* Add phis to the outer loop that connect to the phis in the inner,
9038 original loop, and move the loop entry value of the inner phi to
9039 the loop entry value of the outer phi. */
9040 gphi_iterator psi;
9041 for (psi = gsi_start_phis (l3_bb); !gsi_end_p (psi); gsi_next (&psi))
9042 {
9043 source_location locus;
9044 gphi *nphi;
9045 gphi *exit_phi = psi.phi ();
9046
9047 edge l2_to_l3 = find_edge (l2_bb, l3_bb);
9048 tree exit_res = PHI_ARG_DEF_FROM_EDGE (exit_phi, l2_to_l3);
9049
9050 basic_block latch = BRANCH_EDGE (cont_bb)->dest;
9051 edge latch_to_l1 = find_edge (latch, l1_bb);
9052 gphi *inner_phi
9053 = find_phi_with_arg_on_edge (exit_res, latch_to_l1);
9054
9055 tree t = gimple_phi_result (exit_phi);
9056 tree new_res = copy_ssa_name (t, NULL);
9057 nphi = create_phi_node (new_res, l0_bb);
9058
9059 edge l0_to_l1 = find_edge (l0_bb, l1_bb);
9060 t = PHI_ARG_DEF_FROM_EDGE (inner_phi, l0_to_l1);
9061 locus = gimple_phi_arg_location_from_edge (inner_phi, l0_to_l1);
9062 edge entry_to_l0 = find_edge (entry_bb, l0_bb);
9063 add_phi_arg (nphi, t, entry_to_l0, locus);
9064
9065 edge l2_to_l0 = find_edge (l2_bb, l0_bb);
9066 add_phi_arg (nphi, exit_res, l2_to_l0, UNKNOWN_LOCATION);
9067
9068 add_phi_arg (inner_phi, new_res, l0_to_l1, UNKNOWN_LOCATION);
9069 };
9070 }
9071
79acaae1 9072 set_immediate_dominator (CDI_DOMINATORS, l2_bb,
9073 recompute_dominator (CDI_DOMINATORS, l2_bb));
9074 set_immediate_dominator (CDI_DOMINATORS, l3_bb,
9075 recompute_dominator (CDI_DOMINATORS, l3_bb));
9076 set_immediate_dominator (CDI_DOMINATORS, l0_bb,
9077 recompute_dominator (CDI_DOMINATORS, l0_bb));
9078 set_immediate_dominator (CDI_DOMINATORS, l1_bb,
9079 recompute_dominator (CDI_DOMINATORS, l1_bb));
04c2922b 9080
1c6a437b 9081 /* We enter expand_omp_for_generic with a loop. This original loop may
9082 have its own loop struct, or it may be part of an outer loop struct
9083 (which may be the fake loop). */
9084 struct loop *outer_loop = entry_bb->loop_father;
9085 bool orig_loop_has_loop_struct = l1_bb->loop_father != outer_loop;
9086
9087 add_bb_to_loop (l2_bb, outer_loop);
9088
9089 /* We've added a new loop around the original loop. Allocate the
9090 corresponding loop struct. */
9091 struct loop *new_loop = alloc_loop ();
9092 new_loop->header = l0_bb;
9093 new_loop->latch = l2_bb;
9094 add_loop (new_loop, outer_loop);
9095
9096 /* Allocate a loop structure for the original loop unless we already
9097 had one. */
9098 if (!orig_loop_has_loop_struct
9099 && !gimple_omp_for_combined_p (fd->for_stmt))
3d483a94 9100 {
1c6a437b 9101 struct loop *orig_loop = alloc_loop ();
9102 orig_loop->header = l1_bb;
3d483a94 9103 /* The loop may have multiple latches. */
1c6a437b 9104 add_loop (orig_loop, new_loop);
3d483a94 9105 }
ac6e3339 9106 }
1e8e9920 9107}
9108
9109
773c5ba7 9110/* A subroutine of expand_omp_for. Generate code for a parallel
9111 loop with static schedule and no specified chunk size. Given
9112 parameters:
1e8e9920 9113
9114 for (V = N1; V cond N2; V += STEP) BODY;
9115
9116 where COND is "<" or ">", we generate pseudocode
9117
8e6b4515 9118 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
1e8e9920 9119 if (cond is <)
9120 adj = STEP - 1;
9121 else
9122 adj = STEP + 1;
fd6481cf 9123 if ((__typeof (V)) -1 > 0 && cond is >)
9124 n = -(adj + N2 - N1) / -STEP;
9125 else
9126 n = (adj + N2 - N1) / STEP;
1e8e9920 9127 q = n / nthreads;
31712e83 9128 tt = n % nthreads;
9129 if (threadid < tt) goto L3; else goto L4;
9130 L3:
9131 tt = 0;
9132 q = q + 1;
9133 L4:
9134 s0 = q * threadid + tt;
9135 e0 = s0 + q;
79acaae1 9136 V = s0 * STEP + N1;
1e8e9920 9137 if (s0 >= e0) goto L2; else goto L0;
9138 L0:
1e8e9920 9139 e = e0 * STEP + N1;
9140 L1:
9141 BODY;
9142 V += STEP;
9143 if (V cond e) goto L1;
1e8e9920 9144 L2:
9145*/
9146
61e47ac8 9147static void
773c5ba7 9148expand_omp_for_static_nochunk (struct omp_region *region,
bc7bff74 9149 struct omp_for_data *fd,
42acab1c 9150 gimple *inner_stmt)
1e8e9920 9151{
31712e83 9152 tree n, q, s0, e0, e, t, tt, nthreads, threadid;
fd6481cf 9153 tree type, itype, vmain, vback;
31712e83 9154 basic_block entry_bb, second_bb, third_bb, exit_bb, seq_start_bb;
bc7bff74 9155 basic_block body_bb, cont_bb, collapse_bb = NULL;
61e47ac8 9156 basic_block fin_bb;
75a70cf9 9157 gimple_stmt_iterator gsi;
31712e83 9158 edge ep;
bc7bff74 9159 bool broken_loop = region->cont == NULL;
9160 tree *counts = NULL;
9161 tree n1, n2, step;
1e8e9920 9162
fd6481cf 9163 itype = type = TREE_TYPE (fd->loop.v);
9164 if (POINTER_TYPE_P (type))
3cea8318 9165 itype = signed_type_for (type);
1e8e9920 9166
61e47ac8 9167 entry_bb = region->entry;
61e47ac8 9168 cont_bb = region->cont;
ac6e3339 9169 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
bc7bff74 9170 fin_bb = BRANCH_EDGE (entry_bb)->dest;
9171 gcc_assert (broken_loop
9172 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
ac6e3339 9173 seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb));
9174 body_bb = single_succ (seq_start_bb);
bc7bff74 9175 if (!broken_loop)
9176 {
86a932e0 9177 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb
9178 || single_succ (BRANCH_EDGE (cont_bb)->dest) == body_bb);
bc7bff74 9179 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
9180 }
61e47ac8 9181 exit_bb = region->exit;
9182
773c5ba7 9183 /* Iteration space partitioning goes in ENTRY_BB. */
75a70cf9 9184 gsi = gsi_last_bb (entry_bb);
9185 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
61e47ac8 9186
bc7bff74 9187 if (fd->collapse > 1)
9188 {
43895be5 9189 int first_zero_iter = -1, dummy = -1;
9190 basic_block l2_dom_bb = NULL, dummy_bb = NULL;
bc7bff74 9191
9192 counts = XALLOCAVEC (tree, fd->collapse);
9193 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
9194 fin_bb, first_zero_iter,
43895be5 9195 dummy_bb, dummy, l2_dom_bb);
bc7bff74 9196 t = NULL_TREE;
9197 }
9198 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
9199 t = integer_one_node;
9200 else
9201 t = fold_binary (fd->loop.cond_code, boolean_type_node,
9202 fold_convert (type, fd->loop.n1),
9203 fold_convert (type, fd->loop.n2));
9204 if (fd->collapse == 1
9205 && TYPE_UNSIGNED (type)
8e6b4515 9206 && (t == NULL_TREE || !integer_onep (t)))
9207 {
8e6b4515 9208 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
9209 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
9210 true, GSI_SAME_STMT);
9211 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
9212 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
9213 true, GSI_SAME_STMT);
1a91d914 9214 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
9215 NULL_TREE, NULL_TREE);
9216 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
9217 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
8e6b4515 9218 expand_omp_regimplify_p, NULL, NULL)
1a91d914 9219 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
8e6b4515 9220 expand_omp_regimplify_p, NULL, NULL))
9221 {
1a91d914 9222 gsi = gsi_for_stmt (cond_stmt);
9223 gimple_regimplify_operands (cond_stmt, &gsi);
8e6b4515 9224 }
1a91d914 9225 ep = split_block (entry_bb, cond_stmt);
8e6b4515 9226 ep->flags = EDGE_TRUE_VALUE;
9227 entry_bb = ep->dest;
9228 ep->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
9229 ep = make_edge (ep->src, fin_bb, EDGE_FALSE_VALUE);
9230 ep->probability = REG_BR_PROB_BASE / 2000 - 1;
9231 if (gimple_in_ssa_p (cfun))
9232 {
9233 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
1a91d914 9234 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
9235 !gsi_end_p (gpi); gsi_next (&gpi))
8e6b4515 9236 {
1a91d914 9237 gphi *phi = gpi.phi ();
8e6b4515 9238 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
9239 ep, UNKNOWN_LOCATION);
9240 }
9241 }
9242 gsi = gsi_last_bb (entry_bb);
9243 }
9244
ca4c3545 9245 switch (gimple_omp_for_kind (fd->for_stmt))
9246 {
9247 case GF_OMP_FOR_KIND_FOR:
9248 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
9249 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
9250 break;
9251 case GF_OMP_FOR_KIND_DISTRIBUTE:
9252 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
9253 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
9254 break;
ca4c3545 9255 default:
9256 gcc_unreachable ();
9257 }
9258 nthreads = build_call_expr (nthreads, 0);
9259 nthreads = fold_convert (itype, nthreads);
9260 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
75a70cf9 9261 true, GSI_SAME_STMT);
ca4c3545 9262 threadid = build_call_expr (threadid, 0);
9263 threadid = fold_convert (itype, threadid);
9264 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
75a70cf9 9265 true, GSI_SAME_STMT);
1e8e9920 9266
bc7bff74 9267 n1 = fd->loop.n1;
9268 n2 = fd->loop.n2;
9269 step = fd->loop.step;
9270 if (gimple_omp_for_combined_into_p (fd->for_stmt))
9271 {
9272 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
9273 OMP_CLAUSE__LOOPTEMP_);
9274 gcc_assert (innerc);
9275 n1 = OMP_CLAUSE_DECL (innerc);
9276 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9277 OMP_CLAUSE__LOOPTEMP_);
9278 gcc_assert (innerc);
9279 n2 = OMP_CLAUSE_DECL (innerc);
9280 }
9281 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
9282 true, NULL_TREE, true, GSI_SAME_STMT);
9283 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
9284 true, NULL_TREE, true, GSI_SAME_STMT);
9285 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
9286 true, NULL_TREE, true, GSI_SAME_STMT);
fd6481cf 9287
9288 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
bc7bff74 9289 t = fold_build2 (PLUS_EXPR, itype, step, t);
9290 t = fold_build2 (PLUS_EXPR, itype, t, n2);
9291 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
fd6481cf 9292 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
9293 t = fold_build2 (TRUNC_DIV_EXPR, itype,
9294 fold_build1 (NEGATE_EXPR, itype, t),
bc7bff74 9295 fold_build1 (NEGATE_EXPR, itype, step));
fd6481cf 9296 else
bc7bff74 9297 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
fd6481cf 9298 t = fold_convert (itype, t);
75a70cf9 9299 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
1e8e9920 9300
072f7ab1 9301 q = create_tmp_reg (itype, "q");
fd6481cf 9302 t = fold_build2 (TRUNC_DIV_EXPR, itype, n, nthreads);
31712e83 9303 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
9304 gsi_insert_before (&gsi, gimple_build_assign (q, t), GSI_SAME_STMT);
9305
072f7ab1 9306 tt = create_tmp_reg (itype, "tt");
31712e83 9307 t = fold_build2 (TRUNC_MOD_EXPR, itype, n, nthreads);
9308 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
9309 gsi_insert_before (&gsi, gimple_build_assign (tt, t), GSI_SAME_STMT);
1e8e9920 9310
31712e83 9311 t = build2 (LT_EXPR, boolean_type_node, threadid, tt);
1a91d914 9312 gcond *cond_stmt = gimple_build_cond_empty (t);
9313 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
31712e83 9314
1a91d914 9315 second_bb = split_block (entry_bb, cond_stmt)->dest;
31712e83 9316 gsi = gsi_last_bb (second_bb);
9317 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
9318
9319 gsi_insert_before (&gsi, gimple_build_assign (tt, build_int_cst (itype, 0)),
9320 GSI_SAME_STMT);
1a91d914 9321 gassign *assign_stmt
e9cf809e 9322 = gimple_build_assign (q, PLUS_EXPR, q, build_int_cst (itype, 1));
1a91d914 9323 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
31712e83 9324
1a91d914 9325 third_bb = split_block (second_bb, assign_stmt)->dest;
31712e83 9326 gsi = gsi_last_bb (third_bb);
9327 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
1e8e9920 9328
fd6481cf 9329 t = build2 (MULT_EXPR, itype, q, threadid);
31712e83 9330 t = build2 (PLUS_EXPR, itype, t, tt);
75a70cf9 9331 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
1e8e9920 9332
fd6481cf 9333 t = fold_build2 (PLUS_EXPR, itype, s0, q);
75a70cf9 9334 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
79acaae1 9335
1e8e9920 9336 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
75a70cf9 9337 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
773c5ba7 9338
75a70cf9 9339 /* Remove the GIMPLE_OMP_FOR statement. */
9340 gsi_remove (&gsi, true);
773c5ba7 9341
9342 /* Setup code for sequential iteration goes in SEQ_START_BB. */
75a70cf9 9343 gsi = gsi_start_bb (seq_start_bb);
1e8e9920 9344
bc7bff74 9345 tree startvar = fd->loop.v;
9346 tree endvar = NULL_TREE;
9347
9348 if (gimple_omp_for_combined_p (fd->for_stmt))
9349 {
9350 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
9351 ? gimple_omp_parallel_clauses (inner_stmt)
9352 : gimple_omp_for_clauses (inner_stmt);
9353 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
9354 gcc_assert (innerc);
9355 startvar = OMP_CLAUSE_DECL (innerc);
9356 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9357 OMP_CLAUSE__LOOPTEMP_);
9358 gcc_assert (innerc);
9359 endvar = OMP_CLAUSE_DECL (innerc);
9561765e 9360 if (fd->collapse > 1 && TREE_CODE (fd->loop.n2) != INTEGER_CST
9361 && gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
9362 {
9363 int i;
9364 for (i = 1; i < fd->collapse; i++)
9365 {
9366 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9367 OMP_CLAUSE__LOOPTEMP_);
9368 gcc_assert (innerc);
9369 }
9370 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9371 OMP_CLAUSE__LOOPTEMP_);
9372 if (innerc)
9373 {
9374 /* If needed (distribute parallel for with lastprivate),
9375 propagate down the total number of iterations. */
9376 tree t = fold_convert (TREE_TYPE (OMP_CLAUSE_DECL (innerc)),
9377 fd->loop.n2);
9378 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, false,
9379 GSI_CONTINUE_LINKING);
9380 assign_stmt = gimple_build_assign (OMP_CLAUSE_DECL (innerc), t);
9381 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9382 }
9383 }
bc7bff74 9384 }
fd6481cf 9385 t = fold_convert (itype, s0);
bc7bff74 9386 t = fold_build2 (MULT_EXPR, itype, t, step);
fd6481cf 9387 if (POINTER_TYPE_P (type))
bc7bff74 9388 t = fold_build_pointer_plus (n1, t);
fd6481cf 9389 else
bc7bff74 9390 t = fold_build2 (PLUS_EXPR, type, t, n1);
9391 t = fold_convert (TREE_TYPE (startvar), t);
4abecb72 9392 t = force_gimple_operand_gsi (&gsi, t,
bc7bff74 9393 DECL_P (startvar)
9394 && TREE_ADDRESSABLE (startvar),
4abecb72 9395 NULL_TREE, false, GSI_CONTINUE_LINKING);
1a91d914 9396 assign_stmt = gimple_build_assign (startvar, t);
9397 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
48e1416a 9398
fd6481cf 9399 t = fold_convert (itype, e0);
bc7bff74 9400 t = fold_build2 (MULT_EXPR, itype, t, step);
fd6481cf 9401 if (POINTER_TYPE_P (type))
bc7bff74 9402 t = fold_build_pointer_plus (n1, t);
fd6481cf 9403 else
bc7bff74 9404 t = fold_build2 (PLUS_EXPR, type, t, n1);
9405 t = fold_convert (TREE_TYPE (startvar), t);
75a70cf9 9406 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9407 false, GSI_CONTINUE_LINKING);
bc7bff74 9408 if (endvar)
9409 {
1a91d914 9410 assign_stmt = gimple_build_assign (endvar, e);
9411 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
d44f2f7c 9412 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
1a91d914 9413 assign_stmt = gimple_build_assign (fd->loop.v, e);
d44f2f7c 9414 else
e9cf809e 9415 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
1a91d914 9416 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
bc7bff74 9417 }
43895be5 9418 /* Handle linear clause adjustments. */
9419 tree itercnt = NULL_TREE;
9420 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_FOR)
9421 for (tree c = gimple_omp_for_clauses (fd->for_stmt);
9422 c; c = OMP_CLAUSE_CHAIN (c))
9423 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
9424 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
9425 {
9426 tree d = OMP_CLAUSE_DECL (c);
9427 bool is_ref = is_reference (d);
9428 tree t = d, a, dest;
9429 if (is_ref)
9430 t = build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c), t);
9431 if (itercnt == NULL_TREE)
9432 {
9433 if (gimple_omp_for_combined_into_p (fd->for_stmt))
9434 {
9435 itercnt = fold_build2 (MINUS_EXPR, itype,
9436 fold_convert (itype, n1),
9437 fold_convert (itype, fd->loop.n1));
9438 itercnt = fold_build2 (EXACT_DIV_EXPR, itype, itercnt, step);
9439 itercnt = fold_build2 (PLUS_EXPR, itype, itercnt, s0);
9440 itercnt = force_gimple_operand_gsi (&gsi, itercnt, true,
9441 NULL_TREE, false,
9442 GSI_CONTINUE_LINKING);
9443 }
9444 else
9445 itercnt = s0;
9446 }
9447 tree type = TREE_TYPE (t);
9448 if (POINTER_TYPE_P (type))
9449 type = sizetype;
9450 a = fold_build2 (MULT_EXPR, type,
9451 fold_convert (type, itercnt),
9452 fold_convert (type, OMP_CLAUSE_LINEAR_STEP (c)));
9453 dest = unshare_expr (t);
9454 t = fold_build2 (type == TREE_TYPE (t) ? PLUS_EXPR
9455 : POINTER_PLUS_EXPR, TREE_TYPE (t), t, a);
9456 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9457 false, GSI_CONTINUE_LINKING);
9458 assign_stmt = gimple_build_assign (dest, t);
9459 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9460 }
bc7bff74 9461 if (fd->collapse > 1)
9462 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
1e8e9920 9463
bc7bff74 9464 if (!broken_loop)
9465 {
9466 /* The code controlling the sequential loop replaces the
9467 GIMPLE_OMP_CONTINUE. */
9468 gsi = gsi_last_bb (cont_bb);
1a91d914 9469 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
9470 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
9471 vmain = gimple_omp_continue_control_use (cont_stmt);
9472 vback = gimple_omp_continue_control_def (cont_stmt);
79acaae1 9473
bc7bff74 9474 if (!gimple_omp_for_combined_p (fd->for_stmt))
9475 {
9476 if (POINTER_TYPE_P (type))
9477 t = fold_build_pointer_plus (vmain, step);
9478 else
9479 t = fold_build2 (PLUS_EXPR, type, vmain, step);
9480 t = force_gimple_operand_gsi (&gsi, t,
9481 DECL_P (vback)
9482 && TREE_ADDRESSABLE (vback),
9483 NULL_TREE, true, GSI_SAME_STMT);
1a91d914 9484 assign_stmt = gimple_build_assign (vback, t);
9485 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
79acaae1 9486
bc7bff74 9487 t = build2 (fd->loop.cond_code, boolean_type_node,
9488 DECL_P (vback) && TREE_ADDRESSABLE (vback)
9489 ? t : vback, e);
9490 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
9491 }
1e8e9920 9492
bc7bff74 9493 /* Remove the GIMPLE_OMP_CONTINUE statement. */
9494 gsi_remove (&gsi, true);
9495
9496 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
9497 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
9498 }
773c5ba7 9499
75a70cf9 9500 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
9501 gsi = gsi_last_bb (exit_bb);
9502 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
bc7bff74 9503 {
9504 t = gimple_omp_return_lhs (gsi_stmt (gsi));
a8e785ba 9505 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
bc7bff74 9506 }
75a70cf9 9507 gsi_remove (&gsi, true);
773c5ba7 9508
9509 /* Connect all the blocks. */
31712e83 9510 ep = make_edge (entry_bb, third_bb, EDGE_FALSE_VALUE);
9511 ep->probability = REG_BR_PROB_BASE / 4 * 3;
9512 ep = find_edge (entry_bb, second_bb);
9513 ep->flags = EDGE_TRUE_VALUE;
9514 ep->probability = REG_BR_PROB_BASE / 4;
9515 find_edge (third_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
9516 find_edge (third_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
79acaae1 9517
bc7bff74 9518 if (!broken_loop)
9519 {
9520 ep = find_edge (cont_bb, body_bb);
86a932e0 9521 if (ep == NULL)
9522 {
9523 ep = BRANCH_EDGE (cont_bb);
9524 gcc_assert (single_succ (ep->dest) == body_bb);
9525 }
bc7bff74 9526 if (gimple_omp_for_combined_p (fd->for_stmt))
9527 {
9528 remove_edge (ep);
9529 ep = NULL;
9530 }
9531 else if (fd->collapse > 1)
9532 {
9533 remove_edge (ep);
9534 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
9535 }
9536 else
9537 ep->flags = EDGE_TRUE_VALUE;
9538 find_edge (cont_bb, fin_bb)->flags
9539 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
9540 }
48e1416a 9541
31712e83 9542 set_immediate_dominator (CDI_DOMINATORS, second_bb, entry_bb);
9543 set_immediate_dominator (CDI_DOMINATORS, third_bb, entry_bb);
9544 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, third_bb);
bc7bff74 9545
79acaae1 9546 set_immediate_dominator (CDI_DOMINATORS, body_bb,
9547 recompute_dominator (CDI_DOMINATORS, body_bb));
9548 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
9549 recompute_dominator (CDI_DOMINATORS, fin_bb));
04c2922b 9550
86a932e0 9551 struct loop *loop = body_bb->loop_father;
9552 if (loop != entry_bb->loop_father)
9553 {
9554 gcc_assert (loop->header == body_bb);
9555 gcc_assert (broken_loop
9556 || loop->latch == region->cont
9557 || single_pred (loop->latch) == region->cont);
9558 return;
9559 }
9560
bc7bff74 9561 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
9562 {
86a932e0 9563 loop = alloc_loop ();
bc7bff74 9564 loop->header = body_bb;
9565 if (collapse_bb == NULL)
9566 loop->latch = cont_bb;
9567 add_loop (loop, body_bb->loop_father);
9568 }
1e8e9920 9569}
9570
281001a9 9571/* Return phi in E->DEST with ARG on edge E. */
9572
9573static gphi *
9574find_phi_with_arg_on_edge (tree arg, edge e)
9575{
9576 basic_block bb = e->dest;
9577
9578 for (gphi_iterator gpi = gsi_start_phis (bb);
9579 !gsi_end_p (gpi);
9580 gsi_next (&gpi))
9581 {
9582 gphi *phi = gpi.phi ();
9583 if (PHI_ARG_DEF_FROM_EDGE (phi, e) == arg)
9584 return phi;
9585 }
9586
9587 return NULL;
9588}
773c5ba7 9589
9590/* A subroutine of expand_omp_for. Generate code for a parallel
9591 loop with static schedule and a specified chunk size. Given
9592 parameters:
1e8e9920 9593
9594 for (V = N1; V cond N2; V += STEP) BODY;
9595
9596 where COND is "<" or ">", we generate pseudocode
9597
8e6b4515 9598 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
1e8e9920 9599 if (cond is <)
9600 adj = STEP - 1;
9601 else
9602 adj = STEP + 1;
fd6481cf 9603 if ((__typeof (V)) -1 > 0 && cond is >)
9604 n = -(adj + N2 - N1) / -STEP;
9605 else
9606 n = (adj + N2 - N1) / STEP;
1e8e9920 9607 trip = 0;
79acaae1 9608 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
9609 here so that V is defined
9610 if the loop is not entered
1e8e9920 9611 L0:
9612 s0 = (trip * nthreads + threadid) * CHUNK;
9613 e0 = min(s0 + CHUNK, n);
9614 if (s0 < n) goto L1; else goto L4;
9615 L1:
9616 V = s0 * STEP + N1;
9617 e = e0 * STEP + N1;
9618 L2:
9619 BODY;
9620 V += STEP;
9621 if (V cond e) goto L2; else goto L3;
9622 L3:
9623 trip += 1;
9624 goto L0;
9625 L4:
1e8e9920 9626*/
9627
61e47ac8 9628static void
bc7bff74 9629expand_omp_for_static_chunk (struct omp_region *region,
42acab1c 9630 struct omp_for_data *fd, gimple *inner_stmt)
1e8e9920 9631{
75a70cf9 9632 tree n, s0, e0, e, t;
79acaae1 9633 tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
93481288 9634 tree type, itype, vmain, vback, vextra;
773c5ba7 9635 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
bc7bff74 9636 basic_block trip_update_bb = NULL, cont_bb, collapse_bb = NULL, fin_bb;
93481288 9637 gimple_stmt_iterator gsi;
75a70cf9 9638 edge se;
bc7bff74 9639 bool broken_loop = region->cont == NULL;
9640 tree *counts = NULL;
9641 tree n1, n2, step;
1e8e9920 9642
fd6481cf 9643 itype = type = TREE_TYPE (fd->loop.v);
9644 if (POINTER_TYPE_P (type))
3cea8318 9645 itype = signed_type_for (type);
1e8e9920 9646
61e47ac8 9647 entry_bb = region->entry;
ac6e3339 9648 se = split_block (entry_bb, last_stmt (entry_bb));
9649 entry_bb = se->src;
9650 iter_part_bb = se->dest;
61e47ac8 9651 cont_bb = region->cont;
ac6e3339 9652 gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
bc7bff74 9653 fin_bb = BRANCH_EDGE (iter_part_bb)->dest;
9654 gcc_assert (broken_loop
9655 || fin_bb == FALLTHRU_EDGE (cont_bb)->dest);
ac6e3339 9656 seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
9657 body_bb = single_succ (seq_start_bb);
bc7bff74 9658 if (!broken_loop)
9659 {
fc1d58e3 9660 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb
9661 || single_succ (BRANCH_EDGE (cont_bb)->dest) == body_bb);
bc7bff74 9662 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
9663 trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
9664 }
61e47ac8 9665 exit_bb = region->exit;
773c5ba7 9666
773c5ba7 9667 /* Trip and adjustment setup goes in ENTRY_BB. */
93481288 9668 gsi = gsi_last_bb (entry_bb);
9669 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
773c5ba7 9670
bc7bff74 9671 if (fd->collapse > 1)
9672 {
43895be5 9673 int first_zero_iter = -1, dummy = -1;
9674 basic_block l2_dom_bb = NULL, dummy_bb = NULL;
bc7bff74 9675
9676 counts = XALLOCAVEC (tree, fd->collapse);
93481288 9677 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
bc7bff74 9678 fin_bb, first_zero_iter,
43895be5 9679 dummy_bb, dummy, l2_dom_bb);
bc7bff74 9680 t = NULL_TREE;
9681 }
9682 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
9683 t = integer_one_node;
9684 else
9685 t = fold_binary (fd->loop.cond_code, boolean_type_node,
9686 fold_convert (type, fd->loop.n1),
9687 fold_convert (type, fd->loop.n2));
9688 if (fd->collapse == 1
9689 && TYPE_UNSIGNED (type)
8e6b4515 9690 && (t == NULL_TREE || !integer_onep (t)))
9691 {
8e6b4515 9692 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
93481288 9693 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
8e6b4515 9694 true, GSI_SAME_STMT);
9695 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
93481288 9696 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
8e6b4515 9697 true, GSI_SAME_STMT);
1a91d914 9698 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
9699 NULL_TREE, NULL_TREE);
9700 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
9701 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
8e6b4515 9702 expand_omp_regimplify_p, NULL, NULL)
1a91d914 9703 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
8e6b4515 9704 expand_omp_regimplify_p, NULL, NULL))
9705 {
1a91d914 9706 gsi = gsi_for_stmt (cond_stmt);
9707 gimple_regimplify_operands (cond_stmt, &gsi);
8e6b4515 9708 }
1a91d914 9709 se = split_block (entry_bb, cond_stmt);
8e6b4515 9710 se->flags = EDGE_TRUE_VALUE;
9711 entry_bb = se->dest;
9712 se->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
9713 se = make_edge (se->src, fin_bb, EDGE_FALSE_VALUE);
9714 se->probability = REG_BR_PROB_BASE / 2000 - 1;
9715 if (gimple_in_ssa_p (cfun))
9716 {
264aa959 9717 int dest_idx = find_edge (iter_part_bb, fin_bb)->dest_idx;
1a91d914 9718 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
9719 !gsi_end_p (gpi); gsi_next (&gpi))
8e6b4515 9720 {
1a91d914 9721 gphi *phi = gpi.phi ();
8e6b4515 9722 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
9723 se, UNKNOWN_LOCATION);
9724 }
9725 }
93481288 9726 gsi = gsi_last_bb (entry_bb);
8e6b4515 9727 }
9728
ca4c3545 9729 switch (gimple_omp_for_kind (fd->for_stmt))
9730 {
9731 case GF_OMP_FOR_KIND_FOR:
9732 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
9733 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
9734 break;
9735 case GF_OMP_FOR_KIND_DISTRIBUTE:
9736 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
9737 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
9738 break;
ca4c3545 9739 default:
9740 gcc_unreachable ();
9741 }
9742 nthreads = build_call_expr (nthreads, 0);
9743 nthreads = fold_convert (itype, nthreads);
9744 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
75a70cf9 9745 true, GSI_SAME_STMT);
ca4c3545 9746 threadid = build_call_expr (threadid, 0);
9747 threadid = fold_convert (itype, threadid);
9748 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
75a70cf9 9749 true, GSI_SAME_STMT);
79acaae1 9750
bc7bff74 9751 n1 = fd->loop.n1;
9752 n2 = fd->loop.n2;
9753 step = fd->loop.step;
9754 if (gimple_omp_for_combined_into_p (fd->for_stmt))
9755 {
9756 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
9757 OMP_CLAUSE__LOOPTEMP_);
9758 gcc_assert (innerc);
9759 n1 = OMP_CLAUSE_DECL (innerc);
9760 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9761 OMP_CLAUSE__LOOPTEMP_);
9762 gcc_assert (innerc);
9763 n2 = OMP_CLAUSE_DECL (innerc);
9764 }
93481288 9765 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
bc7bff74 9766 true, NULL_TREE, true, GSI_SAME_STMT);
93481288 9767 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
bc7bff74 9768 true, NULL_TREE, true, GSI_SAME_STMT);
93481288 9769 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
bc7bff74 9770 true, NULL_TREE, true, GSI_SAME_STMT);
43895be5 9771 tree chunk_size = fold_convert (itype, fd->chunk_size);
9772 chunk_size = omp_adjust_chunk_size (chunk_size, fd->simd_schedule);
9773 chunk_size
9774 = force_gimple_operand_gsi (&gsi, chunk_size, true, NULL_TREE, true,
9775 GSI_SAME_STMT);
fd6481cf 9776
9777 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
bc7bff74 9778 t = fold_build2 (PLUS_EXPR, itype, step, t);
9779 t = fold_build2 (PLUS_EXPR, itype, t, n2);
9780 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
fd6481cf 9781 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
9782 t = fold_build2 (TRUNC_DIV_EXPR, itype,
9783 fold_build1 (NEGATE_EXPR, itype, t),
bc7bff74 9784 fold_build1 (NEGATE_EXPR, itype, step));
fd6481cf 9785 else
bc7bff74 9786 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
fd6481cf 9787 t = fold_convert (itype, t);
93481288 9788 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
75a70cf9 9789 true, GSI_SAME_STMT);
79acaae1 9790
083152fb 9791 trip_var = create_tmp_reg (itype, ".trip");
79acaae1 9792 if (gimple_in_ssa_p (cfun))
9793 {
f9e245b2 9794 trip_init = make_ssa_name (trip_var);
9795 trip_main = make_ssa_name (trip_var);
9796 trip_back = make_ssa_name (trip_var);
79acaae1 9797 }
1e8e9920 9798 else
79acaae1 9799 {
9800 trip_init = trip_var;
9801 trip_main = trip_var;
9802 trip_back = trip_var;
9803 }
1e8e9920 9804
1a91d914 9805 gassign *assign_stmt
9806 = gimple_build_assign (trip_init, build_int_cst (itype, 0));
9807 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
773c5ba7 9808
43895be5 9809 t = fold_build2 (MULT_EXPR, itype, threadid, chunk_size);
bc7bff74 9810 t = fold_build2 (MULT_EXPR, itype, t, step);
fd6481cf 9811 if (POINTER_TYPE_P (type))
bc7bff74 9812 t = fold_build_pointer_plus (n1, t);
fd6481cf 9813 else
bc7bff74 9814 t = fold_build2 (PLUS_EXPR, type, t, n1);
93481288 9815 vextra = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9816 true, GSI_SAME_STMT);
79acaae1 9817
75a70cf9 9818 /* Remove the GIMPLE_OMP_FOR. */
93481288 9819 gsi_remove (&gsi, true);
773c5ba7 9820
43895be5 9821 gimple_stmt_iterator gsif = gsi;
9822
773c5ba7 9823 /* Iteration space partitioning goes in ITER_PART_BB. */
93481288 9824 gsi = gsi_last_bb (iter_part_bb);
1e8e9920 9825
fd6481cf 9826 t = fold_build2 (MULT_EXPR, itype, trip_main, nthreads);
9827 t = fold_build2 (PLUS_EXPR, itype, t, threadid);
43895be5 9828 t = fold_build2 (MULT_EXPR, itype, t, chunk_size);
93481288 9829 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
75a70cf9 9830 false, GSI_CONTINUE_LINKING);
1e8e9920 9831
43895be5 9832 t = fold_build2 (PLUS_EXPR, itype, s0, chunk_size);
fd6481cf 9833 t = fold_build2 (MIN_EXPR, itype, t, n);
93481288 9834 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
75a70cf9 9835 false, GSI_CONTINUE_LINKING);
1e8e9920 9836
9837 t = build2 (LT_EXPR, boolean_type_node, s0, n);
93481288 9838 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_CONTINUE_LINKING);
773c5ba7 9839
9840 /* Setup code for sequential iteration goes in SEQ_START_BB. */
93481288 9841 gsi = gsi_start_bb (seq_start_bb);
1e8e9920 9842
bc7bff74 9843 tree startvar = fd->loop.v;
9844 tree endvar = NULL_TREE;
9845
9846 if (gimple_omp_for_combined_p (fd->for_stmt))
9847 {
9848 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
9849 ? gimple_omp_parallel_clauses (inner_stmt)
9850 : gimple_omp_for_clauses (inner_stmt);
9851 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
9852 gcc_assert (innerc);
9853 startvar = OMP_CLAUSE_DECL (innerc);
9854 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9855 OMP_CLAUSE__LOOPTEMP_);
9856 gcc_assert (innerc);
9857 endvar = OMP_CLAUSE_DECL (innerc);
9561765e 9858 if (fd->collapse > 1 && TREE_CODE (fd->loop.n2) != INTEGER_CST
9859 && gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
9860 {
9861 int i;
9862 for (i = 1; i < fd->collapse; i++)
9863 {
9864 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9865 OMP_CLAUSE__LOOPTEMP_);
9866 gcc_assert (innerc);
9867 }
9868 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9869 OMP_CLAUSE__LOOPTEMP_);
9870 if (innerc)
9871 {
9872 /* If needed (distribute parallel for with lastprivate),
9873 propagate down the total number of iterations. */
9874 tree t = fold_convert (TREE_TYPE (OMP_CLAUSE_DECL (innerc)),
9875 fd->loop.n2);
9876 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, false,
9877 GSI_CONTINUE_LINKING);
9878 assign_stmt = gimple_build_assign (OMP_CLAUSE_DECL (innerc), t);
9879 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9880 }
9881 }
bc7bff74 9882 }
9883
fd6481cf 9884 t = fold_convert (itype, s0);
bc7bff74 9885 t = fold_build2 (MULT_EXPR, itype, t, step);
fd6481cf 9886 if (POINTER_TYPE_P (type))
bc7bff74 9887 t = fold_build_pointer_plus (n1, t);
fd6481cf 9888 else
bc7bff74 9889 t = fold_build2 (PLUS_EXPR, type, t, n1);
9890 t = fold_convert (TREE_TYPE (startvar), t);
93481288 9891 t = force_gimple_operand_gsi (&gsi, t,
bc7bff74 9892 DECL_P (startvar)
9893 && TREE_ADDRESSABLE (startvar),
4abecb72 9894 NULL_TREE, false, GSI_CONTINUE_LINKING);
1a91d914 9895 assign_stmt = gimple_build_assign (startvar, t);
9896 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
1e8e9920 9897
fd6481cf 9898 t = fold_convert (itype, e0);
bc7bff74 9899 t = fold_build2 (MULT_EXPR, itype, t, step);
fd6481cf 9900 if (POINTER_TYPE_P (type))
bc7bff74 9901 t = fold_build_pointer_plus (n1, t);
fd6481cf 9902 else
bc7bff74 9903 t = fold_build2 (PLUS_EXPR, type, t, n1);
9904 t = fold_convert (TREE_TYPE (startvar), t);
93481288 9905 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
75a70cf9 9906 false, GSI_CONTINUE_LINKING);
bc7bff74 9907 if (endvar)
9908 {
1a91d914 9909 assign_stmt = gimple_build_assign (endvar, e);
9910 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
d44f2f7c 9911 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
1a91d914 9912 assign_stmt = gimple_build_assign (fd->loop.v, e);
d44f2f7c 9913 else
e9cf809e 9914 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
1a91d914 9915 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
bc7bff74 9916 }
43895be5 9917 /* Handle linear clause adjustments. */
9918 tree itercnt = NULL_TREE, itercntbias = NULL_TREE;
9919 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_FOR)
9920 for (tree c = gimple_omp_for_clauses (fd->for_stmt);
9921 c; c = OMP_CLAUSE_CHAIN (c))
9922 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
9923 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
9924 {
9925 tree d = OMP_CLAUSE_DECL (c);
9926 bool is_ref = is_reference (d);
9927 tree t = d, a, dest;
9928 if (is_ref)
9929 t = build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c), t);
9930 tree type = TREE_TYPE (t);
9931 if (POINTER_TYPE_P (type))
9932 type = sizetype;
9933 dest = unshare_expr (t);
9934 tree v = create_tmp_var (TREE_TYPE (t), NULL);
9935 expand_omp_build_assign (&gsif, v, t);
9936 if (itercnt == NULL_TREE)
9937 {
9938 if (gimple_omp_for_combined_into_p (fd->for_stmt))
9939 {
9940 itercntbias
9941 = fold_build2 (MINUS_EXPR, itype, fold_convert (itype, n1),
9942 fold_convert (itype, fd->loop.n1));
9943 itercntbias = fold_build2 (EXACT_DIV_EXPR, itype,
9944 itercntbias, step);
9945 itercntbias
9946 = force_gimple_operand_gsi (&gsif, itercntbias, true,
9947 NULL_TREE, true,
9948 GSI_SAME_STMT);
9949 itercnt = fold_build2 (PLUS_EXPR, itype, itercntbias, s0);
9950 itercnt = force_gimple_operand_gsi (&gsi, itercnt, true,
9951 NULL_TREE, false,
9952 GSI_CONTINUE_LINKING);
9953 }
9954 else
9955 itercnt = s0;
9956 }
9957 a = fold_build2 (MULT_EXPR, type,
9958 fold_convert (type, itercnt),
9959 fold_convert (type, OMP_CLAUSE_LINEAR_STEP (c)));
9960 t = fold_build2 (type == TREE_TYPE (t) ? PLUS_EXPR
9961 : POINTER_PLUS_EXPR, TREE_TYPE (t), v, a);
9962 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9963 false, GSI_CONTINUE_LINKING);
9964 assign_stmt = gimple_build_assign (dest, t);
9965 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9966 }
bc7bff74 9967 if (fd->collapse > 1)
93481288 9968 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
bc7bff74 9969
9970 if (!broken_loop)
9971 {
9972 /* The code controlling the sequential loop goes in CONT_BB,
9973 replacing the GIMPLE_OMP_CONTINUE. */
93481288 9974 gsi = gsi_last_bb (cont_bb);
1a91d914 9975 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
9976 vmain = gimple_omp_continue_control_use (cont_stmt);
9977 vback = gimple_omp_continue_control_def (cont_stmt);
1e8e9920 9978
bc7bff74 9979 if (!gimple_omp_for_combined_p (fd->for_stmt))
9980 {
9981 if (POINTER_TYPE_P (type))
93481288 9982 t = fold_build_pointer_plus (vmain, step);
bc7bff74 9983 else
93481288 9984 t = fold_build2 (PLUS_EXPR, type, vmain, step);
9985 if (DECL_P (vback) && TREE_ADDRESSABLE (vback))
9986 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
bc7bff74 9987 true, GSI_SAME_STMT);
1a91d914 9988 assign_stmt = gimple_build_assign (vback, t);
9989 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
79acaae1 9990
345f9789 9991 if (tree_int_cst_equal (fd->chunk_size, integer_one_node))
9992 t = build2 (EQ_EXPR, boolean_type_node,
9993 build_int_cst (itype, 0),
9994 build_int_cst (itype, 1));
9995 else
9996 t = build2 (fd->loop.cond_code, boolean_type_node,
9997 DECL_P (vback) && TREE_ADDRESSABLE (vback)
9998 ? t : vback, e);
93481288 9999 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
bc7bff74 10000 }
79acaae1 10001
bc7bff74 10002 /* Remove GIMPLE_OMP_CONTINUE. */
93481288 10003 gsi_remove (&gsi, true);
48e1416a 10004
bc7bff74 10005 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
10006 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
773c5ba7 10007
bc7bff74 10008 /* Trip update code goes into TRIP_UPDATE_BB. */
93481288 10009 gsi = gsi_start_bb (trip_update_bb);
1e8e9920 10010
bc7bff74 10011 t = build_int_cst (itype, 1);
10012 t = build2 (PLUS_EXPR, itype, trip_main, t);
1a91d914 10013 assign_stmt = gimple_build_assign (trip_back, t);
10014 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
bc7bff74 10015 }
1e8e9920 10016
75a70cf9 10017 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
93481288 10018 gsi = gsi_last_bb (exit_bb);
10019 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
bc7bff74 10020 {
93481288 10021 t = gimple_omp_return_lhs (gsi_stmt (gsi));
a8e785ba 10022 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
bc7bff74 10023 }
93481288 10024 gsi_remove (&gsi, true);
1e8e9920 10025
773c5ba7 10026 /* Connect the new blocks. */
ac6e3339 10027 find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
10028 find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
79acaae1 10029
bc7bff74 10030 if (!broken_loop)
10031 {
10032 se = find_edge (cont_bb, body_bb);
fc1d58e3 10033 if (se == NULL)
10034 {
10035 se = BRANCH_EDGE (cont_bb);
10036 gcc_assert (single_succ (se->dest) == body_bb);
10037 }
bc7bff74 10038 if (gimple_omp_for_combined_p (fd->for_stmt))
10039 {
10040 remove_edge (se);
10041 se = NULL;
10042 }
10043 else if (fd->collapse > 1)
10044 {
10045 remove_edge (se);
10046 se = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
10047 }
10048 else
10049 se->flags = EDGE_TRUE_VALUE;
10050 find_edge (cont_bb, trip_update_bb)->flags
10051 = se ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
79acaae1 10052
bc7bff74 10053 redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb);
10054 }
79acaae1 10055
10056 if (gimple_in_ssa_p (cfun))
10057 {
1a91d914 10058 gphi_iterator psi;
10059 gphi *phi;
75a70cf9 10060 edge re, ene;
75a70cf9 10061 edge_var_map *vm;
10062 size_t i;
10063
bc7bff74 10064 gcc_assert (fd->collapse == 1 && !broken_loop);
10065
79acaae1 10066 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
10067 remove arguments of the phi nodes in fin_bb. We need to create
10068 appropriate phi nodes in iter_part_bb instead. */
264aa959 10069 se = find_edge (iter_part_bb, fin_bb);
79acaae1 10070 re = single_succ_edge (trip_update_bb);
06ecf488 10071 vec<edge_var_map> *head = redirect_edge_var_map_vector (re);
79acaae1 10072 ene = single_succ_edge (entry_bb);
10073
75a70cf9 10074 psi = gsi_start_phis (fin_bb);
f1f41a6c 10075 for (i = 0; !gsi_end_p (psi) && head->iterate (i, &vm);
75a70cf9 10076 gsi_next (&psi), ++i)
79acaae1 10077 {
1a91d914 10078 gphi *nphi;
efbcb6de 10079 source_location locus;
75a70cf9 10080
1a91d914 10081 phi = psi.phi ();
75a70cf9 10082 t = gimple_phi_result (phi);
10083 gcc_assert (t == redirect_edge_var_map_result (vm));
264aa959 10084
10085 if (!single_pred_p (fin_bb))
10086 t = copy_ssa_name (t, phi);
10087
79acaae1 10088 nphi = create_phi_node (t, iter_part_bb);
79acaae1 10089
10090 t = PHI_ARG_DEF_FROM_EDGE (phi, se);
efbcb6de 10091 locus = gimple_phi_arg_location_from_edge (phi, se);
10092
fd6481cf 10093 /* A special case -- fd->loop.v is not yet computed in
93481288 10094 iter_part_bb, we need to use vextra instead. */
fd6481cf 10095 if (t == fd->loop.v)
93481288 10096 t = vextra;
60d535d2 10097 add_phi_arg (nphi, t, ene, locus);
efbcb6de 10098 locus = redirect_edge_var_map_location (vm);
281001a9 10099 tree back_arg = redirect_edge_var_map_def (vm);
10100 add_phi_arg (nphi, back_arg, re, locus);
10101 edge ce = find_edge (cont_bb, body_bb);
10102 if (ce == NULL)
10103 {
10104 ce = BRANCH_EDGE (cont_bb);
10105 gcc_assert (single_succ (ce->dest) == body_bb);
10106 ce = single_succ_edge (ce->dest);
10107 }
10108 gphi *inner_loop_phi = find_phi_with_arg_on_edge (back_arg, ce);
10109 gcc_assert (inner_loop_phi != NULL);
10110 add_phi_arg (inner_loop_phi, gimple_phi_result (nphi),
10111 find_edge (seq_start_bb, body_bb), locus);
264aa959 10112
10113 if (!single_pred_p (fin_bb))
10114 add_phi_arg (phi, gimple_phi_result (nphi), se, locus);
75a70cf9 10115 }
4d556e29 10116 gcc_assert (gsi_end_p (psi) && (head == NULL || i == head->length ()));
75a70cf9 10117 redirect_edge_var_map_clear (re);
264aa959 10118 if (single_pred_p (fin_bb))
10119 while (1)
10120 {
10121 psi = gsi_start_phis (fin_bb);
10122 if (gsi_end_p (psi))
10123 break;
10124 remove_phi_node (&psi, false);
10125 }
79acaae1 10126
10127 /* Make phi node for trip. */
10128 phi = create_phi_node (trip_main, iter_part_bb);
efbcb6de 10129 add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb),
60d535d2 10130 UNKNOWN_LOCATION);
efbcb6de 10131 add_phi_arg (phi, trip_init, single_succ_edge (entry_bb),
60d535d2 10132 UNKNOWN_LOCATION);
79acaae1 10133 }
10134
bc7bff74 10135 if (!broken_loop)
10136 set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
79acaae1 10137 set_immediate_dominator (CDI_DOMINATORS, iter_part_bb,
10138 recompute_dominator (CDI_DOMINATORS, iter_part_bb));
10139 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
10140 recompute_dominator (CDI_DOMINATORS, fin_bb));
10141 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb,
10142 recompute_dominator (CDI_DOMINATORS, seq_start_bb));
10143 set_immediate_dominator (CDI_DOMINATORS, body_bb,
10144 recompute_dominator (CDI_DOMINATORS, body_bb));
04c2922b 10145
bc7bff74 10146 if (!broken_loop)
10147 {
fc1d58e3 10148 struct loop *loop = body_bb->loop_father;
bc7bff74 10149 struct loop *trip_loop = alloc_loop ();
10150 trip_loop->header = iter_part_bb;
10151 trip_loop->latch = trip_update_bb;
10152 add_loop (trip_loop, iter_part_bb->loop_father);
04c2922b 10153
fc1d58e3 10154 if (loop != entry_bb->loop_father)
10155 {
10156 gcc_assert (loop->header == body_bb);
10157 gcc_assert (loop->latch == region->cont
10158 || single_pred (loop->latch) == region->cont);
10159 trip_loop->inner = loop;
10160 return;
10161 }
10162
bc7bff74 10163 if (!gimple_omp_for_combined_p (fd->for_stmt))
10164 {
fc1d58e3 10165 loop = alloc_loop ();
bc7bff74 10166 loop->header = body_bb;
33ee4d72 10167 if (collapse_bb == NULL)
10168 loop->latch = cont_bb;
bc7bff74 10169 add_loop (loop, trip_loop);
10170 }
10171 }
1e8e9920 10172}
10173
40750995 10174/* A subroutine of expand_omp_for. Generate code for _Cilk_for loop.
10175 Given parameters:
10176 for (V = N1; V cond N2; V += STEP) BODY;
10177
10178 where COND is "<" or ">" or "!=", we generate pseudocode
10179
10180 for (ind_var = low; ind_var < high; ind_var++)
10181 {
10182 V = n1 + (ind_var * STEP)
10183
10184 <BODY>
10185 }
10186
10187 In the above pseudocode, low and high are function parameters of the
10188 child function. In the function below, we are inserting a temp.
10189 variable that will be making a call to two OMP functions that will not be
10190 found in the body of _Cilk_for (since OMP_FOR cannot be mixed
10191 with _Cilk_for). These functions are replaced with low and high
10192 by the function that handles taskreg. */
10193
10194
10195static void
10196expand_cilk_for (struct omp_region *region, struct omp_for_data *fd)
10197{
10198 bool broken_loop = region->cont == NULL;
10199 basic_block entry_bb = region->entry;
10200 basic_block cont_bb = region->cont;
10201
10202 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
10203 gcc_assert (broken_loop
10204 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
10205 basic_block l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
10206 basic_block l1_bb, l2_bb;
10207
10208 if (!broken_loop)
10209 {
10210 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
10211 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
10212 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
10213 l2_bb = BRANCH_EDGE (entry_bb)->dest;
10214 }
10215 else
10216 {
10217 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
10218 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
10219 l2_bb = single_succ (l1_bb);
10220 }
10221 basic_block exit_bb = region->exit;
10222 basic_block l2_dom_bb = NULL;
10223
10224 gimple_stmt_iterator gsi = gsi_last_bb (entry_bb);
10225
10226 /* Below statements until the "tree high_val = ..." are pseudo statements
10227 used to pass information to be used by expand_omp_taskreg.
10228 low_val and high_val will be replaced by the __low and __high
10229 parameter from the child function.
10230
10231 The call_exprs part is a place-holder, it is mainly used
10232 to distinctly identify to the top-level part that this is
10233 where we should put low and high (reasoning given in header
10234 comment). */
10235
10236 tree child_fndecl
1a91d914 10237 = gimple_omp_parallel_child_fn (
10238 as_a <gomp_parallel *> (last_stmt (region->outer->entry)));
40750995 10239 tree t, low_val = NULL_TREE, high_val = NULL_TREE;
10240 for (t = DECL_ARGUMENTS (child_fndecl); t; t = TREE_CHAIN (t))
10241 {
10242 if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__high"))
10243 high_val = t;
10244 else if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__low"))
10245 low_val = t;
10246 }
10247 gcc_assert (low_val && high_val);
10248
10249 tree type = TREE_TYPE (low_val);
10250 tree ind_var = create_tmp_reg (type, "__cilk_ind_var");
10251 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
10252
10253 /* Not needed in SSA form right now. */
10254 gcc_assert (!gimple_in_ssa_p (cfun));
10255 if (l2_dom_bb == NULL)
10256 l2_dom_bb = l1_bb;
10257
10258 tree n1 = low_val;
10259 tree n2 = high_val;
10260
42acab1c 10261 gimple *stmt = gimple_build_assign (ind_var, n1);
40750995 10262
10263 /* Replace the GIMPLE_OMP_FOR statement. */
10264 gsi_replace (&gsi, stmt, true);
10265
10266 if (!broken_loop)
10267 {
10268 /* Code to control the increment goes in the CONT_BB. */
10269 gsi = gsi_last_bb (cont_bb);
10270 stmt = gsi_stmt (gsi);
10271 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
e9cf809e 10272 stmt = gimple_build_assign (ind_var, PLUS_EXPR, ind_var,
10273 build_one_cst (type));
40750995 10274
10275 /* Replace GIMPLE_OMP_CONTINUE. */
10276 gsi_replace (&gsi, stmt, true);
10277 }
10278
10279 /* Emit the condition in L1_BB. */
10280 gsi = gsi_after_labels (l1_bb);
10281 t = fold_build2 (MULT_EXPR, TREE_TYPE (fd->loop.step),
10282 fold_convert (TREE_TYPE (fd->loop.step), ind_var),
10283 fd->loop.step);
10284 if (POINTER_TYPE_P (TREE_TYPE (fd->loop.n1)))
10285 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (fd->loop.n1),
10286 fd->loop.n1, fold_convert (sizetype, t));
10287 else
10288 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loop.n1),
10289 fd->loop.n1, fold_convert (TREE_TYPE (fd->loop.n1), t));
10290 t = fold_convert (TREE_TYPE (fd->loop.v), t);
10291 expand_omp_build_assign (&gsi, fd->loop.v, t);
10292
10293 /* The condition is always '<' since the runtime will fill in the low
10294 and high values. */
10295 stmt = gimple_build_cond (LT_EXPR, ind_var, n2, NULL_TREE, NULL_TREE);
10296 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
10297
10298 /* Remove GIMPLE_OMP_RETURN. */
10299 gsi = gsi_last_bb (exit_bb);
10300 gsi_remove (&gsi, true);
10301
10302 /* Connect the new blocks. */
10303 remove_edge (FALLTHRU_EDGE (entry_bb));
10304
10305 edge e, ne;
10306 if (!broken_loop)
10307 {
10308 remove_edge (BRANCH_EDGE (entry_bb));
10309 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
10310
10311 e = BRANCH_EDGE (l1_bb);
10312 ne = FALLTHRU_EDGE (l1_bb);
10313 e->flags = EDGE_TRUE_VALUE;
10314 }
10315 else
10316 {
10317 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
10318
10319 ne = single_succ_edge (l1_bb);
10320 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
10321
10322 }
10323 ne->flags = EDGE_FALSE_VALUE;
10324 e->probability = REG_BR_PROB_BASE * 7 / 8;
10325 ne->probability = REG_BR_PROB_BASE / 8;
10326
10327 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
10328 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
10329 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
10330
10331 if (!broken_loop)
10332 {
10333 struct loop *loop = alloc_loop ();
10334 loop->header = l1_bb;
10335 loop->latch = cont_bb;
10336 add_loop (loop, l1_bb->loop_father);
10337 loop->safelen = INT_MAX;
10338 }
10339
10340 /* Pick the correct library function based on the precision of the
10341 induction variable type. */
10342 tree lib_fun = NULL_TREE;
10343 if (TYPE_PRECISION (type) == 32)
10344 lib_fun = cilk_for_32_fndecl;
10345 else if (TYPE_PRECISION (type) == 64)
10346 lib_fun = cilk_for_64_fndecl;
10347 else
10348 gcc_unreachable ();
10349
10350 gcc_assert (fd->sched_kind == OMP_CLAUSE_SCHEDULE_CILKFOR);
10351
10352 /* WS_ARGS contains the library function flavor to call:
10353 __libcilkrts_cilk_for_64 or __libcilkrts_cilk_for_32), and the
10354 user-defined grain value. If the user does not define one, then zero
10355 is passed in by the parser. */
10356 vec_alloc (region->ws_args, 2);
10357 region->ws_args->quick_push (lib_fun);
10358 region->ws_args->quick_push (fd->chunk_size);
10359}
bc7bff74 10360
3d483a94 10361/* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
10362 loop. Given parameters:
10363
10364 for (V = N1; V cond N2; V += STEP) BODY;
10365
10366 where COND is "<" or ">", we generate pseudocode
10367
10368 V = N1;
10369 goto L1;
10370 L0:
10371 BODY;
10372 V += STEP;
10373 L1:
10374 if (V cond N2) goto L0; else goto L2;
10375 L2:
10376
10377 For collapsed loops, given parameters:
10378 collapse(3)
10379 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
10380 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
10381 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
10382 BODY;
10383
10384 we generate pseudocode
10385
10386 if (cond3 is <)
10387 adj = STEP3 - 1;
10388 else
10389 adj = STEP3 + 1;
10390 count3 = (adj + N32 - N31) / STEP3;
10391 if (cond2 is <)
10392 adj = STEP2 - 1;
10393 else
10394 adj = STEP2 + 1;
10395 count2 = (adj + N22 - N21) / STEP2;
10396 if (cond1 is <)
10397 adj = STEP1 - 1;
10398 else
10399 adj = STEP1 + 1;
10400 count1 = (adj + N12 - N11) / STEP1;
10401 count = count1 * count2 * count3;
10402 V = 0;
10403 V1 = N11;
10404 V2 = N21;
10405 V3 = N31;
10406 goto L1;
10407 L0:
10408 BODY;
10409 V += 1;
10410 V3 += STEP3;
10411 V2 += (V3 cond3 N32) ? 0 : STEP2;
10412 V3 = (V3 cond3 N32) ? V3 : N31;
10413 V1 += (V2 cond2 N22) ? 0 : STEP1;
10414 V2 = (V2 cond2 N22) ? V2 : N21;
10415 L1:
10416 if (V < count) goto L0; else goto L2;
10417 L2:
10418
10419 */
10420
10421static void
10422expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
10423{
10424 tree type, t;
10425 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, l2_bb, l2_dom_bb;
10426 gimple_stmt_iterator gsi;
42acab1c 10427 gimple *stmt;
1a91d914 10428 gcond *cond_stmt;
3d483a94 10429 bool broken_loop = region->cont == NULL;
10430 edge e, ne;
10431 tree *counts = NULL;
10432 int i;
10433 tree safelen = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
10434 OMP_CLAUSE_SAFELEN);
10435 tree simduid = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
10436 OMP_CLAUSE__SIMDUID_);
bc7bff74 10437 tree n1, n2;
3d483a94 10438
10439 type = TREE_TYPE (fd->loop.v);
10440 entry_bb = region->entry;
10441 cont_bb = region->cont;
10442 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
10443 gcc_assert (broken_loop
10444 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
10445 l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
10446 if (!broken_loop)
10447 {
10448 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
10449 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
10450 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
10451 l2_bb = BRANCH_EDGE (entry_bb)->dest;
10452 }
10453 else
10454 {
10455 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
10456 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
10457 l2_bb = single_succ (l1_bb);
10458 }
10459 exit_bb = region->exit;
10460 l2_dom_bb = NULL;
10461
10462 gsi = gsi_last_bb (entry_bb);
10463
10464 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
10465 /* Not needed in SSA form right now. */
10466 gcc_assert (!gimple_in_ssa_p (cfun));
10467 if (fd->collapse > 1)
10468 {
43895be5 10469 int first_zero_iter = -1, dummy = -1;
10470 basic_block zero_iter_bb = l2_bb, dummy_bb = NULL;
3d483a94 10471
10472 counts = XALLOCAVEC (tree, fd->collapse);
10473 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
10474 zero_iter_bb, first_zero_iter,
43895be5 10475 dummy_bb, dummy, l2_dom_bb);
3d483a94 10476 }
10477 if (l2_dom_bb == NULL)
10478 l2_dom_bb = l1_bb;
10479
bc7bff74 10480 n1 = fd->loop.n1;
3d483a94 10481 n2 = fd->loop.n2;
bc7bff74 10482 if (gimple_omp_for_combined_into_p (fd->for_stmt))
10483 {
10484 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
10485 OMP_CLAUSE__LOOPTEMP_);
10486 gcc_assert (innerc);
10487 n1 = OMP_CLAUSE_DECL (innerc);
10488 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
10489 OMP_CLAUSE__LOOPTEMP_);
10490 gcc_assert (innerc);
10491 n2 = OMP_CLAUSE_DECL (innerc);
10492 expand_omp_build_assign (&gsi, fd->loop.v,
10493 fold_convert (type, n1));
10494 if (fd->collapse > 1)
10495 {
10496 gsi_prev (&gsi);
10497 expand_omp_for_init_vars (fd, &gsi, counts, NULL, n1);
10498 gsi_next (&gsi);
10499 }
10500 }
3d483a94 10501 else
10502 {
10503 expand_omp_build_assign (&gsi, fd->loop.v,
10504 fold_convert (type, fd->loop.n1));
10505 if (fd->collapse > 1)
10506 for (i = 0; i < fd->collapse; i++)
10507 {
10508 tree itype = TREE_TYPE (fd->loops[i].v);
10509 if (POINTER_TYPE_P (itype))
10510 itype = signed_type_for (itype);
10511 t = fold_convert (TREE_TYPE (fd->loops[i].v), fd->loops[i].n1);
10512 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
10513 }
10514 }
10515
10516 /* Remove the GIMPLE_OMP_FOR statement. */
10517 gsi_remove (&gsi, true);
10518
10519 if (!broken_loop)
10520 {
10521 /* Code to control the increment goes in the CONT_BB. */
10522 gsi = gsi_last_bb (cont_bb);
10523 stmt = gsi_stmt (gsi);
10524 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
10525
10526 if (POINTER_TYPE_P (type))
10527 t = fold_build_pointer_plus (fd->loop.v, fd->loop.step);
10528 else
10529 t = fold_build2 (PLUS_EXPR, type, fd->loop.v, fd->loop.step);
10530 expand_omp_build_assign (&gsi, fd->loop.v, t);
10531
10532 if (fd->collapse > 1)
10533 {
10534 i = fd->collapse - 1;
10535 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
10536 {
10537 t = fold_convert (sizetype, fd->loops[i].step);
10538 t = fold_build_pointer_plus (fd->loops[i].v, t);
10539 }
10540 else
10541 {
10542 t = fold_convert (TREE_TYPE (fd->loops[i].v),
10543 fd->loops[i].step);
10544 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
10545 fd->loops[i].v, t);
10546 }
10547 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
10548
10549 for (i = fd->collapse - 1; i > 0; i--)
10550 {
10551 tree itype = TREE_TYPE (fd->loops[i].v);
10552 tree itype2 = TREE_TYPE (fd->loops[i - 1].v);
10553 if (POINTER_TYPE_P (itype2))
10554 itype2 = signed_type_for (itype2);
10555 t = build3 (COND_EXPR, itype2,
10556 build2 (fd->loops[i].cond_code, boolean_type_node,
10557 fd->loops[i].v,
10558 fold_convert (itype, fd->loops[i].n2)),
10559 build_int_cst (itype2, 0),
10560 fold_convert (itype2, fd->loops[i - 1].step));
10561 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i - 1].v)))
10562 t = fold_build_pointer_plus (fd->loops[i - 1].v, t);
10563 else
10564 t = fold_build2 (PLUS_EXPR, itype2, fd->loops[i - 1].v, t);
10565 expand_omp_build_assign (&gsi, fd->loops[i - 1].v, t);
10566
10567 t = build3 (COND_EXPR, itype,
10568 build2 (fd->loops[i].cond_code, boolean_type_node,
10569 fd->loops[i].v,
10570 fold_convert (itype, fd->loops[i].n2)),
10571 fd->loops[i].v,
10572 fold_convert (itype, fd->loops[i].n1));
10573 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
10574 }
10575 }
10576
10577 /* Remove GIMPLE_OMP_CONTINUE. */
10578 gsi_remove (&gsi, true);
10579 }
10580
10581 /* Emit the condition in L1_BB. */
10582 gsi = gsi_start_bb (l1_bb);
10583
10584 t = fold_convert (type, n2);
10585 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
10586 false, GSI_CONTINUE_LINKING);
43895be5 10587 tree v = fd->loop.v;
10588 if (DECL_P (v) && TREE_ADDRESSABLE (v))
10589 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
10590 false, GSI_CONTINUE_LINKING);
10591 t = build2 (fd->loop.cond_code, boolean_type_node, v, t);
1a91d914 10592 cond_stmt = gimple_build_cond_empty (t);
10593 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
10594 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt), expand_omp_regimplify_p,
3d483a94 10595 NULL, NULL)
1a91d914 10596 || walk_tree (gimple_cond_rhs_ptr (cond_stmt), expand_omp_regimplify_p,
3d483a94 10597 NULL, NULL))
10598 {
1a91d914 10599 gsi = gsi_for_stmt (cond_stmt);
10600 gimple_regimplify_operands (cond_stmt, &gsi);
3d483a94 10601 }
10602
10603 /* Remove GIMPLE_OMP_RETURN. */
10604 gsi = gsi_last_bb (exit_bb);
10605 gsi_remove (&gsi, true);
10606
10607 /* Connect the new blocks. */
10608 remove_edge (FALLTHRU_EDGE (entry_bb));
10609
10610 if (!broken_loop)
10611 {
10612 remove_edge (BRANCH_EDGE (entry_bb));
10613 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
10614
10615 e = BRANCH_EDGE (l1_bb);
10616 ne = FALLTHRU_EDGE (l1_bb);
10617 e->flags = EDGE_TRUE_VALUE;
10618 }
10619 else
10620 {
10621 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
10622
10623 ne = single_succ_edge (l1_bb);
10624 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
10625
10626 }
10627 ne->flags = EDGE_FALSE_VALUE;
10628 e->probability = REG_BR_PROB_BASE * 7 / 8;
10629 ne->probability = REG_BR_PROB_BASE / 8;
10630
10631 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
10632 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
10633 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
10634
10635 if (!broken_loop)
10636 {
10637 struct loop *loop = alloc_loop ();
10638 loop->header = l1_bb;
33ee4d72 10639 loop->latch = cont_bb;
3d483a94 10640 add_loop (loop, l1_bb->loop_father);
10641 if (safelen == NULL_TREE)
10642 loop->safelen = INT_MAX;
10643 else
10644 {
10645 safelen = OMP_CLAUSE_SAFELEN_EXPR (safelen);
c3f3b68d 10646 if (TREE_CODE (safelen) != INTEGER_CST)
10647 loop->safelen = 0;
10648 else if (!tree_fits_uhwi_p (safelen)
10649 || tree_to_uhwi (safelen) > INT_MAX)
3d483a94 10650 loop->safelen = INT_MAX;
10651 else
d85a2013 10652 loop->safelen = tree_to_uhwi (safelen);
3d483a94 10653 if (loop->safelen == 1)
10654 loop->safelen = 0;
10655 }
10656 if (simduid)
10657 {
43895be5 10658 loop->simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
10659 cfun->has_simduid_loops = true;
10660 }
10661 /* If not -fno-tree-loop-vectorize, hint that we want to vectorize
10662 the loop. */
10663 if ((flag_tree_loop_vectorize
10664 || (!global_options_set.x_flag_tree_loop_vectorize
10665 && !global_options_set.x_flag_tree_vectorize))
10666 && flag_tree_loop_optimize
10667 && loop->safelen > 1)
10668 {
10669 loop->force_vectorize = true;
10670 cfun->has_force_vectorize_loops = true;
10671 }
10672 }
10673 else if (simduid)
10674 cfun->has_simduid_loops = true;
10675}
10676
10677/* Taskloop construct is represented after gimplification with
10678 two GIMPLE_OMP_FOR constructs with GIMPLE_OMP_TASK sandwiched
10679 in between them. This routine expands the outer GIMPLE_OMP_FOR,
10680 which should just compute all the needed loop temporaries
10681 for GIMPLE_OMP_TASK. */
10682
10683static void
10684expand_omp_taskloop_for_outer (struct omp_region *region,
10685 struct omp_for_data *fd,
10686 gimple *inner_stmt)
10687{
10688 tree type, bias = NULL_TREE;
10689 basic_block entry_bb, cont_bb, exit_bb;
10690 gimple_stmt_iterator gsi;
10691 gassign *assign_stmt;
10692 tree *counts = NULL;
10693 int i;
10694
10695 gcc_assert (inner_stmt);
10696 gcc_assert (region->cont);
10697 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_TASK
10698 && gimple_omp_task_taskloop_p (inner_stmt));
10699 type = TREE_TYPE (fd->loop.v);
10700
10701 /* See if we need to bias by LLONG_MIN. */
10702 if (fd->iter_type == long_long_unsigned_type_node
10703 && TREE_CODE (type) == INTEGER_TYPE
10704 && !TYPE_UNSIGNED (type))
10705 {
10706 tree n1, n2;
10707
10708 if (fd->loop.cond_code == LT_EXPR)
10709 {
10710 n1 = fd->loop.n1;
10711 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
10712 }
10713 else
10714 {
10715 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
10716 n2 = fd->loop.n1;
10717 }
10718 if (TREE_CODE (n1) != INTEGER_CST
10719 || TREE_CODE (n2) != INTEGER_CST
10720 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
10721 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
10722 }
10723
10724 entry_bb = region->entry;
10725 cont_bb = region->cont;
10726 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
10727 gcc_assert (BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
10728 exit_bb = region->exit;
10729
10730 gsi = gsi_last_bb (entry_bb);
10731 gimple *for_stmt = gsi_stmt (gsi);
10732 gcc_assert (gimple_code (for_stmt) == GIMPLE_OMP_FOR);
10733 if (fd->collapse > 1)
10734 {
10735 int first_zero_iter = -1, dummy = -1;
10736 basic_block zero_iter_bb = NULL, dummy_bb = NULL, l2_dom_bb = NULL;
10737
10738 counts = XALLOCAVEC (tree, fd->collapse);
10739 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
10740 zero_iter_bb, first_zero_iter,
10741 dummy_bb, dummy, l2_dom_bb);
10742
10743 if (zero_iter_bb)
10744 {
10745 /* Some counts[i] vars might be uninitialized if
10746 some loop has zero iterations. But the body shouldn't
10747 be executed in that case, so just avoid uninit warnings. */
10748 for (i = first_zero_iter; i < fd->collapse; i++)
10749 if (SSA_VAR_P (counts[i]))
10750 TREE_NO_WARNING (counts[i]) = 1;
10751 gsi_prev (&gsi);
10752 edge e = split_block (entry_bb, gsi_stmt (gsi));
10753 entry_bb = e->dest;
10754 make_edge (zero_iter_bb, entry_bb, EDGE_FALLTHRU);
10755 gsi = gsi_last_bb (entry_bb);
10756 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
10757 get_immediate_dominator (CDI_DOMINATORS,
10758 zero_iter_bb));
10759 }
10760 }
10761
10762 tree t0, t1;
10763 t1 = fd->loop.n2;
10764 t0 = fd->loop.n1;
10765 if (POINTER_TYPE_P (TREE_TYPE (t0))
10766 && TYPE_PRECISION (TREE_TYPE (t0))
10767 != TYPE_PRECISION (fd->iter_type))
10768 {
10769 /* Avoid casting pointers to integer of a different size. */
10770 tree itype = signed_type_for (type);
10771 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
10772 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
10773 }
10774 else
10775 {
10776 t1 = fold_convert (fd->iter_type, t1);
10777 t0 = fold_convert (fd->iter_type, t0);
10778 }
10779 if (bias)
10780 {
10781 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
10782 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
10783 }
10784
10785 tree innerc = find_omp_clause (gimple_omp_task_clauses (inner_stmt),
10786 OMP_CLAUSE__LOOPTEMP_);
10787 gcc_assert (innerc);
10788 tree startvar = OMP_CLAUSE_DECL (innerc);
10789 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc), OMP_CLAUSE__LOOPTEMP_);
10790 gcc_assert (innerc);
10791 tree endvar = OMP_CLAUSE_DECL (innerc);
10792 if (fd->collapse > 1 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
10793 {
10794 gcc_assert (innerc);
10795 for (i = 1; i < fd->collapse; i++)
10796 {
10797 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
10798 OMP_CLAUSE__LOOPTEMP_);
10799 gcc_assert (innerc);
10800 }
10801 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
10802 OMP_CLAUSE__LOOPTEMP_);
10803 if (innerc)
10804 {
10805 /* If needed (inner taskloop has lastprivate clause), propagate
10806 down the total number of iterations. */
10807 tree t = force_gimple_operand_gsi (&gsi, fd->loop.n2, false,
10808 NULL_TREE, false,
10809 GSI_CONTINUE_LINKING);
10810 assign_stmt = gimple_build_assign (OMP_CLAUSE_DECL (innerc), t);
10811 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10812 }
10813 }
10814
10815 t0 = force_gimple_operand_gsi (&gsi, t0, false, NULL_TREE, false,
10816 GSI_CONTINUE_LINKING);
10817 assign_stmt = gimple_build_assign (startvar, t0);
10818 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10819
10820 t1 = force_gimple_operand_gsi (&gsi, t1, false, NULL_TREE, false,
10821 GSI_CONTINUE_LINKING);
10822 assign_stmt = gimple_build_assign (endvar, t1);
10823 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10824 if (fd->collapse > 1)
10825 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
10826
10827 /* Remove the GIMPLE_OMP_FOR statement. */
10828 gsi = gsi_for_stmt (for_stmt);
10829 gsi_remove (&gsi, true);
10830
10831 gsi = gsi_last_bb (cont_bb);
10832 gsi_remove (&gsi, true);
10833
10834 gsi = gsi_last_bb (exit_bb);
10835 gsi_remove (&gsi, true);
10836
10837 FALLTHRU_EDGE (entry_bb)->probability = REG_BR_PROB_BASE;
10838 remove_edge (BRANCH_EDGE (entry_bb));
10839 FALLTHRU_EDGE (cont_bb)->probability = REG_BR_PROB_BASE;
10840 remove_edge (BRANCH_EDGE (cont_bb));
10841 set_immediate_dominator (CDI_DOMINATORS, exit_bb, cont_bb);
10842 set_immediate_dominator (CDI_DOMINATORS, region->entry,
10843 recompute_dominator (CDI_DOMINATORS, region->entry));
10844}
10845
10846/* Taskloop construct is represented after gimplification with
10847 two GIMPLE_OMP_FOR constructs with GIMPLE_OMP_TASK sandwiched
10848 in between them. This routine expands the inner GIMPLE_OMP_FOR.
10849 GOMP_taskloop{,_ull} function arranges for each task to be given just
10850 a single range of iterations. */
10851
10852static void
10853expand_omp_taskloop_for_inner (struct omp_region *region,
10854 struct omp_for_data *fd,
10855 gimple *inner_stmt)
10856{
10857 tree e, t, type, itype, vmain, vback, bias = NULL_TREE;
10858 basic_block entry_bb, exit_bb, body_bb, cont_bb, collapse_bb = NULL;
10859 basic_block fin_bb;
10860 gimple_stmt_iterator gsi;
10861 edge ep;
10862 bool broken_loop = region->cont == NULL;
10863 tree *counts = NULL;
10864 tree n1, n2, step;
10865
10866 itype = type = TREE_TYPE (fd->loop.v);
10867 if (POINTER_TYPE_P (type))
10868 itype = signed_type_for (type);
10869
10870 /* See if we need to bias by LLONG_MIN. */
10871 if (fd->iter_type == long_long_unsigned_type_node
10872 && TREE_CODE (type) == INTEGER_TYPE
10873 && !TYPE_UNSIGNED (type))
10874 {
10875 tree n1, n2;
10876
10877 if (fd->loop.cond_code == LT_EXPR)
10878 {
10879 n1 = fd->loop.n1;
10880 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
10881 }
10882 else
10883 {
10884 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
10885 n2 = fd->loop.n1;
10886 }
10887 if (TREE_CODE (n1) != INTEGER_CST
10888 || TREE_CODE (n2) != INTEGER_CST
10889 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
10890 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
10891 }
10892
10893 entry_bb = region->entry;
10894 cont_bb = region->cont;
10895 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
10896 fin_bb = BRANCH_EDGE (entry_bb)->dest;
10897 gcc_assert (broken_loop
10898 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
10899 body_bb = FALLTHRU_EDGE (entry_bb)->dest;
10900 if (!broken_loop)
10901 {
10902 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
10903 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
10904 }
10905 exit_bb = region->exit;
10906
10907 /* Iteration space partitioning goes in ENTRY_BB. */
10908 gsi = gsi_last_bb (entry_bb);
10909 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
10910
10911 if (fd->collapse > 1)
10912 {
10913 int first_zero_iter = -1, dummy = -1;
10914 basic_block l2_dom_bb = NULL, dummy_bb = NULL;
10915
10916 counts = XALLOCAVEC (tree, fd->collapse);
10917 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
10918 fin_bb, first_zero_iter,
10919 dummy_bb, dummy, l2_dom_bb);
10920 t = NULL_TREE;
10921 }
10922 else
10923 t = integer_one_node;
10924
10925 step = fd->loop.step;
10926 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
10927 OMP_CLAUSE__LOOPTEMP_);
10928 gcc_assert (innerc);
10929 n1 = OMP_CLAUSE_DECL (innerc);
10930 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc), OMP_CLAUSE__LOOPTEMP_);
10931 gcc_assert (innerc);
10932 n2 = OMP_CLAUSE_DECL (innerc);
10933 if (bias)
10934 {
10935 n1 = fold_build2 (PLUS_EXPR, fd->iter_type, n1, bias);
10936 n2 = fold_build2 (PLUS_EXPR, fd->iter_type, n2, bias);
10937 }
10938 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
10939 true, NULL_TREE, true, GSI_SAME_STMT);
10940 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
10941 true, NULL_TREE, true, GSI_SAME_STMT);
10942 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
10943 true, NULL_TREE, true, GSI_SAME_STMT);
10944
10945 tree startvar = fd->loop.v;
10946 tree endvar = NULL_TREE;
10947
10948 if (gimple_omp_for_combined_p (fd->for_stmt))
10949 {
10950 tree clauses = gimple_omp_for_clauses (inner_stmt);
10951 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
10952 gcc_assert (innerc);
10953 startvar = OMP_CLAUSE_DECL (innerc);
10954 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
10955 OMP_CLAUSE__LOOPTEMP_);
10956 gcc_assert (innerc);
10957 endvar = OMP_CLAUSE_DECL (innerc);
10958 }
10959 t = fold_convert (TREE_TYPE (startvar), n1);
10960 t = force_gimple_operand_gsi (&gsi, t,
10961 DECL_P (startvar)
10962 && TREE_ADDRESSABLE (startvar),
10963 NULL_TREE, false, GSI_CONTINUE_LINKING);
10964 gimple *assign_stmt = gimple_build_assign (startvar, t);
10965 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10966
10967 t = fold_convert (TREE_TYPE (startvar), n2);
10968 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
10969 false, GSI_CONTINUE_LINKING);
10970 if (endvar)
10971 {
10972 assign_stmt = gimple_build_assign (endvar, e);
10973 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10974 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
10975 assign_stmt = gimple_build_assign (fd->loop.v, e);
10976 else
10977 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
10978 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10979 }
10980 if (fd->collapse > 1)
10981 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
10982
10983 if (!broken_loop)
10984 {
10985 /* The code controlling the sequential loop replaces the
10986 GIMPLE_OMP_CONTINUE. */
10987 gsi = gsi_last_bb (cont_bb);
10988 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
10989 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
10990 vmain = gimple_omp_continue_control_use (cont_stmt);
10991 vback = gimple_omp_continue_control_def (cont_stmt);
10992
10993 if (!gimple_omp_for_combined_p (fd->for_stmt))
10994 {
10995 if (POINTER_TYPE_P (type))
10996 t = fold_build_pointer_plus (vmain, step);
10997 else
10998 t = fold_build2 (PLUS_EXPR, type, vmain, step);
10999 t = force_gimple_operand_gsi (&gsi, t,
11000 DECL_P (vback)
11001 && TREE_ADDRESSABLE (vback),
11002 NULL_TREE, true, GSI_SAME_STMT);
11003 assign_stmt = gimple_build_assign (vback, t);
11004 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
11005
11006 t = build2 (fd->loop.cond_code, boolean_type_node,
11007 DECL_P (vback) && TREE_ADDRESSABLE (vback)
11008 ? t : vback, e);
11009 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
11010 }
11011
11012 /* Remove the GIMPLE_OMP_CONTINUE statement. */
11013 gsi_remove (&gsi, true);
11014
11015 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
11016 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
11017 }
11018
11019 /* Remove the GIMPLE_OMP_FOR statement. */
11020 gsi = gsi_for_stmt (fd->for_stmt);
11021 gsi_remove (&gsi, true);
11022
11023 /* Remove the GIMPLE_OMP_RETURN statement. */
11024 gsi = gsi_last_bb (exit_bb);
11025 gsi_remove (&gsi, true);
11026
11027 FALLTHRU_EDGE (entry_bb)->probability = REG_BR_PROB_BASE;
11028 if (!broken_loop)
11029 remove_edge (BRANCH_EDGE (entry_bb));
11030 else
11031 {
11032 remove_edge_and_dominated_blocks (BRANCH_EDGE (entry_bb));
11033 region->outer->cont = NULL;
11034 }
11035
11036 /* Connect all the blocks. */
11037 if (!broken_loop)
11038 {
11039 ep = find_edge (cont_bb, body_bb);
11040 if (gimple_omp_for_combined_p (fd->for_stmt))
11041 {
11042 remove_edge (ep);
11043 ep = NULL;
3d483a94 11044 }
43895be5 11045 else if (fd->collapse > 1)
3d483a94 11046 {
43895be5 11047 remove_edge (ep);
11048 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
3d483a94 11049 }
43895be5 11050 else
11051 ep->flags = EDGE_TRUE_VALUE;
11052 find_edge (cont_bb, fin_bb)->flags
11053 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
3d483a94 11054 }
3d483a94 11055
43895be5 11056 set_immediate_dominator (CDI_DOMINATORS, body_bb,
11057 recompute_dominator (CDI_DOMINATORS, body_bb));
11058 if (!broken_loop)
11059 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
11060 recompute_dominator (CDI_DOMINATORS, fin_bb));
11061
11062 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
11063 {
11064 struct loop *loop = alloc_loop ();
11065 loop->header = body_bb;
11066 if (collapse_bb == NULL)
11067 loop->latch = cont_bb;
11068 add_loop (loop, body_bb->loop_father);
11069 }
11070}
1e8e9920 11071
a8e785ba 11072/* A subroutine of expand_omp_for. Generate code for an OpenACC
11073 partitioned loop. The lowering here is abstracted, in that the
11074 loop parameters are passed through internal functions, which are
11075 further lowered by oacc_device_lower, once we get to the target
11076 compiler. The loop is of the form:
11077
11078 for (V = B; V LTGT E; V += S) {BODY}
11079
11080 where LTGT is < or >. We may have a specified chunking size, CHUNKING
11081 (constant 0 for no chunking) and we will have a GWV partitioning
11082 mask, specifying dimensions over which the loop is to be
11083 partitioned (see note below). We generate code that looks like:
11084
11085 <entry_bb> [incoming FALL->body, BRANCH->exit]
11086 typedef signedintify (typeof (V)) T; // underlying signed integral type
11087 T range = E - B;
11088 T chunk_no = 0;
11089 T DIR = LTGT == '<' ? +1 : -1;
11090 T chunk_max = GOACC_LOOP_CHUNK (dir, range, S, CHUNK_SIZE, GWV);
11091 T step = GOACC_LOOP_STEP (dir, range, S, CHUNK_SIZE, GWV);
11092
11093 <head_bb> [created by splitting end of entry_bb]
11094 T offset = GOACC_LOOP_OFFSET (dir, range, S, CHUNK_SIZE, GWV, chunk_no);
11095 T bound = GOACC_LOOP_BOUND (dir, range, S, CHUNK_SIZE, GWV, offset);
11096 if (!(offset LTGT bound)) goto bottom_bb;
11097
11098 <body_bb> [incoming]
11099 V = B + offset;
11100 {BODY}
11101
11102 <cont_bb> [incoming, may == body_bb FALL->exit_bb, BRANCH->body_bb]
11103 offset += step;
11104 if (offset LTGT bound) goto body_bb; [*]
11105
11106 <bottom_bb> [created by splitting start of exit_bb] insert BRANCH->head_bb
11107 chunk_no++;
11108 if (chunk < chunk_max) goto head_bb;
11109
11110 <exit_bb> [incoming]
11111 V = B + ((range -/+ 1) / S +/- 1) * S [*]
11112
11113 [*] Needed if V live at end of loop
11114
11115 Note: CHUNKING & GWV mask are specified explicitly here. This is a
11116 transition, and will be specified by a more general mechanism shortly.
11117 */
11118
11119static void
11120expand_oacc_for (struct omp_region *region, struct omp_for_data *fd)
11121{
11122 tree v = fd->loop.v;
11123 enum tree_code cond_code = fd->loop.cond_code;
11124 enum tree_code plus_code = PLUS_EXPR;
11125
11126 tree chunk_size = integer_minus_one_node;
11127 tree gwv = integer_zero_node;
11128 tree iter_type = TREE_TYPE (v);
11129 tree diff_type = iter_type;
11130 tree plus_type = iter_type;
11131 struct oacc_collapse *counts = NULL;
11132
11133 gcc_checking_assert (gimple_omp_for_kind (fd->for_stmt)
11134 == GF_OMP_FOR_KIND_OACC_LOOP);
11135 gcc_assert (!gimple_omp_for_combined_into_p (fd->for_stmt));
11136 gcc_assert (cond_code == LT_EXPR || cond_code == GT_EXPR);
11137
11138 if (POINTER_TYPE_P (iter_type))
11139 {
11140 plus_code = POINTER_PLUS_EXPR;
11141 plus_type = sizetype;
11142 }
11143 if (POINTER_TYPE_P (diff_type) || TYPE_UNSIGNED (diff_type))
11144 diff_type = signed_type_for (diff_type);
11145
11146 basic_block entry_bb = region->entry; /* BB ending in OMP_FOR */
11147 basic_block exit_bb = region->exit; /* BB ending in OMP_RETURN */
11148 basic_block cont_bb = region->cont; /* BB ending in OMP_CONTINUE */
11149 basic_block bottom_bb = NULL;
11150
11151 /* entry_bb has two sucessors; the branch edge is to the exit
11152 block, fallthrough edge to body. */
11153 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2
11154 && BRANCH_EDGE (entry_bb)->dest == exit_bb);
11155
11156 /* If cont_bb non-NULL, it has 2 successors. The branch successor is
11157 body_bb, or to a block whose only successor is the body_bb. Its
11158 fallthrough successor is the final block (same as the branch
11159 successor of the entry_bb). */
11160 if (cont_bb)
11161 {
11162 basic_block body_bb = FALLTHRU_EDGE (entry_bb)->dest;
11163 basic_block bed = BRANCH_EDGE (cont_bb)->dest;
11164
11165 gcc_assert (FALLTHRU_EDGE (cont_bb)->dest == exit_bb);
11166 gcc_assert (bed == body_bb || single_succ_edge (bed)->dest == body_bb);
11167 }
11168 else
11169 gcc_assert (!gimple_in_ssa_p (cfun));
11170
11171 /* The exit block only has entry_bb and cont_bb as predecessors. */
11172 gcc_assert (EDGE_COUNT (exit_bb->preds) == 1 + (cont_bb != NULL));
11173
11174 tree chunk_no;
11175 tree chunk_max = NULL_TREE;
11176 tree bound, offset;
11177 tree step = create_tmp_var (diff_type, ".step");
11178 bool up = cond_code == LT_EXPR;
11179 tree dir = build_int_cst (diff_type, up ? +1 : -1);
11180 bool chunking = !gimple_in_ssa_p (cfun);;
11181 bool negating;
11182
11183 /* SSA instances. */
11184 tree offset_incr = NULL_TREE;
11185 tree offset_init = NULL_TREE;
11186
11187 gimple_stmt_iterator gsi;
11188 gassign *ass;
11189 gcall *call;
11190 gimple *stmt;
11191 tree expr;
11192 location_t loc;
11193 edge split, be, fte;
11194
11195 /* Split the end of entry_bb to create head_bb. */
11196 split = split_block (entry_bb, last_stmt (entry_bb));
11197 basic_block head_bb = split->dest;
11198 entry_bb = split->src;
11199
11200 /* Chunk setup goes at end of entry_bb, replacing the omp_for. */
11201 gsi = gsi_last_bb (entry_bb);
11202 gomp_for *for_stmt = as_a <gomp_for *> (gsi_stmt (gsi));
11203 loc = gimple_location (for_stmt);
11204
11205 if (gimple_in_ssa_p (cfun))
11206 {
11207 offset_init = gimple_omp_for_index (for_stmt, 0);
11208 gcc_assert (integer_zerop (fd->loop.n1));
11209 /* The SSA parallelizer does gang parallelism. */
11210 gwv = build_int_cst (integer_type_node, GOMP_DIM_MASK (GOMP_DIM_GANG));
11211 }
11212
11213 if (fd->collapse > 1)
11214 {
11215 counts = XALLOCAVEC (struct oacc_collapse, fd->collapse);
11216 tree total = expand_oacc_collapse_init (fd, &gsi, counts,
11217 TREE_TYPE (fd->loop.n2));
11218
11219 if (SSA_VAR_P (fd->loop.n2))
11220 {
11221 total = force_gimple_operand_gsi (&gsi, total, false, NULL_TREE,
11222 true, GSI_SAME_STMT);
11223 ass = gimple_build_assign (fd->loop.n2, total);
11224 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11225 }
11226
11227 }
11228
11229 tree b = fd->loop.n1;
11230 tree e = fd->loop.n2;
11231 tree s = fd->loop.step;
11232
11233 b = force_gimple_operand_gsi (&gsi, b, true, NULL_TREE, true, GSI_SAME_STMT);
11234 e = force_gimple_operand_gsi (&gsi, e, true, NULL_TREE, true, GSI_SAME_STMT);
11235
11236 /* Convert the step, avoiding possible unsigned->signed overflow. */
11237 negating = !up && TYPE_UNSIGNED (TREE_TYPE (s));
11238 if (negating)
11239 s = fold_build1 (NEGATE_EXPR, TREE_TYPE (s), s);
11240 s = fold_convert (diff_type, s);
11241 if (negating)
11242 s = fold_build1 (NEGATE_EXPR, diff_type, s);
11243 s = force_gimple_operand_gsi (&gsi, s, true, NULL_TREE, true, GSI_SAME_STMT);
11244
11245 if (!chunking)
11246 chunk_size = integer_zero_node;
11247 expr = fold_convert (diff_type, chunk_size);
11248 chunk_size = force_gimple_operand_gsi (&gsi, expr, true,
11249 NULL_TREE, true, GSI_SAME_STMT);
11250 /* Determine the range, avoiding possible unsigned->signed overflow. */
11251 negating = !up && TYPE_UNSIGNED (iter_type);
11252 expr = fold_build2 (MINUS_EXPR, plus_type,
11253 fold_convert (plus_type, negating ? b : e),
11254 fold_convert (plus_type, negating ? e : b));
11255 expr = fold_convert (diff_type, expr);
11256 if (negating)
11257 expr = fold_build1 (NEGATE_EXPR, diff_type, expr);
11258 tree range = force_gimple_operand_gsi (&gsi, expr, true,
11259 NULL_TREE, true, GSI_SAME_STMT);
11260
11261 chunk_no = build_int_cst (diff_type, 0);
11262 if (chunking)
11263 {
11264 gcc_assert (!gimple_in_ssa_p (cfun));
11265
11266 expr = chunk_no;
11267 chunk_max = create_tmp_var (diff_type, ".chunk_max");
11268 chunk_no = create_tmp_var (diff_type, ".chunk_no");
11269
11270 ass = gimple_build_assign (chunk_no, expr);
11271 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11272
11273 call = gimple_build_call_internal (IFN_GOACC_LOOP, 6,
11274 build_int_cst (integer_type_node,
11275 IFN_GOACC_LOOP_CHUNKS),
11276 dir, range, s, chunk_size, gwv);
11277 gimple_call_set_lhs (call, chunk_max);
11278 gimple_set_location (call, loc);
11279 gsi_insert_before (&gsi, call, GSI_SAME_STMT);
11280 }
11281 else
11282 chunk_size = chunk_no;
11283
11284 call = gimple_build_call_internal (IFN_GOACC_LOOP, 6,
11285 build_int_cst (integer_type_node,
11286 IFN_GOACC_LOOP_STEP),
11287 dir, range, s, chunk_size, gwv);
11288 gimple_call_set_lhs (call, step);
11289 gimple_set_location (call, loc);
11290 gsi_insert_before (&gsi, call, GSI_SAME_STMT);
11291
11292 /* Remove the GIMPLE_OMP_FOR. */
11293 gsi_remove (&gsi, true);
11294
11295 /* Fixup edges from head_bb */
11296 be = BRANCH_EDGE (head_bb);
11297 fte = FALLTHRU_EDGE (head_bb);
11298 be->flags |= EDGE_FALSE_VALUE;
11299 fte->flags ^= EDGE_FALLTHRU | EDGE_TRUE_VALUE;
11300
11301 basic_block body_bb = fte->dest;
11302
11303 if (gimple_in_ssa_p (cfun))
11304 {
11305 gsi = gsi_last_bb (cont_bb);
11306 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
11307
11308 offset = gimple_omp_continue_control_use (cont_stmt);
11309 offset_incr = gimple_omp_continue_control_def (cont_stmt);
11310 }
11311 else
11312 {
11313 offset = create_tmp_var (diff_type, ".offset");
11314 offset_init = offset_incr = offset;
11315 }
11316 bound = create_tmp_var (TREE_TYPE (offset), ".bound");
11317
11318 /* Loop offset & bound go into head_bb. */
11319 gsi = gsi_start_bb (head_bb);
11320
11321 call = gimple_build_call_internal (IFN_GOACC_LOOP, 7,
11322 build_int_cst (integer_type_node,
11323 IFN_GOACC_LOOP_OFFSET),
11324 dir, range, s,
11325 chunk_size, gwv, chunk_no);
11326 gimple_call_set_lhs (call, offset_init);
11327 gimple_set_location (call, loc);
11328 gsi_insert_after (&gsi, call, GSI_CONTINUE_LINKING);
11329
11330 call = gimple_build_call_internal (IFN_GOACC_LOOP, 7,
11331 build_int_cst (integer_type_node,
11332 IFN_GOACC_LOOP_BOUND),
11333 dir, range, s,
11334 chunk_size, gwv, offset_init);
11335 gimple_call_set_lhs (call, bound);
11336 gimple_set_location (call, loc);
11337 gsi_insert_after (&gsi, call, GSI_CONTINUE_LINKING);
11338
11339 expr = build2 (cond_code, boolean_type_node, offset_init, bound);
11340 gsi_insert_after (&gsi, gimple_build_cond_empty (expr),
11341 GSI_CONTINUE_LINKING);
11342
11343 /* V assignment goes into body_bb. */
11344 if (!gimple_in_ssa_p (cfun))
11345 {
11346 gsi = gsi_start_bb (body_bb);
11347
11348 expr = build2 (plus_code, iter_type, b,
11349 fold_convert (plus_type, offset));
11350 expr = force_gimple_operand_gsi (&gsi, expr, false, NULL_TREE,
11351 true, GSI_SAME_STMT);
11352 ass = gimple_build_assign (v, expr);
11353 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11354 if (fd->collapse > 1)
11355 expand_oacc_collapse_vars (fd, &gsi, counts, v);
11356 }
11357
11358 /* Loop increment goes into cont_bb. If this is not a loop, we
11359 will have spawned threads as if it was, and each one will
11360 execute one iteration. The specification is not explicit about
11361 whether such constructs are ill-formed or not, and they can
11362 occur, especially when noreturn routines are involved. */
11363 if (cont_bb)
11364 {
11365 gsi = gsi_last_bb (cont_bb);
11366 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
11367 loc = gimple_location (cont_stmt);
11368
11369 /* Increment offset. */
11370 if (gimple_in_ssa_p (cfun))
11371 expr= build2 (plus_code, iter_type, offset,
11372 fold_convert (plus_type, step));
11373 else
11374 expr = build2 (PLUS_EXPR, diff_type, offset, step);
11375 expr = force_gimple_operand_gsi (&gsi, expr, false, NULL_TREE,
11376 true, GSI_SAME_STMT);
11377 ass = gimple_build_assign (offset_incr, expr);
11378 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11379 expr = build2 (cond_code, boolean_type_node, offset_incr, bound);
11380 gsi_insert_before (&gsi, gimple_build_cond_empty (expr), GSI_SAME_STMT);
11381
11382 /* Remove the GIMPLE_OMP_CONTINUE. */
11383 gsi_remove (&gsi, true);
11384
11385 /* Fixup edges from cont_bb */
11386 be = BRANCH_EDGE (cont_bb);
11387 fte = FALLTHRU_EDGE (cont_bb);
11388 be->flags |= EDGE_TRUE_VALUE;
11389 fte->flags ^= EDGE_FALLTHRU | EDGE_FALSE_VALUE;
11390
11391 if (chunking)
11392 {
11393 /* Split the beginning of exit_bb to make bottom_bb. We
11394 need to insert a nop at the start, because splitting is
11395 after a stmt, not before. */
11396 gsi = gsi_start_bb (exit_bb);
11397 stmt = gimple_build_nop ();
11398 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
11399 split = split_block (exit_bb, stmt);
11400 bottom_bb = split->src;
11401 exit_bb = split->dest;
11402 gsi = gsi_last_bb (bottom_bb);
11403
11404 /* Chunk increment and test goes into bottom_bb. */
11405 expr = build2 (PLUS_EXPR, diff_type, chunk_no,
11406 build_int_cst (diff_type, 1));
11407 ass = gimple_build_assign (chunk_no, expr);
11408 gsi_insert_after (&gsi, ass, GSI_CONTINUE_LINKING);
11409
11410 /* Chunk test at end of bottom_bb. */
11411 expr = build2 (LT_EXPR, boolean_type_node, chunk_no, chunk_max);
11412 gsi_insert_after (&gsi, gimple_build_cond_empty (expr),
11413 GSI_CONTINUE_LINKING);
11414
11415 /* Fixup edges from bottom_bb. */
11416 split->flags ^= EDGE_FALLTHRU | EDGE_FALSE_VALUE;
11417 make_edge (bottom_bb, head_bb, EDGE_TRUE_VALUE);
11418 }
11419 }
11420
11421 gsi = gsi_last_bb (exit_bb);
11422 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
11423 loc = gimple_location (gsi_stmt (gsi));
11424
11425 if (!gimple_in_ssa_p (cfun))
11426 {
11427 /* Insert the final value of V, in case it is live. This is the
11428 value for the only thread that survives past the join. */
11429 expr = fold_build2 (MINUS_EXPR, diff_type, range, dir);
11430 expr = fold_build2 (PLUS_EXPR, diff_type, expr, s);
11431 expr = fold_build2 (TRUNC_DIV_EXPR, diff_type, expr, s);
11432 expr = fold_build2 (MULT_EXPR, diff_type, expr, s);
11433 expr = build2 (plus_code, iter_type, b, fold_convert (plus_type, expr));
11434 expr = force_gimple_operand_gsi (&gsi, expr, false, NULL_TREE,
11435 true, GSI_SAME_STMT);
11436 ass = gimple_build_assign (v, expr);
11437 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11438 }
11439
11440 /* Remove the OMP_RETURN. */
11441 gsi_remove (&gsi, true);
11442
11443 if (cont_bb)
11444 {
11445 /* We now have one or two nested loops. Update the loop
11446 structures. */
11447 struct loop *parent = entry_bb->loop_father;
11448 struct loop *body = body_bb->loop_father;
11449
11450 if (chunking)
11451 {
11452 struct loop *chunk_loop = alloc_loop ();
11453 chunk_loop->header = head_bb;
11454 chunk_loop->latch = bottom_bb;
11455 add_loop (chunk_loop, parent);
11456 parent = chunk_loop;
11457 }
11458 else if (parent != body)
11459 {
11460 gcc_assert (body->header == body_bb);
11461 gcc_assert (body->latch == cont_bb
11462 || single_pred (body->latch) == cont_bb);
11463 parent = NULL;
11464 }
11465
11466 if (parent)
11467 {
11468 struct loop *body_loop = alloc_loop ();
11469 body_loop->header = body_bb;
11470 body_loop->latch = cont_bb;
11471 add_loop (body_loop, parent);
11472 }
11473 }
11474}
11475
ca4c3545 11476/* Expand the OMP loop defined by REGION. */
1e8e9920 11477
773c5ba7 11478static void
42acab1c 11479expand_omp_for (struct omp_region *region, gimple *inner_stmt)
773c5ba7 11480{
11481 struct omp_for_data fd;
fd6481cf 11482 struct omp_for_data_loop *loops;
1e8e9920 11483
fd6481cf 11484 loops
11485 = (struct omp_for_data_loop *)
75a70cf9 11486 alloca (gimple_omp_for_collapse (last_stmt (region->entry))
fd6481cf 11487 * sizeof (struct omp_for_data_loop));
1a91d914 11488 extract_omp_for_data (as_a <gomp_for *> (last_stmt (region->entry)),
11489 &fd, loops);
f77459c5 11490 region->sched_kind = fd.sched_kind;
9561765e 11491 region->sched_modifiers = fd.sched_modifiers;
1e8e9920 11492
b3a3ddec 11493 gcc_assert (EDGE_COUNT (region->entry->succs) == 2);
11494 BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
11495 FALLTHRU_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
11496 if (region->cont)
11497 {
11498 gcc_assert (EDGE_COUNT (region->cont->succs) == 2);
11499 BRANCH_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
11500 FALLTHRU_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
11501 }
04c2922b 11502 else
75de4aa2 11503 /* If there isn't a continue then this is a degerate case where
04c2922b 11504 the introduction of abnormal edges during lowering will prevent
11505 original loops from being detected. Fix that up. */
11506 loops_state_set (LOOPS_NEED_FIXUP);
b3a3ddec 11507
10c55644 11508 if (gimple_omp_for_kind (fd.for_stmt) & GF_OMP_FOR_SIMD)
3d483a94 11509 expand_omp_simd (region, &fd);
40750995 11510 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
11511 expand_cilk_for (region, &fd);
a8e785ba 11512 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
11513 {
11514 gcc_assert (!inner_stmt);
11515 expand_oacc_for (region, &fd);
11516 }
43895be5 11517 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_TASKLOOP)
11518 {
11519 if (gimple_omp_for_combined_into_p (fd.for_stmt))
11520 expand_omp_taskloop_for_inner (region, &fd, inner_stmt);
11521 else
11522 expand_omp_taskloop_for_outer (region, &fd, inner_stmt);
11523 }
3d483a94 11524 else if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
bc7bff74 11525 && !fd.have_ordered)
1e8e9920 11526 {
11527 if (fd.chunk_size == NULL)
bc7bff74 11528 expand_omp_for_static_nochunk (region, &fd, inner_stmt);
1e8e9920 11529 else
bc7bff74 11530 expand_omp_for_static_chunk (region, &fd, inner_stmt);
1e8e9920 11531 }
11532 else
11533 {
fd6481cf 11534 int fn_index, start_ix, next_ix;
11535
3d483a94 11536 gcc_assert (gimple_omp_for_kind (fd.for_stmt)
11537 == GF_OMP_FOR_KIND_FOR);
0416ca72 11538 if (fd.chunk_size == NULL
11539 && fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
11540 fd.chunk_size = integer_zero_node;
fd6481cf 11541 gcc_assert (fd.sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
9561765e 11542 switch (fd.sched_kind)
11543 {
11544 case OMP_CLAUSE_SCHEDULE_RUNTIME:
11545 fn_index = 3;
11546 break;
11547 case OMP_CLAUSE_SCHEDULE_DYNAMIC:
11548 case OMP_CLAUSE_SCHEDULE_GUIDED:
11549 if ((fd.sched_modifiers & OMP_CLAUSE_SCHEDULE_NONMONOTONIC)
11550 && !fd.ordered
11551 && !fd.have_ordered)
11552 {
11553 fn_index = 3 + fd.sched_kind;
11554 break;
11555 }
11556 /* FALLTHRU */
11557 default:
11558 fn_index = fd.sched_kind;
11559 break;
11560 }
43895be5 11561 if (!fd.ordered)
9561765e 11562 fn_index += fd.have_ordered * 6;
43895be5 11563 if (fd.ordered)
11564 start_ix = ((int)BUILT_IN_GOMP_LOOP_DOACROSS_STATIC_START) + fn_index;
11565 else
11566 start_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_START) + fn_index;
b9a16870 11567 next_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT) + fn_index;
fd6481cf 11568 if (fd.iter_type == long_long_unsigned_type_node)
11569 {
b9a16870 11570 start_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
11571 - (int)BUILT_IN_GOMP_LOOP_STATIC_START);
11572 next_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
11573 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT);
fd6481cf 11574 }
b9c74b4d 11575 expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
bc7bff74 11576 (enum built_in_function) next_ix, inner_stmt);
1e8e9920 11577 }
28c92cbb 11578
083152fb 11579 if (gimple_in_ssa_p (cfun))
11580 update_ssa (TODO_update_ssa_only_virtuals);
1e8e9920 11581}
11582
1e8e9920 11583
11584/* Expand code for an OpenMP sections directive. In pseudo code, we generate
11585
1e8e9920 11586 v = GOMP_sections_start (n);
11587 L0:
11588 switch (v)
11589 {
11590 case 0:
11591 goto L2;
11592 case 1:
11593 section 1;
11594 goto L1;
11595 case 2:
11596 ...
11597 case n:
11598 ...
1e8e9920 11599 default:
11600 abort ();
11601 }
11602 L1:
11603 v = GOMP_sections_next ();
11604 goto L0;
11605 L2:
11606 reduction;
11607
773c5ba7 11608 If this is a combined parallel sections, replace the call to
79acaae1 11609 GOMP_sections_start with call to GOMP_sections_next. */
1e8e9920 11610
11611static void
773c5ba7 11612expand_omp_sections (struct omp_region *region)
1e8e9920 11613{
f018d957 11614 tree t, u, vin = NULL, vmain, vnext, l2;
75a70cf9 11615 unsigned len;
ac6e3339 11616 basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
75a70cf9 11617 gimple_stmt_iterator si, switch_si;
1a91d914 11618 gomp_sections *sections_stmt;
42acab1c 11619 gimple *stmt;
1a91d914 11620 gomp_continue *cont;
9884aaf8 11621 edge_iterator ei;
11622 edge e;
61e47ac8 11623 struct omp_region *inner;
75a70cf9 11624 unsigned i, casei;
ac6e3339 11625 bool exit_reachable = region->cont != NULL;
1e8e9920 11626
d244d9de 11627 gcc_assert (region->exit != NULL);
61e47ac8 11628 entry_bb = region->entry;
ac6e3339 11629 l0_bb = single_succ (entry_bb);
61e47ac8 11630 l1_bb = region->cont;
ac6e3339 11631 l2_bb = region->exit;
d244d9de 11632 if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
11633 l2 = gimple_block_label (l2_bb);
11634 else
03ed154b 11635 {
d244d9de 11636 /* This can happen if there are reductions. */
11637 len = EDGE_COUNT (l0_bb->succs);
11638 gcc_assert (len > 0);
11639 e = EDGE_SUCC (l0_bb, len - 1);
11640 si = gsi_last_bb (e->dest);
11641 l2 = NULL_TREE;
11642 if (gsi_end_p (si)
11643 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
11644 l2 = gimple_block_label (e->dest);
9884aaf8 11645 else
d244d9de 11646 FOR_EACH_EDGE (e, ei, l0_bb->succs)
11647 {
11648 si = gsi_last_bb (e->dest);
11649 if (gsi_end_p (si)
11650 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
9884aaf8 11651 {
d244d9de 11652 l2 = gimple_block_label (e->dest);
11653 break;
9884aaf8 11654 }
d244d9de 11655 }
03ed154b 11656 }
d244d9de 11657 if (exit_reachable)
11658 default_bb = create_empty_bb (l1_bb->prev_bb);
03ed154b 11659 else
d244d9de 11660 default_bb = create_empty_bb (l0_bb);
773c5ba7 11661
11662 /* We will build a switch() with enough cases for all the
75a70cf9 11663 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
773c5ba7 11664 and a default case to abort if something goes wrong. */
ac6e3339 11665 len = EDGE_COUNT (l0_bb->succs);
75a70cf9 11666
f1f41a6c 11667 /* Use vec::quick_push on label_vec throughout, since we know the size
75a70cf9 11668 in advance. */
c2078b80 11669 auto_vec<tree> label_vec (len);
1e8e9920 11670
61e47ac8 11671 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
75a70cf9 11672 GIMPLE_OMP_SECTIONS statement. */
11673 si = gsi_last_bb (entry_bb);
1a91d914 11674 sections_stmt = as_a <gomp_sections *> (gsi_stmt (si));
75a70cf9 11675 gcc_assert (gimple_code (sections_stmt) == GIMPLE_OMP_SECTIONS);
11676 vin = gimple_omp_sections_control (sections_stmt);
773c5ba7 11677 if (!is_combined_parallel (region))
1e8e9920 11678 {
773c5ba7 11679 /* If we are not inside a combined parallel+sections region,
11680 call GOMP_sections_start. */
39cb6d68 11681 t = build_int_cst (unsigned_type_node, len - 1);
b9a16870 11682 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START);
75a70cf9 11683 stmt = gimple_build_call (u, 1, t);
1e8e9920 11684 }
79acaae1 11685 else
11686 {
11687 /* Otherwise, call GOMP_sections_next. */
b9a16870 11688 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
75a70cf9 11689 stmt = gimple_build_call (u, 0);
79acaae1 11690 }
75a70cf9 11691 gimple_call_set_lhs (stmt, vin);
11692 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
11693 gsi_remove (&si, true);
11694
11695 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
11696 L0_BB. */
11697 switch_si = gsi_last_bb (l0_bb);
11698 gcc_assert (gimple_code (gsi_stmt (switch_si)) == GIMPLE_OMP_SECTIONS_SWITCH);
79acaae1 11699 if (exit_reachable)
11700 {
1a91d914 11701 cont = as_a <gomp_continue *> (last_stmt (l1_bb));
75a70cf9 11702 gcc_assert (gimple_code (cont) == GIMPLE_OMP_CONTINUE);
11703 vmain = gimple_omp_continue_control_use (cont);
11704 vnext = gimple_omp_continue_control_def (cont);
79acaae1 11705 }
11706 else
11707 {
11708 vmain = vin;
11709 vnext = NULL_TREE;
11710 }
1e8e9920 11711
d244d9de 11712 t = build_case_label (build_int_cst (unsigned_type_node, 0), NULL, l2);
f1f41a6c 11713 label_vec.quick_push (t);
d244d9de 11714 i = 1;
03ed154b 11715
75a70cf9 11716 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
ac6e3339 11717 for (inner = region->inner, casei = 1;
11718 inner;
11719 inner = inner->next, i++, casei++)
1e8e9920 11720 {
773c5ba7 11721 basic_block s_entry_bb, s_exit_bb;
11722
9884aaf8 11723 /* Skip optional reduction region. */
75a70cf9 11724 if (inner->type == GIMPLE_OMP_ATOMIC_LOAD)
9884aaf8 11725 {
11726 --i;
11727 --casei;
11728 continue;
11729 }
11730
61e47ac8 11731 s_entry_bb = inner->entry;
11732 s_exit_bb = inner->exit;
1e8e9920 11733
75a70cf9 11734 t = gimple_block_label (s_entry_bb);
ac6e3339 11735 u = build_int_cst (unsigned_type_node, casei);
b6e3dd65 11736 u = build_case_label (u, NULL, t);
f1f41a6c 11737 label_vec.quick_push (u);
61e47ac8 11738
75a70cf9 11739 si = gsi_last_bb (s_entry_bb);
11740 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SECTION);
11741 gcc_assert (i < len || gimple_omp_section_last_p (gsi_stmt (si)));
11742 gsi_remove (&si, true);
61e47ac8 11743 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
03ed154b 11744
11745 if (s_exit_bb == NULL)
11746 continue;
11747
75a70cf9 11748 si = gsi_last_bb (s_exit_bb);
11749 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
11750 gsi_remove (&si, true);
03ed154b 11751
773c5ba7 11752 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
1e8e9920 11753 }
11754
773c5ba7 11755 /* Error handling code goes in DEFAULT_BB. */
75a70cf9 11756 t = gimple_block_label (default_bb);
b6e3dd65 11757 u = build_case_label (NULL, NULL, t);
61e47ac8 11758 make_edge (l0_bb, default_bb, 0);
b3083327 11759 add_bb_to_loop (default_bb, current_loops->tree_root);
1e8e9920 11760
49a70175 11761 stmt = gimple_build_switch (vmain, u, label_vec);
75a70cf9 11762 gsi_insert_after (&switch_si, stmt, GSI_SAME_STMT);
11763 gsi_remove (&switch_si, true);
75a70cf9 11764
11765 si = gsi_start_bb (default_bb);
b9a16870 11766 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
75a70cf9 11767 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
773c5ba7 11768
ac6e3339 11769 if (exit_reachable)
03ed154b 11770 {
b9a16870 11771 tree bfn_decl;
11772
ac6e3339 11773 /* Code to get the next section goes in L1_BB. */
75a70cf9 11774 si = gsi_last_bb (l1_bb);
11775 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
1e8e9920 11776
b9a16870 11777 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
11778 stmt = gimple_build_call (bfn_decl, 0);
75a70cf9 11779 gimple_call_set_lhs (stmt, vnext);
11780 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
11781 gsi_remove (&si, true);
773c5ba7 11782
ac6e3339 11783 single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
03ed154b 11784 }
773c5ba7 11785
d244d9de 11786 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
11787 si = gsi_last_bb (l2_bb);
11788 if (gimple_omp_return_nowait_p (gsi_stmt (si)))
11789 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
bc7bff74 11790 else if (gimple_omp_return_lhs (gsi_stmt (si)))
11791 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL);
d244d9de 11792 else
11793 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
11794 stmt = gimple_build_call (t, 0);
bc7bff74 11795 if (gimple_omp_return_lhs (gsi_stmt (si)))
11796 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (si)));
d244d9de 11797 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
11798 gsi_remove (&si, true);
11799
79acaae1 11800 set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
773c5ba7 11801}
1e8e9920 11802
1e8e9920 11803
61e47ac8 11804/* Expand code for an OpenMP single directive. We've already expanded
11805 much of the code, here we simply place the GOMP_barrier call. */
11806
11807static void
11808expand_omp_single (struct omp_region *region)
11809{
11810 basic_block entry_bb, exit_bb;
75a70cf9 11811 gimple_stmt_iterator si;
61e47ac8 11812
11813 entry_bb = region->entry;
11814 exit_bb = region->exit;
11815
75a70cf9 11816 si = gsi_last_bb (entry_bb);
75a70cf9 11817 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE);
11818 gsi_remove (&si, true);
61e47ac8 11819 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
11820
75a70cf9 11821 si = gsi_last_bb (exit_bb);
bc7bff74 11822 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
11823 {
11824 tree t = gimple_omp_return_lhs (gsi_stmt (si));
11825 gsi_insert_after (&si, build_omp_barrier (t), GSI_SAME_STMT);
11826 }
75a70cf9 11827 gsi_remove (&si, true);
61e47ac8 11828 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
11829}
11830
11831
11832/* Generic expansion for OpenMP synchronization directives: master,
11833 ordered and critical. All we need to do here is remove the entry
11834 and exit markers for REGION. */
773c5ba7 11835
11836static void
11837expand_omp_synch (struct omp_region *region)
11838{
11839 basic_block entry_bb, exit_bb;
75a70cf9 11840 gimple_stmt_iterator si;
773c5ba7 11841
61e47ac8 11842 entry_bb = region->entry;
11843 exit_bb = region->exit;
773c5ba7 11844
75a70cf9 11845 si = gsi_last_bb (entry_bb);
11846 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE
11847 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASTER
bc7bff74 11848 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TASKGROUP
75a70cf9 11849 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ORDERED
bc7bff74 11850 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CRITICAL
11851 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TEAMS);
75a70cf9 11852 gsi_remove (&si, true);
773c5ba7 11853 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
11854
03ed154b 11855 if (exit_bb)
11856 {
75a70cf9 11857 si = gsi_last_bb (exit_bb);
11858 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
11859 gsi_remove (&si, true);
03ed154b 11860 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
11861 }
773c5ba7 11862}
1e8e9920 11863
2169f33b 11864/* A subroutine of expand_omp_atomic. Attempt to implement the atomic
11865 operation as a normal volatile load. */
11866
11867static bool
3ec11c49 11868expand_omp_atomic_load (basic_block load_bb, tree addr,
11869 tree loaded_val, int index)
2169f33b 11870{
3ec11c49 11871 enum built_in_function tmpbase;
11872 gimple_stmt_iterator gsi;
11873 basic_block store_bb;
11874 location_t loc;
42acab1c 11875 gimple *stmt;
3ec11c49 11876 tree decl, call, type, itype;
11877
11878 gsi = gsi_last_bb (load_bb);
11879 stmt = gsi_stmt (gsi);
11880 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
11881 loc = gimple_location (stmt);
11882
11883 /* ??? If the target does not implement atomic_load_optab[mode], and mode
11884 is smaller than word size, then expand_atomic_load assumes that the load
11885 is atomic. We could avoid the builtin entirely in this case. */
11886
11887 tmpbase = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
11888 decl = builtin_decl_explicit (tmpbase);
11889 if (decl == NULL_TREE)
11890 return false;
11891
11892 type = TREE_TYPE (loaded_val);
11893 itype = TREE_TYPE (TREE_TYPE (decl));
11894
11895 call = build_call_expr_loc (loc, decl, 2, addr,
bc7bff74 11896 build_int_cst (NULL,
11897 gimple_omp_atomic_seq_cst_p (stmt)
11898 ? MEMMODEL_SEQ_CST
11899 : MEMMODEL_RELAXED));
3ec11c49 11900 if (!useless_type_conversion_p (type, itype))
11901 call = fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
11902 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
11903
11904 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
11905 gsi_remove (&gsi, true);
11906
11907 store_bb = single_succ (load_bb);
11908 gsi = gsi_last_bb (store_bb);
11909 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
11910 gsi_remove (&gsi, true);
11911
11912 if (gimple_in_ssa_p (cfun))
11913 update_ssa (TODO_update_ssa_no_phi);
11914
11915 return true;
2169f33b 11916}
11917
11918/* A subroutine of expand_omp_atomic. Attempt to implement the atomic
11919 operation as a normal volatile store. */
11920
11921static bool
3ec11c49 11922expand_omp_atomic_store (basic_block load_bb, tree addr,
11923 tree loaded_val, tree stored_val, int index)
2169f33b 11924{
3ec11c49 11925 enum built_in_function tmpbase;
11926 gimple_stmt_iterator gsi;
11927 basic_block store_bb = single_succ (load_bb);
11928 location_t loc;
42acab1c 11929 gimple *stmt;
3ec11c49 11930 tree decl, call, type, itype;
3754d046 11931 machine_mode imode;
3ec11c49 11932 bool exchange;
11933
11934 gsi = gsi_last_bb (load_bb);
11935 stmt = gsi_stmt (gsi);
11936 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
11937
11938 /* If the load value is needed, then this isn't a store but an exchange. */
11939 exchange = gimple_omp_atomic_need_value_p (stmt);
11940
11941 gsi = gsi_last_bb (store_bb);
11942 stmt = gsi_stmt (gsi);
11943 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE);
11944 loc = gimple_location (stmt);
11945
11946 /* ??? If the target does not implement atomic_store_optab[mode], and mode
11947 is smaller than word size, then expand_atomic_store assumes that the store
11948 is atomic. We could avoid the builtin entirely in this case. */
11949
11950 tmpbase = (exchange ? BUILT_IN_ATOMIC_EXCHANGE_N : BUILT_IN_ATOMIC_STORE_N);
11951 tmpbase = (enum built_in_function) ((int) tmpbase + index + 1);
11952 decl = builtin_decl_explicit (tmpbase);
11953 if (decl == NULL_TREE)
11954 return false;
11955
11956 type = TREE_TYPE (stored_val);
11957
11958 /* Dig out the type of the function's second argument. */
11959 itype = TREE_TYPE (decl);
11960 itype = TYPE_ARG_TYPES (itype);
11961 itype = TREE_CHAIN (itype);
11962 itype = TREE_VALUE (itype);
11963 imode = TYPE_MODE (itype);
11964
11965 if (exchange && !can_atomic_exchange_p (imode, true))
11966 return false;
11967
11968 if (!useless_type_conversion_p (itype, type))
11969 stored_val = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, stored_val);
11970 call = build_call_expr_loc (loc, decl, 3, addr, stored_val,
bc7bff74 11971 build_int_cst (NULL,
11972 gimple_omp_atomic_seq_cst_p (stmt)
11973 ? MEMMODEL_SEQ_CST
11974 : MEMMODEL_RELAXED));
3ec11c49 11975 if (exchange)
11976 {
11977 if (!useless_type_conversion_p (type, itype))
11978 call = build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
11979 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
11980 }
11981
11982 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
11983 gsi_remove (&gsi, true);
11984
11985 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
11986 gsi = gsi_last_bb (load_bb);
11987 gsi_remove (&gsi, true);
11988
11989 if (gimple_in_ssa_p (cfun))
11990 update_ssa (TODO_update_ssa_no_phi);
11991
11992 return true;
2169f33b 11993}
11994
cb7f680b 11995/* A subroutine of expand_omp_atomic. Attempt to implement the atomic
1cd6e20d 11996 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
cb7f680b 11997 size of the data type, and thus usable to find the index of the builtin
11998 decl. Returns false if the expression is not of the proper form. */
11999
12000static bool
12001expand_omp_atomic_fetch_op (basic_block load_bb,
12002 tree addr, tree loaded_val,
12003 tree stored_val, int index)
12004{
b9a16870 12005 enum built_in_function oldbase, newbase, tmpbase;
cb7f680b 12006 tree decl, itype, call;
2169f33b 12007 tree lhs, rhs;
cb7f680b 12008 basic_block store_bb = single_succ (load_bb);
75a70cf9 12009 gimple_stmt_iterator gsi;
42acab1c 12010 gimple *stmt;
389dd41b 12011 location_t loc;
1cd6e20d 12012 enum tree_code code;
2169f33b 12013 bool need_old, need_new;
3754d046 12014 machine_mode imode;
bc7bff74 12015 bool seq_cst;
cb7f680b 12016
12017 /* We expect to find the following sequences:
48e1416a 12018
cb7f680b 12019 load_bb:
75a70cf9 12020 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
cb7f680b 12021
12022 store_bb:
12023 val = tmp OP something; (or: something OP tmp)
48e1416a 12024 GIMPLE_OMP_STORE (val)
cb7f680b 12025
48e1416a 12026 ???FIXME: Allow a more flexible sequence.
cb7f680b 12027 Perhaps use data flow to pick the statements.
48e1416a 12028
cb7f680b 12029 */
12030
75a70cf9 12031 gsi = gsi_after_labels (store_bb);
12032 stmt = gsi_stmt (gsi);
389dd41b 12033 loc = gimple_location (stmt);
75a70cf9 12034 if (!is_gimple_assign (stmt))
cb7f680b 12035 return false;
75a70cf9 12036 gsi_next (&gsi);
12037 if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE)
cb7f680b 12038 return false;
2169f33b 12039 need_new = gimple_omp_atomic_need_value_p (gsi_stmt (gsi));
12040 need_old = gimple_omp_atomic_need_value_p (last_stmt (load_bb));
bc7bff74 12041 seq_cst = gimple_omp_atomic_seq_cst_p (last_stmt (load_bb));
2169f33b 12042 gcc_checking_assert (!need_old || !need_new);
cb7f680b 12043
75a70cf9 12044 if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
cb7f680b 12045 return false;
12046
cb7f680b 12047 /* Check for one of the supported fetch-op operations. */
1cd6e20d 12048 code = gimple_assign_rhs_code (stmt);
12049 switch (code)
cb7f680b 12050 {
12051 case PLUS_EXPR:
12052 case POINTER_PLUS_EXPR:
1cd6e20d 12053 oldbase = BUILT_IN_ATOMIC_FETCH_ADD_N;
12054 newbase = BUILT_IN_ATOMIC_ADD_FETCH_N;
cb7f680b 12055 break;
12056 case MINUS_EXPR:
1cd6e20d 12057 oldbase = BUILT_IN_ATOMIC_FETCH_SUB_N;
12058 newbase = BUILT_IN_ATOMIC_SUB_FETCH_N;
cb7f680b 12059 break;
12060 case BIT_AND_EXPR:
1cd6e20d 12061 oldbase = BUILT_IN_ATOMIC_FETCH_AND_N;
12062 newbase = BUILT_IN_ATOMIC_AND_FETCH_N;
cb7f680b 12063 break;
12064 case BIT_IOR_EXPR:
1cd6e20d 12065 oldbase = BUILT_IN_ATOMIC_FETCH_OR_N;
12066 newbase = BUILT_IN_ATOMIC_OR_FETCH_N;
cb7f680b 12067 break;
12068 case BIT_XOR_EXPR:
1cd6e20d 12069 oldbase = BUILT_IN_ATOMIC_FETCH_XOR_N;
12070 newbase = BUILT_IN_ATOMIC_XOR_FETCH_N;
cb7f680b 12071 break;
12072 default:
12073 return false;
12074 }
1cd6e20d 12075
cb7f680b 12076 /* Make sure the expression is of the proper form. */
75a70cf9 12077 if (operand_equal_p (gimple_assign_rhs1 (stmt), loaded_val, 0))
12078 rhs = gimple_assign_rhs2 (stmt);
12079 else if (commutative_tree_code (gimple_assign_rhs_code (stmt))
12080 && operand_equal_p (gimple_assign_rhs2 (stmt), loaded_val, 0))
12081 rhs = gimple_assign_rhs1 (stmt);
cb7f680b 12082 else
12083 return false;
12084
b9a16870 12085 tmpbase = ((enum built_in_function)
12086 ((need_new ? newbase : oldbase) + index + 1));
12087 decl = builtin_decl_explicit (tmpbase);
0f94f46b 12088 if (decl == NULL_TREE)
12089 return false;
cb7f680b 12090 itype = TREE_TYPE (TREE_TYPE (decl));
1cd6e20d 12091 imode = TYPE_MODE (itype);
cb7f680b 12092
1cd6e20d 12093 /* We could test all of the various optabs involved, but the fact of the
12094 matter is that (with the exception of i486 vs i586 and xadd) all targets
12095 that support any atomic operaton optab also implements compare-and-swap.
12096 Let optabs.c take care of expanding any compare-and-swap loop. */
29139cdc 12097 if (!can_compare_and_swap_p (imode, true))
cb7f680b 12098 return false;
12099
75a70cf9 12100 gsi = gsi_last_bb (load_bb);
12101 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
1cd6e20d 12102
12103 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
12104 It only requires that the operation happen atomically. Thus we can
12105 use the RELAXED memory model. */
12106 call = build_call_expr_loc (loc, decl, 3, addr,
12107 fold_convert_loc (loc, itype, rhs),
bc7bff74 12108 build_int_cst (NULL,
12109 seq_cst ? MEMMODEL_SEQ_CST
12110 : MEMMODEL_RELAXED));
1cd6e20d 12111
2169f33b 12112 if (need_old || need_new)
12113 {
12114 lhs = need_old ? loaded_val : stored_val;
12115 call = fold_convert_loc (loc, TREE_TYPE (lhs), call);
12116 call = build2_loc (loc, MODIFY_EXPR, void_type_node, lhs, call);
12117 }
12118 else
12119 call = fold_convert_loc (loc, void_type_node, call);
75a70cf9 12120 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
12121 gsi_remove (&gsi, true);
cb7f680b 12122
75a70cf9 12123 gsi = gsi_last_bb (store_bb);
12124 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
12125 gsi_remove (&gsi, true);
12126 gsi = gsi_last_bb (store_bb);
97d59451 12127 stmt = gsi_stmt (gsi);
75a70cf9 12128 gsi_remove (&gsi, true);
cb7f680b 12129
12130 if (gimple_in_ssa_p (cfun))
97d59451 12131 {
12132 release_defs (stmt);
12133 update_ssa (TODO_update_ssa_no_phi);
12134 }
cb7f680b 12135
12136 return true;
12137}
12138
12139/* A subroutine of expand_omp_atomic. Implement the atomic operation as:
12140
12141 oldval = *addr;
12142 repeat:
12143 newval = rhs; // with oldval replacing *addr in rhs
12144 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
12145 if (oldval != newval)
12146 goto repeat;
12147
12148 INDEX is log2 of the size of the data type, and thus usable to find the
12149 index of the builtin decl. */
12150
12151static bool
12152expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
12153 tree addr, tree loaded_val, tree stored_val,
12154 int index)
12155{
790368c5 12156 tree loadedi, storedi, initial, new_storedi, old_vali;
cb7f680b 12157 tree type, itype, cmpxchg, iaddr;
75a70cf9 12158 gimple_stmt_iterator si;
cb7f680b 12159 basic_block loop_header = single_succ (load_bb);
42acab1c 12160 gimple *phi, *stmt;
cb7f680b 12161 edge e;
b9a16870 12162 enum built_in_function fncode;
cb7f680b 12163
1cd6e20d 12164 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
12165 order to use the RELAXED memory model effectively. */
b9a16870 12166 fncode = (enum built_in_function)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
12167 + index + 1);
12168 cmpxchg = builtin_decl_explicit (fncode);
0f94f46b 12169 if (cmpxchg == NULL_TREE)
12170 return false;
cb7f680b 12171 type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
12172 itype = TREE_TYPE (TREE_TYPE (cmpxchg));
12173
29139cdc 12174 if (!can_compare_and_swap_p (TYPE_MODE (itype), true))
cb7f680b 12175 return false;
12176
75a70cf9 12177 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
12178 si = gsi_last_bb (load_bb);
12179 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
12180
790368c5 12181 /* For floating-point values, we'll need to view-convert them to integers
12182 so that we can perform the atomic compare and swap. Simplify the
12183 following code by always setting up the "i"ntegral variables. */
12184 if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
12185 {
75a70cf9 12186 tree iaddr_val;
12187
072f7ab1 12188 iaddr = create_tmp_reg (build_pointer_type_for_mode (itype, ptr_mode,
f9e245b2 12189 true));
75a70cf9 12190 iaddr_val
12191 = force_gimple_operand_gsi (&si,
12192 fold_convert (TREE_TYPE (iaddr), addr),
12193 false, NULL_TREE, true, GSI_SAME_STMT);
12194 stmt = gimple_build_assign (iaddr, iaddr_val);
12195 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
f9e245b2 12196 loadedi = create_tmp_var (itype);
790368c5 12197 if (gimple_in_ssa_p (cfun))
f9e245b2 12198 loadedi = make_ssa_name (loadedi);
790368c5 12199 }
12200 else
12201 {
12202 iaddr = addr;
12203 loadedi = loaded_val;
12204 }
75a70cf9 12205
2ed72821 12206 fncode = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
12207 tree loaddecl = builtin_decl_explicit (fncode);
12208 if (loaddecl)
12209 initial
12210 = fold_convert (TREE_TYPE (TREE_TYPE (iaddr)),
12211 build_call_expr (loaddecl, 2, iaddr,
12212 build_int_cst (NULL_TREE,
12213 MEMMODEL_RELAXED)));
12214 else
12215 initial = build2 (MEM_REF, TREE_TYPE (TREE_TYPE (iaddr)), iaddr,
12216 build_int_cst (TREE_TYPE (iaddr), 0));
12217
182cf5a9 12218 initial
2ed72821 12219 = force_gimple_operand_gsi (&si, initial, true, NULL_TREE, true,
12220 GSI_SAME_STMT);
790368c5 12221
12222 /* Move the value to the LOADEDI temporary. */
cb7f680b 12223 if (gimple_in_ssa_p (cfun))
12224 {
75a70cf9 12225 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header)));
790368c5 12226 phi = create_phi_node (loadedi, loop_header);
cb7f680b 12227 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)),
12228 initial);
12229 }
12230 else
75a70cf9 12231 gsi_insert_before (&si,
12232 gimple_build_assign (loadedi, initial),
12233 GSI_SAME_STMT);
790368c5 12234 if (loadedi != loaded_val)
12235 {
75a70cf9 12236 gimple_stmt_iterator gsi2;
12237 tree x;
790368c5 12238
12239 x = build1 (VIEW_CONVERT_EXPR, type, loadedi);
75a70cf9 12240 gsi2 = gsi_start_bb (loop_header);
790368c5 12241 if (gimple_in_ssa_p (cfun))
12242 {
1a91d914 12243 gassign *stmt;
75a70cf9 12244 x = force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
12245 true, GSI_SAME_STMT);
12246 stmt = gimple_build_assign (loaded_val, x);
12247 gsi_insert_before (&gsi2, stmt, GSI_SAME_STMT);
790368c5 12248 }
12249 else
12250 {
75a70cf9 12251 x = build2 (MODIFY_EXPR, TREE_TYPE (loaded_val), loaded_val, x);
12252 force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
12253 true, GSI_SAME_STMT);
790368c5 12254 }
12255 }
75a70cf9 12256 gsi_remove (&si, true);
cb7f680b 12257
75a70cf9 12258 si = gsi_last_bb (store_bb);
12259 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
cb7f680b 12260
790368c5 12261 if (iaddr == addr)
12262 storedi = stored_val;
cb7f680b 12263 else
790368c5 12264 storedi =
75a70cf9 12265 force_gimple_operand_gsi (&si,
790368c5 12266 build1 (VIEW_CONVERT_EXPR, itype,
12267 stored_val), true, NULL_TREE, true,
75a70cf9 12268 GSI_SAME_STMT);
cb7f680b 12269
12270 /* Build the compare&swap statement. */
12271 new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi);
75a70cf9 12272 new_storedi = force_gimple_operand_gsi (&si,
87f9ffa4 12273 fold_convert (TREE_TYPE (loadedi),
12274 new_storedi),
cb7f680b 12275 true, NULL_TREE,
75a70cf9 12276 true, GSI_SAME_STMT);
cb7f680b 12277
12278 if (gimple_in_ssa_p (cfun))
12279 old_vali = loadedi;
12280 else
12281 {
f9e245b2 12282 old_vali = create_tmp_var (TREE_TYPE (loadedi));
75a70cf9 12283 stmt = gimple_build_assign (old_vali, loadedi);
12284 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
cb7f680b 12285
75a70cf9 12286 stmt = gimple_build_assign (loadedi, new_storedi);
12287 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
cb7f680b 12288 }
12289
12290 /* Note that we always perform the comparison as an integer, even for
48e1416a 12291 floating point. This allows the atomic operation to properly
cb7f680b 12292 succeed even with NaNs and -0.0. */
75a70cf9 12293 stmt = gimple_build_cond_empty
12294 (build2 (NE_EXPR, boolean_type_node,
12295 new_storedi, old_vali));
12296 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
cb7f680b 12297
12298 /* Update cfg. */
12299 e = single_succ_edge (store_bb);
12300 e->flags &= ~EDGE_FALLTHRU;
12301 e->flags |= EDGE_FALSE_VALUE;
12302
12303 e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE);
12304
790368c5 12305 /* Copy the new value to loadedi (we already did that before the condition
cb7f680b 12306 if we are not in SSA). */
12307 if (gimple_in_ssa_p (cfun))
12308 {
75a70cf9 12309 phi = gimple_seq_first_stmt (phi_nodes (loop_header));
790368c5 12310 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), new_storedi);
cb7f680b 12311 }
12312
75a70cf9 12313 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
12314 gsi_remove (&si, true);
cb7f680b 12315
04c2922b 12316 struct loop *loop = alloc_loop ();
12317 loop->header = loop_header;
5f037457 12318 loop->latch = store_bb;
04c2922b 12319 add_loop (loop, loop_header->loop_father);
12320
cb7f680b 12321 if (gimple_in_ssa_p (cfun))
12322 update_ssa (TODO_update_ssa_no_phi);
12323
12324 return true;
12325}
12326
12327/* A subroutine of expand_omp_atomic. Implement the atomic operation as:
12328
12329 GOMP_atomic_start ();
12330 *addr = rhs;
12331 GOMP_atomic_end ();
12332
12333 The result is not globally atomic, but works so long as all parallel
12334 references are within #pragma omp atomic directives. According to
12335 responses received from omp@openmp.org, appears to be within spec.
12336 Which makes sense, since that's how several other compilers handle
48e1416a 12337 this situation as well.
75a70cf9 12338 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
12339 expanding. STORED_VAL is the operand of the matching
12340 GIMPLE_OMP_ATOMIC_STORE.
cb7f680b 12341
48e1416a 12342 We replace
12343 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
cb7f680b 12344 loaded_val = *addr;
12345
12346 and replace
3ec11c49 12347 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
48e1416a 12348 *addr = stored_val;
cb7f680b 12349*/
12350
12351static bool
12352expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
12353 tree addr, tree loaded_val, tree stored_val)
12354{
75a70cf9 12355 gimple_stmt_iterator si;
1a91d914 12356 gassign *stmt;
cb7f680b 12357 tree t;
12358
75a70cf9 12359 si = gsi_last_bb (load_bb);
12360 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
cb7f680b 12361
b9a16870 12362 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
414c3a2c 12363 t = build_call_expr (t, 0);
75a70cf9 12364 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
cb7f680b 12365
182cf5a9 12366 stmt = gimple_build_assign (loaded_val, build_simple_mem_ref (addr));
75a70cf9 12367 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
12368 gsi_remove (&si, true);
cb7f680b 12369
75a70cf9 12370 si = gsi_last_bb (store_bb);
12371 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
cb7f680b 12372
182cf5a9 12373 stmt = gimple_build_assign (build_simple_mem_ref (unshare_expr (addr)),
12374 stored_val);
75a70cf9 12375 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
cb7f680b 12376
b9a16870 12377 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
414c3a2c 12378 t = build_call_expr (t, 0);
75a70cf9 12379 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
12380 gsi_remove (&si, true);
cb7f680b 12381
12382 if (gimple_in_ssa_p (cfun))
12383 update_ssa (TODO_update_ssa_no_phi);
12384 return true;
12385}
12386
48e1416a 12387/* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
12388 using expand_omp_atomic_fetch_op. If it failed, we try to
cb7f680b 12389 call expand_omp_atomic_pipeline, and if it fails too, the
12390 ultimate fallback is wrapping the operation in a mutex
48e1416a 12391 (expand_omp_atomic_mutex). REGION is the atomic region built
12392 by build_omp_regions_1(). */
cb7f680b 12393
12394static void
12395expand_omp_atomic (struct omp_region *region)
12396{
12397 basic_block load_bb = region->entry, store_bb = region->exit;
1a91d914 12398 gomp_atomic_load *load = as_a <gomp_atomic_load *> (last_stmt (load_bb));
12399 gomp_atomic_store *store = as_a <gomp_atomic_store *> (last_stmt (store_bb));
75a70cf9 12400 tree loaded_val = gimple_omp_atomic_load_lhs (load);
12401 tree addr = gimple_omp_atomic_load_rhs (load);
12402 tree stored_val = gimple_omp_atomic_store_val (store);
cb7f680b 12403 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
12404 HOST_WIDE_INT index;
12405
12406 /* Make sure the type is one of the supported sizes. */
e913b5cd 12407 index = tree_to_uhwi (TYPE_SIZE_UNIT (type));
cb7f680b 12408 index = exact_log2 (index);
12409 if (index >= 0 && index <= 4)
12410 {
12411 unsigned int align = TYPE_ALIGN_UNIT (type);
12412
12413 /* __sync builtins require strict data alignment. */
dcf7024c 12414 if (exact_log2 (align) >= index)
cb7f680b 12415 {
3ec11c49 12416 /* Atomic load. */
2169f33b 12417 if (loaded_val == stored_val
12418 && (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
12419 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
12420 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
3ec11c49 12421 && expand_omp_atomic_load (load_bb, addr, loaded_val, index))
2169f33b 12422 return;
12423
3ec11c49 12424 /* Atomic store. */
2169f33b 12425 if ((GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
12426 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
12427 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
12428 && store_bb == single_succ (load_bb)
12429 && first_stmt (store_bb) == store
3ec11c49 12430 && expand_omp_atomic_store (load_bb, addr, loaded_val,
12431 stored_val, index))
2169f33b 12432 return;
12433
cb7f680b 12434 /* When possible, use specialized atomic update functions. */
12435 if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
3ec11c49 12436 && store_bb == single_succ (load_bb)
12437 && expand_omp_atomic_fetch_op (load_bb, addr,
12438 loaded_val, stored_val, index))
12439 return;
cb7f680b 12440
12441 /* If we don't have specialized __sync builtins, try and implement
12442 as a compare and swap loop. */
12443 if (expand_omp_atomic_pipeline (load_bb, store_bb, addr,
12444 loaded_val, stored_val, index))
12445 return;
12446 }
12447 }
12448
12449 /* The ultimate fallback is wrapping the operation in a mutex. */
12450 expand_omp_atomic_mutex (load_bb, store_bb, addr, loaded_val, stored_val);
12451}
12452
1e8e9920 12453
f69b8a4c 12454/* Encode an oacc launch argument. This matches the GOMP_LAUNCH_PACK
e561d5e1 12455 macro on gomp-constants.h. We do not check for overflow. */
12456
12457static tree
12458oacc_launch_pack (unsigned code, tree device, unsigned op)
12459{
12460 tree res;
12461
12462 res = build_int_cst (unsigned_type_node, GOMP_LAUNCH_PACK (code, 0, op));
12463 if (device)
12464 {
12465 device = fold_build2 (LSHIFT_EXPR, unsigned_type_node,
12466 device, build_int_cst (unsigned_type_node,
12467 GOMP_LAUNCH_DEVICE_SHIFT));
12468 res = fold_build2 (BIT_IOR_EXPR, unsigned_type_node, res, device);
12469 }
12470 return res;
12471}
12472
12473/* Look for compute grid dimension clauses and convert to an attribute
12474 attached to FN. This permits the target-side code to (a) massage
12475 the dimensions, (b) emit that data and (c) optimize. Non-constant
12476 dimensions are pushed onto ARGS.
12477
12478 The attribute value is a TREE_LIST. A set of dimensions is
12479 represented as a list of INTEGER_CST. Those that are runtime
f69b8a4c 12480 exprs are represented as an INTEGER_CST of zero.
e561d5e1 12481
12482 TOOO. Normally the attribute will just contain a single such list. If
12483 however it contains a list of lists, this will represent the use of
12484 device_type. Each member of the outer list is an assoc list of
12485 dimensions, keyed by the device type. The first entry will be the
12486 default. Well, that's the plan. */
12487
12488#define OACC_FN_ATTRIB "oacc function"
12489
12490/* Replace any existing oacc fn attribute with updated dimensions. */
12491
12492void
12493replace_oacc_fn_attrib (tree fn, tree dims)
12494{
12495 tree ident = get_identifier (OACC_FN_ATTRIB);
12496 tree attribs = DECL_ATTRIBUTES (fn);
12497
12498 /* If we happen to be present as the first attrib, drop it. */
12499 if (attribs && TREE_PURPOSE (attribs) == ident)
12500 attribs = TREE_CHAIN (attribs);
12501 DECL_ATTRIBUTES (fn) = tree_cons (ident, dims, attribs);
12502}
12503
12504/* Scan CLAUSES for launch dimensions and attach them to the oacc
12505 function attribute. Push any that are non-constant onto the ARGS
6f431819 12506 list, along with an appropriate GOMP_LAUNCH_DIM tag. IS_KERNEL is
12507 true, if these are for a kernels region offload function. */
e561d5e1 12508
31c2b13b 12509void
6f431819 12510set_oacc_fn_attrib (tree fn, tree clauses, bool is_kernel, vec<tree> *args)
e561d5e1 12511{
12512 /* Must match GOMP_DIM ordering. */
12513 static const omp_clause_code ids[]
12514 = { OMP_CLAUSE_NUM_GANGS, OMP_CLAUSE_NUM_WORKERS,
12515 OMP_CLAUSE_VECTOR_LENGTH };
12516 unsigned ix;
12517 tree dims[GOMP_DIM_MAX];
12518 tree attr = NULL_TREE;
12519 unsigned non_const = 0;
12520
12521 for (ix = GOMP_DIM_MAX; ix--;)
12522 {
12523 tree clause = find_omp_clause (clauses, ids[ix]);
12524 tree dim = NULL_TREE;
12525
12526 if (clause)
12527 dim = OMP_CLAUSE_EXPR (clause, ids[ix]);
12528 dims[ix] = dim;
12529 if (dim && TREE_CODE (dim) != INTEGER_CST)
12530 {
12531 dim = integer_zero_node;
12532 non_const |= GOMP_DIM_MASK (ix);
12533 }
12534 attr = tree_cons (NULL_TREE, dim, attr);
6f431819 12535 /* Note kernelness with TREE_PUBLIC. */
12536 if (is_kernel)
12537 TREE_PUBLIC (attr) = 1;
e561d5e1 12538 }
12539
12540 replace_oacc_fn_attrib (fn, attr);
12541
12542 if (non_const)
12543 {
12544 /* Push a dynamic argument set. */
12545 args->safe_push (oacc_launch_pack (GOMP_LAUNCH_DIM,
12546 NULL_TREE, non_const));
12547 for (unsigned ix = 0; ix != GOMP_DIM_MAX; ix++)
12548 if (non_const & GOMP_DIM_MASK (ix))
12549 args->safe_push (dims[ix]);
12550 }
12551}
12552
a1b7fe4b 12553/* Process the routine's dimension clauess to generate an attribute
12554 value. Issue diagnostics as appropriate. We default to SEQ
12555 (OpenACC 2.5 clarifies this). All dimensions have a size of zero
12556 (dynamic). TREE_PURPOSE is set to indicate whether that dimension
12557 can have a loop partitioned on it. non-zero indicates
12558 yes, zero indicates no. By construction once a non-zero has been
12559 reached, further inner dimensions must also be non-zero. We set
12560 TREE_VALUE to zero for the dimensions that may be partitioned and
12561 1 for the other ones -- if a loop is (erroneously) spawned at
12562 an outer level, we don't want to try and partition it. */
12563
12564tree
12565build_oacc_routine_dims (tree clauses)
12566{
12567 /* Must match GOMP_DIM ordering. */
12568 static const omp_clause_code ids[] =
12569 {OMP_CLAUSE_GANG, OMP_CLAUSE_WORKER, OMP_CLAUSE_VECTOR, OMP_CLAUSE_SEQ};
12570 int ix;
12571 int level = -1;
12572
12573 for (; clauses; clauses = OMP_CLAUSE_CHAIN (clauses))
12574 for (ix = GOMP_DIM_MAX + 1; ix--;)
12575 if (OMP_CLAUSE_CODE (clauses) == ids[ix])
12576 {
12577 if (level >= 0)
12578 error_at (OMP_CLAUSE_LOCATION (clauses),
12579 "multiple loop axes specified for routine");
12580 level = ix;
12581 break;
12582 }
12583
12584 /* Default to SEQ. */
12585 if (level < 0)
12586 level = GOMP_DIM_MAX;
12587
12588 tree dims = NULL_TREE;
12589
12590 for (ix = GOMP_DIM_MAX; ix--;)
12591 dims = tree_cons (build_int_cst (boolean_type_node, ix >= level),
12592 build_int_cst (integer_type_node, ix < level), dims);
12593
12594 return dims;
12595}
12596
e561d5e1 12597/* Retrieve the oacc function attrib and return it. Non-oacc
12598 functions will return NULL. */
12599
12600tree
12601get_oacc_fn_attrib (tree fn)
12602{
12603 return lookup_attribute (OACC_FN_ATTRIB, DECL_ATTRIBUTES (fn));
12604}
12605
6f431819 12606/* Return true if this oacc fn attrib is for a kernels offload
12607 region. We use the TREE_PUBLIC flag of each dimension -- only
12608 need to check the first one. */
12609
12610bool
12611oacc_fn_attrib_kernels_p (tree attr)
12612{
12613 return TREE_PUBLIC (TREE_VALUE (attr));
12614}
12615
12616/* Return level at which oacc routine may spawn a partitioned loop, or
12617 -1 if it is not a routine (i.e. is an offload fn). */
12618
12619static int
12620oacc_fn_attrib_level (tree attr)
12621{
12622 tree pos = TREE_VALUE (attr);
12623
12624 if (!TREE_PURPOSE (pos))
12625 return -1;
12626
12627 int ix = 0;
12628 for (ix = 0; ix != GOMP_DIM_MAX;
12629 ix++, pos = TREE_CHAIN (pos))
12630 if (!integer_zerop (TREE_PURPOSE (pos)))
12631 break;
12632
12633 return ix;
12634}
12635
e1037942 12636/* Extract an oacc execution dimension from FN. FN must be an
12637 offloaded function or routine that has already had its execution
12638 dimensions lowered to the target-specific values. */
12639
12640int
12641get_oacc_fn_dim_size (tree fn, int axis)
12642{
12643 tree attrs = get_oacc_fn_attrib (fn);
12644
12645 gcc_assert (axis < GOMP_DIM_MAX);
12646
12647 tree dims = TREE_VALUE (attrs);
12648 while (axis--)
12649 dims = TREE_CHAIN (dims);
12650
12651 int size = TREE_INT_CST_LOW (TREE_VALUE (dims));
12652
12653 return size;
12654}
12655
12656/* Extract the dimension axis from an IFN_GOACC_DIM_POS or
12657 IFN_GOACC_DIM_SIZE call. */
12658
12659int
12660get_oacc_ifn_dim_arg (const gimple *stmt)
12661{
12662 gcc_checking_assert (gimple_call_internal_fn (stmt) == IFN_GOACC_DIM_SIZE
12663 || gimple_call_internal_fn (stmt) == IFN_GOACC_DIM_POS);
12664 tree arg = gimple_call_arg (stmt, 0);
12665 HOST_WIDE_INT axis = TREE_INT_CST_LOW (arg);
12666
12667 gcc_checking_assert (axis >= 0 && axis < GOMP_DIM_MAX);
12668 return (int) axis;
12669}
12670
1a40f20b 12671/* Mark the loops inside the kernels region starting at REGION_ENTRY and ending
12672 at REGION_EXIT. */
12673
12674static void
12675mark_loops_in_oacc_kernels_region (basic_block region_entry,
12676 basic_block region_exit)
12677{
12678 struct loop *outer = region_entry->loop_father;
12679 gcc_assert (region_exit == NULL || outer == region_exit->loop_father);
12680
12681 /* Don't parallelize the kernels region if it contains more than one outer
12682 loop. */
12683 unsigned int nr_outer_loops = 0;
4dae4a1a 12684 struct loop *single_outer = NULL;
1a40f20b 12685 for (struct loop *loop = outer->inner; loop != NULL; loop = loop->next)
12686 {
12687 gcc_assert (loop_outer (loop) == outer);
12688
12689 if (!dominated_by_p (CDI_DOMINATORS, loop->header, region_entry))
12690 continue;
12691
12692 if (region_exit != NULL
12693 && dominated_by_p (CDI_DOMINATORS, loop->header, region_exit))
12694 continue;
12695
12696 nr_outer_loops++;
12697 single_outer = loop;
12698 }
12699 if (nr_outer_loops != 1)
12700 return;
12701
12702 for (struct loop *loop = single_outer->inner; loop != NULL; loop = loop->inner)
12703 if (loop->next)
12704 return;
12705
12706 /* Mark the loops in the region. */
12707 for (struct loop *loop = single_outer; loop != NULL; loop = loop->inner)
12708 loop->in_oacc_kernels_region = true;
12709}
12710
56686608 12711/* Types used to pass grid and wortkgroup sizes to kernel invocation. */
12712
12713struct GTY(()) grid_launch_attributes_trees
12714{
12715 tree kernel_dim_array_type;
12716 tree kernel_lattrs_dimnum_decl;
12717 tree kernel_lattrs_grid_decl;
12718 tree kernel_lattrs_group_decl;
12719 tree kernel_launch_attributes_type;
12720};
12721
12722static GTY(()) struct grid_launch_attributes_trees *grid_attr_trees;
12723
12724/* Create types used to pass kernel launch attributes to target. */
12725
12726static void
12727grid_create_kernel_launch_attr_types (void)
12728{
12729 if (grid_attr_trees)
12730 return;
12731 grid_attr_trees = ggc_alloc <grid_launch_attributes_trees> ();
12732
12733 tree dim_arr_index_type
12734 = build_index_type (build_int_cst (integer_type_node, 2));
12735 grid_attr_trees->kernel_dim_array_type
12736 = build_array_type (uint32_type_node, dim_arr_index_type);
12737
12738 grid_attr_trees->kernel_launch_attributes_type = make_node (RECORD_TYPE);
12739 grid_attr_trees->kernel_lattrs_dimnum_decl
12740 = build_decl (BUILTINS_LOCATION, FIELD_DECL, get_identifier ("ndim"),
12741 uint32_type_node);
12742 DECL_CHAIN (grid_attr_trees->kernel_lattrs_dimnum_decl) = NULL_TREE;
12743
12744 grid_attr_trees->kernel_lattrs_grid_decl
12745 = build_decl (BUILTINS_LOCATION, FIELD_DECL, get_identifier ("grid_size"),
12746 grid_attr_trees->kernel_dim_array_type);
12747 DECL_CHAIN (grid_attr_trees->kernel_lattrs_grid_decl)
12748 = grid_attr_trees->kernel_lattrs_dimnum_decl;
12749 grid_attr_trees->kernel_lattrs_group_decl
12750 = build_decl (BUILTINS_LOCATION, FIELD_DECL, get_identifier ("group_size"),
12751 grid_attr_trees->kernel_dim_array_type);
12752 DECL_CHAIN (grid_attr_trees->kernel_lattrs_group_decl)
12753 = grid_attr_trees->kernel_lattrs_grid_decl;
12754 finish_builtin_struct (grid_attr_trees->kernel_launch_attributes_type,
12755 "__gomp_kernel_launch_attributes",
12756 grid_attr_trees->kernel_lattrs_group_decl, NULL_TREE);
12757}
12758
12759/* Insert before the current statement in GSI a store of VALUE to INDEX of
12760 array (of type kernel_dim_array_type) FLD_DECL of RANGE_VAR. VALUE must be
12761 of type uint32_type_node. */
12762
12763static void
12764grid_insert_store_range_dim (gimple_stmt_iterator *gsi, tree range_var,
12765 tree fld_decl, int index, tree value)
12766{
12767 tree ref = build4 (ARRAY_REF, uint32_type_node,
12768 build3 (COMPONENT_REF,
12769 grid_attr_trees->kernel_dim_array_type,
12770 range_var, fld_decl, NULL_TREE),
12771 build_int_cst (integer_type_node, index),
12772 NULL_TREE, NULL_TREE);
12773 gsi_insert_before (gsi, gimple_build_assign (ref, value), GSI_SAME_STMT);
12774}
12775
12776/* Return a tree representation of a pointer to a structure with grid and
12777 work-group size information. Statements filling that information will be
12778 inserted before GSI, TGT_STMT is the target statement which has the
12779 necessary information in it. */
12780
12781static tree
12782grid_get_kernel_launch_attributes (gimple_stmt_iterator *gsi,
12783 gomp_target *tgt_stmt)
12784{
12785 grid_create_kernel_launch_attr_types ();
12786 tree u32_one = build_one_cst (uint32_type_node);
12787 tree lattrs = create_tmp_var (grid_attr_trees->kernel_launch_attributes_type,
12788 "__kernel_launch_attrs");
12789
12790 unsigned max_dim = 0;
12791 for (tree clause = gimple_omp_target_clauses (tgt_stmt);
12792 clause;
12793 clause = OMP_CLAUSE_CHAIN (clause))
12794 {
12795 if (OMP_CLAUSE_CODE (clause) != OMP_CLAUSE__GRIDDIM_)
12796 continue;
12797
12798 unsigned dim = OMP_CLAUSE__GRIDDIM__DIMENSION (clause);
12799 max_dim = MAX (dim, max_dim);
12800
12801 grid_insert_store_range_dim (gsi, lattrs,
12802 grid_attr_trees->kernel_lattrs_grid_decl,
12803 dim, OMP_CLAUSE__GRIDDIM__SIZE (clause));
12804 grid_insert_store_range_dim (gsi, lattrs,
12805 grid_attr_trees->kernel_lattrs_group_decl,
12806 dim, OMP_CLAUSE__GRIDDIM__GROUP (clause));
12807 }
12808
12809 tree dimref = build3 (COMPONENT_REF, uint32_type_node, lattrs,
12810 grid_attr_trees->kernel_lattrs_dimnum_decl, NULL_TREE);
12811 /* At this moment we cannot gridify a loop with a collapse clause. */
12812 /* TODO: Adjust when we support bigger collapse. */
12813 gcc_assert (max_dim == 0);
12814 gsi_insert_before (gsi, gimple_build_assign (dimref, u32_one), GSI_SAME_STMT);
12815 TREE_ADDRESSABLE (lattrs) = 1;
12816 return build_fold_addr_expr (lattrs);
12817}
12818
12819/* Build target argument identifier from the DEVICE identifier, value
12820 identifier ID and whether the element also has a SUBSEQUENT_PARAM. */
12821
12822static tree
12823get_target_argument_identifier_1 (int device, bool subseqent_param, int id)
12824{
12825 tree t = build_int_cst (integer_type_node, device);
12826 if (subseqent_param)
12827 t = fold_build2 (BIT_IOR_EXPR, integer_type_node, t,
12828 build_int_cst (integer_type_node,
12829 GOMP_TARGET_ARG_SUBSEQUENT_PARAM));
12830 t = fold_build2 (BIT_IOR_EXPR, integer_type_node, t,
12831 build_int_cst (integer_type_node, id));
12832 return t;
12833}
12834
12835/* Like above but return it in type that can be directly stored as an element
12836 of the argument array. */
12837
12838static tree
12839get_target_argument_identifier (int device, bool subseqent_param, int id)
12840{
12841 tree t = get_target_argument_identifier_1 (device, subseqent_param, id);
12842 return fold_convert (ptr_type_node, t);
12843}
12844
12845/* Return a target argument consisting of DEVICE identifier, value identifier
12846 ID, and the actual VALUE. */
12847
12848static tree
12849get_target_argument_value (gimple_stmt_iterator *gsi, int device, int id,
12850 tree value)
12851{
12852 tree t = fold_build2 (LSHIFT_EXPR, integer_type_node,
12853 fold_convert (integer_type_node, value),
12854 build_int_cst (unsigned_type_node,
12855 GOMP_TARGET_ARG_VALUE_SHIFT));
12856 t = fold_build2 (BIT_IOR_EXPR, integer_type_node, t,
12857 get_target_argument_identifier_1 (device, false, id));
12858 t = fold_convert (ptr_type_node, t);
12859 return force_gimple_operand_gsi (gsi, t, true, NULL, true, GSI_SAME_STMT);
12860}
12861
12862/* If VALUE is an integer constant greater than -2^15 and smaller than 2^15,
12863 push one argument to ARGS with both the DEVICE, ID and VALUE embedded in it,
12864 otherwise push an identifier (with DEVICE and ID) and the VALUE in two
12865 arguments. */
12866
12867static void
12868push_target_argument_according_to_value (gimple_stmt_iterator *gsi, int device,
12869 int id, tree value, vec <tree> *args)
12870{
12871 if (tree_fits_shwi_p (value)
12872 && tree_to_shwi (value) > -(1 << 15)
12873 && tree_to_shwi (value) < (1 << 15))
12874 args->quick_push (get_target_argument_value (gsi, device, id, value));
12875 else
12876 {
12877 args->quick_push (get_target_argument_identifier (device, true, id));
12878 value = fold_convert (ptr_type_node, value);
12879 value = force_gimple_operand_gsi (gsi, value, true, NULL, true,
12880 GSI_SAME_STMT);
12881 args->quick_push (value);
12882 }
12883}
12884
12885/* Create an array of arguments that is then passed to GOMP_target. */
12886
12887static tree
12888get_target_arguments (gimple_stmt_iterator *gsi, gomp_target *tgt_stmt)
12889{
12890 auto_vec <tree, 6> args;
12891 tree clauses = gimple_omp_target_clauses (tgt_stmt);
12892 tree t, c = find_omp_clause (clauses, OMP_CLAUSE_NUM_TEAMS);
12893 if (c)
12894 t = OMP_CLAUSE_NUM_TEAMS_EXPR (c);
12895 else
12896 t = integer_minus_one_node;
12897 push_target_argument_according_to_value (gsi, GOMP_TARGET_ARG_DEVICE_ALL,
12898 GOMP_TARGET_ARG_NUM_TEAMS, t, &args);
12899
12900 c = find_omp_clause (clauses, OMP_CLAUSE_THREAD_LIMIT);
12901 if (c)
12902 t = OMP_CLAUSE_THREAD_LIMIT_EXPR (c);
12903 else
12904 t = integer_minus_one_node;
12905 push_target_argument_according_to_value (gsi, GOMP_TARGET_ARG_DEVICE_ALL,
12906 GOMP_TARGET_ARG_THREAD_LIMIT, t,
12907 &args);
12908
12909 /* Add HSA-specific grid sizes, if available. */
12910 if (find_omp_clause (gimple_omp_target_clauses (tgt_stmt),
12911 OMP_CLAUSE__GRIDDIM_))
12912 {
12913 t = get_target_argument_identifier (GOMP_DEVICE_HSA, true,
12914 GOMP_TARGET_ARG_HSA_KERNEL_ATTRIBUTES);
12915 args.quick_push (t);
12916 args.quick_push (grid_get_kernel_launch_attributes (gsi, tgt_stmt));
12917 }
12918
12919 /* Produce more, perhaps device specific, arguments here. */
12920
12921 tree argarray = create_tmp_var (build_array_type_nelts (ptr_type_node,
12922 args.length () + 1),
12923 ".omp_target_args");
12924 for (unsigned i = 0; i < args.length (); i++)
12925 {
12926 tree ref = build4 (ARRAY_REF, ptr_type_node, argarray,
12927 build_int_cst (integer_type_node, i),
12928 NULL_TREE, NULL_TREE);
12929 gsi_insert_before (gsi, gimple_build_assign (ref, args[i]),
12930 GSI_SAME_STMT);
12931 }
12932 tree ref = build4 (ARRAY_REF, ptr_type_node, argarray,
12933 build_int_cst (integer_type_node, args.length ()),
12934 NULL_TREE, NULL_TREE);
12935 gsi_insert_before (gsi, gimple_build_assign (ref, null_pointer_node),
12936 GSI_SAME_STMT);
12937 TREE_ADDRESSABLE (argarray) = 1;
12938 return build_fold_addr_expr (argarray);
12939}
12940
ca4c3545 12941/* Expand the GIMPLE_OMP_TARGET starting at REGION. */
773c5ba7 12942
12943static void
bc7bff74 12944expand_omp_target (struct omp_region *region)
773c5ba7 12945{
bc7bff74 12946 basic_block entry_bb, exit_bb, new_bb;
ca4c3545 12947 struct function *child_cfun;
12948 tree child_fn, block, t;
bc7bff74 12949 gimple_stmt_iterator gsi;
1a91d914 12950 gomp_target *entry_stmt;
42acab1c 12951 gimple *stmt;
bc7bff74 12952 edge e;
ca4c3545 12953 bool offloaded, data_region;
bc7bff74 12954
1a91d914 12955 entry_stmt = as_a <gomp_target *> (last_stmt (region->entry));
bc7bff74 12956 new_bb = region->entry;
ca4c3545 12957
12958 offloaded = is_gimple_omp_offloaded (entry_stmt);
12959 switch (gimple_omp_target_kind (entry_stmt))
12960 {
e561d5e1 12961 case GF_OMP_TARGET_KIND_REGION:
12962 case GF_OMP_TARGET_KIND_UPDATE:
43895be5 12963 case GF_OMP_TARGET_KIND_ENTER_DATA:
12964 case GF_OMP_TARGET_KIND_EXIT_DATA:
12965 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
12966 case GF_OMP_TARGET_KIND_OACC_KERNELS:
ca4c3545 12967 case GF_OMP_TARGET_KIND_OACC_UPDATE:
12968 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
2fc5e987 12969 case GF_OMP_TARGET_KIND_OACC_DECLARE:
ca4c3545 12970 data_region = false;
12971 break;
12972 case GF_OMP_TARGET_KIND_DATA:
12973 case GF_OMP_TARGET_KIND_OACC_DATA:
571b3486 12974 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
ca4c3545 12975 data_region = true;
12976 break;
12977 default:
12978 gcc_unreachable ();
12979 }
12980
12981 child_fn = NULL_TREE;
12982 child_cfun = NULL;
12983 if (offloaded)
bc7bff74 12984 {
12985 child_fn = gimple_omp_target_child_fn (entry_stmt);
12986 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
12987 }
12988
ca4c3545 12989 /* Supported by expand_omp_taskreg, but not here. */
12990 if (child_cfun != NULL)
12991 gcc_checking_assert (!child_cfun->cfg);
12992 gcc_checking_assert (!gimple_in_ssa_p (cfun));
12993
bc7bff74 12994 entry_bb = region->entry;
12995 exit_bb = region->exit;
12996
1a40f20b 12997 if (gimple_omp_target_kind (entry_stmt) == GF_OMP_TARGET_KIND_OACC_KERNELS)
12998 mark_loops_in_oacc_kernels_region (region->entry, region->exit);
12999
ca4c3545 13000 if (offloaded)
bc7bff74 13001 {
13002 unsigned srcidx, dstidx, num;
13003
ca4c3545 13004 /* If the offloading region needs data sent from the parent
bc7bff74 13005 function, then the very first statement (except possible
ca4c3545 13006 tree profile counter updates) of the offloading body
bc7bff74 13007 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
13008 &.OMP_DATA_O is passed as an argument to the child function,
13009 we need to replace it with the argument as seen by the child
13010 function.
13011
13012 In most cases, this will end up being the identity assignment
ca4c3545 13013 .OMP_DATA_I = .OMP_DATA_I. However, if the offloading body had
bc7bff74 13014 a function call that has been inlined, the original PARM_DECL
13015 .OMP_DATA_I may have been converted into a different local
13016 variable. In which case, we need to keep the assignment. */
ca4c3545 13017 tree data_arg = gimple_omp_target_data_arg (entry_stmt);
13018 if (data_arg)
bc7bff74 13019 {
13020 basic_block entry_succ_bb = single_succ (entry_bb);
13021 gimple_stmt_iterator gsi;
13022 tree arg;
42acab1c 13023 gimple *tgtcopy_stmt = NULL;
ca4c3545 13024 tree sender = TREE_VEC_ELT (data_arg, 0);
bc7bff74 13025
13026 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
13027 {
13028 gcc_assert (!gsi_end_p (gsi));
13029 stmt = gsi_stmt (gsi);
13030 if (gimple_code (stmt) != GIMPLE_ASSIGN)
13031 continue;
13032
13033 if (gimple_num_ops (stmt) == 2)
13034 {
13035 tree arg = gimple_assign_rhs1 (stmt);
13036
13037 /* We're ignoring the subcode because we're
13038 effectively doing a STRIP_NOPS. */
13039
13040 if (TREE_CODE (arg) == ADDR_EXPR
13041 && TREE_OPERAND (arg, 0) == sender)
13042 {
13043 tgtcopy_stmt = stmt;
13044 break;
13045 }
13046 }
13047 }
13048
13049 gcc_assert (tgtcopy_stmt != NULL);
13050 arg = DECL_ARGUMENTS (child_fn);
13051
13052 gcc_assert (gimple_assign_lhs (tgtcopy_stmt) == arg);
13053 gsi_remove (&gsi, true);
13054 }
13055
13056 /* Declare local variables needed in CHILD_CFUN. */
13057 block = DECL_INITIAL (child_fn);
13058 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
ca4c3545 13059 /* The gimplifier could record temporaries in the offloading block
bc7bff74 13060 rather than in containing function's local_decls chain,
13061 which would mean cgraph missed finalizing them. Do it now. */
13062 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
13063 if (TREE_CODE (t) == VAR_DECL
13064 && TREE_STATIC (t)
13065 && !DECL_EXTERNAL (t))
97221fd7 13066 varpool_node::finalize_decl (t);
bc7bff74 13067 DECL_SAVED_TREE (child_fn) = NULL;
13068 /* We'll create a CFG for child_fn, so no gimple body is needed. */
13069 gimple_set_body (child_fn, NULL);
13070 TREE_USED (block) = 1;
13071
13072 /* Reset DECL_CONTEXT on function arguments. */
13073 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
13074 DECL_CONTEXT (t) = child_fn;
13075
ca4c3545 13076 /* Split ENTRY_BB at GIMPLE_*,
bc7bff74 13077 so that it can be moved to the child function. */
13078 gsi = gsi_last_bb (entry_bb);
13079 stmt = gsi_stmt (gsi);
ca4c3545 13080 gcc_assert (stmt
13081 && gimple_code (stmt) == gimple_code (entry_stmt));
bc7bff74 13082 e = split_block (entry_bb, stmt);
923635e7 13083 gsi_remove (&gsi, true);
bc7bff74 13084 entry_bb = e->dest;
13085 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
13086
13087 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
13088 if (exit_bb)
13089 {
13090 gsi = gsi_last_bb (exit_bb);
13091 gcc_assert (!gsi_end_p (gsi)
13092 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
13093 stmt = gimple_build_return (NULL);
13094 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
13095 gsi_remove (&gsi, true);
13096 }
13097
ca4c3545 13098 /* Move the offloading region into CHILD_CFUN. */
bc7bff74 13099
13100 block = gimple_block (entry_stmt);
13101
13102 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
13103 if (exit_bb)
13104 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
13105 /* When the OMP expansion process cannot guarantee an up-to-date
13106 loop tree arrange for the child function to fixup loops. */
13107 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
13108 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
13109
13110 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
13111 num = vec_safe_length (child_cfun->local_decls);
13112 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
13113 {
13114 t = (*child_cfun->local_decls)[srcidx];
13115 if (DECL_CONTEXT (t) == cfun->decl)
13116 continue;
13117 if (srcidx != dstidx)
13118 (*child_cfun->local_decls)[dstidx] = t;
13119 dstidx++;
13120 }
13121 if (dstidx != num)
13122 vec_safe_truncate (child_cfun->local_decls, dstidx);
13123
13124 /* Inform the callgraph about the new function. */
613f2c38 13125 child_cfun->curr_properties = cfun->curr_properties;
13126 child_cfun->has_simduid_loops |= cfun->has_simduid_loops;
13127 child_cfun->has_force_vectorize_loops |= cfun->has_force_vectorize_loops;
6a77ed3d 13128 cgraph_node *node = cgraph_node::get_create (child_fn);
13129 node->parallelized_function = 1;
415d1b9a 13130 cgraph_node::add_new_function (child_fn, true);
bc7bff74 13131
dccabdd1 13132 /* Add the new function to the offload table. */
5f3001a9 13133 if (ENABLE_OFFLOADING)
13134 vec_safe_push (offload_funcs, child_fn);
dccabdd1 13135
9561765e 13136 bool need_asm = DECL_ASSEMBLER_NAME_SET_P (current_function_decl)
13137 && !DECL_ASSEMBLER_NAME_SET_P (child_fn);
13138
bc7bff74 13139 /* Fix the callgraph edges for child_cfun. Those for cfun will be
13140 fixed in a following pass. */
13141 push_cfun (child_cfun);
9561765e 13142 if (need_asm)
13143 assign_assembler_name_if_neeeded (child_fn);
35ee1c66 13144 cgraph_edge::rebuild_edges ();
bc7bff74 13145
13146 /* Some EH regions might become dead, see PR34608. If
13147 pass_cleanup_cfg isn't the first pass to happen with the
13148 new child, these dead EH edges might cause problems.
13149 Clean them up now. */
13150 if (flag_exceptions)
13151 {
13152 basic_block bb;
13153 bool changed = false;
13154
fc00614f 13155 FOR_EACH_BB_FN (bb, cfun)
bc7bff74 13156 changed |= gimple_purge_dead_eh_edges (bb);
13157 if (changed)
13158 cleanup_tree_cfg ();
13159 }
382ecba7 13160 if (flag_checking && !loops_state_satisfies_p (LOOPS_NEED_FIXUP))
86a932e0 13161 verify_loop_structure ();
bc7bff74 13162 pop_cfun ();
9561765e 13163
13164 if (dump_file && !gimple_in_ssa_p (cfun))
13165 {
13166 omp_any_child_fn_dumped = true;
13167 dump_function_header (dump_file, child_fn, dump_flags);
13168 dump_function_to_file (child_fn, dump_file, dump_flags);
13169 }
bc7bff74 13170 }
13171
ca4c3545 13172 /* Emit a library call to launch the offloading region, or do data
bc7bff74 13173 transfers. */
43895be5 13174 tree t1, t2, t3, t4, device, cond, depend, c, clauses;
bc7bff74 13175 enum built_in_function start_ix;
13176 location_t clause_loc;
43895be5 13177 unsigned int flags_i = 0;
6f431819 13178 bool oacc_kernels_p = false;
bc7bff74 13179
ca4c3545 13180 switch (gimple_omp_target_kind (entry_stmt))
13181 {
13182 case GF_OMP_TARGET_KIND_REGION:
13183 start_ix = BUILT_IN_GOMP_TARGET;
13184 break;
13185 case GF_OMP_TARGET_KIND_DATA:
13186 start_ix = BUILT_IN_GOMP_TARGET_DATA;
13187 break;
13188 case GF_OMP_TARGET_KIND_UPDATE:
13189 start_ix = BUILT_IN_GOMP_TARGET_UPDATE;
13190 break;
43895be5 13191 case GF_OMP_TARGET_KIND_ENTER_DATA:
13192 start_ix = BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA;
13193 break;
13194 case GF_OMP_TARGET_KIND_EXIT_DATA:
13195 start_ix = BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA;
13196 flags_i |= GOMP_TARGET_FLAG_EXIT_DATA;
13197 break;
ca4c3545 13198 case GF_OMP_TARGET_KIND_OACC_KERNELS:
6f431819 13199 oacc_kernels_p = true;
13200 /* FALLTHROUGH */
13201 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
ca4c3545 13202 start_ix = BUILT_IN_GOACC_PARALLEL;
13203 break;
13204 case GF_OMP_TARGET_KIND_OACC_DATA:
2bf3f448 13205 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
ca4c3545 13206 start_ix = BUILT_IN_GOACC_DATA_START;
13207 break;
13208 case GF_OMP_TARGET_KIND_OACC_UPDATE:
13209 start_ix = BUILT_IN_GOACC_UPDATE;
13210 break;
13211 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
13212 start_ix = BUILT_IN_GOACC_ENTER_EXIT_DATA;
13213 break;
2fc5e987 13214 case GF_OMP_TARGET_KIND_OACC_DECLARE:
13215 start_ix = BUILT_IN_GOACC_DECLARE;
13216 break;
ca4c3545 13217 default:
13218 gcc_unreachable ();
13219 }
bc7bff74 13220
ca4c3545 13221 clauses = gimple_omp_target_clauses (entry_stmt);
bc7bff74 13222
ca4c3545 13223 /* By default, the value of DEVICE is GOMP_DEVICE_ICV (let runtime
13224 library choose) and there is no conditional. */
bc7bff74 13225 cond = NULL_TREE;
ca4c3545 13226 device = build_int_cst (integer_type_node, GOMP_DEVICE_ICV);
bc7bff74 13227
13228 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
13229 if (c)
13230 cond = OMP_CLAUSE_IF_EXPR (c);
13231
13232 c = find_omp_clause (clauses, OMP_CLAUSE_DEVICE);
13233 if (c)
13234 {
ca4c3545 13235 /* Even if we pass it to all library function calls, it is currently only
13236 defined/used for the OpenMP target ones. */
13237 gcc_checking_assert (start_ix == BUILT_IN_GOMP_TARGET
13238 || start_ix == BUILT_IN_GOMP_TARGET_DATA
43895be5 13239 || start_ix == BUILT_IN_GOMP_TARGET_UPDATE
13240 || start_ix == BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA);
ca4c3545 13241
bc7bff74 13242 device = OMP_CLAUSE_DEVICE_ID (c);
13243 clause_loc = OMP_CLAUSE_LOCATION (c);
13244 }
13245 else
13246 clause_loc = gimple_location (entry_stmt);
13247
43895be5 13248 c = find_omp_clause (clauses, OMP_CLAUSE_NOWAIT);
13249 if (c)
13250 flags_i |= GOMP_TARGET_FLAG_NOWAIT;
13251
bc7bff74 13252 /* Ensure 'device' is of the correct type. */
13253 device = fold_convert_loc (clause_loc, integer_type_node, device);
13254
13255 /* If we found the clause 'if (cond)', build
ca4c3545 13256 (cond ? device : GOMP_DEVICE_HOST_FALLBACK). */
bc7bff74 13257 if (cond)
13258 {
13259 cond = gimple_boolify (cond);
13260
13261 basic_block cond_bb, then_bb, else_bb;
13262 edge e;
13263 tree tmp_var;
13264
f9e245b2 13265 tmp_var = create_tmp_var (TREE_TYPE (device));
ca4c3545 13266 if (offloaded)
4302d619 13267 e = split_block_after_labels (new_bb);
ca4c3545 13268 else
bc7bff74 13269 {
13270 gsi = gsi_last_bb (new_bb);
13271 gsi_prev (&gsi);
13272 e = split_block (new_bb, gsi_stmt (gsi));
13273 }
bc7bff74 13274 cond_bb = e->src;
13275 new_bb = e->dest;
13276 remove_edge (e);
13277
13278 then_bb = create_empty_bb (cond_bb);
13279 else_bb = create_empty_bb (then_bb);
13280 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
13281 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
13282
13283 stmt = gimple_build_cond_empty (cond);
13284 gsi = gsi_last_bb (cond_bb);
13285 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
13286
13287 gsi = gsi_start_bb (then_bb);
13288 stmt = gimple_build_assign (tmp_var, device);
13289 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
13290
13291 gsi = gsi_start_bb (else_bb);
13292 stmt = gimple_build_assign (tmp_var,
ca4c3545 13293 build_int_cst (integer_type_node,
13294 GOMP_DEVICE_HOST_FALLBACK));
bc7bff74 13295 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
13296
13297 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
13298 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
b3083327 13299 add_bb_to_loop (then_bb, cond_bb->loop_father);
13300 add_bb_to_loop (else_bb, cond_bb->loop_father);
bc7bff74 13301 make_edge (then_bb, new_bb, EDGE_FALLTHRU);
13302 make_edge (else_bb, new_bb, EDGE_FALLTHRU);
13303
13304 device = tmp_var;
13305 }
13306
13307 gsi = gsi_last_bb (new_bb);
13308 t = gimple_omp_target_data_arg (entry_stmt);
13309 if (t == NULL)
13310 {
13311 t1 = size_zero_node;
13312 t2 = build_zero_cst (ptr_type_node);
13313 t3 = t2;
13314 t4 = t2;
13315 }
13316 else
13317 {
13318 t1 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t, 1))));
13319 t1 = size_binop (PLUS_EXPR, t1, size_int (1));
13320 t2 = build_fold_addr_expr (TREE_VEC_ELT (t, 0));
13321 t3 = build_fold_addr_expr (TREE_VEC_ELT (t, 1));
13322 t4 = build_fold_addr_expr (TREE_VEC_ELT (t, 2));
13323 }
13324
42acab1c 13325 gimple *g;
e561d5e1 13326 bool tagging = false;
ca4c3545 13327 /* The maximum number used by any start_ix, without varargs. */
02c05c9b 13328 auto_vec<tree, 11> args;
13329 args.quick_push (device);
ca4c3545 13330 if (offloaded)
02c05c9b 13331 args.quick_push (build_fold_addr_expr (child_fn));
02c05c9b 13332 args.quick_push (t1);
13333 args.quick_push (t2);
13334 args.quick_push (t3);
13335 args.quick_push (t4);
ca4c3545 13336 switch (start_ix)
13337 {
13338 case BUILT_IN_GOACC_DATA_START:
2fc5e987 13339 case BUILT_IN_GOACC_DECLARE:
ca4c3545 13340 case BUILT_IN_GOMP_TARGET_DATA:
43895be5 13341 break;
13342 case BUILT_IN_GOMP_TARGET:
ca4c3545 13343 case BUILT_IN_GOMP_TARGET_UPDATE:
43895be5 13344 case BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA:
13345 args.quick_push (build_int_cst (unsigned_type_node, flags_i));
13346 c = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
13347 if (c)
13348 depend = OMP_CLAUSE_DECL (c);
13349 else
13350 depend = build_int_cst (ptr_type_node, 0);
13351 args.quick_push (depend);
9561765e 13352 if (start_ix == BUILT_IN_GOMP_TARGET)
56686608 13353 args.quick_push (get_target_arguments (&gsi, entry_stmt));
ca4c3545 13354 break;
13355 case BUILT_IN_GOACC_PARALLEL:
13356 {
6f431819 13357 set_oacc_fn_attrib (child_fn, clauses, oacc_kernels_p, &args);
e561d5e1 13358 tagging = true;
ca4c3545 13359 }
13360 /* FALLTHRU */
13361 case BUILT_IN_GOACC_ENTER_EXIT_DATA:
13362 case BUILT_IN_GOACC_UPDATE:
13363 {
e561d5e1 13364 tree t_async = NULL_TREE;
13365
13366 /* If present, use the value specified by the respective
ca4c3545 13367 clause, making sure that is of the correct type. */
13368 c = find_omp_clause (clauses, OMP_CLAUSE_ASYNC);
13369 if (c)
13370 t_async = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
13371 integer_type_node,
13372 OMP_CLAUSE_ASYNC_EXPR (c));
e561d5e1 13373 else if (!tagging)
13374 /* Default values for t_async. */
13375 t_async = fold_convert_loc (gimple_location (entry_stmt),
13376 integer_type_node,
13377 build_int_cst (integer_type_node,
13378 GOMP_ASYNC_SYNC));
13379 if (tagging && t_async)
ca4c3545 13380 {
a6258f5a 13381 unsigned HOST_WIDE_INT i_async = GOMP_LAUNCH_OP_MAX;
ca4c3545 13382
e561d5e1 13383 if (TREE_CODE (t_async) == INTEGER_CST)
ca4c3545 13384 {
e561d5e1 13385 /* See if we can pack the async arg in to the tag's
13386 operand. */
13387 i_async = TREE_INT_CST_LOW (t_async);
e561d5e1 13388 if (i_async < GOMP_LAUNCH_OP_MAX)
13389 t_async = NULL_TREE;
a6258f5a 13390 else
13391 i_async = GOMP_LAUNCH_OP_MAX;
ca4c3545 13392 }
a6258f5a 13393 args.safe_push (oacc_launch_pack (GOMP_LAUNCH_ASYNC, NULL_TREE,
13394 i_async));
e561d5e1 13395 }
13396 if (t_async)
13397 args.safe_push (t_async);
ca4c3545 13398
e561d5e1 13399 /* Save the argument index, and ... */
13400 unsigned t_wait_idx = args.length ();
13401 unsigned num_waits = 0;
13402 c = find_omp_clause (clauses, OMP_CLAUSE_WAIT);
13403 if (!tagging || c)
13404 /* ... push a placeholder. */
13405 args.safe_push (integer_zero_node);
13406
13407 for (; c; c = OMP_CLAUSE_CHAIN (c))
13408 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_WAIT)
13409 {
13410 args.safe_push (fold_convert_loc (OMP_CLAUSE_LOCATION (c),
13411 integer_type_node,
13412 OMP_CLAUSE_WAIT_EXPR (c)));
13413 num_waits++;
13414 }
13415
13416 if (!tagging || num_waits)
13417 {
13418 tree len;
13419
13420 /* Now that we know the number, update the placeholder. */
13421 if (tagging)
13422 len = oacc_launch_pack (GOMP_LAUNCH_WAIT, NULL_TREE, num_waits);
13423 else
13424 len = build_int_cst (integer_type_node, num_waits);
13425 len = fold_convert_loc (gimple_location (entry_stmt),
13426 unsigned_type_node, len);
13427 args[t_wait_idx] = len;
ca4c3545 13428 }
13429 }
13430 break;
13431 default:
13432 gcc_unreachable ();
bc7bff74 13433 }
e561d5e1 13434 if (tagging)
13435 /* Push terminal marker - zero. */
13436 args.safe_push (oacc_launch_pack (0, NULL_TREE, 0));
ca4c3545 13437
02c05c9b 13438 g = gimple_build_call_vec (builtin_decl_explicit (start_ix), args);
bc7bff74 13439 gimple_set_location (g, gimple_location (entry_stmt));
13440 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
ca4c3545 13441 if (!offloaded)
bc7bff74 13442 {
13443 g = gsi_stmt (gsi);
13444 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_TARGET);
13445 gsi_remove (&gsi, true);
13446 }
43895be5 13447 if (data_region && region->exit)
bc7bff74 13448 {
13449 gsi = gsi_last_bb (region->exit);
13450 g = gsi_stmt (gsi);
13451 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_RETURN);
13452 gsi_remove (&gsi, true);
13453 }
13454}
13455
56686608 13456/* Expand KFOR loop as a GPGPU kernel, i.e. as a body only with iteration
13457 variable derived from the thread number. */
773c5ba7 13458
13459static void
56686608 13460grid_expand_omp_for_loop (struct omp_region *kfor)
773c5ba7 13461{
56686608 13462 tree t, threadid;
13463 tree type, itype;
13464 gimple_stmt_iterator gsi;
13465 tree n1, step;
13466 struct omp_for_data fd;
1d22f541 13467
56686608 13468 gomp_for *for_stmt = as_a <gomp_for *> (last_stmt (kfor->entry));
13469 gcc_checking_assert (gimple_omp_for_kind (for_stmt)
13470 == GF_OMP_FOR_KIND_GRID_LOOP);
13471 basic_block body_bb = FALLTHRU_EDGE (kfor->entry)->dest;
d1d5b012 13472
56686608 13473 gcc_assert (gimple_omp_for_collapse (for_stmt) == 1);
13474 gcc_assert (kfor->cont);
13475 extract_omp_for_data (for_stmt, &fd, NULL);
bc7bff74 13476
56686608 13477 itype = type = TREE_TYPE (fd.loop.v);
13478 if (POINTER_TYPE_P (type))
13479 itype = signed_type_for (type);
773c5ba7 13480
56686608 13481 gsi = gsi_start_bb (body_bb);
1d22f541 13482
56686608 13483 n1 = fd.loop.n1;
13484 step = fd.loop.step;
13485 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
13486 true, NULL_TREE, true, GSI_SAME_STMT);
13487 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
13488 true, NULL_TREE, true, GSI_SAME_STMT);
13489 threadid = build_call_expr (builtin_decl_explicit
13490 (BUILT_IN_OMP_GET_THREAD_NUM), 0);
13491 threadid = fold_convert (itype, threadid);
13492 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
13493 true, GSI_SAME_STMT);
fd6481cf 13494
56686608 13495 tree startvar = fd.loop.v;
13496 t = fold_build2 (MULT_EXPR, itype, threadid, step);
13497 if (POINTER_TYPE_P (type))
13498 t = fold_build_pointer_plus (n1, t);
13499 else
13500 t = fold_build2 (PLUS_EXPR, type, t, n1);
13501 t = fold_convert (type, t);
13502 t = force_gimple_operand_gsi (&gsi, t,
13503 DECL_P (startvar)
13504 && TREE_ADDRESSABLE (startvar),
13505 NULL_TREE, true, GSI_SAME_STMT);
13506 gassign *assign_stmt = gimple_build_assign (startvar, t);
13507 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
773c5ba7 13508
56686608 13509 /* Remove the omp for statement */
13510 gsi = gsi_last_bb (kfor->entry);
13511 gsi_remove (&gsi, true);
773c5ba7 13512
56686608 13513 /* Remove the GIMPLE_OMP_CONTINUE statement. */
13514 gsi = gsi_last_bb (kfor->cont);
13515 gcc_assert (!gsi_end_p (gsi)
13516 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_CONTINUE);
13517 gsi_remove (&gsi, true);
773c5ba7 13518
56686608 13519 /* Replace the GIMPLE_OMP_RETURN with a real return. */
13520 gsi = gsi_last_bb (kfor->exit);
13521 gcc_assert (!gsi_end_p (gsi)
13522 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
13523 gsi_remove (&gsi, true);
773c5ba7 13524
56686608 13525 /* Fixup the much simpler CFG. */
13526 remove_edge (find_edge (kfor->cont, body_bb));
773c5ba7 13527
56686608 13528 if (kfor->cont != body_bb)
13529 set_immediate_dominator (CDI_DOMINATORS, kfor->cont, body_bb);
13530 set_immediate_dominator (CDI_DOMINATORS, kfor->exit, kfor->cont);
13531}
cb7f680b 13532
56686608 13533/* Structure passed to grid_remap_kernel_arg_accesses so that it can remap
13534 argument_decls. */
13535
13536struct grid_arg_decl_map
13537{
13538 tree old_arg;
13539 tree new_arg;
13540};
13541
13542/* Invoked through walk_gimple_op, will remap all PARM_DECLs to the ones
13543 pertaining to kernel function. */
13544
13545static tree
13546grid_remap_kernel_arg_accesses (tree *tp, int *walk_subtrees, void *data)
13547{
13548 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
13549 struct grid_arg_decl_map *adm = (struct grid_arg_decl_map *) wi->info;
13550 tree t = *tp;
13551
13552 if (t == adm->old_arg)
13553 *tp = adm->new_arg;
13554 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
13555 return NULL_TREE;
13556}
13557
13558static void expand_omp (struct omp_region *region);
13559
13560/* If TARGET region contains a kernel body for loop, remove its region from the
13561 TARGET and expand it in GPGPU kernel fashion. */
13562
13563static void
13564grid_expand_target_grid_body (struct omp_region *target)
13565{
13566 if (!hsa_gen_requested_p ())
13567 return;
13568
13569 gomp_target *tgt_stmt = as_a <gomp_target *> (last_stmt (target->entry));
13570 struct omp_region **pp;
13571
13572 for (pp = &target->inner; *pp; pp = &(*pp)->next)
13573 if ((*pp)->type == GIMPLE_OMP_GRID_BODY)
13574 break;
13575
13576 struct omp_region *gpukernel = *pp;
13577
13578 tree orig_child_fndecl = gimple_omp_target_child_fn (tgt_stmt);
13579 if (!gpukernel)
13580 {
13581 /* HSA cannot handle OACC stuff. */
13582 if (gimple_omp_target_kind (tgt_stmt) != GF_OMP_TARGET_KIND_REGION)
13583 return;
13584 gcc_checking_assert (orig_child_fndecl);
13585 gcc_assert (!find_omp_clause (gimple_omp_target_clauses (tgt_stmt),
13586 OMP_CLAUSE__GRIDDIM_));
13587 cgraph_node *n = cgraph_node::get (orig_child_fndecl);
13588
13589 hsa_register_kernel (n);
13590 return;
13591 }
13592
13593 gcc_assert (find_omp_clause (gimple_omp_target_clauses (tgt_stmt),
13594 OMP_CLAUSE__GRIDDIM_));
13595 tree inside_block = gimple_block (first_stmt (single_succ (gpukernel->entry)));
13596 *pp = gpukernel->next;
13597 for (pp = &gpukernel->inner; *pp; pp = &(*pp)->next)
13598 if ((*pp)->type == GIMPLE_OMP_FOR)
13599 break;
13600
13601 struct omp_region *kfor = *pp;
13602 gcc_assert (kfor);
13603 gcc_assert (gimple_omp_for_kind (last_stmt ((kfor)->entry))
13604 == GF_OMP_FOR_KIND_GRID_LOOP);
13605 *pp = kfor->next;
13606 if (kfor->inner)
13607 expand_omp (kfor->inner);
13608 if (gpukernel->inner)
13609 expand_omp (gpukernel->inner);
13610
13611 tree kern_fndecl = copy_node (orig_child_fndecl);
13612 DECL_NAME (kern_fndecl) = clone_function_name (kern_fndecl, "kernel");
13613 SET_DECL_ASSEMBLER_NAME (kern_fndecl, DECL_NAME (kern_fndecl));
13614 tree tgtblock = gimple_block (tgt_stmt);
13615 tree fniniblock = make_node (BLOCK);
13616 BLOCK_ABSTRACT_ORIGIN (fniniblock) = tgtblock;
13617 BLOCK_SOURCE_LOCATION (fniniblock) = BLOCK_SOURCE_LOCATION (tgtblock);
13618 BLOCK_SOURCE_END_LOCATION (fniniblock) = BLOCK_SOURCE_END_LOCATION (tgtblock);
13619 DECL_INITIAL (kern_fndecl) = fniniblock;
13620 push_struct_function (kern_fndecl);
13621 cfun->function_end_locus = gimple_location (tgt_stmt);
13622 pop_cfun ();
13623
13624 tree old_parm_decl = DECL_ARGUMENTS (kern_fndecl);
13625 gcc_assert (!DECL_CHAIN (old_parm_decl));
13626 tree new_parm_decl = copy_node (DECL_ARGUMENTS (kern_fndecl));
13627 DECL_CONTEXT (new_parm_decl) = kern_fndecl;
13628 DECL_ARGUMENTS (kern_fndecl) = new_parm_decl;
13629 struct function *kern_cfun = DECL_STRUCT_FUNCTION (kern_fndecl);
13630 kern_cfun->curr_properties = cfun->curr_properties;
13631
13632 remove_edge (BRANCH_EDGE (kfor->entry));
13633 grid_expand_omp_for_loop (kfor);
13634
13635 /* Remove the omp for statement */
13636 gimple_stmt_iterator gsi = gsi_last_bb (gpukernel->entry);
13637 gsi_remove (&gsi, true);
13638 /* Replace the GIMPLE_OMP_RETURN at the end of the kernel region with a real
13639 return. */
13640 gsi = gsi_last_bb (gpukernel->exit);
13641 gcc_assert (!gsi_end_p (gsi)
13642 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
13643 gimple *ret_stmt = gimple_build_return (NULL);
13644 gsi_insert_after (&gsi, ret_stmt, GSI_SAME_STMT);
13645 gsi_remove (&gsi, true);
13646
13647 /* Statements in the first BB in the target construct have been produced by
13648 target lowering and must be copied inside the GPUKERNEL, with the two
13649 exceptions of the first OMP statement and the OMP_DATA assignment
13650 statement. */
13651 gsi = gsi_start_bb (single_succ (gpukernel->entry));
13652 tree data_arg = gimple_omp_target_data_arg (tgt_stmt);
13653 tree sender = data_arg ? TREE_VEC_ELT (data_arg, 0) : NULL;
13654 for (gimple_stmt_iterator tsi = gsi_start_bb (single_succ (target->entry));
13655 !gsi_end_p (tsi); gsi_next (&tsi))
13656 {
13657 gimple *stmt = gsi_stmt (tsi);
13658 if (is_gimple_omp (stmt))
13659 break;
13660 if (sender
13661 && is_gimple_assign (stmt)
13662 && TREE_CODE (gimple_assign_rhs1 (stmt)) == ADDR_EXPR
13663 && TREE_OPERAND (gimple_assign_rhs1 (stmt), 0) == sender)
13664 continue;
13665 gimple *copy = gimple_copy (stmt);
13666 gsi_insert_before (&gsi, copy, GSI_SAME_STMT);
13667 gimple_set_block (copy, fniniblock);
13668 }
13669
13670 move_sese_region_to_fn (kern_cfun, single_succ (gpukernel->entry),
13671 gpukernel->exit, inside_block);
13672
13673 cgraph_node *kcn = cgraph_node::get_create (kern_fndecl);
13674 kcn->mark_force_output ();
13675 cgraph_node *orig_child = cgraph_node::get (orig_child_fndecl);
13676
13677 hsa_register_kernel (kcn, orig_child);
13678
13679 cgraph_node::add_new_function (kern_fndecl, true);
13680 push_cfun (kern_cfun);
13681 cgraph_edge::rebuild_edges ();
13682
13683 /* Re-map any mention of the PARM_DECL of the original function to the
13684 PARM_DECL of the new one.
13685
13686 TODO: It would be great if lowering produced references into the GPU
13687 kernel decl straight away and we did not have to do this. */
13688 struct grid_arg_decl_map adm;
13689 adm.old_arg = old_parm_decl;
13690 adm.new_arg = new_parm_decl;
13691 basic_block bb;
13692 FOR_EACH_BB_FN (bb, kern_cfun)
13693 {
13694 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
13695 {
13696 gimple *stmt = gsi_stmt (gsi);
13697 struct walk_stmt_info wi;
13698 memset (&wi, 0, sizeof (wi));
13699 wi.info = &adm;
13700 walk_gimple_op (stmt, grid_remap_kernel_arg_accesses, &wi);
13701 }
13702 }
13703 pop_cfun ();
13704
13705 return;
13706}
13707
13708/* Expand the parallel region tree rooted at REGION. Expansion
13709 proceeds in depth-first order. Innermost regions are expanded
13710 first. This way, parallel regions that require a new function to
13711 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
13712 internal dependencies in their body. */
13713
13714static void
13715expand_omp (struct omp_region *region)
13716{
13717 omp_any_child_fn_dumped = false;
13718 while (region)
13719 {
13720 location_t saved_location;
13721 gimple *inner_stmt = NULL;
13722
13723 /* First, determine whether this is a combined parallel+workshare
13724 region. */
13725 if (region->type == GIMPLE_OMP_PARALLEL)
13726 determine_parallel_type (region);
13727 else if (region->type == GIMPLE_OMP_TARGET)
13728 grid_expand_target_grid_body (region);
13729
13730 if (region->type == GIMPLE_OMP_FOR
13731 && gimple_omp_for_combined_p (last_stmt (region->entry)))
13732 inner_stmt = last_stmt (region->inner->entry);
13733
13734 if (region->inner)
13735 expand_omp (region->inner);
13736
13737 saved_location = input_location;
13738 if (gimple_has_location (last_stmt (region->entry)))
13739 input_location = gimple_location (last_stmt (region->entry));
13740
13741 switch (region->type)
13742 {
13743 case GIMPLE_OMP_PARALLEL:
13744 case GIMPLE_OMP_TASK:
13745 expand_omp_taskreg (region);
13746 break;
13747
13748 case GIMPLE_OMP_FOR:
13749 expand_omp_for (region, inner_stmt);
13750 break;
13751
13752 case GIMPLE_OMP_SECTIONS:
13753 expand_omp_sections (region);
13754 break;
13755
13756 case GIMPLE_OMP_SECTION:
13757 /* Individual omp sections are handled together with their
13758 parent GIMPLE_OMP_SECTIONS region. */
13759 break;
13760
13761 case GIMPLE_OMP_SINGLE:
13762 expand_omp_single (region);
13763 break;
13764
13765 case GIMPLE_OMP_ORDERED:
13766 {
13767 gomp_ordered *ord_stmt
13768 = as_a <gomp_ordered *> (last_stmt (region->entry));
13769 if (find_omp_clause (gimple_omp_ordered_clauses (ord_stmt),
13770 OMP_CLAUSE_DEPEND))
13771 {
13772 /* We'll expand these when expanding corresponding
13773 worksharing region with ordered(n) clause. */
13774 gcc_assert (region->outer
13775 && region->outer->type == GIMPLE_OMP_FOR);
13776 region->ord_stmt = ord_stmt;
13777 break;
13778 }
13779 }
13780 /* FALLTHRU */
13781 case GIMPLE_OMP_MASTER:
13782 case GIMPLE_OMP_TASKGROUP:
13783 case GIMPLE_OMP_CRITICAL:
13784 case GIMPLE_OMP_TEAMS:
13785 expand_omp_synch (region);
13786 break;
13787
13788 case GIMPLE_OMP_ATOMIC_LOAD:
13789 expand_omp_atomic (region);
13790 break;
13791
13792 case GIMPLE_OMP_TARGET:
bc7bff74 13793 expand_omp_target (region);
13794 break;
13795
61e47ac8 13796 default:
13797 gcc_unreachable ();
13798 }
cc5982dc 13799
1d22f541 13800 input_location = saved_location;
773c5ba7 13801 region = region->next;
13802 }
9561765e 13803 if (omp_any_child_fn_dumped)
13804 {
13805 if (dump_file)
13806 dump_function_header (dump_file, current_function_decl, dump_flags);
13807 omp_any_child_fn_dumped = false;
13808 }
773c5ba7 13809}
13810
13811
13812/* Helper for build_omp_regions. Scan the dominator tree starting at
28c92cbb 13813 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
13814 true, the function ends once a single tree is built (otherwise, whole
13815 forest of OMP constructs may be built). */
773c5ba7 13816
13817static void
28c92cbb 13818build_omp_regions_1 (basic_block bb, struct omp_region *parent,
13819 bool single_tree)
773c5ba7 13820{
75a70cf9 13821 gimple_stmt_iterator gsi;
42acab1c 13822 gimple *stmt;
773c5ba7 13823 basic_block son;
13824
75a70cf9 13825 gsi = gsi_last_bb (bb);
13826 if (!gsi_end_p (gsi) && is_gimple_omp (gsi_stmt (gsi)))
773c5ba7 13827 {
13828 struct omp_region *region;
75a70cf9 13829 enum gimple_code code;
773c5ba7 13830
75a70cf9 13831 stmt = gsi_stmt (gsi);
13832 code = gimple_code (stmt);
13833 if (code == GIMPLE_OMP_RETURN)
773c5ba7 13834 {
13835 /* STMT is the return point out of region PARENT. Mark it
13836 as the exit point and make PARENT the immediately
13837 enclosing region. */
13838 gcc_assert (parent);
13839 region = parent;
61e47ac8 13840 region->exit = bb;
773c5ba7 13841 parent = parent->outer;
773c5ba7 13842 }
75a70cf9 13843 else if (code == GIMPLE_OMP_ATOMIC_STORE)
cb7f680b 13844 {
75a70cf9 13845 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
13846 GIMPLE_OMP_RETURN, but matches with
13847 GIMPLE_OMP_ATOMIC_LOAD. */
cb7f680b 13848 gcc_assert (parent);
75a70cf9 13849 gcc_assert (parent->type == GIMPLE_OMP_ATOMIC_LOAD);
cb7f680b 13850 region = parent;
13851 region->exit = bb;
13852 parent = parent->outer;
13853 }
75a70cf9 13854 else if (code == GIMPLE_OMP_CONTINUE)
61e47ac8 13855 {
13856 gcc_assert (parent);
13857 parent->cont = bb;
13858 }
75a70cf9 13859 else if (code == GIMPLE_OMP_SECTIONS_SWITCH)
ac6e3339 13860 {
75a70cf9 13861 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
13862 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
ac6e3339 13863 }
773c5ba7 13864 else
13865 {
61e47ac8 13866 region = new_omp_region (bb, code, parent);
ca4c3545 13867 /* Otherwise... */
13868 if (code == GIMPLE_OMP_TARGET)
13869 {
13870 switch (gimple_omp_target_kind (stmt))
13871 {
13872 case GF_OMP_TARGET_KIND_REGION:
13873 case GF_OMP_TARGET_KIND_DATA:
13874 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
13875 case GF_OMP_TARGET_KIND_OACC_KERNELS:
13876 case GF_OMP_TARGET_KIND_OACC_DATA:
571b3486 13877 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
ca4c3545 13878 break;
13879 case GF_OMP_TARGET_KIND_UPDATE:
43895be5 13880 case GF_OMP_TARGET_KIND_ENTER_DATA:
13881 case GF_OMP_TARGET_KIND_EXIT_DATA:
ca4c3545 13882 case GF_OMP_TARGET_KIND_OACC_UPDATE:
13883 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
2fc5e987 13884 case GF_OMP_TARGET_KIND_OACC_DECLARE:
ca4c3545 13885 /* ..., other than for those stand-alone directives... */
13886 region = NULL;
13887 break;
13888 default:
13889 gcc_unreachable ();
13890 }
13891 }
43895be5 13892 else if (code == GIMPLE_OMP_ORDERED
13893 && find_omp_clause (gimple_omp_ordered_clauses
13894 (as_a <gomp_ordered *> (stmt)),
13895 OMP_CLAUSE_DEPEND))
13896 /* #pragma omp ordered depend is also just a stand-alone
13897 directive. */
13898 region = NULL;
ca4c3545 13899 /* ..., this directive becomes the parent for a new region. */
13900 if (region)
13901 parent = region;
773c5ba7 13902 }
773c5ba7 13903 }
13904
28c92cbb 13905 if (single_tree && !parent)
13906 return;
13907
773c5ba7 13908 for (son = first_dom_son (CDI_DOMINATORS, bb);
13909 son;
13910 son = next_dom_son (CDI_DOMINATORS, son))
28c92cbb 13911 build_omp_regions_1 (son, parent, single_tree);
13912}
13913
13914/* Builds the tree of OMP regions rooted at ROOT, storing it to
13915 root_omp_region. */
13916
13917static void
13918build_omp_regions_root (basic_block root)
13919{
13920 gcc_assert (root_omp_region == NULL);
13921 build_omp_regions_1 (root, NULL, true);
13922 gcc_assert (root_omp_region != NULL);
773c5ba7 13923}
13924
28c92cbb 13925/* Expands omp construct (and its subconstructs) starting in HEAD. */
13926
13927void
13928omp_expand_local (basic_block head)
13929{
13930 build_omp_regions_root (head);
13931 if (dump_file && (dump_flags & TDF_DETAILS))
13932 {
13933 fprintf (dump_file, "\nOMP region tree\n\n");
13934 dump_omp_region (dump_file, root_omp_region, 0);
13935 fprintf (dump_file, "\n");
13936 }
13937
13938 remove_exit_barriers (root_omp_region);
13939 expand_omp (root_omp_region);
13940
13941 free_omp_regions ();
13942}
773c5ba7 13943
13944/* Scan the CFG and build a tree of OMP regions. Return the root of
13945 the OMP region tree. */
13946
13947static void
13948build_omp_regions (void)
13949{
61e47ac8 13950 gcc_assert (root_omp_region == NULL);
773c5ba7 13951 calculate_dominance_info (CDI_DOMINATORS);
34154e27 13952 build_omp_regions_1 (ENTRY_BLOCK_PTR_FOR_FN (cfun), NULL, false);
773c5ba7 13953}
13954
773c5ba7 13955/* Main entry point for expanding OMP-GIMPLE into runtime calls. */
13956
2a1990e9 13957static unsigned int
773c5ba7 13958execute_expand_omp (void)
13959{
13960 build_omp_regions ();
13961
61e47ac8 13962 if (!root_omp_region)
13963 return 0;
773c5ba7 13964
61e47ac8 13965 if (dump_file)
13966 {
13967 fprintf (dump_file, "\nOMP region tree\n\n");
13968 dump_omp_region (dump_file, root_omp_region, 0);
13969 fprintf (dump_file, "\n");
773c5ba7 13970 }
61e47ac8 13971
13972 remove_exit_barriers (root_omp_region);
13973
13974 expand_omp (root_omp_region);
13975
382ecba7 13976 if (flag_checking && !loops_state_satisfies_p (LOOPS_NEED_FIXUP))
86a932e0 13977 verify_loop_structure ();
61e47ac8 13978 cleanup_tree_cfg ();
13979
13980 free_omp_regions ();
13981
2a1990e9 13982 return 0;
773c5ba7 13983}
13984
79acaae1 13985/* OMP expansion -- the default pass, run before creation of SSA form. */
13986
7620bc82 13987namespace {
13988
13989const pass_data pass_data_expand_omp =
cbe8bda8 13990{
13991 GIMPLE_PASS, /* type */
13992 "ompexp", /* name */
13993 OPTGROUP_NONE, /* optinfo_flags */
cbe8bda8 13994 TV_NONE, /* tv_id */
13995 PROP_gimple_any, /* properties_required */
8917c50b 13996 PROP_gimple_eomp, /* properties_provided */
cbe8bda8 13997 0, /* properties_destroyed */
13998 0, /* todo_flags_start */
13999 0, /* todo_flags_finish */
773c5ba7 14000};
cbe8bda8 14001
7620bc82 14002class pass_expand_omp : public gimple_opt_pass
cbe8bda8 14003{
14004public:
9af5ce0c 14005 pass_expand_omp (gcc::context *ctxt)
14006 : gimple_opt_pass (pass_data_expand_omp, ctxt)
cbe8bda8 14007 {}
14008
14009 /* opt_pass methods: */
8917c50b 14010 virtual unsigned int execute (function *)
31315c24 14011 {
ca4c3545 14012 bool gate = ((flag_cilkplus != 0 || flag_openacc != 0 || flag_openmp != 0
14013 || flag_openmp_simd != 0)
14014 && !seen_error ());
31315c24 14015
8917c50b 14016 /* This pass always runs, to provide PROP_gimple_eomp.
ca4c3545 14017 But often, there is nothing to do. */
8917c50b 14018 if (!gate)
14019 return 0;
14020
14021 return execute_expand_omp ();
14022 }
cbe8bda8 14023
14024}; // class pass_expand_omp
14025
7620bc82 14026} // anon namespace
14027
cbe8bda8 14028gimple_opt_pass *
14029make_pass_expand_omp (gcc::context *ctxt)
14030{
14031 return new pass_expand_omp (ctxt);
14032}
8917c50b 14033
7620bc82 14034namespace {
14035
14036const pass_data pass_data_expand_omp_ssa =
8917c50b 14037{
14038 GIMPLE_PASS, /* type */
14039 "ompexpssa", /* name */
14040 OPTGROUP_NONE, /* optinfo_flags */
14041 TV_NONE, /* tv_id */
14042 PROP_cfg | PROP_ssa, /* properties_required */
14043 PROP_gimple_eomp, /* properties_provided */
14044 0, /* properties_destroyed */
14045 0, /* todo_flags_start */
14046 TODO_cleanup_cfg | TODO_rebuild_alias, /* todo_flags_finish */
14047};
14048
7620bc82 14049class pass_expand_omp_ssa : public gimple_opt_pass
8917c50b 14050{
14051public:
14052 pass_expand_omp_ssa (gcc::context *ctxt)
14053 : gimple_opt_pass (pass_data_expand_omp_ssa, ctxt)
14054 {}
14055
14056 /* opt_pass methods: */
14057 virtual bool gate (function *fun)
14058 {
14059 return !(fun->curr_properties & PROP_gimple_eomp);
14060 }
14061 virtual unsigned int execute (function *) { return execute_expand_omp (); }
e1e1688c 14062 opt_pass * clone () { return new pass_expand_omp_ssa (m_ctxt); }
8917c50b 14063
14064}; // class pass_expand_omp_ssa
14065
7620bc82 14066} // anon namespace
14067
8917c50b 14068gimple_opt_pass *
14069make_pass_expand_omp_ssa (gcc::context *ctxt)
14070{
14071 return new pass_expand_omp_ssa (ctxt);
14072}
773c5ba7 14073\f
ca4c3545 14074/* Routines to lower OMP directives into OMP-GIMPLE. */
14075
bc7bff74 14076/* If ctx is a worksharing context inside of a cancellable parallel
14077 region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
14078 and conditional branch to parallel's cancel_label to handle
14079 cancellation in the implicit barrier. */
14080
14081static void
14082maybe_add_implicit_barrier_cancel (omp_context *ctx, gimple_seq *body)
14083{
42acab1c 14084 gimple *omp_return = gimple_seq_last_stmt (*body);
bc7bff74 14085 gcc_assert (gimple_code (omp_return) == GIMPLE_OMP_RETURN);
14086 if (gimple_omp_return_nowait_p (omp_return))
14087 return;
14088 if (ctx->outer
14089 && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_PARALLEL
14090 && ctx->outer->cancellable)
14091 {
15b28553 14092 tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL);
14093 tree c_bool_type = TREE_TYPE (TREE_TYPE (fndecl));
f9e245b2 14094 tree lhs = create_tmp_var (c_bool_type);
bc7bff74 14095 gimple_omp_return_set_lhs (omp_return, lhs);
14096 tree fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
42acab1c 14097 gimple *g = gimple_build_cond (NE_EXPR, lhs,
15b28553 14098 fold_convert (c_bool_type,
14099 boolean_false_node),
bc7bff74 14100 ctx->outer->cancel_label, fallthru_label);
14101 gimple_seq_add_stmt (body, g);
14102 gimple_seq_add_stmt (body, gimple_build_label (fallthru_label));
14103 }
14104}
14105
75a70cf9 14106/* Lower the OpenMP sections directive in the current statement in GSI_P.
14107 CTX is the enclosing OMP context for the current statement. */
773c5ba7 14108
14109static void
75a70cf9 14110lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
773c5ba7 14111{
75a70cf9 14112 tree block, control;
14113 gimple_stmt_iterator tgsi;
1a91d914 14114 gomp_sections *stmt;
42acab1c 14115 gimple *t;
1a91d914 14116 gbind *new_stmt, *bind;
e3a19533 14117 gimple_seq ilist, dlist, olist, new_body;
773c5ba7 14118
1a91d914 14119 stmt = as_a <gomp_sections *> (gsi_stmt (*gsi_p));
773c5ba7 14120
8a4a28a8 14121 push_gimplify_context ();
773c5ba7 14122
14123 dlist = NULL;
14124 ilist = NULL;
75a70cf9 14125 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
bc7bff74 14126 &ilist, &dlist, ctx, NULL);
773c5ba7 14127
e3a19533 14128 new_body = gimple_omp_body (stmt);
14129 gimple_omp_set_body (stmt, NULL);
14130 tgsi = gsi_start (new_body);
14131 for (; !gsi_end_p (tgsi); gsi_next (&tgsi))
773c5ba7 14132 {
14133 omp_context *sctx;
42acab1c 14134 gimple *sec_start;
773c5ba7 14135
75a70cf9 14136 sec_start = gsi_stmt (tgsi);
773c5ba7 14137 sctx = maybe_lookup_ctx (sec_start);
14138 gcc_assert (sctx);
14139
e3a19533 14140 lower_omp (gimple_omp_body_ptr (sec_start), sctx);
14141 gsi_insert_seq_after (&tgsi, gimple_omp_body (sec_start),
14142 GSI_CONTINUE_LINKING);
75a70cf9 14143 gimple_omp_set_body (sec_start, NULL);
773c5ba7 14144
e3a19533 14145 if (gsi_one_before_end_p (tgsi))
773c5ba7 14146 {
75a70cf9 14147 gimple_seq l = NULL;
14148 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
773c5ba7 14149 &l, ctx);
e3a19533 14150 gsi_insert_seq_after (&tgsi, l, GSI_CONTINUE_LINKING);
75a70cf9 14151 gimple_omp_section_set_last (sec_start);
773c5ba7 14152 }
48e1416a 14153
e3a19533 14154 gsi_insert_after (&tgsi, gimple_build_omp_return (false),
14155 GSI_CONTINUE_LINKING);
773c5ba7 14156 }
1e8e9920 14157
14158 block = make_node (BLOCK);
e3a19533 14159 bind = gimple_build_bind (NULL, new_body, block);
1e8e9920 14160
75a70cf9 14161 olist = NULL;
14162 lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist, ctx);
773c5ba7 14163
1d22f541 14164 block = make_node (BLOCK);
75a70cf9 14165 new_stmt = gimple_build_bind (NULL, NULL, block);
e3a19533 14166 gsi_replace (gsi_p, new_stmt, true);
773c5ba7 14167
1d22f541 14168 pop_gimplify_context (new_stmt);
75a70cf9 14169 gimple_bind_append_vars (new_stmt, ctx->block_vars);
14170 BLOCK_VARS (block) = gimple_bind_vars (bind);
1d22f541 14171 if (BLOCK_VARS (block))
14172 TREE_USED (block) = 1;
14173
75a70cf9 14174 new_body = NULL;
14175 gimple_seq_add_seq (&new_body, ilist);
14176 gimple_seq_add_stmt (&new_body, stmt);
14177 gimple_seq_add_stmt (&new_body, gimple_build_omp_sections_switch ());
14178 gimple_seq_add_stmt (&new_body, bind);
61e47ac8 14179
ac6e3339 14180 control = create_tmp_var (unsigned_type_node, ".section");
75a70cf9 14181 t = gimple_build_omp_continue (control, control);
14182 gimple_omp_sections_set_control (stmt, control);
14183 gimple_seq_add_stmt (&new_body, t);
61e47ac8 14184
75a70cf9 14185 gimple_seq_add_seq (&new_body, olist);
bc7bff74 14186 if (ctx->cancellable)
14187 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
75a70cf9 14188 gimple_seq_add_seq (&new_body, dlist);
773c5ba7 14189
75a70cf9 14190 new_body = maybe_catch_exception (new_body);
aade31a0 14191
75a70cf9 14192 t = gimple_build_omp_return
14193 (!!find_omp_clause (gimple_omp_sections_clauses (stmt),
14194 OMP_CLAUSE_NOWAIT));
14195 gimple_seq_add_stmt (&new_body, t);
bc7bff74 14196 maybe_add_implicit_barrier_cancel (ctx, &new_body);
61e47ac8 14197
75a70cf9 14198 gimple_bind_set_body (new_stmt, new_body);
1e8e9920 14199}
14200
14201
773c5ba7 14202/* A subroutine of lower_omp_single. Expand the simple form of
75a70cf9 14203 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
1e8e9920 14204
14205 if (GOMP_single_start ())
14206 BODY;
14207 [ GOMP_barrier (); ] -> unless 'nowait' is present.
773c5ba7 14208
14209 FIXME. It may be better to delay expanding the logic of this until
14210 pass_expand_omp. The expanded logic may make the job more difficult
14211 to a synchronization analysis pass. */
1e8e9920 14212
14213static void
1a91d914 14214lower_omp_single_simple (gomp_single *single_stmt, gimple_seq *pre_p)
1e8e9920 14215{
e60a6f7b 14216 location_t loc = gimple_location (single_stmt);
14217 tree tlabel = create_artificial_label (loc);
14218 tree flabel = create_artificial_label (loc);
42acab1c 14219 gimple *call, *cond;
75a70cf9 14220 tree lhs, decl;
14221
b9a16870 14222 decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START);
f9e245b2 14223 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)));
75a70cf9 14224 call = gimple_build_call (decl, 0);
14225 gimple_call_set_lhs (call, lhs);
14226 gimple_seq_add_stmt (pre_p, call);
14227
14228 cond = gimple_build_cond (EQ_EXPR, lhs,
389dd41b 14229 fold_convert_loc (loc, TREE_TYPE (lhs),
14230 boolean_true_node),
75a70cf9 14231 tlabel, flabel);
14232 gimple_seq_add_stmt (pre_p, cond);
14233 gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
14234 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
14235 gimple_seq_add_stmt (pre_p, gimple_build_label (flabel));
1e8e9920 14236}
14237
773c5ba7 14238
14239/* A subroutine of lower_omp_single. Expand the simple form of
75a70cf9 14240 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
1e8e9920 14241
14242 #pragma omp single copyprivate (a, b, c)
14243
14244 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
14245
14246 {
14247 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
14248 {
14249 BODY;
14250 copyout.a = a;
14251 copyout.b = b;
14252 copyout.c = c;
14253 GOMP_single_copy_end (&copyout);
14254 }
14255 else
14256 {
14257 a = copyout_p->a;
14258 b = copyout_p->b;
14259 c = copyout_p->c;
14260 }
14261 GOMP_barrier ();
14262 }
773c5ba7 14263
14264 FIXME. It may be better to delay expanding the logic of this until
14265 pass_expand_omp. The expanded logic may make the job more difficult
14266 to a synchronization analysis pass. */
1e8e9920 14267
14268static void
1a91d914 14269lower_omp_single_copy (gomp_single *single_stmt, gimple_seq *pre_p,
14270 omp_context *ctx)
1e8e9920 14271{
b9a16870 14272 tree ptr_type, t, l0, l1, l2, bfn_decl;
75a70cf9 14273 gimple_seq copyin_seq;
e60a6f7b 14274 location_t loc = gimple_location (single_stmt);
1e8e9920 14275
14276 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
14277
14278 ptr_type = build_pointer_type (ctx->record_type);
14279 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
14280
e60a6f7b 14281 l0 = create_artificial_label (loc);
14282 l1 = create_artificial_label (loc);
14283 l2 = create_artificial_label (loc);
1e8e9920 14284
b9a16870 14285 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START);
14286 t = build_call_expr_loc (loc, bfn_decl, 0);
389dd41b 14287 t = fold_convert_loc (loc, ptr_type, t);
75a70cf9 14288 gimplify_assign (ctx->receiver_decl, t, pre_p);
1e8e9920 14289
14290 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
14291 build_int_cst (ptr_type, 0));
14292 t = build3 (COND_EXPR, void_type_node, t,
14293 build_and_jump (&l0), build_and_jump (&l1));
14294 gimplify_and_add (t, pre_p);
14295
75a70cf9 14296 gimple_seq_add_stmt (pre_p, gimple_build_label (l0));
1e8e9920 14297
75a70cf9 14298 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
1e8e9920 14299
14300 copyin_seq = NULL;
75a70cf9 14301 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
1e8e9920 14302 &copyin_seq, ctx);
14303
389dd41b 14304 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
b9a16870 14305 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END);
14306 t = build_call_expr_loc (loc, bfn_decl, 1, t);
1e8e9920 14307 gimplify_and_add (t, pre_p);
14308
14309 t = build_and_jump (&l2);
14310 gimplify_and_add (t, pre_p);
14311
75a70cf9 14312 gimple_seq_add_stmt (pre_p, gimple_build_label (l1));
1e8e9920 14313
75a70cf9 14314 gimple_seq_add_seq (pre_p, copyin_seq);
1e8e9920 14315
75a70cf9 14316 gimple_seq_add_stmt (pre_p, gimple_build_label (l2));
1e8e9920 14317}
14318
773c5ba7 14319
1e8e9920 14320/* Expand code for an OpenMP single directive. */
14321
14322static void
75a70cf9 14323lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
1e8e9920 14324{
75a70cf9 14325 tree block;
42acab1c 14326 gimple *t;
1a91d914 14327 gomp_single *single_stmt = as_a <gomp_single *> (gsi_stmt (*gsi_p));
14328 gbind *bind;
bc7bff74 14329 gimple_seq bind_body, bind_body_tail = NULL, dlist;
1e8e9920 14330
8a4a28a8 14331 push_gimplify_context ();
1e8e9920 14332
e3a19533 14333 block = make_node (BLOCK);
14334 bind = gimple_build_bind (NULL, NULL, block);
14335 gsi_replace (gsi_p, bind, true);
75a70cf9 14336 bind_body = NULL;
e3a19533 14337 dlist = NULL;
75a70cf9 14338 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt),
bc7bff74 14339 &bind_body, &dlist, ctx, NULL);
e3a19533 14340 lower_omp (gimple_omp_body_ptr (single_stmt), ctx);
1e8e9920 14341
75a70cf9 14342 gimple_seq_add_stmt (&bind_body, single_stmt);
1e8e9920 14343
14344 if (ctx->record_type)
75a70cf9 14345 lower_omp_single_copy (single_stmt, &bind_body, ctx);
1e8e9920 14346 else
75a70cf9 14347 lower_omp_single_simple (single_stmt, &bind_body);
14348
14349 gimple_omp_set_body (single_stmt, NULL);
1e8e9920 14350
75a70cf9 14351 gimple_seq_add_seq (&bind_body, dlist);
61e47ac8 14352
75a70cf9 14353 bind_body = maybe_catch_exception (bind_body);
61e47ac8 14354
48e1416a 14355 t = gimple_build_omp_return
75a70cf9 14356 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt),
14357 OMP_CLAUSE_NOWAIT));
bc7bff74 14358 gimple_seq_add_stmt (&bind_body_tail, t);
14359 maybe_add_implicit_barrier_cancel (ctx, &bind_body_tail);
14360 if (ctx->record_type)
14361 {
14362 gimple_stmt_iterator gsi = gsi_start (bind_body_tail);
14363 tree clobber = build_constructor (ctx->record_type, NULL);
14364 TREE_THIS_VOLATILE (clobber) = 1;
14365 gsi_insert_after (&gsi, gimple_build_assign (ctx->sender_decl,
14366 clobber), GSI_SAME_STMT);
14367 }
14368 gimple_seq_add_seq (&bind_body, bind_body_tail);
e3a19533 14369 gimple_bind_set_body (bind, bind_body);
61e47ac8 14370
1e8e9920 14371 pop_gimplify_context (bind);
773c5ba7 14372
75a70cf9 14373 gimple_bind_append_vars (bind, ctx->block_vars);
14374 BLOCK_VARS (block) = ctx->block_vars;
1d22f541 14375 if (BLOCK_VARS (block))
14376 TREE_USED (block) = 1;
1e8e9920 14377}
14378
773c5ba7 14379
1e8e9920 14380/* Expand code for an OpenMP master directive. */
14381
14382static void
75a70cf9 14383lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
1e8e9920 14384{
b9a16870 14385 tree block, lab = NULL, x, bfn_decl;
42acab1c 14386 gimple *stmt = gsi_stmt (*gsi_p);
1a91d914 14387 gbind *bind;
389dd41b 14388 location_t loc = gimple_location (stmt);
75a70cf9 14389 gimple_seq tseq;
1e8e9920 14390
8a4a28a8 14391 push_gimplify_context ();
1e8e9920 14392
14393 block = make_node (BLOCK);
e3a19533 14394 bind = gimple_build_bind (NULL, NULL, block);
14395 gsi_replace (gsi_p, bind, true);
14396 gimple_bind_add_stmt (bind, stmt);
61e47ac8 14397
b9a16870 14398 bfn_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
14399 x = build_call_expr_loc (loc, bfn_decl, 0);
1e8e9920 14400 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
14401 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
75a70cf9 14402 tseq = NULL;
14403 gimplify_and_add (x, &tseq);
14404 gimple_bind_add_seq (bind, tseq);
1e8e9920 14405
e3a19533 14406 lower_omp (gimple_omp_body_ptr (stmt), ctx);
75a70cf9 14407 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
14408 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
14409 gimple_omp_set_body (stmt, NULL);
1e8e9920 14410
75a70cf9 14411 gimple_bind_add_stmt (bind, gimple_build_label (lab));
61e47ac8 14412
75a70cf9 14413 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
61e47ac8 14414
1e8e9920 14415 pop_gimplify_context (bind);
773c5ba7 14416
75a70cf9 14417 gimple_bind_append_vars (bind, ctx->block_vars);
14418 BLOCK_VARS (block) = ctx->block_vars;
1e8e9920 14419}
14420
773c5ba7 14421
bc7bff74 14422/* Expand code for an OpenMP taskgroup directive. */
14423
14424static void
14425lower_omp_taskgroup (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14426{
42acab1c 14427 gimple *stmt = gsi_stmt (*gsi_p);
1a91d914 14428 gcall *x;
14429 gbind *bind;
bc7bff74 14430 tree block = make_node (BLOCK);
14431
14432 bind = gimple_build_bind (NULL, NULL, block);
14433 gsi_replace (gsi_p, bind, true);
14434 gimple_bind_add_stmt (bind, stmt);
14435
14436 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START),
14437 0);
14438 gimple_bind_add_stmt (bind, x);
14439
14440 lower_omp (gimple_omp_body_ptr (stmt), ctx);
14441 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
14442 gimple_omp_set_body (stmt, NULL);
14443
14444 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
14445
14446 gimple_bind_append_vars (bind, ctx->block_vars);
14447 BLOCK_VARS (block) = ctx->block_vars;
14448}
14449
14450
43895be5 14451/* Fold the OMP_ORDERED_CLAUSES for the OMP_ORDERED in STMT if possible. */
14452
14453static void
14454lower_omp_ordered_clauses (gimple_stmt_iterator *gsi_p, gomp_ordered *ord_stmt,
14455 omp_context *ctx)
14456{
14457 struct omp_for_data fd;
14458 if (!ctx->outer || gimple_code (ctx->outer->stmt) != GIMPLE_OMP_FOR)
14459 return;
14460
14461 unsigned int len = gimple_omp_for_collapse (ctx->outer->stmt);
14462 struct omp_for_data_loop *loops = XALLOCAVEC (struct omp_for_data_loop, len);
14463 extract_omp_for_data (as_a <gomp_for *> (ctx->outer->stmt), &fd, loops);
14464 if (!fd.ordered)
14465 return;
14466
14467 tree *list_p = gimple_omp_ordered_clauses_ptr (ord_stmt);
14468 tree c = gimple_omp_ordered_clauses (ord_stmt);
14469 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
14470 && OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK)
14471 {
14472 /* Merge depend clauses from multiple adjacent
14473 #pragma omp ordered depend(sink:...) constructs
14474 into one #pragma omp ordered depend(sink:...), so that
14475 we can optimize them together. */
14476 gimple_stmt_iterator gsi = *gsi_p;
14477 gsi_next (&gsi);
14478 while (!gsi_end_p (gsi))
14479 {
14480 gimple *stmt = gsi_stmt (gsi);
14481 if (is_gimple_debug (stmt)
14482 || gimple_code (stmt) == GIMPLE_NOP)
14483 {
14484 gsi_next (&gsi);
14485 continue;
14486 }
14487 if (gimple_code (stmt) != GIMPLE_OMP_ORDERED)
14488 break;
14489 gomp_ordered *ord_stmt2 = as_a <gomp_ordered *> (stmt);
14490 c = gimple_omp_ordered_clauses (ord_stmt2);
14491 if (c == NULL_TREE
14492 || OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND
14493 || OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_SINK)
14494 break;
14495 while (*list_p)
14496 list_p = &OMP_CLAUSE_CHAIN (*list_p);
14497 *list_p = c;
14498 gsi_remove (&gsi, true);
14499 }
14500 }
14501
14502 /* Canonicalize sink dependence clauses into one folded clause if
14503 possible.
14504
14505 The basic algorithm is to create a sink vector whose first
14506 element is the GCD of all the first elements, and whose remaining
14507 elements are the minimum of the subsequent columns.
14508
14509 We ignore dependence vectors whose first element is zero because
14510 such dependencies are known to be executed by the same thread.
14511
14512 We take into account the direction of the loop, so a minimum
14513 becomes a maximum if the loop is iterating forwards. We also
14514 ignore sink clauses where the loop direction is unknown, or where
14515 the offsets are clearly invalid because they are not a multiple
14516 of the loop increment.
14517
14518 For example:
14519
14520 #pragma omp for ordered(2)
14521 for (i=0; i < N; ++i)
14522 for (j=0; j < M; ++j)
14523 {
14524 #pragma omp ordered \
14525 depend(sink:i-8,j-2) \
14526 depend(sink:i,j-1) \ // Completely ignored because i+0.
14527 depend(sink:i-4,j-3) \
14528 depend(sink:i-6,j-4)
14529 #pragma omp ordered depend(source)
14530 }
14531
14532 Folded clause is:
14533
14534 depend(sink:-gcd(8,4,6),-min(2,3,4))
14535 -or-
14536 depend(sink:-2,-2)
14537 */
14538
14539 /* FIXME: Computing GCD's where the first element is zero is
14540 non-trivial in the presence of collapsed loops. Do this later. */
14541 if (fd.collapse > 1)
14542 return;
14543
14544 wide_int *folded_deps = XALLOCAVEC (wide_int, 2 * len - 1);
14545 memset (folded_deps, 0, sizeof (*folded_deps) * (2 * len - 1));
14546 tree folded_dep = NULL_TREE;
14547 /* TRUE if the first dimension's offset is negative. */
14548 bool neg_offset_p = false;
14549
14550 list_p = gimple_omp_ordered_clauses_ptr (ord_stmt);
14551 unsigned int i;
14552 while ((c = *list_p) != NULL)
14553 {
14554 bool remove = false;
14555
14556 gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND);
14557 if (OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_SINK)
14558 goto next_ordered_clause;
14559
14560 tree vec;
14561 for (vec = OMP_CLAUSE_DECL (c), i = 0;
14562 vec && TREE_CODE (vec) == TREE_LIST;
14563 vec = TREE_CHAIN (vec), ++i)
14564 {
14565 gcc_assert (i < len);
14566
14567 /* extract_omp_for_data has canonicalized the condition. */
14568 gcc_assert (fd.loops[i].cond_code == LT_EXPR
14569 || fd.loops[i].cond_code == GT_EXPR);
14570 bool forward = fd.loops[i].cond_code == LT_EXPR;
14571 bool maybe_lexically_later = true;
14572
14573 /* While the committee makes up its mind, bail if we have any
14574 non-constant steps. */
14575 if (TREE_CODE (fd.loops[i].step) != INTEGER_CST)
14576 goto lower_omp_ordered_ret;
14577
14578 tree itype = TREE_TYPE (TREE_VALUE (vec));
14579 if (POINTER_TYPE_P (itype))
14580 itype = sizetype;
14581 wide_int offset = wide_int::from (TREE_PURPOSE (vec),
14582 TYPE_PRECISION (itype),
14583 TYPE_SIGN (itype));
14584
14585 /* Ignore invalid offsets that are not multiples of the step. */
14586 if (!wi::multiple_of_p
14587 (wi::abs (offset), wi::abs ((wide_int) fd.loops[i].step),
14588 UNSIGNED))
14589 {
14590 warning_at (OMP_CLAUSE_LOCATION (c), 0,
14591 "ignoring sink clause with offset that is not "
14592 "a multiple of the loop step");
14593 remove = true;
14594 goto next_ordered_clause;
14595 }
14596
14597 /* Calculate the first dimension. The first dimension of
14598 the folded dependency vector is the GCD of the first
14599 elements, while ignoring any first elements whose offset
14600 is 0. */
14601 if (i == 0)
14602 {
14603 /* Ignore dependence vectors whose first dimension is 0. */
14604 if (offset == 0)
14605 {
14606 remove = true;
14607 goto next_ordered_clause;
14608 }
14609 else
14610 {
14611 if (!TYPE_UNSIGNED (itype) && (forward ^ wi::neg_p (offset)))
14612 {
14613 error_at (OMP_CLAUSE_LOCATION (c),
14614 "first offset must be in opposite direction "
14615 "of loop iterations");
14616 goto lower_omp_ordered_ret;
14617 }
14618 if (forward)
14619 offset = -offset;
14620 neg_offset_p = forward;
14621 /* Initialize the first time around. */
14622 if (folded_dep == NULL_TREE)
14623 {
14624 folded_dep = c;
14625 folded_deps[0] = offset;
14626 }
14627 else
14628 folded_deps[0] = wi::gcd (folded_deps[0],
14629 offset, UNSIGNED);
14630 }
14631 }
14632 /* Calculate minimum for the remaining dimensions. */
14633 else
14634 {
14635 folded_deps[len + i - 1] = offset;
14636 if (folded_dep == c)
14637 folded_deps[i] = offset;
14638 else if (maybe_lexically_later
14639 && !wi::eq_p (folded_deps[i], offset))
14640 {
14641 if (forward ^ wi::gts_p (folded_deps[i], offset))
14642 {
14643 unsigned int j;
14644 folded_dep = c;
14645 for (j = 1; j <= i; j++)
14646 folded_deps[j] = folded_deps[len + j - 1];
14647 }
14648 else
14649 maybe_lexically_later = false;
14650 }
14651 }
14652 }
14653 gcc_assert (i == len);
14654
14655 remove = true;
14656
14657 next_ordered_clause:
14658 if (remove)
14659 *list_p = OMP_CLAUSE_CHAIN (c);
14660 else
14661 list_p = &OMP_CLAUSE_CHAIN (c);
14662 }
14663
14664 if (folded_dep)
14665 {
14666 if (neg_offset_p)
14667 folded_deps[0] = -folded_deps[0];
14668
14669 tree itype = TREE_TYPE (TREE_VALUE (OMP_CLAUSE_DECL (folded_dep)));
14670 if (POINTER_TYPE_P (itype))
14671 itype = sizetype;
14672
14673 TREE_PURPOSE (OMP_CLAUSE_DECL (folded_dep))
14674 = wide_int_to_tree (itype, folded_deps[0]);
14675 OMP_CLAUSE_CHAIN (folded_dep) = gimple_omp_ordered_clauses (ord_stmt);
14676 *gimple_omp_ordered_clauses_ptr (ord_stmt) = folded_dep;
14677 }
14678
14679 lower_omp_ordered_ret:
14680
14681 /* Ordered without clauses is #pragma omp threads, while we want
14682 a nop instead if we remove all clauses. */
14683 if (gimple_omp_ordered_clauses (ord_stmt) == NULL_TREE)
14684 gsi_replace (gsi_p, gimple_build_nop (), true);
14685}
14686
14687
1e8e9920 14688/* Expand code for an OpenMP ordered directive. */
14689
14690static void
75a70cf9 14691lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
1e8e9920 14692{
75a70cf9 14693 tree block;
42acab1c 14694 gimple *stmt = gsi_stmt (*gsi_p);
43895be5 14695 gomp_ordered *ord_stmt = as_a <gomp_ordered *> (stmt);
1a91d914 14696 gcall *x;
14697 gbind *bind;
a9833286 14698 bool simd = find_omp_clause (gimple_omp_ordered_clauses (ord_stmt),
14699 OMP_CLAUSE_SIMD);
14700 bool threads = find_omp_clause (gimple_omp_ordered_clauses (ord_stmt),
14701 OMP_CLAUSE_THREADS);
43895be5 14702
14703 if (find_omp_clause (gimple_omp_ordered_clauses (ord_stmt),
14704 OMP_CLAUSE_DEPEND))
14705 {
14706 /* FIXME: This is needs to be moved to the expansion to verify various
14707 conditions only testable on cfg with dominators computed, and also
14708 all the depend clauses to be merged still might need to be available
14709 for the runtime checks. */
14710 if (0)
14711 lower_omp_ordered_clauses (gsi_p, ord_stmt, ctx);
14712 return;
14713 }
1e8e9920 14714
8a4a28a8 14715 push_gimplify_context ();
1e8e9920 14716
14717 block = make_node (BLOCK);
e3a19533 14718 bind = gimple_build_bind (NULL, NULL, block);
14719 gsi_replace (gsi_p, bind, true);
14720 gimple_bind_add_stmt (bind, stmt);
61e47ac8 14721
43895be5 14722 if (simd)
14723 {
a9833286 14724 x = gimple_build_call_internal (IFN_GOMP_SIMD_ORDERED_START, 1,
14725 build_int_cst (NULL_TREE, threads));
43895be5 14726 cfun->has_simduid_loops = true;
14727 }
14728 else
14729 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START),
14730 0);
75a70cf9 14731 gimple_bind_add_stmt (bind, x);
1e8e9920 14732
e3a19533 14733 lower_omp (gimple_omp_body_ptr (stmt), ctx);
75a70cf9 14734 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
14735 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
14736 gimple_omp_set_body (stmt, NULL);
1e8e9920 14737
43895be5 14738 if (simd)
a9833286 14739 x = gimple_build_call_internal (IFN_GOMP_SIMD_ORDERED_END, 1,
14740 build_int_cst (NULL_TREE, threads));
43895be5 14741 else
14742 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END),
14743 0);
75a70cf9 14744 gimple_bind_add_stmt (bind, x);
61e47ac8 14745
75a70cf9 14746 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
61e47ac8 14747
1e8e9920 14748 pop_gimplify_context (bind);
773c5ba7 14749
75a70cf9 14750 gimple_bind_append_vars (bind, ctx->block_vars);
14751 BLOCK_VARS (block) = gimple_bind_vars (bind);
1e8e9920 14752}
14753
1e8e9920 14754
75a70cf9 14755/* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
1e8e9920 14756 substitution of a couple of function calls. But in the NAMED case,
14757 requires that languages coordinate a symbol name. It is therefore
14758 best put here in common code. */
14759
d4786b13 14760static GTY(()) hash_map<tree, tree> *critical_name_mutexes;
1e8e9920 14761
14762static void
75a70cf9 14763lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
1e8e9920 14764{
75a70cf9 14765 tree block;
14766 tree name, lock, unlock;
1a91d914 14767 gomp_critical *stmt = as_a <gomp_critical *> (gsi_stmt (*gsi_p));
14768 gbind *bind;
389dd41b 14769 location_t loc = gimple_location (stmt);
75a70cf9 14770 gimple_seq tbody;
1e8e9920 14771
75a70cf9 14772 name = gimple_omp_critical_name (stmt);
1e8e9920 14773 if (name)
14774 {
c2f47e15 14775 tree decl;
1e8e9920 14776
14777 if (!critical_name_mutexes)
d4786b13 14778 critical_name_mutexes = hash_map<tree, tree>::create_ggc (10);
1e8e9920 14779
d4786b13 14780 tree *n = critical_name_mutexes->get (name);
1e8e9920 14781 if (n == NULL)
14782 {
14783 char *new_str;
14784
f9e245b2 14785 decl = create_tmp_var_raw (ptr_type_node);
1e8e9920 14786
14787 new_str = ACONCAT ((".gomp_critical_user_",
14788 IDENTIFIER_POINTER (name), NULL));
14789 DECL_NAME (decl) = get_identifier (new_str);
14790 TREE_PUBLIC (decl) = 1;
14791 TREE_STATIC (decl) = 1;
14792 DECL_COMMON (decl) = 1;
14793 DECL_ARTIFICIAL (decl) = 1;
14794 DECL_IGNORED_P (decl) = 1;
b0c5e347 14795
97221fd7 14796 varpool_node::finalize_decl (decl);
1e8e9920 14797
d4786b13 14798 critical_name_mutexes->put (name, decl);
1e8e9920 14799 }
14800 else
d4786b13 14801 decl = *n;
1e8e9920 14802
ca4c3545 14803 /* If '#pragma omp critical' is inside offloaded region or
351fb0ce 14804 inside function marked as offloadable, the symbol must be
14805 marked as offloadable too. */
14806 omp_context *octx;
14807 if (cgraph_node::get (current_function_decl)->offloadable)
14808 varpool_node::get_create (decl)->offloadable = 1;
14809 else
14810 for (octx = ctx->outer; octx; octx = octx->outer)
ca4c3545 14811 if (is_gimple_omp_offloaded (octx->stmt))
351fb0ce 14812 {
14813 varpool_node::get_create (decl)->offloadable = 1;
14814 break;
14815 }
14816
b9a16870 14817 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START);
389dd41b 14818 lock = build_call_expr_loc (loc, lock, 1, build_fold_addr_expr_loc (loc, decl));
1e8e9920 14819
b9a16870 14820 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END);
389dd41b 14821 unlock = build_call_expr_loc (loc, unlock, 1,
14822 build_fold_addr_expr_loc (loc, decl));
1e8e9920 14823 }
14824 else
14825 {
b9a16870 14826 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START);
389dd41b 14827 lock = build_call_expr_loc (loc, lock, 0);
1e8e9920 14828
b9a16870 14829 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END);
389dd41b 14830 unlock = build_call_expr_loc (loc, unlock, 0);
1e8e9920 14831 }
14832
8a4a28a8 14833 push_gimplify_context ();
1e8e9920 14834
14835 block = make_node (BLOCK);
e3a19533 14836 bind = gimple_build_bind (NULL, NULL, block);
14837 gsi_replace (gsi_p, bind, true);
14838 gimple_bind_add_stmt (bind, stmt);
61e47ac8 14839
75a70cf9 14840 tbody = gimple_bind_body (bind);
14841 gimplify_and_add (lock, &tbody);
14842 gimple_bind_set_body (bind, tbody);
1e8e9920 14843
e3a19533 14844 lower_omp (gimple_omp_body_ptr (stmt), ctx);
75a70cf9 14845 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
14846 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
14847 gimple_omp_set_body (stmt, NULL);
1e8e9920 14848
75a70cf9 14849 tbody = gimple_bind_body (bind);
14850 gimplify_and_add (unlock, &tbody);
14851 gimple_bind_set_body (bind, tbody);
61e47ac8 14852
75a70cf9 14853 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
1e8e9920 14854
14855 pop_gimplify_context (bind);
75a70cf9 14856 gimple_bind_append_vars (bind, ctx->block_vars);
14857 BLOCK_VARS (block) = gimple_bind_vars (bind);
773c5ba7 14858}
14859
14860
14861/* A subroutine of lower_omp_for. Generate code to emit the predicate
14862 for a lastprivate clause. Given a loop control predicate of (V
14863 cond N2), we gate the clause on (!(V cond N2)). The lowered form
1e4afe3c 14864 is appended to *DLIST, iterator initialization is appended to
14865 *BODY_P. */
773c5ba7 14866
14867static void
75a70cf9 14868lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
14869 gimple_seq *dlist, struct omp_context *ctx)
773c5ba7 14870{
75a70cf9 14871 tree clauses, cond, vinit;
773c5ba7 14872 enum tree_code cond_code;
75a70cf9 14873 gimple_seq stmts;
48e1416a 14874
fd6481cf 14875 cond_code = fd->loop.cond_code;
773c5ba7 14876 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
14877
14878 /* When possible, use a strict equality expression. This can let VRP
14879 type optimizations deduce the value and remove a copy. */
e913b5cd 14880 if (tree_fits_shwi_p (fd->loop.step))
773c5ba7 14881 {
e913b5cd 14882 HOST_WIDE_INT step = tree_to_shwi (fd->loop.step);
773c5ba7 14883 if (step == 1 || step == -1)
14884 cond_code = EQ_EXPR;
14885 }
14886
d7729e26 14887 tree n2 = fd->loop.n2;
14888 if (fd->collapse > 1
14889 && TREE_CODE (n2) != INTEGER_CST
43895be5 14890 && gimple_omp_for_combined_into_p (fd->for_stmt))
d7729e26 14891 {
9561765e 14892 struct omp_context *taskreg_ctx = NULL;
43895be5 14893 if (gimple_code (ctx->outer->stmt) == GIMPLE_OMP_FOR)
14894 {
14895 gomp_for *gfor = as_a <gomp_for *> (ctx->outer->stmt);
9561765e 14896 if (gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_FOR
14897 || gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_DISTRIBUTE)
43895be5 14898 {
9561765e 14899 if (gimple_omp_for_combined_into_p (gfor))
14900 {
14901 gcc_assert (ctx->outer->outer
14902 && is_parallel_ctx (ctx->outer->outer));
14903 taskreg_ctx = ctx->outer->outer;
14904 }
14905 else
14906 {
14907 struct omp_for_data outer_fd;
14908 extract_omp_for_data (gfor, &outer_fd, NULL);
14909 n2 = fold_convert (TREE_TYPE (n2), outer_fd.loop.n2);
14910 }
43895be5 14911 }
14912 else if (gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_TASKLOOP)
9561765e 14913 taskreg_ctx = ctx->outer->outer;
43895be5 14914 }
9561765e 14915 else if (is_taskreg_ctx (ctx->outer))
14916 taskreg_ctx = ctx->outer;
14917 if (taskreg_ctx)
d7729e26 14918 {
43895be5 14919 int i;
14920 tree innerc
9561765e 14921 = find_omp_clause (gimple_omp_taskreg_clauses (taskreg_ctx->stmt),
43895be5 14922 OMP_CLAUSE__LOOPTEMP_);
14923 gcc_assert (innerc);
14924 for (i = 0; i < fd->collapse; i++)
14925 {
14926 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
14927 OMP_CLAUSE__LOOPTEMP_);
14928 gcc_assert (innerc);
14929 }
14930 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
14931 OMP_CLAUSE__LOOPTEMP_);
14932 if (innerc)
14933 n2 = fold_convert (TREE_TYPE (n2),
14934 lookup_decl (OMP_CLAUSE_DECL (innerc),
9561765e 14935 taskreg_ctx));
d7729e26 14936 }
14937 }
14938 cond = build2 (cond_code, boolean_type_node, fd->loop.v, n2);
773c5ba7 14939
75a70cf9 14940 clauses = gimple_omp_for_clauses (fd->for_stmt);
1e4afe3c 14941 stmts = NULL;
14942 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
75a70cf9 14943 if (!gimple_seq_empty_p (stmts))
1e4afe3c 14944 {
75a70cf9 14945 gimple_seq_add_seq (&stmts, *dlist);
fd6481cf 14946 *dlist = stmts;
1e4afe3c 14947
14948 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
fd6481cf 14949 vinit = fd->loop.n1;
1e4afe3c 14950 if (cond_code == EQ_EXPR
e913b5cd 14951 && tree_fits_shwi_p (fd->loop.n2)
fd6481cf 14952 && ! integer_zerop (fd->loop.n2))
14953 vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0);
3d483a94 14954 else
14955 vinit = unshare_expr (vinit);
1e4afe3c 14956
14957 /* Initialize the iterator variable, so that threads that don't execute
14958 any iterations don't execute the lastprivate clauses by accident. */
75a70cf9 14959 gimplify_assign (fd->loop.v, vinit, body_p);
1e4afe3c 14960 }
773c5ba7 14961}
14962
14963
ca4c3545 14964/* Lower code for an OMP loop directive. */
773c5ba7 14965
14966static void
75a70cf9 14967lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
773c5ba7 14968{
75a70cf9 14969 tree *rhs_p, block;
bc7bff74 14970 struct omp_for_data fd, *fdp = NULL;
1a91d914 14971 gomp_for *stmt = as_a <gomp_for *> (gsi_stmt (*gsi_p));
14972 gbind *new_stmt;
f018d957 14973 gimple_seq omp_for_body, body, dlist;
a8e785ba 14974 gimple_seq oacc_head = NULL, oacc_tail = NULL;
75a70cf9 14975 size_t i;
773c5ba7 14976
8a4a28a8 14977 push_gimplify_context ();
773c5ba7 14978
e3a19533 14979 lower_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
773c5ba7 14980
1d22f541 14981 block = make_node (BLOCK);
75a70cf9 14982 new_stmt = gimple_build_bind (NULL, NULL, block);
e3a19533 14983 /* Replace at gsi right away, so that 'stmt' is no member
47ae02b7 14984 of a sequence anymore as we're going to add to a different
e3a19533 14985 one below. */
14986 gsi_replace (gsi_p, new_stmt, true);
1d22f541 14987
773c5ba7 14988 /* Move declaration of temporaries in the loop body before we make
14989 it go away. */
75a70cf9 14990 omp_for_body = gimple_omp_body (stmt);
14991 if (!gimple_seq_empty_p (omp_for_body)
14992 && gimple_code (gimple_seq_first_stmt (omp_for_body)) == GIMPLE_BIND)
14993 {
1a91d914 14994 gbind *inner_bind
14995 = as_a <gbind *> (gimple_seq_first_stmt (omp_for_body));
6d5a8d89 14996 tree vars = gimple_bind_vars (inner_bind);
75a70cf9 14997 gimple_bind_append_vars (new_stmt, vars);
6d5a8d89 14998 /* bind_vars/BLOCK_VARS are being moved to new_stmt/block, don't
14999 keep them on the inner_bind and it's block. */
15000 gimple_bind_set_vars (inner_bind, NULL_TREE);
15001 if (gimple_bind_block (inner_bind))
15002 BLOCK_VARS (gimple_bind_block (inner_bind)) = NULL_TREE;
75a70cf9 15003 }
773c5ba7 15004
bc7bff74 15005 if (gimple_omp_for_combined_into_p (stmt))
15006 {
15007 extract_omp_for_data (stmt, &fd, NULL);
15008 fdp = &fd;
15009
15010 /* We need two temporaries with fd.loop.v type (istart/iend)
15011 and then (fd.collapse - 1) temporaries with the same
15012 type for count2 ... countN-1 vars if not constant. */
15013 size_t count = 2;
15014 tree type = fd.iter_type;
15015 if (fd.collapse > 1
15016 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
15017 count += fd.collapse - 1;
43895be5 15018 bool taskreg_for
15019 = (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR
15020 || gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_TASKLOOP);
bc7bff74 15021 tree outerc = NULL, *pc = gimple_omp_for_clauses_ptr (stmt);
15022 tree clauses = *pc;
43895be5 15023 if (taskreg_for)
bc7bff74 15024 outerc
43895be5 15025 = find_omp_clause (gimple_omp_taskreg_clauses (ctx->outer->stmt),
bc7bff74 15026 OMP_CLAUSE__LOOPTEMP_);
15027 for (i = 0; i < count; i++)
15028 {
15029 tree temp;
43895be5 15030 if (taskreg_for)
bc7bff74 15031 {
15032 gcc_assert (outerc);
15033 temp = lookup_decl (OMP_CLAUSE_DECL (outerc), ctx->outer);
15034 outerc = find_omp_clause (OMP_CLAUSE_CHAIN (outerc),
15035 OMP_CLAUSE__LOOPTEMP_);
15036 }
15037 else
691447ab 15038 {
f9e245b2 15039 temp = create_tmp_var (type);
691447ab 15040 insert_decl_map (&ctx->outer->cb, temp, temp);
15041 }
bc7bff74 15042 *pc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
15043 OMP_CLAUSE_DECL (*pc) = temp;
15044 pc = &OMP_CLAUSE_CHAIN (*pc);
15045 }
15046 *pc = clauses;
15047 }
15048
75a70cf9 15049 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
773c5ba7 15050 dlist = NULL;
75a70cf9 15051 body = NULL;
bc7bff74 15052 lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx,
15053 fdp);
75a70cf9 15054 gimple_seq_add_seq (&body, gimple_omp_for_pre_body (stmt));
773c5ba7 15055
3d483a94 15056 lower_omp (gimple_omp_body_ptr (stmt), ctx);
15057
773c5ba7 15058 /* Lower the header expressions. At this point, we can assume that
15059 the header is of the form:
15060
15061 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
15062
15063 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
15064 using the .omp_data_s mapping, if needed. */
75a70cf9 15065 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
fd6481cf 15066 {
75a70cf9 15067 rhs_p = gimple_omp_for_initial_ptr (stmt, i);
fd6481cf 15068 if (!is_gimple_min_invariant (*rhs_p))
75a70cf9 15069 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
fd6481cf 15070
75a70cf9 15071 rhs_p = gimple_omp_for_final_ptr (stmt, i);
fd6481cf 15072 if (!is_gimple_min_invariant (*rhs_p))
75a70cf9 15073 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
fd6481cf 15074
75a70cf9 15075 rhs_p = &TREE_OPERAND (gimple_omp_for_incr (stmt, i), 1);
fd6481cf 15076 if (!is_gimple_min_invariant (*rhs_p))
75a70cf9 15077 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
fd6481cf 15078 }
773c5ba7 15079
15080 /* Once lowered, extract the bounds and clauses. */
fd6481cf 15081 extract_omp_for_data (stmt, &fd, NULL);
773c5ba7 15082
a8e785ba 15083 if (is_gimple_omp_oacc (ctx->stmt)
15084 && !ctx_in_oacc_kernels_region (ctx))
15085 lower_oacc_head_tail (gimple_location (stmt),
15086 gimple_omp_for_clauses (stmt),
15087 &oacc_head, &oacc_tail, ctx);
15088
f69b8a4c 15089 /* Add OpenACC partitioning and reduction markers just before the loop */
a8e785ba 15090 if (oacc_head)
15091 gimple_seq_add_seq (&body, oacc_head);
15092
75a70cf9 15093 lower_omp_for_lastprivate (&fd, &body, &dlist, ctx);
773c5ba7 15094
43895be5 15095 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR)
15096 for (tree c = gimple_omp_for_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
15097 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
15098 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
15099 {
15100 OMP_CLAUSE_DECL (c) = lookup_decl (OMP_CLAUSE_DECL (c), ctx);
15101 if (DECL_P (OMP_CLAUSE_LINEAR_STEP (c)))
15102 OMP_CLAUSE_LINEAR_STEP (c)
15103 = maybe_lookup_decl_in_outer_ctx (OMP_CLAUSE_LINEAR_STEP (c),
15104 ctx);
15105 }
15106
56686608 15107 if (!gimple_omp_for_grid_phony (stmt))
15108 gimple_seq_add_stmt (&body, stmt);
75a70cf9 15109 gimple_seq_add_seq (&body, gimple_omp_body (stmt));
61e47ac8 15110
56686608 15111 if (!gimple_omp_for_grid_phony (stmt))
15112 gimple_seq_add_stmt (&body, gimple_build_omp_continue (fd.loop.v,
15113 fd.loop.v));
61e47ac8 15114
773c5ba7 15115 /* After the loop, add exit clauses. */
75a70cf9 15116 lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, ctx);
bc7bff74 15117
15118 if (ctx->cancellable)
15119 gimple_seq_add_stmt (&body, gimple_build_label (ctx->cancel_label));
15120
75a70cf9 15121 gimple_seq_add_seq (&body, dlist);
773c5ba7 15122
75a70cf9 15123 body = maybe_catch_exception (body);
aade31a0 15124
56686608 15125 if (!gimple_omp_for_grid_phony (stmt))
15126 {
15127 /* Region exit marker goes at the end of the loop body. */
15128 gimple_seq_add_stmt (&body, gimple_build_omp_return (fd.have_nowait));
15129 maybe_add_implicit_barrier_cancel (ctx, &body);
15130 }
a8e785ba 15131
15132 /* Add OpenACC joining and reduction markers just after the loop. */
15133 if (oacc_tail)
15134 gimple_seq_add_seq (&body, oacc_tail);
15135
1d22f541 15136 pop_gimplify_context (new_stmt);
75a70cf9 15137
15138 gimple_bind_append_vars (new_stmt, ctx->block_vars);
15139 BLOCK_VARS (block) = gimple_bind_vars (new_stmt);
1d22f541 15140 if (BLOCK_VARS (block))
15141 TREE_USED (block) = 1;
773c5ba7 15142
75a70cf9 15143 gimple_bind_set_body (new_stmt, body);
15144 gimple_omp_set_body (stmt, NULL);
15145 gimple_omp_for_set_pre_body (stmt, NULL);
1e8e9920 15146}
15147
48e1416a 15148/* Callback for walk_stmts. Check if the current statement only contains
a7dfc4fe 15149 GIMPLE_OMP_FOR or GIMPLE_OMP_SECTIONS. */
de7ef844 15150
15151static tree
75a70cf9 15152check_combined_parallel (gimple_stmt_iterator *gsi_p,
15153 bool *handled_ops_p,
15154 struct walk_stmt_info *wi)
de7ef844 15155{
4077bf7a 15156 int *info = (int *) wi->info;
42acab1c 15157 gimple *stmt = gsi_stmt (*gsi_p);
de7ef844 15158
75a70cf9 15159 *handled_ops_p = true;
15160 switch (gimple_code (stmt))
de7ef844 15161 {
75a70cf9 15162 WALK_SUBSTMTS;
15163
15164 case GIMPLE_OMP_FOR:
15165 case GIMPLE_OMP_SECTIONS:
de7ef844 15166 *info = *info == 0 ? 1 : -1;
15167 break;
15168 default:
15169 *info = -1;
15170 break;
15171 }
15172 return NULL;
15173}
773c5ba7 15174
fd6481cf 15175struct omp_taskcopy_context
15176{
15177 /* This field must be at the beginning, as we do "inheritance": Some
15178 callback functions for tree-inline.c (e.g., omp_copy_decl)
15179 receive a copy_body_data pointer that is up-casted to an
15180 omp_context pointer. */
15181 copy_body_data cb;
15182 omp_context *ctx;
15183};
15184
15185static tree
15186task_copyfn_copy_decl (tree var, copy_body_data *cb)
15187{
15188 struct omp_taskcopy_context *tcctx = (struct omp_taskcopy_context *) cb;
15189
15190 if (splay_tree_lookup (tcctx->ctx->sfield_map, (splay_tree_key) var))
f9e245b2 15191 return create_tmp_var (TREE_TYPE (var));
fd6481cf 15192
15193 return var;
15194}
15195
15196static tree
15197task_copyfn_remap_type (struct omp_taskcopy_context *tcctx, tree orig_type)
15198{
15199 tree name, new_fields = NULL, type, f;
15200
15201 type = lang_hooks.types.make_type (RECORD_TYPE);
15202 name = DECL_NAME (TYPE_NAME (orig_type));
e60a6f7b 15203 name = build_decl (gimple_location (tcctx->ctx->stmt),
15204 TYPE_DECL, name, type);
fd6481cf 15205 TYPE_NAME (type) = name;
15206
15207 for (f = TYPE_FIELDS (orig_type); f ; f = TREE_CHAIN (f))
15208 {
15209 tree new_f = copy_node (f);
15210 DECL_CONTEXT (new_f) = type;
15211 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &tcctx->cb);
15212 TREE_CHAIN (new_f) = new_fields;
75a70cf9 15213 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &tcctx->cb, NULL);
15214 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r, &tcctx->cb, NULL);
15215 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
15216 &tcctx->cb, NULL);
fd6481cf 15217 new_fields = new_f;
06ecf488 15218 tcctx->cb.decl_map->put (f, new_f);
fd6481cf 15219 }
15220 TYPE_FIELDS (type) = nreverse (new_fields);
15221 layout_type (type);
15222 return type;
15223}
15224
15225/* Create task copyfn. */
15226
15227static void
1a91d914 15228create_task_copyfn (gomp_task *task_stmt, omp_context *ctx)
fd6481cf 15229{
15230 struct function *child_cfun;
15231 tree child_fn, t, c, src, dst, f, sf, arg, sarg, decl;
15232 tree record_type, srecord_type, bind, list;
15233 bool record_needs_remap = false, srecord_needs_remap = false;
15234 splay_tree_node n;
15235 struct omp_taskcopy_context tcctx;
389dd41b 15236 location_t loc = gimple_location (task_stmt);
fd6481cf 15237
75a70cf9 15238 child_fn = gimple_omp_task_copy_fn (task_stmt);
fd6481cf 15239 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
15240 gcc_assert (child_cfun->cfg == NULL);
fd6481cf 15241 DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
15242
15243 /* Reset DECL_CONTEXT on function arguments. */
1767a056 15244 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
fd6481cf 15245 DECL_CONTEXT (t) = child_fn;
15246
15247 /* Populate the function. */
8a4a28a8 15248 push_gimplify_context ();
9078126c 15249 push_cfun (child_cfun);
fd6481cf 15250
15251 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
15252 TREE_SIDE_EFFECTS (bind) = 1;
15253 list = NULL;
15254 DECL_SAVED_TREE (child_fn) = bind;
75a70cf9 15255 DECL_SOURCE_LOCATION (child_fn) = gimple_location (task_stmt);
fd6481cf 15256
15257 /* Remap src and dst argument types if needed. */
15258 record_type = ctx->record_type;
15259 srecord_type = ctx->srecord_type;
1767a056 15260 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
fd6481cf 15261 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
15262 {
15263 record_needs_remap = true;
15264 break;
15265 }
1767a056 15266 for (f = TYPE_FIELDS (srecord_type); f ; f = DECL_CHAIN (f))
fd6481cf 15267 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
15268 {
15269 srecord_needs_remap = true;
15270 break;
15271 }
15272
15273 if (record_needs_remap || srecord_needs_remap)
15274 {
15275 memset (&tcctx, '\0', sizeof (tcctx));
15276 tcctx.cb.src_fn = ctx->cb.src_fn;
15277 tcctx.cb.dst_fn = child_fn;
415d1b9a 15278 tcctx.cb.src_node = cgraph_node::get (tcctx.cb.src_fn);
53f79206 15279 gcc_checking_assert (tcctx.cb.src_node);
fd6481cf 15280 tcctx.cb.dst_node = tcctx.cb.src_node;
15281 tcctx.cb.src_cfun = ctx->cb.src_cfun;
15282 tcctx.cb.copy_decl = task_copyfn_copy_decl;
e38def9c 15283 tcctx.cb.eh_lp_nr = 0;
fd6481cf 15284 tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
06ecf488 15285 tcctx.cb.decl_map = new hash_map<tree, tree>;
fd6481cf 15286 tcctx.ctx = ctx;
15287
15288 if (record_needs_remap)
15289 record_type = task_copyfn_remap_type (&tcctx, record_type);
15290 if (srecord_needs_remap)
15291 srecord_type = task_copyfn_remap_type (&tcctx, srecord_type);
15292 }
15293 else
15294 tcctx.cb.decl_map = NULL;
15295
fd6481cf 15296 arg = DECL_ARGUMENTS (child_fn);
15297 TREE_TYPE (arg) = build_pointer_type (record_type);
1767a056 15298 sarg = DECL_CHAIN (arg);
fd6481cf 15299 TREE_TYPE (sarg) = build_pointer_type (srecord_type);
15300
15301 /* First pass: initialize temporaries used in record_type and srecord_type
15302 sizes and field offsets. */
15303 if (tcctx.cb.decl_map)
75a70cf9 15304 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
fd6481cf 15305 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
15306 {
15307 tree *p;
15308
15309 decl = OMP_CLAUSE_DECL (c);
06ecf488 15310 p = tcctx.cb.decl_map->get (decl);
fd6481cf 15311 if (p == NULL)
15312 continue;
15313 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
15314 sf = (tree) n->value;
06ecf488 15315 sf = *tcctx.cb.decl_map->get (sf);
182cf5a9 15316 src = build_simple_mem_ref_loc (loc, sarg);
445d06b6 15317 src = omp_build_component_ref (src, sf);
75a70cf9 15318 t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
fd6481cf 15319 append_to_statement_list (t, &list);
15320 }
15321
15322 /* Second pass: copy shared var pointers and copy construct non-VLA
15323 firstprivate vars. */
75a70cf9 15324 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
fd6481cf 15325 switch (OMP_CLAUSE_CODE (c))
15326 {
43895be5 15327 splay_tree_key key;
fd6481cf 15328 case OMP_CLAUSE_SHARED:
15329 decl = OMP_CLAUSE_DECL (c);
43895be5 15330 key = (splay_tree_key) decl;
15331 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
15332 key = (splay_tree_key) &DECL_UID (decl);
15333 n = splay_tree_lookup (ctx->field_map, key);
fd6481cf 15334 if (n == NULL)
15335 break;
15336 f = (tree) n->value;
15337 if (tcctx.cb.decl_map)
06ecf488 15338 f = *tcctx.cb.decl_map->get (f);
43895be5 15339 n = splay_tree_lookup (ctx->sfield_map, key);
fd6481cf 15340 sf = (tree) n->value;
15341 if (tcctx.cb.decl_map)
06ecf488 15342 sf = *tcctx.cb.decl_map->get (sf);
182cf5a9 15343 src = build_simple_mem_ref_loc (loc, sarg);
445d06b6 15344 src = omp_build_component_ref (src, sf);
182cf5a9 15345 dst = build_simple_mem_ref_loc (loc, arg);
445d06b6 15346 dst = omp_build_component_ref (dst, f);
75a70cf9 15347 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
fd6481cf 15348 append_to_statement_list (t, &list);
15349 break;
15350 case OMP_CLAUSE_FIRSTPRIVATE:
15351 decl = OMP_CLAUSE_DECL (c);
15352 if (is_variable_sized (decl))
15353 break;
15354 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
15355 if (n == NULL)
15356 break;
15357 f = (tree) n->value;
15358 if (tcctx.cb.decl_map)
06ecf488 15359 f = *tcctx.cb.decl_map->get (f);
fd6481cf 15360 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
15361 if (n != NULL)
15362 {
15363 sf = (tree) n->value;
15364 if (tcctx.cb.decl_map)
06ecf488 15365 sf = *tcctx.cb.decl_map->get (sf);
182cf5a9 15366 src = build_simple_mem_ref_loc (loc, sarg);
445d06b6 15367 src = omp_build_component_ref (src, sf);
fd6481cf 15368 if (use_pointer_for_field (decl, NULL) || is_reference (decl))
182cf5a9 15369 src = build_simple_mem_ref_loc (loc, src);
fd6481cf 15370 }
15371 else
15372 src = decl;
182cf5a9 15373 dst = build_simple_mem_ref_loc (loc, arg);
445d06b6 15374 dst = omp_build_component_ref (dst, f);
fd6481cf 15375 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
15376 append_to_statement_list (t, &list);
15377 break;
15378 case OMP_CLAUSE_PRIVATE:
15379 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c))
15380 break;
15381 decl = OMP_CLAUSE_DECL (c);
15382 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
15383 f = (tree) n->value;
15384 if (tcctx.cb.decl_map)
06ecf488 15385 f = *tcctx.cb.decl_map->get (f);
fd6481cf 15386 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
15387 if (n != NULL)
15388 {
15389 sf = (tree) n->value;
15390 if (tcctx.cb.decl_map)
06ecf488 15391 sf = *tcctx.cb.decl_map->get (sf);
182cf5a9 15392 src = build_simple_mem_ref_loc (loc, sarg);
445d06b6 15393 src = omp_build_component_ref (src, sf);
fd6481cf 15394 if (use_pointer_for_field (decl, NULL))
182cf5a9 15395 src = build_simple_mem_ref_loc (loc, src);
fd6481cf 15396 }
15397 else
15398 src = decl;
182cf5a9 15399 dst = build_simple_mem_ref_loc (loc, arg);
445d06b6 15400 dst = omp_build_component_ref (dst, f);
75a70cf9 15401 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
fd6481cf 15402 append_to_statement_list (t, &list);
15403 break;
15404 default:
15405 break;
15406 }
15407
15408 /* Last pass: handle VLA firstprivates. */
15409 if (tcctx.cb.decl_map)
75a70cf9 15410 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
fd6481cf 15411 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
15412 {
15413 tree ind, ptr, df;
15414
15415 decl = OMP_CLAUSE_DECL (c);
15416 if (!is_variable_sized (decl))
15417 continue;
15418 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
15419 if (n == NULL)
15420 continue;
15421 f = (tree) n->value;
06ecf488 15422 f = *tcctx.cb.decl_map->get (f);
fd6481cf 15423 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
15424 ind = DECL_VALUE_EXPR (decl);
15425 gcc_assert (TREE_CODE (ind) == INDIRECT_REF);
15426 gcc_assert (DECL_P (TREE_OPERAND (ind, 0)));
15427 n = splay_tree_lookup (ctx->sfield_map,
15428 (splay_tree_key) TREE_OPERAND (ind, 0));
15429 sf = (tree) n->value;
06ecf488 15430 sf = *tcctx.cb.decl_map->get (sf);
182cf5a9 15431 src = build_simple_mem_ref_loc (loc, sarg);
445d06b6 15432 src = omp_build_component_ref (src, sf);
182cf5a9 15433 src = build_simple_mem_ref_loc (loc, src);
15434 dst = build_simple_mem_ref_loc (loc, arg);
445d06b6 15435 dst = omp_build_component_ref (dst, f);
fd6481cf 15436 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
15437 append_to_statement_list (t, &list);
15438 n = splay_tree_lookup (ctx->field_map,
15439 (splay_tree_key) TREE_OPERAND (ind, 0));
15440 df = (tree) n->value;
06ecf488 15441 df = *tcctx.cb.decl_map->get (df);
182cf5a9 15442 ptr = build_simple_mem_ref_loc (loc, arg);
445d06b6 15443 ptr = omp_build_component_ref (ptr, df);
75a70cf9 15444 t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
389dd41b 15445 build_fold_addr_expr_loc (loc, dst));
fd6481cf 15446 append_to_statement_list (t, &list);
15447 }
15448
15449 t = build1 (RETURN_EXPR, void_type_node, NULL);
15450 append_to_statement_list (t, &list);
15451
15452 if (tcctx.cb.decl_map)
06ecf488 15453 delete tcctx.cb.decl_map;
fd6481cf 15454 pop_gimplify_context (NULL);
15455 BIND_EXPR_BODY (bind) = list;
15456 pop_cfun ();
fd6481cf 15457}
15458
bc7bff74 15459static void
43895be5 15460lower_depend_clauses (tree *pclauses, gimple_seq *iseq, gimple_seq *oseq)
bc7bff74 15461{
15462 tree c, clauses;
42acab1c 15463 gimple *g;
bc7bff74 15464 size_t n_in = 0, n_out = 0, idx = 2, i;
15465
43895be5 15466 clauses = find_omp_clause (*pclauses, OMP_CLAUSE_DEPEND);
bc7bff74 15467 gcc_assert (clauses);
15468 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
15469 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
15470 switch (OMP_CLAUSE_DEPEND_KIND (c))
15471 {
15472 case OMP_CLAUSE_DEPEND_IN:
15473 n_in++;
15474 break;
15475 case OMP_CLAUSE_DEPEND_OUT:
15476 case OMP_CLAUSE_DEPEND_INOUT:
15477 n_out++;
15478 break;
43895be5 15479 case OMP_CLAUSE_DEPEND_SOURCE:
15480 case OMP_CLAUSE_DEPEND_SINK:
15481 /* FALLTHRU */
bc7bff74 15482 default:
15483 gcc_unreachable ();
15484 }
15485 tree type = build_array_type_nelts (ptr_type_node, n_in + n_out + 2);
f9e245b2 15486 tree array = create_tmp_var (type);
43895be5 15487 TREE_ADDRESSABLE (array) = 1;
bc7bff74 15488 tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
15489 NULL_TREE);
15490 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_in + n_out));
15491 gimple_seq_add_stmt (iseq, g);
15492 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
15493 NULL_TREE);
15494 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_out));
15495 gimple_seq_add_stmt (iseq, g);
15496 for (i = 0; i < 2; i++)
15497 {
15498 if ((i ? n_in : n_out) == 0)
15499 continue;
15500 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
15501 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
15502 && ((OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_IN) ^ i))
15503 {
15504 tree t = OMP_CLAUSE_DECL (c);
15505 t = fold_convert (ptr_type_node, t);
15506 gimplify_expr (&t, iseq, NULL, is_gimple_val, fb_rvalue);
15507 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (idx++),
15508 NULL_TREE, NULL_TREE);
15509 g = gimple_build_assign (r, t);
15510 gimple_seq_add_stmt (iseq, g);
15511 }
15512 }
bc7bff74 15513 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
15514 OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
43895be5 15515 OMP_CLAUSE_CHAIN (c) = *pclauses;
15516 *pclauses = c;
bc7bff74 15517 tree clobber = build_constructor (type, NULL);
15518 TREE_THIS_VOLATILE (clobber) = 1;
15519 g = gimple_build_assign (array, clobber);
15520 gimple_seq_add_stmt (oseq, g);
15521}
15522
75a70cf9 15523/* Lower the OpenMP parallel or task directive in the current statement
15524 in GSI_P. CTX holds context information for the directive. */
773c5ba7 15525
15526static void
75a70cf9 15527lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
773c5ba7 15528{
75a70cf9 15529 tree clauses;
15530 tree child_fn, t;
42acab1c 15531 gimple *stmt = gsi_stmt (*gsi_p);
1a91d914 15532 gbind *par_bind, *bind, *dep_bind = NULL;
bc7bff74 15533 gimple_seq par_body, olist, ilist, par_olist, par_rlist, par_ilist, new_body;
389dd41b 15534 location_t loc = gimple_location (stmt);
773c5ba7 15535
75a70cf9 15536 clauses = gimple_omp_taskreg_clauses (stmt);
1a91d914 15537 par_bind
15538 = as_a <gbind *> (gimple_seq_first_stmt (gimple_omp_body (stmt)));
75a70cf9 15539 par_body = gimple_bind_body (par_bind);
773c5ba7 15540 child_fn = ctx->cb.dst_fn;
75a70cf9 15541 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
15542 && !gimple_omp_parallel_combined_p (stmt))
de7ef844 15543 {
15544 struct walk_stmt_info wi;
15545 int ws_num = 0;
15546
15547 memset (&wi, 0, sizeof (wi));
de7ef844 15548 wi.info = &ws_num;
15549 wi.val_only = true;
75a70cf9 15550 walk_gimple_seq (par_body, check_combined_parallel, NULL, &wi);
de7ef844 15551 if (ws_num == 1)
75a70cf9 15552 gimple_omp_parallel_set_combined_p (stmt, true);
de7ef844 15553 }
bc7bff74 15554 gimple_seq dep_ilist = NULL;
15555 gimple_seq dep_olist = NULL;
15556 if (gimple_code (stmt) == GIMPLE_OMP_TASK
15557 && find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
15558 {
8a4a28a8 15559 push_gimplify_context ();
bc7bff74 15560 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
43895be5 15561 lower_depend_clauses (gimple_omp_task_clauses_ptr (stmt),
15562 &dep_ilist, &dep_olist);
bc7bff74 15563 }
15564
fd6481cf 15565 if (ctx->srecord_type)
1a91d914 15566 create_task_copyfn (as_a <gomp_task *> (stmt), ctx);
773c5ba7 15567
8a4a28a8 15568 push_gimplify_context ();
773c5ba7 15569
75a70cf9 15570 par_olist = NULL;
15571 par_ilist = NULL;
bc7bff74 15572 par_rlist = NULL;
56686608 15573 bool phony_construct = gimple_code (stmt) == GIMPLE_OMP_PARALLEL
15574 && gimple_omp_parallel_grid_phony (as_a <gomp_parallel *> (stmt));
15575 if (phony_construct && ctx->record_type)
15576 {
15577 gcc_checking_assert (!ctx->receiver_decl);
15578 ctx->receiver_decl = create_tmp_var
15579 (build_reference_type (ctx->record_type), ".omp_rec");
15580 }
bc7bff74 15581 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx, NULL);
e3a19533 15582 lower_omp (&par_body, ctx);
75a70cf9 15583 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL)
bc7bff74 15584 lower_reduction_clauses (clauses, &par_rlist, ctx);
773c5ba7 15585
15586 /* Declare all the variables created by mapping and the variables
15587 declared in the scope of the parallel body. */
15588 record_vars_into (ctx->block_vars, child_fn);
75a70cf9 15589 record_vars_into (gimple_bind_vars (par_bind), child_fn);
773c5ba7 15590
15591 if (ctx->record_type)
15592 {
fd6481cf 15593 ctx->sender_decl
15594 = create_tmp_var (ctx->srecord_type ? ctx->srecord_type
15595 : ctx->record_type, ".omp_data_o");
84bfaaeb 15596 DECL_NAMELESS (ctx->sender_decl) = 1;
86f2ad37 15597 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
75a70cf9 15598 gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl);
773c5ba7 15599 }
15600
75a70cf9 15601 olist = NULL;
15602 ilist = NULL;
773c5ba7 15603 lower_send_clauses (clauses, &ilist, &olist, ctx);
15604 lower_send_shared_vars (&ilist, &olist, ctx);
15605
bc7bff74 15606 if (ctx->record_type)
15607 {
15608 tree clobber = build_constructor (TREE_TYPE (ctx->sender_decl), NULL);
15609 TREE_THIS_VOLATILE (clobber) = 1;
15610 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
15611 clobber));
15612 }
15613
773c5ba7 15614 /* Once all the expansions are done, sequence all the different
75a70cf9 15615 fragments inside gimple_omp_body. */
773c5ba7 15616
75a70cf9 15617 new_body = NULL;
773c5ba7 15618
15619 if (ctx->record_type)
15620 {
389dd41b 15621 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
cc6b725b 15622 /* fixup_child_record_type might have changed receiver_decl's type. */
389dd41b 15623 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
75a70cf9 15624 gimple_seq_add_stmt (&new_body,
15625 gimple_build_assign (ctx->receiver_decl, t));
773c5ba7 15626 }
15627
75a70cf9 15628 gimple_seq_add_seq (&new_body, par_ilist);
15629 gimple_seq_add_seq (&new_body, par_body);
bc7bff74 15630 gimple_seq_add_seq (&new_body, par_rlist);
15631 if (ctx->cancellable)
15632 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
75a70cf9 15633 gimple_seq_add_seq (&new_body, par_olist);
15634 new_body = maybe_catch_exception (new_body);
b25f70fd 15635 if (gimple_code (stmt) == GIMPLE_OMP_TASK)
15636 gimple_seq_add_stmt (&new_body,
15637 gimple_build_omp_continue (integer_zero_node,
15638 integer_zero_node));
56686608 15639 if (!phony_construct)
15640 {
15641 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
15642 gimple_omp_set_body (stmt, new_body);
15643 }
773c5ba7 15644
75a70cf9 15645 bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
bc7bff74 15646 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
15647 gimple_bind_add_seq (bind, ilist);
56686608 15648 if (!phony_construct)
15649 gimple_bind_add_stmt (bind, stmt);
15650 else
15651 gimple_bind_add_seq (bind, new_body);
bc7bff74 15652 gimple_bind_add_seq (bind, olist);
15653
15654 pop_gimplify_context (NULL);
15655
15656 if (dep_bind)
15657 {
15658 gimple_bind_add_seq (dep_bind, dep_ilist);
15659 gimple_bind_add_stmt (dep_bind, bind);
15660 gimple_bind_add_seq (dep_bind, dep_olist);
15661 pop_gimplify_context (dep_bind);
15662 }
15663}
15664
ca4c3545 15665/* Lower the GIMPLE_OMP_TARGET in the current statement
bc7bff74 15666 in GSI_P. CTX holds context information for the directive. */
15667
15668static void
15669lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
15670{
15671 tree clauses;
15672 tree child_fn, t, c;
1a91d914 15673 gomp_target *stmt = as_a <gomp_target *> (gsi_stmt (*gsi_p));
43895be5 15674 gbind *tgt_bind, *bind, *dep_bind = NULL;
b656be3a 15675 gimple_seq tgt_body, olist, ilist, fplist, new_body;
bc7bff74 15676 location_t loc = gimple_location (stmt);
ca4c3545 15677 bool offloaded, data_region;
bc7bff74 15678 unsigned int map_cnt = 0;
43895be5 15679 bool has_depend = false;
bc7bff74 15680
ca4c3545 15681 offloaded = is_gimple_omp_offloaded (stmt);
15682 switch (gimple_omp_target_kind (stmt))
15683 {
15684 case GF_OMP_TARGET_KIND_REGION:
15685 case GF_OMP_TARGET_KIND_UPDATE:
43895be5 15686 case GF_OMP_TARGET_KIND_ENTER_DATA:
15687 case GF_OMP_TARGET_KIND_EXIT_DATA:
ca4c3545 15688 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
15689 case GF_OMP_TARGET_KIND_OACC_KERNELS:
15690 case GF_OMP_TARGET_KIND_OACC_UPDATE:
15691 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
2fc5e987 15692 case GF_OMP_TARGET_KIND_OACC_DECLARE:
ca4c3545 15693 data_region = false;
15694 break;
15695 case GF_OMP_TARGET_KIND_DATA:
15696 case GF_OMP_TARGET_KIND_OACC_DATA:
571b3486 15697 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
ca4c3545 15698 data_region = true;
15699 break;
15700 default:
15701 gcc_unreachable ();
15702 }
15703
bc7bff74 15704 clauses = gimple_omp_target_clauses (stmt);
ca4c3545 15705
43895be5 15706 gimple_seq dep_ilist = NULL;
15707 gimple_seq dep_olist = NULL;
15708 if (find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
15709 {
15710 push_gimplify_context ();
15711 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
15712 lower_depend_clauses (gimple_omp_target_clauses_ptr (stmt),
15713 &dep_ilist, &dep_olist);
15714 has_depend = true;
15715 }
15716
ca4c3545 15717 tgt_bind = NULL;
15718 tgt_body = NULL;
15719 if (offloaded)
bc7bff74 15720 {
1a91d914 15721 tgt_bind = gimple_seq_first_stmt_as_a_bind (gimple_omp_body (stmt));
bc7bff74 15722 tgt_body = gimple_bind_body (tgt_bind);
15723 }
ca4c3545 15724 else if (data_region)
bc7bff74 15725 tgt_body = gimple_omp_body (stmt);
15726 child_fn = ctx->cb.dst_fn;
15727
8a4a28a8 15728 push_gimplify_context ();
b656be3a 15729 fplist = NULL;
bc7bff74 15730
15731 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
15732 switch (OMP_CLAUSE_CODE (c))
15733 {
15734 tree var, x;
15735
15736 default:
15737 break;
15738 case OMP_CLAUSE_MAP:
382ecba7 15739#if CHECKING_P
ca4c3545 15740 /* First check what we're prepared to handle in the following. */
15741 switch (OMP_CLAUSE_MAP_KIND (c))
15742 {
15743 case GOMP_MAP_ALLOC:
15744 case GOMP_MAP_TO:
15745 case GOMP_MAP_FROM:
15746 case GOMP_MAP_TOFROM:
15747 case GOMP_MAP_POINTER:
15748 case GOMP_MAP_TO_PSET:
5cb6b0b9 15749 case GOMP_MAP_DELETE:
43895be5 15750 case GOMP_MAP_RELEASE:
15751 case GOMP_MAP_ALWAYS_TO:
15752 case GOMP_MAP_ALWAYS_FROM:
15753 case GOMP_MAP_ALWAYS_TOFROM:
15754 case GOMP_MAP_FIRSTPRIVATE_POINTER:
9561765e 15755 case GOMP_MAP_FIRSTPRIVATE_REFERENCE:
43895be5 15756 case GOMP_MAP_STRUCT:
9561765e 15757 case GOMP_MAP_ALWAYS_POINTER:
ca4c3545 15758 break;
15759 case GOMP_MAP_FORCE_ALLOC:
15760 case GOMP_MAP_FORCE_TO:
15761 case GOMP_MAP_FORCE_FROM:
15762 case GOMP_MAP_FORCE_TOFROM:
15763 case GOMP_MAP_FORCE_PRESENT:
ca4c3545 15764 case GOMP_MAP_FORCE_DEVICEPTR:
2fc5e987 15765 case GOMP_MAP_DEVICE_RESIDENT:
15766 case GOMP_MAP_LINK:
ca4c3545 15767 gcc_assert (is_gimple_omp_oacc (stmt));
15768 break;
15769 default:
15770 gcc_unreachable ();
15771 }
15772#endif
15773 /* FALLTHRU */
bc7bff74 15774 case OMP_CLAUSE_TO:
15775 case OMP_CLAUSE_FROM:
b656be3a 15776 oacc_firstprivate:
bc7bff74 15777 var = OMP_CLAUSE_DECL (c);
15778 if (!DECL_P (var))
15779 {
15780 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
43895be5 15781 || (!OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
15782 && (OMP_CLAUSE_MAP_KIND (c)
15783 != GOMP_MAP_FIRSTPRIVATE_POINTER)))
bc7bff74 15784 map_cnt++;
15785 continue;
15786 }
15787
15788 if (DECL_SIZE (var)
15789 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
15790 {
15791 tree var2 = DECL_VALUE_EXPR (var);
15792 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
15793 var2 = TREE_OPERAND (var2, 0);
15794 gcc_assert (DECL_P (var2));
15795 var = var2;
15796 }
15797
43895be5 15798 if (offloaded
b656be3a 15799 && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
9561765e 15800 && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
15801 || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_REFERENCE))
43895be5 15802 {
15803 if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
15804 {
15805 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx))
15806 && varpool_node::get_create (var)->offloadable)
15807 continue;
15808
15809 tree type = build_pointer_type (TREE_TYPE (var));
15810 tree new_var = lookup_decl (var, ctx);
15811 x = create_tmp_var_raw (type, get_name (new_var));
15812 gimple_add_tmp_var (x);
15813 x = build_simple_mem_ref (x);
15814 SET_DECL_VALUE_EXPR (new_var, x);
15815 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15816 }
15817 continue;
15818 }
15819
bc7bff74 15820 if (!maybe_lookup_field (var, ctx))
15821 continue;
15822
ca4c3545 15823 if (offloaded)
bc7bff74 15824 {
15825 x = build_receiver_ref (var, true, ctx);
15826 tree new_var = lookup_decl (var, ctx);
43895be5 15827
b656be3a 15828 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
15829 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
bc7bff74 15830 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
15831 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
15832 x = build_simple_mem_ref (x);
b656be3a 15833 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
15834 {
15835 gcc_assert (is_gimple_omp_oacc (ctx->stmt));
15836 if (is_reference (new_var))
15837 {
15838 /* Create a local object to hold the instance
15839 value. */
15840 tree type = TREE_TYPE (TREE_TYPE (new_var));
15841 const char *id = IDENTIFIER_POINTER (DECL_NAME (new_var));
15842 tree inst = create_tmp_var (type, id);
15843 gimplify_assign (inst, fold_indirect_ref (x), &fplist);
15844 x = build_fold_addr_expr (inst);
15845 }
15846 gimplify_assign (new_var, x, &fplist);
15847 }
15848 else if (DECL_P (new_var))
15849 {
15850 SET_DECL_VALUE_EXPR (new_var, x);
15851 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15852 }
15853 else
15854 gcc_unreachable ();
bc7bff74 15855 }
15856 map_cnt++;
43895be5 15857 break;
15858
15859 case OMP_CLAUSE_FIRSTPRIVATE:
b656be3a 15860 if (is_oacc_parallel (ctx))
15861 goto oacc_firstprivate;
43895be5 15862 map_cnt++;
15863 var = OMP_CLAUSE_DECL (c);
15864 if (!is_reference (var)
15865 && !is_gimple_reg_type (TREE_TYPE (var)))
15866 {
15867 tree new_var = lookup_decl (var, ctx);
15868 if (is_variable_sized (var))
15869 {
15870 tree pvar = DECL_VALUE_EXPR (var);
15871 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15872 pvar = TREE_OPERAND (pvar, 0);
15873 gcc_assert (DECL_P (pvar));
15874 tree new_pvar = lookup_decl (pvar, ctx);
15875 x = build_fold_indirect_ref (new_pvar);
15876 TREE_THIS_NOTRAP (x) = 1;
15877 }
15878 else
15879 x = build_receiver_ref (var, true, ctx);
15880 SET_DECL_VALUE_EXPR (new_var, x);
15881 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15882 }
15883 break;
15884
15885 case OMP_CLAUSE_PRIVATE:
b656be3a 15886 if (is_gimple_omp_oacc (ctx->stmt))
15887 break;
43895be5 15888 var = OMP_CLAUSE_DECL (c);
15889 if (is_variable_sized (var))
15890 {
15891 tree new_var = lookup_decl (var, ctx);
15892 tree pvar = DECL_VALUE_EXPR (var);
15893 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15894 pvar = TREE_OPERAND (pvar, 0);
15895 gcc_assert (DECL_P (pvar));
15896 tree new_pvar = lookup_decl (pvar, ctx);
15897 x = build_fold_indirect_ref (new_pvar);
15898 TREE_THIS_NOTRAP (x) = 1;
15899 SET_DECL_VALUE_EXPR (new_var, x);
15900 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15901 }
15902 break;
15903
15904 case OMP_CLAUSE_USE_DEVICE_PTR:
15905 case OMP_CLAUSE_IS_DEVICE_PTR:
15906 var = OMP_CLAUSE_DECL (c);
15907 map_cnt++;
15908 if (is_variable_sized (var))
15909 {
15910 tree new_var = lookup_decl (var, ctx);
15911 tree pvar = DECL_VALUE_EXPR (var);
15912 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15913 pvar = TREE_OPERAND (pvar, 0);
15914 gcc_assert (DECL_P (pvar));
15915 tree new_pvar = lookup_decl (pvar, ctx);
15916 x = build_fold_indirect_ref (new_pvar);
15917 TREE_THIS_NOTRAP (x) = 1;
15918 SET_DECL_VALUE_EXPR (new_var, x);
15919 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15920 }
15921 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
15922 {
15923 tree new_var = lookup_decl (var, ctx);
15924 tree type = build_pointer_type (TREE_TYPE (var));
15925 x = create_tmp_var_raw (type, get_name (new_var));
15926 gimple_add_tmp_var (x);
15927 x = build_simple_mem_ref (x);
15928 SET_DECL_VALUE_EXPR (new_var, x);
15929 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15930 }
b86e24ea 15931 else
15932 {
15933 tree new_var = lookup_decl (var, ctx);
15934 x = create_tmp_var_raw (TREE_TYPE (new_var), get_name (new_var));
15935 gimple_add_tmp_var (x);
15936 SET_DECL_VALUE_EXPR (new_var, x);
15937 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15938 }
43895be5 15939 break;
bc7bff74 15940 }
15941
ca4c3545 15942 if (offloaded)
bc7bff74 15943 {
15944 target_nesting_level++;
15945 lower_omp (&tgt_body, ctx);
15946 target_nesting_level--;
15947 }
ca4c3545 15948 else if (data_region)
bc7bff74 15949 lower_omp (&tgt_body, ctx);
15950
ca4c3545 15951 if (offloaded)
bc7bff74 15952 {
15953 /* Declare all the variables created by mapping and the variables
15954 declared in the scope of the target body. */
15955 record_vars_into (ctx->block_vars, child_fn);
15956 record_vars_into (gimple_bind_vars (tgt_bind), child_fn);
15957 }
15958
15959 olist = NULL;
15960 ilist = NULL;
15961 if (ctx->record_type)
15962 {
15963 ctx->sender_decl
15964 = create_tmp_var (ctx->record_type, ".omp_data_arr");
15965 DECL_NAMELESS (ctx->sender_decl) = 1;
15966 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
15967 t = make_tree_vec (3);
15968 TREE_VEC_ELT (t, 0) = ctx->sender_decl;
15969 TREE_VEC_ELT (t, 1)
15970 = create_tmp_var (build_array_type_nelts (size_type_node, map_cnt),
15971 ".omp_data_sizes");
15972 DECL_NAMELESS (TREE_VEC_ELT (t, 1)) = 1;
15973 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 1)) = 1;
15974 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 1;
43895be5 15975 tree tkind_type = short_unsigned_type_node;
15976 int talign_shift = 8;
bc7bff74 15977 TREE_VEC_ELT (t, 2)
ca4c3545 15978 = create_tmp_var (build_array_type_nelts (tkind_type, map_cnt),
bc7bff74 15979 ".omp_data_kinds");
15980 DECL_NAMELESS (TREE_VEC_ELT (t, 2)) = 1;
15981 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 2)) = 1;
15982 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 1;
15983 gimple_omp_target_set_data_arg (stmt, t);
15984
15985 vec<constructor_elt, va_gc> *vsize;
15986 vec<constructor_elt, va_gc> *vkind;
15987 vec_alloc (vsize, map_cnt);
15988 vec_alloc (vkind, map_cnt);
15989 unsigned int map_idx = 0;
15990
15991 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
15992 switch (OMP_CLAUSE_CODE (c))
15993 {
43895be5 15994 tree ovar, nc, s, purpose, var, x, type;
15995 unsigned int talign;
bc7bff74 15996
15997 default:
15998 break;
b656be3a 15999
bc7bff74 16000 case OMP_CLAUSE_MAP:
16001 case OMP_CLAUSE_TO:
16002 case OMP_CLAUSE_FROM:
b656be3a 16003 oacc_firstprivate_map:
bc7bff74 16004 nc = c;
16005 ovar = OMP_CLAUSE_DECL (c);
43895be5 16006 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
9561765e 16007 && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
16008 || (OMP_CLAUSE_MAP_KIND (c)
16009 == GOMP_MAP_FIRSTPRIVATE_REFERENCE)))
43895be5 16010 break;
bc7bff74 16011 if (!DECL_P (ovar))
16012 {
16013 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
16014 && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
16015 {
16016 gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c))
16017 == get_base_address (ovar));
16018 nc = OMP_CLAUSE_CHAIN (c);
16019 ovar = OMP_CLAUSE_DECL (nc);
16020 }
16021 else
16022 {
16023 tree x = build_sender_ref (ovar, ctx);
16024 tree v
16025 = build_fold_addr_expr_with_type (ovar, ptr_type_node);
16026 gimplify_assign (x, v, &ilist);
16027 nc = NULL_TREE;
16028 }
16029 }
16030 else
16031 {
16032 if (DECL_SIZE (ovar)
16033 && TREE_CODE (DECL_SIZE (ovar)) != INTEGER_CST)
16034 {
16035 tree ovar2 = DECL_VALUE_EXPR (ovar);
16036 gcc_assert (TREE_CODE (ovar2) == INDIRECT_REF);
16037 ovar2 = TREE_OPERAND (ovar2, 0);
16038 gcc_assert (DECL_P (ovar2));
16039 ovar = ovar2;
16040 }
9561765e 16041 if (!maybe_lookup_field (ovar, ctx))
bc7bff74 16042 continue;
16043 }
16044
43895be5 16045 talign = TYPE_ALIGN_UNIT (TREE_TYPE (ovar));
4f3b8d78 16046 if (DECL_P (ovar) && DECL_ALIGN_UNIT (ovar) > talign)
16047 talign = DECL_ALIGN_UNIT (ovar);
bc7bff74 16048 if (nc)
16049 {
43895be5 16050 var = lookup_decl_in_outer_ctx (ovar, ctx);
9561765e 16051 x = build_sender_ref (ovar, ctx);
abe55632 16052
16053 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
b656be3a 16054 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
16055 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
16056 && TREE_CODE (TREE_TYPE (ovar)) == ARRAY_TYPE)
bc7bff74 16057 {
ca4c3545 16058 gcc_assert (offloaded);
bc7bff74 16059 tree avar
f9e245b2 16060 = create_tmp_var (TREE_TYPE (TREE_TYPE (x)));
bc7bff74 16061 mark_addressable (avar);
16062 gimplify_assign (avar, build_fold_addr_expr (var), &ilist);
4f3b8d78 16063 talign = DECL_ALIGN_UNIT (avar);
bc7bff74 16064 avar = build_fold_addr_expr (avar);
16065 gimplify_assign (x, avar, &ilist);
16066 }
b656be3a 16067 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
16068 {
16069 gcc_assert (is_gimple_omp_oacc (ctx->stmt));
16070 if (!is_reference (var))
16071 var = build_fold_addr_expr (var);
16072 else
16073 talign = TYPE_ALIGN_UNIT (TREE_TYPE (TREE_TYPE (ovar)));
16074 gimplify_assign (x, var, &ilist);
16075 }
bc7bff74 16076 else if (is_gimple_reg (var))
16077 {
ca4c3545 16078 gcc_assert (offloaded);
f9e245b2 16079 tree avar = create_tmp_var (TREE_TYPE (var));
bc7bff74 16080 mark_addressable (avar);
ca4c3545 16081 enum gomp_map_kind map_kind = OMP_CLAUSE_MAP_KIND (c);
16082 if (GOMP_MAP_COPY_TO_P (map_kind)
16083 || map_kind == GOMP_MAP_POINTER
16084 || map_kind == GOMP_MAP_TO_PSET
16085 || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
bc7bff74 16086 gimplify_assign (avar, var, &ilist);
16087 avar = build_fold_addr_expr (avar);
16088 gimplify_assign (x, avar, &ilist);
ca4c3545 16089 if ((GOMP_MAP_COPY_FROM_P (map_kind)
16090 || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
bc7bff74 16091 && !TYPE_READONLY (TREE_TYPE (var)))
16092 {
43895be5 16093 x = unshare_expr (x);
bc7bff74 16094 x = build_simple_mem_ref (x);
16095 gimplify_assign (var, x, &olist);
16096 }
16097 }
16098 else
16099 {
16100 var = build_fold_addr_expr (var);
16101 gimplify_assign (x, var, &ilist);
16102 }
16103 }
b656be3a 16104 s = NULL_TREE;
16105 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
16106 {
16107 gcc_checking_assert (is_gimple_omp_oacc (ctx->stmt));
16108 s = TREE_TYPE (ovar);
16109 if (TREE_CODE (s) == REFERENCE_TYPE)
16110 s = TREE_TYPE (s);
16111 s = TYPE_SIZE_UNIT (s);
16112 }
16113 else
16114 s = OMP_CLAUSE_SIZE (c);
bc7bff74 16115 if (s == NULL_TREE)
16116 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
16117 s = fold_convert (size_type_node, s);
43895be5 16118 purpose = size_int (map_idx++);
bc7bff74 16119 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
16120 if (TREE_CODE (s) != INTEGER_CST)
16121 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
16122
43895be5 16123 unsigned HOST_WIDE_INT tkind, tkind_zero;
bc7bff74 16124 switch (OMP_CLAUSE_CODE (c))
16125 {
16126 case OMP_CLAUSE_MAP:
16127 tkind = OMP_CLAUSE_MAP_KIND (c);
43895be5 16128 tkind_zero = tkind;
16129 if (OMP_CLAUSE_MAP_MAYBE_ZERO_LENGTH_ARRAY_SECTION (c))
16130 switch (tkind)
16131 {
16132 case GOMP_MAP_ALLOC:
16133 case GOMP_MAP_TO:
16134 case GOMP_MAP_FROM:
16135 case GOMP_MAP_TOFROM:
16136 case GOMP_MAP_ALWAYS_TO:
16137 case GOMP_MAP_ALWAYS_FROM:
16138 case GOMP_MAP_ALWAYS_TOFROM:
16139 case GOMP_MAP_RELEASE:
16140 tkind_zero = GOMP_MAP_ZERO_LEN_ARRAY_SECTION;
16141 break;
16142 case GOMP_MAP_DELETE:
16143 tkind_zero = GOMP_MAP_DELETE_ZERO_LEN_ARRAY_SECTION;
16144 default:
16145 break;
16146 }
16147 if (tkind_zero != tkind)
16148 {
16149 if (integer_zerop (s))
16150 tkind = tkind_zero;
16151 else if (integer_nonzerop (s))
16152 tkind_zero = tkind;
16153 }
bc7bff74 16154 break;
b656be3a 16155 case OMP_CLAUSE_FIRSTPRIVATE:
16156 gcc_checking_assert (is_gimple_omp_oacc (ctx->stmt));
16157 tkind = GOMP_MAP_TO;
16158 tkind_zero = tkind;
16159 break;
bc7bff74 16160 case OMP_CLAUSE_TO:
ca4c3545 16161 tkind = GOMP_MAP_TO;
43895be5 16162 tkind_zero = tkind;
bc7bff74 16163 break;
16164 case OMP_CLAUSE_FROM:
ca4c3545 16165 tkind = GOMP_MAP_FROM;
43895be5 16166 tkind_zero = tkind;
bc7bff74 16167 break;
16168 default:
16169 gcc_unreachable ();
16170 }
ca4c3545 16171 gcc_checking_assert (tkind
16172 < (HOST_WIDE_INT_C (1U) << talign_shift));
43895be5 16173 gcc_checking_assert (tkind_zero
16174 < (HOST_WIDE_INT_C (1U) << talign_shift));
bc7bff74 16175 talign = ceil_log2 (talign);
ca4c3545 16176 tkind |= talign << talign_shift;
43895be5 16177 tkind_zero |= talign << talign_shift;
ca4c3545 16178 gcc_checking_assert (tkind
16179 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
43895be5 16180 gcc_checking_assert (tkind_zero
16181 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
16182 if (tkind == tkind_zero)
16183 x = build_int_cstu (tkind_type, tkind);
16184 else
16185 {
16186 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 0;
16187 x = build3 (COND_EXPR, tkind_type,
16188 fold_build2 (EQ_EXPR, boolean_type_node,
16189 unshare_expr (s), size_zero_node),
16190 build_int_cstu (tkind_type, tkind_zero),
16191 build_int_cstu (tkind_type, tkind));
16192 }
16193 CONSTRUCTOR_APPEND_ELT (vkind, purpose, x);
bc7bff74 16194 if (nc && nc != c)
16195 c = nc;
43895be5 16196 break;
16197
16198 case OMP_CLAUSE_FIRSTPRIVATE:
b656be3a 16199 if (is_oacc_parallel (ctx))
16200 goto oacc_firstprivate_map;
43895be5 16201 ovar = OMP_CLAUSE_DECL (c);
16202 if (is_reference (ovar))
16203 talign = TYPE_ALIGN_UNIT (TREE_TYPE (TREE_TYPE (ovar)));
16204 else
16205 talign = DECL_ALIGN_UNIT (ovar);
16206 var = lookup_decl_in_outer_ctx (ovar, ctx);
16207 x = build_sender_ref (ovar, ctx);
16208 tkind = GOMP_MAP_FIRSTPRIVATE;
16209 type = TREE_TYPE (ovar);
16210 if (is_reference (ovar))
16211 type = TREE_TYPE (type);
16212 bool use_firstprivate_int, force_addr;
16213 use_firstprivate_int = false;
16214 force_addr = false;
16215 if ((INTEGRAL_TYPE_P (type)
16216 && TYPE_PRECISION (type) <= POINTER_SIZE)
16217 || TREE_CODE (type) == POINTER_TYPE)
16218 use_firstprivate_int = true;
16219 if (has_depend)
16220 {
16221 if (is_reference (var))
16222 use_firstprivate_int = false;
16223 else if (is_gimple_reg (var))
16224 {
16225 if (DECL_HAS_VALUE_EXPR_P (var))
16226 {
16227 tree v = get_base_address (var);
16228 if (DECL_P (v) && TREE_ADDRESSABLE (v))
16229 {
16230 use_firstprivate_int = false;
16231 force_addr = true;
16232 }
16233 else
16234 switch (TREE_CODE (v))
16235 {
16236 case INDIRECT_REF:
16237 case MEM_REF:
16238 use_firstprivate_int = false;
16239 force_addr = true;
16240 break;
16241 default:
16242 break;
16243 }
16244 }
16245 }
16246 else
16247 use_firstprivate_int = false;
16248 }
16249 if (use_firstprivate_int)
16250 {
16251 tkind = GOMP_MAP_FIRSTPRIVATE_INT;
16252 tree t = var;
16253 if (is_reference (var))
16254 t = build_simple_mem_ref (var);
16255 if (TREE_CODE (type) != POINTER_TYPE)
16256 t = fold_convert (pointer_sized_int_node, t);
16257 t = fold_convert (TREE_TYPE (x), t);
16258 gimplify_assign (x, t, &ilist);
16259 }
16260 else if (is_reference (var))
16261 gimplify_assign (x, var, &ilist);
16262 else if (!force_addr && is_gimple_reg (var))
16263 {
16264 tree avar = create_tmp_var (TREE_TYPE (var));
16265 mark_addressable (avar);
16266 gimplify_assign (avar, var, &ilist);
16267 avar = build_fold_addr_expr (avar);
16268 gimplify_assign (x, avar, &ilist);
16269 }
16270 else
16271 {
16272 var = build_fold_addr_expr (var);
16273 gimplify_assign (x, var, &ilist);
16274 }
16275 if (tkind == GOMP_MAP_FIRSTPRIVATE_INT)
16276 s = size_int (0);
16277 else if (is_reference (var))
16278 s = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (ovar)));
16279 else
16280 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
16281 s = fold_convert (size_type_node, s);
16282 purpose = size_int (map_idx++);
16283 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
16284 if (TREE_CODE (s) != INTEGER_CST)
16285 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
16286
16287 gcc_checking_assert (tkind
16288 < (HOST_WIDE_INT_C (1U) << talign_shift));
16289 talign = ceil_log2 (talign);
16290 tkind |= talign << talign_shift;
16291 gcc_checking_assert (tkind
16292 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
16293 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
16294 build_int_cstu (tkind_type, tkind));
16295 break;
16296
16297 case OMP_CLAUSE_USE_DEVICE_PTR:
16298 case OMP_CLAUSE_IS_DEVICE_PTR:
16299 ovar = OMP_CLAUSE_DECL (c);
16300 var = lookup_decl_in_outer_ctx (ovar, ctx);
16301 x = build_sender_ref (ovar, ctx);
9d5fd7c6 16302 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_PTR)
43895be5 16303 tkind = GOMP_MAP_USE_DEVICE_PTR;
16304 else
16305 tkind = GOMP_MAP_FIRSTPRIVATE_INT;
16306 type = TREE_TYPE (ovar);
16307 if (TREE_CODE (type) == ARRAY_TYPE)
16308 var = build_fold_addr_expr (var);
16309 else
16310 {
16311 if (is_reference (ovar))
16312 {
16313 type = TREE_TYPE (type);
16314 if (TREE_CODE (type) != ARRAY_TYPE)
16315 var = build_simple_mem_ref (var);
16316 var = fold_convert (TREE_TYPE (x), var);
16317 }
16318 }
16319 gimplify_assign (x, var, &ilist);
16320 s = size_int (0);
16321 purpose = size_int (map_idx++);
16322 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
16323 gcc_checking_assert (tkind
16324 < (HOST_WIDE_INT_C (1U) << 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;
bc7bff74 16330 }
16331
16332 gcc_assert (map_idx == map_cnt);
16333
16334 DECL_INITIAL (TREE_VEC_ELT (t, 1))
16335 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)), vsize);
16336 DECL_INITIAL (TREE_VEC_ELT (t, 2))
16337 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 2)), vkind);
43895be5 16338 for (int i = 1; i <= 2; i++)
16339 if (!TREE_STATIC (TREE_VEC_ELT (t, i)))
16340 {
16341 gimple_seq initlist = NULL;
16342 force_gimple_operand (build1 (DECL_EXPR, void_type_node,
16343 TREE_VEC_ELT (t, i)),
16344 &initlist, true, NULL_TREE);
16345 gimple_seq_add_seq (&ilist, initlist);
16346
16347 tree clobber = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, i)),
16348 NULL);
16349 TREE_THIS_VOLATILE (clobber) = 1;
16350 gimple_seq_add_stmt (&olist,
16351 gimple_build_assign (TREE_VEC_ELT (t, i),
16352 clobber));
16353 }
bc7bff74 16354
16355 tree clobber = build_constructor (ctx->record_type, NULL);
16356 TREE_THIS_VOLATILE (clobber) = 1;
16357 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
16358 clobber));
16359 }
16360
16361 /* Once all the expansions are done, sequence all the different
16362 fragments inside gimple_omp_body. */
16363
16364 new_body = NULL;
16365
ca4c3545 16366 if (offloaded
16367 && ctx->record_type)
bc7bff74 16368 {
16369 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
16370 /* fixup_child_record_type might have changed receiver_decl's type. */
16371 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
16372 gimple_seq_add_stmt (&new_body,
16373 gimple_build_assign (ctx->receiver_decl, t));
16374 }
b656be3a 16375 gimple_seq_add_seq (&new_body, fplist);
bc7bff74 16376
43895be5 16377 if (offloaded || data_region)
bc7bff74 16378 {
43895be5 16379 tree prev = NULL_TREE;
16380 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
16381 switch (OMP_CLAUSE_CODE (c))
16382 {
16383 tree var, x;
16384 default:
16385 break;
16386 case OMP_CLAUSE_FIRSTPRIVATE:
b656be3a 16387 if (is_gimple_omp_oacc (ctx->stmt))
16388 break;
43895be5 16389 var = OMP_CLAUSE_DECL (c);
16390 if (is_reference (var)
16391 || is_gimple_reg_type (TREE_TYPE (var)))
16392 {
16393 tree new_var = lookup_decl (var, ctx);
16394 tree type;
16395 type = TREE_TYPE (var);
16396 if (is_reference (var))
16397 type = TREE_TYPE (type);
16398 bool use_firstprivate_int;
16399 use_firstprivate_int = false;
16400 if ((INTEGRAL_TYPE_P (type)
16401 && TYPE_PRECISION (type) <= POINTER_SIZE)
16402 || TREE_CODE (type) == POINTER_TYPE)
16403 use_firstprivate_int = true;
16404 if (has_depend)
16405 {
16406 tree v = lookup_decl_in_outer_ctx (var, ctx);
16407 if (is_reference (v))
16408 use_firstprivate_int = false;
16409 else if (is_gimple_reg (v))
16410 {
16411 if (DECL_HAS_VALUE_EXPR_P (v))
16412 {
16413 v = get_base_address (v);
16414 if (DECL_P (v) && TREE_ADDRESSABLE (v))
16415 use_firstprivate_int = false;
16416 else
16417 switch (TREE_CODE (v))
16418 {
16419 case INDIRECT_REF:
16420 case MEM_REF:
16421 use_firstprivate_int = false;
16422 break;
16423 default:
16424 break;
16425 }
16426 }
16427 }
16428 else
16429 use_firstprivate_int = false;
16430 }
16431 if (use_firstprivate_int)
16432 {
16433 x = build_receiver_ref (var, false, ctx);
16434 if (TREE_CODE (type) != POINTER_TYPE)
16435 x = fold_convert (pointer_sized_int_node, x);
16436 x = fold_convert (type, x);
16437 gimplify_expr (&x, &new_body, NULL, is_gimple_val,
16438 fb_rvalue);
16439 if (is_reference (var))
16440 {
16441 tree v = create_tmp_var_raw (type, get_name (var));
16442 gimple_add_tmp_var (v);
16443 TREE_ADDRESSABLE (v) = 1;
16444 gimple_seq_add_stmt (&new_body,
16445 gimple_build_assign (v, x));
16446 x = build_fold_addr_expr (v);
16447 }
16448 gimple_seq_add_stmt (&new_body,
16449 gimple_build_assign (new_var, x));
16450 }
16451 else
16452 {
16453 x = build_receiver_ref (var, !is_reference (var), ctx);
16454 gimplify_expr (&x, &new_body, NULL, is_gimple_val,
16455 fb_rvalue);
16456 gimple_seq_add_stmt (&new_body,
16457 gimple_build_assign (new_var, x));
16458 }
16459 }
16460 else if (is_variable_sized (var))
16461 {
16462 tree pvar = DECL_VALUE_EXPR (var);
16463 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
16464 pvar = TREE_OPERAND (pvar, 0);
16465 gcc_assert (DECL_P (pvar));
16466 tree new_var = lookup_decl (pvar, ctx);
16467 x = build_receiver_ref (var, false, ctx);
16468 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16469 gimple_seq_add_stmt (&new_body,
16470 gimple_build_assign (new_var, x));
16471 }
16472 break;
16473 case OMP_CLAUSE_PRIVATE:
b656be3a 16474 if (is_gimple_omp_oacc (ctx->stmt))
16475 break;
43895be5 16476 var = OMP_CLAUSE_DECL (c);
16477 if (is_reference (var))
16478 {
16479 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
16480 tree new_var = lookup_decl (var, ctx);
16481 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
16482 if (TREE_CONSTANT (x))
16483 {
16484 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
16485 get_name (var));
16486 gimple_add_tmp_var (x);
16487 TREE_ADDRESSABLE (x) = 1;
16488 x = build_fold_addr_expr_loc (clause_loc, x);
16489 }
16490 else
00e3f095 16491 break;
43895be5 16492
16493 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
16494 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16495 gimple_seq_add_stmt (&new_body,
16496 gimple_build_assign (new_var, x));
16497 }
16498 break;
16499 case OMP_CLAUSE_USE_DEVICE_PTR:
16500 case OMP_CLAUSE_IS_DEVICE_PTR:
16501 var = OMP_CLAUSE_DECL (c);
9d5fd7c6 16502 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_PTR)
43895be5 16503 x = build_sender_ref (var, ctx);
16504 else
16505 x = build_receiver_ref (var, false, ctx);
16506 if (is_variable_sized (var))
16507 {
16508 tree pvar = DECL_VALUE_EXPR (var);
16509 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
16510 pvar = TREE_OPERAND (pvar, 0);
16511 gcc_assert (DECL_P (pvar));
16512 tree new_var = lookup_decl (pvar, ctx);
16513 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16514 gimple_seq_add_stmt (&new_body,
16515 gimple_build_assign (new_var, x));
16516 }
16517 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
16518 {
16519 tree new_var = lookup_decl (var, ctx);
16520 new_var = DECL_VALUE_EXPR (new_var);
16521 gcc_assert (TREE_CODE (new_var) == MEM_REF);
16522 new_var = TREE_OPERAND (new_var, 0);
16523 gcc_assert (DECL_P (new_var));
16524 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16525 gimple_seq_add_stmt (&new_body,
16526 gimple_build_assign (new_var, x));
16527 }
16528 else
16529 {
16530 tree type = TREE_TYPE (var);
16531 tree new_var = lookup_decl (var, ctx);
16532 if (is_reference (var))
16533 {
16534 type = TREE_TYPE (type);
16535 if (TREE_CODE (type) != ARRAY_TYPE)
16536 {
16537 tree v = create_tmp_var_raw (type, get_name (var));
16538 gimple_add_tmp_var (v);
16539 TREE_ADDRESSABLE (v) = 1;
16540 x = fold_convert (type, x);
16541 gimplify_expr (&x, &new_body, NULL, is_gimple_val,
16542 fb_rvalue);
16543 gimple_seq_add_stmt (&new_body,
16544 gimple_build_assign (v, x));
16545 x = build_fold_addr_expr (v);
16546 }
16547 }
b86e24ea 16548 new_var = DECL_VALUE_EXPR (new_var);
43895be5 16549 x = fold_convert (TREE_TYPE (new_var), x);
16550 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16551 gimple_seq_add_stmt (&new_body,
16552 gimple_build_assign (new_var, x));
16553 }
16554 break;
16555 }
9561765e 16556 /* Handle GOMP_MAP_FIRSTPRIVATE_{POINTER,REFERENCE} in second pass,
43895be5 16557 so that firstprivate vars holding OMP_CLAUSE_SIZE if needed
00e3f095 16558 are already handled. Similarly OMP_CLAUSE_PRIVATE for VLAs
16559 or references to VLAs. */
b656be3a 16560 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
43895be5 16561 switch (OMP_CLAUSE_CODE (c))
16562 {
16563 tree var;
16564 default:
16565 break;
16566 case OMP_CLAUSE_MAP:
9561765e 16567 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
16568 || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_REFERENCE)
43895be5 16569 {
16570 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
16571 HOST_WIDE_INT offset = 0;
16572 gcc_assert (prev);
16573 var = OMP_CLAUSE_DECL (c);
16574 if (DECL_P (var)
16575 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
16576 && is_global_var (maybe_lookup_decl_in_outer_ctx (var,
16577 ctx))
16578 && varpool_node::get_create (var)->offloadable)
16579 break;
16580 if (TREE_CODE (var) == INDIRECT_REF
16581 && TREE_CODE (TREE_OPERAND (var, 0)) == COMPONENT_REF)
16582 var = TREE_OPERAND (var, 0);
16583 if (TREE_CODE (var) == COMPONENT_REF)
16584 {
16585 var = get_addr_base_and_unit_offset (var, &offset);
16586 gcc_assert (var != NULL_TREE && DECL_P (var));
16587 }
16588 else if (DECL_SIZE (var)
16589 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
16590 {
16591 tree var2 = DECL_VALUE_EXPR (var);
16592 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
16593 var2 = TREE_OPERAND (var2, 0);
16594 gcc_assert (DECL_P (var2));
16595 var = var2;
16596 }
16597 tree new_var = lookup_decl (var, ctx), x;
16598 tree type = TREE_TYPE (new_var);
16599 bool is_ref;
16600 if (TREE_CODE (OMP_CLAUSE_DECL (c)) == INDIRECT_REF
16601 && (TREE_CODE (TREE_OPERAND (OMP_CLAUSE_DECL (c), 0))
16602 == COMPONENT_REF))
16603 {
16604 type = TREE_TYPE (TREE_OPERAND (OMP_CLAUSE_DECL (c), 0));
16605 is_ref = true;
16606 new_var = build2 (MEM_REF, type,
16607 build_fold_addr_expr (new_var),
16608 build_int_cst (build_pointer_type (type),
16609 offset));
16610 }
16611 else if (TREE_CODE (OMP_CLAUSE_DECL (c)) == COMPONENT_REF)
16612 {
16613 type = TREE_TYPE (OMP_CLAUSE_DECL (c));
16614 is_ref = TREE_CODE (type) == REFERENCE_TYPE;
16615 new_var = build2 (MEM_REF, type,
16616 build_fold_addr_expr (new_var),
16617 build_int_cst (build_pointer_type (type),
16618 offset));
16619 }
16620 else
16621 is_ref = is_reference (var);
9561765e 16622 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_REFERENCE)
16623 is_ref = false;
43895be5 16624 bool ref_to_array = false;
16625 if (is_ref)
16626 {
16627 type = TREE_TYPE (type);
16628 if (TREE_CODE (type) == ARRAY_TYPE)
16629 {
16630 type = build_pointer_type (type);
16631 ref_to_array = true;
16632 }
16633 }
16634 else if (TREE_CODE (type) == ARRAY_TYPE)
16635 {
16636 tree decl2 = DECL_VALUE_EXPR (new_var);
16637 gcc_assert (TREE_CODE (decl2) == MEM_REF);
16638 decl2 = TREE_OPERAND (decl2, 0);
16639 gcc_assert (DECL_P (decl2));
16640 new_var = decl2;
16641 type = TREE_TYPE (new_var);
16642 }
16643 x = build_receiver_ref (OMP_CLAUSE_DECL (prev), false, ctx);
16644 x = fold_convert_loc (clause_loc, type, x);
16645 if (!integer_zerop (OMP_CLAUSE_SIZE (c)))
16646 {
16647 tree bias = OMP_CLAUSE_SIZE (c);
16648 if (DECL_P (bias))
16649 bias = lookup_decl (bias, ctx);
16650 bias = fold_convert_loc (clause_loc, sizetype, bias);
16651 bias = fold_build1_loc (clause_loc, NEGATE_EXPR, sizetype,
16652 bias);
16653 x = fold_build2_loc (clause_loc, POINTER_PLUS_EXPR,
16654 TREE_TYPE (x), x, bias);
16655 }
16656 if (ref_to_array)
16657 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
16658 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16659 if (is_ref && !ref_to_array)
16660 {
16661 tree t = create_tmp_var_raw (type, get_name (var));
16662 gimple_add_tmp_var (t);
16663 TREE_ADDRESSABLE (t) = 1;
16664 gimple_seq_add_stmt (&new_body,
16665 gimple_build_assign (t, x));
16666 x = build_fold_addr_expr_loc (clause_loc, t);
16667 }
16668 gimple_seq_add_stmt (&new_body,
16669 gimple_build_assign (new_var, x));
16670 prev = NULL_TREE;
16671 }
16672 else if (OMP_CLAUSE_CHAIN (c)
16673 && OMP_CLAUSE_CODE (OMP_CLAUSE_CHAIN (c))
16674 == OMP_CLAUSE_MAP
9561765e 16675 && (OMP_CLAUSE_MAP_KIND (OMP_CLAUSE_CHAIN (c))
16676 == GOMP_MAP_FIRSTPRIVATE_POINTER
16677 || (OMP_CLAUSE_MAP_KIND (OMP_CLAUSE_CHAIN (c))
16678 == GOMP_MAP_FIRSTPRIVATE_REFERENCE)))
43895be5 16679 prev = c;
16680 break;
16681 case OMP_CLAUSE_PRIVATE:
16682 var = OMP_CLAUSE_DECL (c);
16683 if (is_variable_sized (var))
16684 {
16685 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
16686 tree new_var = lookup_decl (var, ctx);
16687 tree pvar = DECL_VALUE_EXPR (var);
16688 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
16689 pvar = TREE_OPERAND (pvar, 0);
16690 gcc_assert (DECL_P (pvar));
16691 tree new_pvar = lookup_decl (pvar, ctx);
16692 tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
16693 tree al = size_int (DECL_ALIGN (var));
16694 tree x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
16695 x = build_call_expr_loc (clause_loc, atmp, 2, x, al);
16696 x = fold_convert_loc (clause_loc, TREE_TYPE (new_pvar), x);
16697 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16698 gimple_seq_add_stmt (&new_body,
16699 gimple_build_assign (new_pvar, x));
16700 }
00e3f095 16701 else if (is_reference (var) && !is_gimple_omp_oacc (ctx->stmt))
16702 {
16703 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
16704 tree new_var = lookup_decl (var, ctx);
16705 tree x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
16706 if (TREE_CONSTANT (x))
16707 break;
16708 else
16709 {
16710 tree atmp
16711 = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
16712 tree rtype = TREE_TYPE (TREE_TYPE (new_var));
16713 tree al = size_int (TYPE_ALIGN (rtype));
16714 x = build_call_expr_loc (clause_loc, atmp, 2, x, al);
16715 }
16716
16717 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
16718 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16719 gimple_seq_add_stmt (&new_body,
16720 gimple_build_assign (new_var, x));
16721 }
43895be5 16722 break;
16723 }
2eab8648 16724
641a0fa1 16725 gimple_seq fork_seq = NULL;
16726 gimple_seq join_seq = NULL;
16727
16728 if (is_oacc_parallel (ctx))
16729 {
16730 /* If there are reductions on the offloaded region itself, treat
16731 them as a dummy GANG loop. */
16732 tree level = build_int_cst (integer_type_node, GOMP_DIM_GANG);
16733
16734 lower_oacc_reductions (gimple_location (ctx->stmt), clauses, level,
16735 false, NULL, NULL, &fork_seq, &join_seq, ctx);
16736 }
16737
16738 gimple_seq_add_seq (&new_body, fork_seq);
bc7bff74 16739 gimple_seq_add_seq (&new_body, tgt_body);
641a0fa1 16740 gimple_seq_add_seq (&new_body, join_seq);
2eab8648 16741
43895be5 16742 if (offloaded)
16743 new_body = maybe_catch_exception (new_body);
2eab8648 16744
bc7bff74 16745 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
16746 gimple_omp_set_body (stmt, new_body);
16747 }
16748
16749 bind = gimple_build_bind (NULL, NULL,
16750 tgt_bind ? gimple_bind_block (tgt_bind)
16751 : NULL_TREE);
43895be5 16752 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
e3a19533 16753 gimple_bind_add_seq (bind, ilist);
16754 gimple_bind_add_stmt (bind, stmt);
16755 gimple_bind_add_seq (bind, olist);
773c5ba7 16756
75a70cf9 16757 pop_gimplify_context (NULL);
43895be5 16758
16759 if (dep_bind)
16760 {
16761 gimple_bind_add_seq (dep_bind, dep_ilist);
16762 gimple_bind_add_stmt (dep_bind, bind);
16763 gimple_bind_add_seq (dep_bind, dep_olist);
16764 pop_gimplify_context (dep_bind);
16765 }
773c5ba7 16766}
16767
bc7bff74 16768/* Expand code for an OpenMP teams directive. */
16769
16770static void
16771lower_omp_teams (gimple_stmt_iterator *gsi_p, omp_context *ctx)
16772{
1a91d914 16773 gomp_teams *teams_stmt = as_a <gomp_teams *> (gsi_stmt (*gsi_p));
8a4a28a8 16774 push_gimplify_context ();
bc7bff74 16775
16776 tree block = make_node (BLOCK);
1a91d914 16777 gbind *bind = gimple_build_bind (NULL, NULL, block);
bc7bff74 16778 gsi_replace (gsi_p, bind, true);
16779 gimple_seq bind_body = NULL;
16780 gimple_seq dlist = NULL;
16781 gimple_seq olist = NULL;
16782
16783 tree num_teams = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
16784 OMP_CLAUSE_NUM_TEAMS);
16785 if (num_teams == NULL_TREE)
16786 num_teams = build_int_cst (unsigned_type_node, 0);
16787 else
16788 {
16789 num_teams = OMP_CLAUSE_NUM_TEAMS_EXPR (num_teams);
16790 num_teams = fold_convert (unsigned_type_node, num_teams);
16791 gimplify_expr (&num_teams, &bind_body, NULL, is_gimple_val, fb_rvalue);
16792 }
16793 tree thread_limit = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
16794 OMP_CLAUSE_THREAD_LIMIT);
16795 if (thread_limit == NULL_TREE)
16796 thread_limit = build_int_cst (unsigned_type_node, 0);
16797 else
16798 {
16799 thread_limit = OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit);
16800 thread_limit = fold_convert (unsigned_type_node, thread_limit);
16801 gimplify_expr (&thread_limit, &bind_body, NULL, is_gimple_val,
16802 fb_rvalue);
16803 }
16804
16805 lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt),
16806 &bind_body, &dlist, ctx, NULL);
16807 lower_omp (gimple_omp_body_ptr (teams_stmt), ctx);
16808 lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt), &olist, ctx);
56686608 16809 if (!gimple_omp_teams_grid_phony (teams_stmt))
16810 {
16811 gimple_seq_add_stmt (&bind_body, teams_stmt);
16812 location_t loc = gimple_location (teams_stmt);
16813 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TEAMS);
16814 gimple *call = gimple_build_call (decl, 2, num_teams, thread_limit);
16815 gimple_set_location (call, loc);
16816 gimple_seq_add_stmt (&bind_body, call);
16817 }
bc7bff74 16818
16819 gimple_seq_add_seq (&bind_body, gimple_omp_body (teams_stmt));
16820 gimple_omp_set_body (teams_stmt, NULL);
16821 gimple_seq_add_seq (&bind_body, olist);
16822 gimple_seq_add_seq (&bind_body, dlist);
56686608 16823 if (!gimple_omp_teams_grid_phony (teams_stmt))
16824 gimple_seq_add_stmt (&bind_body, gimple_build_omp_return (true));
bc7bff74 16825 gimple_bind_set_body (bind, bind_body);
16826
16827 pop_gimplify_context (bind);
16828
16829 gimple_bind_append_vars (bind, ctx->block_vars);
16830 BLOCK_VARS (block) = ctx->block_vars;
16831 if (BLOCK_VARS (block))
16832 TREE_USED (block) = 1;
16833}
16834
56686608 16835/* Expand code within an artificial GIMPLE_OMP_GRID_BODY OMP construct. */
16836
16837static void
16838lower_omp_grid_body (gimple_stmt_iterator *gsi_p, omp_context *ctx)
16839{
16840 gimple *stmt = gsi_stmt (*gsi_p);
16841 lower_omp (gimple_omp_body_ptr (stmt), ctx);
16842 gimple_seq_add_stmt (gimple_omp_body_ptr (stmt),
16843 gimple_build_omp_return (false));
16844}
16845
bc7bff74 16846
a4890dc9 16847/* Callback for lower_omp_1. Return non-NULL if *tp needs to be
75a70cf9 16848 regimplified. If DATA is non-NULL, lower_omp_1 is outside
ca4c3545 16849 of OMP context, but with task_shared_vars set. */
46515c92 16850
16851static tree
75a70cf9 16852lower_omp_regimplify_p (tree *tp, int *walk_subtrees,
16853 void *data)
46515c92 16854{
a4890dc9 16855 tree t = *tp;
46515c92 16856
a4890dc9 16857 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
75a70cf9 16858 if (TREE_CODE (t) == VAR_DECL && data == NULL && DECL_HAS_VALUE_EXPR_P (t))
9f49e155 16859 return t;
16860
16861 if (task_shared_vars
16862 && DECL_P (t)
16863 && bitmap_bit_p (task_shared_vars, DECL_UID (t)))
a4890dc9 16864 return t;
46515c92 16865
a4890dc9 16866 /* If a global variable has been privatized, TREE_CONSTANT on
16867 ADDR_EXPR might be wrong. */
75a70cf9 16868 if (data == NULL && TREE_CODE (t) == ADDR_EXPR)
a4890dc9 16869 recompute_tree_invariant_for_addr_expr (t);
46515c92 16870
43895be5 16871 *walk_subtrees = !IS_TYPE_OR_DECL_P (t);
16872 return NULL_TREE;
16873}
16874
16875/* Data to be communicated between lower_omp_regimplify_operands and
16876 lower_omp_regimplify_operands_p. */
16877
16878struct lower_omp_regimplify_operands_data
16879{
16880 omp_context *ctx;
16881 vec<tree> *decls;
16882};
16883
16884/* Helper function for lower_omp_regimplify_operands. Find
16885 omp_member_access_dummy_var vars and adjust temporarily their
16886 DECL_VALUE_EXPRs if needed. */
16887
16888static tree
16889lower_omp_regimplify_operands_p (tree *tp, int *walk_subtrees,
16890 void *data)
16891{
16892 tree t = omp_member_access_dummy_var (*tp);
16893 if (t)
16894 {
16895 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
16896 lower_omp_regimplify_operands_data *ldata
16897 = (lower_omp_regimplify_operands_data *) wi->info;
16898 tree o = maybe_lookup_decl (t, ldata->ctx);
16899 if (o != t)
16900 {
16901 ldata->decls->safe_push (DECL_VALUE_EXPR (*tp));
16902 ldata->decls->safe_push (*tp);
16903 tree v = unshare_and_remap (DECL_VALUE_EXPR (*tp), t, o);
16904 SET_DECL_VALUE_EXPR (*tp, v);
16905 }
16906 }
16907 *walk_subtrees = !IS_TYPE_OR_DECL_P (*tp);
a4890dc9 16908 return NULL_TREE;
46515c92 16909}
773c5ba7 16910
43895be5 16911/* Wrapper around gimple_regimplify_operands that adjusts DECL_VALUE_EXPRs
16912 of omp_member_access_dummy_var vars during regimplification. */
16913
16914static void
16915lower_omp_regimplify_operands (omp_context *ctx, gimple *stmt,
16916 gimple_stmt_iterator *gsi_p)
16917{
16918 auto_vec<tree, 10> decls;
16919 if (ctx)
16920 {
16921 struct walk_stmt_info wi;
16922 memset (&wi, '\0', sizeof (wi));
16923 struct lower_omp_regimplify_operands_data data;
16924 data.ctx = ctx;
16925 data.decls = &decls;
16926 wi.info = &data;
16927 walk_gimple_op (stmt, lower_omp_regimplify_operands_p, &wi);
16928 }
16929 gimple_regimplify_operands (stmt, gsi_p);
16930 while (!decls.is_empty ())
16931 {
16932 tree t = decls.pop ();
16933 tree v = decls.pop ();
16934 SET_DECL_VALUE_EXPR (t, v);
16935 }
16936}
16937
a4890dc9 16938static void
75a70cf9 16939lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
1e8e9920 16940{
42acab1c 16941 gimple *stmt = gsi_stmt (*gsi_p);
75a70cf9 16942 struct walk_stmt_info wi;
1a91d914 16943 gcall *call_stmt;
1e8e9920 16944
75a70cf9 16945 if (gimple_has_location (stmt))
16946 input_location = gimple_location (stmt);
a4890dc9 16947
75a70cf9 16948 if (task_shared_vars)
16949 memset (&wi, '\0', sizeof (wi));
a4890dc9 16950
773c5ba7 16951 /* If we have issued syntax errors, avoid doing any heavy lifting.
ca4c3545 16952 Just replace the OMP directives with a NOP to avoid
773c5ba7 16953 confusing RTL expansion. */
852f689e 16954 if (seen_error () && is_gimple_omp (stmt))
773c5ba7 16955 {
75a70cf9 16956 gsi_replace (gsi_p, gimple_build_nop (), true);
a4890dc9 16957 return;
773c5ba7 16958 }
16959
75a70cf9 16960 switch (gimple_code (stmt))
1e8e9920 16961 {
75a70cf9 16962 case GIMPLE_COND:
1a91d914 16963 {
16964 gcond *cond_stmt = as_a <gcond *> (stmt);
16965 if ((ctx || task_shared_vars)
16966 && (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
16967 lower_omp_regimplify_p,
16968 ctx ? NULL : &wi, NULL)
16969 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
16970 lower_omp_regimplify_p,
16971 ctx ? NULL : &wi, NULL)))
43895be5 16972 lower_omp_regimplify_operands (ctx, cond_stmt, gsi_p);
1a91d914 16973 }
a4890dc9 16974 break;
75a70cf9 16975 case GIMPLE_CATCH:
1a91d914 16976 lower_omp (gimple_catch_handler_ptr (as_a <gcatch *> (stmt)), ctx);
a4890dc9 16977 break;
75a70cf9 16978 case GIMPLE_EH_FILTER:
e3a19533 16979 lower_omp (gimple_eh_filter_failure_ptr (stmt), ctx);
a4890dc9 16980 break;
75a70cf9 16981 case GIMPLE_TRY:
e3a19533 16982 lower_omp (gimple_try_eval_ptr (stmt), ctx);
16983 lower_omp (gimple_try_cleanup_ptr (stmt), ctx);
a4890dc9 16984 break;
35215227 16985 case GIMPLE_TRANSACTION:
1a91d914 16986 lower_omp (gimple_transaction_body_ptr (
16987 as_a <gtransaction *> (stmt)),
16988 ctx);
35215227 16989 break;
75a70cf9 16990 case GIMPLE_BIND:
1a91d914 16991 lower_omp (gimple_bind_body_ptr (as_a <gbind *> (stmt)), ctx);
a4890dc9 16992 break;
75a70cf9 16993 case GIMPLE_OMP_PARALLEL:
16994 case GIMPLE_OMP_TASK:
16995 ctx = maybe_lookup_ctx (stmt);
bc7bff74 16996 gcc_assert (ctx);
16997 if (ctx->cancellable)
16998 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
75a70cf9 16999 lower_omp_taskreg (gsi_p, ctx);
a4890dc9 17000 break;
75a70cf9 17001 case GIMPLE_OMP_FOR:
17002 ctx = maybe_lookup_ctx (stmt);
1e8e9920 17003 gcc_assert (ctx);
bc7bff74 17004 if (ctx->cancellable)
17005 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
75a70cf9 17006 lower_omp_for (gsi_p, ctx);
1e8e9920 17007 break;
75a70cf9 17008 case GIMPLE_OMP_SECTIONS:
17009 ctx = maybe_lookup_ctx (stmt);
1e8e9920 17010 gcc_assert (ctx);
bc7bff74 17011 if (ctx->cancellable)
17012 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
75a70cf9 17013 lower_omp_sections (gsi_p, ctx);
1e8e9920 17014 break;
75a70cf9 17015 case GIMPLE_OMP_SINGLE:
17016 ctx = maybe_lookup_ctx (stmt);
1e8e9920 17017 gcc_assert (ctx);
75a70cf9 17018 lower_omp_single (gsi_p, ctx);
1e8e9920 17019 break;
75a70cf9 17020 case GIMPLE_OMP_MASTER:
17021 ctx = maybe_lookup_ctx (stmt);
1e8e9920 17022 gcc_assert (ctx);
75a70cf9 17023 lower_omp_master (gsi_p, ctx);
1e8e9920 17024 break;
bc7bff74 17025 case GIMPLE_OMP_TASKGROUP:
17026 ctx = maybe_lookup_ctx (stmt);
17027 gcc_assert (ctx);
17028 lower_omp_taskgroup (gsi_p, ctx);
17029 break;
75a70cf9 17030 case GIMPLE_OMP_ORDERED:
17031 ctx = maybe_lookup_ctx (stmt);
1e8e9920 17032 gcc_assert (ctx);
75a70cf9 17033 lower_omp_ordered (gsi_p, ctx);
1e8e9920 17034 break;
75a70cf9 17035 case GIMPLE_OMP_CRITICAL:
17036 ctx = maybe_lookup_ctx (stmt);
1e8e9920 17037 gcc_assert (ctx);
75a70cf9 17038 lower_omp_critical (gsi_p, ctx);
17039 break;
17040 case GIMPLE_OMP_ATOMIC_LOAD:
17041 if ((ctx || task_shared_vars)
1a91d914 17042 && walk_tree (gimple_omp_atomic_load_rhs_ptr (
17043 as_a <gomp_atomic_load *> (stmt)),
75a70cf9 17044 lower_omp_regimplify_p, ctx ? NULL : &wi, NULL))
43895be5 17045 lower_omp_regimplify_operands (ctx, stmt, gsi_p);
1e8e9920 17046 break;
bc7bff74 17047 case GIMPLE_OMP_TARGET:
17048 ctx = maybe_lookup_ctx (stmt);
17049 gcc_assert (ctx);
17050 lower_omp_target (gsi_p, ctx);
17051 break;
17052 case GIMPLE_OMP_TEAMS:
17053 ctx = maybe_lookup_ctx (stmt);
17054 gcc_assert (ctx);
17055 lower_omp_teams (gsi_p, ctx);
17056 break;
56686608 17057 case GIMPLE_OMP_GRID_BODY:
17058 ctx = maybe_lookup_ctx (stmt);
17059 gcc_assert (ctx);
17060 lower_omp_grid_body (gsi_p, ctx);
17061 break;
bc7bff74 17062 case GIMPLE_CALL:
17063 tree fndecl;
1a91d914 17064 call_stmt = as_a <gcall *> (stmt);
17065 fndecl = gimple_call_fndecl (call_stmt);
bc7bff74 17066 if (fndecl
17067 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
17068 switch (DECL_FUNCTION_CODE (fndecl))
17069 {
17070 case BUILT_IN_GOMP_BARRIER:
17071 if (ctx == NULL)
17072 break;
17073 /* FALLTHRU */
17074 case BUILT_IN_GOMP_CANCEL:
17075 case BUILT_IN_GOMP_CANCELLATION_POINT:
17076 omp_context *cctx;
17077 cctx = ctx;
17078 if (gimple_code (cctx->stmt) == GIMPLE_OMP_SECTION)
17079 cctx = cctx->outer;
1a91d914 17080 gcc_assert (gimple_call_lhs (call_stmt) == NULL_TREE);
bc7bff74 17081 if (!cctx->cancellable)
17082 {
17083 if (DECL_FUNCTION_CODE (fndecl)
17084 == BUILT_IN_GOMP_CANCELLATION_POINT)
17085 {
17086 stmt = gimple_build_nop ();
17087 gsi_replace (gsi_p, stmt, false);
17088 }
17089 break;
17090 }
bc7bff74 17091 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
17092 {
17093 fndecl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL);
1a91d914 17094 gimple_call_set_fndecl (call_stmt, fndecl);
17095 gimple_call_set_fntype (call_stmt, TREE_TYPE (fndecl));
bc7bff74 17096 }
15b28553 17097 tree lhs;
f9e245b2 17098 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (fndecl)));
1a91d914 17099 gimple_call_set_lhs (call_stmt, lhs);
bc7bff74 17100 tree fallthru_label;
17101 fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
42acab1c 17102 gimple *g;
bc7bff74 17103 g = gimple_build_label (fallthru_label);
17104 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
15b28553 17105 g = gimple_build_cond (NE_EXPR, lhs,
17106 fold_convert (TREE_TYPE (lhs),
17107 boolean_false_node),
bc7bff74 17108 cctx->cancel_label, fallthru_label);
17109 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
17110 break;
17111 default:
17112 break;
17113 }
17114 /* FALLTHRU */
a4890dc9 17115 default:
fd6481cf 17116 if ((ctx || task_shared_vars)
75a70cf9 17117 && walk_gimple_op (stmt, lower_omp_regimplify_p,
17118 ctx ? NULL : &wi))
ef8cfd4d 17119 {
17120 /* Just remove clobbers, this should happen only if we have
17121 "privatized" local addressable variables in SIMD regions,
17122 the clobber isn't needed in that case and gimplifying address
17123 of the ARRAY_REF into a pointer and creating MEM_REF based
17124 clobber would create worse code than we get with the clobber
17125 dropped. */
17126 if (gimple_clobber_p (stmt))
17127 {
17128 gsi_replace (gsi_p, gimple_build_nop (), true);
17129 break;
17130 }
43895be5 17131 lower_omp_regimplify_operands (ctx, stmt, gsi_p);
ef8cfd4d 17132 }
1e8e9920 17133 break;
1e8e9920 17134 }
1e8e9920 17135}
17136
17137static void
e3a19533 17138lower_omp (gimple_seq *body, omp_context *ctx)
1e8e9920 17139{
1d22f541 17140 location_t saved_location = input_location;
e3a19533 17141 gimple_stmt_iterator gsi;
17142 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
75a70cf9 17143 lower_omp_1 (&gsi, ctx);
ca4c3545 17144 /* During gimplification, we haven't folded statments inside offloading
c3a81971 17145 or taskreg regions (gimplify.c:maybe_fold_stmt); do that now. */
17146 if (target_nesting_level || taskreg_nesting_level)
bc7bff74 17147 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
17148 fold_stmt (&gsi);
1d22f541 17149 input_location = saved_location;
1e8e9920 17150}
56686608 17151
17152/* Returen true if STMT is an assignment of a register-type into a local
17153 VAR_DECL. */
17154
17155static bool
17156grid_reg_assignment_to_local_var_p (gimple *stmt)
17157{
17158 gassign *assign = dyn_cast <gassign *> (stmt);
17159 if (!assign)
17160 return false;
17161 tree lhs = gimple_assign_lhs (assign);
17162 if (TREE_CODE (lhs) != VAR_DECL
17163 || !is_gimple_reg_type (TREE_TYPE (lhs))
17164 || is_global_var (lhs))
17165 return false;
17166 return true;
17167}
17168
17169/* Return true if all statements in SEQ are assignments to local register-type
17170 variables. */
17171
17172static bool
17173grid_seq_only_contains_local_assignments (gimple_seq seq)
17174{
17175 if (!seq)
17176 return true;
17177
17178 gimple_stmt_iterator gsi;
17179 for (gsi = gsi_start (seq); !gsi_end_p (gsi); gsi_next (&gsi))
17180 if (!grid_reg_assignment_to_local_var_p (gsi_stmt (gsi)))
17181 return false;
17182 return true;
17183}
17184
17185/* Scan statements in SEQ and call itself recursively on any bind. If during
17186 whole search only assignments to register-type local variables and one
17187 single OMP statement is encountered, return true, otherwise return false.
17188 RET is where we store any OMP statement encountered. TARGET_LOC and NAME
17189 are used for dumping a note about a failure. */
17190
17191static bool
17192grid_find_single_omp_among_assignments_1 (gimple_seq seq, location_t target_loc,
17193 const char *name, gimple **ret)
17194{
17195 gimple_stmt_iterator gsi;
17196 for (gsi = gsi_start (seq); !gsi_end_p (gsi); gsi_next (&gsi))
17197 {
17198 gimple *stmt = gsi_stmt (gsi);
17199
17200 if (grid_reg_assignment_to_local_var_p (stmt))
17201 continue;
17202 if (gbind *bind = dyn_cast <gbind *> (stmt))
17203 {
17204 if (!grid_find_single_omp_among_assignments_1 (gimple_bind_body (bind),
17205 target_loc, name, ret))
17206 return false;
17207 }
17208 else if (is_gimple_omp (stmt))
17209 {
17210 if (*ret)
17211 {
17212 if (dump_enabled_p ())
17213 dump_printf_loc (MSG_NOTE, target_loc,
17214 "Will not turn target construct into a simple "
17215 "GPGPU kernel because %s construct contains "
17216 "multiple OpenMP constructs\n", name);
17217 return false;
17218 }
17219 *ret = stmt;
17220 }
17221 else
17222 {
17223 if (dump_enabled_p ())
17224 dump_printf_loc (MSG_NOTE, target_loc,
17225 "Will not turn target construct into a simple "
17226 "GPGPU kernel because %s construct contains "
17227 "a complex statement\n", name);
17228 return false;
17229 }
17230 }
17231 return true;
17232}
17233
17234/* Scan statements in SEQ and make sure that it and any binds in it contain
17235 only assignments to local register-type variables and one OMP construct. If
17236 so, return that construct, otherwise return NULL. If dumping is enabled and
17237 function fails, use TARGET_LOC and NAME to dump a note with the reason for
17238 failure. */
17239
17240static gimple *
17241grid_find_single_omp_among_assignments (gimple_seq seq, location_t target_loc,
17242 const char *name)
17243{
17244 if (!seq)
17245 {
17246 if (dump_enabled_p ())
17247 dump_printf_loc (MSG_NOTE, target_loc,
17248 "Will not turn target construct into a simple "
17249 "GPGPU kernel because %s construct has empty "
17250 "body\n",
17251 name);
17252 return NULL;
17253 }
17254
17255 gimple *ret = NULL;
17256 if (grid_find_single_omp_among_assignments_1 (seq, target_loc, name, &ret))
17257 {
17258 if (!ret && dump_enabled_p ())
17259 dump_printf_loc (MSG_NOTE, target_loc,
17260 "Will not turn target construct into a simple "
17261 "GPGPU kernel because %s construct does not contain"
17262 "any other OpenMP construct\n", name);
17263 return ret;
17264 }
17265 else
17266 return NULL;
17267}
17268
17269/* Walker function looking for statements there is no point gridifying (and for
17270 noreturn function calls which we cannot do). Return non-NULL if such a
17271 function is found. */
17272
17273static tree
17274grid_find_ungridifiable_statement (gimple_stmt_iterator *gsi,
17275 bool *handled_ops_p,
ece566e7 17276 struct walk_stmt_info *wi)
56686608 17277{
17278 *handled_ops_p = false;
17279 gimple *stmt = gsi_stmt (*gsi);
17280 switch (gimple_code (stmt))
17281 {
17282 case GIMPLE_CALL:
17283 if (gimple_call_noreturn_p (as_a <gcall *> (stmt)))
17284 {
17285 *handled_ops_p = true;
ece566e7 17286 wi->info = stmt;
56686608 17287 return error_mark_node;
17288 }
17289 break;
17290
17291 /* We may reduce the following list if we find a way to implement the
17292 clauses, but now there is no point trying further. */
17293 case GIMPLE_OMP_CRITICAL:
17294 case GIMPLE_OMP_TASKGROUP:
17295 case GIMPLE_OMP_TASK:
17296 case GIMPLE_OMP_SECTION:
17297 case GIMPLE_OMP_SECTIONS:
17298 case GIMPLE_OMP_SECTIONS_SWITCH:
17299 case GIMPLE_OMP_TARGET:
17300 case GIMPLE_OMP_ORDERED:
17301 *handled_ops_p = true;
ece566e7 17302 wi->info = stmt;
56686608 17303 return error_mark_node;
17304
ece566e7 17305 case GIMPLE_OMP_FOR:
17306 if ((gimple_omp_for_kind (stmt) & GF_OMP_FOR_SIMD)
17307 && gimple_omp_for_combined_into_p (stmt))
17308 {
17309 *handled_ops_p = true;
17310 wi->info = stmt;
17311 return error_mark_node;
17312 }
17313 break;
17314
56686608 17315 default:
17316 break;
17317 }
17318 return NULL;
17319}
17320
17321
17322/* If TARGET follows a pattern that can be turned into a gridified GPGPU
17323 kernel, return true, otherwise return false. In the case of success, also
17324 fill in GROUP_SIZE_P with the requested group size or NULL if there is
17325 none. */
17326
17327static bool
17328grid_target_follows_gridifiable_pattern (gomp_target *target, tree *group_size_p)
17329{
17330 if (gimple_omp_target_kind (target) != GF_OMP_TARGET_KIND_REGION)
17331 return false;
17332
17333 location_t tloc = gimple_location (target);
17334 gimple *stmt
17335 = grid_find_single_omp_among_assignments (gimple_omp_body (target),
17336 tloc, "target");
17337 if (!stmt)
17338 return false;
17339 gomp_teams *teams = dyn_cast <gomp_teams *> (stmt);
17340 tree group_size = NULL;
17341 if (!teams)
17342 {
17343 dump_printf_loc (MSG_NOTE, tloc,
17344 "Will not turn target construct into a simple "
17345 "GPGPU kernel because it does not have a sole teams "
17346 "construct in it.\n");
17347 return false;
17348 }
17349
17350 tree clauses = gimple_omp_teams_clauses (teams);
17351 while (clauses)
17352 {
17353 switch (OMP_CLAUSE_CODE (clauses))
17354 {
17355 case OMP_CLAUSE_NUM_TEAMS:
17356 if (dump_enabled_p ())
17357 dump_printf_loc (MSG_NOTE, tloc,
17358 "Will not turn target construct into a "
17359 "gridified GPGPU kernel because we cannot "
17360 "handle num_teams clause of teams "
17361 "construct\n ");
17362 return false;
17363
17364 case OMP_CLAUSE_REDUCTION:
17365 if (dump_enabled_p ())
17366 dump_printf_loc (MSG_NOTE, tloc,
17367 "Will not turn target construct into a "
17368 "gridified GPGPU kernel because a reduction "
17369 "clause is present\n ");
17370 return false;
17371
17372 case OMP_CLAUSE_LASTPRIVATE:
17373 if (dump_enabled_p ())
17374 dump_printf_loc (MSG_NOTE, tloc,
17375 "Will not turn target construct into a "
17376 "gridified GPGPU kernel because a lastprivate "
17377 "clause is present\n ");
17378 return false;
17379
17380 case OMP_CLAUSE_THREAD_LIMIT:
17381 group_size = OMP_CLAUSE_OPERAND (clauses, 0);
17382 break;
17383
17384 default:
17385 break;
17386 }
17387 clauses = OMP_CLAUSE_CHAIN (clauses);
17388 }
17389
17390 stmt = grid_find_single_omp_among_assignments (gimple_omp_body (teams), tloc,
17391 "teams");
17392 if (!stmt)
17393 return false;
17394 gomp_for *dist = dyn_cast <gomp_for *> (stmt);
17395 if (!dist)
17396 {
17397 dump_printf_loc (MSG_NOTE, tloc,
17398 "Will not turn target construct into a simple "
17399 "GPGPU kernel because the teams construct does not have "
17400 "a sole distribute construct in it.\n");
17401 return false;
17402 }
17403
17404 gcc_assert (gimple_omp_for_kind (dist) == GF_OMP_FOR_KIND_DISTRIBUTE);
17405 if (!gimple_omp_for_combined_p (dist))
17406 {
17407 if (dump_enabled_p ())
17408 dump_printf_loc (MSG_NOTE, tloc,
17409 "Will not turn target construct into a gridified GPGPU "
17410 "kernel because we cannot handle a standalone "
17411 "distribute construct\n ");
17412 return false;
17413 }
17414 if (dist->collapse > 1)
17415 {
17416 if (dump_enabled_p ())
17417 dump_printf_loc (MSG_NOTE, tloc,
17418 "Will not turn target construct into a gridified GPGPU "
17419 "kernel because the distribute construct contains "
17420 "collapse clause\n");
17421 return false;
17422 }
17423 struct omp_for_data fd;
17424 extract_omp_for_data (dist, &fd, NULL);
17425 if (fd.chunk_size)
17426 {
17427 if (group_size && !operand_equal_p (group_size, fd.chunk_size, 0))
17428 {
17429 if (dump_enabled_p ())
17430 dump_printf_loc (MSG_NOTE, tloc,
17431 "Will not turn target construct into a "
17432 "gridified GPGPU kernel because the teams "
17433 "thread limit is different from distribute "
17434 "schedule chunk\n");
17435 return false;
17436 }
17437 group_size = fd.chunk_size;
17438 }
17439 stmt = grid_find_single_omp_among_assignments (gimple_omp_body (dist), tloc,
17440 "distribute");
17441 gomp_parallel *par;
17442 if (!stmt || !(par = dyn_cast <gomp_parallel *> (stmt)))
17443 return false;
17444
17445 clauses = gimple_omp_parallel_clauses (par);
17446 while (clauses)
17447 {
17448 switch (OMP_CLAUSE_CODE (clauses))
17449 {
17450 case OMP_CLAUSE_NUM_THREADS:
17451 if (dump_enabled_p ())
17452 dump_printf_loc (MSG_NOTE, tloc,
17453 "Will not turn target construct into a gridified"
17454 "GPGPU kernel because there is a num_threads "
17455 "clause of the parallel construct\n");
17456 return false;
17457
17458 case OMP_CLAUSE_REDUCTION:
17459 if (dump_enabled_p ())
17460 dump_printf_loc (MSG_NOTE, tloc,
17461 "Will not turn target construct into a "
17462 "gridified GPGPU kernel because a reduction "
17463 "clause is present\n ");
17464 return false;
17465
17466 case OMP_CLAUSE_LASTPRIVATE:
17467 if (dump_enabled_p ())
17468 dump_printf_loc (MSG_NOTE, tloc,
17469 "Will not turn target construct into a "
17470 "gridified GPGPU kernel because a lastprivate "
17471 "clause is present\n ");
17472 return false;
17473
17474 default:
17475 break;
17476 }
17477 clauses = OMP_CLAUSE_CHAIN (clauses);
17478 }
17479
17480 stmt = grid_find_single_omp_among_assignments (gimple_omp_body (par), tloc,
17481 "parallel");
17482 gomp_for *gfor;
17483 if (!stmt || !(gfor = dyn_cast <gomp_for *> (stmt)))
17484 return false;
17485
17486 if (gimple_omp_for_kind (gfor) != GF_OMP_FOR_KIND_FOR)
17487 {
17488 if (dump_enabled_p ())
17489 dump_printf_loc (MSG_NOTE, tloc,
17490 "Will not turn target construct into a gridified GPGPU "
17491 "kernel because the inner loop is not a simple for "
17492 "loop\n");
17493 return false;
17494 }
17495 if (gfor->collapse > 1)
17496 {
17497 if (dump_enabled_p ())
17498 dump_printf_loc (MSG_NOTE, tloc,
17499 "Will not turn target construct into a gridified GPGPU "
17500 "kernel because the inner loop contains collapse "
17501 "clause\n");
17502 return false;
17503 }
17504
17505 if (!grid_seq_only_contains_local_assignments (gimple_omp_for_pre_body (gfor)))
17506 {
17507 if (dump_enabled_p ())
17508 dump_printf_loc (MSG_NOTE, tloc,
17509 "Will not turn target construct into a gridified GPGPU "
17510 "kernel because the inner loop pre_body contains"
17511 "a complex instruction\n");
17512 return false;
17513 }
17514
17515 clauses = gimple_omp_for_clauses (gfor);
17516 while (clauses)
17517 {
17518 switch (OMP_CLAUSE_CODE (clauses))
17519 {
17520 case OMP_CLAUSE_SCHEDULE:
17521 if (OMP_CLAUSE_SCHEDULE_KIND (clauses) != OMP_CLAUSE_SCHEDULE_AUTO)
17522 {
17523 if (dump_enabled_p ())
17524 dump_printf_loc (MSG_NOTE, tloc,
17525 "Will not turn target construct into a "
17526 "gridified GPGPU kernel because the inner "
17527 "loop has a non-automatic scheduling clause\n");
17528 return false;
17529 }
17530 break;
17531
17532 case OMP_CLAUSE_REDUCTION:
17533 if (dump_enabled_p ())
17534 dump_printf_loc (MSG_NOTE, tloc,
17535 "Will not turn target construct into a "
17536 "gridified GPGPU kernel because a reduction "
17537 "clause is present\n ");
17538 return false;
17539
17540 case OMP_CLAUSE_LASTPRIVATE:
17541 if (dump_enabled_p ())
17542 dump_printf_loc (MSG_NOTE, tloc,
17543 "Will not turn target construct into a "
17544 "gridified GPGPU kernel because a lastprivate "
17545 "clause is present\n ");
17546 return false;
17547
17548 default:
17549 break;
17550 }
17551 clauses = OMP_CLAUSE_CHAIN (clauses);
17552 }
17553
17554 struct walk_stmt_info wi;
17555 memset (&wi, 0, sizeof (wi));
ece566e7 17556 if (walk_gimple_seq (gimple_omp_body (gfor),
17557 grid_find_ungridifiable_statement,
17558 NULL, &wi))
56686608 17559 {
ece566e7 17560 gimple *bad = (gimple *) wi.info;
56686608 17561 if (dump_enabled_p ())
17562 {
17563 if (is_gimple_call (bad))
17564 dump_printf_loc (MSG_NOTE, tloc,
17565 "Will not turn target construct into a gridified "
17566 " GPGPU kernel because the inner loop contains "
17567 "call to a noreturn function\n");
ece566e7 17568 if (gimple_code (bad) == GIMPLE_OMP_FOR)
17569 dump_printf_loc (MSG_NOTE, tloc,
17570 "Will not turn target construct into a gridified "
17571 " GPGPU kernel because the inner loop contains "
17572 "a simd construct\n");
56686608 17573 else
17574 dump_printf_loc (MSG_NOTE, tloc,
17575 "Will not turn target construct into a gridified "
17576 "GPGPU kernel because the inner loop contains "
17577 "statement %s which cannot be transformed\n",
17578 gimple_code_name[(int) gimple_code (bad)]);
17579 }
17580 return false;
17581 }
17582
17583 *group_size_p = group_size;
17584 return true;
17585}
17586
17587/* Operand walker, used to remap pre-body declarations according to a hash map
17588 provided in DATA. */
17589
17590static tree
17591grid_remap_prebody_decls (tree *tp, int *walk_subtrees, void *data)
17592{
17593 tree t = *tp;
17594
17595 if (DECL_P (t) || TYPE_P (t))
17596 *walk_subtrees = 0;
17597 else
17598 *walk_subtrees = 1;
17599
17600 if (TREE_CODE (t) == VAR_DECL)
17601 {
17602 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
17603 hash_map<tree, tree> *declmap = (hash_map<tree, tree> *) wi->info;
17604 tree *repl = declmap->get (t);
17605 if (repl)
17606 *tp = *repl;
17607 }
17608 return NULL_TREE;
17609}
17610
17611/* Copy leading register-type assignments to local variables in SRC to just
17612 before DST, Creating temporaries, adjusting mapping of operands in WI and
17613 remapping operands as necessary. Add any new temporaries to TGT_BIND.
17614 Return the first statement that does not conform to
17615 grid_reg_assignment_to_local_var_p or NULL. */
17616
17617static gimple *
17618grid_copy_leading_local_assignments (gimple_seq src, gimple_stmt_iterator *dst,
17619 gbind *tgt_bind, struct walk_stmt_info *wi)
17620{
17621 hash_map<tree, tree> *declmap = (hash_map<tree, tree> *) wi->info;
17622 gimple_stmt_iterator gsi;
17623 for (gsi = gsi_start (src); !gsi_end_p (gsi); gsi_next (&gsi))
17624 {
17625 gimple *stmt = gsi_stmt (gsi);
17626 if (gbind *bind = dyn_cast <gbind *> (stmt))
17627 {
17628 gimple *r = grid_copy_leading_local_assignments
17629 (gimple_bind_body (bind), dst, tgt_bind, wi);
17630 if (r)
17631 return r;
17632 else
17633 continue;
17634 }
17635 if (!grid_reg_assignment_to_local_var_p (stmt))
17636 return stmt;
17637 tree lhs = gimple_assign_lhs (as_a <gassign *> (stmt));
17638 tree repl = copy_var_decl (lhs, create_tmp_var_name (NULL),
17639 TREE_TYPE (lhs));
17640 DECL_CONTEXT (repl) = current_function_decl;
17641 gimple_bind_append_vars (tgt_bind, repl);
17642
17643 declmap->put (lhs, repl);
17644 gassign *copy = as_a <gassign *> (gimple_copy (stmt));
17645 walk_gimple_op (copy, grid_remap_prebody_decls, wi);
17646 gsi_insert_before (dst, copy, GSI_SAME_STMT);
17647 }
17648 return NULL;
17649}
17650
17651/* Given freshly copied top level kernel SEQ, identify the individual OMP
17652 components, mark them as part of kernel and return the inner loop, and copy
17653 assignment leading to them just before DST, remapping them using WI and
17654 adding new temporaries to TGT_BIND. */
17655
17656static gomp_for *
17657grid_process_kernel_body_copy (gimple_seq seq, gimple_stmt_iterator *dst,
17658 gbind *tgt_bind, struct walk_stmt_info *wi)
17659{
17660 gimple *stmt = grid_copy_leading_local_assignments (seq, dst, tgt_bind, wi);
17661 gomp_teams *teams = dyn_cast <gomp_teams *> (stmt);
17662 gcc_assert (teams);
17663 gimple_omp_teams_set_grid_phony (teams, true);
17664 stmt = grid_copy_leading_local_assignments (gimple_omp_body (teams), dst,
17665 tgt_bind, wi);
17666 gcc_checking_assert (stmt);
17667 gomp_for *dist = dyn_cast <gomp_for *> (stmt);
17668 gcc_assert (dist);
17669 gimple_seq prebody = gimple_omp_for_pre_body (dist);
17670 if (prebody)
17671 grid_copy_leading_local_assignments (prebody, dst, tgt_bind, wi);
17672 gimple_omp_for_set_grid_phony (dist, true);
17673 stmt = grid_copy_leading_local_assignments (gimple_omp_body (dist), dst,
17674 tgt_bind, wi);
17675 gcc_checking_assert (stmt);
17676
17677 gomp_parallel *parallel = as_a <gomp_parallel *> (stmt);
17678 gimple_omp_parallel_set_grid_phony (parallel, true);
17679 stmt = grid_copy_leading_local_assignments (gimple_omp_body (parallel), dst,
17680 tgt_bind, wi);
17681 gomp_for *inner_loop = as_a <gomp_for *> (stmt);
17682 gimple_omp_for_set_kind (inner_loop, GF_OMP_FOR_KIND_GRID_LOOP);
17683 prebody = gimple_omp_for_pre_body (inner_loop);
17684 if (prebody)
17685 grid_copy_leading_local_assignments (prebody, dst, tgt_bind, wi);
17686
17687 return inner_loop;
17688}
17689
17690/* If TARGET points to a GOMP_TARGET which follows a gridifiable pattern,
17691 create a GPU kernel for it. GSI must point to the same statement, TGT_BIND
17692 is the bind into which temporaries inserted before TARGET should be
17693 added. */
17694
17695static void
17696grid_attempt_target_gridification (gomp_target *target,
17697 gimple_stmt_iterator *gsi,
17698 gbind *tgt_bind)
17699{
17700 tree group_size;
17701 if (!target || !grid_target_follows_gridifiable_pattern (target, &group_size))
17702 return;
17703
17704 location_t loc = gimple_location (target);
17705 if (dump_enabled_p ())
17706 dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc,
17707 "Target construct will be turned into a gridified GPGPU "
17708 "kernel\n");
17709
17710 /* Copy target body to a GPUKERNEL construct: */
17711 gimple_seq kernel_seq = copy_gimple_seq_and_replace_locals
17712 (gimple_omp_body (target));
17713
17714 hash_map<tree, tree> *declmap = new hash_map<tree, tree>;
17715 struct walk_stmt_info wi;
17716 memset (&wi, 0, sizeof (struct walk_stmt_info));
17717 wi.info = declmap;
17718
17719 /* Copy assignments in between OMP statements before target, mark OMP
17720 statements within copy appropriatly. */
17721 gomp_for *inner_loop = grid_process_kernel_body_copy (kernel_seq, gsi,
17722 tgt_bind, &wi);
17723
17724 gbind *old_bind = as_a <gbind *> (gimple_seq_first (gimple_omp_body (target)));
17725 gbind *new_bind = as_a <gbind *> (gimple_seq_first (kernel_seq));
17726 tree new_block = gimple_bind_block (new_bind);
17727 tree enc_block = BLOCK_SUPERCONTEXT (gimple_bind_block (old_bind));
17728 BLOCK_CHAIN (new_block) = BLOCK_SUBBLOCKS (enc_block);
17729 BLOCK_SUBBLOCKS (enc_block) = new_block;
17730 BLOCK_SUPERCONTEXT (new_block) = enc_block;
17731 gimple *gpukernel = gimple_build_omp_grid_body (kernel_seq);
17732 gimple_seq_add_stmt
17733 (gimple_bind_body_ptr (as_a <gbind *> (gimple_omp_body (target))),
17734 gpukernel);
17735
17736 walk_tree (&group_size, grid_remap_prebody_decls, &wi, NULL);
17737 push_gimplify_context ();
17738 size_t collapse = gimple_omp_for_collapse (inner_loop);
17739 for (size_t i = 0; i < collapse; i++)
17740 {
17741 tree itype, type = TREE_TYPE (gimple_omp_for_index (inner_loop, i));
17742 if (POINTER_TYPE_P (type))
17743 itype = signed_type_for (type);
17744 else
17745 itype = type;
17746
17747 enum tree_code cond_code = gimple_omp_for_cond (inner_loop, i);
17748 tree n1 = unshare_expr (gimple_omp_for_initial (inner_loop, i));
17749 walk_tree (&n1, grid_remap_prebody_decls, &wi, NULL);
17750 tree n2 = unshare_expr (gimple_omp_for_final (inner_loop, i));
17751 walk_tree (&n2, grid_remap_prebody_decls, &wi, NULL);
17752 adjust_for_condition (loc, &cond_code, &n2);
17753 tree step;
17754 step = get_omp_for_step_from_incr (loc,
17755 gimple_omp_for_incr (inner_loop, i));
17756 gimple_seq tmpseq = NULL;
17757 n1 = fold_convert (itype, n1);
17758 n2 = fold_convert (itype, n2);
17759 tree t = build_int_cst (itype, (cond_code == LT_EXPR ? -1 : 1));
17760 t = fold_build2 (PLUS_EXPR, itype, step, t);
17761 t = fold_build2 (PLUS_EXPR, itype, t, n2);
17762 t = fold_build2 (MINUS_EXPR, itype, t, n1);
17763 if (TYPE_UNSIGNED (itype) && cond_code == GT_EXPR)
17764 t = fold_build2 (TRUNC_DIV_EXPR, itype,
17765 fold_build1 (NEGATE_EXPR, itype, t),
17766 fold_build1 (NEGATE_EXPR, itype, step));
17767 else
17768 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
17769 tree gs = fold_convert (uint32_type_node, t);
17770 gimplify_expr (&gs, &tmpseq, NULL, is_gimple_val, fb_rvalue);
17771 if (!gimple_seq_empty_p (tmpseq))
17772 gsi_insert_seq_before (gsi, tmpseq, GSI_SAME_STMT);
17773
17774 tree ws;
17775 if (i == 0 && group_size)
17776 {
17777 ws = fold_convert (uint32_type_node, group_size);
17778 tmpseq = NULL;
17779 gimplify_expr (&ws, &tmpseq, NULL, is_gimple_val, fb_rvalue);
17780 if (!gimple_seq_empty_p (tmpseq))
17781 gsi_insert_seq_before (gsi, tmpseq, GSI_SAME_STMT);
17782 }
17783 else
17784 ws = build_zero_cst (uint32_type_node);
17785
17786 tree c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__GRIDDIM_);
17787 OMP_CLAUSE__GRIDDIM__DIMENSION (c) = i;
17788 OMP_CLAUSE__GRIDDIM__SIZE (c) = gs;
17789 OMP_CLAUSE__GRIDDIM__GROUP (c) = ws;
17790 OMP_CLAUSE_CHAIN (c) = gimple_omp_target_clauses (target);
17791 gimple_omp_target_set_clauses (target, c);
17792 }
17793 pop_gimplify_context (tgt_bind);
17794 delete declmap;
17795 return;
17796}
17797
17798/* Walker function doing all the work for create_target_kernels. */
17799
17800static tree
17801grid_gridify_all_targets_stmt (gimple_stmt_iterator *gsi,
17802 bool *handled_ops_p,
17803 struct walk_stmt_info *incoming)
17804{
17805 *handled_ops_p = false;
17806
17807 gimple *stmt = gsi_stmt (*gsi);
17808 gomp_target *target = dyn_cast <gomp_target *> (stmt);
17809 if (target)
17810 {
17811 gbind *tgt_bind = (gbind *) incoming->info;
17812 gcc_checking_assert (tgt_bind);
17813 grid_attempt_target_gridification (target, gsi, tgt_bind);
17814 return NULL_TREE;
17815 }
17816 gbind *bind = dyn_cast <gbind *> (stmt);
17817 if (bind)
17818 {
17819 *handled_ops_p = true;
17820 struct walk_stmt_info wi;
17821 memset (&wi, 0, sizeof (wi));
17822 wi.info = bind;
17823 walk_gimple_seq_mod (gimple_bind_body_ptr (bind),
17824 grid_gridify_all_targets_stmt, NULL, &wi);
17825 }
17826 return NULL_TREE;
17827}
17828
17829/* Attempt to gridify all target constructs in BODY_P. All such targets will
17830 have their bodies duplicated, with the new copy being put into a
17831 gimple_omp_grid_body statement. All kernel-related construct within the
17832 grid_body will be marked with phony flags or kernel kinds. Moreover, some
17833 re-structuring is often needed, such as copying pre-bodies before the target
17834 construct so that kernel grid sizes can be computed. */
17835
17836static void
17837grid_gridify_all_targets (gimple_seq *body_p)
17838{
17839 struct walk_stmt_info wi;
17840 memset (&wi, 0, sizeof (wi));
17841 walk_gimple_seq_mod (body_p, grid_gridify_all_targets_stmt, NULL, &wi);
17842}
1e8e9920 17843\f
56686608 17844
1e8e9920 17845/* Main entry point. */
17846
2a1990e9 17847static unsigned int
1e8e9920 17848execute_lower_omp (void)
17849{
75a70cf9 17850 gimple_seq body;
37eaded9 17851 int i;
17852 omp_context *ctx;
75a70cf9 17853
41709826 17854 /* This pass always runs, to provide PROP_gimple_lomp.
ca4c3545 17855 But often, there is nothing to do. */
17856 if (flag_cilkplus == 0 && flag_openacc == 0 && flag_openmp == 0
17857 && flag_openmp_simd == 0)
41709826 17858 return 0;
17859
1e8e9920 17860 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
17861 delete_omp_context);
17862
75a70cf9 17863 body = gimple_body (current_function_decl);
56686608 17864
17865 if (hsa_gen_requested_p ())
17866 grid_gridify_all_targets (&body);
17867
ab129075 17868 scan_omp (&body, NULL);
fd6481cf 17869 gcc_assert (taskreg_nesting_level == 0);
37eaded9 17870 FOR_EACH_VEC_ELT (taskreg_contexts, i, ctx)
17871 finish_taskreg_scan (ctx);
17872 taskreg_contexts.release ();
1e8e9920 17873
17874 if (all_contexts->root)
fd6481cf 17875 {
17876 if (task_shared_vars)
8a4a28a8 17877 push_gimplify_context ();
e3a19533 17878 lower_omp (&body, NULL);
fd6481cf 17879 if (task_shared_vars)
17880 pop_gimplify_context (NULL);
17881 }
1e8e9920 17882
773c5ba7 17883 if (all_contexts)
17884 {
17885 splay_tree_delete (all_contexts);
17886 all_contexts = NULL;
17887 }
fd6481cf 17888 BITMAP_FREE (task_shared_vars);
2a1990e9 17889 return 0;
1e8e9920 17890}
17891
7620bc82 17892namespace {
17893
17894const pass_data pass_data_lower_omp =
cbe8bda8 17895{
17896 GIMPLE_PASS, /* type */
17897 "omplower", /* name */
17898 OPTGROUP_NONE, /* optinfo_flags */
cbe8bda8 17899 TV_NONE, /* tv_id */
17900 PROP_gimple_any, /* properties_required */
17901 PROP_gimple_lomp, /* properties_provided */
17902 0, /* properties_destroyed */
17903 0, /* todo_flags_start */
17904 0, /* todo_flags_finish */
1e8e9920 17905};
cbe8bda8 17906
7620bc82 17907class pass_lower_omp : public gimple_opt_pass
cbe8bda8 17908{
17909public:
9af5ce0c 17910 pass_lower_omp (gcc::context *ctxt)
17911 : gimple_opt_pass (pass_data_lower_omp, ctxt)
cbe8bda8 17912 {}
17913
17914 /* opt_pass methods: */
65b0537f 17915 virtual unsigned int execute (function *) { return execute_lower_omp (); }
cbe8bda8 17916
17917}; // class pass_lower_omp
17918
7620bc82 17919} // anon namespace
17920
cbe8bda8 17921gimple_opt_pass *
17922make_pass_lower_omp (gcc::context *ctxt)
17923{
17924 return new pass_lower_omp (ctxt);
17925}
1e8e9920 17926\f
ca4c3545 17927/* The following is a utility to diagnose structured block violations.
61e47ac8 17928 It is not part of the "omplower" pass, as that's invoked too late. It
17929 should be invoked by the respective front ends after gimplification. */
1e8e9920 17930
17931static splay_tree all_labels;
17932
17933/* Check for mismatched contexts and generate an error if needed. Return
17934 true if an error is detected. */
17935
17936static bool
75a70cf9 17937diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
42acab1c 17938 gimple *branch_ctx, gimple *label_ctx)
1e8e9920 17939{
ca4c3545 17940 gcc_checking_assert (!branch_ctx || is_gimple_omp (branch_ctx));
17941 gcc_checking_assert (!label_ctx || is_gimple_omp (label_ctx));
17942
75a70cf9 17943 if (label_ctx == branch_ctx)
1e8e9920 17944 return false;
17945
ca4c3545 17946 const char* kind = NULL;
17947
17948 if (flag_cilkplus)
17949 {
17950 if ((branch_ctx
17951 && gimple_code (branch_ctx) == GIMPLE_OMP_FOR
17952 && gimple_omp_for_kind (branch_ctx) == GF_OMP_FOR_KIND_CILKSIMD)
17953 || (label_ctx
17954 && gimple_code (label_ctx) == GIMPLE_OMP_FOR
17955 && gimple_omp_for_kind (label_ctx) == GF_OMP_FOR_KIND_CILKSIMD))
17956 kind = "Cilk Plus";
17957 }
17958 if (flag_openacc)
17959 {
17960 if ((branch_ctx && is_gimple_omp_oacc (branch_ctx))
17961 || (label_ctx && is_gimple_omp_oacc (label_ctx)))
17962 {
17963 gcc_checking_assert (kind == NULL);
17964 kind = "OpenACC";
17965 }
17966 }
17967 if (kind == NULL)
17968 {
17969 gcc_checking_assert (flag_openmp);
17970 kind = "OpenMP";
17971 }
48e1416a 17972
75a70cf9 17973 /*
17974 Previously we kept track of the label's entire context in diagnose_sb_[12]
17975 so we could traverse it and issue a correct "exit" or "enter" error
17976 message upon a structured block violation.
17977
17978 We built the context by building a list with tree_cons'ing, but there is
17979 no easy counterpart in gimple tuples. It seems like far too much work
17980 for issuing exit/enter error messages. If someone really misses the
17981 distinct error message... patches welcome.
17982 */
48e1416a 17983
75a70cf9 17984#if 0
1e8e9920 17985 /* Try to avoid confusing the user by producing and error message
f0b5f617 17986 with correct "exit" or "enter" verbiage. We prefer "exit"
1e8e9920 17987 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
17988 if (branch_ctx == NULL)
17989 exit_p = false;
17990 else
17991 {
17992 while (label_ctx)
17993 {
17994 if (TREE_VALUE (label_ctx) == branch_ctx)
17995 {
17996 exit_p = false;
17997 break;
17998 }
17999 label_ctx = TREE_CHAIN (label_ctx);
18000 }
18001 }
18002
18003 if (exit_p)
ca4c3545 18004 error ("invalid exit from %s structured block", kind);
1e8e9920 18005 else
ca4c3545 18006 error ("invalid entry to %s structured block", kind);
75a70cf9 18007#endif
1e8e9920 18008
75a70cf9 18009 /* If it's obvious we have an invalid entry, be specific about the error. */
18010 if (branch_ctx == NULL)
ca4c3545 18011 error ("invalid entry to %s structured block", kind);
75a70cf9 18012 else
f2697631 18013 {
18014 /* Otherwise, be vague and lazy, but efficient. */
ca4c3545 18015 error ("invalid branch to/from %s structured block", kind);
f2697631 18016 }
75a70cf9 18017
18018 gsi_replace (gsi_p, gimple_build_nop (), false);
1e8e9920 18019 return true;
18020}
18021
ca4c3545 18022/* Pass 1: Create a minimal tree of structured blocks, and record
75a70cf9 18023 where each label is found. */
1e8e9920 18024
18025static tree
75a70cf9 18026diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
18027 struct walk_stmt_info *wi)
1e8e9920 18028{
42acab1c 18029 gimple *context = (gimple *) wi->info;
18030 gimple *inner_context;
18031 gimple *stmt = gsi_stmt (*gsi_p);
1e8e9920 18032
75a70cf9 18033 *handled_ops_p = true;
18034
ca4c3545 18035 switch (gimple_code (stmt))
1e8e9920 18036 {
75a70cf9 18037 WALK_SUBSTMTS;
48e1416a 18038
75a70cf9 18039 case GIMPLE_OMP_PARALLEL:
18040 case GIMPLE_OMP_TASK:
18041 case GIMPLE_OMP_SECTIONS:
18042 case GIMPLE_OMP_SINGLE:
18043 case GIMPLE_OMP_SECTION:
18044 case GIMPLE_OMP_MASTER:
18045 case GIMPLE_OMP_ORDERED:
18046 case GIMPLE_OMP_CRITICAL:
bc7bff74 18047 case GIMPLE_OMP_TARGET:
18048 case GIMPLE_OMP_TEAMS:
18049 case GIMPLE_OMP_TASKGROUP:
75a70cf9 18050 /* The minimal context here is just the current OMP construct. */
18051 inner_context = stmt;
1e8e9920 18052 wi->info = inner_context;
75a70cf9 18053 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
1e8e9920 18054 wi->info = context;
18055 break;
18056
75a70cf9 18057 case GIMPLE_OMP_FOR:
18058 inner_context = stmt;
1e8e9920 18059 wi->info = inner_context;
75a70cf9 18060 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
18061 walk them. */
18062 walk_gimple_seq (gimple_omp_for_pre_body (stmt),
18063 diagnose_sb_1, NULL, wi);
18064 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
1e8e9920 18065 wi->info = context;
18066 break;
18067
75a70cf9 18068 case GIMPLE_LABEL:
1a91d914 18069 splay_tree_insert (all_labels,
18070 (splay_tree_key) gimple_label_label (
18071 as_a <glabel *> (stmt)),
1e8e9920 18072 (splay_tree_value) context);
18073 break;
18074
18075 default:
18076 break;
18077 }
18078
18079 return NULL_TREE;
18080}
18081
18082/* Pass 2: Check each branch and see if its context differs from that of
18083 the destination label's context. */
18084
18085static tree
75a70cf9 18086diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
18087 struct walk_stmt_info *wi)
1e8e9920 18088{
42acab1c 18089 gimple *context = (gimple *) wi->info;
1e8e9920 18090 splay_tree_node n;
42acab1c 18091 gimple *stmt = gsi_stmt (*gsi_p);
1e8e9920 18092
75a70cf9 18093 *handled_ops_p = true;
18094
18095 switch (gimple_code (stmt))
1e8e9920 18096 {
75a70cf9 18097 WALK_SUBSTMTS;
18098
18099 case GIMPLE_OMP_PARALLEL:
18100 case GIMPLE_OMP_TASK:
18101 case GIMPLE_OMP_SECTIONS:
18102 case GIMPLE_OMP_SINGLE:
18103 case GIMPLE_OMP_SECTION:
18104 case GIMPLE_OMP_MASTER:
18105 case GIMPLE_OMP_ORDERED:
18106 case GIMPLE_OMP_CRITICAL:
bc7bff74 18107 case GIMPLE_OMP_TARGET:
18108 case GIMPLE_OMP_TEAMS:
18109 case GIMPLE_OMP_TASKGROUP:
75a70cf9 18110 wi->info = stmt;
e3a19533 18111 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
1e8e9920 18112 wi->info = context;
18113 break;
18114
75a70cf9 18115 case GIMPLE_OMP_FOR:
18116 wi->info = stmt;
18117 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
18118 walk them. */
e3a19533 18119 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt),
18120 diagnose_sb_2, NULL, wi);
18121 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
1e8e9920 18122 wi->info = context;
18123 break;
18124
0e1818e7 18125 case GIMPLE_COND:
18126 {
1a91d914 18127 gcond *cond_stmt = as_a <gcond *> (stmt);
18128 tree lab = gimple_cond_true_label (cond_stmt);
0e1818e7 18129 if (lab)
18130 {
18131 n = splay_tree_lookup (all_labels,
18132 (splay_tree_key) lab);
18133 diagnose_sb_0 (gsi_p, context,
42acab1c 18134 n ? (gimple *) n->value : NULL);
0e1818e7 18135 }
1a91d914 18136 lab = gimple_cond_false_label (cond_stmt);
0e1818e7 18137 if (lab)
18138 {
18139 n = splay_tree_lookup (all_labels,
18140 (splay_tree_key) lab);
18141 diagnose_sb_0 (gsi_p, context,
42acab1c 18142 n ? (gimple *) n->value : NULL);
0e1818e7 18143 }
18144 }
18145 break;
18146
75a70cf9 18147 case GIMPLE_GOTO:
1e8e9920 18148 {
75a70cf9 18149 tree lab = gimple_goto_dest (stmt);
1e8e9920 18150 if (TREE_CODE (lab) != LABEL_DECL)
18151 break;
18152
18153 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
42acab1c 18154 diagnose_sb_0 (gsi_p, context, n ? (gimple *) n->value : NULL);
1e8e9920 18155 }
18156 break;
18157
75a70cf9 18158 case GIMPLE_SWITCH:
1e8e9920 18159 {
1a91d914 18160 gswitch *switch_stmt = as_a <gswitch *> (stmt);
75a70cf9 18161 unsigned int i;
1a91d914 18162 for (i = 0; i < gimple_switch_num_labels (switch_stmt); ++i)
1e8e9920 18163 {
1a91d914 18164 tree lab = CASE_LABEL (gimple_switch_label (switch_stmt, i));
1e8e9920 18165 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
42acab1c 18166 if (n && diagnose_sb_0 (gsi_p, context, (gimple *) n->value))
1e8e9920 18167 break;
18168 }
18169 }
18170 break;
18171
75a70cf9 18172 case GIMPLE_RETURN:
18173 diagnose_sb_0 (gsi_p, context, NULL);
1e8e9920 18174 break;
18175
18176 default:
18177 break;
18178 }
18179
18180 return NULL_TREE;
18181}
18182
ca4c3545 18183/* Called from tree-cfg.c::make_edges to create cfg edges for all relevant
18184 GIMPLE_* codes. */
7740abd8 18185bool
b2c0e0b7 18186make_gimple_omp_edges (basic_block bb, struct omp_region **region,
18187 int *region_idx)
7740abd8 18188{
42acab1c 18189 gimple *last = last_stmt (bb);
7740abd8 18190 enum gimple_code code = gimple_code (last);
18191 struct omp_region *cur_region = *region;
18192 bool fallthru = false;
18193
18194 switch (code)
18195 {
18196 case GIMPLE_OMP_PARALLEL:
18197 case GIMPLE_OMP_TASK:
18198 case GIMPLE_OMP_FOR:
18199 case GIMPLE_OMP_SINGLE:
18200 case GIMPLE_OMP_TEAMS:
18201 case GIMPLE_OMP_MASTER:
18202 case GIMPLE_OMP_TASKGROUP:
7740abd8 18203 case GIMPLE_OMP_CRITICAL:
18204 case GIMPLE_OMP_SECTION:
56686608 18205 case GIMPLE_OMP_GRID_BODY:
7740abd8 18206 cur_region = new_omp_region (bb, code, cur_region);
18207 fallthru = true;
18208 break;
18209
43895be5 18210 case GIMPLE_OMP_ORDERED:
18211 cur_region = new_omp_region (bb, code, cur_region);
18212 fallthru = true;
18213 if (find_omp_clause (gimple_omp_ordered_clauses
18214 (as_a <gomp_ordered *> (last)),
18215 OMP_CLAUSE_DEPEND))
18216 cur_region = cur_region->outer;
18217 break;
18218
7740abd8 18219 case GIMPLE_OMP_TARGET:
18220 cur_region = new_omp_region (bb, code, cur_region);
18221 fallthru = true;
ca4c3545 18222 switch (gimple_omp_target_kind (last))
18223 {
18224 case GF_OMP_TARGET_KIND_REGION:
18225 case GF_OMP_TARGET_KIND_DATA:
18226 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
18227 case GF_OMP_TARGET_KIND_OACC_KERNELS:
18228 case GF_OMP_TARGET_KIND_OACC_DATA:
571b3486 18229 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
ca4c3545 18230 break;
18231 case GF_OMP_TARGET_KIND_UPDATE:
43895be5 18232 case GF_OMP_TARGET_KIND_ENTER_DATA:
18233 case GF_OMP_TARGET_KIND_EXIT_DATA:
ca4c3545 18234 case GF_OMP_TARGET_KIND_OACC_UPDATE:
18235 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
2fc5e987 18236 case GF_OMP_TARGET_KIND_OACC_DECLARE:
ca4c3545 18237 cur_region = cur_region->outer;
18238 break;
18239 default:
18240 gcc_unreachable ();
18241 }
7740abd8 18242 break;
18243
18244 case GIMPLE_OMP_SECTIONS:
18245 cur_region = new_omp_region (bb, code, cur_region);
18246 fallthru = true;
18247 break;
18248
18249 case GIMPLE_OMP_SECTIONS_SWITCH:
18250 fallthru = false;
18251 break;
18252
18253 case GIMPLE_OMP_ATOMIC_LOAD:
18254 case GIMPLE_OMP_ATOMIC_STORE:
18255 fallthru = true;
18256 break;
18257
18258 case GIMPLE_OMP_RETURN:
18259 /* In the case of a GIMPLE_OMP_SECTION, the edge will go
18260 somewhere other than the next block. This will be
18261 created later. */
18262 cur_region->exit = bb;
b25f70fd 18263 if (cur_region->type == GIMPLE_OMP_TASK)
18264 /* Add an edge corresponding to not scheduling the task
18265 immediately. */
18266 make_edge (cur_region->entry, bb, EDGE_ABNORMAL);
7740abd8 18267 fallthru = cur_region->type != GIMPLE_OMP_SECTION;
18268 cur_region = cur_region->outer;
18269 break;
18270
18271 case GIMPLE_OMP_CONTINUE:
18272 cur_region->cont = bb;
18273 switch (cur_region->type)
18274 {
18275 case GIMPLE_OMP_FOR:
18276 /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
18277 succs edges as abnormal to prevent splitting
18278 them. */
18279 single_succ_edge (cur_region->entry)->flags |= EDGE_ABNORMAL;
18280 /* Make the loopback edge. */
18281 make_edge (bb, single_succ (cur_region->entry),
18282 EDGE_ABNORMAL);
18283
18284 /* Create an edge from GIMPLE_OMP_FOR to exit, which
18285 corresponds to the case that the body of the loop
18286 is not executed at all. */
18287 make_edge (cur_region->entry, bb->next_bb, EDGE_ABNORMAL);
18288 make_edge (bb, bb->next_bb, EDGE_FALLTHRU | EDGE_ABNORMAL);
18289 fallthru = false;
18290 break;
18291
18292 case GIMPLE_OMP_SECTIONS:
18293 /* Wire up the edges into and out of the nested sections. */
18294 {
18295 basic_block switch_bb = single_succ (cur_region->entry);
18296
18297 struct omp_region *i;
18298 for (i = cur_region->inner; i ; i = i->next)
18299 {
18300 gcc_assert (i->type == GIMPLE_OMP_SECTION);
18301 make_edge (switch_bb, i->entry, 0);
18302 make_edge (i->exit, bb, EDGE_FALLTHRU);
18303 }
18304
18305 /* Make the loopback edge to the block with
18306 GIMPLE_OMP_SECTIONS_SWITCH. */
18307 make_edge (bb, switch_bb, 0);
18308
18309 /* Make the edge from the switch to exit. */
18310 make_edge (switch_bb, bb->next_bb, 0);
18311 fallthru = false;
18312 }
18313 break;
18314
b25f70fd 18315 case GIMPLE_OMP_TASK:
18316 fallthru = true;
18317 break;
18318
7740abd8 18319 default:
18320 gcc_unreachable ();
18321 }
18322 break;
18323
18324 default:
18325 gcc_unreachable ();
18326 }
18327
18328 if (*region != cur_region)
b2c0e0b7 18329 {
18330 *region = cur_region;
18331 if (cur_region)
18332 *region_idx = cur_region->entry->index;
18333 else
18334 *region_idx = 0;
18335 }
7740abd8 18336
18337 return fallthru;
18338}
18339
bfec3452 18340static unsigned int
18341diagnose_omp_structured_block_errors (void)
1e8e9920 18342{
1e8e9920 18343 struct walk_stmt_info wi;
bfec3452 18344 gimple_seq body = gimple_body (current_function_decl);
1e8e9920 18345
18346 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
18347
18348 memset (&wi, 0, sizeof (wi));
75a70cf9 18349 walk_gimple_seq (body, diagnose_sb_1, NULL, &wi);
1e8e9920 18350
18351 memset (&wi, 0, sizeof (wi));
1e8e9920 18352 wi.want_locations = true;
e3a19533 18353 walk_gimple_seq_mod (&body, diagnose_sb_2, NULL, &wi);
18354
18355 gimple_set_body (current_function_decl, body);
1e8e9920 18356
18357 splay_tree_delete (all_labels);
18358 all_labels = NULL;
18359
bfec3452 18360 return 0;
1e8e9920 18361}
18362
7620bc82 18363namespace {
18364
18365const pass_data pass_data_diagnose_omp_blocks =
cbe8bda8 18366{
18367 GIMPLE_PASS, /* type */
18368 "*diagnose_omp_blocks", /* name */
18369 OPTGROUP_NONE, /* optinfo_flags */
cbe8bda8 18370 TV_NONE, /* tv_id */
18371 PROP_gimple_any, /* properties_required */
18372 0, /* properties_provided */
18373 0, /* properties_destroyed */
18374 0, /* todo_flags_start */
18375 0, /* todo_flags_finish */
bfec3452 18376};
18377
7620bc82 18378class pass_diagnose_omp_blocks : public gimple_opt_pass
cbe8bda8 18379{
18380public:
9af5ce0c 18381 pass_diagnose_omp_blocks (gcc::context *ctxt)
18382 : gimple_opt_pass (pass_data_diagnose_omp_blocks, ctxt)
cbe8bda8 18383 {}
18384
18385 /* opt_pass methods: */
ca4c3545 18386 virtual bool gate (function *)
18387 {
18388 return flag_cilkplus || flag_openacc || flag_openmp;
18389 }
65b0537f 18390 virtual unsigned int execute (function *)
18391 {
18392 return diagnose_omp_structured_block_errors ();
18393 }
cbe8bda8 18394
18395}; // class pass_diagnose_omp_blocks
18396
7620bc82 18397} // anon namespace
18398
cbe8bda8 18399gimple_opt_pass *
18400make_pass_diagnose_omp_blocks (gcc::context *ctxt)
18401{
18402 return new pass_diagnose_omp_blocks (ctxt);
18403}
d09768a4 18404\f
18405/* SIMD clone supporting code. */
18406
18407/* Allocate a fresh `simd_clone' and return it. NARGS is the number
18408 of arguments to reserve space for. */
18409
18410static struct cgraph_simd_clone *
18411simd_clone_struct_alloc (int nargs)
18412{
18413 struct cgraph_simd_clone *clone_info;
18414 size_t len = (sizeof (struct cgraph_simd_clone)
18415 + nargs * sizeof (struct cgraph_simd_clone_arg));
18416 clone_info = (struct cgraph_simd_clone *)
ea7d8c7a 18417 ggc_internal_cleared_alloc (len);
d09768a4 18418 return clone_info;
18419}
18420
18421/* Make a copy of the `struct cgraph_simd_clone' in FROM to TO. */
18422
18423static inline void
18424simd_clone_struct_copy (struct cgraph_simd_clone *to,
18425 struct cgraph_simd_clone *from)
18426{
18427 memcpy (to, from, (sizeof (struct cgraph_simd_clone)
46c0fd4b 18428 + ((from->nargs - from->inbranch)
18429 * sizeof (struct cgraph_simd_clone_arg))));
d09768a4 18430}
18431
18432/* Return vector of parameter types of function FNDECL. This uses
18433 TYPE_ARG_TYPES if available, otherwise falls back to types of
18434 DECL_ARGUMENTS types. */
18435
18436vec<tree>
18437simd_clone_vector_of_formal_parm_types (tree fndecl)
18438{
18439 if (TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
18440 return ipa_get_vector_of_formal_parm_types (TREE_TYPE (fndecl));
18441 vec<tree> args = ipa_get_vector_of_formal_parms (fndecl);
18442 unsigned int i;
18443 tree arg;
18444 FOR_EACH_VEC_ELT (args, i, arg)
18445 args[i] = TREE_TYPE (args[i]);
18446 return args;
18447}
18448
18449/* Given a simd function in NODE, extract the simd specific
18450 information from the OMP clauses passed in CLAUSES, and return
18451 the struct cgraph_simd_clone * if it should be cloned. *INBRANCH_SPECIFIED
18452 is set to TRUE if the `inbranch' or `notinbranch' clause specified,
18453 otherwise set to FALSE. */
18454
18455static struct cgraph_simd_clone *
18456simd_clone_clauses_extract (struct cgraph_node *node, tree clauses,
18457 bool *inbranch_specified)
18458{
18459 vec<tree> args = simd_clone_vector_of_formal_parm_types (node->decl);
18460 tree t;
18461 int n;
18462 *inbranch_specified = false;
18463
18464 n = args.length ();
18465 if (n > 0 && args.last () == void_type_node)
18466 n--;
18467
18468 /* To distinguish from an OpenMP simd clone, Cilk Plus functions to
18469 be cloned have a distinctive artificial label in addition to "omp
18470 declare simd". */
18471 bool cilk_clone
a89e6c15 18472 = (flag_cilkplus
74acc703 18473 && lookup_attribute ("cilk simd function",
d09768a4 18474 DECL_ATTRIBUTES (node->decl)));
18475
18476 /* Allocate one more than needed just in case this is an in-branch
18477 clone which will require a mask argument. */
18478 struct cgraph_simd_clone *clone_info = simd_clone_struct_alloc (n + 1);
18479 clone_info->nargs = n;
18480 clone_info->cilk_elemental = cilk_clone;
18481
18482 if (!clauses)
18483 {
18484 args.release ();
18485 return clone_info;
18486 }
18487 clauses = TREE_VALUE (clauses);
18488 if (!clauses || TREE_CODE (clauses) != OMP_CLAUSE)
18489 return clone_info;
18490
18491 for (t = clauses; t; t = OMP_CLAUSE_CHAIN (t))
18492 {
18493 switch (OMP_CLAUSE_CODE (t))
18494 {
18495 case OMP_CLAUSE_INBRANCH:
18496 clone_info->inbranch = 1;
18497 *inbranch_specified = true;
18498 break;
18499 case OMP_CLAUSE_NOTINBRANCH:
18500 clone_info->inbranch = 0;
18501 *inbranch_specified = true;
18502 break;
18503 case OMP_CLAUSE_SIMDLEN:
18504 clone_info->simdlen
18505 = TREE_INT_CST_LOW (OMP_CLAUSE_SIMDLEN_EXPR (t));
18506 break;
18507 case OMP_CLAUSE_LINEAR:
18508 {
18509 tree decl = OMP_CLAUSE_DECL (t);
18510 tree step = OMP_CLAUSE_LINEAR_STEP (t);
18511 int argno = TREE_INT_CST_LOW (decl);
18512 if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (t))
18513 {
9561765e 18514 enum cgraph_simd_clone_arg_type arg_type;
18515 if (TREE_CODE (args[argno]) == REFERENCE_TYPE)
18516 switch (OMP_CLAUSE_LINEAR_KIND (t))
18517 {
18518 case OMP_CLAUSE_LINEAR_REF:
18519 arg_type
18520 = SIMD_CLONE_ARG_TYPE_LINEAR_REF_VARIABLE_STEP;
18521 break;
18522 case OMP_CLAUSE_LINEAR_UVAL:
18523 arg_type
18524 = SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_VARIABLE_STEP;
18525 break;
18526 case OMP_CLAUSE_LINEAR_VAL:
18527 case OMP_CLAUSE_LINEAR_DEFAULT:
18528 arg_type
18529 = SIMD_CLONE_ARG_TYPE_LINEAR_VAL_VARIABLE_STEP;
18530 break;
18531 default:
18532 gcc_unreachable ();
18533 }
18534 else
18535 arg_type = SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP;
18536 clone_info->args[argno].arg_type = arg_type;
d09768a4 18537 clone_info->args[argno].linear_step = tree_to_shwi (step);
18538 gcc_assert (clone_info->args[argno].linear_step >= 0
18539 && clone_info->args[argno].linear_step < n);
18540 }
18541 else
18542 {
18543 if (POINTER_TYPE_P (args[argno]))
18544 step = fold_convert (ssizetype, step);
18545 if (!tree_fits_shwi_p (step))
18546 {
18547 warning_at (OMP_CLAUSE_LOCATION (t), 0,
18548 "ignoring large linear step");
18549 args.release ();
18550 return NULL;
18551 }
18552 else if (integer_zerop (step))
18553 {
18554 warning_at (OMP_CLAUSE_LOCATION (t), 0,
18555 "ignoring zero linear step");
18556 args.release ();
18557 return NULL;
18558 }
18559 else
18560 {
43895be5 18561 enum cgraph_simd_clone_arg_type arg_type;
18562 if (TREE_CODE (args[argno]) == REFERENCE_TYPE)
18563 switch (OMP_CLAUSE_LINEAR_KIND (t))
18564 {
18565 case OMP_CLAUSE_LINEAR_REF:
18566 arg_type
18567 = SIMD_CLONE_ARG_TYPE_LINEAR_REF_CONSTANT_STEP;
18568 break;
18569 case OMP_CLAUSE_LINEAR_UVAL:
18570 arg_type
18571 = SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP;
18572 break;
18573 case OMP_CLAUSE_LINEAR_VAL:
18574 case OMP_CLAUSE_LINEAR_DEFAULT:
18575 arg_type
18576 = SIMD_CLONE_ARG_TYPE_LINEAR_VAL_CONSTANT_STEP;
18577 break;
18578 default:
18579 gcc_unreachable ();
18580 }
18581 else
18582 arg_type = SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP;
18583 clone_info->args[argno].arg_type = arg_type;
d09768a4 18584 clone_info->args[argno].linear_step = tree_to_shwi (step);
18585 }
18586 }
18587 break;
18588 }
18589 case OMP_CLAUSE_UNIFORM:
18590 {
18591 tree decl = OMP_CLAUSE_DECL (t);
18592 int argno = tree_to_uhwi (decl);
18593 clone_info->args[argno].arg_type
18594 = SIMD_CLONE_ARG_TYPE_UNIFORM;
18595 break;
18596 }
18597 case OMP_CLAUSE_ALIGNED:
18598 {
18599 tree decl = OMP_CLAUSE_DECL (t);
18600 int argno = tree_to_uhwi (decl);
18601 clone_info->args[argno].alignment
18602 = TREE_INT_CST_LOW (OMP_CLAUSE_ALIGNED_ALIGNMENT (t));
18603 break;
18604 }
18605 default:
18606 break;
18607 }
18608 }
18609 args.release ();
18610 return clone_info;
18611}
18612
18613/* Given a SIMD clone in NODE, calculate the characteristic data
18614 type and return the coresponding type. The characteristic data
18615 type is computed as described in the Intel Vector ABI. */
18616
18617static tree
18618simd_clone_compute_base_data_type (struct cgraph_node *node,
18619 struct cgraph_simd_clone *clone_info)
18620{
18621 tree type = integer_type_node;
18622 tree fndecl = node->decl;
18623
18624 /* a) For non-void function, the characteristic data type is the
18625 return type. */
18626 if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) != VOID_TYPE)
18627 type = TREE_TYPE (TREE_TYPE (fndecl));
18628
18629 /* b) If the function has any non-uniform, non-linear parameters,
18630 then the characteristic data type is the type of the first
18631 such parameter. */
18632 else
18633 {
18634 vec<tree> map = simd_clone_vector_of_formal_parm_types (fndecl);
18635 for (unsigned int i = 0; i < clone_info->nargs; ++i)
18636 if (clone_info->args[i].arg_type == SIMD_CLONE_ARG_TYPE_VECTOR)
18637 {
18638 type = map[i];
18639 break;
18640 }
18641 map.release ();
18642 }
18643
18644 /* c) If the characteristic data type determined by a) or b) above
18645 is struct, union, or class type which is pass-by-value (except
18646 for the type that maps to the built-in complex data type), the
18647 characteristic data type is int. */
18648 if (RECORD_OR_UNION_TYPE_P (type)
18649 && !aggregate_value_p (type, NULL)
18650 && TREE_CODE (type) != COMPLEX_TYPE)
18651 return integer_type_node;
18652
18653 /* d) If none of the above three classes is applicable, the
18654 characteristic data type is int. */
18655
18656 return type;
18657
18658 /* e) For Intel Xeon Phi native and offload compilation, if the
18659 resulting characteristic data type is 8-bit or 16-bit integer
18660 data type, the characteristic data type is int. */
18661 /* Well, we don't handle Xeon Phi yet. */
18662}
18663
18664static tree
18665simd_clone_mangle (struct cgraph_node *node,
18666 struct cgraph_simd_clone *clone_info)
18667{
18668 char vecsize_mangle = clone_info->vecsize_mangle;
18669 char mask = clone_info->inbranch ? 'M' : 'N';
18670 unsigned int simdlen = clone_info->simdlen;
18671 unsigned int n;
18672 pretty_printer pp;
18673
18674 gcc_assert (vecsize_mangle && simdlen);
18675
18676 pp_string (&pp, "_ZGV");
18677 pp_character (&pp, vecsize_mangle);
18678 pp_character (&pp, mask);
18679 pp_decimal_int (&pp, simdlen);
18680
18681 for (n = 0; n < clone_info->nargs; ++n)
18682 {
18683 struct cgraph_simd_clone_arg arg = clone_info->args[n];
18684
43895be5 18685 switch (arg.arg_type)
d09768a4 18686 {
43895be5 18687 case SIMD_CLONE_ARG_TYPE_UNIFORM:
18688 pp_character (&pp, 'u');
18689 break;
18690 case SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP:
d09768a4 18691 pp_character (&pp, 'l');
43895be5 18692 goto mangle_linear;
18693 case SIMD_CLONE_ARG_TYPE_LINEAR_REF_CONSTANT_STEP:
18694 pp_character (&pp, 'R');
18695 goto mangle_linear;
18696 case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_CONSTANT_STEP:
18697 pp_character (&pp, 'L');
18698 goto mangle_linear;
18699 case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP:
18700 pp_character (&pp, 'U');
18701 goto mangle_linear;
18702 mangle_linear:
18703 gcc_assert (arg.linear_step != 0);
d09768a4 18704 if (arg.linear_step > 1)
18705 pp_unsigned_wide_integer (&pp, arg.linear_step);
18706 else if (arg.linear_step < 0)
18707 {
18708 pp_character (&pp, 'n');
18709 pp_unsigned_wide_integer (&pp, (-(unsigned HOST_WIDE_INT)
18710 arg.linear_step));
18711 }
43895be5 18712 break;
18713 case SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP:
9561765e 18714 pp_string (&pp, "ls");
18715 pp_unsigned_wide_integer (&pp, arg.linear_step);
18716 break;
18717 case SIMD_CLONE_ARG_TYPE_LINEAR_REF_VARIABLE_STEP:
18718 pp_string (&pp, "Rs");
18719 pp_unsigned_wide_integer (&pp, arg.linear_step);
18720 break;
18721 case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_VARIABLE_STEP:
18722 pp_string (&pp, "Ls");
18723 pp_unsigned_wide_integer (&pp, arg.linear_step);
18724 break;
18725 case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_VARIABLE_STEP:
18726 pp_string (&pp, "Us");
d09768a4 18727 pp_unsigned_wide_integer (&pp, arg.linear_step);
43895be5 18728 break;
18729 default:
18730 pp_character (&pp, 'v');
d09768a4 18731 }
d09768a4 18732 if (arg.alignment)
18733 {
18734 pp_character (&pp, 'a');
18735 pp_decimal_int (&pp, arg.alignment);
18736 }
18737 }
18738
18739 pp_underscore (&pp);
4e4baaad 18740 const char *str = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl));
18741 if (*str == '*')
18742 ++str;
18743 pp_string (&pp, str);
18744 str = pp_formatted_text (&pp);
d09768a4 18745
18746 /* If there already is a SIMD clone with the same mangled name, don't
18747 add another one. This can happen e.g. for
18748 #pragma omp declare simd
18749 #pragma omp declare simd simdlen(8)
18750 int foo (int, int);
18751 if the simdlen is assumed to be 8 for the first one, etc. */
18752 for (struct cgraph_node *clone = node->simd_clones; clone;
18753 clone = clone->simdclone->next_clone)
18754 if (strcmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (clone->decl)),
18755 str) == 0)
18756 return NULL_TREE;
18757
18758 return get_identifier (str);
18759}
18760
18761/* Create a simd clone of OLD_NODE and return it. */
18762
18763static struct cgraph_node *
18764simd_clone_create (struct cgraph_node *old_node)
18765{
18766 struct cgraph_node *new_node;
18767 if (old_node->definition)
ea0695f9 18768 {
415d1b9a 18769 if (!old_node->has_gimple_body_p ())
ea0695f9 18770 return NULL;
415d1b9a 18771 old_node->get_body ();
18772 new_node = old_node->create_version_clone_with_body (vNULL, NULL, NULL,
18773 false, NULL, NULL,
18774 "simdclone");
ea0695f9 18775 }
d09768a4 18776 else
18777 {
18778 tree old_decl = old_node->decl;
18779 tree new_decl = copy_node (old_node->decl);
18780 DECL_NAME (new_decl) = clone_function_name (old_decl, "simdclone");
18781 SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl));
18782 SET_DECL_RTL (new_decl, NULL);
18783 DECL_STATIC_CONSTRUCTOR (new_decl) = 0;
18784 DECL_STATIC_DESTRUCTOR (new_decl) = 0;
415d1b9a 18785 new_node = old_node->create_version_clone (new_decl, vNULL, NULL);
64c7c74a 18786 if (old_node->in_other_partition)
18787 new_node->in_other_partition = 1;
d09768a4 18788 }
18789 if (new_node == NULL)
18790 return new_node;
18791
18792 TREE_PUBLIC (new_node->decl) = TREE_PUBLIC (old_node->decl);
18793
18794 /* The function cgraph_function_versioning () will force the new
18795 symbol local. Undo this, and inherit external visability from
18796 the old node. */
18797 new_node->local.local = old_node->local.local;
18798 new_node->externally_visible = old_node->externally_visible;
18799
18800 return new_node;
18801}
18802
18803/* Adjust the return type of the given function to its appropriate
18804 vector counterpart. Returns a simd array to be used throughout the
18805 function as a return value. */
18806
18807static tree
18808simd_clone_adjust_return_type (struct cgraph_node *node)
18809{
18810 tree fndecl = node->decl;
18811 tree orig_rettype = TREE_TYPE (TREE_TYPE (fndecl));
18812 unsigned int veclen;
18813 tree t;
18814
18815 /* Adjust the function return type. */
18816 if (orig_rettype == void_type_node)
18817 return NULL_TREE;
18818 TREE_TYPE (fndecl) = build_distinct_type_copy (TREE_TYPE (fndecl));
fdf7662c 18819 t = TREE_TYPE (TREE_TYPE (fndecl));
18820 if (INTEGRAL_TYPE_P (t) || POINTER_TYPE_P (t))
d09768a4 18821 veclen = node->simdclone->vecsize_int;
18822 else
18823 veclen = node->simdclone->vecsize_float;
fdf7662c 18824 veclen /= GET_MODE_BITSIZE (TYPE_MODE (t));
d09768a4 18825 if (veclen > node->simdclone->simdlen)
18826 veclen = node->simdclone->simdlen;
fdf7662c 18827 if (POINTER_TYPE_P (t))
18828 t = pointer_sized_int_node;
d09768a4 18829 if (veclen == node->simdclone->simdlen)
fdf7662c 18830 t = build_vector_type (t, node->simdclone->simdlen);
d09768a4 18831 else
18832 {
fdf7662c 18833 t = build_vector_type (t, veclen);
d09768a4 18834 t = build_array_type_nelts (t, node->simdclone->simdlen / veclen);
d09768a4 18835 }
fdf7662c 18836 TREE_TYPE (TREE_TYPE (fndecl)) = t;
d09768a4 18837 if (!node->definition)
18838 return NULL_TREE;
18839
18840 t = DECL_RESULT (fndecl);
18841 /* Adjust the DECL_RESULT. */
18842 gcc_assert (TREE_TYPE (t) != void_type_node);
18843 TREE_TYPE (t) = TREE_TYPE (TREE_TYPE (fndecl));
18844 relayout_decl (t);
18845
18846 tree atype = build_array_type_nelts (orig_rettype,
18847 node->simdclone->simdlen);
18848 if (veclen != node->simdclone->simdlen)
18849 return build1 (VIEW_CONVERT_EXPR, atype, t);
18850
18851 /* Set up a SIMD array to use as the return value. */
18852 tree retval = create_tmp_var_raw (atype, "retval");
18853 gimple_add_tmp_var (retval);
18854 return retval;
18855}
18856
18857/* Each vector argument has a corresponding array to be used locally
18858 as part of the eventual loop. Create such temporary array and
18859 return it.
18860
18861 PREFIX is the prefix to be used for the temporary.
18862
18863 TYPE is the inner element type.
18864
18865 SIMDLEN is the number of elements. */
18866
18867static tree
18868create_tmp_simd_array (const char *prefix, tree type, int simdlen)
18869{
18870 tree atype = build_array_type_nelts (type, simdlen);
18871 tree avar = create_tmp_var_raw (atype, prefix);
18872 gimple_add_tmp_var (avar);
18873 return avar;
18874}
18875
18876/* Modify the function argument types to their corresponding vector
18877 counterparts if appropriate. Also, create one array for each simd
18878 argument to be used locally when using the function arguments as
18879 part of the loop.
18880
18881 NODE is the function whose arguments are to be adjusted.
18882
18883 Returns an adjustment vector that will be filled describing how the
18884 argument types will be adjusted. */
18885
18886static ipa_parm_adjustment_vec
18887simd_clone_adjust_argument_types (struct cgraph_node *node)
18888{
18889 vec<tree> args;
18890 ipa_parm_adjustment_vec adjustments;
18891
18892 if (node->definition)
18893 args = ipa_get_vector_of_formal_parms (node->decl);
18894 else
18895 args = simd_clone_vector_of_formal_parm_types (node->decl);
18896 adjustments.create (args.length ());
18897 unsigned i, j, veclen;
18898 struct ipa_parm_adjustment adj;
18899 for (i = 0; i < node->simdclone->nargs; ++i)
18900 {
18901 memset (&adj, 0, sizeof (adj));
18902 tree parm = args[i];
18903 tree parm_type = node->definition ? TREE_TYPE (parm) : parm;
18904 adj.base_index = i;
18905 adj.base = parm;
18906
18907 node->simdclone->args[i].orig_arg = node->definition ? parm : NULL_TREE;
18908 node->simdclone->args[i].orig_type = parm_type;
18909
43895be5 18910 switch (node->simdclone->args[i].arg_type)
d09768a4 18911 {
43895be5 18912 default:
d09768a4 18913 /* No adjustment necessary for scalar arguments. */
18914 adj.op = IPA_PARM_OP_COPY;
43895be5 18915 break;
18916 case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP:
9561765e 18917 case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_VARIABLE_STEP:
43895be5 18918 if (node->definition)
18919 node->simdclone->args[i].simd_array
18920 = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm)),
18921 TREE_TYPE (parm_type),
18922 node->simdclone->simdlen);
18923 adj.op = IPA_PARM_OP_COPY;
18924 break;
18925 case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_CONSTANT_STEP:
9561765e 18926 case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_VARIABLE_STEP:
43895be5 18927 case SIMD_CLONE_ARG_TYPE_VECTOR:
d09768a4 18928 if (INTEGRAL_TYPE_P (parm_type) || POINTER_TYPE_P (parm_type))
18929 veclen = node->simdclone->vecsize_int;
18930 else
18931 veclen = node->simdclone->vecsize_float;
18932 veclen /= GET_MODE_BITSIZE (TYPE_MODE (parm_type));
18933 if (veclen > node->simdclone->simdlen)
18934 veclen = node->simdclone->simdlen;
18935 adj.arg_prefix = "simd";
fdf7662c 18936 if (POINTER_TYPE_P (parm_type))
18937 adj.type = build_vector_type (pointer_sized_int_node, veclen);
18938 else
18939 adj.type = build_vector_type (parm_type, veclen);
d09768a4 18940 node->simdclone->args[i].vector_type = adj.type;
18941 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
18942 {
18943 adjustments.safe_push (adj);
18944 if (j == veclen)
18945 {
18946 memset (&adj, 0, sizeof (adj));
18947 adj.op = IPA_PARM_OP_NEW;
18948 adj.arg_prefix = "simd";
18949 adj.base_index = i;
18950 adj.type = node->simdclone->args[i].vector_type;
18951 }
18952 }
18953
18954 if (node->definition)
18955 node->simdclone->args[i].simd_array
18956 = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm)),
18957 parm_type, node->simdclone->simdlen);
18958 }
18959 adjustments.safe_push (adj);
18960 }
18961
18962 if (node->simdclone->inbranch)
18963 {
18964 tree base_type
18965 = simd_clone_compute_base_data_type (node->simdclone->origin,
18966 node->simdclone);
18967
18968 memset (&adj, 0, sizeof (adj));
18969 adj.op = IPA_PARM_OP_NEW;
18970 adj.arg_prefix = "mask";
18971
18972 adj.base_index = i;
18973 if (INTEGRAL_TYPE_P (base_type) || POINTER_TYPE_P (base_type))
18974 veclen = node->simdclone->vecsize_int;
18975 else
18976 veclen = node->simdclone->vecsize_float;
18977 veclen /= GET_MODE_BITSIZE (TYPE_MODE (base_type));
18978 if (veclen > node->simdclone->simdlen)
18979 veclen = node->simdclone->simdlen;
fdf7662c 18980 if (POINTER_TYPE_P (base_type))
18981 adj.type = build_vector_type (pointer_sized_int_node, veclen);
18982 else
18983 adj.type = build_vector_type (base_type, veclen);
d09768a4 18984 adjustments.safe_push (adj);
18985
18986 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
18987 adjustments.safe_push (adj);
18988
18989 /* We have previously allocated one extra entry for the mask. Use
18990 it and fill it. */
18991 struct cgraph_simd_clone *sc = node->simdclone;
18992 sc->nargs++;
18993 if (node->definition)
18994 {
18995 sc->args[i].orig_arg
18996 = build_decl (UNKNOWN_LOCATION, PARM_DECL, NULL, base_type);
18997 sc->args[i].simd_array
18998 = create_tmp_simd_array ("mask", base_type, sc->simdlen);
18999 }
19000 sc->args[i].orig_type = base_type;
19001 sc->args[i].arg_type = SIMD_CLONE_ARG_TYPE_MASK;
19002 }
19003
19004 if (node->definition)
19005 ipa_modify_formal_parameters (node->decl, adjustments);
19006 else
19007 {
19008 tree new_arg_types = NULL_TREE, new_reversed;
19009 bool last_parm_void = false;
19010 if (args.length () > 0 && args.last () == void_type_node)
19011 last_parm_void = true;
19012
19013 gcc_assert (TYPE_ARG_TYPES (TREE_TYPE (node->decl)));
19014 j = adjustments.length ();
19015 for (i = 0; i < j; i++)
19016 {
19017 struct ipa_parm_adjustment *adj = &adjustments[i];
19018 tree ptype;
19019 if (adj->op == IPA_PARM_OP_COPY)
19020 ptype = args[adj->base_index];
19021 else
19022 ptype = adj->type;
19023 new_arg_types = tree_cons (NULL_TREE, ptype, new_arg_types);
19024 }
19025 new_reversed = nreverse (new_arg_types);
19026 if (last_parm_void)
19027 {
19028 if (new_reversed)
19029 TREE_CHAIN (new_arg_types) = void_list_node;
19030 else
19031 new_reversed = void_list_node;
19032 }
19033
19034 tree new_type = build_distinct_type_copy (TREE_TYPE (node->decl));
19035 TYPE_ARG_TYPES (new_type) = new_reversed;
19036 TREE_TYPE (node->decl) = new_type;
19037
19038 adjustments.release ();
19039 }
19040 args.release ();
19041 return adjustments;
19042}
19043
19044/* Initialize and copy the function arguments in NODE to their
19045 corresponding local simd arrays. Returns a fresh gimple_seq with
19046 the instruction sequence generated. */
19047
19048static gimple_seq
19049simd_clone_init_simd_arrays (struct cgraph_node *node,
19050 ipa_parm_adjustment_vec adjustments)
19051{
19052 gimple_seq seq = NULL;
19053 unsigned i = 0, j = 0, k;
19054
19055 for (tree arg = DECL_ARGUMENTS (node->decl);
19056 arg;
19057 arg = DECL_CHAIN (arg), i++, j++)
19058 {
43895be5 19059 if (adjustments[j].op == IPA_PARM_OP_COPY
19060 || POINTER_TYPE_P (TREE_TYPE (arg)))
d09768a4 19061 continue;
19062
19063 node->simdclone->args[i].vector_arg = arg;
19064
19065 tree array = node->simdclone->args[i].simd_array;
19066 if (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg)) == node->simdclone->simdlen)
19067 {
19068 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
19069 tree ptr = build_fold_addr_expr (array);
19070 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
19071 build_int_cst (ptype, 0));
19072 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
19073 gimplify_and_add (t, &seq);
19074 }
19075 else
19076 {
19077 unsigned int simdlen = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg));
19078 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
19079 for (k = 0; k < node->simdclone->simdlen; k += simdlen)
19080 {
19081 tree ptr = build_fold_addr_expr (array);
19082 int elemsize;
19083 if (k)
19084 {
19085 arg = DECL_CHAIN (arg);
19086 j++;
19087 }
19088 elemsize
19089 = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg))));
19090 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
19091 build_int_cst (ptype, k * elemsize));
19092 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
19093 gimplify_and_add (t, &seq);
19094 }
19095 }
19096 }
19097 return seq;
19098}
19099
19100/* Callback info for ipa_simd_modify_stmt_ops below. */
19101
19102struct modify_stmt_info {
19103 ipa_parm_adjustment_vec adjustments;
42acab1c 19104 gimple *stmt;
d09768a4 19105 /* True if the parent statement was modified by
19106 ipa_simd_modify_stmt_ops. */
19107 bool modified;
19108};
19109
19110/* Callback for walk_gimple_op.
19111
19112 Adjust operands from a given statement as specified in the
19113 adjustments vector in the callback data. */
19114
19115static tree
19116ipa_simd_modify_stmt_ops (tree *tp, int *walk_subtrees, void *data)
19117{
19118 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
2d78e89f 19119 struct modify_stmt_info *info = (struct modify_stmt_info *) wi->info;
19120 tree *orig_tp = tp;
19121 if (TREE_CODE (*tp) == ADDR_EXPR)
19122 tp = &TREE_OPERAND (*tp, 0);
19123 struct ipa_parm_adjustment *cand = NULL;
19124 if (TREE_CODE (*tp) == PARM_DECL)
19125 cand = ipa_get_adjustment_candidate (&tp, NULL, info->adjustments, true);
19126 else
d09768a4 19127 {
d09768a4 19128 if (TYPE_P (*tp))
19129 *walk_subtrees = 0;
d09768a4 19130 }
d09768a4 19131
2d78e89f 19132 tree repl = NULL_TREE;
19133 if (cand)
19134 repl = unshare_expr (cand->new_decl);
19135 else
d09768a4 19136 {
2d78e89f 19137 if (tp != orig_tp)
19138 {
19139 *walk_subtrees = 0;
19140 bool modified = info->modified;
19141 info->modified = false;
19142 walk_tree (tp, ipa_simd_modify_stmt_ops, wi, wi->pset);
19143 if (!info->modified)
19144 {
19145 info->modified = modified;
19146 return NULL_TREE;
19147 }
19148 info->modified = modified;
19149 repl = *tp;
19150 }
19151 else
19152 return NULL_TREE;
d09768a4 19153 }
2d78e89f 19154
19155 if (tp != orig_tp)
d09768a4 19156 {
2d78e89f 19157 repl = build_fold_addr_expr (repl);
42acab1c 19158 gimple *stmt;
9c1dd4d9 19159 if (is_gimple_debug (info->stmt))
19160 {
19161 tree vexpr = make_node (DEBUG_EXPR_DECL);
19162 stmt = gimple_build_debug_source_bind (vexpr, repl, NULL);
19163 DECL_ARTIFICIAL (vexpr) = 1;
19164 TREE_TYPE (vexpr) = TREE_TYPE (repl);
19165 DECL_MODE (vexpr) = TYPE_MODE (TREE_TYPE (repl));
19166 repl = vexpr;
19167 }
19168 else
19169 {
f9e245b2 19170 stmt = gimple_build_assign (make_ssa_name (TREE_TYPE (repl)), repl);
9c1dd4d9 19171 repl = gimple_assign_lhs (stmt);
19172 }
2d78e89f 19173 gimple_stmt_iterator gsi = gsi_for_stmt (info->stmt);
d09768a4 19174 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
2d78e89f 19175 *orig_tp = repl;
d09768a4 19176 }
2d78e89f 19177 else if (!useless_type_conversion_p (TREE_TYPE (*tp), TREE_TYPE (repl)))
d09768a4 19178 {
19179 tree vce = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (*tp), repl);
19180 *tp = vce;
19181 }
19182 else
19183 *tp = repl;
19184
19185 info->modified = true;
d09768a4 19186 return NULL_TREE;
19187}
19188
19189/* Traverse the function body and perform all modifications as
19190 described in ADJUSTMENTS. At function return, ADJUSTMENTS will be
19191 modified such that the replacement/reduction value will now be an
19192 offset into the corresponding simd_array.
19193
19194 This function will replace all function argument uses with their
19195 corresponding simd array elements, and ajust the return values
19196 accordingly. */
19197
19198static void
19199ipa_simd_modify_function_body (struct cgraph_node *node,
19200 ipa_parm_adjustment_vec adjustments,
19201 tree retval_array, tree iter)
19202{
19203 basic_block bb;
2d78e89f 19204 unsigned int i, j, l;
d09768a4 19205
19206 /* Re-use the adjustments array, but this time use it to replace
19207 every function argument use to an offset into the corresponding
19208 simd_array. */
19209 for (i = 0, j = 0; i < node->simdclone->nargs; ++i, ++j)
19210 {
19211 if (!node->simdclone->args[i].vector_arg)
19212 continue;
19213
19214 tree basetype = TREE_TYPE (node->simdclone->args[i].orig_arg);
19215 tree vectype = TREE_TYPE (node->simdclone->args[i].vector_arg);
19216 adjustments[j].new_decl
19217 = build4 (ARRAY_REF,
19218 basetype,
19219 node->simdclone->args[i].simd_array,
19220 iter,
19221 NULL_TREE, NULL_TREE);
19222 if (adjustments[j].op == IPA_PARM_OP_NONE
19223 && TYPE_VECTOR_SUBPARTS (vectype) < node->simdclone->simdlen)
19224 j += node->simdclone->simdlen / TYPE_VECTOR_SUBPARTS (vectype) - 1;
19225 }
19226
2d78e89f 19227 l = adjustments.length ();
19228 for (i = 1; i < num_ssa_names; i++)
19229 {
19230 tree name = ssa_name (i);
19231 if (name
19232 && SSA_NAME_VAR (name)
19233 && TREE_CODE (SSA_NAME_VAR (name)) == PARM_DECL)
19234 {
19235 for (j = 0; j < l; j++)
19236 if (SSA_NAME_VAR (name) == adjustments[j].base
19237 && adjustments[j].new_decl)
19238 {
19239 tree base_var;
19240 if (adjustments[j].new_ssa_base == NULL_TREE)
19241 {
19242 base_var
19243 = copy_var_decl (adjustments[j].base,
19244 DECL_NAME (adjustments[j].base),
19245 TREE_TYPE (adjustments[j].base));
19246 adjustments[j].new_ssa_base = base_var;
19247 }
19248 else
19249 base_var = adjustments[j].new_ssa_base;
19250 if (SSA_NAME_IS_DEFAULT_DEF (name))
19251 {
19252 bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
19253 gimple_stmt_iterator gsi = gsi_after_labels (bb);
19254 tree new_decl = unshare_expr (adjustments[j].new_decl);
19255 set_ssa_default_def (cfun, adjustments[j].base, NULL_TREE);
19256 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
19257 SSA_NAME_IS_DEFAULT_DEF (name) = 0;
42acab1c 19258 gimple *stmt = gimple_build_assign (name, new_decl);
2d78e89f 19259 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
19260 }
19261 else
19262 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
19263 }
19264 }
19265 }
19266
d09768a4 19267 struct modify_stmt_info info;
19268 info.adjustments = adjustments;
19269
19270 FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl))
19271 {
19272 gimple_stmt_iterator gsi;
19273
19274 gsi = gsi_start_bb (bb);
19275 while (!gsi_end_p (gsi))
19276 {
42acab1c 19277 gimple *stmt = gsi_stmt (gsi);
d09768a4 19278 info.stmt = stmt;
19279 struct walk_stmt_info wi;
19280
19281 memset (&wi, 0, sizeof (wi));
19282 info.modified = false;
19283 wi.info = &info;
19284 walk_gimple_op (stmt, ipa_simd_modify_stmt_ops, &wi);
19285
1a91d914 19286 if (greturn *return_stmt = dyn_cast <greturn *> (stmt))
d09768a4 19287 {
1a91d914 19288 tree retval = gimple_return_retval (return_stmt);
d09768a4 19289 if (!retval)
19290 {
19291 gsi_remove (&gsi, true);
19292 continue;
19293 }
19294
19295 /* Replace `return foo' with `retval_array[iter] = foo'. */
19296 tree ref = build4 (ARRAY_REF, TREE_TYPE (retval),
19297 retval_array, iter, NULL, NULL);
19298 stmt = gimple_build_assign (ref, retval);
19299 gsi_replace (&gsi, stmt, true);
19300 info.modified = true;
19301 }
19302
19303 if (info.modified)
19304 {
19305 update_stmt (stmt);
19306 if (maybe_clean_eh_stmt (stmt))
19307 gimple_purge_dead_eh_edges (gimple_bb (stmt));
19308 }
19309 gsi_next (&gsi);
19310 }
19311 }
19312}
19313
9561765e 19314/* Helper function of simd_clone_adjust, return linear step addend
19315 of Ith argument. */
19316
19317static tree
19318simd_clone_linear_addend (struct cgraph_node *node, unsigned int i,
19319 tree addtype, basic_block entry_bb)
19320{
19321 tree ptype = NULL_TREE;
19322 switch (node->simdclone->args[i].arg_type)
19323 {
19324 case SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP:
19325 case SIMD_CLONE_ARG_TYPE_LINEAR_REF_CONSTANT_STEP:
19326 case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_CONSTANT_STEP:
19327 case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP:
19328 return build_int_cst (addtype, node->simdclone->args[i].linear_step);
19329 case SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP:
19330 case SIMD_CLONE_ARG_TYPE_LINEAR_REF_VARIABLE_STEP:
19331 ptype = TREE_TYPE (node->simdclone->args[i].orig_arg);
19332 break;
19333 case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_VARIABLE_STEP:
19334 case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_VARIABLE_STEP:
19335 ptype = TREE_TYPE (TREE_TYPE (node->simdclone->args[i].orig_arg));
19336 break;
19337 default:
19338 gcc_unreachable ();
19339 }
19340
19341 unsigned int idx = node->simdclone->args[i].linear_step;
19342 tree arg = node->simdclone->args[idx].orig_arg;
19343 gcc_assert (is_gimple_reg_type (TREE_TYPE (arg)));
19344 gimple_stmt_iterator gsi = gsi_after_labels (entry_bb);
19345 gimple *g;
19346 tree ret;
19347 if (is_gimple_reg (arg))
19348 ret = get_or_create_ssa_default_def (cfun, arg);
19349 else
19350 {
19351 g = gimple_build_assign (make_ssa_name (TREE_TYPE (arg)), arg);
19352 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
19353 ret = gimple_assign_lhs (g);
19354 }
19355 if (TREE_CODE (TREE_TYPE (arg)) == REFERENCE_TYPE)
19356 {
19357 g = gimple_build_assign (make_ssa_name (TREE_TYPE (TREE_TYPE (arg))),
19358 build_simple_mem_ref (ret));
19359 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
19360 ret = gimple_assign_lhs (g);
19361 }
19362 if (!useless_type_conversion_p (addtype, TREE_TYPE (ret)))
19363 {
19364 g = gimple_build_assign (make_ssa_name (addtype), NOP_EXPR, ret);
19365 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
19366 ret = gimple_assign_lhs (g);
19367 }
19368 if (POINTER_TYPE_P (ptype))
19369 {
19370 tree size = TYPE_SIZE_UNIT (TREE_TYPE (ptype));
19371 if (size && TREE_CODE (size) == INTEGER_CST)
19372 {
19373 g = gimple_build_assign (make_ssa_name (addtype), MULT_EXPR,
19374 ret, fold_convert (addtype, size));
19375 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
19376 ret = gimple_assign_lhs (g);
19377 }
19378 }
19379 return ret;
19380}
19381
d09768a4 19382/* Adjust the argument types in NODE to their appropriate vector
19383 counterparts. */
19384
19385static void
19386simd_clone_adjust (struct cgraph_node *node)
19387{
19388 push_cfun (DECL_STRUCT_FUNCTION (node->decl));
19389
19390 targetm.simd_clone.adjust (node);
19391
19392 tree retval = simd_clone_adjust_return_type (node);
19393 ipa_parm_adjustment_vec adjustments
19394 = simd_clone_adjust_argument_types (node);
19395
19396 push_gimplify_context ();
19397
19398 gimple_seq seq = simd_clone_init_simd_arrays (node, adjustments);
19399
19400 /* Adjust all uses of vector arguments accordingly. Adjust all
19401 return values accordingly. */
19402 tree iter = create_tmp_var (unsigned_type_node, "iter");
f9e245b2 19403 tree iter1 = make_ssa_name (iter);
19404 tree iter2 = make_ssa_name (iter);
d09768a4 19405 ipa_simd_modify_function_body (node, adjustments, retval, iter1);
19406
19407 /* Initialize the iteration variable. */
19408 basic_block entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
19409 basic_block body_bb = split_block_after_labels (entry_bb)->dest;
19410 gimple_stmt_iterator gsi = gsi_after_labels (entry_bb);
19411 /* Insert the SIMD array and iv initialization at function
19412 entry. */
19413 gsi_insert_seq_before (&gsi, seq, GSI_NEW_STMT);
19414
19415 pop_gimplify_context (NULL);
19416
19417 /* Create a new BB right before the original exit BB, to hold the
19418 iteration increment and the condition/branch. */
19419 basic_block orig_exit = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), 0)->src;
19420 basic_block incr_bb = create_empty_bb (orig_exit);
343ee723 19421 add_bb_to_loop (incr_bb, body_bb->loop_father);
d09768a4 19422 /* The succ of orig_exit was EXIT_BLOCK_PTR_FOR_FN (cfun), with an empty
19423 flag. Set it now to be a FALLTHRU_EDGE. */
19424 gcc_assert (EDGE_COUNT (orig_exit->succs) == 1);
19425 EDGE_SUCC (orig_exit, 0)->flags |= EDGE_FALLTHRU;
19426 for (unsigned i = 0;
19427 i < EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds); ++i)
19428 {
19429 edge e = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), i);
19430 redirect_edge_succ (e, incr_bb);
19431 }
19432 edge e = make_edge (incr_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
19433 e->probability = REG_BR_PROB_BASE;
19434 gsi = gsi_last_bb (incr_bb);
42acab1c 19435 gimple *g = gimple_build_assign (iter2, PLUS_EXPR, iter1,
e9cf809e 19436 build_int_cst (unsigned_type_node, 1));
d09768a4 19437 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
19438
19439 /* Mostly annotate the loop for the vectorizer (the rest is done below). */
19440 struct loop *loop = alloc_loop ();
4c73695b 19441 cfun->has_force_vectorize_loops = true;
d09768a4 19442 loop->safelen = node->simdclone->simdlen;
4c73695b 19443 loop->force_vectorize = true;
d09768a4 19444 loop->header = body_bb;
d09768a4 19445
19446 /* Branch around the body if the mask applies. */
19447 if (node->simdclone->inbranch)
19448 {
19449 gimple_stmt_iterator gsi = gsi_last_bb (loop->header);
19450 tree mask_array
19451 = node->simdclone->args[node->simdclone->nargs - 1].simd_array;
f9e245b2 19452 tree mask = make_ssa_name (TREE_TYPE (TREE_TYPE (mask_array)));
d09768a4 19453 tree aref = build4 (ARRAY_REF,
19454 TREE_TYPE (TREE_TYPE (mask_array)),
19455 mask_array, iter1,
19456 NULL, NULL);
19457 g = gimple_build_assign (mask, aref);
19458 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
19459 int bitsize = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (aref)));
19460 if (!INTEGRAL_TYPE_P (TREE_TYPE (aref)))
19461 {
19462 aref = build1 (VIEW_CONVERT_EXPR,
19463 build_nonstandard_integer_type (bitsize, 0), mask);
f9e245b2 19464 mask = make_ssa_name (TREE_TYPE (aref));
d09768a4 19465 g = gimple_build_assign (mask, aref);
19466 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
19467 }
19468
19469 g = gimple_build_cond (EQ_EXPR, mask, build_zero_cst (TREE_TYPE (mask)),
19470 NULL, NULL);
19471 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
19472 make_edge (loop->header, incr_bb, EDGE_TRUE_VALUE);
19473 FALLTHRU_EDGE (loop->header)->flags = EDGE_FALSE_VALUE;
19474 }
19475
19476 /* Generate the condition. */
19477 g = gimple_build_cond (LT_EXPR,
19478 iter2,
19479 build_int_cst (unsigned_type_node,
19480 node->simdclone->simdlen),
19481 NULL, NULL);
19482 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
19483 e = split_block (incr_bb, gsi_stmt (gsi));
19484 basic_block latch_bb = e->dest;
343ee723 19485 basic_block new_exit_bb;
4302d619 19486 new_exit_bb = split_block_after_labels (latch_bb)->dest;
d09768a4 19487 loop->latch = latch_bb;
19488
19489 redirect_edge_succ (FALLTHRU_EDGE (latch_bb), body_bb);
19490
19491 make_edge (incr_bb, new_exit_bb, EDGE_FALSE_VALUE);
19492 /* The successor of incr_bb is already pointing to latch_bb; just
19493 change the flags.
19494 make_edge (incr_bb, latch_bb, EDGE_TRUE_VALUE); */
19495 FALLTHRU_EDGE (incr_bb)->flags = EDGE_TRUE_VALUE;
19496
1a91d914 19497 gphi *phi = create_phi_node (iter1, body_bb);
d09768a4 19498 edge preheader_edge = find_edge (entry_bb, body_bb);
19499 edge latch_edge = single_succ_edge (latch_bb);
19500 add_phi_arg (phi, build_zero_cst (unsigned_type_node), preheader_edge,
19501 UNKNOWN_LOCATION);
19502 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
19503
19504 /* Generate the new return. */
19505 gsi = gsi_last_bb (new_exit_bb);
19506 if (retval
19507 && TREE_CODE (retval) == VIEW_CONVERT_EXPR
19508 && TREE_CODE (TREE_OPERAND (retval, 0)) == RESULT_DECL)
19509 retval = TREE_OPERAND (retval, 0);
19510 else if (retval)
19511 {
19512 retval = build1 (VIEW_CONVERT_EXPR,
19513 TREE_TYPE (TREE_TYPE (node->decl)),
19514 retval);
19515 retval = force_gimple_operand_gsi (&gsi, retval, true, NULL,
19516 false, GSI_CONTINUE_LINKING);
19517 }
19518 g = gimple_build_return (retval);
19519 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
19520
19521 /* Handle aligned clauses by replacing default defs of the aligned
19522 uniform args with __builtin_assume_aligned (arg_N(D), alignment)
19523 lhs. Handle linear by adding PHIs. */
19524 for (unsigned i = 0; i < node->simdclone->nargs; i++)
97a82d40 19525 if (node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
19526 && (TREE_ADDRESSABLE (node->simdclone->args[i].orig_arg)
19527 || !is_gimple_reg_type
19528 (TREE_TYPE (node->simdclone->args[i].orig_arg))))
19529 {
19530 tree orig_arg = node->simdclone->args[i].orig_arg;
19531 if (is_gimple_reg_type (TREE_TYPE (orig_arg)))
19532 iter1 = make_ssa_name (TREE_TYPE (orig_arg));
19533 else
19534 {
19535 iter1 = create_tmp_var_raw (TREE_TYPE (orig_arg));
19536 gimple_add_tmp_var (iter1);
19537 }
19538 gsi = gsi_after_labels (entry_bb);
19539 g = gimple_build_assign (iter1, orig_arg);
19540 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
19541 gsi = gsi_after_labels (body_bb);
19542 g = gimple_build_assign (orig_arg, iter1);
19543 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
19544 }
19545 else if (node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
19546 && DECL_BY_REFERENCE (node->simdclone->args[i].orig_arg)
19547 && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
19548 == REFERENCE_TYPE
19549 && TREE_ADDRESSABLE
19550 (TREE_TYPE (TREE_TYPE (node->simdclone->args[i].orig_arg))))
19551 {
19552 tree orig_arg = node->simdclone->args[i].orig_arg;
19553 tree def = ssa_default_def (cfun, orig_arg);
19554 if (def && !has_zero_uses (def))
19555 {
19556 iter1 = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (orig_arg)));
19557 gimple_add_tmp_var (iter1);
19558 gsi = gsi_after_labels (entry_bb);
19559 g = gimple_build_assign (iter1, build_simple_mem_ref (def));
19560 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
19561 gsi = gsi_after_labels (body_bb);
19562 g = gimple_build_assign (build_simple_mem_ref (def), iter1);
19563 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
19564 }
19565 }
19566 else if (node->simdclone->args[i].alignment
19567 && node->simdclone->args[i].arg_type
19568 == SIMD_CLONE_ARG_TYPE_UNIFORM
19569 && (node->simdclone->args[i].alignment
19570 & (node->simdclone->args[i].alignment - 1)) == 0
19571 && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
19572 == POINTER_TYPE)
d09768a4 19573 {
19574 unsigned int alignment = node->simdclone->args[i].alignment;
19575 tree orig_arg = node->simdclone->args[i].orig_arg;
19576 tree def = ssa_default_def (cfun, orig_arg);
6db33a3d 19577 if (def && !has_zero_uses (def))
d09768a4 19578 {
19579 tree fn = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
19580 gimple_seq seq = NULL;
19581 bool need_cvt = false;
1a91d914 19582 gcall *call
d09768a4 19583 = gimple_build_call (fn, 2, def, size_int (alignment));
19584 g = call;
19585 if (!useless_type_conversion_p (TREE_TYPE (orig_arg),
19586 ptr_type_node))
19587 need_cvt = true;
f9e245b2 19588 tree t = make_ssa_name (need_cvt ? ptr_type_node : orig_arg);
d09768a4 19589 gimple_call_set_lhs (g, t);
19590 gimple_seq_add_stmt_without_update (&seq, g);
19591 if (need_cvt)
19592 {
f9e245b2 19593 t = make_ssa_name (orig_arg);
e9cf809e 19594 g = gimple_build_assign (t, NOP_EXPR, gimple_call_lhs (g));
d09768a4 19595 gimple_seq_add_stmt_without_update (&seq, g);
19596 }
19597 gsi_insert_seq_on_edge_immediate
19598 (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)), seq);
19599
19600 entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
19601 int freq = compute_call_stmt_bb_frequency (current_function_decl,
19602 entry_bb);
415d1b9a 19603 node->create_edge (cgraph_node::get_create (fn),
19604 call, entry_bb->count, freq);
d09768a4 19605
19606 imm_use_iterator iter;
19607 use_operand_p use_p;
42acab1c 19608 gimple *use_stmt;
d09768a4 19609 tree repl = gimple_get_lhs (g);
19610 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
19611 if (is_gimple_debug (use_stmt) || use_stmt == call)
19612 continue;
19613 else
19614 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
19615 SET_USE (use_p, repl);
19616 }
19617 }
43895be5 19618 else if ((node->simdclone->args[i].arg_type
19619 == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
19620 || (node->simdclone->args[i].arg_type
9561765e 19621 == SIMD_CLONE_ARG_TYPE_LINEAR_REF_CONSTANT_STEP)
19622 || (node->simdclone->args[i].arg_type
19623 == SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP)
19624 || (node->simdclone->args[i].arg_type
19625 == SIMD_CLONE_ARG_TYPE_LINEAR_REF_VARIABLE_STEP))
d09768a4 19626 {
19627 tree orig_arg = node->simdclone->args[i].orig_arg;
d09768a4 19628 gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
19629 || POINTER_TYPE_P (TREE_TYPE (orig_arg)));
97a82d40 19630 tree def = NULL_TREE;
19631 if (TREE_ADDRESSABLE (orig_arg))
19632 {
19633 def = make_ssa_name (TREE_TYPE (orig_arg));
19634 iter1 = make_ssa_name (TREE_TYPE (orig_arg));
19635 iter2 = make_ssa_name (TREE_TYPE (orig_arg));
19636 gsi = gsi_after_labels (entry_bb);
19637 g = gimple_build_assign (def, orig_arg);
19638 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
19639 }
19640 else
19641 {
19642 def = ssa_default_def (cfun, orig_arg);
19643 if (!def || has_zero_uses (def))
19644 def = NULL_TREE;
19645 else
19646 {
19647 iter1 = make_ssa_name (orig_arg);
19648 iter2 = make_ssa_name (orig_arg);
19649 }
19650 }
19651 if (def)
d09768a4 19652 {
d09768a4 19653 phi = create_phi_node (iter1, body_bb);
19654 add_phi_arg (phi, def, preheader_edge, UNKNOWN_LOCATION);
19655 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
19656 enum tree_code code = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
19657 ? PLUS_EXPR : POINTER_PLUS_EXPR;
19658 tree addtype = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
19659 ? TREE_TYPE (orig_arg) : sizetype;
9561765e 19660 tree addcst = simd_clone_linear_addend (node, i, addtype,
19661 entry_bb);
d09768a4 19662 gsi = gsi_last_bb (incr_bb);
9561765e 19663 g = gimple_build_assign (iter2, code, iter1, addcst);
d09768a4 19664 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
19665
19666 imm_use_iterator iter;
19667 use_operand_p use_p;
42acab1c 19668 gimple *use_stmt;
97a82d40 19669 if (TREE_ADDRESSABLE (orig_arg))
19670 {
19671 gsi = gsi_after_labels (body_bb);
19672 g = gimple_build_assign (orig_arg, iter1);
19673 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
19674 }
19675 else
19676 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
19677 if (use_stmt == phi)
19678 continue;
19679 else
19680 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
19681 SET_USE (use_p, iter1);
d09768a4 19682 }
19683 }
43895be5 19684 else if (node->simdclone->args[i].arg_type
9561765e 19685 == SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP
19686 || (node->simdclone->args[i].arg_type
19687 == SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_VARIABLE_STEP))
43895be5 19688 {
19689 tree orig_arg = node->simdclone->args[i].orig_arg;
19690 tree def = ssa_default_def (cfun, orig_arg);
19691 gcc_assert (!TREE_ADDRESSABLE (orig_arg)
19692 && TREE_CODE (TREE_TYPE (orig_arg)) == REFERENCE_TYPE);
19693 if (def && !has_zero_uses (def))
19694 {
19695 tree rtype = TREE_TYPE (TREE_TYPE (orig_arg));
19696 iter1 = make_ssa_name (orig_arg);
19697 iter2 = make_ssa_name (orig_arg);
19698 tree iter3 = make_ssa_name (rtype);
19699 tree iter4 = make_ssa_name (rtype);
19700 tree iter5 = make_ssa_name (rtype);
19701 gsi = gsi_after_labels (entry_bb);
19702 gimple *load
19703 = gimple_build_assign (iter3, build_simple_mem_ref (def));
19704 gsi_insert_before (&gsi, load, GSI_NEW_STMT);
19705
19706 tree array = node->simdclone->args[i].simd_array;
19707 TREE_ADDRESSABLE (array) = 1;
19708 tree ptr = build_fold_addr_expr (array);
19709 phi = create_phi_node (iter1, body_bb);
19710 add_phi_arg (phi, ptr, preheader_edge, UNKNOWN_LOCATION);
19711 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
19712 g = gimple_build_assign (iter2, POINTER_PLUS_EXPR, iter1,
19713 TYPE_SIZE_UNIT (TREE_TYPE (iter3)));
19714 gsi = gsi_last_bb (incr_bb);
19715 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
19716
19717 phi = create_phi_node (iter4, body_bb);
19718 add_phi_arg (phi, iter3, preheader_edge, UNKNOWN_LOCATION);
19719 add_phi_arg (phi, iter5, latch_edge, UNKNOWN_LOCATION);
19720 enum tree_code code = INTEGRAL_TYPE_P (TREE_TYPE (iter3))
19721 ? PLUS_EXPR : POINTER_PLUS_EXPR;
19722 tree addtype = INTEGRAL_TYPE_P (TREE_TYPE (iter3))
19723 ? TREE_TYPE (iter3) : sizetype;
9561765e 19724 tree addcst = simd_clone_linear_addend (node, i, addtype,
19725 entry_bb);
43895be5 19726 g = gimple_build_assign (iter5, code, iter4, addcst);
19727 gsi = gsi_last_bb (incr_bb);
19728 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
19729
19730 g = gimple_build_assign (build_simple_mem_ref (iter1), iter4);
19731 gsi = gsi_after_labels (body_bb);
19732 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
19733
19734 imm_use_iterator iter;
19735 use_operand_p use_p;
19736 gimple *use_stmt;
19737 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
19738 if (use_stmt == load)
19739 continue;
19740 else
19741 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
19742 SET_USE (use_p, iter1);
19743
19744 if (!TYPE_READONLY (rtype))
19745 {
19746 tree v = make_ssa_name (rtype);
19747 tree aref = build4 (ARRAY_REF, rtype, array,
19748 size_zero_node, NULL_TREE,
19749 NULL_TREE);
19750 gsi = gsi_after_labels (new_exit_bb);
19751 g = gimple_build_assign (v, aref);
19752 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
19753 g = gimple_build_assign (build_simple_mem_ref (def), v);
19754 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
19755 }
19756 }
19757 }
d09768a4 19758
19759 calculate_dominance_info (CDI_DOMINATORS);
19760 add_loop (loop, loop->header->loop_father);
19761 update_ssa (TODO_update_ssa);
19762
19763 pop_cfun ();
19764}
19765
19766/* If the function in NODE is tagged as an elemental SIMD function,
19767 create the appropriate SIMD clones. */
19768
19769static void
19770expand_simd_clones (struct cgraph_node *node)
19771{
d09768a4 19772 tree attr = lookup_attribute ("omp declare simd",
19773 DECL_ATTRIBUTES (node->decl));
ea0695f9 19774 if (attr == NULL_TREE
19775 || node->global.inlined_to
19776 || lookup_attribute ("noclone", DECL_ATTRIBUTES (node->decl)))
d09768a4 19777 return;
ea0695f9 19778
d09768a4 19779 /* Ignore
19780 #pragma omp declare simd
19781 extern int foo ();
19782 in C, there we don't know the argument types at all. */
19783 if (!node->definition
19784 && TYPE_ARG_TYPES (TREE_TYPE (node->decl)) == NULL_TREE)
19785 return;
19786
b2fbac0f 19787 /* Call this before creating clone_info, as it might ggc_collect. */
19788 if (node->definition && node->has_gimple_body_p ())
19789 node->get_body ();
19790
d09768a4 19791 do
19792 {
19793 /* Start with parsing the "omp declare simd" attribute(s). */
19794 bool inbranch_clause_specified;
19795 struct cgraph_simd_clone *clone_info
19796 = simd_clone_clauses_extract (node, TREE_VALUE (attr),
19797 &inbranch_clause_specified);
19798 if (clone_info == NULL)
19799 continue;
19800
19801 int orig_simdlen = clone_info->simdlen;
19802 tree base_type = simd_clone_compute_base_data_type (node, clone_info);
19803 /* The target can return 0 (no simd clones should be created),
19804 1 (just one ISA of simd clones should be created) or higher
19805 count of ISA variants. In that case, clone_info is initialized
19806 for the first ISA variant. */
19807 int count
19808 = targetm.simd_clone.compute_vecsize_and_simdlen (node, clone_info,
19809 base_type, 0);
19810 if (count == 0)
19811 continue;
19812
19813 /* Loop over all COUNT ISA variants, and if !INBRANCH_CLAUSE_SPECIFIED,
19814 also create one inbranch and one !inbranch clone of it. */
19815 for (int i = 0; i < count * 2; i++)
19816 {
19817 struct cgraph_simd_clone *clone = clone_info;
19818 if (inbranch_clause_specified && (i & 1) != 0)
19819 continue;
19820
19821 if (i != 0)
19822 {
19823 clone = simd_clone_struct_alloc (clone_info->nargs
d09768a4 19824 + ((i & 1) != 0));
19825 simd_clone_struct_copy (clone, clone_info);
19826 /* Undo changes targetm.simd_clone.compute_vecsize_and_simdlen
19827 and simd_clone_adjust_argument_types did to the first
19828 clone's info. */
19829 clone->nargs -= clone_info->inbranch;
19830 clone->simdlen = orig_simdlen;
19831 /* And call the target hook again to get the right ISA. */
19832 targetm.simd_clone.compute_vecsize_and_simdlen (node, clone,
19833 base_type,
19834 i / 2);
19835 if ((i & 1) != 0)
19836 clone->inbranch = 1;
19837 }
19838
19839 /* simd_clone_mangle might fail if such a clone has been created
19840 already. */
19841 tree id = simd_clone_mangle (node, clone);
19842 if (id == NULL_TREE)
19843 continue;
19844
19845 /* Only when we are sure we want to create the clone actually
19846 clone the function (or definitions) or create another
19847 extern FUNCTION_DECL (for prototypes without definitions). */
19848 struct cgraph_node *n = simd_clone_create (node);
19849 if (n == NULL)
19850 continue;
19851
19852 n->simdclone = clone;
19853 clone->origin = node;
19854 clone->next_clone = NULL;
19855 if (node->simd_clones == NULL)
19856 {
19857 clone->prev_clone = n;
19858 node->simd_clones = n;
19859 }
19860 else
19861 {
19862 clone->prev_clone = node->simd_clones->simdclone->prev_clone;
19863 clone->prev_clone->simdclone->next_clone = n;
19864 node->simd_clones->simdclone->prev_clone = n;
19865 }
35ee1c66 19866 symtab->change_decl_assembler_name (n->decl, id);
d09768a4 19867 /* And finally adjust the return type, parameters and for
19868 definitions also function body. */
19869 if (node->definition)
19870 simd_clone_adjust (n);
19871 else
19872 {
19873 simd_clone_adjust_return_type (n);
19874 simd_clone_adjust_argument_types (n);
19875 }
19876 }
19877 }
19878 while ((attr = lookup_attribute ("omp declare simd", TREE_CHAIN (attr))));
19879}
19880
19881/* Entry point for IPA simd clone creation pass. */
19882
19883static unsigned int
19884ipa_omp_simd_clone (void)
19885{
19886 struct cgraph_node *node;
19887 FOR_EACH_FUNCTION (node)
19888 expand_simd_clones (node);
19889 return 0;
19890}
19891
7620bc82 19892namespace {
19893
19894const pass_data pass_data_omp_simd_clone =
d09768a4 19895{
19896 SIMPLE_IPA_PASS, /* type */
19897 "simdclone", /* name */
19898 OPTGROUP_NONE, /* optinfo_flags */
d09768a4 19899 TV_NONE, /* tv_id */
19900 ( PROP_ssa | PROP_cfg ), /* properties_required */
19901 0, /* properties_provided */
19902 0, /* properties_destroyed */
19903 0, /* todo_flags_start */
19904 0, /* todo_flags_finish */
19905};
19906
7620bc82 19907class pass_omp_simd_clone : public simple_ipa_opt_pass
d09768a4 19908{
19909public:
19910 pass_omp_simd_clone(gcc::context *ctxt)
19911 : simple_ipa_opt_pass(pass_data_omp_simd_clone, ctxt)
19912 {}
19913
19914 /* opt_pass methods: */
31315c24 19915 virtual bool gate (function *);
65b0537f 19916 virtual unsigned int execute (function *) { return ipa_omp_simd_clone (); }
d09768a4 19917};
19918
31315c24 19919bool
19920pass_omp_simd_clone::gate (function *)
19921{
c58a4cfd 19922 return targetm.simd_clone.compute_vecsize_and_simdlen != NULL;
31315c24 19923}
19924
7620bc82 19925} // anon namespace
19926
d09768a4 19927simple_ipa_opt_pass *
19928make_pass_omp_simd_clone (gcc::context *ctxt)
19929{
19930 return new pass_omp_simd_clone (ctxt);
19931}
cbe8bda8 19932
dccabdd1 19933/* Helper function for omp_finish_file routine. Takes decls from V_DECLS and
19934 adds their addresses and sizes to constructor-vector V_CTOR. */
19935static void
19936add_decls_addresses_to_decl_constructor (vec<tree, va_gc> *v_decls,
19937 vec<constructor_elt, va_gc> *v_ctor)
19938{
19939 unsigned len = vec_safe_length (v_decls);
19940 for (unsigned i = 0; i < len; i++)
19941 {
19942 tree it = (*v_decls)[i];
c0998828 19943 bool is_var = TREE_CODE (it) == VAR_DECL;
19944 bool is_link_var
19945 = is_var
19946#ifdef ACCEL_COMPILER
19947 && DECL_HAS_VALUE_EXPR_P (it)
19948#endif
19949 && lookup_attribute ("omp declare target link", DECL_ATTRIBUTES (it));
dccabdd1 19950
c0998828 19951 tree size = NULL_TREE;
19952 if (is_var)
19953 size = fold_convert (const_ptr_type_node, DECL_SIZE_UNIT (it));
19954
19955 tree addr;
19956 if (!is_link_var)
19957 addr = build_fold_addr_expr (it);
19958 else
19959 {
19960#ifdef ACCEL_COMPILER
19961 /* For "omp declare target link" vars add address of the pointer to
19962 the target table, instead of address of the var. */
19963 tree value_expr = DECL_VALUE_EXPR (it);
19964 tree link_ptr_decl = TREE_OPERAND (value_expr, 0);
19965 varpool_node::finalize_decl (link_ptr_decl);
19966 addr = build_fold_addr_expr (link_ptr_decl);
19967#else
19968 addr = build_fold_addr_expr (it);
19969#endif
19970
19971 /* Most significant bit of the size marks "omp declare target link"
19972 vars in host and target tables. */
19973 unsigned HOST_WIDE_INT isize = tree_to_uhwi (size);
19974 isize |= 1ULL << (int_size_in_bytes (const_ptr_type_node)
19975 * BITS_PER_UNIT - 1);
19976 size = wide_int_to_tree (const_ptr_type_node, isize);
19977 }
19978
19979 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE, addr);
19980 if (is_var)
19981 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE, size);
dccabdd1 19982 }
19983}
19984
19985/* Create new symbols containing (address, size) pairs for global variables,
19986 marked with "omp declare target" attribute, as well as addresses for the
ca4c3545 19987 functions, which are outlined offloading regions. */
dccabdd1 19988void
19989omp_finish_file (void)
19990{
19991 unsigned num_funcs = vec_safe_length (offload_funcs);
19992 unsigned num_vars = vec_safe_length (offload_vars);
19993
19994 if (num_funcs == 0 && num_vars == 0)
19995 return;
19996
19997 if (targetm_common.have_named_sections)
19998 {
19999 vec<constructor_elt, va_gc> *v_f, *v_v;
20000 vec_alloc (v_f, num_funcs);
20001 vec_alloc (v_v, num_vars * 2);
20002
20003 add_decls_addresses_to_decl_constructor (offload_funcs, v_f);
20004 add_decls_addresses_to_decl_constructor (offload_vars, v_v);
20005
20006 tree vars_decl_type = build_array_type_nelts (pointer_sized_int_node,
20007 num_vars * 2);
20008 tree funcs_decl_type = build_array_type_nelts (pointer_sized_int_node,
20009 num_funcs);
20010 TYPE_ALIGN (vars_decl_type) = TYPE_ALIGN (pointer_sized_int_node);
20011 TYPE_ALIGN (funcs_decl_type) = TYPE_ALIGN (pointer_sized_int_node);
20012 tree ctor_v = build_constructor (vars_decl_type, v_v);
20013 tree ctor_f = build_constructor (funcs_decl_type, v_f);
20014 TREE_CONSTANT (ctor_v) = TREE_CONSTANT (ctor_f) = 1;
20015 TREE_STATIC (ctor_v) = TREE_STATIC (ctor_f) = 1;
20016 tree funcs_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
20017 get_identifier (".offload_func_table"),
20018 funcs_decl_type);
20019 tree vars_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
20020 get_identifier (".offload_var_table"),
20021 vars_decl_type);
20022 TREE_STATIC (funcs_decl) = TREE_STATIC (vars_decl) = 1;
20023 /* Do not align tables more than TYPE_ALIGN (pointer_sized_int_node),
20024 otherwise a joint table in a binary will contain padding between
20025 tables from multiple object files. */
20026 DECL_USER_ALIGN (funcs_decl) = DECL_USER_ALIGN (vars_decl) = 1;
20027 DECL_ALIGN (funcs_decl) = TYPE_ALIGN (funcs_decl_type);
20028 DECL_ALIGN (vars_decl) = TYPE_ALIGN (vars_decl_type);
20029 DECL_INITIAL (funcs_decl) = ctor_f;
20030 DECL_INITIAL (vars_decl) = ctor_v;
20031 set_decl_section_name (funcs_decl, OFFLOAD_FUNC_TABLE_SECTION_NAME);
20032 set_decl_section_name (vars_decl, OFFLOAD_VAR_TABLE_SECTION_NAME);
20033
20034 varpool_node::finalize_decl (vars_decl);
20035 varpool_node::finalize_decl (funcs_decl);
7114ebdd 20036 }
dccabdd1 20037 else
20038 {
20039 for (unsigned i = 0; i < num_funcs; i++)
20040 {
20041 tree it = (*offload_funcs)[i];
20042 targetm.record_offload_symbol (it);
20043 }
20044 for (unsigned i = 0; i < num_vars; i++)
20045 {
20046 tree it = (*offload_vars)[i];
20047 targetm.record_offload_symbol (it);
20048 }
20049 }
20050}
20051
cbba99a0 20052/* Find the number of threads (POS = false), or thread number (POS =
20053 true) for an OpenACC region partitioned as MASK. Setup code
20054 required for the calculation is added to SEQ. */
20055
20056static tree
20057oacc_thread_numbers (bool pos, int mask, gimple_seq *seq)
20058{
20059 tree res = pos ? NULL_TREE : build_int_cst (unsigned_type_node, 1);
20060 unsigned ix;
20061
20062 /* Start at gang level, and examine relevant dimension indices. */
20063 for (ix = GOMP_DIM_GANG; ix != GOMP_DIM_MAX; ix++)
20064 if (GOMP_DIM_MASK (ix) & mask)
20065 {
20066 tree arg = build_int_cst (unsigned_type_node, ix);
20067
20068 if (res)
20069 {
20070 /* We had an outer index, so scale that by the size of
20071 this dimension. */
20072 tree n = create_tmp_var (integer_type_node);
20073 gimple *call
20074 = gimple_build_call_internal (IFN_GOACC_DIM_SIZE, 1, arg);
20075
20076 gimple_call_set_lhs (call, n);
20077 gimple_seq_add_stmt (seq, call);
20078 res = fold_build2 (MULT_EXPR, integer_type_node, res, n);
20079 }
20080 if (pos)
20081 {
20082 /* Determine index in this dimension. */
20083 tree id = create_tmp_var (integer_type_node);
20084 gimple *call = gimple_build_call_internal
20085 (IFN_GOACC_DIM_POS, 1, arg);
20086
20087 gimple_call_set_lhs (call, id);
20088 gimple_seq_add_stmt (seq, call);
20089 if (res)
20090 res = fold_build2 (PLUS_EXPR, integer_type_node, res, id);
20091 else
20092 res = id;
20093 }
20094 }
20095
20096 if (res == NULL_TREE)
20097 res = integer_zero_node;
20098
20099 return res;
20100}
20101
20102/* Transform IFN_GOACC_LOOP calls to actual code. See
20103 expand_oacc_for for where these are generated. At the vector
20104 level, we stride loops, such that each member of a warp will
20105 operate on adjacent iterations. At the worker and gang level,
20106 each gang/warp executes a set of contiguous iterations. Chunking
20107 can override this such that each iteration engine executes a
20108 contiguous chunk, and then moves on to stride to the next chunk. */
20109
20110static void
20111oacc_xform_loop (gcall *call)
20112{
20113 gimple_stmt_iterator gsi = gsi_for_stmt (call);
20114 enum ifn_goacc_loop_kind code
20115 = (enum ifn_goacc_loop_kind) TREE_INT_CST_LOW (gimple_call_arg (call, 0));
20116 tree dir = gimple_call_arg (call, 1);
20117 tree range = gimple_call_arg (call, 2);
20118 tree step = gimple_call_arg (call, 3);
20119 tree chunk_size = NULL_TREE;
20120 unsigned mask = (unsigned) TREE_INT_CST_LOW (gimple_call_arg (call, 5));
20121 tree lhs = gimple_call_lhs (call);
20122 tree type = TREE_TYPE (lhs);
20123 tree diff_type = TREE_TYPE (range);
20124 tree r = NULL_TREE;
20125 gimple_seq seq = NULL;
20126 bool chunking = false, striding = true;
20127 unsigned outer_mask = mask & (~mask + 1); // Outermost partitioning
20128 unsigned inner_mask = mask & ~outer_mask; // Inner partitioning (if any)
20129
20130#ifdef ACCEL_COMPILER
20131 chunk_size = gimple_call_arg (call, 4);
20132 if (integer_minus_onep (chunk_size) /* Force static allocation. */
20133 || integer_zerop (chunk_size)) /* Default (also static). */
20134 {
20135 /* If we're at the gang level, we want each to execute a
20136 contiguous run of iterations. Otherwise we want each element
20137 to stride. */
20138 striding = !(outer_mask & GOMP_DIM_MASK (GOMP_DIM_GANG));
20139 chunking = false;
20140 }
20141 else
20142 {
20143 /* Chunk of size 1 is striding. */
20144 striding = integer_onep (chunk_size);
20145 chunking = !striding;
20146 }
20147#endif
20148
20149 /* striding=true, chunking=true
20150 -> invalid.
20151 striding=true, chunking=false
20152 -> chunks=1
20153 striding=false,chunking=true
20154 -> chunks=ceil (range/(chunksize*threads*step))
20155 striding=false,chunking=false
20156 -> chunk_size=ceil(range/(threads*step)),chunks=1 */
20157 push_gimplify_context (true);
20158
20159 switch (code)
20160 {
20161 default: gcc_unreachable ();
20162
20163 case IFN_GOACC_LOOP_CHUNKS:
20164 if (!chunking)
20165 r = build_int_cst (type, 1);
20166 else
20167 {
20168 /* chunk_max
20169 = (range - dir) / (chunks * step * num_threads) + dir */
20170 tree per = oacc_thread_numbers (false, mask, &seq);
20171 per = fold_convert (type, per);
20172 chunk_size = fold_convert (type, chunk_size);
20173 per = fold_build2 (MULT_EXPR, type, per, chunk_size);
20174 per = fold_build2 (MULT_EXPR, type, per, step);
20175 r = build2 (MINUS_EXPR, type, range, dir);
20176 r = build2 (PLUS_EXPR, type, r, per);
20177 r = build2 (TRUNC_DIV_EXPR, type, r, per);
20178 }
20179 break;
20180
20181 case IFN_GOACC_LOOP_STEP:
20182 {
20183 /* If striding, step by the entire compute volume, otherwise
20184 step by the inner volume. */
20185 unsigned volume = striding ? mask : inner_mask;
20186
20187 r = oacc_thread_numbers (false, volume, &seq);
20188 r = build2 (MULT_EXPR, type, fold_convert (type, r), step);
20189 }
20190 break;
20191
20192 case IFN_GOACC_LOOP_OFFSET:
20193 if (striding)
20194 {
20195 r = oacc_thread_numbers (true, mask, &seq);
20196 r = fold_convert (diff_type, r);
20197 }
20198 else
20199 {
20200 tree inner_size = oacc_thread_numbers (false, inner_mask, &seq);
20201 tree outer_size = oacc_thread_numbers (false, outer_mask, &seq);
20202 tree volume = fold_build2 (MULT_EXPR, TREE_TYPE (inner_size),
20203 inner_size, outer_size);
20204
20205 volume = fold_convert (diff_type, volume);
20206 if (chunking)
20207 chunk_size = fold_convert (diff_type, chunk_size);
20208 else
20209 {
20210 tree per = fold_build2 (MULT_EXPR, diff_type, volume, step);
20211
20212 chunk_size = build2 (MINUS_EXPR, diff_type, range, dir);
20213 chunk_size = build2 (PLUS_EXPR, diff_type, chunk_size, per);
20214 chunk_size = build2 (TRUNC_DIV_EXPR, diff_type, chunk_size, per);
20215 }
20216
20217 tree span = build2 (MULT_EXPR, diff_type, chunk_size,
20218 fold_convert (diff_type, inner_size));
20219 r = oacc_thread_numbers (true, outer_mask, &seq);
20220 r = fold_convert (diff_type, r);
20221 r = build2 (MULT_EXPR, diff_type, r, span);
20222
20223 tree inner = oacc_thread_numbers (true, inner_mask, &seq);
20224 inner = fold_convert (diff_type, inner);
20225 r = fold_build2 (PLUS_EXPR, diff_type, r, inner);
20226
20227 if (chunking)
20228 {
20229 tree chunk = fold_convert (diff_type, gimple_call_arg (call, 6));
20230 tree per
20231 = fold_build2 (MULT_EXPR, diff_type, volume, chunk_size);
20232 per = build2 (MULT_EXPR, diff_type, per, chunk);
20233
20234 r = build2 (PLUS_EXPR, diff_type, r, per);
20235 }
20236 }
20237 r = fold_build2 (MULT_EXPR, diff_type, r, step);
20238 if (type != diff_type)
20239 r = fold_convert (type, r);
20240 break;
20241
20242 case IFN_GOACC_LOOP_BOUND:
20243 if (striding)
20244 r = range;
20245 else
20246 {
20247 tree inner_size = oacc_thread_numbers (false, inner_mask, &seq);
20248 tree outer_size = oacc_thread_numbers (false, outer_mask, &seq);
20249 tree volume = fold_build2 (MULT_EXPR, TREE_TYPE (inner_size),
20250 inner_size, outer_size);
20251
20252 volume = fold_convert (diff_type, volume);
20253 if (chunking)
20254 chunk_size = fold_convert (diff_type, chunk_size);
20255 else
20256 {
20257 tree per = fold_build2 (MULT_EXPR, diff_type, volume, step);
20258
20259 chunk_size = build2 (MINUS_EXPR, diff_type, range, dir);
20260 chunk_size = build2 (PLUS_EXPR, diff_type, chunk_size, per);
20261 chunk_size = build2 (TRUNC_DIV_EXPR, diff_type, chunk_size, per);
20262 }
20263
20264 tree span = build2 (MULT_EXPR, diff_type, chunk_size,
20265 fold_convert (diff_type, inner_size));
20266
20267 r = fold_build2 (MULT_EXPR, diff_type, span, step);
20268
20269 tree offset = gimple_call_arg (call, 6);
20270 r = build2 (PLUS_EXPR, diff_type, r,
20271 fold_convert (diff_type, offset));
20272 r = build2 (integer_onep (dir) ? MIN_EXPR : MAX_EXPR,
20273 diff_type, r, range);
20274 }
20275 if (diff_type != type)
20276 r = fold_convert (type, r);
20277 break;
20278 }
20279
20280 gimplify_assign (lhs, r, &seq);
20281
20282 pop_gimplify_context (NULL);
20283
20284 gsi_replace_with_seq (&gsi, seq, true);
20285}
20286
948eee2f 20287/* Default partitioned and minimum partitioned dimensions. */
20288
20289static int oacc_default_dims[GOMP_DIM_MAX];
20290static int oacc_min_dims[GOMP_DIM_MAX];
20291
20292/* Parse the default dimension parameter. This is a set of
20293 :-separated optional compute dimensions. Each specified dimension
20294 is a positive integer. When device type support is added, it is
20295 planned to be a comma separated list of such compute dimensions,
20296 with all but the first prefixed by the colon-terminated device
20297 type. */
20298
20299static void
20300oacc_parse_default_dims (const char *dims)
20301{
20302 int ix;
20303
20304 for (ix = GOMP_DIM_MAX; ix--;)
20305 {
20306 oacc_default_dims[ix] = -1;
20307 oacc_min_dims[ix] = 1;
20308 }
20309
20310#ifndef ACCEL_COMPILER
20311 /* Cannot be overridden on the host. */
20312 dims = NULL;
20313#endif
20314 if (dims)
20315 {
20316 const char *pos = dims;
20317
20318 for (ix = 0; *pos && ix != GOMP_DIM_MAX; ix++)
20319 {
20320 if (ix)
20321 {
20322 if (*pos != ':')
20323 goto malformed;
20324 pos++;
20325 }
20326
20327 if (*pos != ':')
20328 {
20329 long val;
20330 const char *eptr;
20331
20332 errno = 0;
20333 val = strtol (pos, CONST_CAST (char **, &eptr), 10);
bd1b9075 20334 if (errno || val <= 0 || (int) val != val)
948eee2f 20335 goto malformed;
20336 pos = eptr;
bd1b9075 20337 oacc_default_dims[ix] = (int) val;
948eee2f 20338 }
20339 }
20340 if (*pos)
20341 {
20342 malformed:
20343 error_at (UNKNOWN_LOCATION,
20344 "-fopenacc-dim operand is malformed at '%s'", pos);
20345 }
20346 }
20347
20348 /* Allow the backend to validate the dimensions. */
20349 targetm.goacc.validate_dims (NULL_TREE, oacc_default_dims, -1);
20350 targetm.goacc.validate_dims (NULL_TREE, oacc_min_dims, -2);
20351}
20352
0bb0f256 20353/* Validate and update the dimensions for offloaded FN. ATTRS is the
6f431819 20354 raw attribute. DIMS is an array of dimensions, which is filled in.
20355 LEVEL is the partitioning level of a routine, or -1 for an offload
948eee2f 20356 region itself. USED is the mask of partitioned execution in the
20357 function. */
0bb0f256 20358
6f431819 20359static void
948eee2f 20360oacc_validate_dims (tree fn, tree attrs, int *dims, int level, unsigned used)
0bb0f256 20361{
20362 tree purpose[GOMP_DIM_MAX];
20363 unsigned ix;
20364 tree pos = TREE_VALUE (attrs);
6f431819 20365 bool is_kernel = oacc_fn_attrib_kernels_p (attrs);
0bb0f256 20366
20367 /* Make sure the attribute creator attached the dimension
20368 information. */
20369 gcc_assert (pos);
20370
20371 for (ix = 0; ix != GOMP_DIM_MAX; ix++)
20372 {
20373 purpose[ix] = TREE_PURPOSE (pos);
0bb0f256 20374 tree val = TREE_VALUE (pos);
20375 dims[ix] = val ? TREE_INT_CST_LOW (val) : -1;
20376 pos = TREE_CHAIN (pos);
20377 }
20378
6f431819 20379 bool changed = targetm.goacc.validate_dims (fn, dims, level);
0bb0f256 20380
948eee2f 20381 /* Default anything left to 1 or a partitioned default. */
0bb0f256 20382 for (ix = 0; ix != GOMP_DIM_MAX; ix++)
20383 if (dims[ix] < 0)
20384 {
948eee2f 20385 /* The OpenACC spec says 'If the [num_gangs] clause is not
20386 specified, an implementation-defined default will be used;
20387 the default may depend on the code within the construct.'
20388 (2.5.6). Thus an implementation is free to choose
20389 non-unity default for a parallel region that doesn't have
20390 any gang-partitioned loops. However, it appears that there
20391 is a sufficient body of user code that expects non-gang
20392 partitioned regions to not execute in gang-redundant mode.
20393 So we (a) don't warn about the non-portability and (b) pick
20394 the minimum permissible dimension size when there is no
20395 partitioned execution. Otherwise we pick the global
20396 default for the dimension, which the user can control. The
20397 same wording and logic applies to num_workers and
20398 vector_length, however the worker- or vector- single
20399 execution doesn't have the same impact as gang-redundant
20400 execution. (If the minimum gang-level partioning is not 1,
20401 the target is probably too confusing.) */
20402 dims[ix] = (used & GOMP_DIM_MASK (ix)
20403 ? oacc_default_dims[ix] : oacc_min_dims[ix]);
0bb0f256 20404 changed = true;
20405 }
20406
20407 if (changed)
20408 {
20409 /* Replace the attribute with new values. */
20410 pos = NULL_TREE;
20411 for (ix = GOMP_DIM_MAX; ix--;)
6f431819 20412 {
20413 pos = tree_cons (purpose[ix],
20414 build_int_cst (integer_type_node, dims[ix]),
20415 pos);
20416 if (is_kernel)
20417 TREE_PUBLIC (pos) = 1;
20418 }
0bb0f256 20419 replace_oacc_fn_attrib (fn, pos);
20420 }
0bb0f256 20421}
20422
cbba99a0 20423/* Create an empty OpenACC loop structure at LOC. */
20424
20425static oacc_loop *
20426new_oacc_loop_raw (oacc_loop *parent, location_t loc)
20427{
20428 oacc_loop *loop = XCNEW (oacc_loop);
20429
20430 loop->parent = parent;
20431 loop->child = loop->sibling = NULL;
20432
20433 if (parent)
20434 {
20435 loop->sibling = parent->child;
20436 parent->child = loop;
20437 }
20438
20439 loop->loc = loc;
20440 loop->marker = NULL;
20441 memset (loop->heads, 0, sizeof (loop->heads));
20442 memset (loop->tails, 0, sizeof (loop->tails));
20443 loop->routine = NULL_TREE;
20444
20445 loop->mask = loop->flags = 0;
584fba4b 20446 loop->ifns = 0;
cbba99a0 20447 loop->chunk_size = 0;
20448 loop->head_end = NULL;
20449
20450 return loop;
20451}
20452
20453/* Create an outermost, dummy OpenACC loop for offloaded function
20454 DECL. */
20455
20456static oacc_loop *
20457new_oacc_loop_outer (tree decl)
20458{
20459 return new_oacc_loop_raw (NULL, DECL_SOURCE_LOCATION (decl));
20460}
20461
20462/* Start a new OpenACC loop structure beginning at head marker HEAD.
20463 Link into PARENT loop. Return the new loop. */
20464
20465static oacc_loop *
20466new_oacc_loop (oacc_loop *parent, gcall *marker)
20467{
20468 oacc_loop *loop = new_oacc_loop_raw (parent, gimple_location (marker));
20469
20470 loop->marker = marker;
20471
20472 /* TODO: This is where device_type flattening would occur for the loop
20473 flags. */
20474
20475 loop->flags = TREE_INT_CST_LOW (gimple_call_arg (marker, 3));
20476
20477 tree chunk_size = integer_zero_node;
20478 if (loop->flags & OLF_GANG_STATIC)
20479 chunk_size = gimple_call_arg (marker, 4);
20480 loop->chunk_size = chunk_size;
20481
20482 return loop;
20483}
20484
20485/* Create a dummy loop encompassing a call to a openACC routine.
20486 Extract the routine's partitioning requirements. */
20487
20488static void
20489new_oacc_loop_routine (oacc_loop *parent, gcall *call, tree decl, tree attrs)
20490{
20491 oacc_loop *loop = new_oacc_loop_raw (parent, gimple_location (call));
6f431819 20492 int level = oacc_fn_attrib_level (attrs);
cbba99a0 20493
20494 gcc_assert (level >= 0);
20495
20496 loop->marker = call;
20497 loop->routine = decl;
20498 loop->mask = ((GOMP_DIM_MASK (GOMP_DIM_MAX) - 1)
20499 ^ (GOMP_DIM_MASK (level) - 1));
20500}
20501
20502/* Finish off the current OpenACC loop ending at tail marker TAIL.
20503 Return the parent loop. */
20504
20505static oacc_loop *
20506finish_oacc_loop (oacc_loop *loop)
20507{
584fba4b 20508 /* If the loop has been collapsed, don't partition it. */
20509 if (!loop->ifns)
20510 loop->mask = loop->flags = 0;
cbba99a0 20511 return loop->parent;
20512}
20513
20514/* Free all OpenACC loop structures within LOOP (inclusive). */
20515
20516static void
20517free_oacc_loop (oacc_loop *loop)
20518{
20519 if (loop->sibling)
20520 free_oacc_loop (loop->sibling);
20521 if (loop->child)
20522 free_oacc_loop (loop->child);
20523
20524 free (loop);
20525}
20526
20527/* Dump out the OpenACC loop head or tail beginning at FROM. */
20528
20529static void
20530dump_oacc_loop_part (FILE *file, gcall *from, int depth,
20531 const char *title, int level)
20532{
20533 enum ifn_unique_kind kind
20534 = (enum ifn_unique_kind) TREE_INT_CST_LOW (gimple_call_arg (from, 0));
20535
20536 fprintf (file, "%*s%s-%d:\n", depth * 2, "", title, level);
20537 for (gimple_stmt_iterator gsi = gsi_for_stmt (from);;)
20538 {
20539 gimple *stmt = gsi_stmt (gsi);
20540
20541 if (is_gimple_call (stmt)
20542 && gimple_call_internal_p (stmt)
20543 && gimple_call_internal_fn (stmt) == IFN_UNIQUE)
20544 {
20545 enum ifn_unique_kind k
20546 = ((enum ifn_unique_kind) TREE_INT_CST_LOW
20547 (gimple_call_arg (stmt, 0)));
20548
20549 if (k == kind && stmt != from)
20550 break;
20551 }
20552 print_gimple_stmt (file, stmt, depth * 2 + 2, 0);
20553
20554 gsi_next (&gsi);
20555 while (gsi_end_p (gsi))
20556 gsi = gsi_start_bb (single_succ (gsi_bb (gsi)));
20557 }
20558}
20559
20560/* Dump OpenACC loops LOOP, its siblings and its children. */
20561
20562static void
20563dump_oacc_loop (FILE *file, oacc_loop *loop, int depth)
20564{
20565 int ix;
20566
20567 fprintf (file, "%*sLoop %x(%x) %s:%u\n", depth * 2, "",
20568 loop->flags, loop->mask,
20569 LOCATION_FILE (loop->loc), LOCATION_LINE (loop->loc));
20570
20571 if (loop->marker)
20572 print_gimple_stmt (file, loop->marker, depth * 2, 0);
20573
20574 if (loop->routine)
20575 fprintf (file, "%*sRoutine %s:%u:%s\n",
20576 depth * 2, "", DECL_SOURCE_FILE (loop->routine),
20577 DECL_SOURCE_LINE (loop->routine),
20578 IDENTIFIER_POINTER (DECL_NAME (loop->routine)));
20579
20580 for (ix = GOMP_DIM_GANG; ix != GOMP_DIM_MAX; ix++)
20581 if (loop->heads[ix])
20582 dump_oacc_loop_part (file, loop->heads[ix], depth, "Head", ix);
20583 for (ix = GOMP_DIM_MAX; ix--;)
20584 if (loop->tails[ix])
20585 dump_oacc_loop_part (file, loop->tails[ix], depth, "Tail", ix);
20586
20587 if (loop->child)
20588 dump_oacc_loop (file, loop->child, depth + 1);
20589 if (loop->sibling)
20590 dump_oacc_loop (file, loop->sibling, depth);
20591}
20592
20593void debug_oacc_loop (oacc_loop *);
20594
20595/* Dump loops to stderr. */
20596
20597DEBUG_FUNCTION void
20598debug_oacc_loop (oacc_loop *loop)
20599{
20600 dump_oacc_loop (stderr, loop, 0);
20601}
20602
20603/* DFS walk of basic blocks BB onwards, creating OpenACC loop
20604 structures as we go. By construction these loops are properly
20605 nested. */
20606
20607static void
20608oacc_loop_discover_walk (oacc_loop *loop, basic_block bb)
20609{
20610 int marker = 0;
20611 int remaining = 0;
20612
20613 if (bb->flags & BB_VISITED)
20614 return;
20615
20616 follow:
20617 bb->flags |= BB_VISITED;
20618
20619 /* Scan for loop markers. */
20620 for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);
20621 gsi_next (&gsi))
20622 {
20623 gimple *stmt = gsi_stmt (gsi);
20624
20625 if (!is_gimple_call (stmt))
20626 continue;
20627
20628 gcall *call = as_a <gcall *> (stmt);
20629
20630 /* If this is a routine, make a dummy loop for it. */
20631 if (tree decl = gimple_call_fndecl (call))
20632 if (tree attrs = get_oacc_fn_attrib (decl))
20633 {
20634 gcc_assert (!marker);
20635 new_oacc_loop_routine (loop, call, decl, attrs);
20636 }
20637
20638 if (!gimple_call_internal_p (call))
20639 continue;
20640
584fba4b 20641 switch (gimple_call_internal_fn (call))
cbba99a0 20642 {
584fba4b 20643 default:
20644 break;
20645
20646 case IFN_GOACC_LOOP:
20647 /* Count the goacc loop abstraction fns, to determine if the
20648 loop was collapsed already. */
20649 loop->ifns++;
20650 break;
cbba99a0 20651
584fba4b 20652 case IFN_UNIQUE:
20653 enum ifn_unique_kind kind
20654 = (enum ifn_unique_kind) (TREE_INT_CST_LOW
20655 (gimple_call_arg (call, 0)));
20656 if (kind == IFN_UNIQUE_OACC_HEAD_MARK
20657 || kind == IFN_UNIQUE_OACC_TAIL_MARK)
20658 {
20659 if (gimple_call_num_args (call) == 2)
cbba99a0 20660 {
584fba4b 20661 gcc_assert (marker && !remaining);
20662 marker = 0;
20663 if (kind == IFN_UNIQUE_OACC_TAIL_MARK)
20664 loop = finish_oacc_loop (loop);
20665 else
20666 loop->head_end = call;
cbba99a0 20667 }
584fba4b 20668 else
cbba99a0 20669 {
584fba4b 20670 int count = TREE_INT_CST_LOW (gimple_call_arg (call, 2));
20671
20672 if (!marker)
20673 {
20674 if (kind == IFN_UNIQUE_OACC_HEAD_MARK)
20675 loop = new_oacc_loop (loop, call);
20676 remaining = count;
20677 }
20678 gcc_assert (count == remaining);
20679 if (remaining)
20680 {
20681 remaining--;
20682 if (kind == IFN_UNIQUE_OACC_HEAD_MARK)
20683 loop->heads[marker] = call;
20684 else
20685 loop->tails[remaining] = call;
20686 }
20687 marker++;
cbba99a0 20688 }
cbba99a0 20689 }
20690 }
20691 }
20692 if (remaining || marker)
20693 {
20694 bb = single_succ (bb);
20695 gcc_assert (single_pred_p (bb) && !(bb->flags & BB_VISITED));
20696 goto follow;
20697 }
20698
20699 /* Walk successor blocks. */
20700 edge e;
20701 edge_iterator ei;
20702
20703 FOR_EACH_EDGE (e, ei, bb->succs)
20704 oacc_loop_discover_walk (loop, e->dest);
20705}
20706
20707/* LOOP is the first sibling. Reverse the order in place and return
20708 the new first sibling. Recurse to child loops. */
20709
20710static oacc_loop *
20711oacc_loop_sibling_nreverse (oacc_loop *loop)
20712{
20713 oacc_loop *last = NULL;
20714 do
20715 {
20716 if (loop->child)
20717 loop->child = oacc_loop_sibling_nreverse (loop->child);
20718
20719 oacc_loop *next = loop->sibling;
20720 loop->sibling = last;
20721 last = loop;
20722 loop = next;
20723 }
20724 while (loop);
20725
20726 return last;
20727}
20728
20729/* Discover the OpenACC loops marked up by HEAD and TAIL markers for
20730 the current function. */
20731
20732static oacc_loop *
20733oacc_loop_discovery ()
20734{
20735 basic_block bb;
20736
20737 oacc_loop *top = new_oacc_loop_outer (current_function_decl);
20738 oacc_loop_discover_walk (top, ENTRY_BLOCK_PTR_FOR_FN (cfun));
20739
20740 /* The siblings were constructed in reverse order, reverse them so
20741 that diagnostics come out in an unsurprising order. */
20742 top = oacc_loop_sibling_nreverse (top);
20743
20744 /* Reset the visited flags. */
20745 FOR_ALL_BB_FN (bb, cfun)
20746 bb->flags &= ~BB_VISITED;
20747
20748 return top;
20749}
20750
20751/* Transform the abstract internal function markers starting at FROM
20752 to be for partitioning level LEVEL. Stop when we meet another HEAD
20753 or TAIL marker. */
20754
20755static void
20756oacc_loop_xform_head_tail (gcall *from, int level)
20757{
20758 enum ifn_unique_kind kind
20759 = (enum ifn_unique_kind) TREE_INT_CST_LOW (gimple_call_arg (from, 0));
20760 tree replacement = build_int_cst (unsigned_type_node, level);
20761
20762 for (gimple_stmt_iterator gsi = gsi_for_stmt (from);;)
20763 {
20764 gimple *stmt = gsi_stmt (gsi);
20765
20766 if (is_gimple_call (stmt)
20767 && gimple_call_internal_p (stmt)
20768 && gimple_call_internal_fn (stmt) == IFN_UNIQUE)
20769 {
20770 enum ifn_unique_kind k
20771 = ((enum ifn_unique_kind)
20772 TREE_INT_CST_LOW (gimple_call_arg (stmt, 0)));
20773
20774 if (k == IFN_UNIQUE_OACC_FORK || k == IFN_UNIQUE_OACC_JOIN)
20775 *gimple_call_arg_ptr (stmt, 2) = replacement;
20776 else if (k == kind && stmt != from)
20777 break;
20778 }
641a0fa1 20779 else if (is_gimple_call (stmt)
20780 && gimple_call_internal_p (stmt)
20781 && gimple_call_internal_fn (stmt) == IFN_GOACC_REDUCTION)
20782 *gimple_call_arg_ptr (stmt, 3) = replacement;
20783
cbba99a0 20784 gsi_next (&gsi);
20785 while (gsi_end_p (gsi))
20786 gsi = gsi_start_bb (single_succ (gsi_bb (gsi)));
20787 }
20788}
20789
20790/* Transform the IFN_GOACC_LOOP internal functions by providing the
584fba4b 20791 determined partitioning mask and chunking argument. END_MARKER
20792 points at the end IFN_HEAD_TAIL call intgroducing the loop. IFNS
20793 is the number of IFN_GOACC_LOOP calls for the loop. MASK_ARG is
20794 the replacement partitioning mask and CHUNK_ARG is the replacement
20795 chunking arg. */
cbba99a0 20796
20797static void
584fba4b 20798oacc_loop_xform_loop (gcall *end_marker, unsigned ifns,
20799 tree mask_arg, tree chunk_arg)
cbba99a0 20800{
20801 gimple_stmt_iterator gsi = gsi_for_stmt (end_marker);
20802
584fba4b 20803 gcc_checking_assert (ifns);
cbba99a0 20804 for (;;)
20805 {
20806 for (; !gsi_end_p (gsi); gsi_next (&gsi))
20807 {
20808 gimple *stmt = gsi_stmt (gsi);
20809
20810 if (!is_gimple_call (stmt))
20811 continue;
20812
20813 gcall *call = as_a <gcall *> (stmt);
20814
20815 if (!gimple_call_internal_p (call))
20816 continue;
20817
20818 if (gimple_call_internal_fn (call) != IFN_GOACC_LOOP)
20819 continue;
20820
20821 *gimple_call_arg_ptr (call, 5) = mask_arg;
20822 *gimple_call_arg_ptr (call, 4) = chunk_arg;
584fba4b 20823 ifns--;
20824 if (!ifns)
cbba99a0 20825 return;
20826 }
20827
584fba4b 20828 /* The LOOP_BOUND ifn could be in the single successor
20829 block. */
cbba99a0 20830 basic_block bb = single_succ (gsi_bb (gsi));
20831 gsi = gsi_start_bb (bb);
20832 }
20833}
20834
20835/* Process the discovered OpenACC loops, setting the correct
20836 partitioning level etc. */
20837
20838static void
20839oacc_loop_process (oacc_loop *loop)
20840{
20841 if (loop->child)
20842 oacc_loop_process (loop->child);
20843
20844 if (loop->mask && !loop->routine)
20845 {
20846 int ix;
20847 unsigned mask = loop->mask;
20848 unsigned dim = GOMP_DIM_GANG;
20849 tree mask_arg = build_int_cst (unsigned_type_node, mask);
20850 tree chunk_arg = loop->chunk_size;
20851
584fba4b 20852 oacc_loop_xform_loop (loop->head_end, loop->ifns, mask_arg, chunk_arg);
cbba99a0 20853
20854 for (ix = 0; ix != GOMP_DIM_MAX && loop->heads[ix]; ix++)
20855 {
20856 gcc_assert (mask);
20857
20858 while (!(GOMP_DIM_MASK (dim) & mask))
20859 dim++;
20860
20861 oacc_loop_xform_head_tail (loop->heads[ix], dim);
20862 oacc_loop_xform_head_tail (loop->tails[ix], dim);
20863
20864 mask ^= GOMP_DIM_MASK (dim);
20865 }
20866 }
20867
20868 if (loop->sibling)
20869 oacc_loop_process (loop->sibling);
20870}
20871
20872/* Walk the OpenACC loop heirarchy checking and assigning the
20873 programmer-specified partitionings. OUTER_MASK is the partitioning
948eee2f 20874 this loop is contained within. Return mask of partitioning
20875 encountered. If any auto loops are discovered, set GOMP_DIM_MAX
20876 bit. */
cbba99a0 20877
948eee2f 20878static unsigned
cbba99a0 20879oacc_loop_fixed_partitions (oacc_loop *loop, unsigned outer_mask)
20880{
20881 unsigned this_mask = loop->mask;
948eee2f 20882 unsigned mask_all = 0;
cbba99a0 20883 bool noisy = true;
20884
20885#ifdef ACCEL_COMPILER
20886 /* When device_type is supported, we want the device compiler to be
20887 noisy, if the loop parameters are device_type-specific. */
20888 noisy = false;
20889#endif
20890
20891 if (!loop->routine)
20892 {
20893 bool auto_par = (loop->flags & OLF_AUTO) != 0;
20894 bool seq_par = (loop->flags & OLF_SEQ) != 0;
20895
20896 this_mask = ((loop->flags >> OLF_DIM_BASE)
20897 & (GOMP_DIM_MASK (GOMP_DIM_MAX) - 1));
20898
20899 if ((this_mask != 0) + auto_par + seq_par > 1)
20900 {
20901 if (noisy)
20902 error_at (loop->loc,
20903 seq_par
20904 ? "%<seq%> overrides other OpenACC loop specifiers"
20905 : "%<auto%> conflicts with other OpenACC loop specifiers");
20906 auto_par = false;
20907 loop->flags &= ~OLF_AUTO;
20908 if (seq_par)
20909 {
20910 loop->flags &=
20911 ~((GOMP_DIM_MASK (GOMP_DIM_MAX) - 1) << OLF_DIM_BASE);
20912 this_mask = 0;
20913 }
20914 }
20915 if (auto_par && (loop->flags & OLF_INDEPENDENT))
948eee2f 20916 mask_all |= GOMP_DIM_MASK (GOMP_DIM_MAX);
cbba99a0 20917 }
20918
20919 if (this_mask & outer_mask)
20920 {
20921 const oacc_loop *outer;
20922 for (outer = loop->parent; outer; outer = outer->parent)
20923 if (outer->mask & this_mask)
20924 break;
20925
20926 if (noisy)
20927 {
20928 if (outer)
20929 {
20930 error_at (loop->loc,
20931 "%s uses same OpenACC parallelism as containing loop",
20932 loop->routine ? "routine call" : "inner loop");
20933 inform (outer->loc, "containing loop here");
20934 }
20935 else
20936 error_at (loop->loc,
20937 "%s uses OpenACC parallelism disallowed by containing routine",
20938 loop->routine ? "routine call" : "loop");
20939
20940 if (loop->routine)
20941 inform (DECL_SOURCE_LOCATION (loop->routine),
20942 "routine %qD declared here", loop->routine);
20943 }
20944 this_mask &= ~outer_mask;
20945 }
20946 else
20947 {
20948 unsigned outermost = this_mask & -this_mask;
20949
20950 if (outermost && outermost <= outer_mask)
20951 {
20952 if (noisy)
20953 {
20954 error_at (loop->loc,
20955 "incorrectly nested OpenACC loop parallelism");
20956
20957 const oacc_loop *outer;
20958 for (outer = loop->parent;
20959 outer->flags && outer->flags < outermost;
20960 outer = outer->parent)
20961 continue;
20962 inform (outer->loc, "containing loop here");
20963 }
20964
20965 this_mask &= ~outermost;
20966 }
20967 }
20968
20969 loop->mask = this_mask;
948eee2f 20970 mask_all |= this_mask;
20971
20972 if (loop->child)
20973 mask_all |= oacc_loop_fixed_partitions (loop->child,
20974 outer_mask | this_mask);
cbba99a0 20975
948eee2f 20976 if (loop->sibling)
20977 mask_all |= oacc_loop_fixed_partitions (loop->sibling, outer_mask);
cbba99a0 20978
948eee2f 20979 return mask_all;
cbba99a0 20980}
20981
f4f5b4b4 20982/* Walk the OpenACC loop heirarchy to assign auto-partitioned loops.
20983 OUTER_MASK is the partitioning this loop is contained within.
20984 Return the cumulative partitioning used by this loop, siblings and
20985 children. */
20986
20987static unsigned
20988oacc_loop_auto_partitions (oacc_loop *loop, unsigned outer_mask)
20989{
20990 unsigned inner_mask = 0;
20991 bool noisy = true;
20992
20993#ifdef ACCEL_COMPILER
20994 /* When device_type is supported, we want the device compiler to be
20995 noisy, if the loop parameters are device_type-specific. */
20996 noisy = false;
20997#endif
20998
20999 if (loop->child)
21000 inner_mask |= oacc_loop_auto_partitions (loop->child,
21001 outer_mask | loop->mask);
21002
21003 if ((loop->flags & OLF_AUTO) && (loop->flags & OLF_INDEPENDENT))
21004 {
21005 unsigned this_mask = 0;
21006
21007 /* Determine the outermost partitioning used within this loop. */
21008 this_mask = inner_mask | GOMP_DIM_MASK (GOMP_DIM_MAX);
21009 this_mask = (this_mask & -this_mask);
21010
21011 /* Pick the partitioning just inside that one. */
21012 this_mask >>= 1;
21013
21014 /* And avoid picking one use by an outer loop. */
21015 this_mask &= ~outer_mask;
21016
21017 if (!this_mask && noisy)
21018 warning_at (loop->loc, 0,
21019 "insufficient partitioning available to parallelize loop");
21020
948eee2f 21021 if (dump_file)
21022 fprintf (dump_file, "Auto loop %s:%d assigned %d\n",
21023 LOCATION_FILE (loop->loc), LOCATION_LINE (loop->loc),
21024 this_mask);
21025
f4f5b4b4 21026 loop->mask = this_mask;
21027 }
21028 inner_mask |= loop->mask;
21029
21030 if (loop->sibling)
21031 inner_mask |= oacc_loop_auto_partitions (loop->sibling, outer_mask);
21032
21033 return inner_mask;
21034}
21035
cbba99a0 21036/* Walk the OpenACC loop heirarchy to check and assign partitioning
948eee2f 21037 axes. Return mask of partitioning. */
cbba99a0 21038
948eee2f 21039static unsigned
f4f5b4b4 21040oacc_loop_partition (oacc_loop *loop, unsigned outer_mask)
cbba99a0 21041{
948eee2f 21042 unsigned mask_all = oacc_loop_fixed_partitions (loop, outer_mask);
21043
21044 if (mask_all & GOMP_DIM_MASK (GOMP_DIM_MAX))
21045 {
21046 mask_all ^= GOMP_DIM_MASK (GOMP_DIM_MAX);
21047 mask_all |= oacc_loop_auto_partitions (loop, outer_mask);
21048 }
21049 return mask_all;
cbba99a0 21050}
21051
c25f1934 21052/* Default fork/join early expander. Delete the function calls if
21053 there is no RTL expander. */
21054
21055bool
21056default_goacc_fork_join (gcall *ARG_UNUSED (call),
21057 const int *ARG_UNUSED (dims), bool is_fork)
21058{
21059 if (is_fork)
21060 return targetm.have_oacc_fork ();
21061 else
21062 return targetm.have_oacc_join ();
21063}
21064
641a0fa1 21065/* Default goacc.reduction early expander.
21066
21067 LHS-opt = IFN_REDUCTION (KIND, RES_PTR, VAR, LEVEL, OP, OFFSET)
21068 If RES_PTR is not integer-zerop:
21069 SETUP - emit 'LHS = *RES_PTR', LHS = NULL
21070 TEARDOWN - emit '*RES_PTR = VAR'
21071 If LHS is not NULL
21072 emit 'LHS = VAR' */
21073
21074void
21075default_goacc_reduction (gcall *call)
21076{
21077 unsigned code = (unsigned)TREE_INT_CST_LOW (gimple_call_arg (call, 0));
21078 gimple_stmt_iterator gsi = gsi_for_stmt (call);
21079 tree lhs = gimple_call_lhs (call);
21080 tree var = gimple_call_arg (call, 2);
21081 gimple_seq seq = NULL;
21082
21083 if (code == IFN_GOACC_REDUCTION_SETUP
21084 || code == IFN_GOACC_REDUCTION_TEARDOWN)
21085 {
21086 /* Setup and Teardown need to copy from/to the receiver object,
21087 if there is one. */
21088 tree ref_to_res = gimple_call_arg (call, 1);
21089
21090 if (!integer_zerop (ref_to_res))
21091 {
21092 tree dst = build_simple_mem_ref (ref_to_res);
21093 tree src = var;
21094
21095 if (code == IFN_GOACC_REDUCTION_SETUP)
21096 {
21097 src = dst;
21098 dst = lhs;
21099 lhs = NULL;
21100 }
21101 gimple_seq_add_stmt (&seq, gimple_build_assign (dst, src));
21102 }
21103 }
21104
21105 /* Copy VAR to LHS, if there is an LHS. */
21106 if (lhs)
21107 gimple_seq_add_stmt (&seq, gimple_build_assign (lhs, var));
21108
21109 gsi_replace_with_seq (&gsi, seq, true);
21110}
21111
0bb0f256 21112/* Main entry point for oacc transformations which run on the device
21113 compiler after LTO, so we know what the target device is at this
21114 point (including the host fallback). */
21115
21116static unsigned int
21117execute_oacc_device_lower ()
21118{
21119 tree attrs = get_oacc_fn_attrib (current_function_decl);
0bb0f256 21120
21121 if (!attrs)
21122 /* Not an offloaded function. */
21123 return 0;
21124
948eee2f 21125 /* Parse the default dim argument exactly once. */
21126 if ((const void *)flag_openacc_dims != &flag_openacc_dims)
21127 {
21128 oacc_parse_default_dims (flag_openacc_dims);
21129 flag_openacc_dims = (char *)&flag_openacc_dims;
21130 }
21131
cbba99a0 21132 /* Discover, partition and process the loops. */
21133 oacc_loop *loops = oacc_loop_discovery ();
6f431819 21134 int fn_level = oacc_fn_attrib_level (attrs);
21135
21136 if (dump_file)
21137 fprintf (dump_file, oacc_fn_attrib_kernels_p (attrs)
21138 ? "Function is kernels offload\n"
21139 : fn_level < 0 ? "Function is parallel offload\n"
21140 : "Function is routine level %d\n", fn_level);
21141
f4f5b4b4 21142 unsigned outer_mask = fn_level >= 0 ? GOMP_DIM_MASK (fn_level) - 1 : 0;
948eee2f 21143 unsigned used_mask = oacc_loop_partition (loops, outer_mask);
6f431819 21144 int dims[GOMP_DIM_MAX];
948eee2f 21145
21146 oacc_validate_dims (current_function_decl, attrs, dims, fn_level, used_mask);
6f431819 21147
21148 if (dump_file)
21149 {
21150 const char *comma = "Compute dimensions [";
21151 for (int ix = 0; ix != GOMP_DIM_MAX; ix++, comma = ", ")
21152 fprintf (dump_file, "%s%d", comma, dims[ix]);
21153 fprintf (dump_file, "]\n");
21154 }
21155
cbba99a0 21156 oacc_loop_process (loops);
21157 if (dump_file)
21158 {
21159 fprintf (dump_file, "OpenACC loops\n");
21160 dump_oacc_loop (dump_file, loops, 0);
21161 fprintf (dump_file, "\n");
21162 }
21163
641a0fa1 21164 /* Offloaded targets may introduce new basic blocks, which require
21165 dominance information to update SSA. */
21166 calculate_dominance_info (CDI_DOMINATORS);
21167
cbba99a0 21168 /* Now lower internal loop functions to target-specific code
21169 sequences. */
21170 basic_block bb;
21171 FOR_ALL_BB_FN (bb, cfun)
21172 for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);)
21173 {
21174 gimple *stmt = gsi_stmt (gsi);
21175 if (!is_gimple_call (stmt))
21176 {
21177 gsi_next (&gsi);
21178 continue;
21179 }
21180
21181 gcall *call = as_a <gcall *> (stmt);
21182 if (!gimple_call_internal_p (call))
21183 {
21184 gsi_next (&gsi);
21185 continue;
21186 }
21187
21188 /* Rewind to allow rescan. */
21189 gsi_prev (&gsi);
21190 bool rescan = false, remove = false;
21191 enum internal_fn ifn_code = gimple_call_internal_fn (call);
21192
21193 switch (ifn_code)
21194 {
21195 default: break;
21196
21197 case IFN_GOACC_LOOP:
21198 oacc_xform_loop (call);
21199 rescan = true;
21200 break;
21201
641a0fa1 21202 case IFN_GOACC_REDUCTION:
21203 /* Mark the function for SSA renaming. */
21204 mark_virtual_operands_for_renaming (cfun);
21205
21206 /* If the level is -1, this ended up being an unused
21207 axis. Handle as a default. */
21208 if (integer_minus_onep (gimple_call_arg (call, 3)))
21209 default_goacc_reduction (call);
21210 else
21211 targetm.goacc.reduction (call);
21212 rescan = true;
21213 break;
21214
cbba99a0 21215 case IFN_UNIQUE:
21216 {
21217 enum ifn_unique_kind kind
21218 = ((enum ifn_unique_kind)
21219 TREE_INT_CST_LOW (gimple_call_arg (call, 0)));
21220
21221 switch (kind)
21222 {
21223 default:
21224 gcc_unreachable ();
21225
21226 case IFN_UNIQUE_OACC_FORK:
21227 case IFN_UNIQUE_OACC_JOIN:
21228 if (integer_minus_onep (gimple_call_arg (call, 2)))
21229 remove = true;
21230 else if (!targetm.goacc.fork_join
21231 (call, dims, kind == IFN_UNIQUE_OACC_FORK))
21232 remove = true;
21233 break;
21234
21235 case IFN_UNIQUE_OACC_HEAD_MARK:
21236 case IFN_UNIQUE_OACC_TAIL_MARK:
21237 remove = true;
21238 break;
21239 }
21240 break;
21241 }
21242 }
21243
21244 if (gsi_end_p (gsi))
21245 /* We rewound past the beginning of the BB. */
21246 gsi = gsi_start_bb (bb);
21247 else
21248 /* Undo the rewind. */
21249 gsi_next (&gsi);
21250
21251 if (remove)
21252 {
21253 if (gimple_vdef (call))
21254 replace_uses_by (gimple_vdef (call), gimple_vuse (call));
21255 if (gimple_call_lhs (call))
21256 {
21257 /* Propagate the data dependency var. */
21258 gimple *ass = gimple_build_assign (gimple_call_lhs (call),
21259 gimple_call_arg (call, 1));
21260 gsi_replace (&gsi, ass, false);
21261 }
21262 else
21263 gsi_remove (&gsi, true);
21264 }
21265 else if (!rescan)
21266 /* If not rescanning, advance over the call. */
21267 gsi_next (&gsi);
21268 }
21269
21270 free_oacc_loop (loops);
21271
0bb0f256 21272 return 0;
21273}
21274
21275/* Default launch dimension validator. Force everything to 1. A
21276 backend that wants to provide larger dimensions must override this
21277 hook. */
21278
21279bool
21280default_goacc_validate_dims (tree ARG_UNUSED (decl), int *dims,
21281 int ARG_UNUSED (fn_level))
21282{
21283 bool changed = false;
21284
21285 for (unsigned ix = 0; ix != GOMP_DIM_MAX; ix++)
21286 {
21287 if (dims[ix] != 1)
21288 {
21289 dims[ix] = 1;
21290 changed = true;
21291 }
21292 }
21293
21294 return changed;
21295}
21296
e1037942 21297/* Default dimension bound is unknown on accelerator and 1 on host. */
21298
21299int
21300default_goacc_dim_limit (int ARG_UNUSED (axis))
21301{
21302#ifdef ACCEL_COMPILER
21303 return 0;
21304#else
21305 return 1;
21306#endif
21307}
21308
0bb0f256 21309namespace {
21310
21311const pass_data pass_data_oacc_device_lower =
21312{
21313 GIMPLE_PASS, /* type */
21314 "oaccdevlow", /* name */
21315 OPTGROUP_NONE, /* optinfo_flags */
21316 TV_NONE, /* tv_id */
21317 PROP_cfg, /* properties_required */
21318 0 /* Possibly PROP_gimple_eomp. */, /* properties_provided */
21319 0, /* properties_destroyed */
21320 0, /* todo_flags_start */
21321 TODO_update_ssa | TODO_cleanup_cfg, /* todo_flags_finish */
21322};
21323
21324class pass_oacc_device_lower : public gimple_opt_pass
21325{
21326public:
21327 pass_oacc_device_lower (gcc::context *ctxt)
21328 : gimple_opt_pass (pass_data_oacc_device_lower, ctxt)
21329 {}
21330
21331 /* opt_pass methods: */
21332 virtual unsigned int execute (function *)
21333 {
173dfdf5 21334 bool gate = flag_openacc != 0;
0bb0f256 21335
21336 if (!gate)
21337 return 0;
21338
21339 return execute_oacc_device_lower ();
21340 }
21341
f69b8a4c 21342}; // class pass_oacc_device_lower
0bb0f256 21343
21344} // anon namespace
21345
21346gimple_opt_pass *
21347make_pass_oacc_device_lower (gcc::context *ctxt)
21348{
21349 return new pass_oacc_device_lower (ctxt);
21350}
21351
c0998828 21352/* "omp declare target link" handling pass. */
21353
21354namespace {
21355
21356const pass_data pass_data_omp_target_link =
21357{
21358 GIMPLE_PASS, /* type */
21359 "omptargetlink", /* name */
21360 OPTGROUP_NONE, /* optinfo_flags */
21361 TV_NONE, /* tv_id */
21362 PROP_ssa, /* properties_required */
21363 0, /* properties_provided */
21364 0, /* properties_destroyed */
21365 0, /* todo_flags_start */
21366 TODO_update_ssa, /* todo_flags_finish */
21367};
21368
21369class pass_omp_target_link : public gimple_opt_pass
21370{
21371public:
21372 pass_omp_target_link (gcc::context *ctxt)
21373 : gimple_opt_pass (pass_data_omp_target_link, ctxt)
21374 {}
21375
21376 /* opt_pass methods: */
21377 virtual bool gate (function *fun)
21378 {
21379#ifdef ACCEL_COMPILER
21380 tree attrs = DECL_ATTRIBUTES (fun->decl);
21381 return lookup_attribute ("omp declare target", attrs)
21382 || lookup_attribute ("omp target entrypoint", attrs);
21383#else
21384 (void) fun;
21385 return false;
21386#endif
21387 }
21388
21389 virtual unsigned execute (function *);
21390};
21391
21392/* Callback for walk_gimple_stmt used to scan for link var operands. */
21393
21394static tree
21395find_link_var_op (tree *tp, int *walk_subtrees, void *)
21396{
21397 tree t = *tp;
21398
21399 if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t)
21400 && lookup_attribute ("omp declare target link", DECL_ATTRIBUTES (t)))
21401 {
21402 *walk_subtrees = 0;
21403 return t;
21404 }
21405
21406 return NULL_TREE;
21407}
21408
21409unsigned
21410pass_omp_target_link::execute (function *fun)
21411{
21412 basic_block bb;
21413 FOR_EACH_BB_FN (bb, fun)
21414 {
21415 gimple_stmt_iterator gsi;
21416 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
21417 if (walk_gimple_stmt (&gsi, NULL, find_link_var_op, NULL))
21418 gimple_regimplify_operands (gsi_stmt (gsi), &gsi);
21419 }
21420
21421 return 0;
21422}
21423
21424} // anon namespace
21425
21426gimple_opt_pass *
21427make_pass_omp_target_link (gcc::context *ctxt)
21428{
21429 return new pass_omp_target_link (ctxt);
21430}
21431
1e8e9920 21432#include "gt-omp-low.h"