]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/omp-low.c
gcc/c-family/
[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
d353bf18 7 Copyright (C) 2005-2015 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"
1e8e9920 83
ca4c3545 84/* Lowering of OMP parallel and workshare constructs proceeds in two
1e8e9920 85 phases. The first phase scans the function looking for OMP statements
86 and then for variables that must be replaced to satisfy data sharing
87 clauses. The second phase expands code for the constructs, as well as
334ec2d8 88 re-gimplifying things when variables have been replaced with complex
1e8e9920 89 expressions.
90
d134bccc 91 Final code generation is done by pass_expand_omp. The flowgraph is
ca4c3545 92 scanned for regions which are then moved to a new
93 function, to be invoked by the thread library, or offloaded. */
1e8e9920 94
ca4c3545 95/* OMP region information. Every parallel and workshare
7740abd8 96 directive is enclosed between two markers, the OMP_* directive
43895be5 97 and a corresponding GIMPLE_OMP_RETURN statement. */
7740abd8 98
99struct omp_region
100{
101 /* The enclosing region. */
102 struct omp_region *outer;
103
104 /* First child region. */
105 struct omp_region *inner;
106
107 /* Next peer region. */
108 struct omp_region *next;
109
110 /* Block containing the omp directive as its last stmt. */
111 basic_block entry;
112
43895be5 113 /* Block containing the GIMPLE_OMP_RETURN as its last stmt. */
7740abd8 114 basic_block exit;
115
43895be5 116 /* Block containing the GIMPLE_OMP_CONTINUE as its last stmt. */
7740abd8 117 basic_block cont;
118
119 /* If this is a combined parallel+workshare region, this is a list
120 of additional arguments needed by the combined parallel+workshare
121 library call. */
122 vec<tree, va_gc> *ws_args;
123
124 /* The code for the omp directive of this region. */
125 enum gimple_code type;
126
43895be5 127 /* Schedule kind, only used for GIMPLE_OMP_FOR type regions. */
7740abd8 128 enum omp_clause_schedule_kind sched_kind;
129
9561765e 130 /* Schedule modifiers. */
131 unsigned char sched_modifiers;
132
7740abd8 133 /* True if this is a combined parallel+workshare region. */
134 bool is_combined_parallel;
43895be5 135
136 /* The ordered stmt if type is GIMPLE_OMP_ORDERED and it has
137 a depend clause. */
138 gomp_ordered *ord_stmt;
7740abd8 139};
140
1e8e9920 141/* Context structure. Used to store information about each parallel
142 directive in the code. */
143
6dc50383 144struct omp_context
1e8e9920 145{
146 /* This field must be at the beginning, as we do "inheritance": Some
147 callback functions for tree-inline.c (e.g., omp_copy_decl)
148 receive a copy_body_data pointer that is up-casted to an
149 omp_context pointer. */
150 copy_body_data cb;
151
152 /* The tree of contexts corresponding to the encountered constructs. */
153 struct omp_context *outer;
42acab1c 154 gimple *stmt;
1e8e9920 155
48e1416a 156 /* Map variables to fields in a structure that allows communication
1e8e9920 157 between sending and receiving threads. */
158 splay_tree field_map;
159 tree record_type;
160 tree sender_decl;
161 tree receiver_decl;
162
fd6481cf 163 /* These are used just by task contexts, if task firstprivate fn is
164 needed. srecord_type is used to communicate from the thread
165 that encountered the task construct to task firstprivate fn,
166 record_type is allocated by GOMP_task, initialized by task firstprivate
167 fn and passed to the task body fn. */
168 splay_tree sfield_map;
169 tree srecord_type;
170
1e8e9920 171 /* A chain of variables to add to the top-level block surrounding the
172 construct. In the case of a parallel, this is in the child function. */
173 tree block_vars;
174
bc7bff74 175 /* Label to which GOMP_cancel{,llation_point} and explicit and implicit
176 barriers should jump to during omplower pass. */
177 tree cancel_label;
178
1e8e9920 179 /* What to do with variables with implicitly determined sharing
180 attributes. */
181 enum omp_clause_default_kind default_kind;
182
183 /* Nesting depth of this context. Used to beautify error messages re
184 invalid gotos. The outermost ctx is depth 1, with depth 0 being
185 reserved for the main body of the function. */
186 int depth;
187
1e8e9920 188 /* True if this parallel directive is nested within another. */
189 bool is_nested;
bc7bff74 190
191 /* True if this construct can be cancelled. */
192 bool cancellable;
6dc50383 193};
1e8e9920 194
ca4c3545 195/* A structure holding the elements of:
196 for (V = N1; V cond N2; V += STEP) [...] */
1e8e9920 197
fd6481cf 198struct omp_for_data_loop
199{
200 tree v, n1, n2, step;
201 enum tree_code cond_code;
202};
203
773c5ba7 204/* A structure describing the main elements of a parallel loop. */
1e8e9920 205
773c5ba7 206struct omp_for_data
1e8e9920 207{
fd6481cf 208 struct omp_for_data_loop loop;
75a70cf9 209 tree chunk_size;
1a91d914 210 gomp_for *for_stmt;
fd6481cf 211 tree pre, iter_type;
212 int collapse;
43895be5 213 int ordered;
214 bool have_nowait, have_ordered, simd_schedule;
9561765e 215 unsigned char sched_modifiers;
1e8e9920 216 enum omp_clause_schedule_kind sched_kind;
fd6481cf 217 struct omp_for_data_loop *loops;
1e8e9920 218};
219
cbba99a0 220/* Describe the OpenACC looping structure of a function. The entire
221 function is held in a 'NULL' loop. */
222
223struct oacc_loop
224{
225 oacc_loop *parent; /* Containing loop. */
226
227 oacc_loop *child; /* First inner loop. */
228
229 oacc_loop *sibling; /* Next loop within same parent. */
230
231 location_t loc; /* Location of the loop start. */
232
233 gcall *marker; /* Initial head marker. */
234
235 gcall *heads[GOMP_DIM_MAX]; /* Head marker functions. */
236 gcall *tails[GOMP_DIM_MAX]; /* Tail marker functions. */
237
238 tree routine; /* Pseudo-loop enclosing a routine. */
239
240 unsigned mask; /* Partitioning mask. */
241 unsigned flags; /* Partitioning flags. */
242 tree chunk_size; /* Chunk size. */
243 gcall *head_end; /* Final marker of head sequence. */
244};
245
246/* Flags for an OpenACC loop. */
247
248enum oacc_loop_flags {
249 OLF_SEQ = 1u << 0, /* Explicitly sequential */
250 OLF_AUTO = 1u << 1, /* Compiler chooses axes. */
251 OLF_INDEPENDENT = 1u << 2, /* Iterations are known independent. */
252 OLF_GANG_STATIC = 1u << 3, /* Gang partitioning is static (has op). */
253
254 /* Explicitly specified loop axes. */
255 OLF_DIM_BASE = 4,
256 OLF_DIM_GANG = 1u << (OLF_DIM_BASE + GOMP_DIM_GANG),
257 OLF_DIM_WORKER = 1u << (OLF_DIM_BASE + GOMP_DIM_WORKER),
258 OLF_DIM_VECTOR = 1u << (OLF_DIM_BASE + GOMP_DIM_VECTOR),
259
260 OLF_MAX = OLF_DIM_BASE + GOMP_DIM_MAX
261};
262
773c5ba7 263
1e8e9920 264static splay_tree all_contexts;
fd6481cf 265static int taskreg_nesting_level;
bc7bff74 266static int target_nesting_level;
7740abd8 267static struct omp_region *root_omp_region;
fd6481cf 268static bitmap task_shared_vars;
37eaded9 269static vec<omp_context *> taskreg_contexts;
9561765e 270static bool omp_any_child_fn_dumped;
1e8e9920 271
ab129075 272static void scan_omp (gimple_seq *, omp_context *);
75a70cf9 273static tree scan_omp_1_op (tree *, int *, void *);
2131a1a9 274static gphi *find_phi_with_arg_on_edge (tree, edge);
75a70cf9 275
276#define WALK_SUBSTMTS \
277 case GIMPLE_BIND: \
278 case GIMPLE_TRY: \
279 case GIMPLE_CATCH: \
280 case GIMPLE_EH_FILTER: \
4c0315d0 281 case GIMPLE_TRANSACTION: \
75a70cf9 282 /* The sub-statements for these should be walked. */ \
283 *handled_ops_p = false; \
284 break;
285
a8e785ba 286/* Return true if CTX corresponds to an oacc parallel region. */
287
288static bool
289is_oacc_parallel (omp_context *ctx)
290{
291 enum gimple_code outer_type = gimple_code (ctx->stmt);
292 return ((outer_type == GIMPLE_OMP_TARGET)
293 && (gimple_omp_target_kind (ctx->stmt)
294 == GF_OMP_TARGET_KIND_OACC_PARALLEL));
295}
296
297/* Return true if CTX corresponds to an oacc kernels region. */
298
299static bool
300is_oacc_kernels (omp_context *ctx)
301{
302 enum gimple_code outer_type = gimple_code (ctx->stmt);
303 return ((outer_type == GIMPLE_OMP_TARGET)
304 && (gimple_omp_target_kind (ctx->stmt)
305 == GF_OMP_TARGET_KIND_OACC_KERNELS));
306}
307
43895be5 308/* If DECL is the artificial dummy VAR_DECL created for non-static
309 data member privatization, return the underlying "this" parameter,
310 otherwise return NULL. */
311
312tree
313omp_member_access_dummy_var (tree decl)
314{
315 if (!VAR_P (decl)
316 || !DECL_ARTIFICIAL (decl)
317 || !DECL_IGNORED_P (decl)
318 || !DECL_HAS_VALUE_EXPR_P (decl)
319 || !lang_hooks.decls.omp_disregard_value_expr (decl, false))
320 return NULL_TREE;
321
322 tree v = DECL_VALUE_EXPR (decl);
323 if (TREE_CODE (v) != COMPONENT_REF)
324 return NULL_TREE;
325
326 while (1)
327 switch (TREE_CODE (v))
328 {
329 case COMPONENT_REF:
330 case MEM_REF:
331 case INDIRECT_REF:
332 CASE_CONVERT:
333 case POINTER_PLUS_EXPR:
334 v = TREE_OPERAND (v, 0);
335 continue;
336 case PARM_DECL:
337 if (DECL_CONTEXT (v) == current_function_decl
338 && DECL_ARTIFICIAL (v)
339 && TREE_CODE (TREE_TYPE (v)) == POINTER_TYPE)
340 return v;
341 return NULL_TREE;
342 default:
343 return NULL_TREE;
344 }
345}
346
347/* Helper for unshare_and_remap, called through walk_tree. */
348
349static tree
350unshare_and_remap_1 (tree *tp, int *walk_subtrees, void *data)
351{
352 tree *pair = (tree *) data;
353 if (*tp == pair[0])
354 {
355 *tp = unshare_expr (pair[1]);
356 *walk_subtrees = 0;
357 }
358 else if (IS_TYPE_OR_DECL_P (*tp))
359 *walk_subtrees = 0;
360 return NULL_TREE;
361}
362
363/* Return unshare_expr (X) with all occurrences of FROM
364 replaced with TO. */
365
366static tree
367unshare_and_remap (tree x, tree from, tree to)
368{
369 tree pair[2] = { from, to };
370 x = unshare_expr (x);
371 walk_tree (&x, unshare_and_remap_1, pair, NULL);
372 return x;
373}
374
dccabdd1 375/* Holds offload tables with decls. */
376vec<tree, va_gc> *offload_funcs, *offload_vars;
377
75a70cf9 378/* Convenience function for calling scan_omp_1_op on tree operands. */
379
380static inline tree
381scan_omp_op (tree *tp, omp_context *ctx)
382{
383 struct walk_stmt_info wi;
384
385 memset (&wi, 0, sizeof (wi));
386 wi.info = ctx;
387 wi.want_locations = true;
388
389 return walk_tree (tp, scan_omp_1_op, &wi, NULL);
390}
391
e3a19533 392static void lower_omp (gimple_seq *, omp_context *);
f49d7bb5 393static tree lookup_decl_in_outer_ctx (tree, omp_context *);
394static tree maybe_lookup_decl_in_outer_ctx (tree, omp_context *);
1e8e9920 395
ca4c3545 396/* Find an OMP clause of type KIND within CLAUSES. */
1e8e9920 397
79acaae1 398tree
590c3166 399find_omp_clause (tree clauses, enum omp_clause_code kind)
1e8e9920 400{
401 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
55d6e7cd 402 if (OMP_CLAUSE_CODE (clauses) == kind)
1e8e9920 403 return clauses;
404
405 return NULL_TREE;
406}
407
408/* Return true if CTX is for an omp parallel. */
409
410static inline bool
411is_parallel_ctx (omp_context *ctx)
412{
75a70cf9 413 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL;
1e8e9920 414}
415
773c5ba7 416
fd6481cf 417/* Return true if CTX is for an omp task. */
418
419static inline bool
420is_task_ctx (omp_context *ctx)
421{
75a70cf9 422 return gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
fd6481cf 423}
424
425
43895be5 426/* Return true if CTX is for an omp taskloop. */
427
428static inline bool
429is_taskloop_ctx (omp_context *ctx)
430{
431 return gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
432 && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_TASKLOOP;
433}
434
435
fd6481cf 436/* Return true if CTX is for an omp parallel or omp task. */
437
438static inline bool
439is_taskreg_ctx (omp_context *ctx)
440{
43895be5 441 return is_parallel_ctx (ctx) || is_task_ctx (ctx);
fd6481cf 442}
443
444
773c5ba7 445/* Return true if REGION is a combined parallel+workshare region. */
1e8e9920 446
447static inline bool
773c5ba7 448is_combined_parallel (struct omp_region *region)
449{
450 return region->is_combined_parallel;
451}
452
453
454/* Extract the header elements of parallel loop FOR_STMT and store
455 them into *FD. */
456
457static void
1a91d914 458extract_omp_for_data (gomp_for *for_stmt, struct omp_for_data *fd,
fd6481cf 459 struct omp_for_data_loop *loops)
773c5ba7 460{
fd6481cf 461 tree t, var, *collapse_iter, *collapse_count;
462 tree count = NULL_TREE, iter_type = long_integer_type_node;
463 struct omp_for_data_loop *loop;
464 int i;
465 struct omp_for_data_loop dummy_loop;
389dd41b 466 location_t loc = gimple_location (for_stmt);
10c55644 467 bool simd = gimple_omp_for_kind (for_stmt) & GF_OMP_FOR_SIMD;
bc7bff74 468 bool distribute = gimple_omp_for_kind (for_stmt)
469 == GF_OMP_FOR_KIND_DISTRIBUTE;
43895be5 470 bool taskloop = gimple_omp_for_kind (for_stmt)
471 == GF_OMP_FOR_KIND_TASKLOOP;
472 tree iterv, countv;
773c5ba7 473
474 fd->for_stmt = for_stmt;
475 fd->pre = NULL;
43895be5 476 if (gimple_omp_for_collapse (for_stmt) > 1)
fd6481cf 477 fd->loops = loops;
478 else
479 fd->loops = &fd->loop;
773c5ba7 480
bc7bff74 481 fd->have_nowait = distribute || simd;
482 fd->have_ordered = false;
43895be5 483 fd->collapse = 1;
484 fd->ordered = 0;
773c5ba7 485 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
9561765e 486 fd->sched_modifiers = 0;
773c5ba7 487 fd->chunk_size = NULL_TREE;
43895be5 488 fd->simd_schedule = false;
40750995 489 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
490 fd->sched_kind = OMP_CLAUSE_SCHEDULE_CILKFOR;
fd6481cf 491 collapse_iter = NULL;
492 collapse_count = NULL;
773c5ba7 493
75a70cf9 494 for (t = gimple_omp_for_clauses (for_stmt); t ; t = OMP_CLAUSE_CHAIN (t))
55d6e7cd 495 switch (OMP_CLAUSE_CODE (t))
773c5ba7 496 {
497 case OMP_CLAUSE_NOWAIT:
498 fd->have_nowait = true;
499 break;
500 case OMP_CLAUSE_ORDERED:
501 fd->have_ordered = true;
43895be5 502 if (OMP_CLAUSE_ORDERED_EXPR (t))
503 fd->ordered = tree_to_shwi (OMP_CLAUSE_ORDERED_EXPR (t));
773c5ba7 504 break;
505 case OMP_CLAUSE_SCHEDULE:
43895be5 506 gcc_assert (!distribute && !taskloop);
9561765e 507 fd->sched_kind
508 = (enum omp_clause_schedule_kind)
509 (OMP_CLAUSE_SCHEDULE_KIND (t) & OMP_CLAUSE_SCHEDULE_MASK);
510 fd->sched_modifiers = (OMP_CLAUSE_SCHEDULE_KIND (t)
511 & ~OMP_CLAUSE_SCHEDULE_MASK);
773c5ba7 512 fd->chunk_size = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t);
43895be5 513 fd->simd_schedule = OMP_CLAUSE_SCHEDULE_SIMD (t);
773c5ba7 514 break;
bc7bff74 515 case OMP_CLAUSE_DIST_SCHEDULE:
516 gcc_assert (distribute);
517 fd->chunk_size = OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (t);
518 break;
fd6481cf 519 case OMP_CLAUSE_COLLAPSE:
43895be5 520 fd->collapse = tree_to_shwi (OMP_CLAUSE_COLLAPSE_EXPR (t));
fd6481cf 521 if (fd->collapse > 1)
522 {
523 collapse_iter = &OMP_CLAUSE_COLLAPSE_ITERVAR (t);
524 collapse_count = &OMP_CLAUSE_COLLAPSE_COUNT (t);
525 }
757abb46 526 break;
773c5ba7 527 default:
528 break;
529 }
43895be5 530 if (fd->ordered && fd->collapse == 1 && loops != NULL)
531 {
532 fd->loops = loops;
533 iterv = NULL_TREE;
534 countv = NULL_TREE;
535 collapse_iter = &iterv;
536 collapse_count = &countv;
537 }
773c5ba7 538
fd6481cf 539 /* FIXME: for now map schedule(auto) to schedule(static).
540 There should be analysis to determine whether all iterations
541 are approximately the same amount of work (then schedule(static)
bde357c8 542 is best) or if it varies (then schedule(dynamic,N) is better). */
fd6481cf 543 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_AUTO)
544 {
545 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
546 gcc_assert (fd->chunk_size == NULL);
547 }
548 gcc_assert (fd->collapse == 1 || collapse_iter != NULL);
43895be5 549 if (taskloop)
550 fd->sched_kind = OMP_CLAUSE_SCHEDULE_RUNTIME;
773c5ba7 551 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
552 gcc_assert (fd->chunk_size == NULL);
553 else if (fd->chunk_size == NULL)
554 {
555 /* We only need to compute a default chunk size for ordered
556 static loops and dynamic loops. */
fd6481cf 557 if (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
bc7bff74 558 || fd->have_ordered)
773c5ba7 559 fd->chunk_size = (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
560 ? integer_zero_node : integer_one_node;
561 }
fd6481cf 562
43895be5 563 int cnt = fd->ordered ? fd->ordered : fd->collapse;
564 for (i = 0; i < cnt; i++)
fd6481cf 565 {
43895be5 566 if (i == 0 && fd->collapse == 1 && (fd->ordered == 0 || loops == NULL))
fd6481cf 567 loop = &fd->loop;
568 else if (loops != NULL)
569 loop = loops + i;
570 else
571 loop = &dummy_loop;
572
75a70cf9 573 loop->v = gimple_omp_for_index (for_stmt, i);
fd6481cf 574 gcc_assert (SSA_VAR_P (loop->v));
575 gcc_assert (TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
576 || TREE_CODE (TREE_TYPE (loop->v)) == POINTER_TYPE);
577 var = TREE_CODE (loop->v) == SSA_NAME ? SSA_NAME_VAR (loop->v) : loop->v;
75a70cf9 578 loop->n1 = gimple_omp_for_initial (for_stmt, i);
fd6481cf 579
75a70cf9 580 loop->cond_code = gimple_omp_for_cond (for_stmt, i);
581 loop->n2 = gimple_omp_for_final (for_stmt, i);
fd6481cf 582 switch (loop->cond_code)
583 {
584 case LT_EXPR:
585 case GT_EXPR:
586 break;
f2697631 587 case NE_EXPR:
588 gcc_assert (gimple_omp_for_kind (for_stmt)
40750995 589 == GF_OMP_FOR_KIND_CILKSIMD
590 || (gimple_omp_for_kind (for_stmt)
591 == GF_OMP_FOR_KIND_CILKFOR));
f2697631 592 break;
fd6481cf 593 case LE_EXPR:
594 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
2cc66f2a 595 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, 1);
fd6481cf 596 else
389dd41b 597 loop->n2 = fold_build2_loc (loc,
598 PLUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
fd6481cf 599 build_int_cst (TREE_TYPE (loop->n2), 1));
600 loop->cond_code = LT_EXPR;
601 break;
602 case GE_EXPR:
603 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
2cc66f2a 604 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, -1);
fd6481cf 605 else
389dd41b 606 loop->n2 = fold_build2_loc (loc,
607 MINUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
fd6481cf 608 build_int_cst (TREE_TYPE (loop->n2), 1));
609 loop->cond_code = GT_EXPR;
610 break;
611 default:
612 gcc_unreachable ();
613 }
614
75a70cf9 615 t = gimple_omp_for_incr (for_stmt, i);
fd6481cf 616 gcc_assert (TREE_OPERAND (t, 0) == var);
617 switch (TREE_CODE (t))
618 {
619 case PLUS_EXPR:
fd6481cf 620 loop->step = TREE_OPERAND (t, 1);
621 break;
85d86b55 622 case POINTER_PLUS_EXPR:
623 loop->step = fold_convert (ssizetype, TREE_OPERAND (t, 1));
624 break;
fd6481cf 625 case MINUS_EXPR:
626 loop->step = TREE_OPERAND (t, 1);
389dd41b 627 loop->step = fold_build1_loc (loc,
628 NEGATE_EXPR, TREE_TYPE (loop->step),
fd6481cf 629 loop->step);
630 break;
631 default:
632 gcc_unreachable ();
633 }
634
bc7bff74 635 if (simd
636 || (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
637 && !fd->have_ordered))
3d483a94 638 {
639 if (fd->collapse == 1)
640 iter_type = TREE_TYPE (loop->v);
641 else if (i == 0
642 || TYPE_PRECISION (iter_type)
643 < TYPE_PRECISION (TREE_TYPE (loop->v)))
644 iter_type
645 = build_nonstandard_integer_type
bc7bff74 646 (TYPE_PRECISION (TREE_TYPE (loop->v)), 1);
3d483a94 647 }
648 else if (iter_type != long_long_unsigned_type_node)
fd6481cf 649 {
650 if (POINTER_TYPE_P (TREE_TYPE (loop->v)))
651 iter_type = long_long_unsigned_type_node;
652 else if (TYPE_UNSIGNED (TREE_TYPE (loop->v))
653 && TYPE_PRECISION (TREE_TYPE (loop->v))
654 >= TYPE_PRECISION (iter_type))
655 {
656 tree n;
657
658 if (loop->cond_code == LT_EXPR)
389dd41b 659 n = fold_build2_loc (loc,
660 PLUS_EXPR, TREE_TYPE (loop->v),
fd6481cf 661 loop->n2, loop->step);
662 else
663 n = loop->n1;
664 if (TREE_CODE (n) != INTEGER_CST
665 || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type), n))
666 iter_type = long_long_unsigned_type_node;
667 }
668 else if (TYPE_PRECISION (TREE_TYPE (loop->v))
669 > TYPE_PRECISION (iter_type))
670 {
671 tree n1, n2;
672
673 if (loop->cond_code == LT_EXPR)
674 {
675 n1 = loop->n1;
389dd41b 676 n2 = fold_build2_loc (loc,
677 PLUS_EXPR, TREE_TYPE (loop->v),
fd6481cf 678 loop->n2, loop->step);
679 }
680 else
681 {
389dd41b 682 n1 = fold_build2_loc (loc,
683 MINUS_EXPR, TREE_TYPE (loop->v),
fd6481cf 684 loop->n2, loop->step);
685 n2 = loop->n1;
686 }
687 if (TREE_CODE (n1) != INTEGER_CST
688 || TREE_CODE (n2) != INTEGER_CST
689 || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type), n1)
690 || !tree_int_cst_lt (n2, TYPE_MAX_VALUE (iter_type)))
691 iter_type = long_long_unsigned_type_node;
692 }
693 }
694
43895be5 695 if (i >= fd->collapse)
696 continue;
697
fd6481cf 698 if (collapse_count && *collapse_count == NULL)
699 {
8e6b4515 700 t = fold_binary (loop->cond_code, boolean_type_node,
701 fold_convert (TREE_TYPE (loop->v), loop->n1),
702 fold_convert (TREE_TYPE (loop->v), loop->n2));
703 if (t && integer_zerop (t))
704 count = build_zero_cst (long_long_unsigned_type_node);
705 else if ((i == 0 || count != NULL_TREE)
706 && TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
707 && TREE_CONSTANT (loop->n1)
708 && TREE_CONSTANT (loop->n2)
709 && TREE_CODE (loop->step) == INTEGER_CST)
fd6481cf 710 {
711 tree itype = TREE_TYPE (loop->v);
712
713 if (POINTER_TYPE_P (itype))
3cea8318 714 itype = signed_type_for (itype);
fd6481cf 715 t = build_int_cst (itype, (loop->cond_code == LT_EXPR ? -1 : 1));
389dd41b 716 t = fold_build2_loc (loc,
717 PLUS_EXPR, itype,
718 fold_convert_loc (loc, itype, loop->step), t);
719 t = fold_build2_loc (loc, PLUS_EXPR, itype, t,
720 fold_convert_loc (loc, itype, loop->n2));
721 t = fold_build2_loc (loc, MINUS_EXPR, itype, t,
722 fold_convert_loc (loc, itype, loop->n1));
fd6481cf 723 if (TYPE_UNSIGNED (itype) && loop->cond_code == GT_EXPR)
389dd41b 724 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype,
725 fold_build1_loc (loc, NEGATE_EXPR, itype, t),
726 fold_build1_loc (loc, NEGATE_EXPR, itype,
727 fold_convert_loc (loc, itype,
728 loop->step)));
fd6481cf 729 else
389dd41b 730 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, t,
731 fold_convert_loc (loc, itype, loop->step));
732 t = fold_convert_loc (loc, long_long_unsigned_type_node, t);
fd6481cf 733 if (count != NULL_TREE)
389dd41b 734 count = fold_build2_loc (loc,
735 MULT_EXPR, long_long_unsigned_type_node,
fd6481cf 736 count, t);
737 else
738 count = t;
739 if (TREE_CODE (count) != INTEGER_CST)
740 count = NULL_TREE;
741 }
8e6b4515 742 else if (count && !integer_zerop (count))
fd6481cf 743 count = NULL_TREE;
744 }
745 }
746
3d483a94 747 if (count
bc7bff74 748 && !simd
749 && (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
750 || fd->have_ordered))
fd6481cf 751 {
752 if (!tree_int_cst_lt (count, TYPE_MAX_VALUE (long_integer_type_node)))
753 iter_type = long_long_unsigned_type_node;
754 else
755 iter_type = long_integer_type_node;
756 }
757 else if (collapse_iter && *collapse_iter != NULL)
758 iter_type = TREE_TYPE (*collapse_iter);
759 fd->iter_type = iter_type;
760 if (collapse_iter && *collapse_iter == NULL)
761 *collapse_iter = create_tmp_var (iter_type, ".iter");
762 if (collapse_count && *collapse_count == NULL)
763 {
764 if (count)
389dd41b 765 *collapse_count = fold_convert_loc (loc, iter_type, count);
fd6481cf 766 else
767 *collapse_count = create_tmp_var (iter_type, ".count");
768 }
769
43895be5 770 if (fd->collapse > 1 || (fd->ordered && loops))
fd6481cf 771 {
772 fd->loop.v = *collapse_iter;
773 fd->loop.n1 = build_int_cst (TREE_TYPE (fd->loop.v), 0);
774 fd->loop.n2 = *collapse_count;
775 fd->loop.step = build_int_cst (TREE_TYPE (fd->loop.v), 1);
776 fd->loop.cond_code = LT_EXPR;
777 }
43895be5 778 else if (loops)
779 loops[0] = fd->loop;
773c5ba7 780}
781
782
783/* Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB
784 is the immediate dominator of PAR_ENTRY_BB, return true if there
785 are no data dependencies that would prevent expanding the parallel
786 directive at PAR_ENTRY_BB as a combined parallel+workshare region.
787
788 When expanding a combined parallel+workshare region, the call to
789 the child function may need additional arguments in the case of
75a70cf9 790 GIMPLE_OMP_FOR regions. In some cases, these arguments are
791 computed out of variables passed in from the parent to the child
792 via 'struct .omp_data_s'. For instance:
773c5ba7 793
794 #pragma omp parallel for schedule (guided, i * 4)
795 for (j ...)
796
797 Is lowered into:
798
799 # BLOCK 2 (PAR_ENTRY_BB)
800 .omp_data_o.i = i;
801 #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
48e1416a 802
773c5ba7 803 # BLOCK 3 (WS_ENTRY_BB)
804 .omp_data_i = &.omp_data_o;
805 D.1667 = .omp_data_i->i;
806 D.1598 = D.1667 * 4;
807 #pragma omp for schedule (guided, D.1598)
808
809 When we outline the parallel region, the call to the child function
810 'bar.omp_fn.0' will need the value D.1598 in its argument list, but
811 that value is computed *after* the call site. So, in principle we
812 cannot do the transformation.
813
814 To see whether the code in WS_ENTRY_BB blocks the combined
815 parallel+workshare call, we collect all the variables used in the
75a70cf9 816 GIMPLE_OMP_FOR header check whether they appear on the LHS of any
773c5ba7 817 statement in WS_ENTRY_BB. If so, then we cannot emit the combined
818 call.
819
820 FIXME. If we had the SSA form built at this point, we could merely
821 hoist the code in block 3 into block 2 and be done with it. But at
822 this point we don't have dataflow information and though we could
823 hack something up here, it is really not worth the aggravation. */
824
825static bool
f018d957 826workshare_safe_to_combine_p (basic_block ws_entry_bb)
773c5ba7 827{
828 struct omp_for_data fd;
42acab1c 829 gimple *ws_stmt = last_stmt (ws_entry_bb);
773c5ba7 830
75a70cf9 831 if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
773c5ba7 832 return true;
833
75a70cf9 834 gcc_assert (gimple_code (ws_stmt) == GIMPLE_OMP_FOR);
773c5ba7 835
1a91d914 836 extract_omp_for_data (as_a <gomp_for *> (ws_stmt), &fd, NULL);
fd6481cf 837
838 if (fd.collapse > 1 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
839 return false;
840 if (fd.iter_type != long_integer_type_node)
841 return false;
773c5ba7 842
843 /* FIXME. We give up too easily here. If any of these arguments
844 are not constants, they will likely involve variables that have
845 been mapped into fields of .omp_data_s for sharing with the child
846 function. With appropriate data flow, it would be possible to
847 see through this. */
fd6481cf 848 if (!is_gimple_min_invariant (fd.loop.n1)
849 || !is_gimple_min_invariant (fd.loop.n2)
850 || !is_gimple_min_invariant (fd.loop.step)
773c5ba7 851 || (fd.chunk_size && !is_gimple_min_invariant (fd.chunk_size)))
852 return false;
853
854 return true;
855}
856
857
43895be5 858static int omp_max_vf (void);
859
860/* Adjust CHUNK_SIZE from SCHEDULE clause, depending on simd modifier
861 presence (SIMD_SCHEDULE). */
862
863static tree
864omp_adjust_chunk_size (tree chunk_size, bool simd_schedule)
865{
866 if (!simd_schedule)
867 return chunk_size;
868
869 int vf = omp_max_vf ();
870 if (vf == 1)
871 return chunk_size;
872
873 tree type = TREE_TYPE (chunk_size);
874 chunk_size = fold_build2 (PLUS_EXPR, type, chunk_size,
875 build_int_cst (type, vf - 1));
876 return fold_build2 (BIT_AND_EXPR, type, chunk_size,
877 build_int_cst (type, -vf));
878}
879
880
773c5ba7 881/* Collect additional arguments needed to emit a combined
882 parallel+workshare call. WS_STMT is the workshare directive being
883 expanded. */
884
f1f41a6c 885static vec<tree, va_gc> *
42acab1c 886get_ws_args_for (gimple *par_stmt, gimple *ws_stmt)
773c5ba7 887{
888 tree t;
389dd41b 889 location_t loc = gimple_location (ws_stmt);
f1f41a6c 890 vec<tree, va_gc> *ws_args;
773c5ba7 891
1a91d914 892 if (gomp_for *for_stmt = dyn_cast <gomp_for *> (ws_stmt))
773c5ba7 893 {
894 struct omp_for_data fd;
bc7bff74 895 tree n1, n2;
773c5ba7 896
1a91d914 897 extract_omp_for_data (for_stmt, &fd, NULL);
bc7bff74 898 n1 = fd.loop.n1;
899 n2 = fd.loop.n2;
900
1a91d914 901 if (gimple_omp_for_combined_into_p (for_stmt))
bc7bff74 902 {
903 tree innerc
904 = find_omp_clause (gimple_omp_parallel_clauses (par_stmt),
905 OMP_CLAUSE__LOOPTEMP_);
906 gcc_assert (innerc);
907 n1 = OMP_CLAUSE_DECL (innerc);
908 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
909 OMP_CLAUSE__LOOPTEMP_);
910 gcc_assert (innerc);
911 n2 = OMP_CLAUSE_DECL (innerc);
912 }
773c5ba7 913
f1f41a6c 914 vec_alloc (ws_args, 3 + (fd.chunk_size != 0));
773c5ba7 915
bc7bff74 916 t = fold_convert_loc (loc, long_integer_type_node, n1);
f1f41a6c 917 ws_args->quick_push (t);
773c5ba7 918
bc7bff74 919 t = fold_convert_loc (loc, long_integer_type_node, n2);
f1f41a6c 920 ws_args->quick_push (t);
773c5ba7 921
414c3a2c 922 t = fold_convert_loc (loc, long_integer_type_node, fd.loop.step);
f1f41a6c 923 ws_args->quick_push (t);
414c3a2c 924
925 if (fd.chunk_size)
926 {
927 t = fold_convert_loc (loc, long_integer_type_node, fd.chunk_size);
43895be5 928 t = omp_adjust_chunk_size (t, fd.simd_schedule);
f1f41a6c 929 ws_args->quick_push (t);
414c3a2c 930 }
773c5ba7 931
932 return ws_args;
933 }
75a70cf9 934 else if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
773c5ba7 935 {
ac6e3339 936 /* Number of sections is equal to the number of edges from the
75a70cf9 937 GIMPLE_OMP_SECTIONS_SWITCH statement, except for the one to
938 the exit of the sections region. */
939 basic_block bb = single_succ (gimple_bb (ws_stmt));
ac6e3339 940 t = build_int_cst (unsigned_type_node, EDGE_COUNT (bb->succs) - 1);
f1f41a6c 941 vec_alloc (ws_args, 1);
942 ws_args->quick_push (t);
414c3a2c 943 return ws_args;
773c5ba7 944 }
945
946 gcc_unreachable ();
947}
948
949
950/* Discover whether REGION is a combined parallel+workshare region. */
951
952static void
953determine_parallel_type (struct omp_region *region)
1e8e9920 954{
773c5ba7 955 basic_block par_entry_bb, par_exit_bb;
956 basic_block ws_entry_bb, ws_exit_bb;
957
03ed154b 958 if (region == NULL || region->inner == NULL
ac6e3339 959 || region->exit == NULL || region->inner->exit == NULL
960 || region->inner->cont == NULL)
773c5ba7 961 return;
962
963 /* We only support parallel+for and parallel+sections. */
75a70cf9 964 if (region->type != GIMPLE_OMP_PARALLEL
965 || (region->inner->type != GIMPLE_OMP_FOR
966 && region->inner->type != GIMPLE_OMP_SECTIONS))
773c5ba7 967 return;
968
969 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
970 WS_EXIT_BB -> PAR_EXIT_BB. */
61e47ac8 971 par_entry_bb = region->entry;
972 par_exit_bb = region->exit;
973 ws_entry_bb = region->inner->entry;
974 ws_exit_bb = region->inner->exit;
773c5ba7 975
976 if (single_succ (par_entry_bb) == ws_entry_bb
977 && single_succ (ws_exit_bb) == par_exit_bb
f018d957 978 && workshare_safe_to_combine_p (ws_entry_bb)
75a70cf9 979 && (gimple_omp_parallel_combined_p (last_stmt (par_entry_bb))
de7ef844 980 || (last_and_only_stmt (ws_entry_bb)
981 && last_and_only_stmt (par_exit_bb))))
773c5ba7 982 {
42acab1c 983 gimple *par_stmt = last_stmt (par_entry_bb);
984 gimple *ws_stmt = last_stmt (ws_entry_bb);
61e47ac8 985
75a70cf9 986 if (region->inner->type == GIMPLE_OMP_FOR)
773c5ba7 987 {
988 /* If this is a combined parallel loop, we need to determine
989 whether or not to use the combined library calls. There
990 are two cases where we do not apply the transformation:
991 static loops and any kind of ordered loop. In the first
992 case, we already open code the loop so there is no need
993 to do anything else. In the latter case, the combined
994 parallel loop call would still need extra synchronization
995 to implement ordered semantics, so there would not be any
996 gain in using the combined call. */
75a70cf9 997 tree clauses = gimple_omp_for_clauses (ws_stmt);
773c5ba7 998 tree c = find_omp_clause (clauses, OMP_CLAUSE_SCHEDULE);
999 if (c == NULL
9561765e 1000 || ((OMP_CLAUSE_SCHEDULE_KIND (c) & OMP_CLAUSE_SCHEDULE_MASK)
1001 == OMP_CLAUSE_SCHEDULE_STATIC)
773c5ba7 1002 || find_omp_clause (clauses, OMP_CLAUSE_ORDERED))
1003 {
1004 region->is_combined_parallel = false;
1005 region->inner->is_combined_parallel = false;
1006 return;
1007 }
1008 }
1009
1010 region->is_combined_parallel = true;
1011 region->inner->is_combined_parallel = true;
bc7bff74 1012 region->ws_args = get_ws_args_for (par_stmt, ws_stmt);
773c5ba7 1013 }
1e8e9920 1014}
1015
773c5ba7 1016
1e8e9920 1017/* Return true if EXPR is variable sized. */
1018
1019static inline bool
1f1872fd 1020is_variable_sized (const_tree expr)
1e8e9920 1021{
1022 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr)));
1023}
1024
1025/* Return true if DECL is a reference type. */
1026
1027static inline bool
1028is_reference (tree decl)
1029{
1030 return lang_hooks.decls.omp_privatize_by_reference (decl);
1031}
1032
ca4c3545 1033/* Return the type of a decl. If the decl is reference type,
1034 return its base type. */
1035static inline tree
1036get_base_type (tree decl)
1037{
1038 tree type = TREE_TYPE (decl);
1039 if (is_reference (decl))
1040 type = TREE_TYPE (type);
1041 return type;
1042}
1043
1044/* Lookup variables. The "maybe" form
1e8e9920 1045 allows for the variable form to not have been entered, otherwise we
1046 assert that the variable must have been entered. */
1047
1048static inline tree
1049lookup_decl (tree var, omp_context *ctx)
1050{
06ecf488 1051 tree *n = ctx->cb.decl_map->get (var);
e3022db7 1052 return *n;
1e8e9920 1053}
1054
1055static inline tree
e8a588af 1056maybe_lookup_decl (const_tree var, omp_context *ctx)
1e8e9920 1057{
06ecf488 1058 tree *n = ctx->cb.decl_map->get (const_cast<tree> (var));
e3022db7 1059 return n ? *n : NULL_TREE;
1e8e9920 1060}
1061
1062static inline tree
1063lookup_field (tree var, omp_context *ctx)
1064{
1065 splay_tree_node n;
1066 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
1067 return (tree) n->value;
1068}
1069
fd6481cf 1070static inline tree
43895be5 1071lookup_sfield (splay_tree_key key, omp_context *ctx)
fd6481cf 1072{
1073 splay_tree_node n;
1074 n = splay_tree_lookup (ctx->sfield_map
43895be5 1075 ? ctx->sfield_map : ctx->field_map, key);
fd6481cf 1076 return (tree) n->value;
1077}
1078
1e8e9920 1079static inline tree
43895be5 1080lookup_sfield (tree var, omp_context *ctx)
1081{
1082 return lookup_sfield ((splay_tree_key) var, ctx);
1083}
1084
1085static inline tree
1086maybe_lookup_field (splay_tree_key key, omp_context *ctx)
1e8e9920 1087{
1088 splay_tree_node n;
43895be5 1089 n = splay_tree_lookup (ctx->field_map, key);
1e8e9920 1090 return n ? (tree) n->value : NULL_TREE;
1091}
1092
43895be5 1093static inline tree
1094maybe_lookup_field (tree var, omp_context *ctx)
1095{
1096 return maybe_lookup_field ((splay_tree_key) var, ctx);
1097}
1098
e8a588af 1099/* Return true if DECL should be copied by pointer. SHARED_CTX is
1100 the parallel context if DECL is to be shared. */
1e8e9920 1101
1102static bool
fd6481cf 1103use_pointer_for_field (tree decl, omp_context *shared_ctx)
1e8e9920 1104{
1105 if (AGGREGATE_TYPE_P (TREE_TYPE (decl)))
1106 return true;
1107
554f2707 1108 /* We can only use copy-in/copy-out semantics for shared variables
1e8e9920 1109 when we know the value is not accessible from an outer scope. */
e8a588af 1110 if (shared_ctx)
1e8e9920 1111 {
ca4c3545 1112 gcc_assert (!is_gimple_omp_oacc (shared_ctx->stmt));
1113
1e8e9920 1114 /* ??? Trivially accessible from anywhere. But why would we even
1115 be passing an address in this case? Should we simply assert
1116 this to be false, or should we have a cleanup pass that removes
1117 these from the list of mappings? */
1118 if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
1119 return true;
1120
1121 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
1122 without analyzing the expression whether or not its location
1123 is accessible to anyone else. In the case of nested parallel
1124 regions it certainly may be. */
df2c34fc 1125 if (TREE_CODE (decl) != RESULT_DECL && DECL_HAS_VALUE_EXPR_P (decl))
1e8e9920 1126 return true;
1127
1128 /* Do not use copy-in/copy-out for variables that have their
1129 address taken. */
1130 if (TREE_ADDRESSABLE (decl))
1131 return true;
e8a588af 1132
b8214689 1133 /* lower_send_shared_vars only uses copy-in, but not copy-out
1134 for these. */
1135 if (TREE_READONLY (decl)
1136 || ((TREE_CODE (decl) == RESULT_DECL
1137 || TREE_CODE (decl) == PARM_DECL)
1138 && DECL_BY_REFERENCE (decl)))
1139 return false;
1140
e8a588af 1141 /* Disallow copy-in/out in nested parallel if
1142 decl is shared in outer parallel, otherwise
1143 each thread could store the shared variable
1144 in its own copy-in location, making the
1145 variable no longer really shared. */
b8214689 1146 if (shared_ctx->is_nested)
e8a588af 1147 {
1148 omp_context *up;
1149
1150 for (up = shared_ctx->outer; up; up = up->outer)
0cb159ec 1151 if (is_taskreg_ctx (up) && maybe_lookup_decl (decl, up))
e8a588af 1152 break;
1153
0cb159ec 1154 if (up)
e8a588af 1155 {
1156 tree c;
1157
75a70cf9 1158 for (c = gimple_omp_taskreg_clauses (up->stmt);
e8a588af 1159 c; c = OMP_CLAUSE_CHAIN (c))
1160 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
1161 && OMP_CLAUSE_DECL (c) == decl)
1162 break;
1163
1164 if (c)
784ad964 1165 goto maybe_mark_addressable_and_ret;
e8a588af 1166 }
1167 }
fd6481cf 1168
b8214689 1169 /* For tasks avoid using copy-in/out. As tasks can be
fd6481cf 1170 deferred or executed in different thread, when GOMP_task
1171 returns, the task hasn't necessarily terminated. */
b8214689 1172 if (is_task_ctx (shared_ctx))
fd6481cf 1173 {
784ad964 1174 tree outer;
1175 maybe_mark_addressable_and_ret:
1176 outer = maybe_lookup_decl_in_outer_ctx (decl, shared_ctx);
43895be5 1177 if (is_gimple_reg (outer) && !omp_member_access_dummy_var (outer))
fd6481cf 1178 {
1179 /* Taking address of OUTER in lower_send_shared_vars
1180 might need regimplification of everything that uses the
1181 variable. */
1182 if (!task_shared_vars)
1183 task_shared_vars = BITMAP_ALLOC (NULL);
1184 bitmap_set_bit (task_shared_vars, DECL_UID (outer));
1185 TREE_ADDRESSABLE (outer) = 1;
1186 }
1187 return true;
1188 }
1e8e9920 1189 }
1190
1191 return false;
1192}
1193
79acaae1 1194/* Construct a new automatic decl similar to VAR. */
1195
1196static tree
1197omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx)
1198{
1199 tree copy = copy_var_decl (var, name, type);
1200
1201 DECL_CONTEXT (copy) = current_function_decl;
1767a056 1202 DECL_CHAIN (copy) = ctx->block_vars;
43895be5 1203 /* If VAR is listed in task_shared_vars, it means it wasn't
1204 originally addressable and is just because task needs to take
1205 it's address. But we don't need to take address of privatizations
1206 from that var. */
1207 if (TREE_ADDRESSABLE (var)
1208 && task_shared_vars
1209 && bitmap_bit_p (task_shared_vars, DECL_UID (var)))
1210 TREE_ADDRESSABLE (copy) = 0;
1e8e9920 1211 ctx->block_vars = copy;
1212
1213 return copy;
1214}
1215
1216static tree
1217omp_copy_decl_1 (tree var, omp_context *ctx)
1218{
1219 return omp_copy_decl_2 (var, DECL_NAME (var), TREE_TYPE (var), ctx);
1220}
1221
445d06b6 1222/* Build COMPONENT_REF and set TREE_THIS_VOLATILE and TREE_READONLY on it
1223 as appropriate. */
1224static tree
1225omp_build_component_ref (tree obj, tree field)
1226{
1227 tree ret = build3 (COMPONENT_REF, TREE_TYPE (field), obj, field, NULL);
1228 if (TREE_THIS_VOLATILE (field))
1229 TREE_THIS_VOLATILE (ret) |= 1;
1230 if (TREE_READONLY (field))
1231 TREE_READONLY (ret) |= 1;
1232 return ret;
1233}
1234
1e8e9920 1235/* Build tree nodes to access the field for VAR on the receiver side. */
1236
1237static tree
1238build_receiver_ref (tree var, bool by_ref, omp_context *ctx)
1239{
1240 tree x, field = lookup_field (var, ctx);
1241
1242 /* If the receiver record type was remapped in the child function,
1243 remap the field into the new record type. */
1244 x = maybe_lookup_field (field, ctx);
1245 if (x != NULL)
1246 field = x;
1247
182cf5a9 1248 x = build_simple_mem_ref (ctx->receiver_decl);
75c20a2e 1249 TREE_THIS_NOTRAP (x) = 1;
445d06b6 1250 x = omp_build_component_ref (x, field);
1e8e9920 1251 if (by_ref)
b16d27b9 1252 {
1253 x = build_simple_mem_ref (x);
1254 TREE_THIS_NOTRAP (x) = 1;
1255 }
1e8e9920 1256
1257 return x;
1258}
1259
1260/* Build tree nodes to access VAR in the scope outer to CTX. In the case
1261 of a parallel, this is a component reference; for workshare constructs
1262 this is some variable. */
1263
1264static tree
43895be5 1265build_outer_var_ref (tree var, omp_context *ctx, bool lastprivate = false)
1e8e9920 1266{
1267 tree x;
1268
f49d7bb5 1269 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx)))
1e8e9920 1270 x = var;
1271 else if (is_variable_sized (var))
1272 {
1273 x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
43895be5 1274 x = build_outer_var_ref (x, ctx, lastprivate);
182cf5a9 1275 x = build_simple_mem_ref (x);
1e8e9920 1276 }
fd6481cf 1277 else if (is_taskreg_ctx (ctx))
1e8e9920 1278 {
e8a588af 1279 bool by_ref = use_pointer_for_field (var, NULL);
1e8e9920 1280 x = build_receiver_ref (var, by_ref, ctx);
1281 }
3d483a94 1282 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
10c55644 1283 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3d483a94 1284 {
1285 /* #pragma omp simd isn't a worksharing construct, and can reference even
1286 private vars in its linear etc. clauses. */
1287 x = NULL_TREE;
1288 if (ctx->outer && is_taskreg_ctx (ctx))
1289 x = lookup_decl (var, ctx->outer);
1290 else if (ctx->outer)
84cb1020 1291 x = maybe_lookup_decl_in_outer_ctx (var, ctx);
3d483a94 1292 if (x == NULL_TREE)
1293 x = var;
1294 }
43895be5 1295 else if (lastprivate && is_taskloop_ctx (ctx))
1296 {
1297 gcc_assert (ctx->outer);
1298 splay_tree_node n
1299 = splay_tree_lookup (ctx->outer->field_map,
1300 (splay_tree_key) &DECL_UID (var));
1301 if (n == NULL)
1302 {
1303 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx->outer)))
1304 x = var;
1305 else
1306 x = lookup_decl (var, ctx->outer);
1307 }
1308 else
1309 {
1310 tree field = (tree) n->value;
1311 /* If the receiver record type was remapped in the child function,
1312 remap the field into the new record type. */
1313 x = maybe_lookup_field (field, ctx->outer);
1314 if (x != NULL)
1315 field = x;
1316
1317 x = build_simple_mem_ref (ctx->outer->receiver_decl);
1318 x = omp_build_component_ref (x, field);
1319 if (use_pointer_for_field (var, ctx->outer))
1320 x = build_simple_mem_ref (x);
1321 }
1322 }
1e8e9920 1323 else if (ctx->outer)
1324 x = lookup_decl (var, ctx->outer);
9438af57 1325 else if (is_reference (var))
1326 /* This can happen with orphaned constructs. If var is reference, it is
1327 possible it is shared and as such valid. */
1328 x = var;
43895be5 1329 else if (omp_member_access_dummy_var (var))
1330 x = var;
1e8e9920 1331 else
1332 gcc_unreachable ();
1333
43895be5 1334 if (x == var)
1335 {
1336 tree t = omp_member_access_dummy_var (var);
1337 if (t)
1338 {
1339 x = DECL_VALUE_EXPR (var);
1340 tree o = maybe_lookup_decl_in_outer_ctx (t, ctx);
1341 if (o != t)
1342 x = unshare_and_remap (x, t, o);
1343 else
1344 x = unshare_expr (x);
1345 }
1346 }
1347
1e8e9920 1348 if (is_reference (var))
182cf5a9 1349 x = build_simple_mem_ref (x);
1e8e9920 1350
1351 return x;
1352}
1353
1354/* Build tree nodes to access the field for VAR on the sender side. */
1355
1356static tree
43895be5 1357build_sender_ref (splay_tree_key key, omp_context *ctx)
1e8e9920 1358{
43895be5 1359 tree field = lookup_sfield (key, ctx);
445d06b6 1360 return omp_build_component_ref (ctx->sender_decl, field);
1e8e9920 1361}
1362
43895be5 1363static tree
1364build_sender_ref (tree var, omp_context *ctx)
1365{
1366 return build_sender_ref ((splay_tree_key) var, ctx);
1367}
1368
12dc9a16 1369/* Add a new field for VAR inside the structure CTX->SENDER_DECL. If
1370 BASE_POINTERS_RESTRICT, declare the field with restrict. */
1e8e9920 1371
1372static void
12dc9a16 1373install_var_field (tree var, bool by_ref, int mask, omp_context *ctx,
1374 bool base_pointers_restrict = false)
1e8e9920 1375{
fd6481cf 1376 tree field, type, sfield = NULL_TREE;
43895be5 1377 splay_tree_key key = (splay_tree_key) var;
1e8e9920 1378
43895be5 1379 if ((mask & 8) != 0)
1380 {
1381 key = (splay_tree_key) &DECL_UID (var);
1382 gcc_checking_assert (key != (splay_tree_key) var);
1383 }
fd6481cf 1384 gcc_assert ((mask & 1) == 0
43895be5 1385 || !splay_tree_lookup (ctx->field_map, key));
fd6481cf 1386 gcc_assert ((mask & 2) == 0 || !ctx->sfield_map
43895be5 1387 || !splay_tree_lookup (ctx->sfield_map, key));
ca4c3545 1388 gcc_assert ((mask & 3) == 3
1389 || !is_gimple_omp_oacc (ctx->stmt));
1e8e9920 1390
1391 type = TREE_TYPE (var);
44c0112f 1392 /* Prevent redeclaring the var in the split-off function with a restrict
1393 pointer type. Note that we only clear type itself, restrict qualifiers in
1394 the pointed-to type will be ignored by points-to analysis. */
1395 if (POINTER_TYPE_P (type)
1396 && TYPE_RESTRICT (type))
1397 type = build_qualified_type (type, TYPE_QUALS (type) & ~TYPE_QUAL_RESTRICT);
1398
bc7bff74 1399 if (mask & 4)
1400 {
1401 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
1402 type = build_pointer_type (build_pointer_type (type));
1403 }
1404 else if (by_ref)
12dc9a16 1405 {
1406 type = build_pointer_type (type);
1407 if (base_pointers_restrict)
1408 type = build_qualified_type (type, TYPE_QUAL_RESTRICT);
1409 }
fd6481cf 1410 else if ((mask & 3) == 1 && is_reference (var))
1411 type = TREE_TYPE (type);
1e8e9920 1412
e60a6f7b 1413 field = build_decl (DECL_SOURCE_LOCATION (var),
1414 FIELD_DECL, DECL_NAME (var), type);
1e8e9920 1415
1416 /* Remember what variable this field was created for. This does have a
1417 side effect of making dwarf2out ignore this member, so for helpful
1418 debugging we clear it later in delete_omp_context. */
1419 DECL_ABSTRACT_ORIGIN (field) = var;
fd6481cf 1420 if (type == TREE_TYPE (var))
1421 {
1422 DECL_ALIGN (field) = DECL_ALIGN (var);
1423 DECL_USER_ALIGN (field) = DECL_USER_ALIGN (var);
1424 TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (var);
1425 }
1426 else
1427 DECL_ALIGN (field) = TYPE_ALIGN (type);
1e8e9920 1428
fd6481cf 1429 if ((mask & 3) == 3)
1430 {
1431 insert_field_into_struct (ctx->record_type, field);
1432 if (ctx->srecord_type)
1433 {
e60a6f7b 1434 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1435 FIELD_DECL, DECL_NAME (var), type);
fd6481cf 1436 DECL_ABSTRACT_ORIGIN (sfield) = var;
1437 DECL_ALIGN (sfield) = DECL_ALIGN (field);
1438 DECL_USER_ALIGN (sfield) = DECL_USER_ALIGN (field);
1439 TREE_THIS_VOLATILE (sfield) = TREE_THIS_VOLATILE (field);
1440 insert_field_into_struct (ctx->srecord_type, sfield);
1441 }
1442 }
1443 else
1444 {
1445 if (ctx->srecord_type == NULL_TREE)
1446 {
1447 tree t;
1448
1449 ctx->srecord_type = lang_hooks.types.make_type (RECORD_TYPE);
1450 ctx->sfield_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1451 for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
1452 {
43895be5 1453 sfield = build_decl (DECL_SOURCE_LOCATION (t),
e60a6f7b 1454 FIELD_DECL, DECL_NAME (t), TREE_TYPE (t));
fd6481cf 1455 DECL_ABSTRACT_ORIGIN (sfield) = DECL_ABSTRACT_ORIGIN (t);
1456 insert_field_into_struct (ctx->srecord_type, sfield);
1457 splay_tree_insert (ctx->sfield_map,
1458 (splay_tree_key) DECL_ABSTRACT_ORIGIN (t),
1459 (splay_tree_value) sfield);
1460 }
1461 }
1462 sfield = field;
1463 insert_field_into_struct ((mask & 1) ? ctx->record_type
1464 : ctx->srecord_type, field);
1465 }
1e8e9920 1466
fd6481cf 1467 if (mask & 1)
43895be5 1468 splay_tree_insert (ctx->field_map, key, (splay_tree_value) field);
fd6481cf 1469 if ((mask & 2) && ctx->sfield_map)
43895be5 1470 splay_tree_insert (ctx->sfield_map, key, (splay_tree_value) sfield);
1e8e9920 1471}
1472
1473static tree
1474install_var_local (tree var, omp_context *ctx)
1475{
1476 tree new_var = omp_copy_decl_1 (var, ctx);
1477 insert_decl_map (&ctx->cb, var, new_var);
1478 return new_var;
1479}
1480
1481/* Adjust the replacement for DECL in CTX for the new context. This means
1482 copying the DECL_VALUE_EXPR, and fixing up the type. */
1483
1484static void
1485fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug)
1486{
1487 tree new_decl, size;
1488
1489 new_decl = lookup_decl (decl, ctx);
1490
1491 TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb);
1492
1493 if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug)
1494 && DECL_HAS_VALUE_EXPR_P (decl))
1495 {
1496 tree ve = DECL_VALUE_EXPR (decl);
75a70cf9 1497 walk_tree (&ve, copy_tree_body_r, &ctx->cb, NULL);
1e8e9920 1498 SET_DECL_VALUE_EXPR (new_decl, ve);
1499 DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
1500 }
1501
1502 if (!TREE_CONSTANT (DECL_SIZE (new_decl)))
1503 {
1504 size = remap_decl (DECL_SIZE (decl), &ctx->cb);
1505 if (size == error_mark_node)
1506 size = TYPE_SIZE (TREE_TYPE (new_decl));
1507 DECL_SIZE (new_decl) = size;
1508
1509 size = remap_decl (DECL_SIZE_UNIT (decl), &ctx->cb);
1510 if (size == error_mark_node)
1511 size = TYPE_SIZE_UNIT (TREE_TYPE (new_decl));
1512 DECL_SIZE_UNIT (new_decl) = size;
1513 }
1514}
1515
1516/* The callback for remap_decl. Search all containing contexts for a
1517 mapping of the variable; this avoids having to duplicate the splay
1518 tree ahead of time. We know a mapping doesn't already exist in the
1519 given context. Create new mappings to implement default semantics. */
1520
1521static tree
1522omp_copy_decl (tree var, copy_body_data *cb)
1523{
1524 omp_context *ctx = (omp_context *) cb;
1525 tree new_var;
1526
1e8e9920 1527 if (TREE_CODE (var) == LABEL_DECL)
1528 {
e60a6f7b 1529 new_var = create_artificial_label (DECL_SOURCE_LOCATION (var));
773c5ba7 1530 DECL_CONTEXT (new_var) = current_function_decl;
1e8e9920 1531 insert_decl_map (&ctx->cb, var, new_var);
1532 return new_var;
1533 }
1534
fd6481cf 1535 while (!is_taskreg_ctx (ctx))
1e8e9920 1536 {
1537 ctx = ctx->outer;
1538 if (ctx == NULL)
1539 return var;
1540 new_var = maybe_lookup_decl (var, ctx);
1541 if (new_var)
1542 return new_var;
1543 }
1544
f49d7bb5 1545 if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn)
1546 return var;
1547
1e8e9920 1548 return error_mark_node;
1549}
1550
773c5ba7 1551
773c5ba7 1552/* Debugging dumps for parallel regions. */
1553void dump_omp_region (FILE *, struct omp_region *, int);
1554void debug_omp_region (struct omp_region *);
1555void debug_all_omp_regions (void);
1556
1557/* Dump the parallel region tree rooted at REGION. */
1558
1559void
1560dump_omp_region (FILE *file, struct omp_region *region, int indent)
1561{
61e47ac8 1562 fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index,
75a70cf9 1563 gimple_code_name[region->type]);
773c5ba7 1564
1565 if (region->inner)
1566 dump_omp_region (file, region->inner, indent + 4);
1567
61e47ac8 1568 if (region->cont)
1569 {
75a70cf9 1570 fprintf (file, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent, "",
61e47ac8 1571 region->cont->index);
1572 }
48e1416a 1573
773c5ba7 1574 if (region->exit)
75a70cf9 1575 fprintf (file, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent, "",
61e47ac8 1576 region->exit->index);
773c5ba7 1577 else
61e47ac8 1578 fprintf (file, "%*s[no exit marker]\n", indent, "");
773c5ba7 1579
1580 if (region->next)
61e47ac8 1581 dump_omp_region (file, region->next, indent);
773c5ba7 1582}
1583
4b987fac 1584DEBUG_FUNCTION void
773c5ba7 1585debug_omp_region (struct omp_region *region)
1586{
1587 dump_omp_region (stderr, region, 0);
1588}
1589
4b987fac 1590DEBUG_FUNCTION void
773c5ba7 1591debug_all_omp_regions (void)
1592{
1593 dump_omp_region (stderr, root_omp_region, 0);
1594}
1595
1596
1597/* Create a new parallel region starting at STMT inside region PARENT. */
1598
7740abd8 1599static struct omp_region *
75a70cf9 1600new_omp_region (basic_block bb, enum gimple_code type,
1601 struct omp_region *parent)
773c5ba7 1602{
4077bf7a 1603 struct omp_region *region = XCNEW (struct omp_region);
773c5ba7 1604
1605 region->outer = parent;
61e47ac8 1606 region->entry = bb;
1607 region->type = type;
773c5ba7 1608
1609 if (parent)
1610 {
1611 /* This is a nested region. Add it to the list of inner
1612 regions in PARENT. */
1613 region->next = parent->inner;
1614 parent->inner = region;
1615 }
61e47ac8 1616 else
773c5ba7 1617 {
1618 /* This is a toplevel region. Add it to the list of toplevel
1619 regions in ROOT_OMP_REGION. */
1620 region->next = root_omp_region;
1621 root_omp_region = region;
1622 }
61e47ac8 1623
1624 return region;
1625}
1626
1627/* Release the memory associated with the region tree rooted at REGION. */
1628
1629static void
1630free_omp_region_1 (struct omp_region *region)
1631{
1632 struct omp_region *i, *n;
1633
1634 for (i = region->inner; i ; i = n)
773c5ba7 1635 {
61e47ac8 1636 n = i->next;
1637 free_omp_region_1 (i);
773c5ba7 1638 }
1639
61e47ac8 1640 free (region);
1641}
773c5ba7 1642
61e47ac8 1643/* Release the memory for the entire omp region tree. */
1644
1645void
1646free_omp_regions (void)
1647{
1648 struct omp_region *r, *n;
1649 for (r = root_omp_region; r ; r = n)
1650 {
1651 n = r->next;
1652 free_omp_region_1 (r);
1653 }
1654 root_omp_region = NULL;
773c5ba7 1655}
1656
1657
1e8e9920 1658/* Create a new context, with OUTER_CTX being the surrounding context. */
1659
1660static omp_context *
42acab1c 1661new_omp_context (gimple *stmt, omp_context *outer_ctx)
1e8e9920 1662{
1663 omp_context *ctx = XCNEW (omp_context);
1664
1665 splay_tree_insert (all_contexts, (splay_tree_key) stmt,
1666 (splay_tree_value) ctx);
1667 ctx->stmt = stmt;
1668
1669 if (outer_ctx)
1670 {
1671 ctx->outer = outer_ctx;
1672 ctx->cb = outer_ctx->cb;
1673 ctx->cb.block = NULL;
1674 ctx->depth = outer_ctx->depth + 1;
1675 }
1676 else
1677 {
1678 ctx->cb.src_fn = current_function_decl;
1679 ctx->cb.dst_fn = current_function_decl;
415d1b9a 1680 ctx->cb.src_node = cgraph_node::get (current_function_decl);
53f79206 1681 gcc_checking_assert (ctx->cb.src_node);
1e8e9920 1682 ctx->cb.dst_node = ctx->cb.src_node;
1683 ctx->cb.src_cfun = cfun;
1684 ctx->cb.copy_decl = omp_copy_decl;
e38def9c 1685 ctx->cb.eh_lp_nr = 0;
1e8e9920 1686 ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
1687 ctx->depth = 1;
1688 }
1689
06ecf488 1690 ctx->cb.decl_map = new hash_map<tree, tree>;
1e8e9920 1691
1692 return ctx;
1693}
1694
75a70cf9 1695static gimple_seq maybe_catch_exception (gimple_seq);
f6430caa 1696
1697/* Finalize task copyfn. */
1698
1699static void
1a91d914 1700finalize_task_copyfn (gomp_task *task_stmt)
f6430caa 1701{
1702 struct function *child_cfun;
9078126c 1703 tree child_fn;
e3a19533 1704 gimple_seq seq = NULL, new_seq;
1a91d914 1705 gbind *bind;
f6430caa 1706
75a70cf9 1707 child_fn = gimple_omp_task_copy_fn (task_stmt);
f6430caa 1708 if (child_fn == NULL_TREE)
1709 return;
1710
1711 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
82b40354 1712 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
f6430caa 1713
f6430caa 1714 push_cfun (child_cfun);
7e3aae05 1715 bind = gimplify_body (child_fn, false);
75a70cf9 1716 gimple_seq_add_stmt (&seq, bind);
1717 new_seq = maybe_catch_exception (seq);
1718 if (new_seq != seq)
1719 {
1720 bind = gimple_build_bind (NULL, new_seq, NULL);
e3a19533 1721 seq = NULL;
75a70cf9 1722 gimple_seq_add_stmt (&seq, bind);
1723 }
1724 gimple_set_body (child_fn, seq);
f6430caa 1725 pop_cfun ();
f6430caa 1726
82b40354 1727 /* Inform the callgraph about the new function. */
47300487 1728 cgraph_node *node = cgraph_node::get_create (child_fn);
1729 node->parallelized_function = 1;
415d1b9a 1730 cgraph_node::add_new_function (child_fn, false);
f6430caa 1731}
1732
1e8e9920 1733/* Destroy a omp_context data structures. Called through the splay tree
1734 value delete callback. */
1735
1736static void
1737delete_omp_context (splay_tree_value value)
1738{
1739 omp_context *ctx = (omp_context *) value;
1740
06ecf488 1741 delete ctx->cb.decl_map;
1e8e9920 1742
1743 if (ctx->field_map)
1744 splay_tree_delete (ctx->field_map);
fd6481cf 1745 if (ctx->sfield_map)
1746 splay_tree_delete (ctx->sfield_map);
1e8e9920 1747
1748 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
1749 it produces corrupt debug information. */
1750 if (ctx->record_type)
1751 {
1752 tree t;
1767a056 1753 for (t = TYPE_FIELDS (ctx->record_type); t ; t = DECL_CHAIN (t))
1e8e9920 1754 DECL_ABSTRACT_ORIGIN (t) = NULL;
1755 }
fd6481cf 1756 if (ctx->srecord_type)
1757 {
1758 tree t;
1767a056 1759 for (t = TYPE_FIELDS (ctx->srecord_type); t ; t = DECL_CHAIN (t))
fd6481cf 1760 DECL_ABSTRACT_ORIGIN (t) = NULL;
1761 }
1e8e9920 1762
f6430caa 1763 if (is_task_ctx (ctx))
1a91d914 1764 finalize_task_copyfn (as_a <gomp_task *> (ctx->stmt));
f6430caa 1765
1e8e9920 1766 XDELETE (ctx);
1767}
1768
1769/* Fix up RECEIVER_DECL with a type that has been remapped to the child
1770 context. */
1771
1772static void
1773fixup_child_record_type (omp_context *ctx)
1774{
1775 tree f, type = ctx->record_type;
1776
1777 /* ??? It isn't sufficient to just call remap_type here, because
1778 variably_modified_type_p doesn't work the way we expect for
1779 record types. Testing each field for whether it needs remapping
1780 and creating a new record by hand works, however. */
1767a056 1781 for (f = TYPE_FIELDS (type); f ; f = DECL_CHAIN (f))
1e8e9920 1782 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
1783 break;
1784 if (f)
1785 {
1786 tree name, new_fields = NULL;
1787
1788 type = lang_hooks.types.make_type (RECORD_TYPE);
1789 name = DECL_NAME (TYPE_NAME (ctx->record_type));
e60a6f7b 1790 name = build_decl (DECL_SOURCE_LOCATION (ctx->receiver_decl),
1791 TYPE_DECL, name, type);
1e8e9920 1792 TYPE_NAME (type) = name;
1793
1767a056 1794 for (f = TYPE_FIELDS (ctx->record_type); f ; f = DECL_CHAIN (f))
1e8e9920 1795 {
1796 tree new_f = copy_node (f);
1797 DECL_CONTEXT (new_f) = type;
1798 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
1767a056 1799 DECL_CHAIN (new_f) = new_fields;
75a70cf9 1800 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &ctx->cb, NULL);
1801 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r,
1802 &ctx->cb, NULL);
1803 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
1804 &ctx->cb, NULL);
1e8e9920 1805 new_fields = new_f;
1806
1807 /* Arrange to be able to look up the receiver field
1808 given the sender field. */
1809 splay_tree_insert (ctx->field_map, (splay_tree_key) f,
1810 (splay_tree_value) new_f);
1811 }
1812 TYPE_FIELDS (type) = nreverse (new_fields);
1813 layout_type (type);
1814 }
1815
43895be5 1816 /* In a target region we never modify any of the pointers in *.omp_data_i,
1817 so attempt to help the optimizers. */
1818 if (is_gimple_omp_offloaded (ctx->stmt))
1819 type = build_qualified_type (type, TYPE_QUAL_CONST);
1820
5455b100 1821 TREE_TYPE (ctx->receiver_decl)
1822 = build_qualified_type (build_reference_type (type), TYPE_QUAL_RESTRICT);
1e8e9920 1823}
1824
1825/* Instantiate decls as necessary in CTX to satisfy the data sharing
12dc9a16 1826 specified by CLAUSES. If BASE_POINTERS_RESTRICT, install var field with
1827 restrict. */
1e8e9920 1828
1829static void
12dc9a16 1830scan_sharing_clauses (tree clauses, omp_context *ctx,
1831 bool base_pointers_restrict = false)
1e8e9920 1832{
1833 tree c, decl;
1834 bool scan_array_reductions = false;
1835
1836 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1837 {
1838 bool by_ref;
1839
55d6e7cd 1840 switch (OMP_CLAUSE_CODE (c))
1e8e9920 1841 {
1842 case OMP_CLAUSE_PRIVATE:
1843 decl = OMP_CLAUSE_DECL (c);
fd6481cf 1844 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
1845 goto do_private;
1846 else if (!is_variable_sized (decl))
1e8e9920 1847 install_var_local (decl, ctx);
1848 break;
1849
1850 case OMP_CLAUSE_SHARED:
5fddcf34 1851 decl = OMP_CLAUSE_DECL (c);
bc7bff74 1852 /* Ignore shared directives in teams construct. */
1853 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
5fddcf34 1854 {
1855 /* Global variables don't need to be copied,
1856 the receiver side will use them directly. */
1857 tree odecl = maybe_lookup_decl_in_outer_ctx (decl, ctx);
1858 if (is_global_var (odecl))
1859 break;
1860 insert_decl_map (&ctx->cb, decl, odecl);
1861 break;
1862 }
fd6481cf 1863 gcc_assert (is_taskreg_ctx (ctx));
e7327393 1864 gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl))
1865 || !is_variable_sized (decl));
f49d7bb5 1866 /* Global variables don't need to be copied,
1867 the receiver side will use them directly. */
1868 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1869 break;
43895be5 1870 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
98588013 1871 {
1872 use_pointer_for_field (decl, ctx);
1873 break;
1874 }
1875 by_ref = use_pointer_for_field (decl, NULL);
1876 if ((! TREE_READONLY (decl) && !OMP_CLAUSE_SHARED_READONLY (c))
1e8e9920 1877 || TREE_ADDRESSABLE (decl)
1878 || by_ref
1879 || is_reference (decl))
1880 {
98588013 1881 by_ref = use_pointer_for_field (decl, ctx);
fd6481cf 1882 install_var_field (decl, by_ref, 3, ctx);
1e8e9920 1883 install_var_local (decl, ctx);
1884 break;
1885 }
1886 /* We don't need to copy const scalar vars back. */
55d6e7cd 1887 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
1e8e9920 1888 goto do_private;
1889
43895be5 1890 case OMP_CLAUSE_REDUCTION:
1891 decl = OMP_CLAUSE_DECL (c);
1892 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1893 && TREE_CODE (decl) == MEM_REF)
1894 {
1895 tree t = TREE_OPERAND (decl, 0);
9561765e 1896 if (TREE_CODE (t) == POINTER_PLUS_EXPR)
1897 t = TREE_OPERAND (t, 0);
43895be5 1898 if (TREE_CODE (t) == INDIRECT_REF
1899 || TREE_CODE (t) == ADDR_EXPR)
1900 t = TREE_OPERAND (t, 0);
1901 install_var_local (t, ctx);
1902 if (is_taskreg_ctx (ctx)
1903 && !is_global_var (maybe_lookup_decl_in_outer_ctx (t, ctx))
1904 && !is_variable_sized (t))
1905 {
1906 by_ref = use_pointer_for_field (t, ctx);
1907 install_var_field (t, by_ref, 3, ctx);
1908 }
1909 break;
1910 }
1911 goto do_private;
1912
1e8e9920 1913 case OMP_CLAUSE_LASTPRIVATE:
1914 /* Let the corresponding firstprivate clause create
1915 the variable. */
1916 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1917 break;
1918 /* FALLTHRU */
1919
1920 case OMP_CLAUSE_FIRSTPRIVATE:
3d483a94 1921 case OMP_CLAUSE_LINEAR:
1e8e9920 1922 decl = OMP_CLAUSE_DECL (c);
1923 do_private:
43895be5 1924 if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
1925 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IS_DEVICE_PTR)
1926 && is_gimple_omp_offloaded (ctx->stmt))
1927 {
1928 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
1929 install_var_field (decl, !is_reference (decl), 3, ctx);
1930 else if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1931 install_var_field (decl, true, 3, ctx);
1932 else
1933 install_var_field (decl, false, 3, ctx);
1934 }
1e8e9920 1935 if (is_variable_sized (decl))
1e8e9920 1936 {
fd6481cf 1937 if (is_task_ctx (ctx))
1938 install_var_field (decl, false, 1, ctx);
1939 break;
1940 }
1941 else if (is_taskreg_ctx (ctx))
1942 {
1943 bool global
1944 = is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx));
e8a588af 1945 by_ref = use_pointer_for_field (decl, NULL);
fd6481cf 1946
1947 if (is_task_ctx (ctx)
1948 && (global || by_ref || is_reference (decl)))
1949 {
1950 install_var_field (decl, false, 1, ctx);
1951 if (!global)
1952 install_var_field (decl, by_ref, 2, ctx);
1953 }
1954 else if (!global)
1955 install_var_field (decl, by_ref, 3, ctx);
1e8e9920 1956 }
1957 install_var_local (decl, ctx);
1958 break;
1959
571b3486 1960 case OMP_CLAUSE_USE_DEVICE:
43895be5 1961 case OMP_CLAUSE_USE_DEVICE_PTR:
1962 decl = OMP_CLAUSE_DECL (c);
1963 if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1964 install_var_field (decl, true, 3, ctx);
1965 else
1966 install_var_field (decl, false, 3, ctx);
1967 if (DECL_SIZE (decl)
1968 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1969 {
1970 tree decl2 = DECL_VALUE_EXPR (decl);
1971 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1972 decl2 = TREE_OPERAND (decl2, 0);
1973 gcc_assert (DECL_P (decl2));
1974 install_var_local (decl2, ctx);
1975 }
1976 install_var_local (decl, ctx);
1977 break;
1978
1979 case OMP_CLAUSE_IS_DEVICE_PTR:
1980 decl = OMP_CLAUSE_DECL (c);
1981 goto do_private;
1982
bc7bff74 1983 case OMP_CLAUSE__LOOPTEMP_:
43895be5 1984 gcc_assert (is_taskreg_ctx (ctx));
bc7bff74 1985 decl = OMP_CLAUSE_DECL (c);
1986 install_var_field (decl, false, 3, ctx);
1987 install_var_local (decl, ctx);
1988 break;
1989
1e8e9920 1990 case OMP_CLAUSE_COPYPRIVATE:
1e8e9920 1991 case OMP_CLAUSE_COPYIN:
1992 decl = OMP_CLAUSE_DECL (c);
e8a588af 1993 by_ref = use_pointer_for_field (decl, NULL);
fd6481cf 1994 install_var_field (decl, by_ref, 3, ctx);
1e8e9920 1995 break;
1996
1997 case OMP_CLAUSE_DEFAULT:
1998 ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
1999 break;
2000
2169f33b 2001 case OMP_CLAUSE_FINAL:
1e8e9920 2002 case OMP_CLAUSE_IF:
2003 case OMP_CLAUSE_NUM_THREADS:
bc7bff74 2004 case OMP_CLAUSE_NUM_TEAMS:
2005 case OMP_CLAUSE_THREAD_LIMIT:
2006 case OMP_CLAUSE_DEVICE:
1e8e9920 2007 case OMP_CLAUSE_SCHEDULE:
bc7bff74 2008 case OMP_CLAUSE_DIST_SCHEDULE:
2009 case OMP_CLAUSE_DEPEND:
43895be5 2010 case OMP_CLAUSE_PRIORITY:
2011 case OMP_CLAUSE_GRAINSIZE:
2012 case OMP_CLAUSE_NUM_TASKS:
40750995 2013 case OMP_CLAUSE__CILK_FOR_COUNT_:
ca4c3545 2014 case OMP_CLAUSE_NUM_GANGS:
2015 case OMP_CLAUSE_NUM_WORKERS:
2016 case OMP_CLAUSE_VECTOR_LENGTH:
1e8e9920 2017 if (ctx->outer)
75a70cf9 2018 scan_omp_op (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
1e8e9920 2019 break;
2020
bc7bff74 2021 case OMP_CLAUSE_TO:
2022 case OMP_CLAUSE_FROM:
2023 case OMP_CLAUSE_MAP:
2024 if (ctx->outer)
2025 scan_omp_op (&OMP_CLAUSE_SIZE (c), ctx->outer);
2026 decl = OMP_CLAUSE_DECL (c);
2027 /* Global variables with "omp declare target" attribute
2028 don't need to be copied, the receiver side will use them
c0998828 2029 directly. However, global variables with "omp declare target link"
2030 attribute need to be copied. */
bc7bff74 2031 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
2032 && DECL_P (decl)
9561765e 2033 && ((OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_FIRSTPRIVATE_POINTER
2034 && (OMP_CLAUSE_MAP_KIND (c)
2035 != GOMP_MAP_FIRSTPRIVATE_REFERENCE))
43895be5 2036 || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
bc7bff74 2037 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
c0998828 2038 && varpool_node::get_create (decl)->offloadable
2039 && !lookup_attribute ("omp declare target link",
2040 DECL_ATTRIBUTES (decl)))
bc7bff74 2041 break;
2042 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
ca4c3545 2043 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER)
bc7bff74 2044 {
ca4c3545 2045 /* Ignore GOMP_MAP_POINTER kind for arrays in regions that are
2046 not offloaded; there is nothing to map for those. */
2047 if (!is_gimple_omp_offloaded (ctx->stmt)
c1a114c2 2048 && !POINTER_TYPE_P (TREE_TYPE (decl))
2049 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
bc7bff74 2050 break;
2051 }
43895be5 2052 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
9561765e 2053 && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
2054 || (OMP_CLAUSE_MAP_KIND (c)
2055 == GOMP_MAP_FIRSTPRIVATE_REFERENCE)))
43895be5 2056 {
2057 if (TREE_CODE (decl) == COMPONENT_REF
2058 || (TREE_CODE (decl) == INDIRECT_REF
2059 && TREE_CODE (TREE_OPERAND (decl, 0)) == COMPONENT_REF
2060 && (TREE_CODE (TREE_TYPE (TREE_OPERAND (decl, 0)))
2061 == REFERENCE_TYPE)))
2062 break;
2063 if (DECL_SIZE (decl)
2064 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
2065 {
2066 tree decl2 = DECL_VALUE_EXPR (decl);
2067 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2068 decl2 = TREE_OPERAND (decl2, 0);
2069 gcc_assert (DECL_P (decl2));
2070 install_var_local (decl2, ctx);
2071 }
2072 install_var_local (decl, ctx);
2073 break;
2074 }
bc7bff74 2075 if (DECL_P (decl))
2076 {
2077 if (DECL_SIZE (decl)
2078 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
2079 {
2080 tree decl2 = DECL_VALUE_EXPR (decl);
2081 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2082 decl2 = TREE_OPERAND (decl2, 0);
2083 gcc_assert (DECL_P (decl2));
9561765e 2084 install_var_field (decl2, true, 3, ctx);
bc7bff74 2085 install_var_local (decl2, ctx);
2086 install_var_local (decl, ctx);
2087 }
2088 else
2089 {
2090 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
ca4c3545 2091 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
bc7bff74 2092 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
2093 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
2094 install_var_field (decl, true, 7, ctx);
2095 else
12dc9a16 2096 install_var_field (decl, true, 3, ctx,
2097 base_pointers_restrict);
ca4c3545 2098 if (is_gimple_omp_offloaded (ctx->stmt))
bc7bff74 2099 install_var_local (decl, ctx);
2100 }
2101 }
2102 else
2103 {
2104 tree base = get_base_address (decl);
2105 tree nc = OMP_CLAUSE_CHAIN (c);
2106 if (DECL_P (base)
2107 && nc != NULL_TREE
2108 && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
2109 && OMP_CLAUSE_DECL (nc) == base
ca4c3545 2110 && OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_POINTER
bc7bff74 2111 && integer_zerop (OMP_CLAUSE_SIZE (nc)))
2112 {
2113 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c) = 1;
2114 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (nc) = 1;
2115 }
2116 else
2117 {
691447ab 2118 if (ctx->outer)
2119 {
2120 scan_omp_op (&OMP_CLAUSE_DECL (c), ctx->outer);
2121 decl = OMP_CLAUSE_DECL (c);
2122 }
bc7bff74 2123 gcc_assert (!splay_tree_lookup (ctx->field_map,
2124 (splay_tree_key) decl));
2125 tree field
2126 = build_decl (OMP_CLAUSE_LOCATION (c),
2127 FIELD_DECL, NULL_TREE, ptr_type_node);
2128 DECL_ALIGN (field) = TYPE_ALIGN (ptr_type_node);
2129 insert_field_into_struct (ctx->record_type, field);
2130 splay_tree_insert (ctx->field_map, (splay_tree_key) decl,
2131 (splay_tree_value) field);
2132 }
2133 }
2134 break;
2135
1e8e9920 2136 case OMP_CLAUSE_NOWAIT:
2137 case OMP_CLAUSE_ORDERED:
fd6481cf 2138 case OMP_CLAUSE_COLLAPSE:
2139 case OMP_CLAUSE_UNTIED:
2169f33b 2140 case OMP_CLAUSE_MERGEABLE:
bc7bff74 2141 case OMP_CLAUSE_PROC_BIND:
3d483a94 2142 case OMP_CLAUSE_SAFELEN:
43895be5 2143 case OMP_CLAUSE_SIMDLEN:
2144 case OMP_CLAUSE_THREADS:
2145 case OMP_CLAUSE_SIMD:
2146 case OMP_CLAUSE_NOGROUP:
2147 case OMP_CLAUSE_DEFAULTMAP:
ca4c3545 2148 case OMP_CLAUSE_ASYNC:
2149 case OMP_CLAUSE_WAIT:
2150 case OMP_CLAUSE_GANG:
2151 case OMP_CLAUSE_WORKER:
2152 case OMP_CLAUSE_VECTOR:
ef014f95 2153 case OMP_CLAUSE_TILE:
f4f5b4b4 2154 case OMP_CLAUSE_INDEPENDENT:
2155 case OMP_CLAUSE_AUTO:
2156 case OMP_CLAUSE_SEQ:
1e8e9920 2157 break;
2158
bc7bff74 2159 case OMP_CLAUSE_ALIGNED:
2160 decl = OMP_CLAUSE_DECL (c);
2161 if (is_global_var (decl)
2162 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
2163 install_var_local (decl, ctx);
2164 break;
2165
ca4c3545 2166 case OMP_CLAUSE_DEVICE_RESIDENT:
ca4c3545 2167 case OMP_CLAUSE__CACHE_:
ca4c3545 2168 sorry ("Clause not supported yet");
2169 break;
2170
1e8e9920 2171 default:
2172 gcc_unreachable ();
2173 }
2174 }
2175
2176 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2177 {
55d6e7cd 2178 switch (OMP_CLAUSE_CODE (c))
1e8e9920 2179 {
2180 case OMP_CLAUSE_LASTPRIVATE:
2181 /* Let the corresponding firstprivate clause create
2182 the variable. */
75a70cf9 2183 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
fd6481cf 2184 scan_array_reductions = true;
1e8e9920 2185 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
2186 break;
2187 /* FALLTHRU */
2188
1e8e9920 2189 case OMP_CLAUSE_FIRSTPRIVATE:
ca4c3545 2190 case OMP_CLAUSE_PRIVATE:
3d483a94 2191 case OMP_CLAUSE_LINEAR:
43895be5 2192 case OMP_CLAUSE_IS_DEVICE_PTR:
1e8e9920 2193 decl = OMP_CLAUSE_DECL (c);
2194 if (is_variable_sized (decl))
43895be5 2195 {
2196 if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
2197 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IS_DEVICE_PTR)
2198 && is_gimple_omp_offloaded (ctx->stmt))
2199 {
2200 tree decl2 = DECL_VALUE_EXPR (decl);
2201 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2202 decl2 = TREE_OPERAND (decl2, 0);
2203 gcc_assert (DECL_P (decl2));
2204 install_var_local (decl2, ctx);
2205 fixup_remapped_decl (decl2, ctx, false);
2206 }
2207 install_var_local (decl, ctx);
2208 }
1e8e9920 2209 fixup_remapped_decl (decl, ctx,
55d6e7cd 2210 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
1e8e9920 2211 && OMP_CLAUSE_PRIVATE_DEBUG (c));
43895be5 2212 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
2213 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
1e8e9920 2214 scan_array_reductions = true;
43895be5 2215 break;
2216
2217 case OMP_CLAUSE_REDUCTION:
2218 decl = OMP_CLAUSE_DECL (c);
2219 if (TREE_CODE (decl) != MEM_REF)
2220 {
2221 if (is_variable_sized (decl))
2222 install_var_local (decl, ctx);
2223 fixup_remapped_decl (decl, ctx, false);
2224 }
2225 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2b536a17 2226 scan_array_reductions = true;
1e8e9920 2227 break;
2228
2229 case OMP_CLAUSE_SHARED:
bc7bff74 2230 /* Ignore shared directives in teams construct. */
2231 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
2232 break;
1e8e9920 2233 decl = OMP_CLAUSE_DECL (c);
43895be5 2234 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
2235 break;
2236 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
2237 {
2238 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl,
2239 ctx->outer)))
2240 break;
2241 bool by_ref = use_pointer_for_field (decl, ctx);
2242 install_var_field (decl, by_ref, 11, ctx);
2243 break;
2244 }
2245 fixup_remapped_decl (decl, ctx, false);
1e8e9920 2246 break;
2247
bc7bff74 2248 case OMP_CLAUSE_MAP:
ca4c3545 2249 if (!is_gimple_omp_offloaded (ctx->stmt))
bc7bff74 2250 break;
2251 decl = OMP_CLAUSE_DECL (c);
2252 if (DECL_P (decl)
9561765e 2253 && ((OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_FIRSTPRIVATE_POINTER
2254 && (OMP_CLAUSE_MAP_KIND (c)
2255 != GOMP_MAP_FIRSTPRIVATE_REFERENCE))
43895be5 2256 || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
bc7bff74 2257 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
b0c5e347 2258 && varpool_node::get_create (decl)->offloadable)
bc7bff74 2259 break;
2260 if (DECL_P (decl))
2261 {
43895be5 2262 if ((OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
2263 || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER)
bc7bff74 2264 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
2265 && !COMPLETE_TYPE_P (TREE_TYPE (decl)))
2266 {
2267 tree new_decl = lookup_decl (decl, ctx);
2268 TREE_TYPE (new_decl)
2269 = remap_type (TREE_TYPE (decl), &ctx->cb);
2270 }
2271 else if (DECL_SIZE (decl)
2272 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
2273 {
2274 tree decl2 = DECL_VALUE_EXPR (decl);
2275 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2276 decl2 = TREE_OPERAND (decl2, 0);
2277 gcc_assert (DECL_P (decl2));
2278 fixup_remapped_decl (decl2, ctx, false);
2279 fixup_remapped_decl (decl, ctx, true);
2280 }
2281 else
2282 fixup_remapped_decl (decl, ctx, false);
2283 }
2284 break;
2285
1e8e9920 2286 case OMP_CLAUSE_COPYPRIVATE:
2287 case OMP_CLAUSE_COPYIN:
2288 case OMP_CLAUSE_DEFAULT:
2289 case OMP_CLAUSE_IF:
2290 case OMP_CLAUSE_NUM_THREADS:
bc7bff74 2291 case OMP_CLAUSE_NUM_TEAMS:
2292 case OMP_CLAUSE_THREAD_LIMIT:
2293 case OMP_CLAUSE_DEVICE:
1e8e9920 2294 case OMP_CLAUSE_SCHEDULE:
bc7bff74 2295 case OMP_CLAUSE_DIST_SCHEDULE:
1e8e9920 2296 case OMP_CLAUSE_NOWAIT:
2297 case OMP_CLAUSE_ORDERED:
fd6481cf 2298 case OMP_CLAUSE_COLLAPSE:
2299 case OMP_CLAUSE_UNTIED:
2169f33b 2300 case OMP_CLAUSE_FINAL:
2301 case OMP_CLAUSE_MERGEABLE:
bc7bff74 2302 case OMP_CLAUSE_PROC_BIND:
3d483a94 2303 case OMP_CLAUSE_SAFELEN:
43895be5 2304 case OMP_CLAUSE_SIMDLEN:
bc7bff74 2305 case OMP_CLAUSE_ALIGNED:
2306 case OMP_CLAUSE_DEPEND:
2307 case OMP_CLAUSE__LOOPTEMP_:
2308 case OMP_CLAUSE_TO:
2309 case OMP_CLAUSE_FROM:
43895be5 2310 case OMP_CLAUSE_PRIORITY:
2311 case OMP_CLAUSE_GRAINSIZE:
2312 case OMP_CLAUSE_NUM_TASKS:
2313 case OMP_CLAUSE_THREADS:
2314 case OMP_CLAUSE_SIMD:
2315 case OMP_CLAUSE_NOGROUP:
2316 case OMP_CLAUSE_DEFAULTMAP:
571b3486 2317 case OMP_CLAUSE_USE_DEVICE:
43895be5 2318 case OMP_CLAUSE_USE_DEVICE_PTR:
40750995 2319 case OMP_CLAUSE__CILK_FOR_COUNT_:
ca4c3545 2320 case OMP_CLAUSE_ASYNC:
2321 case OMP_CLAUSE_WAIT:
2322 case OMP_CLAUSE_NUM_GANGS:
2323 case OMP_CLAUSE_NUM_WORKERS:
2324 case OMP_CLAUSE_VECTOR_LENGTH:
2325 case OMP_CLAUSE_GANG:
2326 case OMP_CLAUSE_WORKER:
2327 case OMP_CLAUSE_VECTOR:
ef014f95 2328 case OMP_CLAUSE_TILE:
f4f5b4b4 2329 case OMP_CLAUSE_INDEPENDENT:
2330 case OMP_CLAUSE_AUTO:
2331 case OMP_CLAUSE_SEQ:
ca4c3545 2332 break;
2333
2334 case OMP_CLAUSE_DEVICE_RESIDENT:
ca4c3545 2335 case OMP_CLAUSE__CACHE_:
ca4c3545 2336 sorry ("Clause not supported yet");
1e8e9920 2337 break;
2338
2339 default:
2340 gcc_unreachable ();
2341 }
2342 }
2343
ca4c3545 2344 gcc_checking_assert (!scan_array_reductions
2345 || !is_gimple_omp_oacc (ctx->stmt));
1e8e9920 2346 if (scan_array_reductions)
2347 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
55d6e7cd 2348 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1e8e9920 2349 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2350 {
ab129075 2351 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
2352 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
1e8e9920 2353 }
fd6481cf 2354 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
75a70cf9 2355 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
ab129075 2356 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
2b536a17 2357 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
2358 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
2359 scan_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
1e8e9920 2360}
2361
40750995 2362/* Create a new name for omp child function. Returns an identifier. If
2363 IS_CILK_FOR is true then the suffix for the child function is
2364 "_cilk_for_fn." */
1e8e9920 2365
1e8e9920 2366static tree
40750995 2367create_omp_child_function_name (bool task_copy, bool is_cilk_for)
1e8e9920 2368{
40750995 2369 if (is_cilk_for)
2370 return clone_function_name (current_function_decl, "_cilk_for_fn");
2371 return clone_function_name (current_function_decl,
2372 task_copy ? "_omp_cpyfn" : "_omp_fn");
2373}
2374
2375/* Returns the type of the induction variable for the child function for
2376 _Cilk_for and the types for _high and _low variables based on TYPE. */
2377
2378static tree
2379cilk_for_check_loop_diff_type (tree type)
2380{
2381 if (TYPE_PRECISION (type) <= TYPE_PRECISION (uint32_type_node))
2382 {
2383 if (TYPE_UNSIGNED (type))
2384 return uint32_type_node;
2385 else
2386 return integer_type_node;
2387 }
2388 else
2389 {
2390 if (TYPE_UNSIGNED (type))
2391 return uint64_type_node;
2392 else
2393 return long_long_integer_type_node;
2394 }
1e8e9920 2395}
2396
2397/* Build a decl for the omp child function. It'll not contain a body
2398 yet, just the bare decl. */
2399
2400static void
fd6481cf 2401create_omp_child_function (omp_context *ctx, bool task_copy)
1e8e9920 2402{
2403 tree decl, type, name, t;
2404
40750995 2405 tree cilk_for_count
2406 = (flag_cilkplus && gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2407 ? find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
2408 OMP_CLAUSE__CILK_FOR_COUNT_) : NULL_TREE;
2409 tree cilk_var_type = NULL_TREE;
2410
2411 name = create_omp_child_function_name (task_copy,
2412 cilk_for_count != NULL_TREE);
fd6481cf 2413 if (task_copy)
2414 type = build_function_type_list (void_type_node, ptr_type_node,
2415 ptr_type_node, NULL_TREE);
40750995 2416 else if (cilk_for_count)
2417 {
2418 type = TREE_TYPE (OMP_CLAUSE_OPERAND (cilk_for_count, 0));
2419 cilk_var_type = cilk_for_check_loop_diff_type (type);
2420 type = build_function_type_list (void_type_node, ptr_type_node,
2421 cilk_var_type, cilk_var_type, NULL_TREE);
2422 }
fd6481cf 2423 else
2424 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
1e8e9920 2425
40750995 2426 decl = build_decl (gimple_location (ctx->stmt), FUNCTION_DECL, name, type);
1e8e9920 2427
ca4c3545 2428 gcc_checking_assert (!is_gimple_omp_oacc (ctx->stmt)
2429 || !task_copy);
fd6481cf 2430 if (!task_copy)
2431 ctx->cb.dst_fn = decl;
2432 else
75a70cf9 2433 gimple_omp_task_set_copy_fn (ctx->stmt, decl);
1e8e9920 2434
2435 TREE_STATIC (decl) = 1;
2436 TREE_USED (decl) = 1;
2437 DECL_ARTIFICIAL (decl) = 1;
2438 DECL_IGNORED_P (decl) = 0;
2439 TREE_PUBLIC (decl) = 0;
2440 DECL_UNINLINABLE (decl) = 1;
2441 DECL_EXTERNAL (decl) = 0;
2442 DECL_CONTEXT (decl) = NULL_TREE;
773c5ba7 2443 DECL_INITIAL (decl) = make_node (BLOCK);
b0c5e347 2444 if (cgraph_node::get (current_function_decl)->offloadable)
2445 cgraph_node::get_create (decl)->offloadable = 1;
bc7bff74 2446 else
2447 {
2448 omp_context *octx;
2449 for (octx = ctx; octx; octx = octx->outer)
ca4c3545 2450 if (is_gimple_omp_offloaded (octx->stmt))
bc7bff74 2451 {
b0c5e347 2452 cgraph_node::get_create (decl)->offloadable = 1;
5f3001a9 2453 if (ENABLE_OFFLOADING)
2454 g->have_offload = true;
2455
bc7bff74 2456 break;
2457 }
2458 }
1e8e9920 2459
ec12b31a 2460 if (cgraph_node::get_create (decl)->offloadable
2461 && !lookup_attribute ("omp declare target",
2462 DECL_ATTRIBUTES (current_function_decl)))
2463 DECL_ATTRIBUTES (decl)
2464 = tree_cons (get_identifier ("omp target entrypoint"),
2465 NULL_TREE, DECL_ATTRIBUTES (decl));
2466
e60a6f7b 2467 t = build_decl (DECL_SOURCE_LOCATION (decl),
2468 RESULT_DECL, NULL_TREE, void_type_node);
1e8e9920 2469 DECL_ARTIFICIAL (t) = 1;
2470 DECL_IGNORED_P (t) = 1;
8e5b4ed6 2471 DECL_CONTEXT (t) = decl;
1e8e9920 2472 DECL_RESULT (decl) = t;
2473
40750995 2474 /* _Cilk_for's child function requires two extra parameters called
2475 __low and __high that are set the by Cilk runtime when it calls this
2476 function. */
2477 if (cilk_for_count)
2478 {
2479 t = build_decl (DECL_SOURCE_LOCATION (decl),
2480 PARM_DECL, get_identifier ("__high"), cilk_var_type);
2481 DECL_ARTIFICIAL (t) = 1;
2482 DECL_NAMELESS (t) = 1;
2483 DECL_ARG_TYPE (t) = ptr_type_node;
2484 DECL_CONTEXT (t) = current_function_decl;
2485 TREE_USED (t) = 1;
2486 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2487 DECL_ARGUMENTS (decl) = t;
2488
2489 t = build_decl (DECL_SOURCE_LOCATION (decl),
2490 PARM_DECL, get_identifier ("__low"), cilk_var_type);
2491 DECL_ARTIFICIAL (t) = 1;
2492 DECL_NAMELESS (t) = 1;
2493 DECL_ARG_TYPE (t) = ptr_type_node;
2494 DECL_CONTEXT (t) = current_function_decl;
2495 TREE_USED (t) = 1;
2496 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2497 DECL_ARGUMENTS (decl) = t;
2498 }
2499
2500 tree data_name = get_identifier (".omp_data_i");
2501 t = build_decl (DECL_SOURCE_LOCATION (decl), PARM_DECL, data_name,
2502 ptr_type_node);
1e8e9920 2503 DECL_ARTIFICIAL (t) = 1;
84bfaaeb 2504 DECL_NAMELESS (t) = 1;
1e8e9920 2505 DECL_ARG_TYPE (t) = ptr_type_node;
773c5ba7 2506 DECL_CONTEXT (t) = current_function_decl;
1e8e9920 2507 TREE_USED (t) = 1;
43895be5 2508 TREE_READONLY (t) = 1;
40750995 2509 if (cilk_for_count)
2510 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
1e8e9920 2511 DECL_ARGUMENTS (decl) = t;
fd6481cf 2512 if (!task_copy)
2513 ctx->receiver_decl = t;
2514 else
2515 {
e60a6f7b 2516 t = build_decl (DECL_SOURCE_LOCATION (decl),
2517 PARM_DECL, get_identifier (".omp_data_o"),
fd6481cf 2518 ptr_type_node);
2519 DECL_ARTIFICIAL (t) = 1;
84bfaaeb 2520 DECL_NAMELESS (t) = 1;
fd6481cf 2521 DECL_ARG_TYPE (t) = ptr_type_node;
2522 DECL_CONTEXT (t) = current_function_decl;
2523 TREE_USED (t) = 1;
86f2ad37 2524 TREE_ADDRESSABLE (t) = 1;
1767a056 2525 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
fd6481cf 2526 DECL_ARGUMENTS (decl) = t;
2527 }
1e8e9920 2528
48e1416a 2529 /* Allocate memory for the function structure. The call to
773c5ba7 2530 allocate_struct_function clobbers CFUN, so we need to restore
1e8e9920 2531 it afterward. */
87d4aa85 2532 push_struct_function (decl);
75a70cf9 2533 cfun->function_end_locus = gimple_location (ctx->stmt);
87d4aa85 2534 pop_cfun ();
1e8e9920 2535}
2536
bc7bff74 2537/* Callback for walk_gimple_seq. Check if combined parallel
2538 contains gimple_omp_for_combined_into_p OMP_FOR. */
2539
2540static tree
2541find_combined_for (gimple_stmt_iterator *gsi_p,
2542 bool *handled_ops_p,
2543 struct walk_stmt_info *wi)
2544{
42acab1c 2545 gimple *stmt = gsi_stmt (*gsi_p);
bc7bff74 2546
2547 *handled_ops_p = true;
2548 switch (gimple_code (stmt))
2549 {
2550 WALK_SUBSTMTS;
2551
2552 case GIMPLE_OMP_FOR:
2553 if (gimple_omp_for_combined_into_p (stmt)
43895be5 2554 && gimple_omp_for_kind (stmt)
2555 == *(const enum gf_mask *) (wi->info))
bc7bff74 2556 {
2557 wi->info = stmt;
2558 return integer_zero_node;
2559 }
2560 break;
2561 default:
2562 break;
2563 }
2564 return NULL;
2565}
2566
43895be5 2567/* Add _LOOPTEMP_ clauses on OpenMP parallel or task. */
2568
2569static void
2570add_taskreg_looptemp_clauses (enum gf_mask msk, gimple *stmt,
2571 omp_context *outer_ctx)
2572{
2573 struct walk_stmt_info wi;
2574
2575 memset (&wi, 0, sizeof (wi));
2576 wi.val_only = true;
2577 wi.info = (void *) &msk;
2578 walk_gimple_seq (gimple_omp_body (stmt), find_combined_for, NULL, &wi);
2579 if (wi.info != (void *) &msk)
2580 {
2581 gomp_for *for_stmt = as_a <gomp_for *> ((gimple *) wi.info);
2582 struct omp_for_data fd;
2583 extract_omp_for_data (for_stmt, &fd, NULL);
2584 /* We need two temporaries with fd.loop.v type (istart/iend)
2585 and then (fd.collapse - 1) temporaries with the same
2586 type for count2 ... countN-1 vars if not constant. */
2587 size_t count = 2, i;
2588 tree type = fd.iter_type;
2589 if (fd.collapse > 1
2590 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
2591 {
2592 count += fd.collapse - 1;
9561765e 2593 /* If there are lastprivate clauses on the inner
43895be5 2594 GIMPLE_OMP_FOR, add one more temporaries for the total number
2595 of iterations (product of count1 ... countN-1). */
9561765e 2596 if (find_omp_clause (gimple_omp_for_clauses (for_stmt),
2597 OMP_CLAUSE_LASTPRIVATE))
2598 count++;
2599 else if (msk == GF_OMP_FOR_KIND_FOR
2600 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
2601 OMP_CLAUSE_LASTPRIVATE))
43895be5 2602 count++;
2603 }
2604 for (i = 0; i < count; i++)
2605 {
2606 tree temp = create_tmp_var (type);
2607 tree c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
2608 insert_decl_map (&outer_ctx->cb, temp, temp);
2609 OMP_CLAUSE_DECL (c) = temp;
2610 OMP_CLAUSE_CHAIN (c) = gimple_omp_taskreg_clauses (stmt);
2611 gimple_omp_taskreg_set_clauses (stmt, c);
2612 }
2613 }
2614}
2615
1e8e9920 2616/* Scan an OpenMP parallel directive. */
2617
2618static void
75a70cf9 2619scan_omp_parallel (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
1e8e9920 2620{
2621 omp_context *ctx;
2622 tree name;
1a91d914 2623 gomp_parallel *stmt = as_a <gomp_parallel *> (gsi_stmt (*gsi));
1e8e9920 2624
2625 /* Ignore parallel directives with empty bodies, unless there
2626 are copyin clauses. */
2627 if (optimize > 0
75a70cf9 2628 && empty_body_p (gimple_omp_body (stmt))
2629 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
2630 OMP_CLAUSE_COPYIN) == NULL)
1e8e9920 2631 {
75a70cf9 2632 gsi_replace (gsi, gimple_build_nop (), false);
1e8e9920 2633 return;
2634 }
2635
bc7bff74 2636 if (gimple_omp_parallel_combined_p (stmt))
43895be5 2637 add_taskreg_looptemp_clauses (GF_OMP_FOR_KIND_FOR, stmt, outer_ctx);
bc7bff74 2638
75a70cf9 2639 ctx = new_omp_context (stmt, outer_ctx);
37eaded9 2640 taskreg_contexts.safe_push (ctx);
fd6481cf 2641 if (taskreg_nesting_level > 1)
773c5ba7 2642 ctx->is_nested = true;
1e8e9920 2643 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1e8e9920 2644 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2645 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
1e8e9920 2646 name = create_tmp_var_name (".omp_data_s");
e60a6f7b 2647 name = build_decl (gimple_location (stmt),
2648 TYPE_DECL, name, ctx->record_type);
84bfaaeb 2649 DECL_ARTIFICIAL (name) = 1;
2650 DECL_NAMELESS (name) = 1;
1e8e9920 2651 TYPE_NAME (ctx->record_type) = name;
240131b5 2652 TYPE_ARTIFICIAL (ctx->record_type) = 1;
fd6481cf 2653 create_omp_child_function (ctx, false);
75a70cf9 2654 gimple_omp_parallel_set_child_fn (stmt, ctx->cb.dst_fn);
1e8e9920 2655
75a70cf9 2656 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt), ctx);
ab129075 2657 scan_omp (gimple_omp_body_ptr (stmt), ctx);
1e8e9920 2658
2659 if (TYPE_FIELDS (ctx->record_type) == NULL)
2660 ctx->record_type = ctx->receiver_decl = NULL;
1e8e9920 2661}
2662
fd6481cf 2663/* Scan an OpenMP task directive. */
2664
2665static void
75a70cf9 2666scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
fd6481cf 2667{
2668 omp_context *ctx;
75a70cf9 2669 tree name, t;
1a91d914 2670 gomp_task *stmt = as_a <gomp_task *> (gsi_stmt (*gsi));
fd6481cf 2671
2672 /* Ignore task directives with empty bodies. */
2673 if (optimize > 0
75a70cf9 2674 && empty_body_p (gimple_omp_body (stmt)))
fd6481cf 2675 {
75a70cf9 2676 gsi_replace (gsi, gimple_build_nop (), false);
fd6481cf 2677 return;
2678 }
2679
43895be5 2680 if (gimple_omp_task_taskloop_p (stmt))
2681 add_taskreg_looptemp_clauses (GF_OMP_FOR_KIND_TASKLOOP, stmt, outer_ctx);
2682
75a70cf9 2683 ctx = new_omp_context (stmt, outer_ctx);
37eaded9 2684 taskreg_contexts.safe_push (ctx);
fd6481cf 2685 if (taskreg_nesting_level > 1)
2686 ctx->is_nested = true;
2687 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2688 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2689 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2690 name = create_tmp_var_name (".omp_data_s");
e60a6f7b 2691 name = build_decl (gimple_location (stmt),
2692 TYPE_DECL, name, ctx->record_type);
84bfaaeb 2693 DECL_ARTIFICIAL (name) = 1;
2694 DECL_NAMELESS (name) = 1;
fd6481cf 2695 TYPE_NAME (ctx->record_type) = name;
240131b5 2696 TYPE_ARTIFICIAL (ctx->record_type) = 1;
fd6481cf 2697 create_omp_child_function (ctx, false);
75a70cf9 2698 gimple_omp_task_set_child_fn (stmt, ctx->cb.dst_fn);
fd6481cf 2699
75a70cf9 2700 scan_sharing_clauses (gimple_omp_task_clauses (stmt), ctx);
fd6481cf 2701
2702 if (ctx->srecord_type)
2703 {
2704 name = create_tmp_var_name (".omp_data_a");
e60a6f7b 2705 name = build_decl (gimple_location (stmt),
2706 TYPE_DECL, name, ctx->srecord_type);
84bfaaeb 2707 DECL_ARTIFICIAL (name) = 1;
2708 DECL_NAMELESS (name) = 1;
fd6481cf 2709 TYPE_NAME (ctx->srecord_type) = name;
240131b5 2710 TYPE_ARTIFICIAL (ctx->srecord_type) = 1;
fd6481cf 2711 create_omp_child_function (ctx, true);
2712 }
2713
ab129075 2714 scan_omp (gimple_omp_body_ptr (stmt), ctx);
fd6481cf 2715
2716 if (TYPE_FIELDS (ctx->record_type) == NULL)
2717 {
2718 ctx->record_type = ctx->receiver_decl = NULL;
75a70cf9 2719 t = build_int_cst (long_integer_type_node, 0);
2720 gimple_omp_task_set_arg_size (stmt, t);
2721 t = build_int_cst (long_integer_type_node, 1);
2722 gimple_omp_task_set_arg_align (stmt, t);
fd6481cf 2723 }
37eaded9 2724}
2725
2726
2727/* If any decls have been made addressable during scan_omp,
2728 adjust their fields if needed, and layout record types
2729 of parallel/task constructs. */
2730
2731static void
2732finish_taskreg_scan (omp_context *ctx)
2733{
2734 if (ctx->record_type == NULL_TREE)
2735 return;
2736
2737 /* If any task_shared_vars were needed, verify all
2738 OMP_CLAUSE_SHARED clauses on GIMPLE_OMP_{PARALLEL,TASK}
2739 statements if use_pointer_for_field hasn't changed
2740 because of that. If it did, update field types now. */
2741 if (task_shared_vars)
2742 {
2743 tree c;
2744
2745 for (c = gimple_omp_taskreg_clauses (ctx->stmt);
2746 c; c = OMP_CLAUSE_CHAIN (c))
43895be5 2747 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
2748 && !OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
37eaded9 2749 {
2750 tree decl = OMP_CLAUSE_DECL (c);
2751
2752 /* Global variables don't need to be copied,
2753 the receiver side will use them directly. */
2754 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
2755 continue;
2756 if (!bitmap_bit_p (task_shared_vars, DECL_UID (decl))
2757 || !use_pointer_for_field (decl, ctx))
2758 continue;
2759 tree field = lookup_field (decl, ctx);
2760 if (TREE_CODE (TREE_TYPE (field)) == POINTER_TYPE
2761 && TREE_TYPE (TREE_TYPE (field)) == TREE_TYPE (decl))
2762 continue;
2763 TREE_TYPE (field) = build_pointer_type (TREE_TYPE (decl));
2764 TREE_THIS_VOLATILE (field) = 0;
2765 DECL_USER_ALIGN (field) = 0;
2766 DECL_ALIGN (field) = TYPE_ALIGN (TREE_TYPE (field));
2767 if (TYPE_ALIGN (ctx->record_type) < DECL_ALIGN (field))
2768 TYPE_ALIGN (ctx->record_type) = DECL_ALIGN (field);
2769 if (ctx->srecord_type)
2770 {
2771 tree sfield = lookup_sfield (decl, ctx);
2772 TREE_TYPE (sfield) = TREE_TYPE (field);
2773 TREE_THIS_VOLATILE (sfield) = 0;
2774 DECL_USER_ALIGN (sfield) = 0;
2775 DECL_ALIGN (sfield) = DECL_ALIGN (field);
2776 if (TYPE_ALIGN (ctx->srecord_type) < DECL_ALIGN (sfield))
2777 TYPE_ALIGN (ctx->srecord_type) = DECL_ALIGN (sfield);
2778 }
2779 }
2780 }
2781
2782 if (gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2783 {
2784 layout_type (ctx->record_type);
2785 fixup_child_record_type (ctx);
2786 }
fd6481cf 2787 else
2788 {
37eaded9 2789 location_t loc = gimple_location (ctx->stmt);
fd6481cf 2790 tree *p, vla_fields = NULL_TREE, *q = &vla_fields;
2791 /* Move VLA fields to the end. */
2792 p = &TYPE_FIELDS (ctx->record_type);
2793 while (*p)
2794 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p))
2795 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p))))
2796 {
2797 *q = *p;
2798 *p = TREE_CHAIN (*p);
2799 TREE_CHAIN (*q) = NULL_TREE;
2800 q = &TREE_CHAIN (*q);
2801 }
2802 else
1767a056 2803 p = &DECL_CHAIN (*p);
fd6481cf 2804 *p = vla_fields;
43895be5 2805 if (gimple_omp_task_taskloop_p (ctx->stmt))
2806 {
2807 /* Move fields corresponding to first and second _looptemp_
2808 clause first. There are filled by GOMP_taskloop
2809 and thus need to be in specific positions. */
2810 tree c1 = gimple_omp_task_clauses (ctx->stmt);
2811 c1 = find_omp_clause (c1, OMP_CLAUSE__LOOPTEMP_);
2812 tree c2 = find_omp_clause (OMP_CLAUSE_CHAIN (c1),
2813 OMP_CLAUSE__LOOPTEMP_);
2814 tree f1 = lookup_field (OMP_CLAUSE_DECL (c1), ctx);
2815 tree f2 = lookup_field (OMP_CLAUSE_DECL (c2), ctx);
2816 p = &TYPE_FIELDS (ctx->record_type);
2817 while (*p)
2818 if (*p == f1 || *p == f2)
2819 *p = DECL_CHAIN (*p);
2820 else
2821 p = &DECL_CHAIN (*p);
2822 DECL_CHAIN (f1) = f2;
2823 DECL_CHAIN (f2) = TYPE_FIELDS (ctx->record_type);
2824 TYPE_FIELDS (ctx->record_type) = f1;
2825 if (ctx->srecord_type)
2826 {
2827 f1 = lookup_sfield (OMP_CLAUSE_DECL (c1), ctx);
2828 f2 = lookup_sfield (OMP_CLAUSE_DECL (c2), ctx);
2829 p = &TYPE_FIELDS (ctx->srecord_type);
2830 while (*p)
2831 if (*p == f1 || *p == f2)
2832 *p = DECL_CHAIN (*p);
2833 else
2834 p = &DECL_CHAIN (*p);
2835 DECL_CHAIN (f1) = f2;
2836 DECL_CHAIN (f2) = TYPE_FIELDS (ctx->srecord_type);
2837 TYPE_FIELDS (ctx->srecord_type) = f1;
2838 }
2839 }
fd6481cf 2840 layout_type (ctx->record_type);
2841 fixup_child_record_type (ctx);
2842 if (ctx->srecord_type)
2843 layout_type (ctx->srecord_type);
37eaded9 2844 tree t = fold_convert_loc (loc, long_integer_type_node,
2845 TYPE_SIZE_UNIT (ctx->record_type));
2846 gimple_omp_task_set_arg_size (ctx->stmt, t);
75a70cf9 2847 t = build_int_cst (long_integer_type_node,
fd6481cf 2848 TYPE_ALIGN_UNIT (ctx->record_type));
37eaded9 2849 gimple_omp_task_set_arg_align (ctx->stmt, t);
fd6481cf 2850 }
2851}
2852
a8e785ba 2853/* Find the enclosing offload context. */
1e8e9920 2854
ca4c3545 2855static omp_context *
2856enclosing_target_ctx (omp_context *ctx)
2857{
a8e785ba 2858 for (; ctx; ctx = ctx->outer)
2859 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET)
2860 break;
2861
ca4c3545 2862 return ctx;
2863}
2864
a8e785ba 2865/* Return true if ctx is part of an oacc kernels region. */
2866
ca4c3545 2867static bool
a8e785ba 2868ctx_in_oacc_kernels_region (omp_context *ctx)
ca4c3545 2869{
a8e785ba 2870 for (;ctx != NULL; ctx = ctx->outer)
2871 {
2872 gimple *stmt = ctx->stmt;
2873 if (gimple_code (stmt) == GIMPLE_OMP_TARGET
2874 && gimple_omp_target_kind (stmt) == GF_OMP_TARGET_KIND_OACC_KERNELS)
2875 return true;
2876 }
2877
2878 return false;
2879}
2880
2881/* Check the parallelism clauses inside a kernels regions.
2882 Until kernels handling moves to use the same loop indirection
2883 scheme as parallel, we need to do this checking early. */
2884
2885static unsigned
2886check_oacc_kernel_gwv (gomp_for *stmt, omp_context *ctx)
2887{
2888 bool checking = true;
2889 unsigned outer_mask = 0;
2890 unsigned this_mask = 0;
2891 bool has_seq = false, has_auto = false;
2892
2893 if (ctx->outer)
2894 outer_mask = check_oacc_kernel_gwv (NULL, ctx->outer);
2895 if (!stmt)
2896 {
2897 checking = false;
2898 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR)
2899 return outer_mask;
2900 stmt = as_a <gomp_for *> (ctx->stmt);
2901 }
2902
2903 for (tree c = gimple_omp_for_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
2904 {
2905 switch (OMP_CLAUSE_CODE (c))
2906 {
2907 case OMP_CLAUSE_GANG:
2908 this_mask |= GOMP_DIM_MASK (GOMP_DIM_GANG);
2909 break;
2910 case OMP_CLAUSE_WORKER:
2911 this_mask |= GOMP_DIM_MASK (GOMP_DIM_WORKER);
2912 break;
2913 case OMP_CLAUSE_VECTOR:
2914 this_mask |= GOMP_DIM_MASK (GOMP_DIM_VECTOR);
2915 break;
2916 case OMP_CLAUSE_SEQ:
2917 has_seq = true;
2918 break;
2919 case OMP_CLAUSE_AUTO:
2920 has_auto = true;
2921 break;
2922 default:
2923 break;
2924 }
2925 }
2926
2927 if (checking)
2928 {
2929 if (has_seq && (this_mask || has_auto))
2930 error_at (gimple_location (stmt), "%<seq%> overrides other"
2931 " OpenACC loop specifiers");
2932 else if (has_auto && this_mask)
2933 error_at (gimple_location (stmt), "%<auto%> conflicts with other"
2934 " OpenACC loop specifiers");
2935
2936 if (this_mask & outer_mask)
2937 error_at (gimple_location (stmt), "inner loop uses same"
2938 " OpenACC parallelism as containing loop");
2939 }
2940
2941 return outer_mask | this_mask;
ca4c3545 2942}
2943
2944/* Scan a GIMPLE_OMP_FOR. */
1e8e9920 2945
2946static void
1a91d914 2947scan_omp_for (gomp_for *stmt, omp_context *outer_ctx)
1e8e9920 2948{
773c5ba7 2949 omp_context *ctx;
75a70cf9 2950 size_t i;
ca4c3545 2951 tree clauses = gimple_omp_for_clauses (stmt);
2952
773c5ba7 2953 ctx = new_omp_context (stmt, outer_ctx);
1e8e9920 2954
ca4c3545 2955 if (is_gimple_omp_oacc (stmt))
2956 {
a8e785ba 2957 omp_context *tgt = enclosing_target_ctx (outer_ctx);
2958
2959 if (!tgt || is_oacc_parallel (tgt))
2960 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2961 {
2962 char const *check = NULL;
2963
2964 switch (OMP_CLAUSE_CODE (c))
2965 {
2966 case OMP_CLAUSE_GANG:
2967 check = "gang";
2968 break;
2969
2970 case OMP_CLAUSE_WORKER:
2971 check = "worker";
2972 break;
2973
2974 case OMP_CLAUSE_VECTOR:
2975 check = "vector";
2976 break;
2977
2978 default:
2979 break;
2980 }
2981
2982 if (check && OMP_CLAUSE_OPERAND (c, 0))
2983 error_at (gimple_location (stmt),
2984 "argument not permitted on %qs clause in"
2985 " OpenACC %<parallel%>", check);
2986 }
2987
2988 if (tgt && is_oacc_kernels (tgt))
2989 {
2990 /* Strip out reductions, as they are not handled yet. */
2991 tree *prev_ptr = &clauses;
2992
2993 while (tree probe = *prev_ptr)
ca4c3545 2994 {
a8e785ba 2995 tree *next_ptr = &OMP_CLAUSE_CHAIN (probe);
2996
2997 if (OMP_CLAUSE_CODE (probe) == OMP_CLAUSE_REDUCTION)
2998 *prev_ptr = *next_ptr;
2999 else
3000 prev_ptr = next_ptr;
ca4c3545 3001 }
a8e785ba 3002
3003 gimple_omp_for_set_clauses (stmt, clauses);
3004 check_oacc_kernel_gwv (stmt, ctx);
ca4c3545 3005 }
3006 }
3007
3008 scan_sharing_clauses (clauses, ctx);
1e8e9920 3009
ab129075 3010 scan_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
75a70cf9 3011 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
fd6481cf 3012 {
75a70cf9 3013 scan_omp_op (gimple_omp_for_index_ptr (stmt, i), ctx);
3014 scan_omp_op (gimple_omp_for_initial_ptr (stmt, i), ctx);
3015 scan_omp_op (gimple_omp_for_final_ptr (stmt, i), ctx);
3016 scan_omp_op (gimple_omp_for_incr_ptr (stmt, i), ctx);
fd6481cf 3017 }
ab129075 3018 scan_omp (gimple_omp_body_ptr (stmt), ctx);
1e8e9920 3019}
3020
3021/* Scan an OpenMP sections directive. */
3022
3023static void
1a91d914 3024scan_omp_sections (gomp_sections *stmt, omp_context *outer_ctx)
1e8e9920 3025{
1e8e9920 3026 omp_context *ctx;
3027
3028 ctx = new_omp_context (stmt, outer_ctx);
75a70cf9 3029 scan_sharing_clauses (gimple_omp_sections_clauses (stmt), ctx);
ab129075 3030 scan_omp (gimple_omp_body_ptr (stmt), ctx);
1e8e9920 3031}
3032
3033/* Scan an OpenMP single directive. */
3034
3035static void
1a91d914 3036scan_omp_single (gomp_single *stmt, omp_context *outer_ctx)
1e8e9920 3037{
1e8e9920 3038 omp_context *ctx;
3039 tree name;
3040
3041 ctx = new_omp_context (stmt, outer_ctx);
3042 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
3043 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
3044 name = create_tmp_var_name (".omp_copy_s");
e60a6f7b 3045 name = build_decl (gimple_location (stmt),
3046 TYPE_DECL, name, ctx->record_type);
1e8e9920 3047 TYPE_NAME (ctx->record_type) = name;
3048
75a70cf9 3049 scan_sharing_clauses (gimple_omp_single_clauses (stmt), ctx);
ab129075 3050 scan_omp (gimple_omp_body_ptr (stmt), ctx);
1e8e9920 3051
3052 if (TYPE_FIELDS (ctx->record_type) == NULL)
3053 ctx->record_type = NULL;
3054 else
3055 layout_type (ctx->record_type);
3056}
3057
12dc9a16 3058/* Return true if the CLAUSES of an omp target guarantee that the base pointers
3059 used in the corresponding offloaded function are restrict. */
3060
3061static bool
3062omp_target_base_pointers_restrict_p (tree clauses)
3063{
3064 /* The analysis relies on the GOMP_MAP_FORCE_* mapping kinds, which are only
3065 used by OpenACC. */
3066 if (flag_openacc == 0)
3067 return false;
3068
3069 /* I. Basic example:
3070
3071 void foo (void)
3072 {
3073 unsigned int a[2], b[2];
3074
3075 #pragma acc kernels \
3076 copyout (a) \
3077 copyout (b)
3078 {
3079 a[0] = 0;
3080 b[0] = 1;
3081 }
3082 }
3083
3084 After gimplification, we have:
3085
3086 #pragma omp target oacc_kernels \
3087 map(force_from:a [len: 8]) \
3088 map(force_from:b [len: 8])
3089 {
3090 a[0] = 0;
3091 b[0] = 1;
3092 }
3093
3094 Because both mappings have the force prefix, we know that they will be
3095 allocated when calling the corresponding offloaded function, which means we
3096 can mark the base pointers for a and b in the offloaded function as
3097 restrict. */
3098
3099 tree c;
3100 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
3101 {
3102 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP)
3103 return false;
3104
3105 switch (OMP_CLAUSE_MAP_KIND (c))
3106 {
3107 case GOMP_MAP_FORCE_ALLOC:
3108 case GOMP_MAP_FORCE_TO:
3109 case GOMP_MAP_FORCE_FROM:
3110 case GOMP_MAP_FORCE_TOFROM:
3111 break;
3112 default:
3113 return false;
3114 }
3115 }
3116
3117 return true;
3118}
3119
ca4c3545 3120/* Scan a GIMPLE_OMP_TARGET. */
bc7bff74 3121
3122static void
1a91d914 3123scan_omp_target (gomp_target *stmt, omp_context *outer_ctx)
bc7bff74 3124{
3125 omp_context *ctx;
3126 tree name;
ca4c3545 3127 bool offloaded = is_gimple_omp_offloaded (stmt);
3128 tree clauses = gimple_omp_target_clauses (stmt);
bc7bff74 3129
3130 ctx = new_omp_context (stmt, outer_ctx);
3131 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
3132 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
3133 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
3134 name = create_tmp_var_name (".omp_data_t");
3135 name = build_decl (gimple_location (stmt),
3136 TYPE_DECL, name, ctx->record_type);
3137 DECL_ARTIFICIAL (name) = 1;
3138 DECL_NAMELESS (name) = 1;
3139 TYPE_NAME (ctx->record_type) = name;
240131b5 3140 TYPE_ARTIFICIAL (ctx->record_type) = 1;
12dc9a16 3141
3142 bool base_pointers_restrict = false;
ca4c3545 3143 if (offloaded)
bc7bff74 3144 {
3145 create_omp_child_function (ctx, false);
3146 gimple_omp_target_set_child_fn (stmt, ctx->cb.dst_fn);
12dc9a16 3147
3148 base_pointers_restrict = omp_target_base_pointers_restrict_p (clauses);
3149 if (base_pointers_restrict
3150 && dump_file && (dump_flags & TDF_DETAILS))
3151 fprintf (dump_file,
3152 "Base pointers in offloaded function are restrict\n");
bc7bff74 3153 }
3154
12dc9a16 3155 scan_sharing_clauses (clauses, ctx, base_pointers_restrict);
bc7bff74 3156 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3157
3158 if (TYPE_FIELDS (ctx->record_type) == NULL)
3159 ctx->record_type = ctx->receiver_decl = NULL;
3160 else
3161 {
3162 TYPE_FIELDS (ctx->record_type)
3163 = nreverse (TYPE_FIELDS (ctx->record_type));
382ecba7 3164 if (flag_checking)
3165 {
3166 unsigned int align = DECL_ALIGN (TYPE_FIELDS (ctx->record_type));
3167 for (tree field = TYPE_FIELDS (ctx->record_type);
3168 field;
3169 field = DECL_CHAIN (field))
3170 gcc_assert (DECL_ALIGN (field) == align);
3171 }
bc7bff74 3172 layout_type (ctx->record_type);
ca4c3545 3173 if (offloaded)
bc7bff74 3174 fixup_child_record_type (ctx);
3175 }
3176}
3177
3178/* Scan an OpenMP teams directive. */
3179
3180static void
1a91d914 3181scan_omp_teams (gomp_teams *stmt, omp_context *outer_ctx)
bc7bff74 3182{
3183 omp_context *ctx = new_omp_context (stmt, outer_ctx);
3184 scan_sharing_clauses (gimple_omp_teams_clauses (stmt), ctx);
3185 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3186}
1e8e9920 3187
ca4c3545 3188/* Check nesting restrictions. */
ab129075 3189static bool
42acab1c 3190check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx)
c1d127dd 3191{
43895be5 3192 tree c;
3193
ca4c3545 3194 /* No nesting of non-OpenACC STMT (that is, an OpenMP one, or a GOMP builtin)
3195 inside an OpenACC CTX. */
3196 if (!(is_gimple_omp (stmt)
3197 && is_gimple_omp_oacc (stmt)))
3198 {
7821c1b5 3199 for (omp_context *octx = ctx; octx != NULL; octx = octx->outer)
3200 if (is_gimple_omp (octx->stmt)
3201 && is_gimple_omp_oacc (octx->stmt)
9e10bfb7 3202 /* Except for atomic codes that we share with OpenMP. */
3203 && ! (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD
3204 || gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE))
ca4c3545 3205 {
3206 error_at (gimple_location (stmt),
3207 "non-OpenACC construct inside of OpenACC region");
3208 return false;
3209 }
3210 }
3211
3d483a94 3212 if (ctx != NULL)
3213 {
3214 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
10c55644 3215 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3d483a94 3216 {
43895be5 3217 c = NULL_TREE;
3218 if (gimple_code (stmt) == GIMPLE_OMP_ORDERED)
3219 {
3220 c = gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt));
7821c1b5 3221 if (find_omp_clause (c, OMP_CLAUSE_SIMD))
3222 {
3223 if (find_omp_clause (c, OMP_CLAUSE_THREADS)
3224 && (ctx->outer == NULL
3225 || !gimple_omp_for_combined_into_p (ctx->stmt)
3226 || gimple_code (ctx->outer->stmt) != GIMPLE_OMP_FOR
3227 || (gimple_omp_for_kind (ctx->outer->stmt)
3228 != GF_OMP_FOR_KIND_FOR)
3229 || !gimple_omp_for_combined_p (ctx->outer->stmt)))
3230 {
3231 error_at (gimple_location (stmt),
3232 "%<ordered simd threads%> must be closely "
3233 "nested inside of %<for simd%> region");
3234 return false;
3235 }
3236 return true;
3237 }
43895be5 3238 }
3d483a94 3239 error_at (gimple_location (stmt),
43895be5 3240 "OpenMP constructs other than %<#pragma omp ordered simd%>"
7821c1b5 3241 " may not be nested inside %<simd%> region");
3d483a94 3242 return false;
3243 }
bc7bff74 3244 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3245 {
3246 if ((gimple_code (stmt) != GIMPLE_OMP_FOR
3247 || (gimple_omp_for_kind (stmt)
3248 != GF_OMP_FOR_KIND_DISTRIBUTE))
3249 && gimple_code (stmt) != GIMPLE_OMP_PARALLEL)
3250 {
3251 error_at (gimple_location (stmt),
7821c1b5 3252 "only %<distribute%> or %<parallel%> regions are "
3253 "allowed to be strictly nested inside %<teams%> "
3254 "region");
bc7bff74 3255 return false;
3256 }
3257 }
3d483a94 3258 }
75a70cf9 3259 switch (gimple_code (stmt))
c1d127dd 3260 {
75a70cf9 3261 case GIMPLE_OMP_FOR:
10c55644 3262 if (gimple_omp_for_kind (stmt) & GF_OMP_FOR_SIMD)
3d483a94 3263 return true;
bc7bff74 3264 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
3265 {
3266 if (ctx != NULL && gimple_code (ctx->stmt) != GIMPLE_OMP_TEAMS)
3267 {
3268 error_at (gimple_location (stmt),
7821c1b5 3269 "%<distribute%> region must be strictly nested "
3270 "inside %<teams%> construct");
bc7bff74 3271 return false;
3272 }
3273 return true;
3274 }
43895be5 3275 /* We split taskloop into task and nested taskloop in it. */
3276 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_TASKLOOP)
3277 return true;
7a1ed40d 3278 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
3279 {
3280 bool ok = false;
3281
3282 if (ctx)
3283 switch (gimple_code (ctx->stmt))
3284 {
3285 case GIMPLE_OMP_FOR:
3286 ok = (gimple_omp_for_kind (ctx->stmt)
3287 == GF_OMP_FOR_KIND_OACC_LOOP);
3288 break;
3289
3290 case GIMPLE_OMP_TARGET:
3291 switch (gimple_omp_target_kind (ctx->stmt))
3292 {
3293 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
3294 case GF_OMP_TARGET_KIND_OACC_KERNELS:
3295 ok = true;
3296 break;
3297
3298 default:
3299 break;
3300 }
3301
3302 default:
3303 break;
3304 }
3305 else if (get_oacc_fn_attrib (current_function_decl))
3306 ok = true;
3307 if (!ok)
3308 {
3309 error_at (gimple_location (stmt),
3310 "OpenACC loop directive must be associated with"
3311 " an OpenACC compute region");
3312 return false;
3313 }
3314 }
bc7bff74 3315 /* FALLTHRU */
3316 case GIMPLE_CALL:
3317 if (is_gimple_call (stmt)
3318 && (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3319 == BUILT_IN_GOMP_CANCEL
3320 || DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3321 == BUILT_IN_GOMP_CANCELLATION_POINT))
3322 {
3323 const char *bad = NULL;
3324 const char *kind = NULL;
7821c1b5 3325 const char *construct
3326 = (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3327 == BUILT_IN_GOMP_CANCEL)
3328 ? "#pragma omp cancel"
3329 : "#pragma omp cancellation point";
bc7bff74 3330 if (ctx == NULL)
3331 {
3332 error_at (gimple_location (stmt), "orphaned %qs construct",
7821c1b5 3333 construct);
bc7bff74 3334 return false;
3335 }
6b409616 3336 switch (tree_fits_shwi_p (gimple_call_arg (stmt, 0))
3337 ? tree_to_shwi (gimple_call_arg (stmt, 0))
bc7bff74 3338 : 0)
3339 {
3340 case 1:
3341 if (gimple_code (ctx->stmt) != GIMPLE_OMP_PARALLEL)
3342 bad = "#pragma omp parallel";
3343 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3344 == BUILT_IN_GOMP_CANCEL
3345 && !integer_zerop (gimple_call_arg (stmt, 1)))
3346 ctx->cancellable = true;
3347 kind = "parallel";
3348 break;
3349 case 2:
3350 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
3351 || gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR)
3352 bad = "#pragma omp for";
3353 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3354 == BUILT_IN_GOMP_CANCEL
3355 && !integer_zerop (gimple_call_arg (stmt, 1)))
3356 {
3357 ctx->cancellable = true;
3358 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3359 OMP_CLAUSE_NOWAIT))
3360 warning_at (gimple_location (stmt), 0,
3361 "%<#pragma omp cancel for%> inside "
3362 "%<nowait%> for construct");
3363 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3364 OMP_CLAUSE_ORDERED))
3365 warning_at (gimple_location (stmt), 0,
3366 "%<#pragma omp cancel for%> inside "
3367 "%<ordered%> for construct");
3368 }
3369 kind = "for";
3370 break;
3371 case 4:
3372 if (gimple_code (ctx->stmt) != GIMPLE_OMP_SECTIONS
3373 && gimple_code (ctx->stmt) != GIMPLE_OMP_SECTION)
3374 bad = "#pragma omp sections";
3375 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3376 == BUILT_IN_GOMP_CANCEL
3377 && !integer_zerop (gimple_call_arg (stmt, 1)))
3378 {
3379 if (gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS)
3380 {
3381 ctx->cancellable = true;
3382 if (find_omp_clause (gimple_omp_sections_clauses
3383 (ctx->stmt),
3384 OMP_CLAUSE_NOWAIT))
3385 warning_at (gimple_location (stmt), 0,
3386 "%<#pragma omp cancel sections%> inside "
3387 "%<nowait%> sections construct");
3388 }
3389 else
3390 {
3391 gcc_assert (ctx->outer
3392 && gimple_code (ctx->outer->stmt)
3393 == GIMPLE_OMP_SECTIONS);
3394 ctx->outer->cancellable = true;
3395 if (find_omp_clause (gimple_omp_sections_clauses
3396 (ctx->outer->stmt),
3397 OMP_CLAUSE_NOWAIT))
3398 warning_at (gimple_location (stmt), 0,
3399 "%<#pragma omp cancel sections%> inside "
3400 "%<nowait%> sections construct");
3401 }
3402 }
3403 kind = "sections";
3404 break;
3405 case 8:
3406 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TASK)
3407 bad = "#pragma omp task";
3408 else
7821c1b5 3409 {
3410 for (omp_context *octx = ctx->outer;
3411 octx; octx = octx->outer)
3412 {
3413 switch (gimple_code (octx->stmt))
3414 {
3415 case GIMPLE_OMP_TASKGROUP:
3416 break;
3417 case GIMPLE_OMP_TARGET:
3418 if (gimple_omp_target_kind (octx->stmt)
3419 != GF_OMP_TARGET_KIND_REGION)
3420 continue;
3421 /* FALLTHRU */
3422 case GIMPLE_OMP_PARALLEL:
3423 case GIMPLE_OMP_TEAMS:
3424 error_at (gimple_location (stmt),
3425 "%<%s taskgroup%> construct not closely "
3426 "nested inside of %<taskgroup%> region",
3427 construct);
3428 return false;
3429 default:
3430 continue;
3431 }
3432 break;
3433 }
3434 ctx->cancellable = true;
3435 }
bc7bff74 3436 kind = "taskgroup";
3437 break;
3438 default:
3439 error_at (gimple_location (stmt), "invalid arguments");
3440 return false;
3441 }
3442 if (bad)
3443 {
3444 error_at (gimple_location (stmt),
3445 "%<%s %s%> construct not closely nested inside of %qs",
7821c1b5 3446 construct, kind, bad);
bc7bff74 3447 return false;
3448 }
3449 }
3d483a94 3450 /* FALLTHRU */
75a70cf9 3451 case GIMPLE_OMP_SECTIONS:
3452 case GIMPLE_OMP_SINGLE:
c1d127dd 3453 for (; ctx != NULL; ctx = ctx->outer)
75a70cf9 3454 switch (gimple_code (ctx->stmt))
c1d127dd 3455 {
75a70cf9 3456 case GIMPLE_OMP_FOR:
7821c1b5 3457 if (gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR
3458 && gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_TASKLOOP)
3459 break;
3460 /* FALLTHRU */
75a70cf9 3461 case GIMPLE_OMP_SECTIONS:
3462 case GIMPLE_OMP_SINGLE:
3463 case GIMPLE_OMP_ORDERED:
3464 case GIMPLE_OMP_MASTER:
3465 case GIMPLE_OMP_TASK:
bc7bff74 3466 case GIMPLE_OMP_CRITICAL:
75a70cf9 3467 if (is_gimple_call (stmt))
fd6481cf 3468 {
bc7bff74 3469 if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3470 != BUILT_IN_GOMP_BARRIER)
3471 return true;
ab129075 3472 error_at (gimple_location (stmt),
3473 "barrier region may not be closely nested inside "
7821c1b5 3474 "of work-sharing, %<critical%>, %<ordered%>, "
3475 "%<master%>, explicit %<task%> or %<taskloop%> "
3476 "region");
ab129075 3477 return false;
fd6481cf 3478 }
ab129075 3479 error_at (gimple_location (stmt),
3480 "work-sharing region may not be closely nested inside "
7821c1b5 3481 "of work-sharing, %<critical%>, %<ordered%>, "
3482 "%<master%>, explicit %<task%> or %<taskloop%> region");
ab129075 3483 return false;
75a70cf9 3484 case GIMPLE_OMP_PARALLEL:
7821c1b5 3485 case GIMPLE_OMP_TEAMS:
ab129075 3486 return true;
7821c1b5 3487 case GIMPLE_OMP_TARGET:
3488 if (gimple_omp_target_kind (ctx->stmt)
3489 == GF_OMP_TARGET_KIND_REGION)
3490 return true;
3491 break;
c1d127dd 3492 default:
3493 break;
3494 }
3495 break;
75a70cf9 3496 case GIMPLE_OMP_MASTER:
c1d127dd 3497 for (; ctx != NULL; ctx = ctx->outer)
75a70cf9 3498 switch (gimple_code (ctx->stmt))
c1d127dd 3499 {
75a70cf9 3500 case GIMPLE_OMP_FOR:
7821c1b5 3501 if (gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR
3502 && gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_TASKLOOP)
3503 break;
3504 /* FALLTHRU */
75a70cf9 3505 case GIMPLE_OMP_SECTIONS:
3506 case GIMPLE_OMP_SINGLE:
3507 case GIMPLE_OMP_TASK:
ab129075 3508 error_at (gimple_location (stmt),
7821c1b5 3509 "%<master%> region may not be closely nested inside "
3510 "of work-sharing, explicit %<task%> or %<taskloop%> "
3511 "region");
ab129075 3512 return false;
75a70cf9 3513 case GIMPLE_OMP_PARALLEL:
7821c1b5 3514 case GIMPLE_OMP_TEAMS:
ab129075 3515 return true;
7821c1b5 3516 case GIMPLE_OMP_TARGET:
3517 if (gimple_omp_target_kind (ctx->stmt)
3518 == GF_OMP_TARGET_KIND_REGION)
3519 return true;
3520 break;
c1d127dd 3521 default:
3522 break;
3523 }
3524 break;
43895be5 3525 case GIMPLE_OMP_TASK:
3526 for (c = gimple_omp_task_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
3527 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
3528 && (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE
3529 || OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK))
3530 {
3531 enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c);
3532 error_at (OMP_CLAUSE_LOCATION (c),
3533 "%<depend(%s)%> is only allowed in %<omp ordered%>",
3534 kind == OMP_CLAUSE_DEPEND_SOURCE ? "source" : "sink");
3535 return false;
3536 }
3537 break;
75a70cf9 3538 case GIMPLE_OMP_ORDERED:
43895be5 3539 for (c = gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt));
3540 c; c = OMP_CLAUSE_CHAIN (c))
3541 {
3542 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND)
3543 {
3544 gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_THREADS
7821c1b5 3545 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SIMD);
43895be5 3546 continue;
3547 }
3548 enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c);
3549 if (kind == OMP_CLAUSE_DEPEND_SOURCE
3550 || kind == OMP_CLAUSE_DEPEND_SINK)
3551 {
3552 tree oclause;
3553 /* Look for containing ordered(N) loop. */
3554 if (ctx == NULL
3555 || gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
3556 || (oclause
3557 = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3558 OMP_CLAUSE_ORDERED)) == NULL_TREE)
3559 {
3560 error_at (OMP_CLAUSE_LOCATION (c),
7821c1b5 3561 "%<ordered%> construct with %<depend%> clause "
3562 "must be closely nested inside an %<ordered%> "
3563 "loop");
43895be5 3564 return false;
3565 }
3566 else if (OMP_CLAUSE_ORDERED_EXPR (oclause) == NULL_TREE)
3567 {
3568 error_at (OMP_CLAUSE_LOCATION (c),
7821c1b5 3569 "%<ordered%> construct with %<depend%> clause "
3570 "must be closely nested inside a loop with "
3571 "%<ordered%> clause with a parameter");
43895be5 3572 return false;
3573 }
3574 }
3575 else
3576 {
3577 error_at (OMP_CLAUSE_LOCATION (c),
7821c1b5 3578 "invalid depend kind in omp %<ordered%> %<depend%>");
3579 return false;
3580 }
3581 }
3582 c = gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt));
3583 if (find_omp_clause (c, OMP_CLAUSE_SIMD))
3584 {
3585 /* ordered simd must be closely nested inside of simd region,
3586 and simd region must not encounter constructs other than
3587 ordered simd, therefore ordered simd may be either orphaned,
3588 or ctx->stmt must be simd. The latter case is handled already
3589 earlier. */
3590 if (ctx != NULL)
3591 {
3592 error_at (gimple_location (stmt),
3593 "%<ordered%> %<simd%> must be closely nested inside "
3594 "%<simd%> region");
43895be5 3595 return false;
3596 }
3597 }
c1d127dd 3598 for (; ctx != NULL; ctx = ctx->outer)
75a70cf9 3599 switch (gimple_code (ctx->stmt))
c1d127dd 3600 {
75a70cf9 3601 case GIMPLE_OMP_CRITICAL:
3602 case GIMPLE_OMP_TASK:
7821c1b5 3603 case GIMPLE_OMP_ORDERED:
3604 ordered_in_taskloop:
ab129075 3605 error_at (gimple_location (stmt),
7821c1b5 3606 "%<ordered%> region may not be closely nested inside "
3607 "of %<critical%>, %<ordered%>, explicit %<task%> or "
3608 "%<taskloop%> region");
ab129075 3609 return false;
75a70cf9 3610 case GIMPLE_OMP_FOR:
7821c1b5 3611 if (gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_TASKLOOP)
3612 goto ordered_in_taskloop;
75a70cf9 3613 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
c1d127dd 3614 OMP_CLAUSE_ORDERED) == NULL)
ab129075 3615 {
3616 error_at (gimple_location (stmt),
7821c1b5 3617 "%<ordered%> region must be closely nested inside "
3618 "a loop region with an %<ordered%> clause");
ab129075 3619 return false;
3620 }
3621 return true;
7821c1b5 3622 case GIMPLE_OMP_TARGET:
3623 if (gimple_omp_target_kind (ctx->stmt)
3624 != GF_OMP_TARGET_KIND_REGION)
3625 break;
3626 /* FALLTHRU */
75a70cf9 3627 case GIMPLE_OMP_PARALLEL:
7821c1b5 3628 case GIMPLE_OMP_TEAMS:
bc7bff74 3629 error_at (gimple_location (stmt),
7821c1b5 3630 "%<ordered%> region must be closely nested inside "
3631 "a loop region with an %<ordered%> clause");
bc7bff74 3632 return false;
c1d127dd 3633 default:
3634 break;
3635 }
3636 break;
75a70cf9 3637 case GIMPLE_OMP_CRITICAL:
1a91d914 3638 {
3639 tree this_stmt_name
3640 = gimple_omp_critical_name (as_a <gomp_critical *> (stmt));
3641 for (; ctx != NULL; ctx = ctx->outer)
3642 if (gomp_critical *other_crit
3643 = dyn_cast <gomp_critical *> (ctx->stmt))
3644 if (this_stmt_name == gimple_omp_critical_name (other_crit))
3645 {
3646 error_at (gimple_location (stmt),
7821c1b5 3647 "%<critical%> region may not be nested inside "
3648 "a %<critical%> region with the same name");
1a91d914 3649 return false;
3650 }
3651 }
c1d127dd 3652 break;
bc7bff74 3653 case GIMPLE_OMP_TEAMS:
3654 if (ctx == NULL
3655 || gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET
3656 || gimple_omp_target_kind (ctx->stmt) != GF_OMP_TARGET_KIND_REGION)
3657 {
3658 error_at (gimple_location (stmt),
7821c1b5 3659 "%<teams%> construct not closely nested inside of "
3660 "%<target%> construct");
bc7bff74 3661 return false;
3662 }
3663 break;
691447ab 3664 case GIMPLE_OMP_TARGET:
43895be5 3665 for (c = gimple_omp_target_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
3666 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
3667 && (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE
3668 || OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK))
3669 {
3670 enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c);
3671 error_at (OMP_CLAUSE_LOCATION (c),
3672 "%<depend(%s)%> is only allowed in %<omp ordered%>",
3673 kind == OMP_CLAUSE_DEPEND_SOURCE ? "source" : "sink");
3674 return false;
3675 }
691447ab 3676 for (; ctx != NULL; ctx = ctx->outer)
ca4c3545 3677 {
3678 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET)
3679 {
3680 if (is_gimple_omp (stmt)
3681 && is_gimple_omp_oacc (stmt)
3682 && is_gimple_omp (ctx->stmt))
3683 {
3684 error_at (gimple_location (stmt),
3685 "OpenACC construct inside of non-OpenACC region");
3686 return false;
3687 }
3688 continue;
3689 }
3690
3691 const char *stmt_name, *ctx_stmt_name;
3692 switch (gimple_omp_target_kind (stmt))
3693 {
3694 case GF_OMP_TARGET_KIND_REGION: stmt_name = "target"; break;
3695 case GF_OMP_TARGET_KIND_DATA: stmt_name = "target data"; break;
3696 case GF_OMP_TARGET_KIND_UPDATE: stmt_name = "target update"; break;
43895be5 3697 case GF_OMP_TARGET_KIND_ENTER_DATA:
3698 stmt_name = "target enter data"; break;
3699 case GF_OMP_TARGET_KIND_EXIT_DATA:
3700 stmt_name = "target exit data"; break;
ca4c3545 3701 case GF_OMP_TARGET_KIND_OACC_PARALLEL: stmt_name = "parallel"; break;
3702 case GF_OMP_TARGET_KIND_OACC_KERNELS: stmt_name = "kernels"; break;
3703 case GF_OMP_TARGET_KIND_OACC_DATA: stmt_name = "data"; break;
3704 case GF_OMP_TARGET_KIND_OACC_UPDATE: stmt_name = "update"; break;
43895be5 3705 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
3706 stmt_name = "enter/exit data"; break;
571b3486 3707 case GF_OMP_TARGET_KIND_OACC_HOST_DATA: stmt_name = "host_data";
3708 break;
ca4c3545 3709 default: gcc_unreachable ();
3710 }
3711 switch (gimple_omp_target_kind (ctx->stmt))
3712 {
3713 case GF_OMP_TARGET_KIND_REGION: ctx_stmt_name = "target"; break;
3714 case GF_OMP_TARGET_KIND_DATA: ctx_stmt_name = "target data"; break;
43895be5 3715 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
3716 ctx_stmt_name = "parallel"; break;
3717 case GF_OMP_TARGET_KIND_OACC_KERNELS:
3718 ctx_stmt_name = "kernels"; break;
ca4c3545 3719 case GF_OMP_TARGET_KIND_OACC_DATA: ctx_stmt_name = "data"; break;
571b3486 3720 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
3721 ctx_stmt_name = "host_data"; break;
ca4c3545 3722 default: gcc_unreachable ();
3723 }
3724
3725 /* OpenACC/OpenMP mismatch? */
3726 if (is_gimple_omp_oacc (stmt)
3727 != is_gimple_omp_oacc (ctx->stmt))
3728 {
3729 error_at (gimple_location (stmt),
7821c1b5 3730 "%s %qs construct inside of %s %qs region",
ca4c3545 3731 (is_gimple_omp_oacc (stmt)
3732 ? "OpenACC" : "OpenMP"), stmt_name,
3733 (is_gimple_omp_oacc (ctx->stmt)
3734 ? "OpenACC" : "OpenMP"), ctx_stmt_name);
3735 return false;
3736 }
3737 if (is_gimple_omp_offloaded (ctx->stmt))
3738 {
3739 /* No GIMPLE_OMP_TARGET inside offloaded OpenACC CTX. */
3740 if (is_gimple_omp_oacc (ctx->stmt))
3741 {
3742 error_at (gimple_location (stmt),
7821c1b5 3743 "%qs construct inside of %qs region",
ca4c3545 3744 stmt_name, ctx_stmt_name);
3745 return false;
3746 }
3747 else
3748 {
ca4c3545 3749 warning_at (gimple_location (stmt), 0,
7821c1b5 3750 "%qs construct inside of %qs region",
ca4c3545 3751 stmt_name, ctx_stmt_name);
3752 }
3753 }
3754 }
691447ab 3755 break;
c1d127dd 3756 default:
3757 break;
3758 }
ab129075 3759 return true;
c1d127dd 3760}
3761
3762
75a70cf9 3763/* Helper function scan_omp.
3764
3765 Callback for walk_tree or operators in walk_gimple_stmt used to
ca4c3545 3766 scan for OMP directives in TP. */
1e8e9920 3767
3768static tree
75a70cf9 3769scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
1e8e9920 3770{
4077bf7a 3771 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
3772 omp_context *ctx = (omp_context *) wi->info;
1e8e9920 3773 tree t = *tp;
3774
75a70cf9 3775 switch (TREE_CODE (t))
3776 {
3777 case VAR_DECL:
3778 case PARM_DECL:
3779 case LABEL_DECL:
3780 case RESULT_DECL:
3781 if (ctx)
3782 *tp = remap_decl (t, &ctx->cb);
3783 break;
3784
3785 default:
3786 if (ctx && TYPE_P (t))
3787 *tp = remap_type (t, &ctx->cb);
3788 else if (!DECL_P (t))
7cf869dd 3789 {
3790 *walk_subtrees = 1;
3791 if (ctx)
182cf5a9 3792 {
3793 tree tem = remap_type (TREE_TYPE (t), &ctx->cb);
3794 if (tem != TREE_TYPE (t))
3795 {
3796 if (TREE_CODE (t) == INTEGER_CST)
e913b5cd 3797 *tp = wide_int_to_tree (tem, t);
182cf5a9 3798 else
3799 TREE_TYPE (t) = tem;
3800 }
3801 }
7cf869dd 3802 }
75a70cf9 3803 break;
3804 }
3805
3806 return NULL_TREE;
3807}
3808
f2697631 3809/* Return true if FNDECL is a setjmp or a longjmp. */
3810
3811static bool
3812setjmp_or_longjmp_p (const_tree fndecl)
3813{
3814 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
3815 && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_SETJMP
3816 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LONGJMP))
3817 return true;
3818
3819 tree declname = DECL_NAME (fndecl);
3820 if (!declname)
3821 return false;
3822 const char *name = IDENTIFIER_POINTER (declname);
3823 return !strcmp (name, "setjmp") || !strcmp (name, "longjmp");
3824}
3825
75a70cf9 3826
3827/* Helper function for scan_omp.
3828
ca4c3545 3829 Callback for walk_gimple_stmt used to scan for OMP directives in
75a70cf9 3830 the current statement in GSI. */
3831
3832static tree
3833scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
3834 struct walk_stmt_info *wi)
3835{
42acab1c 3836 gimple *stmt = gsi_stmt (*gsi);
75a70cf9 3837 omp_context *ctx = (omp_context *) wi->info;
3838
3839 if (gimple_has_location (stmt))
3840 input_location = gimple_location (stmt);
1e8e9920 3841
ca4c3545 3842 /* Check the nesting restrictions. */
bc7bff74 3843 bool remove = false;
3844 if (is_gimple_omp (stmt))
3845 remove = !check_omp_nesting_restrictions (stmt, ctx);
3846 else if (is_gimple_call (stmt))
3847 {
3848 tree fndecl = gimple_call_fndecl (stmt);
f2697631 3849 if (fndecl)
3850 {
3851 if (setjmp_or_longjmp_p (fndecl)
3852 && ctx
3853 && gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
10c55644 3854 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
f2697631 3855 {
3856 remove = true;
3857 error_at (gimple_location (stmt),
3858 "setjmp/longjmp inside simd construct");
3859 }
3860 else if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
3861 switch (DECL_FUNCTION_CODE (fndecl))
3862 {
3863 case BUILT_IN_GOMP_BARRIER:
3864 case BUILT_IN_GOMP_CANCEL:
3865 case BUILT_IN_GOMP_CANCELLATION_POINT:
3866 case BUILT_IN_GOMP_TASKYIELD:
3867 case BUILT_IN_GOMP_TASKWAIT:
3868 case BUILT_IN_GOMP_TASKGROUP_START:
3869 case BUILT_IN_GOMP_TASKGROUP_END:
3870 remove = !check_omp_nesting_restrictions (stmt, ctx);
3871 break;
3872 default:
3873 break;
3874 }
3875 }
bc7bff74 3876 }
3877 if (remove)
3878 {
3879 stmt = gimple_build_nop ();
3880 gsi_replace (gsi, stmt, false);
fd6481cf 3881 }
c1d127dd 3882
75a70cf9 3883 *handled_ops_p = true;
3884
3885 switch (gimple_code (stmt))
1e8e9920 3886 {
75a70cf9 3887 case GIMPLE_OMP_PARALLEL:
fd6481cf 3888 taskreg_nesting_level++;
75a70cf9 3889 scan_omp_parallel (gsi, ctx);
fd6481cf 3890 taskreg_nesting_level--;
3891 break;
3892
75a70cf9 3893 case GIMPLE_OMP_TASK:
fd6481cf 3894 taskreg_nesting_level++;
75a70cf9 3895 scan_omp_task (gsi, ctx);
fd6481cf 3896 taskreg_nesting_level--;
1e8e9920 3897 break;
3898
75a70cf9 3899 case GIMPLE_OMP_FOR:
1a91d914 3900 scan_omp_for (as_a <gomp_for *> (stmt), ctx);
1e8e9920 3901 break;
3902
75a70cf9 3903 case GIMPLE_OMP_SECTIONS:
1a91d914 3904 scan_omp_sections (as_a <gomp_sections *> (stmt), ctx);
1e8e9920 3905 break;
3906
75a70cf9 3907 case GIMPLE_OMP_SINGLE:
1a91d914 3908 scan_omp_single (as_a <gomp_single *> (stmt), ctx);
1e8e9920 3909 break;
3910
75a70cf9 3911 case GIMPLE_OMP_SECTION:
3912 case GIMPLE_OMP_MASTER:
bc7bff74 3913 case GIMPLE_OMP_TASKGROUP:
75a70cf9 3914 case GIMPLE_OMP_ORDERED:
3915 case GIMPLE_OMP_CRITICAL:
3916 ctx = new_omp_context (stmt, ctx);
ab129075 3917 scan_omp (gimple_omp_body_ptr (stmt), ctx);
1e8e9920 3918 break;
3919
bc7bff74 3920 case GIMPLE_OMP_TARGET:
1a91d914 3921 scan_omp_target (as_a <gomp_target *> (stmt), ctx);
bc7bff74 3922 break;
3923
3924 case GIMPLE_OMP_TEAMS:
1a91d914 3925 scan_omp_teams (as_a <gomp_teams *> (stmt), ctx);
bc7bff74 3926 break;
3927
75a70cf9 3928 case GIMPLE_BIND:
1e8e9920 3929 {
3930 tree var;
1e8e9920 3931
75a70cf9 3932 *handled_ops_p = false;
3933 if (ctx)
1a91d914 3934 for (var = gimple_bind_vars (as_a <gbind *> (stmt));
3935 var ;
3936 var = DECL_CHAIN (var))
75a70cf9 3937 insert_decl_map (&ctx->cb, var, var);
1e8e9920 3938 }
3939 break;
1e8e9920 3940 default:
75a70cf9 3941 *handled_ops_p = false;
1e8e9920 3942 break;
3943 }
3944
3945 return NULL_TREE;
3946}
3947
3948
75a70cf9 3949/* Scan all the statements starting at the current statement. CTX
ca4c3545 3950 contains context information about the OMP directives and
75a70cf9 3951 clauses found during the scan. */
1e8e9920 3952
3953static void
ab129075 3954scan_omp (gimple_seq *body_p, omp_context *ctx)
1e8e9920 3955{
3956 location_t saved_location;
3957 struct walk_stmt_info wi;
3958
3959 memset (&wi, 0, sizeof (wi));
1e8e9920 3960 wi.info = ctx;
1e8e9920 3961 wi.want_locations = true;
3962
3963 saved_location = input_location;
ab129075 3964 walk_gimple_seq_mod (body_p, scan_omp_1_stmt, scan_omp_1_op, &wi);
1e8e9920 3965 input_location = saved_location;
3966}
3967\f
3968/* Re-gimplification and code generation routines. */
3969
3970/* Build a call to GOMP_barrier. */
3971
42acab1c 3972static gimple *
bc7bff74 3973build_omp_barrier (tree lhs)
3974{
3975 tree fndecl = builtin_decl_explicit (lhs ? BUILT_IN_GOMP_BARRIER_CANCEL
3976 : BUILT_IN_GOMP_BARRIER);
1a91d914 3977 gcall *g = gimple_build_call (fndecl, 0);
bc7bff74 3978 if (lhs)
3979 gimple_call_set_lhs (g, lhs);
3980 return g;
1e8e9920 3981}
3982
3983/* If a context was created for STMT when it was scanned, return it. */
3984
3985static omp_context *
42acab1c 3986maybe_lookup_ctx (gimple *stmt)
1e8e9920 3987{
3988 splay_tree_node n;
3989 n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
3990 return n ? (omp_context *) n->value : NULL;
3991}
3992
773c5ba7 3993
3994/* Find the mapping for DECL in CTX or the immediately enclosing
3995 context that has a mapping for DECL.
3996
3997 If CTX is a nested parallel directive, we may have to use the decl
3998 mappings created in CTX's parent context. Suppose that we have the
3999 following parallel nesting (variable UIDs showed for clarity):
4000
4001 iD.1562 = 0;
4002 #omp parallel shared(iD.1562) -> outer parallel
4003 iD.1562 = iD.1562 + 1;
4004
4005 #omp parallel shared (iD.1562) -> inner parallel
4006 iD.1562 = iD.1562 - 1;
4007
4008 Each parallel structure will create a distinct .omp_data_s structure
4009 for copying iD.1562 in/out of the directive:
4010
4011 outer parallel .omp_data_s.1.i -> iD.1562
4012 inner parallel .omp_data_s.2.i -> iD.1562
4013
4014 A shared variable mapping will produce a copy-out operation before
4015 the parallel directive and a copy-in operation after it. So, in
4016 this case we would have:
4017
4018 iD.1562 = 0;
4019 .omp_data_o.1.i = iD.1562;
4020 #omp parallel shared(iD.1562) -> outer parallel
4021 .omp_data_i.1 = &.omp_data_o.1
4022 .omp_data_i.1->i = .omp_data_i.1->i + 1;
4023
4024 .omp_data_o.2.i = iD.1562; -> **
4025 #omp parallel shared(iD.1562) -> inner parallel
4026 .omp_data_i.2 = &.omp_data_o.2
4027 .omp_data_i.2->i = .omp_data_i.2->i - 1;
4028
4029
4030 ** This is a problem. The symbol iD.1562 cannot be referenced
4031 inside the body of the outer parallel region. But since we are
4032 emitting this copy operation while expanding the inner parallel
4033 directive, we need to access the CTX structure of the outer
4034 parallel directive to get the correct mapping:
4035
4036 .omp_data_o.2.i = .omp_data_i.1->i
4037
4038 Since there may be other workshare or parallel directives enclosing
4039 the parallel directive, it may be necessary to walk up the context
4040 parent chain. This is not a problem in general because nested
4041 parallelism happens only rarely. */
4042
4043static tree
4044lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
4045{
4046 tree t;
4047 omp_context *up;
4048
773c5ba7 4049 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
4050 t = maybe_lookup_decl (decl, up);
4051
87b31375 4052 gcc_assert (!ctx->is_nested || t || is_global_var (decl));
773c5ba7 4053
c37594c7 4054 return t ? t : decl;
773c5ba7 4055}
4056
4057
f49d7bb5 4058/* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
4059 in outer contexts. */
4060
4061static tree
4062maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
4063{
4064 tree t = NULL;
4065 omp_context *up;
4066
87b31375 4067 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
4068 t = maybe_lookup_decl (decl, up);
f49d7bb5 4069
4070 return t ? t : decl;
4071}
4072
4073
df67b98c 4074/* Construct the initialization value for reduction operation OP. */
1e8e9920 4075
4076tree
df67b98c 4077omp_reduction_init_op (location_t loc, enum tree_code op, tree type)
1e8e9920 4078{
df67b98c 4079 switch (op)
1e8e9920 4080 {
4081 case PLUS_EXPR:
4082 case MINUS_EXPR:
4083 case BIT_IOR_EXPR:
4084 case BIT_XOR_EXPR:
4085 case TRUTH_OR_EXPR:
4086 case TRUTH_ORIF_EXPR:
4087 case TRUTH_XOR_EXPR:
4088 case NE_EXPR:
385f3f36 4089 return build_zero_cst (type);
1e8e9920 4090
4091 case MULT_EXPR:
4092 case TRUTH_AND_EXPR:
4093 case TRUTH_ANDIF_EXPR:
4094 case EQ_EXPR:
389dd41b 4095 return fold_convert_loc (loc, type, integer_one_node);
1e8e9920 4096
4097 case BIT_AND_EXPR:
389dd41b 4098 return fold_convert_loc (loc, type, integer_minus_one_node);
1e8e9920 4099
4100 case MAX_EXPR:
4101 if (SCALAR_FLOAT_TYPE_P (type))
4102 {
4103 REAL_VALUE_TYPE max, min;
fe994837 4104 if (HONOR_INFINITIES (type))
1e8e9920 4105 {
4106 real_inf (&max);
4107 real_arithmetic (&min, NEGATE_EXPR, &max, NULL);
4108 }
4109 else
4110 real_maxval (&min, 1, TYPE_MODE (type));
4111 return build_real (type, min);
4112 }
5902cce5 4113 else if (POINTER_TYPE_P (type))
4114 {
4115 wide_int min
4116 = wi::min_value (TYPE_PRECISION (type), TYPE_SIGN (type));
4117 return wide_int_to_tree (type, min);
4118 }
1e8e9920 4119 else
4120 {
4121 gcc_assert (INTEGRAL_TYPE_P (type));
4122 return TYPE_MIN_VALUE (type);
4123 }
4124
4125 case MIN_EXPR:
4126 if (SCALAR_FLOAT_TYPE_P (type))
4127 {
4128 REAL_VALUE_TYPE max;
fe994837 4129 if (HONOR_INFINITIES (type))
1e8e9920 4130 real_inf (&max);
4131 else
4132 real_maxval (&max, 0, TYPE_MODE (type));
4133 return build_real (type, max);
4134 }
5902cce5 4135 else if (POINTER_TYPE_P (type))
4136 {
4137 wide_int max
4138 = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type));
4139 return wide_int_to_tree (type, max);
4140 }
1e8e9920 4141 else
4142 {
4143 gcc_assert (INTEGRAL_TYPE_P (type));
4144 return TYPE_MAX_VALUE (type);
4145 }
4146
4147 default:
4148 gcc_unreachable ();
4149 }
4150}
4151
df67b98c 4152/* Construct the initialization value for reduction CLAUSE. */
4153
4154tree
4155omp_reduction_init (tree clause, tree type)
4156{
4157 return omp_reduction_init_op (OMP_CLAUSE_LOCATION (clause),
4158 OMP_CLAUSE_REDUCTION_CODE (clause), type);
4159}
4160
bc7bff74 4161/* Return alignment to be assumed for var in CLAUSE, which should be
4162 OMP_CLAUSE_ALIGNED. */
4163
4164static tree
4165omp_clause_aligned_alignment (tree clause)
4166{
4167 if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause))
4168 return OMP_CLAUSE_ALIGNED_ALIGNMENT (clause);
4169
4170 /* Otherwise return implementation defined alignment. */
4171 unsigned int al = 1;
3754d046 4172 machine_mode mode, vmode;
bc7bff74 4173 int vs = targetm.vectorize.autovectorize_vector_sizes ();
4174 if (vs)
4175 vs = 1 << floor_log2 (vs);
4176 static enum mode_class classes[]
4177 = { MODE_INT, MODE_VECTOR_INT, MODE_FLOAT, MODE_VECTOR_FLOAT };
4178 for (int i = 0; i < 4; i += 2)
4179 for (mode = GET_CLASS_NARROWEST_MODE (classes[i]);
4180 mode != VOIDmode;
4181 mode = GET_MODE_WIDER_MODE (mode))
4182 {
4183 vmode = targetm.vectorize.preferred_simd_mode (mode);
4184 if (GET_MODE_CLASS (vmode) != classes[i + 1])
4185 continue;
4186 while (vs
4187 && GET_MODE_SIZE (vmode) < vs
4188 && GET_MODE_2XWIDER_MODE (vmode) != VOIDmode)
4189 vmode = GET_MODE_2XWIDER_MODE (vmode);
4190
4191 tree type = lang_hooks.types.type_for_mode (mode, 1);
4192 if (type == NULL_TREE || TYPE_MODE (type) != mode)
4193 continue;
4194 type = build_vector_type (type, GET_MODE_SIZE (vmode)
4195 / GET_MODE_SIZE (mode));
4196 if (TYPE_MODE (type) != vmode)
4197 continue;
4198 if (TYPE_ALIGN_UNIT (type) > al)
4199 al = TYPE_ALIGN_UNIT (type);
4200 }
4201 return build_int_cst (integer_type_node, al);
4202}
4203
3d483a94 4204/* Return maximum possible vectorization factor for the target. */
4205
4206static int
4207omp_max_vf (void)
4208{
4209 if (!optimize
4210 || optimize_debug
ad45e43e 4211 || !flag_tree_loop_optimize
043115ec 4212 || (!flag_tree_loop_vectorize
4213 && (global_options_set.x_flag_tree_loop_vectorize
4214 || global_options_set.x_flag_tree_vectorize)))
3d483a94 4215 return 1;
4216
4217 int vs = targetm.vectorize.autovectorize_vector_sizes ();
4218 if (vs)
4219 {
4220 vs = 1 << floor_log2 (vs);
4221 return vs;
4222 }
3754d046 4223 machine_mode vqimode = targetm.vectorize.preferred_simd_mode (QImode);
3d483a94 4224 if (GET_MODE_CLASS (vqimode) == MODE_VECTOR_INT)
4225 return GET_MODE_NUNITS (vqimode);
4226 return 1;
4227}
4228
4229/* Helper function of lower_rec_input_clauses, used for #pragma omp simd
4230 privatization. */
4231
4232static bool
4233lower_rec_simd_input_clauses (tree new_var, omp_context *ctx, int &max_vf,
4234 tree &idx, tree &lane, tree &ivar, tree &lvar)
4235{
4236 if (max_vf == 0)
4237 {
4238 max_vf = omp_max_vf ();
4239 if (max_vf > 1)
4240 {
4241 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
4242 OMP_CLAUSE_SAFELEN);
c3f3b68d 4243 if (c && TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) != INTEGER_CST)
4244 max_vf = 1;
4245 else if (c && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
4246 max_vf) == -1)
d85a2013 4247 max_vf = tree_to_shwi (OMP_CLAUSE_SAFELEN_EXPR (c));
3d483a94 4248 }
4249 if (max_vf > 1)
4250 {
f9e245b2 4251 idx = create_tmp_var (unsigned_type_node);
4252 lane = create_tmp_var (unsigned_type_node);
3d483a94 4253 }
4254 }
4255 if (max_vf == 1)
4256 return false;
4257
4258 tree atype = build_array_type_nelts (TREE_TYPE (new_var), max_vf);
f9e245b2 4259 tree avar = create_tmp_var_raw (atype);
3d483a94 4260 if (TREE_ADDRESSABLE (new_var))
4261 TREE_ADDRESSABLE (avar) = 1;
4262 DECL_ATTRIBUTES (avar)
4263 = tree_cons (get_identifier ("omp simd array"), NULL,
4264 DECL_ATTRIBUTES (avar));
4265 gimple_add_tmp_var (avar);
4266 ivar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, idx,
4267 NULL_TREE, NULL_TREE);
4268 lvar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, lane,
4269 NULL_TREE, NULL_TREE);
bc7bff74 4270 if (DECL_P (new_var))
4271 {
4272 SET_DECL_VALUE_EXPR (new_var, lvar);
4273 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4274 }
3d483a94 4275 return true;
4276}
4277
2712b6de 4278/* Helper function of lower_rec_input_clauses. For a reference
4279 in simd reduction, add an underlying variable it will reference. */
4280
4281static void
4282handle_simd_reference (location_t loc, tree new_vard, gimple_seq *ilist)
4283{
4284 tree z = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard)));
4285 if (TREE_CONSTANT (z))
4286 {
43895be5 4287 z = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_vard)),
4288 get_name (new_vard));
2712b6de 4289 gimple_add_tmp_var (z);
4290 TREE_ADDRESSABLE (z) = 1;
4291 z = build_fold_addr_expr_loc (loc, z);
4292 gimplify_assign (new_vard, z, ilist);
4293 }
4294}
4295
1e8e9920 4296/* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
4297 from the receiver (aka child) side and initializers for REFERENCE_TYPE
4298 private variables. Initialization statements go in ILIST, while calls
4299 to destructors go in DLIST. */
4300
4301static void
75a70cf9 4302lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
bc7bff74 4303 omp_context *ctx, struct omp_for_data *fd)
1e8e9920 4304{
c2f47e15 4305 tree c, dtor, copyin_seq, x, ptr;
1e8e9920 4306 bool copyin_by_ref = false;
f49d7bb5 4307 bool lastprivate_firstprivate = false;
bc7bff74 4308 bool reduction_omp_orig_ref = false;
1e8e9920 4309 int pass;
3d483a94 4310 bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
10c55644 4311 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD);
3d483a94 4312 int max_vf = 0;
4313 tree lane = NULL_TREE, idx = NULL_TREE;
4314 tree ivar = NULL_TREE, lvar = NULL_TREE;
4315 gimple_seq llist[2] = { NULL, NULL };
1e8e9920 4316
1e8e9920 4317 copyin_seq = NULL;
4318
3d483a94 4319 /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
4320 with data sharing clauses referencing variable sized vars. That
4321 is unnecessarily hard to support and very unlikely to result in
4322 vectorized code anyway. */
4323 if (is_simd)
4324 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4325 switch (OMP_CLAUSE_CODE (c))
4326 {
9580cb79 4327 case OMP_CLAUSE_LINEAR:
4328 if (OMP_CLAUSE_LINEAR_ARRAY (c))
4329 max_vf = 1;
4330 /* FALLTHRU */
3d483a94 4331 case OMP_CLAUSE_PRIVATE:
4332 case OMP_CLAUSE_FIRSTPRIVATE:
4333 case OMP_CLAUSE_LASTPRIVATE:
3d483a94 4334 if (is_variable_sized (OMP_CLAUSE_DECL (c)))
4335 max_vf = 1;
4336 break;
43895be5 4337 case OMP_CLAUSE_REDUCTION:
4338 if (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF
4339 || is_variable_sized (OMP_CLAUSE_DECL (c)))
4340 max_vf = 1;
4341 break;
3d483a94 4342 default:
4343 continue;
4344 }
4345
1e8e9920 4346 /* Do all the fixed sized types in the first pass, and the variable sized
4347 types in the second pass. This makes sure that the scalar arguments to
48e1416a 4348 the variable sized types are processed before we use them in the
1e8e9920 4349 variable sized operations. */
4350 for (pass = 0; pass < 2; ++pass)
4351 {
4352 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4353 {
55d6e7cd 4354 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
1e8e9920 4355 tree var, new_var;
4356 bool by_ref;
389dd41b 4357 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
1e8e9920 4358
4359 switch (c_kind)
4360 {
4361 case OMP_CLAUSE_PRIVATE:
4362 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
4363 continue;
4364 break;
4365 case OMP_CLAUSE_SHARED:
bc7bff74 4366 /* Ignore shared directives in teams construct. */
4367 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
4368 continue;
f49d7bb5 4369 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
4370 {
43895be5 4371 gcc_assert (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c)
4372 || is_global_var (OMP_CLAUSE_DECL (c)));
f49d7bb5 4373 continue;
4374 }
1e8e9920 4375 case OMP_CLAUSE_FIRSTPRIVATE:
1e8e9920 4376 case OMP_CLAUSE_COPYIN:
43895be5 4377 break;
bc7bff74 4378 case OMP_CLAUSE_LINEAR:
43895be5 4379 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c)
4380 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
4381 lastprivate_firstprivate = true;
bc7bff74 4382 break;
1e8e9920 4383 case OMP_CLAUSE_REDUCTION:
bc7bff74 4384 if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
4385 reduction_omp_orig_ref = true;
1e8e9920 4386 break;
bc7bff74 4387 case OMP_CLAUSE__LOOPTEMP_:
43895be5 4388 /* Handle _looptemp_ clauses only on parallel/task. */
bc7bff74 4389 if (fd)
4390 continue;
3d483a94 4391 break;
df2c34fc 4392 case OMP_CLAUSE_LASTPRIVATE:
f49d7bb5 4393 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4394 {
4395 lastprivate_firstprivate = true;
43895be5 4396 if (pass != 0 || is_taskloop_ctx (ctx))
f49d7bb5 4397 continue;
4398 }
cf5f881f 4399 /* Even without corresponding firstprivate, if
4400 decl is Fortran allocatable, it needs outer var
4401 reference. */
4402 else if (pass == 0
4403 && lang_hooks.decls.omp_private_outer_ref
4404 (OMP_CLAUSE_DECL (c)))
4405 lastprivate_firstprivate = true;
df2c34fc 4406 break;
bc7bff74 4407 case OMP_CLAUSE_ALIGNED:
4408 if (pass == 0)
4409 continue;
4410 var = OMP_CLAUSE_DECL (c);
4411 if (TREE_CODE (TREE_TYPE (var)) == POINTER_TYPE
4412 && !is_global_var (var))
4413 {
4414 new_var = maybe_lookup_decl (var, ctx);
4415 if (new_var == NULL_TREE)
4416 new_var = maybe_lookup_decl_in_outer_ctx (var, ctx);
4417 x = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
4418 x = build_call_expr_loc (clause_loc, x, 2, new_var,
4419 omp_clause_aligned_alignment (c));
4420 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
4421 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
4422 gimplify_and_add (x, ilist);
4423 }
4424 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
4425 && is_global_var (var))
4426 {
4427 tree ptype = build_pointer_type (TREE_TYPE (var)), t, t2;
4428 new_var = lookup_decl (var, ctx);
4429 t = maybe_lookup_decl_in_outer_ctx (var, ctx);
4430 t = build_fold_addr_expr_loc (clause_loc, t);
4431 t2 = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
4432 t = build_call_expr_loc (clause_loc, t2, 2, t,
4433 omp_clause_aligned_alignment (c));
4434 t = fold_convert_loc (clause_loc, ptype, t);
f9e245b2 4435 x = create_tmp_var (ptype);
bc7bff74 4436 t = build2 (MODIFY_EXPR, ptype, x, t);
4437 gimplify_and_add (t, ilist);
4438 t = build_simple_mem_ref_loc (clause_loc, x);
4439 SET_DECL_VALUE_EXPR (new_var, t);
4440 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4441 }
4442 continue;
1e8e9920 4443 default:
4444 continue;
4445 }
4446
4447 new_var = var = OMP_CLAUSE_DECL (c);
43895be5 4448 if (c_kind == OMP_CLAUSE_REDUCTION && TREE_CODE (var) == MEM_REF)
4449 {
4450 var = TREE_OPERAND (var, 0);
9561765e 4451 if (TREE_CODE (var) == POINTER_PLUS_EXPR)
4452 var = TREE_OPERAND (var, 0);
43895be5 4453 if (TREE_CODE (var) == INDIRECT_REF
4454 || TREE_CODE (var) == ADDR_EXPR)
4455 var = TREE_OPERAND (var, 0);
4456 if (is_variable_sized (var))
4457 {
4458 gcc_assert (DECL_HAS_VALUE_EXPR_P (var));
4459 var = DECL_VALUE_EXPR (var);
4460 gcc_assert (TREE_CODE (var) == INDIRECT_REF);
4461 var = TREE_OPERAND (var, 0);
4462 gcc_assert (DECL_P (var));
4463 }
4464 new_var = var;
4465 }
1e8e9920 4466 if (c_kind != OMP_CLAUSE_COPYIN)
4467 new_var = lookup_decl (var, ctx);
4468
4469 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
4470 {
4471 if (pass != 0)
4472 continue;
4473 }
43895be5 4474 /* C/C++ array section reductions. */
4475 else if (c_kind == OMP_CLAUSE_REDUCTION
4476 && var != OMP_CLAUSE_DECL (c))
1e8e9920 4477 {
4478 if (pass == 0)
4479 continue;
4480
9561765e 4481 tree bias = TREE_OPERAND (OMP_CLAUSE_DECL (c), 1);
43895be5 4482 tree orig_var = TREE_OPERAND (OMP_CLAUSE_DECL (c), 0);
9561765e 4483 if (TREE_CODE (orig_var) == POINTER_PLUS_EXPR)
4484 {
4485 tree b = TREE_OPERAND (orig_var, 1);
4486 b = maybe_lookup_decl (b, ctx);
4487 if (b == NULL)
4488 {
4489 b = TREE_OPERAND (orig_var, 1);
4490 b = maybe_lookup_decl_in_outer_ctx (b, ctx);
4491 }
4492 if (integer_zerop (bias))
4493 bias = b;
4494 else
4495 {
4496 bias = fold_convert_loc (clause_loc,
4497 TREE_TYPE (b), bias);
4498 bias = fold_build2_loc (clause_loc, PLUS_EXPR,
4499 TREE_TYPE (b), b, bias);
4500 }
4501 orig_var = TREE_OPERAND (orig_var, 0);
4502 }
43895be5 4503 if (TREE_CODE (orig_var) == INDIRECT_REF
4504 || TREE_CODE (orig_var) == ADDR_EXPR)
4505 orig_var = TREE_OPERAND (orig_var, 0);
4506 tree d = OMP_CLAUSE_DECL (c);
4507 tree type = TREE_TYPE (d);
4508 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
4509 tree v = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
4510 const char *name = get_name (orig_var);
4511 if (TREE_CONSTANT (v))
fd6481cf 4512 {
43895be5 4513 x = create_tmp_var_raw (type, name);
4514 gimple_add_tmp_var (x);
4515 TREE_ADDRESSABLE (x) = 1;
4516 x = build_fold_addr_expr_loc (clause_loc, x);
4517 }
4518 else
4519 {
4520 tree atmp
4521 = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
4522 tree t = maybe_lookup_decl (v, ctx);
4523 if (t)
4524 v = t;
4525 else
4526 v = maybe_lookup_decl_in_outer_ctx (v, ctx);
4527 gimplify_expr (&v, ilist, NULL, is_gimple_val, fb_rvalue);
4528 t = fold_build2_loc (clause_loc, PLUS_EXPR,
4529 TREE_TYPE (v), v,
4530 build_int_cst (TREE_TYPE (v), 1));
4531 t = fold_build2_loc (clause_loc, MULT_EXPR,
4532 TREE_TYPE (v), t,
4533 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4534 tree al = size_int (TYPE_ALIGN (TREE_TYPE (type)));
4535 x = build_call_expr_loc (clause_loc, atmp, 2, t, al);
4536 }
4537
4538 tree ptype = build_pointer_type (TREE_TYPE (type));
4539 x = fold_convert_loc (clause_loc, ptype, x);
4540 tree y = create_tmp_var (ptype, name);
4541 gimplify_assign (y, x, ilist);
4542 x = y;
9561765e 4543 tree yb = y;
4544
4545 if (!integer_zerop (bias))
4546 {
219e09fc 4547 bias = fold_convert_loc (clause_loc, pointer_sized_int_node,
4548 bias);
4549 yb = fold_convert_loc (clause_loc, pointer_sized_int_node,
4550 x);
4551 yb = fold_build2_loc (clause_loc, MINUS_EXPR,
4552 pointer_sized_int_node, yb, bias);
4553 x = fold_convert_loc (clause_loc, TREE_TYPE (x), yb);
9561765e 4554 yb = create_tmp_var (ptype, name);
4555 gimplify_assign (yb, x, ilist);
4556 x = yb;
4557 }
4558
4559 d = TREE_OPERAND (d, 0);
4560 if (TREE_CODE (d) == POINTER_PLUS_EXPR)
4561 d = TREE_OPERAND (d, 0);
4562 if (TREE_CODE (d) == ADDR_EXPR)
43895be5 4563 {
4564 if (orig_var != var)
4565 {
4566 gcc_assert (is_variable_sized (orig_var));
4567 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var),
4568 x);
4569 gimplify_assign (new_var, x, ilist);
4570 tree new_orig_var = lookup_decl (orig_var, ctx);
4571 tree t = build_fold_indirect_ref (new_var);
4572 DECL_IGNORED_P (new_var) = 0;
4573 TREE_THIS_NOTRAP (t);
4574 SET_DECL_VALUE_EXPR (new_orig_var, t);
4575 DECL_HAS_VALUE_EXPR_P (new_orig_var) = 1;
4576 }
4577 else
4578 {
4579 x = build2 (MEM_REF, TREE_TYPE (new_var), x,
4580 build_int_cst (ptype, 0));
4581 SET_DECL_VALUE_EXPR (new_var, x);
4582 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4583 }
4584 }
4585 else
4586 {
4587 gcc_assert (orig_var == var);
9561765e 4588 if (TREE_CODE (d) == INDIRECT_REF)
43895be5 4589 {
4590 x = create_tmp_var (ptype, name);
4591 TREE_ADDRESSABLE (x) = 1;
9561765e 4592 gimplify_assign (x, yb, ilist);
43895be5 4593 x = build_fold_addr_expr_loc (clause_loc, x);
4594 }
4595 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
4596 gimplify_assign (new_var, x, ilist);
4597 }
4598 tree y1 = create_tmp_var (ptype, NULL);
4599 gimplify_assign (y1, y, ilist);
4600 tree i2 = NULL_TREE, y2 = NULL_TREE;
4601 tree body2 = NULL_TREE, end2 = NULL_TREE;
4602 tree y3 = NULL_TREE, y4 = NULL_TREE;
4603 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) || is_simd)
4604 {
4605 y2 = create_tmp_var (ptype, NULL);
4606 gimplify_assign (y2, y, ilist);
4607 tree ref = build_outer_var_ref (var, ctx);
4608 /* For ref build_outer_var_ref already performs this. */
9561765e 4609 if (TREE_CODE (d) == INDIRECT_REF)
43895be5 4610 gcc_assert (is_reference (var));
9561765e 4611 else if (TREE_CODE (d) == ADDR_EXPR)
43895be5 4612 ref = build_fold_addr_expr (ref);
4613 else if (is_reference (var))
4614 ref = build_fold_addr_expr (ref);
4615 ref = fold_convert_loc (clause_loc, ptype, ref);
4616 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
4617 && OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
4618 {
4619 y3 = create_tmp_var (ptype, NULL);
4620 gimplify_assign (y3, unshare_expr (ref), ilist);
4621 }
4622 if (is_simd)
4623 {
4624 y4 = create_tmp_var (ptype, NULL);
4625 gimplify_assign (y4, ref, dlist);
4626 }
4627 }
4628 tree i = create_tmp_var (TREE_TYPE (v), NULL);
4629 gimplify_assign (i, build_int_cst (TREE_TYPE (v), 0), ilist);
4630 tree body = create_artificial_label (UNKNOWN_LOCATION);
4631 tree end = create_artificial_label (UNKNOWN_LOCATION);
4632 gimple_seq_add_stmt (ilist, gimple_build_label (body));
4633 if (y2)
4634 {
4635 i2 = create_tmp_var (TREE_TYPE (v), NULL);
4636 gimplify_assign (i2, build_int_cst (TREE_TYPE (v), 0), dlist);
4637 body2 = create_artificial_label (UNKNOWN_LOCATION);
4638 end2 = create_artificial_label (UNKNOWN_LOCATION);
4639 gimple_seq_add_stmt (dlist, gimple_build_label (body2));
4640 }
4641 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4642 {
4643 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
4644 tree decl_placeholder
4645 = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c);
4646 SET_DECL_VALUE_EXPR (decl_placeholder,
4647 build_simple_mem_ref (y1));
4648 DECL_HAS_VALUE_EXPR_P (decl_placeholder) = 1;
4649 SET_DECL_VALUE_EXPR (placeholder,
4650 y3 ? build_simple_mem_ref (y3)
4651 : error_mark_node);
4652 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
4653 x = lang_hooks.decls.omp_clause_default_ctor
4654 (c, build_simple_mem_ref (y1),
4655 y3 ? build_simple_mem_ref (y3) : NULL_TREE);
4656 if (x)
4657 gimplify_and_add (x, ilist);
4658 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
4659 {
4660 gimple_seq tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
4661 lower_omp (&tseq, ctx);
4662 gimple_seq_add_seq (ilist, tseq);
4663 }
4664 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
4665 if (is_simd)
4666 {
4667 SET_DECL_VALUE_EXPR (decl_placeholder,
4668 build_simple_mem_ref (y2));
4669 SET_DECL_VALUE_EXPR (placeholder,
4670 build_simple_mem_ref (y4));
4671 gimple_seq tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
4672 lower_omp (&tseq, ctx);
4673 gimple_seq_add_seq (dlist, tseq);
4674 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4675 }
4676 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
4677 DECL_HAS_VALUE_EXPR_P (decl_placeholder) = 0;
4678 x = lang_hooks.decls.omp_clause_dtor
4679 (c, build_simple_mem_ref (y2));
4680 if (x)
4681 {
4682 gimple_seq tseq = NULL;
4683 dtor = x;
4684 gimplify_stmt (&dtor, &tseq);
4685 gimple_seq_add_seq (dlist, tseq);
4686 }
4687 }
4688 else
4689 {
4690 x = omp_reduction_init (c, TREE_TYPE (type));
4691 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
4692
4693 /* reduction(-:var) sums up the partial results, so it
4694 acts identically to reduction(+:var). */
4695 if (code == MINUS_EXPR)
4696 code = PLUS_EXPR;
4697
4698 gimplify_assign (build_simple_mem_ref (y1), x, ilist);
4699 if (is_simd)
4700 {
4701 x = build2 (code, TREE_TYPE (type),
4702 build_simple_mem_ref (y4),
4703 build_simple_mem_ref (y2));
4704 gimplify_assign (build_simple_mem_ref (y4), x, dlist);
4705 }
4706 }
4707 gimple *g
4708 = gimple_build_assign (y1, POINTER_PLUS_EXPR, y1,
4709 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4710 gimple_seq_add_stmt (ilist, g);
4711 if (y3)
4712 {
4713 g = gimple_build_assign (y3, POINTER_PLUS_EXPR, y3,
4714 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4715 gimple_seq_add_stmt (ilist, g);
4716 }
4717 g = gimple_build_assign (i, PLUS_EXPR, i,
4718 build_int_cst (TREE_TYPE (i), 1));
4719 gimple_seq_add_stmt (ilist, g);
4720 g = gimple_build_cond (LE_EXPR, i, v, body, end);
4721 gimple_seq_add_stmt (ilist, g);
4722 gimple_seq_add_stmt (ilist, gimple_build_label (end));
4723 if (y2)
4724 {
4725 g = gimple_build_assign (y2, POINTER_PLUS_EXPR, y2,
4726 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4727 gimple_seq_add_stmt (dlist, g);
4728 if (y4)
4729 {
4730 g = gimple_build_assign
4731 (y4, POINTER_PLUS_EXPR, y4,
4732 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4733 gimple_seq_add_stmt (dlist, g);
4734 }
4735 g = gimple_build_assign (i2, PLUS_EXPR, i2,
4736 build_int_cst (TREE_TYPE (i2), 1));
4737 gimple_seq_add_stmt (dlist, g);
4738 g = gimple_build_cond (LE_EXPR, i2, v, body2, end2);
4739 gimple_seq_add_stmt (dlist, g);
4740 gimple_seq_add_stmt (dlist, gimple_build_label (end2));
4741 }
4742 continue;
4743 }
4744 else if (is_variable_sized (var))
4745 {
4746 /* For variable sized types, we need to allocate the
4747 actual storage here. Call alloca and store the
4748 result in the pointer decl that we created elsewhere. */
4749 if (pass == 0)
4750 continue;
4751
4752 if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
4753 {
4754 gcall *stmt;
4755 tree tmp, atmp;
4756
4757 ptr = DECL_VALUE_EXPR (new_var);
4758 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
4759 ptr = TREE_OPERAND (ptr, 0);
fd6481cf 4760 gcc_assert (DECL_P (ptr));
4761 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
75a70cf9 4762
4763 /* void *tmp = __builtin_alloca */
43895be5 4764 atmp = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
4765 stmt = gimple_build_call (atmp, 2, x,
4766 size_int (DECL_ALIGN (var)));
f9e245b2 4767 tmp = create_tmp_var_raw (ptr_type_node);
75a70cf9 4768 gimple_add_tmp_var (tmp);
4769 gimple_call_set_lhs (stmt, tmp);
4770
4771 gimple_seq_add_stmt (ilist, stmt);
4772
389dd41b 4773 x = fold_convert_loc (clause_loc, TREE_TYPE (ptr), tmp);
75a70cf9 4774 gimplify_assign (ptr, x, ilist);
fd6481cf 4775 }
1e8e9920 4776 }
b656be3a 4777 else if (is_reference (var) && !is_oacc_parallel (ctx))
1e8e9920 4778 {
773c5ba7 4779 /* For references that are being privatized for Fortran,
4780 allocate new backing storage for the new pointer
4781 variable. This allows us to avoid changing all the
4782 code that expects a pointer to something that expects
bc7bff74 4783 a direct variable. */
1e8e9920 4784 if (pass == 0)
4785 continue;
4786
4787 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
fd6481cf 4788 if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx))
4789 {
4790 x = build_receiver_ref (var, false, ctx);
389dd41b 4791 x = build_fold_addr_expr_loc (clause_loc, x);
fd6481cf 4792 }
4793 else if (TREE_CONSTANT (x))
1e8e9920 4794 {
2712b6de 4795 /* For reduction in SIMD loop, defer adding the
4796 initialization of the reference, because if we decide
4797 to use SIMD array for it, the initilization could cause
4798 expansion ICE. */
4799 if (c_kind == OMP_CLAUSE_REDUCTION && is_simd)
09d1c205 4800 x = NULL_TREE;
4801 else
4802 {
09d1c205 4803 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
43895be5 4804 get_name (var));
09d1c205 4805 gimple_add_tmp_var (x);
4806 TREE_ADDRESSABLE (x) = 1;
4807 x = build_fold_addr_expr_loc (clause_loc, x);
4808 }
1e8e9920 4809 }
4810 else
4811 {
43895be5 4812 tree atmp
4813 = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
4814 tree rtype = TREE_TYPE (TREE_TYPE (new_var));
4815 tree al = size_int (TYPE_ALIGN (rtype));
4816 x = build_call_expr_loc (clause_loc, atmp, 2, x, al);
1e8e9920 4817 }
4818
09d1c205 4819 if (x)
4820 {
4821 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
4822 gimplify_assign (new_var, x, ilist);
4823 }
1e8e9920 4824
182cf5a9 4825 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
1e8e9920 4826 }
4827 else if (c_kind == OMP_CLAUSE_REDUCTION
4828 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4829 {
4830 if (pass == 0)
4831 continue;
4832 }
4833 else if (pass != 0)
4834 continue;
4835
55d6e7cd 4836 switch (OMP_CLAUSE_CODE (c))
1e8e9920 4837 {
4838 case OMP_CLAUSE_SHARED:
bc7bff74 4839 /* Ignore shared directives in teams construct. */
4840 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
4841 continue;
f49d7bb5 4842 /* Shared global vars are just accessed directly. */
4843 if (is_global_var (new_var))
4844 break;
43895be5 4845 /* For taskloop firstprivate/lastprivate, represented
4846 as firstprivate and shared clause on the task, new_var
4847 is the firstprivate var. */
4848 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
4849 break;
1e8e9920 4850 /* Set up the DECL_VALUE_EXPR for shared variables now. This
4851 needs to be delayed until after fixup_child_record_type so
4852 that we get the correct type during the dereference. */
e8a588af 4853 by_ref = use_pointer_for_field (var, ctx);
1e8e9920 4854 x = build_receiver_ref (var, by_ref, ctx);
4855 SET_DECL_VALUE_EXPR (new_var, x);
4856 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4857
4858 /* ??? If VAR is not passed by reference, and the variable
4859 hasn't been initialized yet, then we'll get a warning for
4860 the store into the omp_data_s structure. Ideally, we'd be
48e1416a 4861 able to notice this and not store anything at all, but
1e8e9920 4862 we're generating code too early. Suppress the warning. */
4863 if (!by_ref)
4864 TREE_NO_WARNING (var) = 1;
4865 break;
4866
4867 case OMP_CLAUSE_LASTPRIVATE:
4868 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4869 break;
4870 /* FALLTHRU */
4871
4872 case OMP_CLAUSE_PRIVATE:
fd6481cf 4873 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE)
4874 x = build_outer_var_ref (var, ctx);
4875 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
4876 {
4877 if (is_task_ctx (ctx))
4878 x = build_receiver_ref (var, false, ctx);
4879 else
4880 x = build_outer_var_ref (var, ctx);
4881 }
4882 else
4883 x = NULL;
3d483a94 4884 do_private:
bc7bff74 4885 tree nx;
43895be5 4886 nx = lang_hooks.decls.omp_clause_default_ctor
4887 (c, unshare_expr (new_var), x);
3d483a94 4888 if (is_simd)
4889 {
4890 tree y = lang_hooks.decls.omp_clause_dtor (c, new_var);
bc7bff74 4891 if ((TREE_ADDRESSABLE (new_var) || nx || y
3d483a94 4892 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
4893 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4894 idx, lane, ivar, lvar))
4895 {
bc7bff74 4896 if (nx)
3d483a94 4897 x = lang_hooks.decls.omp_clause_default_ctor
4898 (c, unshare_expr (ivar), x);
bc7bff74 4899 if (nx && x)
3d483a94 4900 gimplify_and_add (x, &llist[0]);
4901 if (y)
4902 {
4903 y = lang_hooks.decls.omp_clause_dtor (c, ivar);
4904 if (y)
4905 {
4906 gimple_seq tseq = NULL;
4907
4908 dtor = y;
4909 gimplify_stmt (&dtor, &tseq);
4910 gimple_seq_add_seq (&llist[1], tseq);
4911 }
4912 }
4913 break;
4914 }
4915 }
bc7bff74 4916 if (nx)
4917 gimplify_and_add (nx, ilist);
1e8e9920 4918 /* FALLTHRU */
4919
4920 do_dtor:
4921 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
4922 if (x)
4923 {
75a70cf9 4924 gimple_seq tseq = NULL;
4925
1e8e9920 4926 dtor = x;
75a70cf9 4927 gimplify_stmt (&dtor, &tseq);
e3a19533 4928 gimple_seq_add_seq (dlist, tseq);
1e8e9920 4929 }
4930 break;
4931
3d483a94 4932 case OMP_CLAUSE_LINEAR:
4933 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c))
4934 goto do_firstprivate;
4935 if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
4936 x = NULL;
4937 else
4938 x = build_outer_var_ref (var, ctx);
4939 goto do_private;
4940
1e8e9920 4941 case OMP_CLAUSE_FIRSTPRIVATE:
fd6481cf 4942 if (is_task_ctx (ctx))
4943 {
4944 if (is_reference (var) || is_variable_sized (var))
4945 goto do_dtor;
4946 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var,
4947 ctx))
4948 || use_pointer_for_field (var, NULL))
4949 {
4950 x = build_receiver_ref (var, false, ctx);
4951 SET_DECL_VALUE_EXPR (new_var, x);
4952 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4953 goto do_dtor;
4954 }
4955 }
3d483a94 4956 do_firstprivate:
1e8e9920 4957 x = build_outer_var_ref (var, ctx);
3d483a94 4958 if (is_simd)
4959 {
bc7bff74 4960 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
4961 && gimple_omp_for_combined_into_p (ctx->stmt))
4962 {
9580cb79 4963 tree t = OMP_CLAUSE_LINEAR_STEP (c);
4964 tree stept = TREE_TYPE (t);
4965 tree ct = find_omp_clause (clauses,
4966 OMP_CLAUSE__LOOPTEMP_);
4967 gcc_assert (ct);
4968 tree l = OMP_CLAUSE_DECL (ct);
e471cc6f 4969 tree n1 = fd->loop.n1;
4970 tree step = fd->loop.step;
4971 tree itype = TREE_TYPE (l);
4972 if (POINTER_TYPE_P (itype))
4973 itype = signed_type_for (itype);
4974 l = fold_build2 (MINUS_EXPR, itype, l, n1);
4975 if (TYPE_UNSIGNED (itype)
4976 && fd->loop.cond_code == GT_EXPR)
4977 l = fold_build2 (TRUNC_DIV_EXPR, itype,
4978 fold_build1 (NEGATE_EXPR, itype, l),
4979 fold_build1 (NEGATE_EXPR,
4980 itype, step));
4981 else
4982 l = fold_build2 (TRUNC_DIV_EXPR, itype, l, step);
bc7bff74 4983 t = fold_build2 (MULT_EXPR, stept,
4984 fold_convert (stept, l), t);
9580cb79 4985
4986 if (OMP_CLAUSE_LINEAR_ARRAY (c))
4987 {
4988 x = lang_hooks.decls.omp_clause_linear_ctor
4989 (c, new_var, x, t);
4990 gimplify_and_add (x, ilist);
4991 goto do_dtor;
4992 }
4993
bc7bff74 4994 if (POINTER_TYPE_P (TREE_TYPE (x)))
4995 x = fold_build2 (POINTER_PLUS_EXPR,
4996 TREE_TYPE (x), x, t);
4997 else
4998 x = fold_build2 (PLUS_EXPR, TREE_TYPE (x), x, t);
4999 }
5000
3d483a94 5001 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
5002 || TREE_ADDRESSABLE (new_var))
5003 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
5004 idx, lane, ivar, lvar))
5005 {
5006 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR)
5007 {
f9e245b2 5008 tree iv = create_tmp_var (TREE_TYPE (new_var));
3d483a94 5009 x = lang_hooks.decls.omp_clause_copy_ctor (c, iv, x);
5010 gimplify_and_add (x, ilist);
5011 gimple_stmt_iterator gsi
5012 = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
1a91d914 5013 gassign *g
3d483a94 5014 = gimple_build_assign (unshare_expr (lvar), iv);
5015 gsi_insert_before_without_update (&gsi, g,
5016 GSI_SAME_STMT);
9580cb79 5017 tree t = OMP_CLAUSE_LINEAR_STEP (c);
3d483a94 5018 enum tree_code code = PLUS_EXPR;
5019 if (POINTER_TYPE_P (TREE_TYPE (new_var)))
5020 code = POINTER_PLUS_EXPR;
e9cf809e 5021 g = gimple_build_assign (iv, code, iv, t);
3d483a94 5022 gsi_insert_before_without_update (&gsi, g,
5023 GSI_SAME_STMT);
5024 break;
5025 }
5026 x = lang_hooks.decls.omp_clause_copy_ctor
5027 (c, unshare_expr (ivar), x);
5028 gimplify_and_add (x, &llist[0]);
5029 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
5030 if (x)
5031 {
5032 gimple_seq tseq = NULL;
5033
5034 dtor = x;
5035 gimplify_stmt (&dtor, &tseq);
5036 gimple_seq_add_seq (&llist[1], tseq);
5037 }
5038 break;
5039 }
5040 }
43895be5 5041 x = lang_hooks.decls.omp_clause_copy_ctor
5042 (c, unshare_expr (new_var), x);
1e8e9920 5043 gimplify_and_add (x, ilist);
5044 goto do_dtor;
1e8e9920 5045
bc7bff74 5046 case OMP_CLAUSE__LOOPTEMP_:
43895be5 5047 gcc_assert (is_taskreg_ctx (ctx));
bc7bff74 5048 x = build_outer_var_ref (var, ctx);
5049 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
5050 gimplify_and_add (x, ilist);
5051 break;
5052
1e8e9920 5053 case OMP_CLAUSE_COPYIN:
e8a588af 5054 by_ref = use_pointer_for_field (var, NULL);
1e8e9920 5055 x = build_receiver_ref (var, by_ref, ctx);
5056 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
5057 append_to_statement_list (x, &copyin_seq);
5058 copyin_by_ref |= by_ref;
5059 break;
5060
5061 case OMP_CLAUSE_REDUCTION:
641a0fa1 5062 /* OpenACC reductions are initialized using the
5063 GOACC_REDUCTION internal function. */
5064 if (is_gimple_omp_oacc (ctx->stmt))
5065 break;
1e8e9920 5066 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
5067 {
fd6481cf 5068 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
42acab1c 5069 gimple *tseq;
fd6481cf 5070 x = build_outer_var_ref (var, ctx);
5071
bc7bff74 5072 if (is_reference (var)
5073 && !useless_type_conversion_p (TREE_TYPE (placeholder),
5074 TREE_TYPE (x)))
389dd41b 5075 x = build_fold_addr_expr_loc (clause_loc, x);
fd6481cf 5076 SET_DECL_VALUE_EXPR (placeholder, x);
5077 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
bc7bff74 5078 tree new_vard = new_var;
5079 if (is_reference (var))
5080 {
5081 gcc_assert (TREE_CODE (new_var) == MEM_REF);
5082 new_vard = TREE_OPERAND (new_var, 0);
5083 gcc_assert (DECL_P (new_vard));
5084 }
3d483a94 5085 if (is_simd
5086 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
5087 idx, lane, ivar, lvar))
5088 {
bc7bff74 5089 if (new_vard == new_var)
5090 {
5091 gcc_assert (DECL_VALUE_EXPR (new_var) == lvar);
5092 SET_DECL_VALUE_EXPR (new_var, ivar);
5093 }
5094 else
5095 {
5096 SET_DECL_VALUE_EXPR (new_vard,
5097 build_fold_addr_expr (ivar));
5098 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
5099 }
5100 x = lang_hooks.decls.omp_clause_default_ctor
5101 (c, unshare_expr (ivar),
5102 build_outer_var_ref (var, ctx));
5103 if (x)
5104 gimplify_and_add (x, &llist[0]);
5105 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
5106 {
5107 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
5108 lower_omp (&tseq, ctx);
5109 gimple_seq_add_seq (&llist[0], tseq);
5110 }
5111 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
5112 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
5113 lower_omp (&tseq, ctx);
5114 gimple_seq_add_seq (&llist[1], tseq);
5115 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
5116 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
5117 if (new_vard == new_var)
5118 SET_DECL_VALUE_EXPR (new_var, lvar);
5119 else
5120 SET_DECL_VALUE_EXPR (new_vard,
5121 build_fold_addr_expr (lvar));
5122 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
5123 if (x)
5124 {
5125 tseq = NULL;
5126 dtor = x;
5127 gimplify_stmt (&dtor, &tseq);
5128 gimple_seq_add_seq (&llist[1], tseq);
5129 }
5130 break;
5131 }
09d1c205 5132 /* If this is a reference to constant size reduction var
5133 with placeholder, we haven't emitted the initializer
5134 for it because it is undesirable if SIMD arrays are used.
5135 But if they aren't used, we need to emit the deferred
5136 initialization now. */
5137 else if (is_reference (var) && is_simd)
2712b6de 5138 handle_simd_reference (clause_loc, new_vard, ilist);
bc7bff74 5139 x = lang_hooks.decls.omp_clause_default_ctor
cf5f881f 5140 (c, unshare_expr (new_var),
5141 build_outer_var_ref (var, ctx));
bc7bff74 5142 if (x)
5143 gimplify_and_add (x, ilist);
5144 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
5145 {
5146 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
5147 lower_omp (&tseq, ctx);
5148 gimple_seq_add_seq (ilist, tseq);
5149 }
75a70cf9 5150 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
bc7bff74 5151 if (is_simd)
5152 {
5153 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
5154 lower_omp (&tseq, ctx);
5155 gimple_seq_add_seq (dlist, tseq);
5156 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
5157 }
fd6481cf 5158 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
bc7bff74 5159 goto do_dtor;
1e8e9920 5160 }
5161 else
5162 {
5163 x = omp_reduction_init (c, TREE_TYPE (new_var));
5164 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
c22ad515 5165 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
5166
5167 /* reduction(-:var) sums up the partial results, so it
5168 acts identically to reduction(+:var). */
5169 if (code == MINUS_EXPR)
5170 code = PLUS_EXPR;
5171
2712b6de 5172 tree new_vard = new_var;
5173 if (is_simd && is_reference (var))
5174 {
5175 gcc_assert (TREE_CODE (new_var) == MEM_REF);
5176 new_vard = TREE_OPERAND (new_var, 0);
5177 gcc_assert (DECL_P (new_vard));
5178 }
3d483a94 5179 if (is_simd
5180 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
5181 idx, lane, ivar, lvar))
5182 {
3d483a94 5183 tree ref = build_outer_var_ref (var, ctx);
5184
5185 gimplify_assign (unshare_expr (ivar), x, &llist[0]);
5186
3d483a94 5187 x = build2 (code, TREE_TYPE (ref), ref, ivar);
5188 ref = build_outer_var_ref (var, ctx);
5189 gimplify_assign (ref, x, &llist[1]);
2712b6de 5190
5191 if (new_vard != new_var)
5192 {
5193 SET_DECL_VALUE_EXPR (new_vard,
5194 build_fold_addr_expr (lvar));
5195 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
5196 }
3d483a94 5197 }
5198 else
5199 {
2712b6de 5200 if (is_reference (var) && is_simd)
5201 handle_simd_reference (clause_loc, new_vard, ilist);
3d483a94 5202 gimplify_assign (new_var, x, ilist);
5203 if (is_simd)
c22ad515 5204 {
5205 tree ref = build_outer_var_ref (var, ctx);
5206
5207 x = build2 (code, TREE_TYPE (ref), ref, new_var);
5208 ref = build_outer_var_ref (var, ctx);
5209 gimplify_assign (ref, x, dlist);
5210 }
3d483a94 5211 }
1e8e9920 5212 }
5213 break;
5214
5215 default:
5216 gcc_unreachable ();
5217 }
5218 }
5219 }
5220
3d483a94 5221 if (lane)
5222 {
5223 tree uid = create_tmp_var (ptr_type_node, "simduid");
8e1a382d 5224 /* Don't want uninit warnings on simduid, it is always uninitialized,
5225 but we use it not for the value, but for the DECL_UID only. */
5226 TREE_NO_WARNING (uid) = 1;
42acab1c 5227 gimple *g
3d483a94 5228 = gimple_build_call_internal (IFN_GOMP_SIMD_LANE, 1, uid);
5229 gimple_call_set_lhs (g, lane);
5230 gimple_stmt_iterator gsi = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
5231 gsi_insert_before_without_update (&gsi, g, GSI_SAME_STMT);
5232 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SIMDUID_);
5233 OMP_CLAUSE__SIMDUID__DECL (c) = uid;
5234 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
5235 gimple_omp_for_set_clauses (ctx->stmt, c);
e9cf809e 5236 g = gimple_build_assign (lane, INTEGER_CST,
5237 build_int_cst (unsigned_type_node, 0));
3d483a94 5238 gimple_seq_add_stmt (ilist, g);
5239 for (int i = 0; i < 2; i++)
5240 if (llist[i])
5241 {
f9e245b2 5242 tree vf = create_tmp_var (unsigned_type_node);
3d483a94 5243 g = gimple_build_call_internal (IFN_GOMP_SIMD_VF, 1, uid);
5244 gimple_call_set_lhs (g, vf);
5245 gimple_seq *seq = i == 0 ? ilist : dlist;
5246 gimple_seq_add_stmt (seq, g);
5247 tree t = build_int_cst (unsigned_type_node, 0);
e9cf809e 5248 g = gimple_build_assign (idx, INTEGER_CST, t);
3d483a94 5249 gimple_seq_add_stmt (seq, g);
5250 tree body = create_artificial_label (UNKNOWN_LOCATION);
5251 tree header = create_artificial_label (UNKNOWN_LOCATION);
5252 tree end = create_artificial_label (UNKNOWN_LOCATION);
5253 gimple_seq_add_stmt (seq, gimple_build_goto (header));
5254 gimple_seq_add_stmt (seq, gimple_build_label (body));
5255 gimple_seq_add_seq (seq, llist[i]);
5256 t = build_int_cst (unsigned_type_node, 1);
e9cf809e 5257 g = gimple_build_assign (idx, PLUS_EXPR, idx, t);
3d483a94 5258 gimple_seq_add_stmt (seq, g);
5259 gimple_seq_add_stmt (seq, gimple_build_label (header));
5260 g = gimple_build_cond (LT_EXPR, idx, vf, body, end);
5261 gimple_seq_add_stmt (seq, g);
5262 gimple_seq_add_stmt (seq, gimple_build_label (end));
5263 }
5264 }
5265
1e8e9920 5266 /* The copyin sequence is not to be executed by the main thread, since
5267 that would result in self-copies. Perhaps not visible to scalars,
5268 but it certainly is to C++ operator=. */
5269 if (copyin_seq)
5270 {
b9a16870 5271 x = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM),
5272 0);
1e8e9920 5273 x = build2 (NE_EXPR, boolean_type_node, x,
5274 build_int_cst (TREE_TYPE (x), 0));
5275 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
5276 gimplify_and_add (x, ilist);
5277 }
5278
5279 /* If any copyin variable is passed by reference, we must ensure the
5280 master thread doesn't modify it before it is copied over in all
f49d7bb5 5281 threads. Similarly for variables in both firstprivate and
5282 lastprivate clauses we need to ensure the lastprivate copying
bc7bff74 5283 happens after firstprivate copying in all threads. And similarly
5284 for UDRs if initializer expression refers to omp_orig. */
5285 if (copyin_by_ref || lastprivate_firstprivate || reduction_omp_orig_ref)
3d483a94 5286 {
5287 /* Don't add any barrier for #pragma omp simd or
5288 #pragma omp distribute. */
5289 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
7c01fa6c 5290 || gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_FOR)
bc7bff74 5291 gimple_seq_add_stmt (ilist, build_omp_barrier (NULL_TREE));
3d483a94 5292 }
5293
5294 /* If max_vf is non-zero, then we can use only a vectorization factor
5295 up to the max_vf we chose. So stick it into the safelen clause. */
5296 if (max_vf)
5297 {
5298 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
5299 OMP_CLAUSE_SAFELEN);
5300 if (c == NULL_TREE
c3f3b68d 5301 || (TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) == INTEGER_CST
5302 && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
5303 max_vf) == 1))
3d483a94 5304 {
5305 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_SAFELEN);
5306 OMP_CLAUSE_SAFELEN_EXPR (c) = build_int_cst (integer_type_node,
5307 max_vf);
5308 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
5309 gimple_omp_for_set_clauses (ctx->stmt, c);
5310 }
5311 }
1e8e9920 5312}
5313
773c5ba7 5314
1e8e9920 5315/* Generate code to implement the LASTPRIVATE clauses. This is used for
5316 both parallel and workshare constructs. PREDICATE may be NULL if it's
5317 always true. */
5318
5319static void
75a70cf9 5320lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
bc7bff74 5321 omp_context *ctx)
1e8e9920 5322{
3d483a94 5323 tree x, c, label = NULL, orig_clauses = clauses;
fd6481cf 5324 bool par_clauses = false;
3d483a94 5325 tree simduid = NULL, lastlane = NULL;
1e8e9920 5326
3d483a94 5327 /* Early exit if there are no lastprivate or linear clauses. */
5328 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
5329 if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LASTPRIVATE
5330 || (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LINEAR
5331 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses)))
5332 break;
1e8e9920 5333 if (clauses == NULL)
5334 {
5335 /* If this was a workshare clause, see if it had been combined
5336 with its parallel. In that case, look for the clauses on the
5337 parallel statement itself. */
5338 if (is_parallel_ctx (ctx))
5339 return;
5340
5341 ctx = ctx->outer;
5342 if (ctx == NULL || !is_parallel_ctx (ctx))
5343 return;
5344
75a70cf9 5345 clauses = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
1e8e9920 5346 OMP_CLAUSE_LASTPRIVATE);
5347 if (clauses == NULL)
5348 return;
fd6481cf 5349 par_clauses = true;
1e8e9920 5350 }
5351
75a70cf9 5352 if (predicate)
5353 {
1a91d914 5354 gcond *stmt;
75a70cf9 5355 tree label_true, arm1, arm2;
5356
e60a6f7b 5357 label = create_artificial_label (UNKNOWN_LOCATION);
5358 label_true = create_artificial_label (UNKNOWN_LOCATION);
75a70cf9 5359 arm1 = TREE_OPERAND (predicate, 0);
5360 arm2 = TREE_OPERAND (predicate, 1);
5361 gimplify_expr (&arm1, stmt_list, NULL, is_gimple_val, fb_rvalue);
5362 gimplify_expr (&arm2, stmt_list, NULL, is_gimple_val, fb_rvalue);
5363 stmt = gimple_build_cond (TREE_CODE (predicate), arm1, arm2,
5364 label_true, label);
5365 gimple_seq_add_stmt (stmt_list, stmt);
5366 gimple_seq_add_stmt (stmt_list, gimple_build_label (label_true));
5367 }
1e8e9920 5368
3d483a94 5369 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
10c55644 5370 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3d483a94 5371 {
5372 simduid = find_omp_clause (orig_clauses, OMP_CLAUSE__SIMDUID_);
5373 if (simduid)
5374 simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
5375 }
5376
fd6481cf 5377 for (c = clauses; c ;)
1e8e9920 5378 {
5379 tree var, new_var;
389dd41b 5380 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
1e8e9920 5381
3d483a94 5382 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5383 || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
5384 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
fd6481cf 5385 {
5386 var = OMP_CLAUSE_DECL (c);
43895be5 5387 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5388 && OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c)
5389 && is_taskloop_ctx (ctx))
5390 {
5391 gcc_checking_assert (ctx->outer && is_task_ctx (ctx->outer));
5392 new_var = lookup_decl (var, ctx->outer);
5393 }
5394 else
5395 new_var = lookup_decl (var, ctx);
1e8e9920 5396
3d483a94 5397 if (simduid && DECL_HAS_VALUE_EXPR_P (new_var))
5398 {
5399 tree val = DECL_VALUE_EXPR (new_var);
5400 if (TREE_CODE (val) == ARRAY_REF
5401 && VAR_P (TREE_OPERAND (val, 0))
5402 && lookup_attribute ("omp simd array",
5403 DECL_ATTRIBUTES (TREE_OPERAND (val,
5404 0))))
5405 {
5406 if (lastlane == NULL)
5407 {
f9e245b2 5408 lastlane = create_tmp_var (unsigned_type_node);
1a91d914 5409 gcall *g
3d483a94 5410 = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE,
5411 2, simduid,
5412 TREE_OPERAND (val, 1));
5413 gimple_call_set_lhs (g, lastlane);
5414 gimple_seq_add_stmt (stmt_list, g);
5415 }
5416 new_var = build4 (ARRAY_REF, TREE_TYPE (val),
5417 TREE_OPERAND (val, 0), lastlane,
5418 NULL_TREE, NULL_TREE);
5419 }
5420 }
5421
5422 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5423 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
75a70cf9 5424 {
e3a19533 5425 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
75a70cf9 5426 gimple_seq_add_seq (stmt_list,
5427 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
3d483a94 5428 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) = NULL;
75a70cf9 5429 }
2b536a17 5430 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
5431 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
5432 {
5433 lower_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
5434 gimple_seq_add_seq (stmt_list,
5435 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c));
5436 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c) = NULL;
5437 }
1e8e9920 5438
43895be5 5439 x = NULL_TREE;
5440 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5441 && OMP_CLAUSE_LASTPRIVATE_TASKLOOP_IV (c))
5442 {
5443 gcc_checking_assert (is_taskloop_ctx (ctx));
5444 tree ovar = maybe_lookup_decl_in_outer_ctx (var,
5445 ctx->outer->outer);
5446 if (is_global_var (ovar))
5447 x = ovar;
5448 }
5449 if (!x)
5450 x = build_outer_var_ref (var, ctx, true);
fd6481cf 5451 if (is_reference (var))
182cf5a9 5452 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
fd6481cf 5453 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
75a70cf9 5454 gimplify_and_add (x, stmt_list);
fd6481cf 5455 }
5456 c = OMP_CLAUSE_CHAIN (c);
5457 if (c == NULL && !par_clauses)
5458 {
5459 /* If this was a workshare clause, see if it had been combined
5460 with its parallel. In that case, continue looking for the
5461 clauses also on the parallel statement itself. */
5462 if (is_parallel_ctx (ctx))
5463 break;
5464
5465 ctx = ctx->outer;
5466 if (ctx == NULL || !is_parallel_ctx (ctx))
5467 break;
5468
75a70cf9 5469 c = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
fd6481cf 5470 OMP_CLAUSE_LASTPRIVATE);
5471 par_clauses = true;
5472 }
1e8e9920 5473 }
5474
75a70cf9 5475 if (label)
5476 gimple_seq_add_stmt (stmt_list, gimple_build_label (label));
1e8e9920 5477}
5478
641a0fa1 5479/* Lower the OpenACC reductions of CLAUSES for compute axis LEVEL
5480 (which might be a placeholder). INNER is true if this is an inner
5481 axis of a multi-axis loop. FORK and JOIN are (optional) fork and
5482 join markers. Generate the before-loop forking sequence in
5483 FORK_SEQ and the after-loop joining sequence to JOIN_SEQ. The
5484 general form of these sequences is
5485
5486 GOACC_REDUCTION_SETUP
5487 GOACC_FORK
5488 GOACC_REDUCTION_INIT
5489 ...
5490 GOACC_REDUCTION_FINI
5491 GOACC_JOIN
5492 GOACC_REDUCTION_TEARDOWN. */
5493
ca4c3545 5494static void
641a0fa1 5495lower_oacc_reductions (location_t loc, tree clauses, tree level, bool inner,
5496 gcall *fork, gcall *join, gimple_seq *fork_seq,
5497 gimple_seq *join_seq, omp_context *ctx)
ca4c3545 5498{
641a0fa1 5499 gimple_seq before_fork = NULL;
5500 gimple_seq after_fork = NULL;
5501 gimple_seq before_join = NULL;
5502 gimple_seq after_join = NULL;
5503 tree init_code = NULL_TREE, fini_code = NULL_TREE,
5504 setup_code = NULL_TREE, teardown_code = NULL_TREE;
5505 unsigned offset = 0;
5506
5507 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
5508 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
5509 {
5510 tree orig = OMP_CLAUSE_DECL (c);
5511 tree var = maybe_lookup_decl (orig, ctx);
5512 tree ref_to_res = NULL_TREE;
5513 tree incoming, outgoing;
5514
5515 enum tree_code rcode = OMP_CLAUSE_REDUCTION_CODE (c);
5516 if (rcode == MINUS_EXPR)
5517 rcode = PLUS_EXPR;
5518 else if (rcode == TRUTH_ANDIF_EXPR)
5519 rcode = BIT_AND_EXPR;
5520 else if (rcode == TRUTH_ORIF_EXPR)
5521 rcode = BIT_IOR_EXPR;
5522 tree op = build_int_cst (unsigned_type_node, rcode);
5523
5524 if (!var)
5525 var = orig;
5526 gcc_assert (!is_reference (var));
5527
5528 incoming = outgoing = var;
5529
5530 if (!inner)
5531 {
5532 /* See if an outer construct also reduces this variable. */
5533 omp_context *outer = ctx;
ca4c3545 5534
641a0fa1 5535 while (omp_context *probe = outer->outer)
5536 {
5537 enum gimple_code type = gimple_code (probe->stmt);
5538 tree cls;
ca4c3545 5539
641a0fa1 5540 switch (type)
5541 {
5542 case GIMPLE_OMP_FOR:
5543 cls = gimple_omp_for_clauses (probe->stmt);
5544 break;
ca4c3545 5545
641a0fa1 5546 case GIMPLE_OMP_TARGET:
5547 if (gimple_omp_target_kind (probe->stmt)
5548 != GF_OMP_TARGET_KIND_OACC_PARALLEL)
5549 goto do_lookup;
ca4c3545 5550
641a0fa1 5551 cls = gimple_omp_target_clauses (probe->stmt);
5552 break;
ca4c3545 5553
641a0fa1 5554 default:
5555 goto do_lookup;
5556 }
5557
5558 outer = probe;
5559 for (; cls; cls = OMP_CLAUSE_CHAIN (cls))
5560 if (OMP_CLAUSE_CODE (cls) == OMP_CLAUSE_REDUCTION
5561 && orig == OMP_CLAUSE_DECL (cls))
5562 goto has_outer_reduction;
5563 }
ca4c3545 5564
641a0fa1 5565 do_lookup:
5566 /* This is the outermost construct with this reduction,
5567 see if there's a mapping for it. */
5568 if (gimple_code (outer->stmt) == GIMPLE_OMP_TARGET
5569 && maybe_lookup_field (orig, outer))
5570 {
5571 ref_to_res = build_receiver_ref (orig, false, outer);
5572 if (is_reference (orig))
5573 ref_to_res = build_simple_mem_ref (ref_to_res);
ca4c3545 5574
641a0fa1 5575 outgoing = var;
5576 incoming = omp_reduction_init_op (loc, rcode, TREE_TYPE (var));
5577 }
5578 else
5579 incoming = outgoing = orig;
5580
5581 has_outer_reduction:;
5582 }
ca4c3545 5583
641a0fa1 5584 if (!ref_to_res)
5585 ref_to_res = integer_zero_node;
ca4c3545 5586
641a0fa1 5587 /* Determine position in reduction buffer, which may be used
5588 by target. */
5589 enum machine_mode mode = TYPE_MODE (TREE_TYPE (var));
5590 unsigned align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
5591 offset = (offset + align - 1) & ~(align - 1);
5592 tree off = build_int_cst (sizetype, offset);
5593 offset += GET_MODE_SIZE (mode);
ca4c3545 5594
641a0fa1 5595 if (!init_code)
5596 {
5597 init_code = build_int_cst (integer_type_node,
5598 IFN_GOACC_REDUCTION_INIT);
5599 fini_code = build_int_cst (integer_type_node,
5600 IFN_GOACC_REDUCTION_FINI);
5601 setup_code = build_int_cst (integer_type_node,
5602 IFN_GOACC_REDUCTION_SETUP);
5603 teardown_code = build_int_cst (integer_type_node,
5604 IFN_GOACC_REDUCTION_TEARDOWN);
5605 }
5606
5607 tree setup_call
5608 = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
5609 TREE_TYPE (var), 6, setup_code,
5610 unshare_expr (ref_to_res),
5611 incoming, level, op, off);
5612 tree init_call
5613 = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
5614 TREE_TYPE (var), 6, init_code,
5615 unshare_expr (ref_to_res),
5616 var, level, op, off);
5617 tree fini_call
5618 = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
5619 TREE_TYPE (var), 6, fini_code,
5620 unshare_expr (ref_to_res),
5621 var, level, op, off);
5622 tree teardown_call
5623 = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
5624 TREE_TYPE (var), 6, teardown_code,
5625 ref_to_res, var, level, op, off);
5626
5627 gimplify_assign (var, setup_call, &before_fork);
5628 gimplify_assign (var, init_call, &after_fork);
5629 gimplify_assign (var, fini_call, &before_join);
5630 gimplify_assign (outgoing, teardown_call, &after_join);
5631 }
5632
5633 /* Now stitch things together. */
5634 gimple_seq_add_seq (fork_seq, before_fork);
5635 if (fork)
5636 gimple_seq_add_stmt (fork_seq, fork);
5637 gimple_seq_add_seq (fork_seq, after_fork);
5638
5639 gimple_seq_add_seq (join_seq, before_join);
5640 if (join)
5641 gimple_seq_add_stmt (join_seq, join);
5642 gimple_seq_add_seq (join_seq, after_join);
ca4c3545 5643}
773c5ba7 5644
1e8e9920 5645/* Generate code to implement the REDUCTION clauses. */
5646
5647static void
75a70cf9 5648lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
1e8e9920 5649{
75a70cf9 5650 gimple_seq sub_seq = NULL;
42acab1c 5651 gimple *stmt;
f69b8a4c 5652 tree x, c;
1e8e9920 5653 int count = 0;
5654
641a0fa1 5655 /* OpenACC loop reductions are handled elsewhere. */
5656 if (is_gimple_omp_oacc (ctx->stmt))
5657 return;
5658
3d483a94 5659 /* SIMD reductions are handled in lower_rec_input_clauses. */
5660 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
10c55644 5661 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3d483a94 5662 return;
5663
1e8e9920 5664 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
5665 update in that case, otherwise use a lock. */
5666 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
55d6e7cd 5667 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
1e8e9920 5668 {
43895be5 5669 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
5670 || TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF)
1e8e9920 5671 {
bc7bff74 5672 /* Never use OMP_ATOMIC for array reductions or UDRs. */
1e8e9920 5673 count = -1;
5674 break;
5675 }
5676 count++;
5677 }
5678
5679 if (count == 0)
5680 return;
5681
5682 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
5683 {
43895be5 5684 tree var, ref, new_var, orig_var;
1e8e9920 5685 enum tree_code code;
389dd41b 5686 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
1e8e9920 5687
55d6e7cd 5688 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
1e8e9920 5689 continue;
5690
43895be5 5691 orig_var = var = OMP_CLAUSE_DECL (c);
5692 if (TREE_CODE (var) == MEM_REF)
5693 {
5694 var = TREE_OPERAND (var, 0);
9561765e 5695 if (TREE_CODE (var) == POINTER_PLUS_EXPR)
5696 var = TREE_OPERAND (var, 0);
43895be5 5697 if (TREE_CODE (var) == INDIRECT_REF
5698 || TREE_CODE (var) == ADDR_EXPR)
5699 var = TREE_OPERAND (var, 0);
5700 orig_var = var;
5701 if (is_variable_sized (var))
5702 {
5703 gcc_assert (DECL_HAS_VALUE_EXPR_P (var));
5704 var = DECL_VALUE_EXPR (var);
5705 gcc_assert (TREE_CODE (var) == INDIRECT_REF);
5706 var = TREE_OPERAND (var, 0);
5707 gcc_assert (DECL_P (var));
5708 }
5709 }
1e8e9920 5710 new_var = lookup_decl (var, ctx);
43895be5 5711 if (var == OMP_CLAUSE_DECL (c) && is_reference (var))
182cf5a9 5712 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
1e8e9920 5713 ref = build_outer_var_ref (var, ctx);
5714 code = OMP_CLAUSE_REDUCTION_CODE (c);
773c5ba7 5715
5716 /* reduction(-:var) sums up the partial results, so it acts
5717 identically to reduction(+:var). */
1e8e9920 5718 if (code == MINUS_EXPR)
5719 code = PLUS_EXPR;
5720
641a0fa1 5721 if (count == 1)
1e8e9920 5722 {
389dd41b 5723 tree addr = build_fold_addr_expr_loc (clause_loc, ref);
1e8e9920 5724
5725 addr = save_expr (addr);
5726 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
389dd41b 5727 x = fold_build2_loc (clause_loc, code, TREE_TYPE (ref), ref, new_var);
1e8e9920 5728 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
75a70cf9 5729 gimplify_and_add (x, stmt_seqp);
1e8e9920 5730 return;
5731 }
43895be5 5732 else if (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF)
5733 {
5734 tree d = OMP_CLAUSE_DECL (c);
5735 tree type = TREE_TYPE (d);
5736 tree v = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
5737 tree i = create_tmp_var (TREE_TYPE (v), NULL);
5738 tree ptype = build_pointer_type (TREE_TYPE (type));
9561765e 5739 tree bias = TREE_OPERAND (d, 1);
5740 d = TREE_OPERAND (d, 0);
5741 if (TREE_CODE (d) == POINTER_PLUS_EXPR)
5742 {
5743 tree b = TREE_OPERAND (d, 1);
5744 b = maybe_lookup_decl (b, ctx);
5745 if (b == NULL)
5746 {
5747 b = TREE_OPERAND (d, 1);
5748 b = maybe_lookup_decl_in_outer_ctx (b, ctx);
5749 }
5750 if (integer_zerop (bias))
5751 bias = b;
5752 else
5753 {
5754 bias = fold_convert_loc (clause_loc, TREE_TYPE (b), bias);
5755 bias = fold_build2_loc (clause_loc, PLUS_EXPR,
5756 TREE_TYPE (b), b, bias);
5757 }
5758 d = TREE_OPERAND (d, 0);
5759 }
43895be5 5760 /* For ref build_outer_var_ref already performs this, so
5761 only new_var needs a dereference. */
9561765e 5762 if (TREE_CODE (d) == INDIRECT_REF)
43895be5 5763 {
5764 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
5765 gcc_assert (is_reference (var) && var == orig_var);
5766 }
9561765e 5767 else if (TREE_CODE (d) == ADDR_EXPR)
43895be5 5768 {
5769 if (orig_var == var)
5770 {
5771 new_var = build_fold_addr_expr (new_var);
5772 ref = build_fold_addr_expr (ref);
5773 }
5774 }
5775 else
5776 {
5777 gcc_assert (orig_var == var);
5778 if (is_reference (var))
5779 ref = build_fold_addr_expr (ref);
5780 }
5781 if (DECL_P (v))
5782 {
5783 tree t = maybe_lookup_decl (v, ctx);
5784 if (t)
5785 v = t;
5786 else
5787 v = maybe_lookup_decl_in_outer_ctx (v, ctx);
5788 gimplify_expr (&v, stmt_seqp, NULL, is_gimple_val, fb_rvalue);
5789 }
9561765e 5790 if (!integer_zerop (bias))
5791 {
5792 bias = fold_convert_loc (clause_loc, sizetype, bias);
5793 new_var = fold_build2_loc (clause_loc, POINTER_PLUS_EXPR,
5794 TREE_TYPE (new_var), new_var,
5795 unshare_expr (bias));
5796 ref = fold_build2_loc (clause_loc, POINTER_PLUS_EXPR,
5797 TREE_TYPE (ref), ref, bias);
5798 }
43895be5 5799 new_var = fold_convert_loc (clause_loc, ptype, new_var);
5800 ref = fold_convert_loc (clause_loc, ptype, ref);
5801 tree m = create_tmp_var (ptype, NULL);
5802 gimplify_assign (m, new_var, stmt_seqp);
5803 new_var = m;
5804 m = create_tmp_var (ptype, NULL);
5805 gimplify_assign (m, ref, stmt_seqp);
5806 ref = m;
5807 gimplify_assign (i, build_int_cst (TREE_TYPE (v), 0), stmt_seqp);
5808 tree body = create_artificial_label (UNKNOWN_LOCATION);
5809 tree end = create_artificial_label (UNKNOWN_LOCATION);
5810 gimple_seq_add_stmt (&sub_seq, gimple_build_label (body));
5811 tree priv = build_simple_mem_ref_loc (clause_loc, new_var);
5812 tree out = build_simple_mem_ref_loc (clause_loc, ref);
5813 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
5814 {
5815 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
5816 tree decl_placeholder
5817 = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c);
5818 SET_DECL_VALUE_EXPR (placeholder, out);
5819 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
5820 SET_DECL_VALUE_EXPR (decl_placeholder, priv);
5821 DECL_HAS_VALUE_EXPR_P (decl_placeholder) = 1;
5822 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
5823 gimple_seq_add_seq (&sub_seq,
5824 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
5825 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
5826 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
5827 OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c) = NULL;
5828 }
5829 else
5830 {
5831 x = build2 (code, TREE_TYPE (out), out, priv);
5832 out = unshare_expr (out);
5833 gimplify_assign (out, x, &sub_seq);
5834 }
5835 gimple *g = gimple_build_assign (new_var, POINTER_PLUS_EXPR, new_var,
5836 TYPE_SIZE_UNIT (TREE_TYPE (type)));
5837 gimple_seq_add_stmt (&sub_seq, g);
5838 g = gimple_build_assign (ref, POINTER_PLUS_EXPR, ref,
5839 TYPE_SIZE_UNIT (TREE_TYPE (type)));
5840 gimple_seq_add_stmt (&sub_seq, g);
5841 g = gimple_build_assign (i, PLUS_EXPR, i,
5842 build_int_cst (TREE_TYPE (i), 1));
5843 gimple_seq_add_stmt (&sub_seq, g);
5844 g = gimple_build_cond (LE_EXPR, i, v, body, end);
5845 gimple_seq_add_stmt (&sub_seq, g);
5846 gimple_seq_add_stmt (&sub_seq, gimple_build_label (end));
5847 }
ca4c3545 5848 else if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1e8e9920 5849 {
5850 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
5851
bc7bff74 5852 if (is_reference (var)
5853 && !useless_type_conversion_p (TREE_TYPE (placeholder),
5854 TREE_TYPE (ref)))
389dd41b 5855 ref = build_fold_addr_expr_loc (clause_loc, ref);
1e8e9920 5856 SET_DECL_VALUE_EXPR (placeholder, ref);
5857 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
e3a19533 5858 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
75a70cf9 5859 gimple_seq_add_seq (&sub_seq, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
5860 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
1e8e9920 5861 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
5862 }
5863 else
5864 {
5865 x = build2 (code, TREE_TYPE (ref), ref, new_var);
5866 ref = build_outer_var_ref (var, ctx);
75a70cf9 5867 gimplify_assign (ref, x, &sub_seq);
1e8e9920 5868 }
5869 }
5870
ca4c3545 5871 if (is_gimple_omp_oacc (ctx->stmt))
5872 return;
5873
b9a16870 5874 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START),
5875 0);
75a70cf9 5876 gimple_seq_add_stmt (stmt_seqp, stmt);
1e8e9920 5877
75a70cf9 5878 gimple_seq_add_seq (stmt_seqp, sub_seq);
1e8e9920 5879
b9a16870 5880 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END),
5881 0);
75a70cf9 5882 gimple_seq_add_stmt (stmt_seqp, stmt);
1e8e9920 5883}
5884
773c5ba7 5885
1e8e9920 5886/* Generate code to implement the COPYPRIVATE clauses. */
5887
5888static void
75a70cf9 5889lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist,
1e8e9920 5890 omp_context *ctx)
5891{
5892 tree c;
5893
5894 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
5895 {
cb561506 5896 tree var, new_var, ref, x;
1e8e9920 5897 bool by_ref;
389dd41b 5898 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
1e8e9920 5899
55d6e7cd 5900 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
1e8e9920 5901 continue;
5902
5903 var = OMP_CLAUSE_DECL (c);
e8a588af 5904 by_ref = use_pointer_for_field (var, NULL);
1e8e9920 5905
5906 ref = build_sender_ref (var, ctx);
cb561506 5907 x = new_var = lookup_decl_in_outer_ctx (var, ctx);
5908 if (by_ref)
5909 {
5910 x = build_fold_addr_expr_loc (clause_loc, new_var);
5911 x = fold_convert_loc (clause_loc, TREE_TYPE (ref), x);
5912 }
75a70cf9 5913 gimplify_assign (ref, x, slist);
1e8e9920 5914
cb561506 5915 ref = build_receiver_ref (var, false, ctx);
5916 if (by_ref)
5917 {
5918 ref = fold_convert_loc (clause_loc,
5919 build_pointer_type (TREE_TYPE (new_var)),
5920 ref);
5921 ref = build_fold_indirect_ref_loc (clause_loc, ref);
5922 }
1e8e9920 5923 if (is_reference (var))
5924 {
cb561506 5925 ref = fold_convert_loc (clause_loc, TREE_TYPE (new_var), ref);
182cf5a9 5926 ref = build_simple_mem_ref_loc (clause_loc, ref);
5927 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
1e8e9920 5928 }
cb561506 5929 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, ref);
1e8e9920 5930 gimplify_and_add (x, rlist);
5931 }
5932}
5933
773c5ba7 5934
1e8e9920 5935/* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
5936 and REDUCTION from the sender (aka parent) side. */
5937
5938static void
75a70cf9 5939lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
5940 omp_context *ctx)
1e8e9920 5941{
43895be5 5942 tree c, t;
5943 int ignored_looptemp = 0;
5944 bool is_taskloop = false;
5945
5946 /* For taskloop, ignore first two _looptemp_ clauses, those are initialized
5947 by GOMP_taskloop. */
5948 if (is_task_ctx (ctx) && gimple_omp_task_taskloop_p (ctx->stmt))
5949 {
5950 ignored_looptemp = 2;
5951 is_taskloop = true;
5952 }
1e8e9920 5953
5954 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
5955 {
773c5ba7 5956 tree val, ref, x, var;
1e8e9920 5957 bool by_ref, do_in = false, do_out = false;
389dd41b 5958 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
1e8e9920 5959
55d6e7cd 5960 switch (OMP_CLAUSE_CODE (c))
1e8e9920 5961 {
fd6481cf 5962 case OMP_CLAUSE_PRIVATE:
5963 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
5964 break;
5965 continue;
1e8e9920 5966 case OMP_CLAUSE_FIRSTPRIVATE:
5967 case OMP_CLAUSE_COPYIN:
5968 case OMP_CLAUSE_LASTPRIVATE:
5969 case OMP_CLAUSE_REDUCTION:
43895be5 5970 break;
5971 case OMP_CLAUSE_SHARED:
5972 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
5973 break;
5974 continue;
bc7bff74 5975 case OMP_CLAUSE__LOOPTEMP_:
43895be5 5976 if (ignored_looptemp)
5977 {
5978 ignored_looptemp--;
5979 continue;
5980 }
1e8e9920 5981 break;
5982 default:
5983 continue;
5984 }
5985
87b31375 5986 val = OMP_CLAUSE_DECL (c);
43895be5 5987 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
5988 && TREE_CODE (val) == MEM_REF)
5989 {
5990 val = TREE_OPERAND (val, 0);
9561765e 5991 if (TREE_CODE (val) == POINTER_PLUS_EXPR)
5992 val = TREE_OPERAND (val, 0);
43895be5 5993 if (TREE_CODE (val) == INDIRECT_REF
5994 || TREE_CODE (val) == ADDR_EXPR)
5995 val = TREE_OPERAND (val, 0);
5996 if (is_variable_sized (val))
5997 continue;
5998 }
5999
6000 /* For OMP_CLAUSE_SHARED_FIRSTPRIVATE, look beyond the
6001 outer taskloop region. */
6002 omp_context *ctx_for_o = ctx;
6003 if (is_taskloop
6004 && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
6005 && OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
6006 ctx_for_o = ctx->outer;
6007
6008 var = lookup_decl_in_outer_ctx (val, ctx_for_o);
773c5ba7 6009
f49d7bb5 6010 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
6011 && is_global_var (var))
6012 continue;
43895be5 6013
6014 t = omp_member_access_dummy_var (var);
6015 if (t)
6016 {
6017 var = DECL_VALUE_EXPR (var);
6018 tree o = maybe_lookup_decl_in_outer_ctx (t, ctx_for_o);
6019 if (o != t)
6020 var = unshare_and_remap (var, t, o);
6021 else
6022 var = unshare_expr (var);
6023 }
6024
6025 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED)
6026 {
6027 /* Handle taskloop firstprivate/lastprivate, where the
6028 lastprivate on GIMPLE_OMP_TASK is represented as
6029 OMP_CLAUSE_SHARED_FIRSTPRIVATE. */
6030 tree f = lookup_sfield ((splay_tree_key) &DECL_UID (val), ctx);
6031 x = omp_build_component_ref (ctx->sender_decl, f);
6032 if (use_pointer_for_field (val, ctx))
6033 var = build_fold_addr_expr (var);
6034 gimplify_assign (x, var, ilist);
6035 DECL_ABSTRACT_ORIGIN (f) = NULL;
6036 continue;
6037 }
6038
6039 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION
6040 || val == OMP_CLAUSE_DECL (c))
6041 && is_variable_sized (val))
1e8e9920 6042 continue;
e8a588af 6043 by_ref = use_pointer_for_field (val, NULL);
1e8e9920 6044
55d6e7cd 6045 switch (OMP_CLAUSE_CODE (c))
1e8e9920 6046 {
fd6481cf 6047 case OMP_CLAUSE_PRIVATE:
1e8e9920 6048 case OMP_CLAUSE_FIRSTPRIVATE:
6049 case OMP_CLAUSE_COPYIN:
bc7bff74 6050 case OMP_CLAUSE__LOOPTEMP_:
1e8e9920 6051 do_in = true;
6052 break;
6053
6054 case OMP_CLAUSE_LASTPRIVATE:
6055 if (by_ref || is_reference (val))
6056 {
6057 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
6058 continue;
6059 do_in = true;
6060 }
6061 else
fd6481cf 6062 {
6063 do_out = true;
6064 if (lang_hooks.decls.omp_private_outer_ref (val))
6065 do_in = true;
6066 }
1e8e9920 6067 break;
6068
6069 case OMP_CLAUSE_REDUCTION:
6070 do_in = true;
43895be5 6071 if (val == OMP_CLAUSE_DECL (c))
6072 do_out = !(by_ref || is_reference (val));
6073 else
6074 by_ref = TREE_CODE (TREE_TYPE (val)) == ARRAY_TYPE;
1e8e9920 6075 break;
6076
6077 default:
6078 gcc_unreachable ();
6079 }
6080
6081 if (do_in)
6082 {
6083 ref = build_sender_ref (val, ctx);
389dd41b 6084 x = by_ref ? build_fold_addr_expr_loc (clause_loc, var) : var;
75a70cf9 6085 gimplify_assign (ref, x, ilist);
fd6481cf 6086 if (is_task_ctx (ctx))
6087 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref, 1)) = NULL;
1e8e9920 6088 }
773c5ba7 6089
1e8e9920 6090 if (do_out)
6091 {
6092 ref = build_sender_ref (val, ctx);
75a70cf9 6093 gimplify_assign (var, ref, olist);
1e8e9920 6094 }
6095 }
6096}
6097
75a70cf9 6098/* Generate code to implement SHARED from the sender (aka parent)
6099 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
6100 list things that got automatically shared. */
1e8e9920 6101
6102static void
75a70cf9 6103lower_send_shared_vars (gimple_seq *ilist, gimple_seq *olist, omp_context *ctx)
1e8e9920 6104{
43895be5 6105 tree var, ovar, nvar, t, f, x, record_type;
1e8e9920 6106
6107 if (ctx->record_type == NULL)
6108 return;
773c5ba7 6109
fd6481cf 6110 record_type = ctx->srecord_type ? ctx->srecord_type : ctx->record_type;
1767a056 6111 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
1e8e9920 6112 {
6113 ovar = DECL_ABSTRACT_ORIGIN (f);
43895be5 6114 if (!ovar || TREE_CODE (ovar) == FIELD_DECL)
6115 continue;
6116
1e8e9920 6117 nvar = maybe_lookup_decl (ovar, ctx);
6118 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
6119 continue;
6120
773c5ba7 6121 /* If CTX is a nested parallel directive. Find the immediately
6122 enclosing parallel or workshare construct that contains a
6123 mapping for OVAR. */
87b31375 6124 var = lookup_decl_in_outer_ctx (ovar, ctx);
773c5ba7 6125
43895be5 6126 t = omp_member_access_dummy_var (var);
6127 if (t)
6128 {
6129 var = DECL_VALUE_EXPR (var);
6130 tree o = maybe_lookup_decl_in_outer_ctx (t, ctx);
6131 if (o != t)
6132 var = unshare_and_remap (var, t, o);
6133 else
6134 var = unshare_expr (var);
6135 }
6136
e8a588af 6137 if (use_pointer_for_field (ovar, ctx))
1e8e9920 6138 {
6139 x = build_sender_ref (ovar, ctx);
773c5ba7 6140 var = build_fold_addr_expr (var);
75a70cf9 6141 gimplify_assign (x, var, ilist);
1e8e9920 6142 }
6143 else
6144 {
6145 x = build_sender_ref (ovar, ctx);
75a70cf9 6146 gimplify_assign (x, var, ilist);
1e8e9920 6147
d2263ebb 6148 if (!TREE_READONLY (var)
6149 /* We don't need to receive a new reference to a result
6150 or parm decl. In fact we may not store to it as we will
6151 invalidate any pending RSO and generate wrong gimple
6152 during inlining. */
6153 && !((TREE_CODE (var) == RESULT_DECL
6154 || TREE_CODE (var) == PARM_DECL)
6155 && DECL_BY_REFERENCE (var)))
fd6481cf 6156 {
6157 x = build_sender_ref (ovar, ctx);
75a70cf9 6158 gimplify_assign (var, x, olist);
fd6481cf 6159 }
1e8e9920 6160 }
6161 }
6162}
6163
a8e785ba 6164/* Emit an OpenACC head marker call, encapulating the partitioning and
6165 other information that must be processed by the target compiler.
6166 Return the maximum number of dimensions the associated loop might
6167 be partitioned over. */
6168
6169static unsigned
6170lower_oacc_head_mark (location_t loc, tree ddvar, tree clauses,
6171 gimple_seq *seq, omp_context *ctx)
6172{
6173 unsigned levels = 0;
6174 unsigned tag = 0;
6175 tree gang_static = NULL_TREE;
6176 auto_vec<tree, 5> args;
6177
6178 args.quick_push (build_int_cst
6179 (integer_type_node, IFN_UNIQUE_OACC_HEAD_MARK));
6180 args.quick_push (ddvar);
6181 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
6182 {
6183 switch (OMP_CLAUSE_CODE (c))
6184 {
6185 case OMP_CLAUSE_GANG:
6186 tag |= OLF_DIM_GANG;
6187 gang_static = OMP_CLAUSE_GANG_STATIC_EXPR (c);
6188 /* static:* is represented by -1, and we can ignore it, as
6189 scheduling is always static. */
6190 if (gang_static && integer_minus_onep (gang_static))
6191 gang_static = NULL_TREE;
6192 levels++;
6193 break;
6194
6195 case OMP_CLAUSE_WORKER:
6196 tag |= OLF_DIM_WORKER;
6197 levels++;
6198 break;
6199
6200 case OMP_CLAUSE_VECTOR:
6201 tag |= OLF_DIM_VECTOR;
6202 levels++;
6203 break;
6204
6205 case OMP_CLAUSE_SEQ:
6206 tag |= OLF_SEQ;
6207 break;
6208
6209 case OMP_CLAUSE_AUTO:
6210 tag |= OLF_AUTO;
6211 break;
6212
6213 case OMP_CLAUSE_INDEPENDENT:
6214 tag |= OLF_INDEPENDENT;
6215 break;
6216
6217 default:
6218 continue;
6219 }
6220 }
6221
6222 if (gang_static)
6223 {
6224 if (DECL_P (gang_static))
6225 gang_static = build_outer_var_ref (gang_static, ctx);
6226 tag |= OLF_GANG_STATIC;
6227 }
6228
6229 /* In a parallel region, loops are implicitly INDEPENDENT. */
6230 omp_context *tgt = enclosing_target_ctx (ctx);
6231 if (!tgt || is_oacc_parallel (tgt))
6232 tag |= OLF_INDEPENDENT;
6233
6234 /* A loop lacking SEQ, GANG, WORKER and/or VECTOR is implicitly AUTO. */
6235 if (!(tag & (((GOMP_DIM_MASK (GOMP_DIM_MAX) - 1) << OLF_DIM_BASE)
6236 | OLF_SEQ)))
6237 tag |= OLF_AUTO;
6238
6239 /* Ensure at least one level. */
6240 if (!levels)
6241 levels++;
6242
6243 args.quick_push (build_int_cst (integer_type_node, levels));
6244 args.quick_push (build_int_cst (integer_type_node, tag));
6245 if (gang_static)
6246 args.quick_push (gang_static);
6247
6248 gcall *call = gimple_build_call_internal_vec (IFN_UNIQUE, args);
6249 gimple_set_location (call, loc);
6250 gimple_set_lhs (call, ddvar);
6251 gimple_seq_add_stmt (seq, call);
6252
6253 return levels;
6254}
6255
6256/* Emit an OpenACC lopp head or tail marker to SEQ. LEVEL is the
6257 partitioning level of the enclosed region. */
6258
6259static void
6260lower_oacc_loop_marker (location_t loc, tree ddvar, bool head,
6261 tree tofollow, gimple_seq *seq)
6262{
6263 int marker_kind = (head ? IFN_UNIQUE_OACC_HEAD_MARK
6264 : IFN_UNIQUE_OACC_TAIL_MARK);
6265 tree marker = build_int_cst (integer_type_node, marker_kind);
6266 int nargs = 2 + (tofollow != NULL_TREE);
6267 gcall *call = gimple_build_call_internal (IFN_UNIQUE, nargs,
6268 marker, ddvar, tofollow);
6269 gimple_set_location (call, loc);
6270 gimple_set_lhs (call, ddvar);
6271 gimple_seq_add_stmt (seq, call);
6272}
6273
6274/* Generate the before and after OpenACC loop sequences. CLAUSES are
6275 the loop clauses, from which we extract reductions. Initialize
6276 HEAD and TAIL. */
6277
6278static void
6279lower_oacc_head_tail (location_t loc, tree clauses,
6280 gimple_seq *head, gimple_seq *tail, omp_context *ctx)
6281{
6282 bool inner = false;
6283 tree ddvar = create_tmp_var (integer_type_node, ".data_dep");
6284 gimple_seq_add_stmt (head, gimple_build_assign (ddvar, integer_zero_node));
6285
6286 unsigned count = lower_oacc_head_mark (loc, ddvar, clauses, head, ctx);
6287 if (!count)
6288 lower_oacc_loop_marker (loc, ddvar, false, integer_zero_node, tail);
6289
6290 tree fork_kind = build_int_cst (unsigned_type_node, IFN_UNIQUE_OACC_FORK);
6291 tree join_kind = build_int_cst (unsigned_type_node, IFN_UNIQUE_OACC_JOIN);
6292
6293 for (unsigned done = 1; count; count--, done++)
6294 {
6295 gimple_seq fork_seq = NULL;
6296 gimple_seq join_seq = NULL;
6297
6298 tree place = build_int_cst (integer_type_node, -1);
6299 gcall *fork = gimple_build_call_internal (IFN_UNIQUE, 3,
6300 fork_kind, ddvar, place);
6301 gimple_set_location (fork, loc);
6302 gimple_set_lhs (fork, ddvar);
6303
6304 gcall *join = gimple_build_call_internal (IFN_UNIQUE, 3,
6305 join_kind, ddvar, place);
6306 gimple_set_location (join, loc);
6307 gimple_set_lhs (join, ddvar);
6308
6309 /* Mark the beginning of this level sequence. */
6310 if (inner)
6311 lower_oacc_loop_marker (loc, ddvar, true,
6312 build_int_cst (integer_type_node, count),
6313 &fork_seq);
6314 lower_oacc_loop_marker (loc, ddvar, false,
6315 build_int_cst (integer_type_node, done),
6316 &join_seq);
6317
641a0fa1 6318 lower_oacc_reductions (loc, clauses, place, inner,
6319 fork, join, &fork_seq, &join_seq, ctx);
a8e785ba 6320
6321 /* Append this level to head. */
6322 gimple_seq_add_seq (head, fork_seq);
6323 /* Prepend it to tail. */
6324 gimple_seq_add_seq (&join_seq, *tail);
6325 *tail = join_seq;
6326
6327 inner = true;
6328 }
6329
6330 /* Mark the end of the sequence. */
6331 lower_oacc_loop_marker (loc, ddvar, true, NULL_TREE, head);
6332 lower_oacc_loop_marker (loc, ddvar, false, NULL_TREE, tail);
6333}
75a70cf9 6334
6335/* A convenience function to build an empty GIMPLE_COND with just the
6336 condition. */
6337
1a91d914 6338static gcond *
75a70cf9 6339gimple_build_cond_empty (tree cond)
6340{
6341 enum tree_code pred_code;
6342 tree lhs, rhs;
6343
6344 gimple_cond_get_ops_from_tree (cond, &pred_code, &lhs, &rhs);
6345 return gimple_build_cond (pred_code, lhs, rhs, NULL_TREE, NULL_TREE);
6346}
6347
43895be5 6348static void expand_omp_build_assign (gimple_stmt_iterator *, tree, tree,
6349 bool = false);
75a70cf9 6350
48e1416a 6351/* Build the function calls to GOMP_parallel_start etc to actually
773c5ba7 6352 generate the parallel operation. REGION is the parallel region
6353 being expanded. BB is the block where to insert the code. WS_ARGS
6354 will be set if this is a call to a combined parallel+workshare
6355 construct, it contains the list of additional arguments needed by
6356 the workshare construct. */
1e8e9920 6357
6358static void
61e47ac8 6359expand_parallel_call (struct omp_region *region, basic_block bb,
1a91d914 6360 gomp_parallel *entry_stmt,
6361 vec<tree, va_gc> *ws_args)
1e8e9920 6362{
bc7bff74 6363 tree t, t1, t2, val, cond, c, clauses, flags;
75a70cf9 6364 gimple_stmt_iterator gsi;
42acab1c 6365 gimple *stmt;
b9a16870 6366 enum built_in_function start_ix;
6367 int start_ix2;
389dd41b 6368 location_t clause_loc;
f1f41a6c 6369 vec<tree, va_gc> *args;
773c5ba7 6370
75a70cf9 6371 clauses = gimple_omp_parallel_clauses (entry_stmt);
773c5ba7 6372
bc7bff74 6373 /* Determine what flavor of GOMP_parallel we will be
773c5ba7 6374 emitting. */
bc7bff74 6375 start_ix = BUILT_IN_GOMP_PARALLEL;
773c5ba7 6376 if (is_combined_parallel (region))
6377 {
61e47ac8 6378 switch (region->inner->type)
773c5ba7 6379 {
75a70cf9 6380 case GIMPLE_OMP_FOR:
fd6481cf 6381 gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
9561765e 6382 switch (region->inner->sched_kind)
6383 {
6384 case OMP_CLAUSE_SCHEDULE_RUNTIME:
6385 start_ix2 = 3;
6386 break;
6387 case OMP_CLAUSE_SCHEDULE_DYNAMIC:
6388 case OMP_CLAUSE_SCHEDULE_GUIDED:
6389 if (region->inner->sched_modifiers
6390 & OMP_CLAUSE_SCHEDULE_NONMONOTONIC)
6391 {
6392 start_ix2 = 3 + region->inner->sched_kind;
6393 break;
6394 }
6395 /* FALLTHRU */
6396 default:
6397 start_ix2 = region->inner->sched_kind;
6398 break;
6399 }
6400 start_ix2 += (int) BUILT_IN_GOMP_PARALLEL_LOOP_STATIC;
6401 start_ix = (enum built_in_function) start_ix2;
61e47ac8 6402 break;
75a70cf9 6403 case GIMPLE_OMP_SECTIONS:
bc7bff74 6404 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS;
61e47ac8 6405 break;
6406 default:
6407 gcc_unreachable ();
773c5ba7 6408 }
773c5ba7 6409 }
1e8e9920 6410
6411 /* By default, the value of NUM_THREADS is zero (selected at run time)
6412 and there is no conditional. */
6413 cond = NULL_TREE;
6414 val = build_int_cst (unsigned_type_node, 0);
bc7bff74 6415 flags = build_int_cst (unsigned_type_node, 0);
1e8e9920 6416
6417 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
6418 if (c)
6419 cond = OMP_CLAUSE_IF_EXPR (c);
6420
6421 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
6422 if (c)
389dd41b 6423 {
6424 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
6425 clause_loc = OMP_CLAUSE_LOCATION (c);
6426 }
6427 else
6428 clause_loc = gimple_location (entry_stmt);
1e8e9920 6429
bc7bff74 6430 c = find_omp_clause (clauses, OMP_CLAUSE_PROC_BIND);
6431 if (c)
6432 flags = build_int_cst (unsigned_type_node, OMP_CLAUSE_PROC_BIND_KIND (c));
6433
1e8e9920 6434 /* Ensure 'val' is of the correct type. */
389dd41b 6435 val = fold_convert_loc (clause_loc, unsigned_type_node, val);
1e8e9920 6436
6437 /* If we found the clause 'if (cond)', build either
6438 (cond != 0) or (cond ? val : 1u). */
6439 if (cond)
6440 {
773c5ba7 6441 cond = gimple_boolify (cond);
6442
1e8e9920 6443 if (integer_zerop (val))
389dd41b 6444 val = fold_build2_loc (clause_loc,
6445 EQ_EXPR, unsigned_type_node, cond,
79acaae1 6446 build_int_cst (TREE_TYPE (cond), 0));
1e8e9920 6447 else
773c5ba7 6448 {
6449 basic_block cond_bb, then_bb, else_bb;
79acaae1 6450 edge e, e_then, e_else;
75a70cf9 6451 tree tmp_then, tmp_else, tmp_join, tmp_var;
79acaae1 6452
f9e245b2 6453 tmp_var = create_tmp_var (TREE_TYPE (val));
79acaae1 6454 if (gimple_in_ssa_p (cfun))
6455 {
f9e245b2 6456 tmp_then = make_ssa_name (tmp_var);
6457 tmp_else = make_ssa_name (tmp_var);
6458 tmp_join = make_ssa_name (tmp_var);
79acaae1 6459 }
6460 else
6461 {
6462 tmp_then = tmp_var;
6463 tmp_else = tmp_var;
6464 tmp_join = tmp_var;
6465 }
773c5ba7 6466
4302d619 6467 e = split_block_after_labels (bb);
773c5ba7 6468 cond_bb = e->src;
6469 bb = e->dest;
6470 remove_edge (e);
6471
6472 then_bb = create_empty_bb (cond_bb);
6473 else_bb = create_empty_bb (then_bb);
79acaae1 6474 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
6475 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
773c5ba7 6476
75a70cf9 6477 stmt = gimple_build_cond_empty (cond);
6478 gsi = gsi_start_bb (cond_bb);
6479 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
773c5ba7 6480
75a70cf9 6481 gsi = gsi_start_bb (then_bb);
43895be5 6482 expand_omp_build_assign (&gsi, tmp_then, val, true);
773c5ba7 6483
75a70cf9 6484 gsi = gsi_start_bb (else_bb);
43895be5 6485 expand_omp_build_assign (&gsi, tmp_else,
6486 build_int_cst (unsigned_type_node, 1),
6487 true);
773c5ba7 6488
6489 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
6490 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
b3083327 6491 add_bb_to_loop (then_bb, cond_bb->loop_father);
6492 add_bb_to_loop (else_bb, cond_bb->loop_father);
79acaae1 6493 e_then = make_edge (then_bb, bb, EDGE_FALLTHRU);
6494 e_else = make_edge (else_bb, bb, EDGE_FALLTHRU);
773c5ba7 6495
79acaae1 6496 if (gimple_in_ssa_p (cfun))
6497 {
1a91d914 6498 gphi *phi = create_phi_node (tmp_join, bb);
60d535d2 6499 add_phi_arg (phi, tmp_then, e_then, UNKNOWN_LOCATION);
6500 add_phi_arg (phi, tmp_else, e_else, UNKNOWN_LOCATION);
79acaae1 6501 }
6502
6503 val = tmp_join;
773c5ba7 6504 }
6505
75a70cf9 6506 gsi = gsi_start_bb (bb);
6507 val = force_gimple_operand_gsi (&gsi, val, true, NULL_TREE,
6508 false, GSI_CONTINUE_LINKING);
1e8e9920 6509 }
6510
75a70cf9 6511 gsi = gsi_last_bb (bb);
6512 t = gimple_omp_parallel_data_arg (entry_stmt);
1e8e9920 6513 if (t == NULL)
c2f47e15 6514 t1 = null_pointer_node;
1e8e9920 6515 else
c2f47e15 6516 t1 = build_fold_addr_expr (t);
75a70cf9 6517 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
773c5ba7 6518
bc7bff74 6519 vec_alloc (args, 4 + vec_safe_length (ws_args));
f1f41a6c 6520 args->quick_push (t2);
6521 args->quick_push (t1);
6522 args->quick_push (val);
6523 if (ws_args)
6524 args->splice (*ws_args);
bc7bff74 6525 args->quick_push (flags);
414c3a2c 6526
6527 t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
b9a16870 6528 builtin_decl_explicit (start_ix), args);
773c5ba7 6529
75a70cf9 6530 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6531 false, GSI_CONTINUE_LINKING);
1e8e9920 6532}
6533
40750995 6534/* Insert a function call whose name is FUNC_NAME with the information from
6535 ENTRY_STMT into the basic_block BB. */
6536
6537static void
1a91d914 6538expand_cilk_for_call (basic_block bb, gomp_parallel *entry_stmt,
40750995 6539 vec <tree, va_gc> *ws_args)
6540{
6541 tree t, t1, t2;
6542 gimple_stmt_iterator gsi;
6543 vec <tree, va_gc> *args;
6544
6545 gcc_assert (vec_safe_length (ws_args) == 2);
6546 tree func_name = (*ws_args)[0];
6547 tree grain = (*ws_args)[1];
6548
6549 tree clauses = gimple_omp_parallel_clauses (entry_stmt);
6550 tree count = find_omp_clause (clauses, OMP_CLAUSE__CILK_FOR_COUNT_);
6551 gcc_assert (count != NULL_TREE);
6552 count = OMP_CLAUSE_OPERAND (count, 0);
6553
6554 gsi = gsi_last_bb (bb);
6555 t = gimple_omp_parallel_data_arg (entry_stmt);
6556 if (t == NULL)
6557 t1 = null_pointer_node;
6558 else
6559 t1 = build_fold_addr_expr (t);
6560 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
6561
6562 vec_alloc (args, 4);
6563 args->quick_push (t2);
6564 args->quick_push (t1);
6565 args->quick_push (count);
6566 args->quick_push (grain);
6567 t = build_call_expr_loc_vec (UNKNOWN_LOCATION, func_name, args);
6568
6569 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, false,
6570 GSI_CONTINUE_LINKING);
6571}
773c5ba7 6572
fd6481cf 6573/* Build the function call to GOMP_task to actually
6574 generate the task operation. BB is the block where to insert the code. */
6575
6576static void
43895be5 6577expand_task_call (struct omp_region *region, basic_block bb,
6578 gomp_task *entry_stmt)
fd6481cf 6579{
43895be5 6580 tree t1, t2, t3;
75a70cf9 6581 gimple_stmt_iterator gsi;
389dd41b 6582 location_t loc = gimple_location (entry_stmt);
fd6481cf 6583
43895be5 6584 tree clauses = gimple_omp_task_clauses (entry_stmt);
6585
6586 tree ifc = find_omp_clause (clauses, OMP_CLAUSE_IF);
6587 tree untied = find_omp_clause (clauses, OMP_CLAUSE_UNTIED);
6588 tree mergeable = find_omp_clause (clauses, OMP_CLAUSE_MERGEABLE);
6589 tree depend = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
6590 tree finalc = find_omp_clause (clauses, OMP_CLAUSE_FINAL);
6591 tree priority = find_omp_clause (clauses, OMP_CLAUSE_PRIORITY);
6592
6593 unsigned int iflags
6594 = (untied ? GOMP_TASK_FLAG_UNTIED : 0)
6595 | (mergeable ? GOMP_TASK_FLAG_MERGEABLE : 0)
6596 | (depend ? GOMP_TASK_FLAG_DEPEND : 0);
6597
6598 bool taskloop_p = gimple_omp_task_taskloop_p (entry_stmt);
6599 tree startvar = NULL_TREE, endvar = NULL_TREE, step = NULL_TREE;
6600 tree num_tasks = NULL_TREE;
6601 bool ull = false;
6602 if (taskloop_p)
6603 {
6604 gimple *g = last_stmt (region->outer->entry);
6605 gcc_assert (gimple_code (g) == GIMPLE_OMP_FOR
6606 && gimple_omp_for_kind (g) == GF_OMP_FOR_KIND_TASKLOOP);
6607 struct omp_for_data fd;
6608 extract_omp_for_data (as_a <gomp_for *> (g), &fd, NULL);
6609 startvar = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
6610 endvar = find_omp_clause (OMP_CLAUSE_CHAIN (startvar),
6611 OMP_CLAUSE__LOOPTEMP_);
6612 startvar = OMP_CLAUSE_DECL (startvar);
6613 endvar = OMP_CLAUSE_DECL (endvar);
6614 step = fold_convert_loc (loc, fd.iter_type, fd.loop.step);
6615 if (fd.loop.cond_code == LT_EXPR)
6616 iflags |= GOMP_TASK_FLAG_UP;
6617 tree tclauses = gimple_omp_for_clauses (g);
6618 num_tasks = find_omp_clause (tclauses, OMP_CLAUSE_NUM_TASKS);
6619 if (num_tasks)
6620 num_tasks = OMP_CLAUSE_NUM_TASKS_EXPR (num_tasks);
6621 else
6622 {
6623 num_tasks = find_omp_clause (tclauses, OMP_CLAUSE_GRAINSIZE);
6624 if (num_tasks)
6625 {
6626 iflags |= GOMP_TASK_FLAG_GRAINSIZE;
6627 num_tasks = OMP_CLAUSE_GRAINSIZE_EXPR (num_tasks);
6628 }
6629 else
6630 num_tasks = integer_zero_node;
6631 }
6632 num_tasks = fold_convert_loc (loc, long_integer_type_node, num_tasks);
6633 if (ifc == NULL_TREE)
6634 iflags |= GOMP_TASK_FLAG_IF;
6635 if (find_omp_clause (tclauses, OMP_CLAUSE_NOGROUP))
6636 iflags |= GOMP_TASK_FLAG_NOGROUP;
6637 ull = fd.iter_type == long_long_unsigned_type_node;
6638 }
6639 else if (priority)
6640 iflags |= GOMP_TASK_FLAG_PRIORITY;
fd6481cf 6641
43895be5 6642 tree flags = build_int_cst (unsigned_type_node, iflags);
fd6481cf 6643
43895be5 6644 tree cond = boolean_true_node;
6645 if (ifc)
6646 {
6647 if (taskloop_p)
6648 {
6649 tree t = gimple_boolify (OMP_CLAUSE_IF_EXPR (ifc));
6650 t = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, t,
6651 build_int_cst (unsigned_type_node,
6652 GOMP_TASK_FLAG_IF),
6653 build_int_cst (unsigned_type_node, 0));
6654 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node,
6655 flags, t);
6656 }
6657 else
6658 cond = gimple_boolify (OMP_CLAUSE_IF_EXPR (ifc));
6659 }
2169f33b 6660
43895be5 6661 if (finalc)
2169f33b 6662 {
43895be5 6663 tree t = gimple_boolify (OMP_CLAUSE_FINAL_EXPR (finalc));
6664 t = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, t,
6665 build_int_cst (unsigned_type_node,
6666 GOMP_TASK_FLAG_FINAL),
2169f33b 6667 build_int_cst (unsigned_type_node, 0));
43895be5 6668 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node, flags, t);
2169f33b 6669 }
bc7bff74 6670 if (depend)
6671 depend = OMP_CLAUSE_DECL (depend);
6672 else
6673 depend = build_int_cst (ptr_type_node, 0);
43895be5 6674 if (priority)
6675 priority = fold_convert (integer_type_node,
6676 OMP_CLAUSE_PRIORITY_EXPR (priority));
6677 else
6678 priority = integer_zero_node;
fd6481cf 6679
75a70cf9 6680 gsi = gsi_last_bb (bb);
43895be5 6681 tree t = gimple_omp_task_data_arg (entry_stmt);
fd6481cf 6682 if (t == NULL)
6683 t2 = null_pointer_node;
6684 else
389dd41b 6685 t2 = build_fold_addr_expr_loc (loc, t);
6686 t1 = build_fold_addr_expr_loc (loc, gimple_omp_task_child_fn (entry_stmt));
75a70cf9 6687 t = gimple_omp_task_copy_fn (entry_stmt);
fd6481cf 6688 if (t == NULL)
6689 t3 = null_pointer_node;
6690 else
389dd41b 6691 t3 = build_fold_addr_expr_loc (loc, t);
fd6481cf 6692
43895be5 6693 if (taskloop_p)
6694 t = build_call_expr (ull
6695 ? builtin_decl_explicit (BUILT_IN_GOMP_TASKLOOP_ULL)
6696 : builtin_decl_explicit (BUILT_IN_GOMP_TASKLOOP),
6697 11, t1, t2, t3,
6698 gimple_omp_task_arg_size (entry_stmt),
6699 gimple_omp_task_arg_align (entry_stmt), flags,
6700 num_tasks, priority, startvar, endvar, step);
6701 else
6702 t = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK),
6703 9, t1, t2, t3,
6704 gimple_omp_task_arg_size (entry_stmt),
6705 gimple_omp_task_arg_align (entry_stmt), cond, flags,
6706 depend, priority);
fd6481cf 6707
75a70cf9 6708 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6709 false, GSI_CONTINUE_LINKING);
fd6481cf 6710}
6711
6712
75a70cf9 6713/* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
6714 catch handler and return it. This prevents programs from violating the
6715 structured block semantics with throws. */
1e8e9920 6716
75a70cf9 6717static gimple_seq
6718maybe_catch_exception (gimple_seq body)
1e8e9920 6719{
42acab1c 6720 gimple *g;
e38def9c 6721 tree decl;
1e8e9920 6722
6723 if (!flag_exceptions)
75a70cf9 6724 return body;
1e8e9920 6725
596981c8 6726 if (lang_hooks.eh_protect_cleanup_actions != NULL)
6727 decl = lang_hooks.eh_protect_cleanup_actions ();
1e8e9920 6728 else
b9a16870 6729 decl = builtin_decl_explicit (BUILT_IN_TRAP);
75a70cf9 6730
e38def9c 6731 g = gimple_build_eh_must_not_throw (decl);
6732 g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g),
75a70cf9 6733 GIMPLE_TRY_CATCH);
1e8e9920 6734
e38def9c 6735 return gimple_seq_alloc_with_stmt (g);
1e8e9920 6736}
6737
773c5ba7 6738/* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
1e8e9920 6739
773c5ba7 6740static tree
f1f41a6c 6741vec2chain (vec<tree, va_gc> *v)
1e8e9920 6742{
2ab2ce89 6743 tree chain = NULL_TREE, t;
6744 unsigned ix;
1e8e9920 6745
f1f41a6c 6746 FOR_EACH_VEC_SAFE_ELT_REVERSE (v, ix, t)
773c5ba7 6747 {
1767a056 6748 DECL_CHAIN (t) = chain;
2ab2ce89 6749 chain = t;
773c5ba7 6750 }
1e8e9920 6751
2ab2ce89 6752 return chain;
773c5ba7 6753}
1e8e9920 6754
1e8e9920 6755
773c5ba7 6756/* Remove barriers in REGION->EXIT's block. Note that this is only
75a70cf9 6757 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
6758 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
6759 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
773c5ba7 6760 removed. */
1e8e9920 6761
773c5ba7 6762static void
6763remove_exit_barrier (struct omp_region *region)
6764{
75a70cf9 6765 gimple_stmt_iterator gsi;
773c5ba7 6766 basic_block exit_bb;
61e47ac8 6767 edge_iterator ei;
6768 edge e;
42acab1c 6769 gimple *stmt;
4a04f4b4 6770 int any_addressable_vars = -1;
1e8e9920 6771
61e47ac8 6772 exit_bb = region->exit;
1e8e9920 6773
5056ba1a 6774 /* If the parallel region doesn't return, we don't have REGION->EXIT
6775 block at all. */
6776 if (! exit_bb)
6777 return;
6778
75a70cf9 6779 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
6780 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
61e47ac8 6781 statements that can appear in between are extremely limited -- no
6782 memory operations at all. Here, we allow nothing at all, so the
75a70cf9 6783 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
6784 gsi = gsi_last_bb (exit_bb);
6785 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
6786 gsi_prev (&gsi);
6787 if (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
773c5ba7 6788 return;
1e8e9920 6789
61e47ac8 6790 FOR_EACH_EDGE (e, ei, exit_bb->preds)
6791 {
75a70cf9 6792 gsi = gsi_last_bb (e->src);
6793 if (gsi_end_p (gsi))
61e47ac8 6794 continue;
75a70cf9 6795 stmt = gsi_stmt (gsi);
4a04f4b4 6796 if (gimple_code (stmt) == GIMPLE_OMP_RETURN
6797 && !gimple_omp_return_nowait_p (stmt))
6798 {
6799 /* OpenMP 3.0 tasks unfortunately prevent this optimization
6800 in many cases. If there could be tasks queued, the barrier
6801 might be needed to let the tasks run before some local
6802 variable of the parallel that the task uses as shared
6803 runs out of scope. The task can be spawned either
6804 from within current function (this would be easy to check)
6805 or from some function it calls and gets passed an address
6806 of such a variable. */
6807 if (any_addressable_vars < 0)
6808 {
1a91d914 6809 gomp_parallel *parallel_stmt
6810 = as_a <gomp_parallel *> (last_stmt (region->entry));
4a04f4b4 6811 tree child_fun = gimple_omp_parallel_child_fn (parallel_stmt);
2ab2ce89 6812 tree local_decls, block, decl;
6813 unsigned ix;
4a04f4b4 6814
6815 any_addressable_vars = 0;
2ab2ce89 6816 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun), ix, decl)
6817 if (TREE_ADDRESSABLE (decl))
4a04f4b4 6818 {
6819 any_addressable_vars = 1;
6820 break;
6821 }
6822 for (block = gimple_block (stmt);
6823 !any_addressable_vars
6824 && block
6825 && TREE_CODE (block) == BLOCK;
6826 block = BLOCK_SUPERCONTEXT (block))
6827 {
6828 for (local_decls = BLOCK_VARS (block);
6829 local_decls;
1767a056 6830 local_decls = DECL_CHAIN (local_decls))
4a04f4b4 6831 if (TREE_ADDRESSABLE (local_decls))
6832 {
6833 any_addressable_vars = 1;
6834 break;
6835 }
6836 if (block == gimple_block (parallel_stmt))
6837 break;
6838 }
6839 }
6840 if (!any_addressable_vars)
6841 gimple_omp_return_set_nowait (stmt);
6842 }
61e47ac8 6843 }
1e8e9920 6844}
6845
61e47ac8 6846static void
6847remove_exit_barriers (struct omp_region *region)
6848{
75a70cf9 6849 if (region->type == GIMPLE_OMP_PARALLEL)
61e47ac8 6850 remove_exit_barrier (region);
6851
6852 if (region->inner)
6853 {
6854 region = region->inner;
6855 remove_exit_barriers (region);
6856 while (region->next)
6857 {
6858 region = region->next;
6859 remove_exit_barriers (region);
6860 }
6861 }
6862}
773c5ba7 6863
658b4427 6864/* Optimize omp_get_thread_num () and omp_get_num_threads ()
6865 calls. These can't be declared as const functions, but
6866 within one parallel body they are constant, so they can be
6867 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
fd6481cf 6868 which are declared const. Similarly for task body, except
6869 that in untied task omp_get_thread_num () can change at any task
6870 scheduling point. */
658b4427 6871
6872static void
42acab1c 6873optimize_omp_library_calls (gimple *entry_stmt)
658b4427 6874{
6875 basic_block bb;
75a70cf9 6876 gimple_stmt_iterator gsi;
b9a16870 6877 tree thr_num_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
6878 tree thr_num_id = DECL_ASSEMBLER_NAME (thr_num_tree);
6879 tree num_thr_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
6880 tree num_thr_id = DECL_ASSEMBLER_NAME (num_thr_tree);
75a70cf9 6881 bool untied_task = (gimple_code (entry_stmt) == GIMPLE_OMP_TASK
6882 && find_omp_clause (gimple_omp_task_clauses (entry_stmt),
fd6481cf 6883 OMP_CLAUSE_UNTIED) != NULL);
658b4427 6884
fc00614f 6885 FOR_EACH_BB_FN (bb, cfun)
75a70cf9 6886 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
658b4427 6887 {
42acab1c 6888 gimple *call = gsi_stmt (gsi);
658b4427 6889 tree decl;
6890
75a70cf9 6891 if (is_gimple_call (call)
6892 && (decl = gimple_call_fndecl (call))
658b4427 6893 && DECL_EXTERNAL (decl)
6894 && TREE_PUBLIC (decl)
6895 && DECL_INITIAL (decl) == NULL)
6896 {
6897 tree built_in;
6898
6899 if (DECL_NAME (decl) == thr_num_id)
fd6481cf 6900 {
6901 /* In #pragma omp task untied omp_get_thread_num () can change
6902 during the execution of the task region. */
6903 if (untied_task)
6904 continue;
b9a16870 6905 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
fd6481cf 6906 }
658b4427 6907 else if (DECL_NAME (decl) == num_thr_id)
b9a16870 6908 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
658b4427 6909 else
6910 continue;
6911
6912 if (DECL_ASSEMBLER_NAME (decl) != DECL_ASSEMBLER_NAME (built_in)
75a70cf9 6913 || gimple_call_num_args (call) != 0)
658b4427 6914 continue;
6915
6916 if (flag_exceptions && !TREE_NOTHROW (decl))
6917 continue;
6918
6919 if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
1ea6a73c 6920 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl)),
6921 TREE_TYPE (TREE_TYPE (built_in))))
658b4427 6922 continue;
6923
0acacf9e 6924 gimple_call_set_fndecl (call, built_in);
658b4427 6925 }
6926 }
6927}
6928
8e6b4515 6929/* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
6930 regimplified. */
6931
6932static tree
6933expand_omp_regimplify_p (tree *tp, int *walk_subtrees, void *)
6934{
6935 tree t = *tp;
6936
6937 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
6938 if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t))
6939 return t;
6940
6941 if (TREE_CODE (t) == ADDR_EXPR)
6942 recompute_tree_invariant_for_addr_expr (t);
6943
6944 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
6945 return NULL_TREE;
6946}
6947
43895be5 6948/* Prepend or append TO = FROM assignment before or after *GSI_P. */
3d483a94 6949
6950static void
43895be5 6951expand_omp_build_assign (gimple_stmt_iterator *gsi_p, tree to, tree from,
6952 bool after)
3d483a94 6953{
6954 bool simple_p = DECL_P (to) && TREE_ADDRESSABLE (to);
6955 from = force_gimple_operand_gsi (gsi_p, from, simple_p, NULL_TREE,
43895be5 6956 !after, after ? GSI_CONTINUE_LINKING
6957 : GSI_SAME_STMT);
42acab1c 6958 gimple *stmt = gimple_build_assign (to, from);
43895be5 6959 if (after)
6960 gsi_insert_after (gsi_p, stmt, GSI_CONTINUE_LINKING);
6961 else
6962 gsi_insert_before (gsi_p, stmt, GSI_SAME_STMT);
3d483a94 6963 if (walk_tree (&from, expand_omp_regimplify_p, NULL, NULL)
6964 || walk_tree (&to, expand_omp_regimplify_p, NULL, NULL))
6965 {
6966 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
6967 gimple_regimplify_operands (stmt, &gsi);
6968 }
6969}
6970
fd6481cf 6971/* Expand the OpenMP parallel or task directive starting at REGION. */
1e8e9920 6972
6973static void
fd6481cf 6974expand_omp_taskreg (struct omp_region *region)
1e8e9920 6975{
773c5ba7 6976 basic_block entry_bb, exit_bb, new_bb;
87d4aa85 6977 struct function *child_cfun;
414c3a2c 6978 tree child_fn, block, t;
75a70cf9 6979 gimple_stmt_iterator gsi;
42acab1c 6980 gimple *entry_stmt, *stmt;
773c5ba7 6981 edge e;
f1f41a6c 6982 vec<tree, va_gc> *ws_args;
773c5ba7 6983
61e47ac8 6984 entry_stmt = last_stmt (region->entry);
75a70cf9 6985 child_fn = gimple_omp_taskreg_child_fn (entry_stmt);
773c5ba7 6986 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
773c5ba7 6987
61e47ac8 6988 entry_bb = region->entry;
b25f70fd 6989 if (gimple_code (entry_stmt) == GIMPLE_OMP_TASK)
6990 exit_bb = region->cont;
6991 else
6992 exit_bb = region->exit;
773c5ba7 6993
40750995 6994 bool is_cilk_for
6995 = (flag_cilkplus
6996 && gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL
6997 && find_omp_clause (gimple_omp_parallel_clauses (entry_stmt),
6998 OMP_CLAUSE__CILK_FOR_COUNT_) != NULL_TREE);
6999
7000 if (is_cilk_for)
7001 /* If it is a _Cilk_for statement, it is modelled *like* a parallel for,
7002 and the inner statement contains the name of the built-in function
7003 and grain. */
7004 ws_args = region->inner->ws_args;
7005 else if (is_combined_parallel (region))
61e47ac8 7006 ws_args = region->ws_args;
773c5ba7 7007 else
414c3a2c 7008 ws_args = NULL;
1e8e9920 7009
61e47ac8 7010 if (child_cfun->cfg)
1e8e9920 7011 {
773c5ba7 7012 /* Due to inlining, it may happen that we have already outlined
7013 the region, in which case all we need to do is make the
7014 sub-graph unreachable and emit the parallel call. */
7015 edge entry_succ_e, exit_succ_e;
773c5ba7 7016
7017 entry_succ_e = single_succ_edge (entry_bb);
773c5ba7 7018
75a70cf9 7019 gsi = gsi_last_bb (entry_bb);
7020 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_PARALLEL
7021 || gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_TASK);
7022 gsi_remove (&gsi, true);
773c5ba7 7023
7024 new_bb = entry_bb;
03ed154b 7025 if (exit_bb)
7026 {
7027 exit_succ_e = single_succ_edge (exit_bb);
7028 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
7029 }
79acaae1 7030 remove_edge_and_dominated_blocks (entry_succ_e);
1e8e9920 7031 }
773c5ba7 7032 else
7033 {
501bdd19 7034 unsigned srcidx, dstidx, num;
2ab2ce89 7035
773c5ba7 7036 /* If the parallel region needs data sent from the parent
3480139d 7037 function, then the very first statement (except possible
7038 tree profile counter updates) of the parallel body
773c5ba7 7039 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
7040 &.OMP_DATA_O is passed as an argument to the child function,
7041 we need to replace it with the argument as seen by the child
7042 function.
7043
7044 In most cases, this will end up being the identity assignment
7045 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
7046 a function call that has been inlined, the original PARM_DECL
7047 .OMP_DATA_I may have been converted into a different local
7048 variable. In which case, we need to keep the assignment. */
75a70cf9 7049 if (gimple_omp_taskreg_data_arg (entry_stmt))
773c5ba7 7050 {
b25f70fd 7051 basic_block entry_succ_bb
7052 = single_succ_p (entry_bb) ? single_succ (entry_bb)
7053 : FALLTHRU_EDGE (entry_bb)->dest;
883f001d 7054 tree arg;
42acab1c 7055 gimple *parcopy_stmt = NULL;
1e8e9920 7056
75a70cf9 7057 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
3480139d 7058 {
42acab1c 7059 gimple *stmt;
3480139d 7060
75a70cf9 7061 gcc_assert (!gsi_end_p (gsi));
7062 stmt = gsi_stmt (gsi);
7063 if (gimple_code (stmt) != GIMPLE_ASSIGN)
cc6b725b 7064 continue;
7065
75a70cf9 7066 if (gimple_num_ops (stmt) == 2)
3480139d 7067 {
75a70cf9 7068 tree arg = gimple_assign_rhs1 (stmt);
7069
7070 /* We're ignore the subcode because we're
7071 effectively doing a STRIP_NOPS. */
7072
7073 if (TREE_CODE (arg) == ADDR_EXPR
7074 && TREE_OPERAND (arg, 0)
7075 == gimple_omp_taskreg_data_arg (entry_stmt))
7076 {
7077 parcopy_stmt = stmt;
7078 break;
7079 }
3480139d 7080 }
7081 }
79acaae1 7082
75a70cf9 7083 gcc_assert (parcopy_stmt != NULL);
79acaae1 7084 arg = DECL_ARGUMENTS (child_fn);
7085
7086 if (!gimple_in_ssa_p (cfun))
7087 {
75a70cf9 7088 if (gimple_assign_lhs (parcopy_stmt) == arg)
7089 gsi_remove (&gsi, true);
79acaae1 7090 else
75a70cf9 7091 {
7092 /* ?? Is setting the subcode really necessary ?? */
7093 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (arg));
7094 gimple_assign_set_rhs1 (parcopy_stmt, arg);
7095 }
79acaae1 7096 }
7097 else
7098 {
883f001d 7099 tree lhs = gimple_assign_lhs (parcopy_stmt);
7100 gcc_assert (SSA_NAME_VAR (lhs) == arg);
7101 /* We'd like to set the rhs to the default def in the child_fn,
7102 but it's too early to create ssa names in the child_fn.
7103 Instead, we set the rhs to the parm. In
7104 move_sese_region_to_fn, we introduce a default def for the
7105 parm, map the parm to it's default def, and once we encounter
7106 this stmt, replace the parm with the default def. */
7107 gimple_assign_set_rhs1 (parcopy_stmt, arg);
79acaae1 7108 update_stmt (parcopy_stmt);
7109 }
773c5ba7 7110 }
7111
7112 /* Declare local variables needed in CHILD_CFUN. */
7113 block = DECL_INITIAL (child_fn);
2ab2ce89 7114 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
e1a7ccb9 7115 /* The gimplifier could record temporaries in parallel/task block
7116 rather than in containing function's local_decls chain,
7117 which would mean cgraph missed finalizing them. Do it now. */
1767a056 7118 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
e1a7ccb9 7119 if (TREE_CODE (t) == VAR_DECL
7120 && TREE_STATIC (t)
7121 && !DECL_EXTERNAL (t))
97221fd7 7122 varpool_node::finalize_decl (t);
75a70cf9 7123 DECL_SAVED_TREE (child_fn) = NULL;
e3a19533 7124 /* We'll create a CFG for child_fn, so no gimple body is needed. */
7125 gimple_set_body (child_fn, NULL);
1d22f541 7126 TREE_USED (block) = 1;
773c5ba7 7127
79acaae1 7128 /* Reset DECL_CONTEXT on function arguments. */
1767a056 7129 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
773c5ba7 7130 DECL_CONTEXT (t) = child_fn;
7131
75a70cf9 7132 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
7133 so that it can be moved to the child function. */
7134 gsi = gsi_last_bb (entry_bb);
7135 stmt = gsi_stmt (gsi);
7136 gcc_assert (stmt && (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
7137 || gimple_code (stmt) == GIMPLE_OMP_TASK));
75a70cf9 7138 e = split_block (entry_bb, stmt);
923635e7 7139 gsi_remove (&gsi, true);
773c5ba7 7140 entry_bb = e->dest;
b25f70fd 7141 edge e2 = NULL;
7142 if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
7143 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7144 else
7145 {
7146 e2 = make_edge (e->src, BRANCH_EDGE (entry_bb)->dest, EDGE_ABNORMAL);
7147 gcc_assert (e2->dest == region->exit);
7148 remove_edge (BRANCH_EDGE (entry_bb));
7149 set_immediate_dominator (CDI_DOMINATORS, e2->dest, e->src);
7150 gsi = gsi_last_bb (region->exit);
7151 gcc_assert (!gsi_end_p (gsi)
7152 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
7153 gsi_remove (&gsi, true);
7154 }
773c5ba7 7155
b25f70fd 7156 /* Convert GIMPLE_OMP_{RETURN,CONTINUE} into a RETURN_EXPR. */
5056ba1a 7157 if (exit_bb)
7158 {
75a70cf9 7159 gsi = gsi_last_bb (exit_bb);
7160 gcc_assert (!gsi_end_p (gsi)
b25f70fd 7161 && (gimple_code (gsi_stmt (gsi))
7162 == (e2 ? GIMPLE_OMP_CONTINUE : GIMPLE_OMP_RETURN)));
75a70cf9 7163 stmt = gimple_build_return (NULL);
7164 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
7165 gsi_remove (&gsi, true);
5056ba1a 7166 }
79acaae1 7167
7168 /* Move the parallel region into CHILD_CFUN. */
48e1416a 7169
79acaae1 7170 if (gimple_in_ssa_p (cfun))
7171 {
bcaa2770 7172 init_tree_ssa (child_cfun);
5084b2e4 7173 init_ssa_operands (child_cfun);
7174 child_cfun->gimple_df->in_ssa_p = true;
1d22f541 7175 block = NULL_TREE;
79acaae1 7176 }
1d22f541 7177 else
75a70cf9 7178 block = gimple_block (entry_stmt);
1d22f541 7179
7180 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
79acaae1 7181 if (exit_bb)
7182 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
b25f70fd 7183 if (e2)
7184 {
7185 basic_block dest_bb = e2->dest;
7186 if (!exit_bb)
7187 make_edge (new_bb, dest_bb, EDGE_FALLTHRU);
7188 remove_edge (e2);
7189 set_immediate_dominator (CDI_DOMINATORS, dest_bb, new_bb);
7190 }
04c2922b 7191 /* When the OMP expansion process cannot guarantee an up-to-date
7192 loop tree arrange for the child function to fixup loops. */
7193 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
7194 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
79acaae1 7195
1d22f541 7196 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
f1f41a6c 7197 num = vec_safe_length (child_cfun->local_decls);
501bdd19 7198 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
7199 {
f1f41a6c 7200 t = (*child_cfun->local_decls)[srcidx];
501bdd19 7201 if (DECL_CONTEXT (t) == cfun->decl)
7202 continue;
7203 if (srcidx != dstidx)
f1f41a6c 7204 (*child_cfun->local_decls)[dstidx] = t;
501bdd19 7205 dstidx++;
7206 }
7207 if (dstidx != num)
f1f41a6c 7208 vec_safe_truncate (child_cfun->local_decls, dstidx);
1d22f541 7209
79acaae1 7210 /* Inform the callgraph about the new function. */
9918db44 7211 child_cfun->curr_properties = cfun->curr_properties;
7212 child_cfun->has_simduid_loops |= cfun->has_simduid_loops;
7213 child_cfun->has_force_vectorize_loops |= cfun->has_force_vectorize_loops;
47300487 7214 cgraph_node *node = cgraph_node::get_create (child_fn);
7215 node->parallelized_function = 1;
415d1b9a 7216 cgraph_node::add_new_function (child_fn, true);
79acaae1 7217
9561765e 7218 bool need_asm = DECL_ASSEMBLER_NAME_SET_P (current_function_decl)
7219 && !DECL_ASSEMBLER_NAME_SET_P (child_fn);
7220
79acaae1 7221 /* Fix the callgraph edges for child_cfun. Those for cfun will be
7222 fixed in a following pass. */
7223 push_cfun (child_cfun);
9561765e 7224 if (need_asm)
7225 assign_assembler_name_if_neeeded (child_fn);
7226
658b4427 7227 if (optimize)
fd6481cf 7228 optimize_omp_library_calls (entry_stmt);
35ee1c66 7229 cgraph_edge::rebuild_edges ();
fbe86b1b 7230
7231 /* Some EH regions might become dead, see PR34608. If
7232 pass_cleanup_cfg isn't the first pass to happen with the
7233 new child, these dead EH edges might cause problems.
7234 Clean them up now. */
7235 if (flag_exceptions)
7236 {
7237 basic_block bb;
fbe86b1b 7238 bool changed = false;
7239
fc00614f 7240 FOR_EACH_BB_FN (bb, cfun)
75a70cf9 7241 changed |= gimple_purge_dead_eh_edges (bb);
fbe86b1b 7242 if (changed)
7243 cleanup_tree_cfg ();
fbe86b1b 7244 }
dd277d48 7245 if (gimple_in_ssa_p (cfun))
7246 update_ssa (TODO_update_ssa);
382ecba7 7247 if (flag_checking && !loops_state_satisfies_p (LOOPS_NEED_FIXUP))
86a932e0 7248 verify_loop_structure ();
79acaae1 7249 pop_cfun ();
9561765e 7250
7251 if (dump_file && !gimple_in_ssa_p (cfun))
7252 {
7253 omp_any_child_fn_dumped = true;
7254 dump_function_header (dump_file, child_fn, dump_flags);
7255 dump_function_to_file (child_fn, dump_file, dump_flags);
7256 }
773c5ba7 7257 }
48e1416a 7258
773c5ba7 7259 /* Emit a library call to launch the children threads. */
40750995 7260 if (is_cilk_for)
1a91d914 7261 expand_cilk_for_call (new_bb,
7262 as_a <gomp_parallel *> (entry_stmt), ws_args);
40750995 7263 else if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
1a91d914 7264 expand_parallel_call (region, new_bb,
7265 as_a <gomp_parallel *> (entry_stmt), ws_args);
fd6481cf 7266 else
43895be5 7267 expand_task_call (region, new_bb, as_a <gomp_task *> (entry_stmt));
083152fb 7268 if (gimple_in_ssa_p (cfun))
7269 update_ssa (TODO_update_ssa_only_virtuals);
1e8e9920 7270}
7271
a8e785ba 7272/* Information about members of an OpenACC collapsed loop nest. */
7273
7274struct oacc_collapse
7275{
7276 tree base; /* Base value. */
7277 tree iters; /* Number of steps. */
7278 tree step; /* step size. */
7279};
7280
7281/* Helper for expand_oacc_for. Determine collapsed loop information.
7282 Fill in COUNTS array. Emit any initialization code before GSI.
7283 Return the calculated outer loop bound of BOUND_TYPE. */
7284
7285static tree
7286expand_oacc_collapse_init (const struct omp_for_data *fd,
7287 gimple_stmt_iterator *gsi,
7288 oacc_collapse *counts, tree bound_type)
7289{
7290 tree total = build_int_cst (bound_type, 1);
7291 int ix;
7292
7293 gcc_assert (integer_onep (fd->loop.step));
7294 gcc_assert (integer_zerop (fd->loop.n1));
7295
7296 for (ix = 0; ix != fd->collapse; ix++)
7297 {
7298 const omp_for_data_loop *loop = &fd->loops[ix];
7299
7300 tree iter_type = TREE_TYPE (loop->v);
7301 tree diff_type = iter_type;
7302 tree plus_type = iter_type;
7303
7304 gcc_assert (loop->cond_code == fd->loop.cond_code);
7305
7306 if (POINTER_TYPE_P (iter_type))
7307 plus_type = sizetype;
7308 if (POINTER_TYPE_P (diff_type) || TYPE_UNSIGNED (diff_type))
7309 diff_type = signed_type_for (diff_type);
7310
7311 tree b = loop->n1;
7312 tree e = loop->n2;
7313 tree s = loop->step;
7314 bool up = loop->cond_code == LT_EXPR;
7315 tree dir = build_int_cst (diff_type, up ? +1 : -1);
7316 bool negating;
7317 tree expr;
7318
7319 b = force_gimple_operand_gsi (gsi, b, true, NULL_TREE,
7320 true, GSI_SAME_STMT);
7321 e = force_gimple_operand_gsi (gsi, e, true, NULL_TREE,
7322 true, GSI_SAME_STMT);
7323
7324 /* Convert the step, avoiding possible unsigned->signed overflow. */
7325 negating = !up && TYPE_UNSIGNED (TREE_TYPE (s));
7326 if (negating)
7327 s = fold_build1 (NEGATE_EXPR, TREE_TYPE (s), s);
7328 s = fold_convert (diff_type, s);
7329 if (negating)
7330 s = fold_build1 (NEGATE_EXPR, diff_type, s);
7331 s = force_gimple_operand_gsi (gsi, s, true, NULL_TREE,
7332 true, GSI_SAME_STMT);
7333
7334 /* Determine the range, avoiding possible unsigned->signed overflow. */
7335 negating = !up && TYPE_UNSIGNED (iter_type);
7336 expr = fold_build2 (MINUS_EXPR, plus_type,
7337 fold_convert (plus_type, negating ? b : e),
7338 fold_convert (plus_type, negating ? e : b));
7339 expr = fold_convert (diff_type, expr);
7340 if (negating)
7341 expr = fold_build1 (NEGATE_EXPR, diff_type, expr);
7342 tree range = force_gimple_operand_gsi
7343 (gsi, expr, true, NULL_TREE, true, GSI_SAME_STMT);
7344
7345 /* Determine number of iterations. */
7346 expr = fold_build2 (MINUS_EXPR, diff_type, range, dir);
7347 expr = fold_build2 (PLUS_EXPR, diff_type, expr, s);
7348 expr = fold_build2 (TRUNC_DIV_EXPR, diff_type, expr, s);
7349
7350 tree iters = force_gimple_operand_gsi (gsi, expr, true, NULL_TREE,
7351 true, GSI_SAME_STMT);
7352
7353 counts[ix].base = b;
7354 counts[ix].iters = iters;
7355 counts[ix].step = s;
7356
7357 total = fold_build2 (MULT_EXPR, bound_type, total,
7358 fold_convert (bound_type, iters));
7359 }
7360
7361 return total;
7362}
7363
7364/* Emit initializers for collapsed loop members. IVAR is the outer
7365 loop iteration variable, from which collapsed loop iteration values
7366 are calculated. COUNTS array has been initialized by
7367 expand_oacc_collapse_inits. */
7368
7369static void
7370expand_oacc_collapse_vars (const struct omp_for_data *fd,
7371 gimple_stmt_iterator *gsi,
7372 const oacc_collapse *counts, tree ivar)
7373{
7374 tree ivar_type = TREE_TYPE (ivar);
7375
7376 /* The most rapidly changing iteration variable is the innermost
7377 one. */
7378 for (int ix = fd->collapse; ix--;)
7379 {
7380 const omp_for_data_loop *loop = &fd->loops[ix];
7381 const oacc_collapse *collapse = &counts[ix];
7382 tree iter_type = TREE_TYPE (loop->v);
7383 tree diff_type = TREE_TYPE (collapse->step);
7384 tree plus_type = iter_type;
7385 enum tree_code plus_code = PLUS_EXPR;
7386 tree expr;
7387
7388 if (POINTER_TYPE_P (iter_type))
7389 {
7390 plus_code = POINTER_PLUS_EXPR;
7391 plus_type = sizetype;
7392 }
7393
7394 expr = fold_build2 (TRUNC_MOD_EXPR, ivar_type, ivar,
7395 fold_convert (ivar_type, collapse->iters));
7396 expr = fold_build2 (MULT_EXPR, diff_type, fold_convert (diff_type, expr),
7397 collapse->step);
7398 expr = fold_build2 (plus_code, iter_type, collapse->base,
7399 fold_convert (plus_type, expr));
7400 expr = force_gimple_operand_gsi (gsi, expr, false, NULL_TREE,
7401 true, GSI_SAME_STMT);
7402 gassign *ass = gimple_build_assign (loop->v, expr);
7403 gsi_insert_before (gsi, ass, GSI_SAME_STMT);
7404
7405 if (ix)
7406 {
7407 expr = fold_build2 (TRUNC_DIV_EXPR, ivar_type, ivar,
7408 fold_convert (ivar_type, collapse->iters));
7409 ivar = force_gimple_operand_gsi (gsi, expr, true, NULL_TREE,
7410 true, GSI_SAME_STMT);
7411 }
7412 }
7413}
7414
773c5ba7 7415
3d483a94 7416/* Helper function for expand_omp_{for_*,simd}. If this is the outermost
7417 of the combined collapse > 1 loop constructs, generate code like:
7418 if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
7419 if (cond3 is <)
7420 adj = STEP3 - 1;
7421 else
7422 adj = STEP3 + 1;
7423 count3 = (adj + N32 - N31) / STEP3;
7424 if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
7425 if (cond2 is <)
7426 adj = STEP2 - 1;
7427 else
7428 adj = STEP2 + 1;
7429 count2 = (adj + N22 - N21) / STEP2;
7430 if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
7431 if (cond1 is <)
7432 adj = STEP1 - 1;
7433 else
7434 adj = STEP1 + 1;
7435 count1 = (adj + N12 - N11) / STEP1;
7436 count = count1 * count2 * count3;
7437 Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
7438 count = 0;
bc7bff74 7439 and set ZERO_ITER_BB to that bb. If this isn't the outermost
7440 of the combined loop constructs, just initialize COUNTS array
7441 from the _looptemp_ clauses. */
3d483a94 7442
7443/* NOTE: It *could* be better to moosh all of the BBs together,
7444 creating one larger BB with all the computation and the unexpected
7445 jump at the end. I.e.
7446
7447 bool zero3, zero2, zero1, zero;
7448
7449 zero3 = N32 c3 N31;
7450 count3 = (N32 - N31) /[cl] STEP3;
7451 zero2 = N22 c2 N21;
7452 count2 = (N22 - N21) /[cl] STEP2;
7453 zero1 = N12 c1 N11;
7454 count1 = (N12 - N11) /[cl] STEP1;
7455 zero = zero3 || zero2 || zero1;
7456 count = count1 * count2 * count3;
7457 if (__builtin_expect(zero, false)) goto zero_iter_bb;
7458
7459 After all, we expect the zero=false, and thus we expect to have to
7460 evaluate all of the comparison expressions, so short-circuiting
7461 oughtn't be a win. Since the condition isn't protecting a
7462 denominator, we're not concerned about divide-by-zero, so we can
7463 fully evaluate count even if a numerator turned out to be wrong.
7464
7465 It seems like putting this all together would create much better
7466 scheduling opportunities, and less pressure on the chip's branch
7467 predictor. */
7468
7469static void
7470expand_omp_for_init_counts (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
7471 basic_block &entry_bb, tree *counts,
43895be5 7472 basic_block &zero_iter1_bb, int &first_zero_iter1,
7473 basic_block &zero_iter2_bb, int &first_zero_iter2,
3d483a94 7474 basic_block &l2_dom_bb)
7475{
7476 tree t, type = TREE_TYPE (fd->loop.v);
3d483a94 7477 edge e, ne;
7478 int i;
7479
7480 /* Collapsed loops need work for expansion into SSA form. */
7481 gcc_assert (!gimple_in_ssa_p (cfun));
7482
bc7bff74 7483 if (gimple_omp_for_combined_into_p (fd->for_stmt)
7484 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
7485 {
43895be5 7486 gcc_assert (fd->ordered == 0);
bc7bff74 7487 /* First two _looptemp_ clauses are for istart/iend, counts[0]
7488 isn't supposed to be handled, as the inner loop doesn't
7489 use it. */
7490 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7491 OMP_CLAUSE__LOOPTEMP_);
7492 gcc_assert (innerc);
7493 for (i = 0; i < fd->collapse; i++)
7494 {
7495 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7496 OMP_CLAUSE__LOOPTEMP_);
7497 gcc_assert (innerc);
7498 if (i)
7499 counts[i] = OMP_CLAUSE_DECL (innerc);
7500 else
7501 counts[0] = NULL_TREE;
7502 }
7503 return;
7504 }
7505
43895be5 7506 for (i = fd->collapse; i < fd->ordered; i++)
7507 {
7508 tree itype = TREE_TYPE (fd->loops[i].v);
7509 counts[i] = NULL_TREE;
7510 t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
7511 fold_convert (itype, fd->loops[i].n1),
7512 fold_convert (itype, fd->loops[i].n2));
7513 if (t && integer_zerop (t))
7514 {
7515 for (i = fd->collapse; i < fd->ordered; i++)
7516 counts[i] = build_int_cst (type, 0);
7517 break;
7518 }
7519 }
7520 for (i = 0; i < (fd->ordered ? fd->ordered : fd->collapse); i++)
3d483a94 7521 {
7522 tree itype = TREE_TYPE (fd->loops[i].v);
7523
43895be5 7524 if (i >= fd->collapse && counts[i])
7525 continue;
7526 if ((SSA_VAR_P (fd->loop.n2) || i >= fd->collapse)
3d483a94 7527 && ((t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
7528 fold_convert (itype, fd->loops[i].n1),
7529 fold_convert (itype, fd->loops[i].n2)))
7530 == NULL_TREE || !integer_onep (t)))
7531 {
1a91d914 7532 gcond *cond_stmt;
3d483a94 7533 tree n1, n2;
7534 n1 = fold_convert (itype, unshare_expr (fd->loops[i].n1));
7535 n1 = force_gimple_operand_gsi (gsi, n1, true, NULL_TREE,
7536 true, GSI_SAME_STMT);
7537 n2 = fold_convert (itype, unshare_expr (fd->loops[i].n2));
7538 n2 = force_gimple_operand_gsi (gsi, n2, true, NULL_TREE,
7539 true, GSI_SAME_STMT);
1a91d914 7540 cond_stmt = gimple_build_cond (fd->loops[i].cond_code, n1, n2,
7541 NULL_TREE, NULL_TREE);
7542 gsi_insert_before (gsi, cond_stmt, GSI_SAME_STMT);
7543 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
3d483a94 7544 expand_omp_regimplify_p, NULL, NULL)
1a91d914 7545 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
3d483a94 7546 expand_omp_regimplify_p, NULL, NULL))
7547 {
1a91d914 7548 *gsi = gsi_for_stmt (cond_stmt);
7549 gimple_regimplify_operands (cond_stmt, gsi);
3d483a94 7550 }
1a91d914 7551 e = split_block (entry_bb, cond_stmt);
43895be5 7552 basic_block &zero_iter_bb
7553 = i < fd->collapse ? zero_iter1_bb : zero_iter2_bb;
7554 int &first_zero_iter
7555 = i < fd->collapse ? first_zero_iter1 : first_zero_iter2;
3d483a94 7556 if (zero_iter_bb == NULL)
7557 {
1a91d914 7558 gassign *assign_stmt;
3d483a94 7559 first_zero_iter = i;
7560 zero_iter_bb = create_empty_bb (entry_bb);
b3083327 7561 add_bb_to_loop (zero_iter_bb, entry_bb->loop_father);
3d483a94 7562 *gsi = gsi_after_labels (zero_iter_bb);
43895be5 7563 if (i < fd->collapse)
7564 assign_stmt = gimple_build_assign (fd->loop.n2,
7565 build_zero_cst (type));
7566 else
7567 {
7568 counts[i] = create_tmp_reg (type, ".count");
7569 assign_stmt
7570 = gimple_build_assign (counts[i], build_zero_cst (type));
7571 }
1a91d914 7572 gsi_insert_before (gsi, assign_stmt, GSI_SAME_STMT);
3d483a94 7573 set_immediate_dominator (CDI_DOMINATORS, zero_iter_bb,
7574 entry_bb);
7575 }
7576 ne = make_edge (entry_bb, zero_iter_bb, EDGE_FALSE_VALUE);
7577 ne->probability = REG_BR_PROB_BASE / 2000 - 1;
7578 e->flags = EDGE_TRUE_VALUE;
7579 e->probability = REG_BR_PROB_BASE - ne->probability;
7580 if (l2_dom_bb == NULL)
7581 l2_dom_bb = entry_bb;
7582 entry_bb = e->dest;
7583 *gsi = gsi_last_bb (entry_bb);
7584 }
7585
7586 if (POINTER_TYPE_P (itype))
7587 itype = signed_type_for (itype);
7588 t = build_int_cst (itype, (fd->loops[i].cond_code == LT_EXPR
7589 ? -1 : 1));
7590 t = fold_build2 (PLUS_EXPR, itype,
7591 fold_convert (itype, fd->loops[i].step), t);
7592 t = fold_build2 (PLUS_EXPR, itype, t,
7593 fold_convert (itype, fd->loops[i].n2));
7594 t = fold_build2 (MINUS_EXPR, itype, t,
7595 fold_convert (itype, fd->loops[i].n1));
7596 /* ?? We could probably use CEIL_DIV_EXPR instead of
7597 TRUNC_DIV_EXPR and adjusting by hand. Unless we can't
7598 generate the same code in the end because generically we
7599 don't know that the values involved must be negative for
7600 GT?? */
7601 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
7602 t = fold_build2 (TRUNC_DIV_EXPR, itype,
7603 fold_build1 (NEGATE_EXPR, itype, t),
7604 fold_build1 (NEGATE_EXPR, itype,
7605 fold_convert (itype,
7606 fd->loops[i].step)));
7607 else
7608 t = fold_build2 (TRUNC_DIV_EXPR, itype, t,
7609 fold_convert (itype, fd->loops[i].step));
7610 t = fold_convert (type, t);
7611 if (TREE_CODE (t) == INTEGER_CST)
7612 counts[i] = t;
7613 else
7614 {
43895be5 7615 if (i < fd->collapse || i != first_zero_iter2)
7616 counts[i] = create_tmp_reg (type, ".count");
3d483a94 7617 expand_omp_build_assign (gsi, counts[i], t);
7618 }
43895be5 7619 if (SSA_VAR_P (fd->loop.n2) && i < fd->collapse)
3d483a94 7620 {
7621 if (i == 0)
7622 t = counts[0];
7623 else
7624 t = fold_build2 (MULT_EXPR, type, fd->loop.n2, counts[i]);
7625 expand_omp_build_assign (gsi, fd->loop.n2, t);
7626 }
7627 }
7628}
7629
7630
7631/* Helper function for expand_omp_{for_*,simd}. Generate code like:
7632 T = V;
7633 V3 = N31 + (T % count3) * STEP3;
7634 T = T / count3;
7635 V2 = N21 + (T % count2) * STEP2;
7636 T = T / count2;
7637 V1 = N11 + T * STEP1;
bc7bff74 7638 if this loop doesn't have an inner loop construct combined with it.
7639 If it does have an inner loop construct combined with it and the
7640 iteration count isn't known constant, store values from counts array
7641 into its _looptemp_ temporaries instead. */
3d483a94 7642
7643static void
7644expand_omp_for_init_vars (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
42acab1c 7645 tree *counts, gimple *inner_stmt, tree startvar)
3d483a94 7646{
7647 int i;
bc7bff74 7648 if (gimple_omp_for_combined_p (fd->for_stmt))
7649 {
7650 /* If fd->loop.n2 is constant, then no propagation of the counts
7651 is needed, they are constant. */
7652 if (TREE_CODE (fd->loop.n2) == INTEGER_CST)
7653 return;
7654
43895be5 7655 tree clauses = gimple_code (inner_stmt) != GIMPLE_OMP_FOR
7656 ? gimple_omp_taskreg_clauses (inner_stmt)
bc7bff74 7657 : gimple_omp_for_clauses (inner_stmt);
7658 /* First two _looptemp_ clauses are for istart/iend, counts[0]
7659 isn't supposed to be handled, as the inner loop doesn't
7660 use it. */
7661 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
7662 gcc_assert (innerc);
7663 for (i = 0; i < fd->collapse; i++)
7664 {
7665 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7666 OMP_CLAUSE__LOOPTEMP_);
7667 gcc_assert (innerc);
7668 if (i)
7669 {
7670 tree tem = OMP_CLAUSE_DECL (innerc);
7671 tree t = fold_convert (TREE_TYPE (tem), counts[i]);
7672 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
7673 false, GSI_CONTINUE_LINKING);
1a91d914 7674 gassign *stmt = gimple_build_assign (tem, t);
bc7bff74 7675 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7676 }
7677 }
7678 return;
7679 }
7680
3d483a94 7681 tree type = TREE_TYPE (fd->loop.v);
7682 tree tem = create_tmp_reg (type, ".tem");
1a91d914 7683 gassign *stmt = gimple_build_assign (tem, startvar);
3d483a94 7684 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7685
7686 for (i = fd->collapse - 1; i >= 0; i--)
7687 {
7688 tree vtype = TREE_TYPE (fd->loops[i].v), itype, t;
7689 itype = vtype;
7690 if (POINTER_TYPE_P (vtype))
7691 itype = signed_type_for (vtype);
7692 if (i != 0)
7693 t = fold_build2 (TRUNC_MOD_EXPR, type, tem, counts[i]);
7694 else
7695 t = tem;
7696 t = fold_convert (itype, t);
7697 t = fold_build2 (MULT_EXPR, itype, t,
7698 fold_convert (itype, fd->loops[i].step));
7699 if (POINTER_TYPE_P (vtype))
7700 t = fold_build_pointer_plus (fd->loops[i].n1, t);
7701 else
7702 t = fold_build2 (PLUS_EXPR, itype, fd->loops[i].n1, t);
7703 t = force_gimple_operand_gsi (gsi, t,
7704 DECL_P (fd->loops[i].v)
7705 && TREE_ADDRESSABLE (fd->loops[i].v),
7706 NULL_TREE, false,
7707 GSI_CONTINUE_LINKING);
7708 stmt = gimple_build_assign (fd->loops[i].v, t);
7709 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7710 if (i != 0)
7711 {
7712 t = fold_build2 (TRUNC_DIV_EXPR, type, tem, counts[i]);
7713 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
7714 false, GSI_CONTINUE_LINKING);
7715 stmt = gimple_build_assign (tem, t);
7716 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7717 }
7718 }
7719}
7720
7721
7722/* Helper function for expand_omp_for_*. Generate code like:
7723 L10:
7724 V3 += STEP3;
7725 if (V3 cond3 N32) goto BODY_BB; else goto L11;
7726 L11:
7727 V3 = N31;
7728 V2 += STEP2;
7729 if (V2 cond2 N22) goto BODY_BB; else goto L12;
7730 L12:
7731 V2 = N21;
7732 V1 += STEP1;
7733 goto BODY_BB; */
7734
7735static basic_block
7736extract_omp_for_update_vars (struct omp_for_data *fd, basic_block cont_bb,
7737 basic_block body_bb)
7738{
7739 basic_block last_bb, bb, collapse_bb = NULL;
7740 int i;
7741 gimple_stmt_iterator gsi;
7742 edge e;
7743 tree t;
42acab1c 7744 gimple *stmt;
3d483a94 7745
7746 last_bb = cont_bb;
7747 for (i = fd->collapse - 1; i >= 0; i--)
7748 {
7749 tree vtype = TREE_TYPE (fd->loops[i].v);
7750
7751 bb = create_empty_bb (last_bb);
b3083327 7752 add_bb_to_loop (bb, last_bb->loop_father);
3d483a94 7753 gsi = gsi_start_bb (bb);
7754
7755 if (i < fd->collapse - 1)
7756 {
7757 e = make_edge (last_bb, bb, EDGE_FALSE_VALUE);
7758 e->probability = REG_BR_PROB_BASE / 8;
7759
7760 t = fd->loops[i + 1].n1;
7761 t = force_gimple_operand_gsi (&gsi, t,
7762 DECL_P (fd->loops[i + 1].v)
7763 && TREE_ADDRESSABLE (fd->loops[i
7764 + 1].v),
7765 NULL_TREE, false,
7766 GSI_CONTINUE_LINKING);
7767 stmt = gimple_build_assign (fd->loops[i + 1].v, t);
7768 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7769 }
7770 else
7771 collapse_bb = bb;
7772
7773 set_immediate_dominator (CDI_DOMINATORS, bb, last_bb);
7774
7775 if (POINTER_TYPE_P (vtype))
7776 t = fold_build_pointer_plus (fd->loops[i].v, fd->loops[i].step);
7777 else
7778 t = fold_build2 (PLUS_EXPR, vtype, fd->loops[i].v, fd->loops[i].step);
7779 t = force_gimple_operand_gsi (&gsi, t,
7780 DECL_P (fd->loops[i].v)
7781 && TREE_ADDRESSABLE (fd->loops[i].v),
7782 NULL_TREE, false, GSI_CONTINUE_LINKING);
7783 stmt = gimple_build_assign (fd->loops[i].v, t);
7784 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7785
7786 if (i > 0)
7787 {
7788 t = fd->loops[i].n2;
7789 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7790 false, GSI_CONTINUE_LINKING);
7791 tree v = fd->loops[i].v;
7792 if (DECL_P (v) && TREE_ADDRESSABLE (v))
7793 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
7794 false, GSI_CONTINUE_LINKING);
7795 t = fold_build2 (fd->loops[i].cond_code, boolean_type_node, v, t);
7796 stmt = gimple_build_cond_empty (t);
7797 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7798 e = make_edge (bb, body_bb, EDGE_TRUE_VALUE);
7799 e->probability = REG_BR_PROB_BASE * 7 / 8;
7800 }
7801 else
7802 make_edge (bb, body_bb, EDGE_FALLTHRU);
7803 last_bb = bb;
7804 }
7805
7806 return collapse_bb;
7807}
7808
7809
43895be5 7810/* Expand #pragma omp ordered depend(source). */
1e8e9920 7811
43895be5 7812static void
7813expand_omp_ordered_source (gimple_stmt_iterator *gsi, struct omp_for_data *fd,
7814 tree *counts, location_t loc)
7815{
7816 enum built_in_function source_ix
7817 = fd->iter_type == long_integer_type_node
7818 ? BUILT_IN_GOMP_DOACROSS_POST : BUILT_IN_GOMP_DOACROSS_ULL_POST;
7819 gimple *g
7820 = gimple_build_call (builtin_decl_explicit (source_ix), 1,
7821 build_fold_addr_expr (counts[fd->ordered]));
7822 gimple_set_location (g, loc);
7823 gsi_insert_before (gsi, g, GSI_SAME_STMT);
7824}
1e8e9920 7825
43895be5 7826/* Expand a single depend from #pragma omp ordered depend(sink:...). */
1e8e9920 7827
43895be5 7828static void
7829expand_omp_ordered_sink (gimple_stmt_iterator *gsi, struct omp_for_data *fd,
7830 tree *counts, tree c, location_t loc)
7831{
7832 auto_vec<tree, 10> args;
7833 enum built_in_function sink_ix
7834 = fd->iter_type == long_integer_type_node
7835 ? BUILT_IN_GOMP_DOACROSS_WAIT : BUILT_IN_GOMP_DOACROSS_ULL_WAIT;
7836 tree t, off, coff = NULL_TREE, deps = OMP_CLAUSE_DECL (c), cond = NULL_TREE;
7837 int i;
7838 gimple_stmt_iterator gsi2 = *gsi;
7839 bool warned_step = false;
fd6481cf 7840
43895be5 7841 for (i = 0; i < fd->ordered; i++)
7842 {
7843 off = TREE_PURPOSE (deps);
7844 if (!integer_zerop (off))
7845 {
7846 gcc_assert (fd->loops[i].cond_code == LT_EXPR
7847 || fd->loops[i].cond_code == GT_EXPR);
7848 bool forward = fd->loops[i].cond_code == LT_EXPR;
7849 if (forward ^ OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
7850 warning_at (loc, 0, "%<depend(sink)%> clause waiting for "
7851 "lexically later iteration");
7852 break;
7853 }
7854 deps = TREE_CHAIN (deps);
7855 }
7856 /* If all offsets corresponding to the collapsed loops are zero,
7857 this depend clause can be ignored. FIXME: but there is still a
7858 flush needed. We need to emit one __sync_synchronize () for it
7859 though (perhaps conditionally)? Solve this together with the
7860 conservative dependence folding optimization.
7861 if (i >= fd->collapse)
7862 return; */
fd6481cf 7863
43895be5 7864 deps = OMP_CLAUSE_DECL (c);
7865 gsi_prev (&gsi2);
7866 edge e1 = split_block (gsi_bb (gsi2), gsi_stmt (gsi2));
7867 edge e2 = split_block_after_labels (e1->dest);
fd6481cf 7868
43895be5 7869 *gsi = gsi_after_labels (e1->dest);
7870 for (i = 0; i < fd->ordered; i++)
7871 {
7872 tree itype = TREE_TYPE (fd->loops[i].v);
7873 if (POINTER_TYPE_P (itype))
7874 itype = sizetype;
7875 if (i)
7876 deps = TREE_CHAIN (deps);
7877 off = TREE_PURPOSE (deps);
7878 tree s = fold_convert_loc (loc, itype, fd->loops[i].step);
7879
7880 if (integer_zerop (off))
7881 t = boolean_true_node;
7882 else
7883 {
7884 tree a;
7885 tree co = fold_convert_loc (loc, itype, off);
7886 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
7887 {
7888 if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
7889 co = fold_build1_loc (loc, NEGATE_EXPR, itype, co);
7890 a = fold_build2_loc (loc, POINTER_PLUS_EXPR,
7891 TREE_TYPE (fd->loops[i].v), fd->loops[i].v,
7892 co);
7893 }
7894 else if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
7895 a = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (fd->loops[i].v),
7896 fd->loops[i].v, co);
7897 else
7898 a = fold_build2_loc (loc, PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
7899 fd->loops[i].v, co);
7900 if (fd->loops[i].cond_code == LT_EXPR)
7901 {
7902 if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
7903 t = fold_build2_loc (loc, GE_EXPR, boolean_type_node, a,
7904 fd->loops[i].n1);
7905 else
7906 t = fold_build2_loc (loc, LT_EXPR, boolean_type_node, a,
7907 fd->loops[i].n2);
7908 }
7909 else if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
7910 t = fold_build2_loc (loc, GT_EXPR, boolean_type_node, a,
7911 fd->loops[i].n2);
7912 else
7913 t = fold_build2_loc (loc, LE_EXPR, boolean_type_node, a,
7914 fd->loops[i].n1);
7915 }
7916 if (cond)
7917 cond = fold_build2_loc (loc, BIT_AND_EXPR, boolean_type_node, cond, t);
7918 else
7919 cond = t;
7920
7921 off = fold_convert_loc (loc, itype, off);
7922
7923 if (fd->loops[i].cond_code == LT_EXPR
7924 ? !integer_onep (fd->loops[i].step)
7925 : !integer_minus_onep (fd->loops[i].step))
7926 {
7927 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
7928 t = fold_build2_loc (loc, TRUNC_MOD_EXPR, itype, off,
7929 fold_build1_loc (loc, NEGATE_EXPR, itype,
7930 s));
7931 else
7932 t = fold_build2_loc (loc, TRUNC_MOD_EXPR, itype, off, s);
7933 t = fold_build2_loc (loc, EQ_EXPR, boolean_type_node, t,
7934 build_int_cst (itype, 0));
7935 if (integer_zerop (t) && !warned_step)
7936 {
7937 warning_at (loc, 0, "%<depend(sink)%> refers to iteration never "
7938 "in the iteration space");
7939 warned_step = true;
7940 }
7941 cond = fold_build2_loc (loc, BIT_AND_EXPR, boolean_type_node,
7942 cond, t);
7943 }
7944
7945 if (i <= fd->collapse - 1 && fd->collapse > 1)
7946 t = fd->loop.v;
7947 else if (counts[i])
7948 t = counts[i];
7949 else
7950 {
7951 t = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (fd->loops[i].v),
7952 fd->loops[i].v, fd->loops[i].n1);
7953 t = fold_convert_loc (loc, fd->iter_type, t);
7954 }
7955 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
7956 off = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, off,
7957 fold_build1_loc (loc, NEGATE_EXPR, itype,
7958 s));
7959 else
7960 off = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, off, s);
7961 if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
7962 off = fold_build1_loc (loc, NEGATE_EXPR, itype, off);
7963 off = fold_convert_loc (loc, fd->iter_type, off);
7964 if (i <= fd->collapse - 1 && fd->collapse > 1)
7965 {
7966 if (i)
7967 off = fold_build2_loc (loc, PLUS_EXPR, fd->iter_type, coff,
7968 off);
7969 if (i < fd->collapse - 1)
7970 {
7971 coff = fold_build2_loc (loc, MULT_EXPR, fd->iter_type, off,
7972 counts[i]);
7973 continue;
7974 }
7975 }
7976 off = unshare_expr (off);
7977 t = fold_build2_loc (loc, PLUS_EXPR, fd->iter_type, t, off);
7978 t = force_gimple_operand_gsi (gsi, t, true, NULL_TREE,
7979 true, GSI_SAME_STMT);
7980 args.safe_push (t);
7981 }
7982 gimple *g = gimple_build_call_vec (builtin_decl_explicit (sink_ix), args);
7983 gimple_set_location (g, loc);
7984 gsi_insert_before (gsi, g, GSI_SAME_STMT);
7985
7986 *gsi = gsi_last_bb (e1->src);
7987 cond = unshare_expr (cond);
7988 cond = force_gimple_operand_gsi (gsi, cond, true, NULL_TREE, false,
7989 GSI_CONTINUE_LINKING);
7990 gsi_insert_after (gsi, gimple_build_cond_empty (cond), GSI_NEW_STMT);
7991 edge e3 = make_edge (e1->src, e2->dest, EDGE_FALSE_VALUE);
7992 e3->probability = REG_BR_PROB_BASE / 8;
7993 e1->probability = REG_BR_PROB_BASE - e3->probability;
7994 e1->flags = EDGE_TRUE_VALUE;
7995 set_immediate_dominator (CDI_DOMINATORS, e2->dest, e1->src);
7996
7997 *gsi = gsi_after_labels (e2->dest);
7998}
7999
8000/* Expand all #pragma omp ordered depend(source) and
8001 #pragma omp ordered depend(sink:...) constructs in the current
8002 #pragma omp for ordered(n) region. */
8003
8004static void
8005expand_omp_ordered_source_sink (struct omp_region *region,
8006 struct omp_for_data *fd, tree *counts,
8007 basic_block cont_bb)
8008{
8009 struct omp_region *inner;
8010 int i;
8011 for (i = fd->collapse - 1; i < fd->ordered; i++)
8012 if (i == fd->collapse - 1 && fd->collapse > 1)
8013 counts[i] = NULL_TREE;
8014 else if (i >= fd->collapse && !cont_bb)
8015 counts[i] = build_zero_cst (fd->iter_type);
8016 else if (!POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v))
8017 && integer_onep (fd->loops[i].step))
8018 counts[i] = NULL_TREE;
8019 else
8020 counts[i] = create_tmp_var (fd->iter_type, ".orditer");
8021 tree atype
8022 = build_array_type_nelts (fd->iter_type, fd->ordered - fd->collapse + 1);
8023 counts[fd->ordered] = create_tmp_var (atype, ".orditera");
8024 TREE_ADDRESSABLE (counts[fd->ordered]) = 1;
8025
8026 for (inner = region->inner; inner; inner = inner->next)
8027 if (inner->type == GIMPLE_OMP_ORDERED)
8028 {
8029 gomp_ordered *ord_stmt = inner->ord_stmt;
8030 gimple_stmt_iterator gsi = gsi_for_stmt (ord_stmt);
8031 location_t loc = gimple_location (ord_stmt);
8032 tree c;
8033 for (c = gimple_omp_ordered_clauses (ord_stmt);
8034 c; c = OMP_CLAUSE_CHAIN (c))
8035 if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE)
8036 break;
8037 if (c)
8038 expand_omp_ordered_source (&gsi, fd, counts, loc);
8039 for (c = gimple_omp_ordered_clauses (ord_stmt);
8040 c; c = OMP_CLAUSE_CHAIN (c))
8041 if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK)
8042 expand_omp_ordered_sink (&gsi, fd, counts, c, loc);
8043 gsi_remove (&gsi, true);
8044 }
8045}
8046
8047/* Wrap the body into fd->ordered - fd->collapse loops that aren't
8048 collapsed. */
8049
8050static basic_block
8051expand_omp_for_ordered_loops (struct omp_for_data *fd, tree *counts,
8052 basic_block cont_bb, basic_block body_bb,
8053 bool ordered_lastprivate)
8054{
8055 if (fd->ordered == fd->collapse)
8056 return cont_bb;
8057
8058 if (!cont_bb)
8059 {
8060 gimple_stmt_iterator gsi = gsi_after_labels (body_bb);
8061 for (int i = fd->collapse; i < fd->ordered; i++)
8062 {
8063 tree type = TREE_TYPE (fd->loops[i].v);
8064 tree n1 = fold_convert (type, fd->loops[i].n1);
8065 expand_omp_build_assign (&gsi, fd->loops[i].v, n1);
8066 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8067 size_int (i - fd->collapse + 1),
8068 NULL_TREE, NULL_TREE);
8069 expand_omp_build_assign (&gsi, aref, build_zero_cst (fd->iter_type));
8070 }
8071 return NULL;
8072 }
8073
8074 for (int i = fd->ordered - 1; i >= fd->collapse; i--)
8075 {
8076 tree t, type = TREE_TYPE (fd->loops[i].v);
8077 gimple_stmt_iterator gsi = gsi_after_labels (body_bb);
8078 expand_omp_build_assign (&gsi, fd->loops[i].v,
8079 fold_convert (type, fd->loops[i].n1));
8080 if (counts[i])
8081 expand_omp_build_assign (&gsi, counts[i],
8082 build_zero_cst (fd->iter_type));
8083 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8084 size_int (i - fd->collapse + 1),
8085 NULL_TREE, NULL_TREE);
8086 expand_omp_build_assign (&gsi, aref, build_zero_cst (fd->iter_type));
8087 if (!gsi_end_p (gsi))
8088 gsi_prev (&gsi);
8089 else
8090 gsi = gsi_last_bb (body_bb);
8091 edge e1 = split_block (body_bb, gsi_stmt (gsi));
8092 basic_block new_body = e1->dest;
8093 if (body_bb == cont_bb)
8094 cont_bb = new_body;
8095 edge e2 = NULL;
8096 basic_block new_header;
8097 if (EDGE_COUNT (cont_bb->preds) > 0)
8098 {
8099 gsi = gsi_last_bb (cont_bb);
8100 if (POINTER_TYPE_P (type))
8101 t = fold_build_pointer_plus (fd->loops[i].v,
8102 fold_convert (sizetype,
8103 fd->loops[i].step));
8104 else
8105 t = fold_build2 (PLUS_EXPR, type, fd->loops[i].v,
8106 fold_convert (type, fd->loops[i].step));
8107 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
8108 if (counts[i])
8109 {
8110 t = fold_build2 (PLUS_EXPR, fd->iter_type, counts[i],
8111 build_int_cst (fd->iter_type, 1));
8112 expand_omp_build_assign (&gsi, counts[i], t);
8113 t = counts[i];
8114 }
8115 else
8116 {
8117 t = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->loops[i].v),
8118 fd->loops[i].v, fd->loops[i].n1);
8119 t = fold_convert (fd->iter_type, t);
8120 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8121 true, GSI_SAME_STMT);
8122 }
8123 aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8124 size_int (i - fd->collapse + 1),
8125 NULL_TREE, NULL_TREE);
8126 expand_omp_build_assign (&gsi, aref, t);
8127 gsi_prev (&gsi);
8128 e2 = split_block (cont_bb, gsi_stmt (gsi));
8129 new_header = e2->dest;
8130 }
8131 else
8132 new_header = cont_bb;
8133 gsi = gsi_after_labels (new_header);
8134 tree v = force_gimple_operand_gsi (&gsi, fd->loops[i].v, true, NULL_TREE,
8135 true, GSI_SAME_STMT);
8136 tree n2
8137 = force_gimple_operand_gsi (&gsi, fold_convert (type, fd->loops[i].n2),
8138 true, NULL_TREE, true, GSI_SAME_STMT);
8139 t = build2 (fd->loops[i].cond_code, boolean_type_node, v, n2);
8140 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_NEW_STMT);
8141 edge e3 = split_block (new_header, gsi_stmt (gsi));
8142 cont_bb = e3->dest;
8143 remove_edge (e1);
8144 make_edge (body_bb, new_header, EDGE_FALLTHRU);
8145 e3->flags = EDGE_FALSE_VALUE;
8146 e3->probability = REG_BR_PROB_BASE / 8;
8147 e1 = make_edge (new_header, new_body, EDGE_TRUE_VALUE);
8148 e1->probability = REG_BR_PROB_BASE - e3->probability;
8149
8150 set_immediate_dominator (CDI_DOMINATORS, new_header, body_bb);
8151 set_immediate_dominator (CDI_DOMINATORS, new_body, new_header);
8152
8153 if (e2)
8154 {
8155 struct loop *loop = alloc_loop ();
8156 loop->header = new_header;
8157 loop->latch = e2->src;
8158 add_loop (loop, body_bb->loop_father);
8159 }
8160 }
8161
8162 /* If there are any lastprivate clauses and it is possible some loops
8163 might have zero iterations, ensure all the decls are initialized,
8164 otherwise we could crash evaluating C++ class iterators with lastprivate
8165 clauses. */
8166 bool need_inits = false;
8167 for (int i = fd->collapse; ordered_lastprivate && i < fd->ordered; i++)
8168 if (need_inits)
8169 {
8170 tree type = TREE_TYPE (fd->loops[i].v);
8171 gimple_stmt_iterator gsi = gsi_after_labels (body_bb);
8172 expand_omp_build_assign (&gsi, fd->loops[i].v,
8173 fold_convert (type, fd->loops[i].n1));
8174 }
8175 else
8176 {
8177 tree type = TREE_TYPE (fd->loops[i].v);
8178 tree this_cond = fold_build2 (fd->loops[i].cond_code,
8179 boolean_type_node,
8180 fold_convert (type, fd->loops[i].n1),
8181 fold_convert (type, fd->loops[i].n2));
8182 if (!integer_onep (this_cond))
8183 need_inits = true;
8184 }
8185
8186 return cont_bb;
8187}
8188
8189
8190/* A subroutine of expand_omp_for. Generate code for a parallel
8191 loop with any schedule. Given parameters:
8192
8193 for (V = N1; V cond N2; V += STEP) BODY;
8194
8195 where COND is "<" or ">", we generate pseudocode
8196
8197 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
8198 if (more) goto L0; else goto L3;
8199 L0:
8200 V = istart0;
8201 iend = iend0;
8202 L1:
8203 BODY;
8204 V += STEP;
8205 if (V cond iend) goto L1; else goto L2;
8206 L2:
8207 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
8208 L3:
8209
8210 If this is a combined omp parallel loop, instead of the call to
8211 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
8212 If this is gimple_omp_for_combined_p loop, then instead of assigning
8213 V and iend in L0 we assign the first two _looptemp_ clause decls of the
8214 inner GIMPLE_OMP_FOR and V += STEP; and
8215 if (V cond iend) goto L1; else goto L2; are removed.
8216
8217 For collapsed loops, given parameters:
8218 collapse(3)
8219 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
8220 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
8221 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
8222 BODY;
8223
8224 we generate pseudocode
8225
8226 if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
8227 if (cond3 is <)
8228 adj = STEP3 - 1;
8229 else
8230 adj = STEP3 + 1;
8231 count3 = (adj + N32 - N31) / STEP3;
8232 if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
8233 if (cond2 is <)
8234 adj = STEP2 - 1;
8235 else
8236 adj = STEP2 + 1;
fd6481cf 8237 count2 = (adj + N22 - N21) / STEP2;
8e6b4515 8238 if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
fd6481cf 8239 if (cond1 is <)
8240 adj = STEP1 - 1;
8241 else
8242 adj = STEP1 + 1;
8243 count1 = (adj + N12 - N11) / STEP1;
8244 count = count1 * count2 * count3;
8e6b4515 8245 goto Z1;
8246 Z0:
8247 count = 0;
8248 Z1:
fd6481cf 8249 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
8250 if (more) goto L0; else goto L3;
8251 L0:
8252 V = istart0;
8253 T = V;
8254 V3 = N31 + (T % count3) * STEP3;
8255 T = T / count3;
8256 V2 = N21 + (T % count2) * STEP2;
8257 T = T / count2;
8258 V1 = N11 + T * STEP1;
8259 iend = iend0;
8260 L1:
8261 BODY;
8262 V += 1;
8263 if (V < iend) goto L10; else goto L2;
8264 L10:
8265 V3 += STEP3;
8266 if (V3 cond3 N32) goto L1; else goto L11;
8267 L11:
8268 V3 = N31;
8269 V2 += STEP2;
8270 if (V2 cond2 N22) goto L1; else goto L12;
8271 L12:
8272 V2 = N21;
8273 V1 += STEP1;
8274 goto L1;
8275 L2:
8276 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
8277 L3:
8278
8279 */
1e8e9920 8280
61e47ac8 8281static void
773c5ba7 8282expand_omp_for_generic (struct omp_region *region,
8283 struct omp_for_data *fd,
1e8e9920 8284 enum built_in_function start_fn,
bc7bff74 8285 enum built_in_function next_fn,
42acab1c 8286 gimple *inner_stmt)
1e8e9920 8287{
75a70cf9 8288 tree type, istart0, iend0, iend;
fd6481cf 8289 tree t, vmain, vback, bias = NULL_TREE;
8290 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, collapse_bb;
03ed154b 8291 basic_block l2_bb = NULL, l3_bb = NULL;
75a70cf9 8292 gimple_stmt_iterator gsi;
1a91d914 8293 gassign *assign_stmt;
773c5ba7 8294 bool in_combined_parallel = is_combined_parallel (region);
ac6e3339 8295 bool broken_loop = region->cont == NULL;
79acaae1 8296 edge e, ne;
fd6481cf 8297 tree *counts = NULL;
8298 int i;
43895be5 8299 bool ordered_lastprivate = false;
ac6e3339 8300
8301 gcc_assert (!broken_loop || !in_combined_parallel);
fd6481cf 8302 gcc_assert (fd->iter_type == long_integer_type_node
8303 || !in_combined_parallel);
1e8e9920 8304
61e47ac8 8305 entry_bb = region->entry;
03ed154b 8306 cont_bb = region->cont;
fd6481cf 8307 collapse_bb = NULL;
ac6e3339 8308 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
8309 gcc_assert (broken_loop
8310 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
8311 l0_bb = split_edge (FALLTHRU_EDGE (entry_bb));
8312 l1_bb = single_succ (l0_bb);
8313 if (!broken_loop)
03ed154b 8314 {
8315 l2_bb = create_empty_bb (cont_bb);
95cd5725 8316 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb
8317 || (single_succ_edge (BRANCH_EDGE (cont_bb)->dest)->dest
8318 == l1_bb));
ac6e3339 8319 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
03ed154b 8320 }
ac6e3339 8321 else
8322 l2_bb = NULL;
8323 l3_bb = BRANCH_EDGE (entry_bb)->dest;
8324 exit_bb = region->exit;
773c5ba7 8325
75a70cf9 8326 gsi = gsi_last_bb (entry_bb);
fd6481cf 8327
75a70cf9 8328 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
43895be5 8329 if (fd->ordered
8330 && find_omp_clause (gimple_omp_for_clauses (gsi_stmt (gsi)),
8331 OMP_CLAUSE_LASTPRIVATE))
8332 ordered_lastprivate = false;
8333 if (fd->collapse > 1 || fd->ordered)
fd6481cf 8334 {
43895be5 8335 int first_zero_iter1 = -1, first_zero_iter2 = -1;
8336 basic_block zero_iter1_bb = NULL, zero_iter2_bb = NULL, l2_dom_bb = NULL;
8e6b4515 8337
43895be5 8338 counts = XALLOCAVEC (tree, fd->ordered ? fd->ordered + 1 : fd->collapse);
3d483a94 8339 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
43895be5 8340 zero_iter1_bb, first_zero_iter1,
8341 zero_iter2_bb, first_zero_iter2, l2_dom_bb);
fd6481cf 8342
43895be5 8343 if (zero_iter1_bb)
8e6b4515 8344 {
8345 /* Some counts[i] vars might be uninitialized if
8346 some loop has zero iterations. But the body shouldn't
8347 be executed in that case, so just avoid uninit warnings. */
43895be5 8348 for (i = first_zero_iter1;
8349 i < (fd->ordered ? fd->ordered : fd->collapse); i++)
8e6b4515 8350 if (SSA_VAR_P (counts[i]))
8351 TREE_NO_WARNING (counts[i]) = 1;
8352 gsi_prev (&gsi);
8353 e = split_block (entry_bb, gsi_stmt (gsi));
8354 entry_bb = e->dest;
43895be5 8355 make_edge (zero_iter1_bb, entry_bb, EDGE_FALLTHRU);
8e6b4515 8356 gsi = gsi_last_bb (entry_bb);
8357 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
8358 get_immediate_dominator (CDI_DOMINATORS,
43895be5 8359 zero_iter1_bb));
8360 }
8361 if (zero_iter2_bb)
8362 {
8363 /* Some counts[i] vars might be uninitialized if
8364 some loop has zero iterations. But the body shouldn't
8365 be executed in that case, so just avoid uninit warnings. */
8366 for (i = first_zero_iter2; i < fd->ordered; i++)
8367 if (SSA_VAR_P (counts[i]))
8368 TREE_NO_WARNING (counts[i]) = 1;
8369 if (zero_iter1_bb)
8370 make_edge (zero_iter2_bb, entry_bb, EDGE_FALLTHRU);
8371 else
8372 {
8373 gsi_prev (&gsi);
8374 e = split_block (entry_bb, gsi_stmt (gsi));
8375 entry_bb = e->dest;
8376 make_edge (zero_iter2_bb, entry_bb, EDGE_FALLTHRU);
8377 gsi = gsi_last_bb (entry_bb);
8378 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
8379 get_immediate_dominator
8380 (CDI_DOMINATORS, zero_iter2_bb));
8381 }
8382 }
8383 if (fd->collapse == 1)
8384 {
8385 counts[0] = fd->loop.n2;
8386 fd->loop = fd->loops[0];
8387 }
8388 }
8389
8390 type = TREE_TYPE (fd->loop.v);
8391 istart0 = create_tmp_var (fd->iter_type, ".istart0");
8392 iend0 = create_tmp_var (fd->iter_type, ".iend0");
8393 TREE_ADDRESSABLE (istart0) = 1;
8394 TREE_ADDRESSABLE (iend0) = 1;
8395
8396 /* See if we need to bias by LLONG_MIN. */
8397 if (fd->iter_type == long_long_unsigned_type_node
8398 && TREE_CODE (type) == INTEGER_TYPE
8399 && !TYPE_UNSIGNED (type)
8400 && fd->ordered == 0)
8401 {
8402 tree n1, n2;
8403
8404 if (fd->loop.cond_code == LT_EXPR)
8405 {
8406 n1 = fd->loop.n1;
8407 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
8e6b4515 8408 }
43895be5 8409 else
8410 {
8411 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
8412 n2 = fd->loop.n1;
8413 }
8414 if (TREE_CODE (n1) != INTEGER_CST
8415 || TREE_CODE (n2) != INTEGER_CST
8416 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
8417 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
fd6481cf 8418 }
43895be5 8419
8420 gimple_stmt_iterator gsif = gsi;
8421 gsi_prev (&gsif);
8422
8423 tree arr = NULL_TREE;
79acaae1 8424 if (in_combined_parallel)
8425 {
43895be5 8426 gcc_assert (fd->ordered == 0);
79acaae1 8427 /* In a combined parallel loop, emit a call to
8428 GOMP_loop_foo_next. */
b9a16870 8429 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
79acaae1 8430 build_fold_addr_expr (istart0),
8431 build_fold_addr_expr (iend0));
8432 }
8433 else
1e8e9920 8434 {
c2f47e15 8435 tree t0, t1, t2, t3, t4;
773c5ba7 8436 /* If this is not a combined parallel loop, emit a call to
8437 GOMP_loop_foo_start in ENTRY_BB. */
c2f47e15 8438 t4 = build_fold_addr_expr (iend0);
8439 t3 = build_fold_addr_expr (istart0);
43895be5 8440 if (fd->ordered)
c799f233 8441 {
43895be5 8442 t0 = build_int_cst (unsigned_type_node,
8443 fd->ordered - fd->collapse + 1);
8444 arr = create_tmp_var (build_array_type_nelts (fd->iter_type,
8445 fd->ordered
8446 - fd->collapse + 1),
8447 ".omp_counts");
8448 DECL_NAMELESS (arr) = 1;
8449 TREE_ADDRESSABLE (arr) = 1;
8450 TREE_STATIC (arr) = 1;
8451 vec<constructor_elt, va_gc> *v;
8452 vec_alloc (v, fd->ordered - fd->collapse + 1);
8453 int idx;
8454
8455 for (idx = 0; idx < fd->ordered - fd->collapse + 1; idx++)
8456 {
8457 tree c;
8458 if (idx == 0 && fd->collapse > 1)
8459 c = fd->loop.n2;
8460 else
8461 c = counts[idx + fd->collapse - 1];
8462 tree purpose = size_int (idx);
8463 CONSTRUCTOR_APPEND_ELT (v, purpose, c);
8464 if (TREE_CODE (c) != INTEGER_CST)
8465 TREE_STATIC (arr) = 0;
8466 }
8467
8468 DECL_INITIAL (arr) = build_constructor (TREE_TYPE (arr), v);
8469 if (!TREE_STATIC (arr))
8470 force_gimple_operand_gsi (&gsi, build1 (DECL_EXPR,
8471 void_type_node, arr),
8472 true, NULL_TREE, true, GSI_SAME_STMT);
8473 t1 = build_fold_addr_expr (arr);
8474 t2 = NULL_TREE;
c799f233 8475 }
8476 else
8477 {
43895be5 8478 t2 = fold_convert (fd->iter_type, fd->loop.step);
8479 t1 = fd->loop.n2;
8480 t0 = fd->loop.n1;
8481 if (gimple_omp_for_combined_into_p (fd->for_stmt))
8482 {
8483 tree innerc
8484 = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
8485 OMP_CLAUSE__LOOPTEMP_);
8486 gcc_assert (innerc);
8487 t0 = OMP_CLAUSE_DECL (innerc);
8488 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
8489 OMP_CLAUSE__LOOPTEMP_);
8490 gcc_assert (innerc);
8491 t1 = OMP_CLAUSE_DECL (innerc);
8492 }
8493 if (POINTER_TYPE_P (TREE_TYPE (t0))
8494 && TYPE_PRECISION (TREE_TYPE (t0))
8495 != TYPE_PRECISION (fd->iter_type))
8496 {
8497 /* Avoid casting pointers to integer of a different size. */
8498 tree itype = signed_type_for (type);
8499 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
8500 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
8501 }
8502 else
8503 {
8504 t1 = fold_convert (fd->iter_type, t1);
8505 t0 = fold_convert (fd->iter_type, t0);
8506 }
8507 if (bias)
8508 {
8509 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
8510 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
8511 }
fd6481cf 8512 }
43895be5 8513 if (fd->iter_type == long_integer_type_node || fd->ordered)
fd6481cf 8514 {
8515 if (fd->chunk_size)
8516 {
8517 t = fold_convert (fd->iter_type, fd->chunk_size);
43895be5 8518 t = omp_adjust_chunk_size (t, fd->simd_schedule);
8519 if (fd->ordered)
8520 t = build_call_expr (builtin_decl_explicit (start_fn),
8521 5, t0, t1, t, t3, t4);
8522 else
8523 t = build_call_expr (builtin_decl_explicit (start_fn),
8524 6, t0, t1, t2, t, t3, t4);
fd6481cf 8525 }
43895be5 8526 else if (fd->ordered)
8527 t = build_call_expr (builtin_decl_explicit (start_fn),
8528 4, t0, t1, t3, t4);
fd6481cf 8529 else
b9a16870 8530 t = build_call_expr (builtin_decl_explicit (start_fn),
8531 5, t0, t1, t2, t3, t4);
1e8e9920 8532 }
c2f47e15 8533 else
fd6481cf 8534 {
8535 tree t5;
8536 tree c_bool_type;
b9a16870 8537 tree bfn_decl;
fd6481cf 8538
8539 /* The GOMP_loop_ull_*start functions have additional boolean
8540 argument, true for < loops and false for > loops.
8541 In Fortran, the C bool type can be different from
8542 boolean_type_node. */
b9a16870 8543 bfn_decl = builtin_decl_explicit (start_fn);
8544 c_bool_type = TREE_TYPE (TREE_TYPE (bfn_decl));
fd6481cf 8545 t5 = build_int_cst (c_bool_type,
8546 fd->loop.cond_code == LT_EXPR ? 1 : 0);
8547 if (fd->chunk_size)
8548 {
b9a16870 8549 tree bfn_decl = builtin_decl_explicit (start_fn);
fd6481cf 8550 t = fold_convert (fd->iter_type, fd->chunk_size);
43895be5 8551 t = omp_adjust_chunk_size (t, fd->simd_schedule);
b9a16870 8552 t = build_call_expr (bfn_decl, 7, t5, t0, t1, t2, t, t3, t4);
fd6481cf 8553 }
8554 else
b9a16870 8555 t = build_call_expr (builtin_decl_explicit (start_fn),
8556 6, t5, t0, t1, t2, t3, t4);
fd6481cf 8557 }
1e8e9920 8558 }
fd6481cf 8559 if (TREE_TYPE (t) != boolean_type_node)
8560 t = fold_build2 (NE_EXPR, boolean_type_node,
8561 t, build_int_cst (TREE_TYPE (t), 0));
75a70cf9 8562 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8563 true, GSI_SAME_STMT);
43895be5 8564 if (arr && !TREE_STATIC (arr))
8565 {
8566 tree clobber = build_constructor (TREE_TYPE (arr), NULL);
8567 TREE_THIS_VOLATILE (clobber) = 1;
8568 gsi_insert_before (&gsi, gimple_build_assign (arr, clobber),
8569 GSI_SAME_STMT);
8570 }
75a70cf9 8571 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
79acaae1 8572
75a70cf9 8573 /* Remove the GIMPLE_OMP_FOR statement. */
8574 gsi_remove (&gsi, true);
1e8e9920 8575
43895be5 8576 if (gsi_end_p (gsif))
8577 gsif = gsi_after_labels (gsi_bb (gsif));
8578 gsi_next (&gsif);
8579
773c5ba7 8580 /* Iteration setup for sequential loop goes in L0_BB. */
3d483a94 8581 tree startvar = fd->loop.v;
8582 tree endvar = NULL_TREE;
8583
bc7bff74 8584 if (gimple_omp_for_combined_p (fd->for_stmt))
8585 {
8586 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_FOR
8587 && gimple_omp_for_kind (inner_stmt)
8588 == GF_OMP_FOR_KIND_SIMD);
8589 tree innerc = find_omp_clause (gimple_omp_for_clauses (inner_stmt),
8590 OMP_CLAUSE__LOOPTEMP_);
8591 gcc_assert (innerc);
8592 startvar = OMP_CLAUSE_DECL (innerc);
8593 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
8594 OMP_CLAUSE__LOOPTEMP_);
8595 gcc_assert (innerc);
8596 endvar = OMP_CLAUSE_DECL (innerc);
8597 }
8598
75a70cf9 8599 gsi = gsi_start_bb (l0_bb);
1efcacec 8600 t = istart0;
43895be5 8601 if (fd->ordered && fd->collapse == 1)
8602 t = fold_build2 (MULT_EXPR, fd->iter_type, t,
8603 fold_convert (fd->iter_type, fd->loop.step));
8604 else if (bias)
1efcacec 8605 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
43895be5 8606 if (fd->ordered && fd->collapse == 1)
8607 {
8608 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8609 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (startvar),
8610 fd->loop.n1, fold_convert (sizetype, t));
8611 else
8612 {
8613 t = fold_convert (TREE_TYPE (startvar), t);
8614 t = fold_build2 (PLUS_EXPR, TREE_TYPE (startvar),
8615 fd->loop.n1, t);
8616 }
8617 }
8618 else
8619 {
8620 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8621 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
8622 t = fold_convert (TREE_TYPE (startvar), t);
8623 }
4abecb72 8624 t = force_gimple_operand_gsi (&gsi, t,
3d483a94 8625 DECL_P (startvar)
8626 && TREE_ADDRESSABLE (startvar),
4abecb72 8627 NULL_TREE, false, GSI_CONTINUE_LINKING);
1a91d914 8628 assign_stmt = gimple_build_assign (startvar, t);
8629 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
1e8e9920 8630
1efcacec 8631 t = iend0;
43895be5 8632 if (fd->ordered && fd->collapse == 1)
8633 t = fold_build2 (MULT_EXPR, fd->iter_type, t,
8634 fold_convert (fd->iter_type, fd->loop.step));
8635 else if (bias)
1efcacec 8636 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
43895be5 8637 if (fd->ordered && fd->collapse == 1)
fd6481cf 8638 {
43895be5 8639 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8640 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (startvar),
8641 fd->loop.n1, fold_convert (sizetype, t));
8642 else
8643 {
8644 t = fold_convert (TREE_TYPE (startvar), t);
8645 t = fold_build2 (PLUS_EXPR, TREE_TYPE (startvar),
8646 fd->loop.n1, t);
8647 }
8648 }
8649 else
8650 {
8651 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8652 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
8653 t = fold_convert (TREE_TYPE (startvar), t);
8654 }
8655 iend = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8656 false, GSI_CONTINUE_LINKING);
8657 if (endvar)
8658 {
8659 assign_stmt = gimple_build_assign (endvar, iend);
1a91d914 8660 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
d44f2f7c 8661 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (iend)))
1a91d914 8662 assign_stmt = gimple_build_assign (fd->loop.v, iend);
d44f2f7c 8663 else
e9cf809e 8664 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, iend);
1a91d914 8665 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
fd6481cf 8666 }
43895be5 8667 /* Handle linear clause adjustments. */
8668 tree itercnt = NULL_TREE;
8669 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_FOR)
8670 for (tree c = gimple_omp_for_clauses (fd->for_stmt);
8671 c; c = OMP_CLAUSE_CHAIN (c))
8672 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
8673 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
8674 {
8675 tree d = OMP_CLAUSE_DECL (c);
8676 bool is_ref = is_reference (d);
8677 tree t = d, a, dest;
8678 if (is_ref)
8679 t = build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c), t);
8680 tree type = TREE_TYPE (t);
8681 if (POINTER_TYPE_P (type))
8682 type = sizetype;
8683 dest = unshare_expr (t);
8684 tree v = create_tmp_var (TREE_TYPE (t), NULL);
8685 expand_omp_build_assign (&gsif, v, t);
8686 if (itercnt == NULL_TREE)
8687 {
8688 itercnt = startvar;
8689 tree n1 = fd->loop.n1;
8690 if (POINTER_TYPE_P (TREE_TYPE (itercnt)))
8691 {
8692 itercnt
8693 = fold_convert (signed_type_for (TREE_TYPE (itercnt)),
8694 itercnt);
8695 n1 = fold_convert (TREE_TYPE (itercnt), n1);
8696 }
8697 itercnt = fold_build2 (MINUS_EXPR, TREE_TYPE (itercnt),
8698 itercnt, n1);
8699 itercnt = fold_build2 (EXACT_DIV_EXPR, TREE_TYPE (itercnt),
8700 itercnt, fd->loop.step);
8701 itercnt = force_gimple_operand_gsi (&gsi, itercnt, true,
8702 NULL_TREE, false,
8703 GSI_CONTINUE_LINKING);
8704 }
8705 a = fold_build2 (MULT_EXPR, type,
8706 fold_convert (type, itercnt),
8707 fold_convert (type, OMP_CLAUSE_LINEAR_STEP (c)));
8708 t = fold_build2 (type == TREE_TYPE (t) ? PLUS_EXPR
8709 : POINTER_PLUS_EXPR, TREE_TYPE (t), v, a);
8710 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8711 false, GSI_CONTINUE_LINKING);
8712 assign_stmt = gimple_build_assign (dest, t);
8713 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
8714 }
3d483a94 8715 if (fd->collapse > 1)
bc7bff74 8716 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
773c5ba7 8717
43895be5 8718 if (fd->ordered)
8719 {
8720 /* Until now, counts array contained number of iterations or
8721 variable containing it for ith loop. From now on, we need
8722 those counts only for collapsed loops, and only for the 2nd
8723 till the last collapsed one. Move those one element earlier,
8724 we'll use counts[fd->collapse - 1] for the first source/sink
8725 iteration counter and so on and counts[fd->ordered]
8726 as the array holding the current counter values for
8727 depend(source). */
8728 if (fd->collapse > 1)
8729 memmove (counts, counts + 1, (fd->collapse - 1) * sizeof (counts[0]));
8730 if (broken_loop)
8731 {
8732 int i;
8733 for (i = fd->collapse; i < fd->ordered; i++)
8734 {
8735 tree type = TREE_TYPE (fd->loops[i].v);
8736 tree this_cond
8737 = fold_build2 (fd->loops[i].cond_code, boolean_type_node,
8738 fold_convert (type, fd->loops[i].n1),
8739 fold_convert (type, fd->loops[i].n2));
8740 if (!integer_onep (this_cond))
8741 break;
8742 }
8743 if (i < fd->ordered)
8744 {
8745 cont_bb
8746 = create_empty_bb (EXIT_BLOCK_PTR_FOR_FN (cfun)->prev_bb);
8747 add_bb_to_loop (cont_bb, l1_bb->loop_father);
8748 gimple_stmt_iterator gsi = gsi_after_labels (cont_bb);
8749 gimple *g = gimple_build_omp_continue (fd->loop.v, fd->loop.v);
8750 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
8751 make_edge (cont_bb, l3_bb, EDGE_FALLTHRU);
8752 make_edge (cont_bb, l1_bb, 0);
8753 l2_bb = create_empty_bb (cont_bb);
8754 broken_loop = false;
8755 }
8756 }
8757 expand_omp_ordered_source_sink (region, fd, counts, cont_bb);
8758 cont_bb = expand_omp_for_ordered_loops (fd, counts, cont_bb, l1_bb,
8759 ordered_lastprivate);
8760 if (counts[fd->collapse - 1])
8761 {
8762 gcc_assert (fd->collapse == 1);
8763 gsi = gsi_last_bb (l0_bb);
8764 expand_omp_build_assign (&gsi, counts[fd->collapse - 1],
8765 istart0, true);
8766 gsi = gsi_last_bb (cont_bb);
8767 t = fold_build2 (PLUS_EXPR, fd->iter_type, counts[fd->collapse - 1],
8768 build_int_cst (fd->iter_type, 1));
8769 expand_omp_build_assign (&gsi, counts[fd->collapse - 1], t);
8770 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8771 size_zero_node, NULL_TREE, NULL_TREE);
8772 expand_omp_build_assign (&gsi, aref, counts[fd->collapse - 1]);
8773 t = counts[fd->collapse - 1];
8774 }
8775 else if (fd->collapse > 1)
8776 t = fd->loop.v;
8777 else
8778 {
8779 t = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->loops[0].v),
8780 fd->loops[0].v, fd->loops[0].n1);
8781 t = fold_convert (fd->iter_type, t);
8782 }
8783 gsi = gsi_last_bb (l0_bb);
8784 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8785 size_zero_node, NULL_TREE, NULL_TREE);
8786 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8787 false, GSI_CONTINUE_LINKING);
8788 expand_omp_build_assign (&gsi, aref, t, true);
8789 }
8790
ac6e3339 8791 if (!broken_loop)
03ed154b 8792 {
ac6e3339 8793 /* Code to control the increment and predicate for the sequential
8794 loop goes in the CONT_BB. */
75a70cf9 8795 gsi = gsi_last_bb (cont_bb);
1a91d914 8796 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
8797 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
8798 vmain = gimple_omp_continue_control_use (cont_stmt);
8799 vback = gimple_omp_continue_control_def (cont_stmt);
79acaae1 8800
bc7bff74 8801 if (!gimple_omp_for_combined_p (fd->for_stmt))
3d483a94 8802 {
8803 if (POINTER_TYPE_P (type))
8804 t = fold_build_pointer_plus (vmain, fd->loop.step);
8805 else
8806 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
8807 t = force_gimple_operand_gsi (&gsi, t,
8808 DECL_P (vback)
8809 && TREE_ADDRESSABLE (vback),
8810 NULL_TREE, true, GSI_SAME_STMT);
1a91d914 8811 assign_stmt = gimple_build_assign (vback, t);
8812 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
3d483a94 8813
43895be5 8814 if (fd->ordered && counts[fd->collapse - 1] == NULL_TREE)
8815 {
8816 if (fd->collapse > 1)
8817 t = fd->loop.v;
8818 else
8819 {
8820 t = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->loops[0].v),
8821 fd->loops[0].v, fd->loops[0].n1);
8822 t = fold_convert (fd->iter_type, t);
8823 }
8824 tree aref = build4 (ARRAY_REF, fd->iter_type,
8825 counts[fd->ordered], size_zero_node,
8826 NULL_TREE, NULL_TREE);
8827 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8828 true, GSI_SAME_STMT);
8829 expand_omp_build_assign (&gsi, aref, t);
8830 }
8831
3d483a94 8832 t = build2 (fd->loop.cond_code, boolean_type_node,
8833 DECL_P (vback) && TREE_ADDRESSABLE (vback) ? t : vback,
8834 iend);
1a91d914 8835 gcond *cond_stmt = gimple_build_cond_empty (t);
8836 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
3d483a94 8837 }
773c5ba7 8838
75a70cf9 8839 /* Remove GIMPLE_OMP_CONTINUE. */
8840 gsi_remove (&gsi, true);
773c5ba7 8841
bc7bff74 8842 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
3d483a94 8843 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, l1_bb);
fd6481cf 8844
ac6e3339 8845 /* Emit code to get the next parallel iteration in L2_BB. */
75a70cf9 8846 gsi = gsi_start_bb (l2_bb);
773c5ba7 8847
b9a16870 8848 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
ac6e3339 8849 build_fold_addr_expr (istart0),
8850 build_fold_addr_expr (iend0));
75a70cf9 8851 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8852 false, GSI_CONTINUE_LINKING);
fd6481cf 8853 if (TREE_TYPE (t) != boolean_type_node)
8854 t = fold_build2 (NE_EXPR, boolean_type_node,
8855 t, build_int_cst (TREE_TYPE (t), 0));
1a91d914 8856 gcond *cond_stmt = gimple_build_cond_empty (t);
8857 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
ac6e3339 8858 }
1e8e9920 8859
61e47ac8 8860 /* Add the loop cleanup function. */
75a70cf9 8861 gsi = gsi_last_bb (exit_bb);
8862 if (gimple_omp_return_nowait_p (gsi_stmt (gsi)))
b9a16870 8863 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
bc7bff74 8864 else if (gimple_omp_return_lhs (gsi_stmt (gsi)))
8865 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL);
61e47ac8 8866 else
b9a16870 8867 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END);
1a91d914 8868 gcall *call_stmt = gimple_build_call (t, 0);
bc7bff74 8869 if (gimple_omp_return_lhs (gsi_stmt (gsi)))
1a91d914 8870 gimple_call_set_lhs (call_stmt, gimple_omp_return_lhs (gsi_stmt (gsi)));
8871 gsi_insert_after (&gsi, call_stmt, GSI_SAME_STMT);
43895be5 8872 if (fd->ordered)
8873 {
8874 tree arr = counts[fd->ordered];
8875 tree clobber = build_constructor (TREE_TYPE (arr), NULL);
8876 TREE_THIS_VOLATILE (clobber) = 1;
8877 gsi_insert_after (&gsi, gimple_build_assign (arr, clobber),
8878 GSI_SAME_STMT);
8879 }
75a70cf9 8880 gsi_remove (&gsi, true);
773c5ba7 8881
8882 /* Connect the new blocks. */
79acaae1 8883 find_edge (entry_bb, l0_bb)->flags = EDGE_TRUE_VALUE;
8884 find_edge (entry_bb, l3_bb)->flags = EDGE_FALSE_VALUE;
1e8e9920 8885
ac6e3339 8886 if (!broken_loop)
8887 {
75a70cf9 8888 gimple_seq phis;
8889
79acaae1 8890 e = find_edge (cont_bb, l3_bb);
8891 ne = make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
8892
75a70cf9 8893 phis = phi_nodes (l3_bb);
8894 for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi))
8895 {
42acab1c 8896 gimple *phi = gsi_stmt (gsi);
75a70cf9 8897 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, ne),
8898 PHI_ARG_DEF_FROM_EDGE (phi, e));
8899 }
79acaae1 8900 remove_edge (e);
8901
ac6e3339 8902 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
3d483a94 8903 e = find_edge (cont_bb, l1_bb);
95cd5725 8904 if (e == NULL)
8905 {
8906 e = BRANCH_EDGE (cont_bb);
8907 gcc_assert (single_succ (e->dest) == l1_bb);
8908 }
bc7bff74 8909 if (gimple_omp_for_combined_p (fd->for_stmt))
8910 {
8911 remove_edge (e);
8912 e = NULL;
8913 }
3d483a94 8914 else if (fd->collapse > 1)
fd6481cf 8915 {
fd6481cf 8916 remove_edge (e);
8917 e = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
8918 }
8919 else
3d483a94 8920 e->flags = EDGE_TRUE_VALUE;
8921 if (e)
fd6481cf 8922 {
3d483a94 8923 e->probability = REG_BR_PROB_BASE * 7 / 8;
8924 find_edge (cont_bb, l2_bb)->probability = REG_BR_PROB_BASE / 8;
8925 }
8926 else
8927 {
8928 e = find_edge (cont_bb, l2_bb);
8929 e->flags = EDGE_FALLTHRU;
fd6481cf 8930 }
ac6e3339 8931 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
79acaae1 8932
2131a1a9 8933 if (gimple_in_ssa_p (cfun))
8934 {
8935 /* Add phis to the outer loop that connect to the phis in the inner,
8936 original loop, and move the loop entry value of the inner phi to
8937 the loop entry value of the outer phi. */
8938 gphi_iterator psi;
8939 for (psi = gsi_start_phis (l3_bb); !gsi_end_p (psi); gsi_next (&psi))
8940 {
8941 source_location locus;
8942 gphi *nphi;
8943 gphi *exit_phi = psi.phi ();
8944
8945 edge l2_to_l3 = find_edge (l2_bb, l3_bb);
8946 tree exit_res = PHI_ARG_DEF_FROM_EDGE (exit_phi, l2_to_l3);
8947
8948 basic_block latch = BRANCH_EDGE (cont_bb)->dest;
8949 edge latch_to_l1 = find_edge (latch, l1_bb);
8950 gphi *inner_phi
8951 = find_phi_with_arg_on_edge (exit_res, latch_to_l1);
8952
8953 tree t = gimple_phi_result (exit_phi);
8954 tree new_res = copy_ssa_name (t, NULL);
8955 nphi = create_phi_node (new_res, l0_bb);
8956
8957 edge l0_to_l1 = find_edge (l0_bb, l1_bb);
8958 t = PHI_ARG_DEF_FROM_EDGE (inner_phi, l0_to_l1);
8959 locus = gimple_phi_arg_location_from_edge (inner_phi, l0_to_l1);
8960 edge entry_to_l0 = find_edge (entry_bb, l0_bb);
8961 add_phi_arg (nphi, t, entry_to_l0, locus);
8962
8963 edge l2_to_l0 = find_edge (l2_bb, l0_bb);
8964 add_phi_arg (nphi, exit_res, l2_to_l0, UNKNOWN_LOCATION);
8965
8966 add_phi_arg (inner_phi, new_res, l0_to_l1, UNKNOWN_LOCATION);
8967 };
8968 }
8969
79acaae1 8970 set_immediate_dominator (CDI_DOMINATORS, l2_bb,
8971 recompute_dominator (CDI_DOMINATORS, l2_bb));
8972 set_immediate_dominator (CDI_DOMINATORS, l3_bb,
8973 recompute_dominator (CDI_DOMINATORS, l3_bb));
8974 set_immediate_dominator (CDI_DOMINATORS, l0_bb,
8975 recompute_dominator (CDI_DOMINATORS, l0_bb));
8976 set_immediate_dominator (CDI_DOMINATORS, l1_bb,
8977 recompute_dominator (CDI_DOMINATORS, l1_bb));
04c2922b 8978
1c6a437b 8979 /* We enter expand_omp_for_generic with a loop. This original loop may
8980 have its own loop struct, or it may be part of an outer loop struct
8981 (which may be the fake loop). */
8982 struct loop *outer_loop = entry_bb->loop_father;
8983 bool orig_loop_has_loop_struct = l1_bb->loop_father != outer_loop;
8984
8985 add_bb_to_loop (l2_bb, outer_loop);
8986
8987 /* We've added a new loop around the original loop. Allocate the
8988 corresponding loop struct. */
8989 struct loop *new_loop = alloc_loop ();
8990 new_loop->header = l0_bb;
8991 new_loop->latch = l2_bb;
8992 add_loop (new_loop, outer_loop);
8993
8994 /* Allocate a loop structure for the original loop unless we already
8995 had one. */
8996 if (!orig_loop_has_loop_struct
8997 && !gimple_omp_for_combined_p (fd->for_stmt))
3d483a94 8998 {
1c6a437b 8999 struct loop *orig_loop = alloc_loop ();
9000 orig_loop->header = l1_bb;
3d483a94 9001 /* The loop may have multiple latches. */
1c6a437b 9002 add_loop (orig_loop, new_loop);
3d483a94 9003 }
ac6e3339 9004 }
1e8e9920 9005}
9006
9007
773c5ba7 9008/* A subroutine of expand_omp_for. Generate code for a parallel
9009 loop with static schedule and no specified chunk size. Given
9010 parameters:
1e8e9920 9011
9012 for (V = N1; V cond N2; V += STEP) BODY;
9013
9014 where COND is "<" or ">", we generate pseudocode
9015
8e6b4515 9016 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
1e8e9920 9017 if (cond is <)
9018 adj = STEP - 1;
9019 else
9020 adj = STEP + 1;
fd6481cf 9021 if ((__typeof (V)) -1 > 0 && cond is >)
9022 n = -(adj + N2 - N1) / -STEP;
9023 else
9024 n = (adj + N2 - N1) / STEP;
1e8e9920 9025 q = n / nthreads;
31712e83 9026 tt = n % nthreads;
9027 if (threadid < tt) goto L3; else goto L4;
9028 L3:
9029 tt = 0;
9030 q = q + 1;
9031 L4:
9032 s0 = q * threadid + tt;
9033 e0 = s0 + q;
79acaae1 9034 V = s0 * STEP + N1;
1e8e9920 9035 if (s0 >= e0) goto L2; else goto L0;
9036 L0:
1e8e9920 9037 e = e0 * STEP + N1;
9038 L1:
9039 BODY;
9040 V += STEP;
9041 if (V cond e) goto L1;
1e8e9920 9042 L2:
9043*/
9044
61e47ac8 9045static void
773c5ba7 9046expand_omp_for_static_nochunk (struct omp_region *region,
bc7bff74 9047 struct omp_for_data *fd,
42acab1c 9048 gimple *inner_stmt)
1e8e9920 9049{
31712e83 9050 tree n, q, s0, e0, e, t, tt, nthreads, threadid;
fd6481cf 9051 tree type, itype, vmain, vback;
31712e83 9052 basic_block entry_bb, second_bb, third_bb, exit_bb, seq_start_bb;
bc7bff74 9053 basic_block body_bb, cont_bb, collapse_bb = NULL;
61e47ac8 9054 basic_block fin_bb;
75a70cf9 9055 gimple_stmt_iterator gsi;
31712e83 9056 edge ep;
bc7bff74 9057 bool broken_loop = region->cont == NULL;
9058 tree *counts = NULL;
9059 tree n1, n2, step;
1e8e9920 9060
fd6481cf 9061 itype = type = TREE_TYPE (fd->loop.v);
9062 if (POINTER_TYPE_P (type))
3cea8318 9063 itype = signed_type_for (type);
1e8e9920 9064
61e47ac8 9065 entry_bb = region->entry;
61e47ac8 9066 cont_bb = region->cont;
ac6e3339 9067 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
bc7bff74 9068 fin_bb = BRANCH_EDGE (entry_bb)->dest;
9069 gcc_assert (broken_loop
9070 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
ac6e3339 9071 seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb));
9072 body_bb = single_succ (seq_start_bb);
bc7bff74 9073 if (!broken_loop)
9074 {
86a932e0 9075 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb
9076 || single_succ (BRANCH_EDGE (cont_bb)->dest) == body_bb);
bc7bff74 9077 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
9078 }
61e47ac8 9079 exit_bb = region->exit;
9080
773c5ba7 9081 /* Iteration space partitioning goes in ENTRY_BB. */
75a70cf9 9082 gsi = gsi_last_bb (entry_bb);
9083 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
61e47ac8 9084
bc7bff74 9085 if (fd->collapse > 1)
9086 {
43895be5 9087 int first_zero_iter = -1, dummy = -1;
9088 basic_block l2_dom_bb = NULL, dummy_bb = NULL;
bc7bff74 9089
9090 counts = XALLOCAVEC (tree, fd->collapse);
9091 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
9092 fin_bb, first_zero_iter,
43895be5 9093 dummy_bb, dummy, l2_dom_bb);
bc7bff74 9094 t = NULL_TREE;
9095 }
9096 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
9097 t = integer_one_node;
9098 else
9099 t = fold_binary (fd->loop.cond_code, boolean_type_node,
9100 fold_convert (type, fd->loop.n1),
9101 fold_convert (type, fd->loop.n2));
9102 if (fd->collapse == 1
9103 && TYPE_UNSIGNED (type)
8e6b4515 9104 && (t == NULL_TREE || !integer_onep (t)))
9105 {
8e6b4515 9106 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
9107 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
9108 true, GSI_SAME_STMT);
9109 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
9110 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
9111 true, GSI_SAME_STMT);
1a91d914 9112 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
9113 NULL_TREE, NULL_TREE);
9114 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
9115 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
8e6b4515 9116 expand_omp_regimplify_p, NULL, NULL)
1a91d914 9117 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
8e6b4515 9118 expand_omp_regimplify_p, NULL, NULL))
9119 {
1a91d914 9120 gsi = gsi_for_stmt (cond_stmt);
9121 gimple_regimplify_operands (cond_stmt, &gsi);
8e6b4515 9122 }
1a91d914 9123 ep = split_block (entry_bb, cond_stmt);
8e6b4515 9124 ep->flags = EDGE_TRUE_VALUE;
9125 entry_bb = ep->dest;
9126 ep->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
9127 ep = make_edge (ep->src, fin_bb, EDGE_FALSE_VALUE);
9128 ep->probability = REG_BR_PROB_BASE / 2000 - 1;
9129 if (gimple_in_ssa_p (cfun))
9130 {
9131 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
1a91d914 9132 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
9133 !gsi_end_p (gpi); gsi_next (&gpi))
8e6b4515 9134 {
1a91d914 9135 gphi *phi = gpi.phi ();
8e6b4515 9136 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
9137 ep, UNKNOWN_LOCATION);
9138 }
9139 }
9140 gsi = gsi_last_bb (entry_bb);
9141 }
9142
ca4c3545 9143 switch (gimple_omp_for_kind (fd->for_stmt))
9144 {
9145 case GF_OMP_FOR_KIND_FOR:
9146 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
9147 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
9148 break;
9149 case GF_OMP_FOR_KIND_DISTRIBUTE:
9150 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
9151 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
9152 break;
ca4c3545 9153 default:
9154 gcc_unreachable ();
9155 }
9156 nthreads = build_call_expr (nthreads, 0);
9157 nthreads = fold_convert (itype, nthreads);
9158 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
75a70cf9 9159 true, GSI_SAME_STMT);
ca4c3545 9160 threadid = build_call_expr (threadid, 0);
9161 threadid = fold_convert (itype, threadid);
9162 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
75a70cf9 9163 true, GSI_SAME_STMT);
1e8e9920 9164
bc7bff74 9165 n1 = fd->loop.n1;
9166 n2 = fd->loop.n2;
9167 step = fd->loop.step;
9168 if (gimple_omp_for_combined_into_p (fd->for_stmt))
9169 {
9170 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
9171 OMP_CLAUSE__LOOPTEMP_);
9172 gcc_assert (innerc);
9173 n1 = OMP_CLAUSE_DECL (innerc);
9174 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9175 OMP_CLAUSE__LOOPTEMP_);
9176 gcc_assert (innerc);
9177 n2 = OMP_CLAUSE_DECL (innerc);
9178 }
9179 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
9180 true, NULL_TREE, true, GSI_SAME_STMT);
9181 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
9182 true, NULL_TREE, true, GSI_SAME_STMT);
9183 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
9184 true, NULL_TREE, true, GSI_SAME_STMT);
fd6481cf 9185
9186 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
bc7bff74 9187 t = fold_build2 (PLUS_EXPR, itype, step, t);
9188 t = fold_build2 (PLUS_EXPR, itype, t, n2);
9189 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
fd6481cf 9190 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
9191 t = fold_build2 (TRUNC_DIV_EXPR, itype,
9192 fold_build1 (NEGATE_EXPR, itype, t),
bc7bff74 9193 fold_build1 (NEGATE_EXPR, itype, step));
fd6481cf 9194 else
bc7bff74 9195 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
fd6481cf 9196 t = fold_convert (itype, t);
75a70cf9 9197 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
1e8e9920 9198
072f7ab1 9199 q = create_tmp_reg (itype, "q");
fd6481cf 9200 t = fold_build2 (TRUNC_DIV_EXPR, itype, n, nthreads);
31712e83 9201 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
9202 gsi_insert_before (&gsi, gimple_build_assign (q, t), GSI_SAME_STMT);
9203
072f7ab1 9204 tt = create_tmp_reg (itype, "tt");
31712e83 9205 t = fold_build2 (TRUNC_MOD_EXPR, itype, n, nthreads);
9206 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
9207 gsi_insert_before (&gsi, gimple_build_assign (tt, t), GSI_SAME_STMT);
1e8e9920 9208
31712e83 9209 t = build2 (LT_EXPR, boolean_type_node, threadid, tt);
1a91d914 9210 gcond *cond_stmt = gimple_build_cond_empty (t);
9211 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
31712e83 9212
1a91d914 9213 second_bb = split_block (entry_bb, cond_stmt)->dest;
31712e83 9214 gsi = gsi_last_bb (second_bb);
9215 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
9216
9217 gsi_insert_before (&gsi, gimple_build_assign (tt, build_int_cst (itype, 0)),
9218 GSI_SAME_STMT);
1a91d914 9219 gassign *assign_stmt
e9cf809e 9220 = gimple_build_assign (q, PLUS_EXPR, q, build_int_cst (itype, 1));
1a91d914 9221 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
31712e83 9222
1a91d914 9223 third_bb = split_block (second_bb, assign_stmt)->dest;
31712e83 9224 gsi = gsi_last_bb (third_bb);
9225 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
1e8e9920 9226
fd6481cf 9227 t = build2 (MULT_EXPR, itype, q, threadid);
31712e83 9228 t = build2 (PLUS_EXPR, itype, t, tt);
75a70cf9 9229 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
1e8e9920 9230
fd6481cf 9231 t = fold_build2 (PLUS_EXPR, itype, s0, q);
75a70cf9 9232 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
79acaae1 9233
1e8e9920 9234 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
75a70cf9 9235 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
773c5ba7 9236
75a70cf9 9237 /* Remove the GIMPLE_OMP_FOR statement. */
9238 gsi_remove (&gsi, true);
773c5ba7 9239
9240 /* Setup code for sequential iteration goes in SEQ_START_BB. */
75a70cf9 9241 gsi = gsi_start_bb (seq_start_bb);
1e8e9920 9242
bc7bff74 9243 tree startvar = fd->loop.v;
9244 tree endvar = NULL_TREE;
9245
9246 if (gimple_omp_for_combined_p (fd->for_stmt))
9247 {
9248 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
9249 ? gimple_omp_parallel_clauses (inner_stmt)
9250 : gimple_omp_for_clauses (inner_stmt);
9251 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
9252 gcc_assert (innerc);
9253 startvar = OMP_CLAUSE_DECL (innerc);
9254 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9255 OMP_CLAUSE__LOOPTEMP_);
9256 gcc_assert (innerc);
9257 endvar = OMP_CLAUSE_DECL (innerc);
9561765e 9258 if (fd->collapse > 1 && TREE_CODE (fd->loop.n2) != INTEGER_CST
9259 && gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
9260 {
9261 int i;
9262 for (i = 1; i < fd->collapse; i++)
9263 {
9264 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9265 OMP_CLAUSE__LOOPTEMP_);
9266 gcc_assert (innerc);
9267 }
9268 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9269 OMP_CLAUSE__LOOPTEMP_);
9270 if (innerc)
9271 {
9272 /* If needed (distribute parallel for with lastprivate),
9273 propagate down the total number of iterations. */
9274 tree t = fold_convert (TREE_TYPE (OMP_CLAUSE_DECL (innerc)),
9275 fd->loop.n2);
9276 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, false,
9277 GSI_CONTINUE_LINKING);
9278 assign_stmt = gimple_build_assign (OMP_CLAUSE_DECL (innerc), t);
9279 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9280 }
9281 }
bc7bff74 9282 }
fd6481cf 9283 t = fold_convert (itype, s0);
bc7bff74 9284 t = fold_build2 (MULT_EXPR, itype, t, step);
fd6481cf 9285 if (POINTER_TYPE_P (type))
bc7bff74 9286 t = fold_build_pointer_plus (n1, t);
fd6481cf 9287 else
bc7bff74 9288 t = fold_build2 (PLUS_EXPR, type, t, n1);
9289 t = fold_convert (TREE_TYPE (startvar), t);
4abecb72 9290 t = force_gimple_operand_gsi (&gsi, t,
bc7bff74 9291 DECL_P (startvar)
9292 && TREE_ADDRESSABLE (startvar),
4abecb72 9293 NULL_TREE, false, GSI_CONTINUE_LINKING);
1a91d914 9294 assign_stmt = gimple_build_assign (startvar, t);
9295 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
48e1416a 9296
fd6481cf 9297 t = fold_convert (itype, e0);
bc7bff74 9298 t = fold_build2 (MULT_EXPR, itype, t, step);
fd6481cf 9299 if (POINTER_TYPE_P (type))
bc7bff74 9300 t = fold_build_pointer_plus (n1, t);
fd6481cf 9301 else
bc7bff74 9302 t = fold_build2 (PLUS_EXPR, type, t, n1);
9303 t = fold_convert (TREE_TYPE (startvar), t);
75a70cf9 9304 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9305 false, GSI_CONTINUE_LINKING);
bc7bff74 9306 if (endvar)
9307 {
1a91d914 9308 assign_stmt = gimple_build_assign (endvar, e);
9309 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
d44f2f7c 9310 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
1a91d914 9311 assign_stmt = gimple_build_assign (fd->loop.v, e);
d44f2f7c 9312 else
e9cf809e 9313 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
1a91d914 9314 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
bc7bff74 9315 }
43895be5 9316 /* Handle linear clause adjustments. */
9317 tree itercnt = NULL_TREE;
9318 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_FOR)
9319 for (tree c = gimple_omp_for_clauses (fd->for_stmt);
9320 c; c = OMP_CLAUSE_CHAIN (c))
9321 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
9322 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
9323 {
9324 tree d = OMP_CLAUSE_DECL (c);
9325 bool is_ref = is_reference (d);
9326 tree t = d, a, dest;
9327 if (is_ref)
9328 t = build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c), t);
9329 if (itercnt == NULL_TREE)
9330 {
9331 if (gimple_omp_for_combined_into_p (fd->for_stmt))
9332 {
9333 itercnt = fold_build2 (MINUS_EXPR, itype,
9334 fold_convert (itype, n1),
9335 fold_convert (itype, fd->loop.n1));
9336 itercnt = fold_build2 (EXACT_DIV_EXPR, itype, itercnt, step);
9337 itercnt = fold_build2 (PLUS_EXPR, itype, itercnt, s0);
9338 itercnt = force_gimple_operand_gsi (&gsi, itercnt, true,
9339 NULL_TREE, false,
9340 GSI_CONTINUE_LINKING);
9341 }
9342 else
9343 itercnt = s0;
9344 }
9345 tree type = TREE_TYPE (t);
9346 if (POINTER_TYPE_P (type))
9347 type = sizetype;
9348 a = fold_build2 (MULT_EXPR, type,
9349 fold_convert (type, itercnt),
9350 fold_convert (type, OMP_CLAUSE_LINEAR_STEP (c)));
9351 dest = unshare_expr (t);
9352 t = fold_build2 (type == TREE_TYPE (t) ? PLUS_EXPR
9353 : POINTER_PLUS_EXPR, TREE_TYPE (t), t, a);
9354 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9355 false, GSI_CONTINUE_LINKING);
9356 assign_stmt = gimple_build_assign (dest, t);
9357 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9358 }
bc7bff74 9359 if (fd->collapse > 1)
9360 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
1e8e9920 9361
bc7bff74 9362 if (!broken_loop)
9363 {
9364 /* The code controlling the sequential loop replaces the
9365 GIMPLE_OMP_CONTINUE. */
9366 gsi = gsi_last_bb (cont_bb);
1a91d914 9367 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
9368 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
9369 vmain = gimple_omp_continue_control_use (cont_stmt);
9370 vback = gimple_omp_continue_control_def (cont_stmt);
79acaae1 9371
bc7bff74 9372 if (!gimple_omp_for_combined_p (fd->for_stmt))
9373 {
9374 if (POINTER_TYPE_P (type))
9375 t = fold_build_pointer_plus (vmain, step);
9376 else
9377 t = fold_build2 (PLUS_EXPR, type, vmain, step);
9378 t = force_gimple_operand_gsi (&gsi, t,
9379 DECL_P (vback)
9380 && TREE_ADDRESSABLE (vback),
9381 NULL_TREE, true, GSI_SAME_STMT);
1a91d914 9382 assign_stmt = gimple_build_assign (vback, t);
9383 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
79acaae1 9384
bc7bff74 9385 t = build2 (fd->loop.cond_code, boolean_type_node,
9386 DECL_P (vback) && TREE_ADDRESSABLE (vback)
9387 ? t : vback, e);
9388 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
9389 }
1e8e9920 9390
bc7bff74 9391 /* Remove the GIMPLE_OMP_CONTINUE statement. */
9392 gsi_remove (&gsi, true);
9393
9394 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
9395 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
9396 }
773c5ba7 9397
75a70cf9 9398 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
9399 gsi = gsi_last_bb (exit_bb);
9400 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
bc7bff74 9401 {
9402 t = gimple_omp_return_lhs (gsi_stmt (gsi));
a8e785ba 9403 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
bc7bff74 9404 }
75a70cf9 9405 gsi_remove (&gsi, true);
773c5ba7 9406
9407 /* Connect all the blocks. */
31712e83 9408 ep = make_edge (entry_bb, third_bb, EDGE_FALSE_VALUE);
9409 ep->probability = REG_BR_PROB_BASE / 4 * 3;
9410 ep = find_edge (entry_bb, second_bb);
9411 ep->flags = EDGE_TRUE_VALUE;
9412 ep->probability = REG_BR_PROB_BASE / 4;
9413 find_edge (third_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
9414 find_edge (third_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
79acaae1 9415
bc7bff74 9416 if (!broken_loop)
9417 {
9418 ep = find_edge (cont_bb, body_bb);
86a932e0 9419 if (ep == NULL)
9420 {
9421 ep = BRANCH_EDGE (cont_bb);
9422 gcc_assert (single_succ (ep->dest) == body_bb);
9423 }
bc7bff74 9424 if (gimple_omp_for_combined_p (fd->for_stmt))
9425 {
9426 remove_edge (ep);
9427 ep = NULL;
9428 }
9429 else if (fd->collapse > 1)
9430 {
9431 remove_edge (ep);
9432 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
9433 }
9434 else
9435 ep->flags = EDGE_TRUE_VALUE;
9436 find_edge (cont_bb, fin_bb)->flags
9437 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
9438 }
48e1416a 9439
31712e83 9440 set_immediate_dominator (CDI_DOMINATORS, second_bb, entry_bb);
9441 set_immediate_dominator (CDI_DOMINATORS, third_bb, entry_bb);
9442 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, third_bb);
bc7bff74 9443
79acaae1 9444 set_immediate_dominator (CDI_DOMINATORS, body_bb,
9445 recompute_dominator (CDI_DOMINATORS, body_bb));
9446 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
9447 recompute_dominator (CDI_DOMINATORS, fin_bb));
04c2922b 9448
86a932e0 9449 struct loop *loop = body_bb->loop_father;
9450 if (loop != entry_bb->loop_father)
9451 {
9452 gcc_assert (loop->header == body_bb);
9453 gcc_assert (broken_loop
9454 || loop->latch == region->cont
9455 || single_pred (loop->latch) == region->cont);
9456 return;
9457 }
9458
bc7bff74 9459 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
9460 {
86a932e0 9461 loop = alloc_loop ();
bc7bff74 9462 loop->header = body_bb;
9463 if (collapse_bb == NULL)
9464 loop->latch = cont_bb;
9465 add_loop (loop, body_bb->loop_father);
9466 }
1e8e9920 9467}
9468
281001a9 9469/* Return phi in E->DEST with ARG on edge E. */
9470
9471static gphi *
9472find_phi_with_arg_on_edge (tree arg, edge e)
9473{
9474 basic_block bb = e->dest;
9475
9476 for (gphi_iterator gpi = gsi_start_phis (bb);
9477 !gsi_end_p (gpi);
9478 gsi_next (&gpi))
9479 {
9480 gphi *phi = gpi.phi ();
9481 if (PHI_ARG_DEF_FROM_EDGE (phi, e) == arg)
9482 return phi;
9483 }
9484
9485 return NULL;
9486}
773c5ba7 9487
9488/* A subroutine of expand_omp_for. Generate code for a parallel
9489 loop with static schedule and a specified chunk size. Given
9490 parameters:
1e8e9920 9491
9492 for (V = N1; V cond N2; V += STEP) BODY;
9493
9494 where COND is "<" or ">", we generate pseudocode
9495
8e6b4515 9496 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
1e8e9920 9497 if (cond is <)
9498 adj = STEP - 1;
9499 else
9500 adj = STEP + 1;
fd6481cf 9501 if ((__typeof (V)) -1 > 0 && cond is >)
9502 n = -(adj + N2 - N1) / -STEP;
9503 else
9504 n = (adj + N2 - N1) / STEP;
1e8e9920 9505 trip = 0;
79acaae1 9506 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
9507 here so that V is defined
9508 if the loop is not entered
1e8e9920 9509 L0:
9510 s0 = (trip * nthreads + threadid) * CHUNK;
9511 e0 = min(s0 + CHUNK, n);
9512 if (s0 < n) goto L1; else goto L4;
9513 L1:
9514 V = s0 * STEP + N1;
9515 e = e0 * STEP + N1;
9516 L2:
9517 BODY;
9518 V += STEP;
9519 if (V cond e) goto L2; else goto L3;
9520 L3:
9521 trip += 1;
9522 goto L0;
9523 L4:
1e8e9920 9524*/
9525
61e47ac8 9526static void
bc7bff74 9527expand_omp_for_static_chunk (struct omp_region *region,
42acab1c 9528 struct omp_for_data *fd, gimple *inner_stmt)
1e8e9920 9529{
75a70cf9 9530 tree n, s0, e0, e, t;
79acaae1 9531 tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
93481288 9532 tree type, itype, vmain, vback, vextra;
773c5ba7 9533 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
bc7bff74 9534 basic_block trip_update_bb = NULL, cont_bb, collapse_bb = NULL, fin_bb;
93481288 9535 gimple_stmt_iterator gsi;
75a70cf9 9536 edge se;
bc7bff74 9537 bool broken_loop = region->cont == NULL;
9538 tree *counts = NULL;
9539 tree n1, n2, step;
1e8e9920 9540
fd6481cf 9541 itype = type = TREE_TYPE (fd->loop.v);
9542 if (POINTER_TYPE_P (type))
3cea8318 9543 itype = signed_type_for (type);
1e8e9920 9544
61e47ac8 9545 entry_bb = region->entry;
ac6e3339 9546 se = split_block (entry_bb, last_stmt (entry_bb));
9547 entry_bb = se->src;
9548 iter_part_bb = se->dest;
61e47ac8 9549 cont_bb = region->cont;
ac6e3339 9550 gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
bc7bff74 9551 fin_bb = BRANCH_EDGE (iter_part_bb)->dest;
9552 gcc_assert (broken_loop
9553 || fin_bb == FALLTHRU_EDGE (cont_bb)->dest);
ac6e3339 9554 seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
9555 body_bb = single_succ (seq_start_bb);
bc7bff74 9556 if (!broken_loop)
9557 {
fc1d58e3 9558 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb
9559 || single_succ (BRANCH_EDGE (cont_bb)->dest) == body_bb);
bc7bff74 9560 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
9561 trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
9562 }
61e47ac8 9563 exit_bb = region->exit;
773c5ba7 9564
773c5ba7 9565 /* Trip and adjustment setup goes in ENTRY_BB. */
93481288 9566 gsi = gsi_last_bb (entry_bb);
9567 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
773c5ba7 9568
bc7bff74 9569 if (fd->collapse > 1)
9570 {
43895be5 9571 int first_zero_iter = -1, dummy = -1;
9572 basic_block l2_dom_bb = NULL, dummy_bb = NULL;
bc7bff74 9573
9574 counts = XALLOCAVEC (tree, fd->collapse);
93481288 9575 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
bc7bff74 9576 fin_bb, first_zero_iter,
43895be5 9577 dummy_bb, dummy, l2_dom_bb);
bc7bff74 9578 t = NULL_TREE;
9579 }
9580 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
9581 t = integer_one_node;
9582 else
9583 t = fold_binary (fd->loop.cond_code, boolean_type_node,
9584 fold_convert (type, fd->loop.n1),
9585 fold_convert (type, fd->loop.n2));
9586 if (fd->collapse == 1
9587 && TYPE_UNSIGNED (type)
8e6b4515 9588 && (t == NULL_TREE || !integer_onep (t)))
9589 {
8e6b4515 9590 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
93481288 9591 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
8e6b4515 9592 true, GSI_SAME_STMT);
9593 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
93481288 9594 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
8e6b4515 9595 true, GSI_SAME_STMT);
1a91d914 9596 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
9597 NULL_TREE, NULL_TREE);
9598 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
9599 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
8e6b4515 9600 expand_omp_regimplify_p, NULL, NULL)
1a91d914 9601 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
8e6b4515 9602 expand_omp_regimplify_p, NULL, NULL))
9603 {
1a91d914 9604 gsi = gsi_for_stmt (cond_stmt);
9605 gimple_regimplify_operands (cond_stmt, &gsi);
8e6b4515 9606 }
1a91d914 9607 se = split_block (entry_bb, cond_stmt);
8e6b4515 9608 se->flags = EDGE_TRUE_VALUE;
9609 entry_bb = se->dest;
9610 se->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
9611 se = make_edge (se->src, fin_bb, EDGE_FALSE_VALUE);
9612 se->probability = REG_BR_PROB_BASE / 2000 - 1;
9613 if (gimple_in_ssa_p (cfun))
9614 {
264aa959 9615 int dest_idx = find_edge (iter_part_bb, fin_bb)->dest_idx;
1a91d914 9616 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
9617 !gsi_end_p (gpi); gsi_next (&gpi))
8e6b4515 9618 {
1a91d914 9619 gphi *phi = gpi.phi ();
8e6b4515 9620 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
9621 se, UNKNOWN_LOCATION);
9622 }
9623 }
93481288 9624 gsi = gsi_last_bb (entry_bb);
8e6b4515 9625 }
9626
ca4c3545 9627 switch (gimple_omp_for_kind (fd->for_stmt))
9628 {
9629 case GF_OMP_FOR_KIND_FOR:
9630 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
9631 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
9632 break;
9633 case GF_OMP_FOR_KIND_DISTRIBUTE:
9634 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
9635 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
9636 break;
ca4c3545 9637 default:
9638 gcc_unreachable ();
9639 }
9640 nthreads = build_call_expr (nthreads, 0);
9641 nthreads = fold_convert (itype, nthreads);
9642 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
75a70cf9 9643 true, GSI_SAME_STMT);
ca4c3545 9644 threadid = build_call_expr (threadid, 0);
9645 threadid = fold_convert (itype, threadid);
9646 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
75a70cf9 9647 true, GSI_SAME_STMT);
79acaae1 9648
bc7bff74 9649 n1 = fd->loop.n1;
9650 n2 = fd->loop.n2;
9651 step = fd->loop.step;
9652 if (gimple_omp_for_combined_into_p (fd->for_stmt))
9653 {
9654 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
9655 OMP_CLAUSE__LOOPTEMP_);
9656 gcc_assert (innerc);
9657 n1 = OMP_CLAUSE_DECL (innerc);
9658 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9659 OMP_CLAUSE__LOOPTEMP_);
9660 gcc_assert (innerc);
9661 n2 = OMP_CLAUSE_DECL (innerc);
9662 }
93481288 9663 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
bc7bff74 9664 true, NULL_TREE, true, GSI_SAME_STMT);
93481288 9665 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
bc7bff74 9666 true, NULL_TREE, true, GSI_SAME_STMT);
93481288 9667 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
bc7bff74 9668 true, NULL_TREE, true, GSI_SAME_STMT);
43895be5 9669 tree chunk_size = fold_convert (itype, fd->chunk_size);
9670 chunk_size = omp_adjust_chunk_size (chunk_size, fd->simd_schedule);
9671 chunk_size
9672 = force_gimple_operand_gsi (&gsi, chunk_size, true, NULL_TREE, true,
9673 GSI_SAME_STMT);
fd6481cf 9674
9675 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
bc7bff74 9676 t = fold_build2 (PLUS_EXPR, itype, step, t);
9677 t = fold_build2 (PLUS_EXPR, itype, t, n2);
9678 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
fd6481cf 9679 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
9680 t = fold_build2 (TRUNC_DIV_EXPR, itype,
9681 fold_build1 (NEGATE_EXPR, itype, t),
bc7bff74 9682 fold_build1 (NEGATE_EXPR, itype, step));
fd6481cf 9683 else
bc7bff74 9684 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
fd6481cf 9685 t = fold_convert (itype, t);
93481288 9686 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
75a70cf9 9687 true, GSI_SAME_STMT);
79acaae1 9688
083152fb 9689 trip_var = create_tmp_reg (itype, ".trip");
79acaae1 9690 if (gimple_in_ssa_p (cfun))
9691 {
f9e245b2 9692 trip_init = make_ssa_name (trip_var);
9693 trip_main = make_ssa_name (trip_var);
9694 trip_back = make_ssa_name (trip_var);
79acaae1 9695 }
1e8e9920 9696 else
79acaae1 9697 {
9698 trip_init = trip_var;
9699 trip_main = trip_var;
9700 trip_back = trip_var;
9701 }
1e8e9920 9702
1a91d914 9703 gassign *assign_stmt
9704 = gimple_build_assign (trip_init, build_int_cst (itype, 0));
9705 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
773c5ba7 9706
43895be5 9707 t = fold_build2 (MULT_EXPR, itype, threadid, chunk_size);
bc7bff74 9708 t = fold_build2 (MULT_EXPR, itype, t, step);
fd6481cf 9709 if (POINTER_TYPE_P (type))
bc7bff74 9710 t = fold_build_pointer_plus (n1, t);
fd6481cf 9711 else
bc7bff74 9712 t = fold_build2 (PLUS_EXPR, type, t, n1);
93481288 9713 vextra = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9714 true, GSI_SAME_STMT);
79acaae1 9715
75a70cf9 9716 /* Remove the GIMPLE_OMP_FOR. */
93481288 9717 gsi_remove (&gsi, true);
773c5ba7 9718
43895be5 9719 gimple_stmt_iterator gsif = gsi;
9720
773c5ba7 9721 /* Iteration space partitioning goes in ITER_PART_BB. */
93481288 9722 gsi = gsi_last_bb (iter_part_bb);
1e8e9920 9723
fd6481cf 9724 t = fold_build2 (MULT_EXPR, itype, trip_main, nthreads);
9725 t = fold_build2 (PLUS_EXPR, itype, t, threadid);
43895be5 9726 t = fold_build2 (MULT_EXPR, itype, t, chunk_size);
93481288 9727 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
75a70cf9 9728 false, GSI_CONTINUE_LINKING);
1e8e9920 9729
43895be5 9730 t = fold_build2 (PLUS_EXPR, itype, s0, chunk_size);
fd6481cf 9731 t = fold_build2 (MIN_EXPR, itype, t, n);
93481288 9732 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
75a70cf9 9733 false, GSI_CONTINUE_LINKING);
1e8e9920 9734
9735 t = build2 (LT_EXPR, boolean_type_node, s0, n);
93481288 9736 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_CONTINUE_LINKING);
773c5ba7 9737
9738 /* Setup code for sequential iteration goes in SEQ_START_BB. */
93481288 9739 gsi = gsi_start_bb (seq_start_bb);
1e8e9920 9740
bc7bff74 9741 tree startvar = fd->loop.v;
9742 tree endvar = NULL_TREE;
9743
9744 if (gimple_omp_for_combined_p (fd->for_stmt))
9745 {
9746 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
9747 ? gimple_omp_parallel_clauses (inner_stmt)
9748 : gimple_omp_for_clauses (inner_stmt);
9749 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
9750 gcc_assert (innerc);
9751 startvar = OMP_CLAUSE_DECL (innerc);
9752 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9753 OMP_CLAUSE__LOOPTEMP_);
9754 gcc_assert (innerc);
9755 endvar = OMP_CLAUSE_DECL (innerc);
9561765e 9756 if (fd->collapse > 1 && TREE_CODE (fd->loop.n2) != INTEGER_CST
9757 && gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
9758 {
9759 int i;
9760 for (i = 1; i < fd->collapse; i++)
9761 {
9762 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9763 OMP_CLAUSE__LOOPTEMP_);
9764 gcc_assert (innerc);
9765 }
9766 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9767 OMP_CLAUSE__LOOPTEMP_);
9768 if (innerc)
9769 {
9770 /* If needed (distribute parallel for with lastprivate),
9771 propagate down the total number of iterations. */
9772 tree t = fold_convert (TREE_TYPE (OMP_CLAUSE_DECL (innerc)),
9773 fd->loop.n2);
9774 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, false,
9775 GSI_CONTINUE_LINKING);
9776 assign_stmt = gimple_build_assign (OMP_CLAUSE_DECL (innerc), t);
9777 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9778 }
9779 }
bc7bff74 9780 }
9781
fd6481cf 9782 t = fold_convert (itype, s0);
bc7bff74 9783 t = fold_build2 (MULT_EXPR, itype, t, step);
fd6481cf 9784 if (POINTER_TYPE_P (type))
bc7bff74 9785 t = fold_build_pointer_plus (n1, t);
fd6481cf 9786 else
bc7bff74 9787 t = fold_build2 (PLUS_EXPR, type, t, n1);
9788 t = fold_convert (TREE_TYPE (startvar), t);
93481288 9789 t = force_gimple_operand_gsi (&gsi, t,
bc7bff74 9790 DECL_P (startvar)
9791 && TREE_ADDRESSABLE (startvar),
4abecb72 9792 NULL_TREE, false, GSI_CONTINUE_LINKING);
1a91d914 9793 assign_stmt = gimple_build_assign (startvar, t);
9794 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
1e8e9920 9795
fd6481cf 9796 t = fold_convert (itype, e0);
bc7bff74 9797 t = fold_build2 (MULT_EXPR, itype, t, step);
fd6481cf 9798 if (POINTER_TYPE_P (type))
bc7bff74 9799 t = fold_build_pointer_plus (n1, t);
fd6481cf 9800 else
bc7bff74 9801 t = fold_build2 (PLUS_EXPR, type, t, n1);
9802 t = fold_convert (TREE_TYPE (startvar), t);
93481288 9803 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
75a70cf9 9804 false, GSI_CONTINUE_LINKING);
bc7bff74 9805 if (endvar)
9806 {
1a91d914 9807 assign_stmt = gimple_build_assign (endvar, e);
9808 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
d44f2f7c 9809 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
1a91d914 9810 assign_stmt = gimple_build_assign (fd->loop.v, e);
d44f2f7c 9811 else
e9cf809e 9812 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
1a91d914 9813 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
bc7bff74 9814 }
43895be5 9815 /* Handle linear clause adjustments. */
9816 tree itercnt = NULL_TREE, itercntbias = NULL_TREE;
9817 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_FOR)
9818 for (tree c = gimple_omp_for_clauses (fd->for_stmt);
9819 c; c = OMP_CLAUSE_CHAIN (c))
9820 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
9821 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
9822 {
9823 tree d = OMP_CLAUSE_DECL (c);
9824 bool is_ref = is_reference (d);
9825 tree t = d, a, dest;
9826 if (is_ref)
9827 t = build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c), t);
9828 tree type = TREE_TYPE (t);
9829 if (POINTER_TYPE_P (type))
9830 type = sizetype;
9831 dest = unshare_expr (t);
9832 tree v = create_tmp_var (TREE_TYPE (t), NULL);
9833 expand_omp_build_assign (&gsif, v, t);
9834 if (itercnt == NULL_TREE)
9835 {
9836 if (gimple_omp_for_combined_into_p (fd->for_stmt))
9837 {
9838 itercntbias
9839 = fold_build2 (MINUS_EXPR, itype, fold_convert (itype, n1),
9840 fold_convert (itype, fd->loop.n1));
9841 itercntbias = fold_build2 (EXACT_DIV_EXPR, itype,
9842 itercntbias, step);
9843 itercntbias
9844 = force_gimple_operand_gsi (&gsif, itercntbias, true,
9845 NULL_TREE, true,
9846 GSI_SAME_STMT);
9847 itercnt = fold_build2 (PLUS_EXPR, itype, itercntbias, s0);
9848 itercnt = force_gimple_operand_gsi (&gsi, itercnt, true,
9849 NULL_TREE, false,
9850 GSI_CONTINUE_LINKING);
9851 }
9852 else
9853 itercnt = s0;
9854 }
9855 a = fold_build2 (MULT_EXPR, type,
9856 fold_convert (type, itercnt),
9857 fold_convert (type, OMP_CLAUSE_LINEAR_STEP (c)));
9858 t = fold_build2 (type == TREE_TYPE (t) ? PLUS_EXPR
9859 : POINTER_PLUS_EXPR, TREE_TYPE (t), v, a);
9860 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9861 false, GSI_CONTINUE_LINKING);
9862 assign_stmt = gimple_build_assign (dest, t);
9863 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9864 }
bc7bff74 9865 if (fd->collapse > 1)
93481288 9866 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
bc7bff74 9867
9868 if (!broken_loop)
9869 {
9870 /* The code controlling the sequential loop goes in CONT_BB,
9871 replacing the GIMPLE_OMP_CONTINUE. */
93481288 9872 gsi = gsi_last_bb (cont_bb);
1a91d914 9873 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
9874 vmain = gimple_omp_continue_control_use (cont_stmt);
9875 vback = gimple_omp_continue_control_def (cont_stmt);
1e8e9920 9876
bc7bff74 9877 if (!gimple_omp_for_combined_p (fd->for_stmt))
9878 {
9879 if (POINTER_TYPE_P (type))
93481288 9880 t = fold_build_pointer_plus (vmain, step);
bc7bff74 9881 else
93481288 9882 t = fold_build2 (PLUS_EXPR, type, vmain, step);
9883 if (DECL_P (vback) && TREE_ADDRESSABLE (vback))
9884 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
bc7bff74 9885 true, GSI_SAME_STMT);
1a91d914 9886 assign_stmt = gimple_build_assign (vback, t);
9887 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
79acaae1 9888
345f9789 9889 if (tree_int_cst_equal (fd->chunk_size, integer_one_node))
9890 t = build2 (EQ_EXPR, boolean_type_node,
9891 build_int_cst (itype, 0),
9892 build_int_cst (itype, 1));
9893 else
9894 t = build2 (fd->loop.cond_code, boolean_type_node,
9895 DECL_P (vback) && TREE_ADDRESSABLE (vback)
9896 ? t : vback, e);
93481288 9897 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
bc7bff74 9898 }
79acaae1 9899
bc7bff74 9900 /* Remove GIMPLE_OMP_CONTINUE. */
93481288 9901 gsi_remove (&gsi, true);
48e1416a 9902
bc7bff74 9903 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
9904 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
773c5ba7 9905
bc7bff74 9906 /* Trip update code goes into TRIP_UPDATE_BB. */
93481288 9907 gsi = gsi_start_bb (trip_update_bb);
1e8e9920 9908
bc7bff74 9909 t = build_int_cst (itype, 1);
9910 t = build2 (PLUS_EXPR, itype, trip_main, t);
1a91d914 9911 assign_stmt = gimple_build_assign (trip_back, t);
9912 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
bc7bff74 9913 }
1e8e9920 9914
75a70cf9 9915 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
93481288 9916 gsi = gsi_last_bb (exit_bb);
9917 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
bc7bff74 9918 {
93481288 9919 t = gimple_omp_return_lhs (gsi_stmt (gsi));
a8e785ba 9920 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
bc7bff74 9921 }
93481288 9922 gsi_remove (&gsi, true);
1e8e9920 9923
773c5ba7 9924 /* Connect the new blocks. */
ac6e3339 9925 find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
9926 find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
79acaae1 9927
bc7bff74 9928 if (!broken_loop)
9929 {
9930 se = find_edge (cont_bb, body_bb);
fc1d58e3 9931 if (se == NULL)
9932 {
9933 se = BRANCH_EDGE (cont_bb);
9934 gcc_assert (single_succ (se->dest) == body_bb);
9935 }
bc7bff74 9936 if (gimple_omp_for_combined_p (fd->for_stmt))
9937 {
9938 remove_edge (se);
9939 se = NULL;
9940 }
9941 else if (fd->collapse > 1)
9942 {
9943 remove_edge (se);
9944 se = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
9945 }
9946 else
9947 se->flags = EDGE_TRUE_VALUE;
9948 find_edge (cont_bb, trip_update_bb)->flags
9949 = se ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
79acaae1 9950
bc7bff74 9951 redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb);
9952 }
79acaae1 9953
9954 if (gimple_in_ssa_p (cfun))
9955 {
1a91d914 9956 gphi_iterator psi;
9957 gphi *phi;
75a70cf9 9958 edge re, ene;
75a70cf9 9959 edge_var_map *vm;
9960 size_t i;
9961
bc7bff74 9962 gcc_assert (fd->collapse == 1 && !broken_loop);
9963
79acaae1 9964 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
9965 remove arguments of the phi nodes in fin_bb. We need to create
9966 appropriate phi nodes in iter_part_bb instead. */
264aa959 9967 se = find_edge (iter_part_bb, fin_bb);
79acaae1 9968 re = single_succ_edge (trip_update_bb);
06ecf488 9969 vec<edge_var_map> *head = redirect_edge_var_map_vector (re);
79acaae1 9970 ene = single_succ_edge (entry_bb);
9971
75a70cf9 9972 psi = gsi_start_phis (fin_bb);
f1f41a6c 9973 for (i = 0; !gsi_end_p (psi) && head->iterate (i, &vm);
75a70cf9 9974 gsi_next (&psi), ++i)
79acaae1 9975 {
1a91d914 9976 gphi *nphi;
efbcb6de 9977 source_location locus;
75a70cf9 9978
1a91d914 9979 phi = psi.phi ();
75a70cf9 9980 t = gimple_phi_result (phi);
9981 gcc_assert (t == redirect_edge_var_map_result (vm));
264aa959 9982
9983 if (!single_pred_p (fin_bb))
9984 t = copy_ssa_name (t, phi);
9985
79acaae1 9986 nphi = create_phi_node (t, iter_part_bb);
79acaae1 9987
9988 t = PHI_ARG_DEF_FROM_EDGE (phi, se);
efbcb6de 9989 locus = gimple_phi_arg_location_from_edge (phi, se);
9990
fd6481cf 9991 /* A special case -- fd->loop.v is not yet computed in
93481288 9992 iter_part_bb, we need to use vextra instead. */
fd6481cf 9993 if (t == fd->loop.v)
93481288 9994 t = vextra;
60d535d2 9995 add_phi_arg (nphi, t, ene, locus);
efbcb6de 9996 locus = redirect_edge_var_map_location (vm);
281001a9 9997 tree back_arg = redirect_edge_var_map_def (vm);
9998 add_phi_arg (nphi, back_arg, re, locus);
9999 edge ce = find_edge (cont_bb, body_bb);
10000 if (ce == NULL)
10001 {
10002 ce = BRANCH_EDGE (cont_bb);
10003 gcc_assert (single_succ (ce->dest) == body_bb);
10004 ce = single_succ_edge (ce->dest);
10005 }
10006 gphi *inner_loop_phi = find_phi_with_arg_on_edge (back_arg, ce);
10007 gcc_assert (inner_loop_phi != NULL);
10008 add_phi_arg (inner_loop_phi, gimple_phi_result (nphi),
10009 find_edge (seq_start_bb, body_bb), locus);
264aa959 10010
10011 if (!single_pred_p (fin_bb))
10012 add_phi_arg (phi, gimple_phi_result (nphi), se, locus);
75a70cf9 10013 }
4d556e29 10014 gcc_assert (gsi_end_p (psi) && (head == NULL || i == head->length ()));
75a70cf9 10015 redirect_edge_var_map_clear (re);
264aa959 10016 if (single_pred_p (fin_bb))
10017 while (1)
10018 {
10019 psi = gsi_start_phis (fin_bb);
10020 if (gsi_end_p (psi))
10021 break;
10022 remove_phi_node (&psi, false);
10023 }
79acaae1 10024
10025 /* Make phi node for trip. */
10026 phi = create_phi_node (trip_main, iter_part_bb);
efbcb6de 10027 add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb),
60d535d2 10028 UNKNOWN_LOCATION);
efbcb6de 10029 add_phi_arg (phi, trip_init, single_succ_edge (entry_bb),
60d535d2 10030 UNKNOWN_LOCATION);
79acaae1 10031 }
10032
bc7bff74 10033 if (!broken_loop)
10034 set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
79acaae1 10035 set_immediate_dominator (CDI_DOMINATORS, iter_part_bb,
10036 recompute_dominator (CDI_DOMINATORS, iter_part_bb));
10037 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
10038 recompute_dominator (CDI_DOMINATORS, fin_bb));
10039 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb,
10040 recompute_dominator (CDI_DOMINATORS, seq_start_bb));
10041 set_immediate_dominator (CDI_DOMINATORS, body_bb,
10042 recompute_dominator (CDI_DOMINATORS, body_bb));
04c2922b 10043
bc7bff74 10044 if (!broken_loop)
10045 {
fc1d58e3 10046 struct loop *loop = body_bb->loop_father;
bc7bff74 10047 struct loop *trip_loop = alloc_loop ();
10048 trip_loop->header = iter_part_bb;
10049 trip_loop->latch = trip_update_bb;
10050 add_loop (trip_loop, iter_part_bb->loop_father);
04c2922b 10051
fc1d58e3 10052 if (loop != entry_bb->loop_father)
10053 {
10054 gcc_assert (loop->header == body_bb);
10055 gcc_assert (loop->latch == region->cont
10056 || single_pred (loop->latch) == region->cont);
10057 trip_loop->inner = loop;
10058 return;
10059 }
10060
bc7bff74 10061 if (!gimple_omp_for_combined_p (fd->for_stmt))
10062 {
fc1d58e3 10063 loop = alloc_loop ();
bc7bff74 10064 loop->header = body_bb;
33ee4d72 10065 if (collapse_bb == NULL)
10066 loop->latch = cont_bb;
bc7bff74 10067 add_loop (loop, trip_loop);
10068 }
10069 }
1e8e9920 10070}
10071
40750995 10072/* A subroutine of expand_omp_for. Generate code for _Cilk_for loop.
10073 Given parameters:
10074 for (V = N1; V cond N2; V += STEP) BODY;
10075
10076 where COND is "<" or ">" or "!=", we generate pseudocode
10077
10078 for (ind_var = low; ind_var < high; ind_var++)
10079 {
10080 V = n1 + (ind_var * STEP)
10081
10082 <BODY>
10083 }
10084
10085 In the above pseudocode, low and high are function parameters of the
10086 child function. In the function below, we are inserting a temp.
10087 variable that will be making a call to two OMP functions that will not be
10088 found in the body of _Cilk_for (since OMP_FOR cannot be mixed
10089 with _Cilk_for). These functions are replaced with low and high
10090 by the function that handles taskreg. */
10091
10092
10093static void
10094expand_cilk_for (struct omp_region *region, struct omp_for_data *fd)
10095{
10096 bool broken_loop = region->cont == NULL;
10097 basic_block entry_bb = region->entry;
10098 basic_block cont_bb = region->cont;
10099
10100 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
10101 gcc_assert (broken_loop
10102 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
10103 basic_block l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
10104 basic_block l1_bb, l2_bb;
10105
10106 if (!broken_loop)
10107 {
10108 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
10109 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
10110 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
10111 l2_bb = BRANCH_EDGE (entry_bb)->dest;
10112 }
10113 else
10114 {
10115 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
10116 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
10117 l2_bb = single_succ (l1_bb);
10118 }
10119 basic_block exit_bb = region->exit;
10120 basic_block l2_dom_bb = NULL;
10121
10122 gimple_stmt_iterator gsi = gsi_last_bb (entry_bb);
10123
10124 /* Below statements until the "tree high_val = ..." are pseudo statements
10125 used to pass information to be used by expand_omp_taskreg.
10126 low_val and high_val will be replaced by the __low and __high
10127 parameter from the child function.
10128
10129 The call_exprs part is a place-holder, it is mainly used
10130 to distinctly identify to the top-level part that this is
10131 where we should put low and high (reasoning given in header
10132 comment). */
10133
10134 tree child_fndecl
1a91d914 10135 = gimple_omp_parallel_child_fn (
10136 as_a <gomp_parallel *> (last_stmt (region->outer->entry)));
40750995 10137 tree t, low_val = NULL_TREE, high_val = NULL_TREE;
10138 for (t = DECL_ARGUMENTS (child_fndecl); t; t = TREE_CHAIN (t))
10139 {
10140 if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__high"))
10141 high_val = t;
10142 else if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__low"))
10143 low_val = t;
10144 }
10145 gcc_assert (low_val && high_val);
10146
10147 tree type = TREE_TYPE (low_val);
10148 tree ind_var = create_tmp_reg (type, "__cilk_ind_var");
10149 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
10150
10151 /* Not needed in SSA form right now. */
10152 gcc_assert (!gimple_in_ssa_p (cfun));
10153 if (l2_dom_bb == NULL)
10154 l2_dom_bb = l1_bb;
10155
10156 tree n1 = low_val;
10157 tree n2 = high_val;
10158
42acab1c 10159 gimple *stmt = gimple_build_assign (ind_var, n1);
40750995 10160
10161 /* Replace the GIMPLE_OMP_FOR statement. */
10162 gsi_replace (&gsi, stmt, true);
10163
10164 if (!broken_loop)
10165 {
10166 /* Code to control the increment goes in the CONT_BB. */
10167 gsi = gsi_last_bb (cont_bb);
10168 stmt = gsi_stmt (gsi);
10169 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
e9cf809e 10170 stmt = gimple_build_assign (ind_var, PLUS_EXPR, ind_var,
10171 build_one_cst (type));
40750995 10172
10173 /* Replace GIMPLE_OMP_CONTINUE. */
10174 gsi_replace (&gsi, stmt, true);
10175 }
10176
10177 /* Emit the condition in L1_BB. */
10178 gsi = gsi_after_labels (l1_bb);
10179 t = fold_build2 (MULT_EXPR, TREE_TYPE (fd->loop.step),
10180 fold_convert (TREE_TYPE (fd->loop.step), ind_var),
10181 fd->loop.step);
10182 if (POINTER_TYPE_P (TREE_TYPE (fd->loop.n1)))
10183 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (fd->loop.n1),
10184 fd->loop.n1, fold_convert (sizetype, t));
10185 else
10186 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loop.n1),
10187 fd->loop.n1, fold_convert (TREE_TYPE (fd->loop.n1), t));
10188 t = fold_convert (TREE_TYPE (fd->loop.v), t);
10189 expand_omp_build_assign (&gsi, fd->loop.v, t);
10190
10191 /* The condition is always '<' since the runtime will fill in the low
10192 and high values. */
10193 stmt = gimple_build_cond (LT_EXPR, ind_var, n2, NULL_TREE, NULL_TREE);
10194 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
10195
10196 /* Remove GIMPLE_OMP_RETURN. */
10197 gsi = gsi_last_bb (exit_bb);
10198 gsi_remove (&gsi, true);
10199
10200 /* Connect the new blocks. */
10201 remove_edge (FALLTHRU_EDGE (entry_bb));
10202
10203 edge e, ne;
10204 if (!broken_loop)
10205 {
10206 remove_edge (BRANCH_EDGE (entry_bb));
10207 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
10208
10209 e = BRANCH_EDGE (l1_bb);
10210 ne = FALLTHRU_EDGE (l1_bb);
10211 e->flags = EDGE_TRUE_VALUE;
10212 }
10213 else
10214 {
10215 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
10216
10217 ne = single_succ_edge (l1_bb);
10218 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
10219
10220 }
10221 ne->flags = EDGE_FALSE_VALUE;
10222 e->probability = REG_BR_PROB_BASE * 7 / 8;
10223 ne->probability = REG_BR_PROB_BASE / 8;
10224
10225 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
10226 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
10227 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
10228
10229 if (!broken_loop)
10230 {
10231 struct loop *loop = alloc_loop ();
10232 loop->header = l1_bb;
10233 loop->latch = cont_bb;
10234 add_loop (loop, l1_bb->loop_father);
10235 loop->safelen = INT_MAX;
10236 }
10237
10238 /* Pick the correct library function based on the precision of the
10239 induction variable type. */
10240 tree lib_fun = NULL_TREE;
10241 if (TYPE_PRECISION (type) == 32)
10242 lib_fun = cilk_for_32_fndecl;
10243 else if (TYPE_PRECISION (type) == 64)
10244 lib_fun = cilk_for_64_fndecl;
10245 else
10246 gcc_unreachable ();
10247
10248 gcc_assert (fd->sched_kind == OMP_CLAUSE_SCHEDULE_CILKFOR);
10249
10250 /* WS_ARGS contains the library function flavor to call:
10251 __libcilkrts_cilk_for_64 or __libcilkrts_cilk_for_32), and the
10252 user-defined grain value. If the user does not define one, then zero
10253 is passed in by the parser. */
10254 vec_alloc (region->ws_args, 2);
10255 region->ws_args->quick_push (lib_fun);
10256 region->ws_args->quick_push (fd->chunk_size);
10257}
bc7bff74 10258
3d483a94 10259/* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
10260 loop. Given parameters:
10261
10262 for (V = N1; V cond N2; V += STEP) BODY;
10263
10264 where COND is "<" or ">", we generate pseudocode
10265
10266 V = N1;
10267 goto L1;
10268 L0:
10269 BODY;
10270 V += STEP;
10271 L1:
10272 if (V cond N2) goto L0; else goto L2;
10273 L2:
10274
10275 For collapsed loops, given parameters:
10276 collapse(3)
10277 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
10278 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
10279 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
10280 BODY;
10281
10282 we generate pseudocode
10283
10284 if (cond3 is <)
10285 adj = STEP3 - 1;
10286 else
10287 adj = STEP3 + 1;
10288 count3 = (adj + N32 - N31) / STEP3;
10289 if (cond2 is <)
10290 adj = STEP2 - 1;
10291 else
10292 adj = STEP2 + 1;
10293 count2 = (adj + N22 - N21) / STEP2;
10294 if (cond1 is <)
10295 adj = STEP1 - 1;
10296 else
10297 adj = STEP1 + 1;
10298 count1 = (adj + N12 - N11) / STEP1;
10299 count = count1 * count2 * count3;
10300 V = 0;
10301 V1 = N11;
10302 V2 = N21;
10303 V3 = N31;
10304 goto L1;
10305 L0:
10306 BODY;
10307 V += 1;
10308 V3 += STEP3;
10309 V2 += (V3 cond3 N32) ? 0 : STEP2;
10310 V3 = (V3 cond3 N32) ? V3 : N31;
10311 V1 += (V2 cond2 N22) ? 0 : STEP1;
10312 V2 = (V2 cond2 N22) ? V2 : N21;
10313 L1:
10314 if (V < count) goto L0; else goto L2;
10315 L2:
10316
10317 */
10318
10319static void
10320expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
10321{
10322 tree type, t;
10323 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, l2_bb, l2_dom_bb;
10324 gimple_stmt_iterator gsi;
42acab1c 10325 gimple *stmt;
1a91d914 10326 gcond *cond_stmt;
3d483a94 10327 bool broken_loop = region->cont == NULL;
10328 edge e, ne;
10329 tree *counts = NULL;
10330 int i;
10331 tree safelen = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
10332 OMP_CLAUSE_SAFELEN);
10333 tree simduid = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
10334 OMP_CLAUSE__SIMDUID_);
bc7bff74 10335 tree n1, n2;
3d483a94 10336
10337 type = TREE_TYPE (fd->loop.v);
10338 entry_bb = region->entry;
10339 cont_bb = region->cont;
10340 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
10341 gcc_assert (broken_loop
10342 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
10343 l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
10344 if (!broken_loop)
10345 {
10346 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
10347 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
10348 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
10349 l2_bb = BRANCH_EDGE (entry_bb)->dest;
10350 }
10351 else
10352 {
10353 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
10354 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
10355 l2_bb = single_succ (l1_bb);
10356 }
10357 exit_bb = region->exit;
10358 l2_dom_bb = NULL;
10359
10360 gsi = gsi_last_bb (entry_bb);
10361
10362 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
10363 /* Not needed in SSA form right now. */
10364 gcc_assert (!gimple_in_ssa_p (cfun));
10365 if (fd->collapse > 1)
10366 {
43895be5 10367 int first_zero_iter = -1, dummy = -1;
10368 basic_block zero_iter_bb = l2_bb, dummy_bb = NULL;
3d483a94 10369
10370 counts = XALLOCAVEC (tree, fd->collapse);
10371 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
10372 zero_iter_bb, first_zero_iter,
43895be5 10373 dummy_bb, dummy, l2_dom_bb);
3d483a94 10374 }
10375 if (l2_dom_bb == NULL)
10376 l2_dom_bb = l1_bb;
10377
bc7bff74 10378 n1 = fd->loop.n1;
3d483a94 10379 n2 = fd->loop.n2;
bc7bff74 10380 if (gimple_omp_for_combined_into_p (fd->for_stmt))
10381 {
10382 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
10383 OMP_CLAUSE__LOOPTEMP_);
10384 gcc_assert (innerc);
10385 n1 = OMP_CLAUSE_DECL (innerc);
10386 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
10387 OMP_CLAUSE__LOOPTEMP_);
10388 gcc_assert (innerc);
10389 n2 = OMP_CLAUSE_DECL (innerc);
10390 expand_omp_build_assign (&gsi, fd->loop.v,
10391 fold_convert (type, n1));
10392 if (fd->collapse > 1)
10393 {
10394 gsi_prev (&gsi);
10395 expand_omp_for_init_vars (fd, &gsi, counts, NULL, n1);
10396 gsi_next (&gsi);
10397 }
10398 }
3d483a94 10399 else
10400 {
10401 expand_omp_build_assign (&gsi, fd->loop.v,
10402 fold_convert (type, fd->loop.n1));
10403 if (fd->collapse > 1)
10404 for (i = 0; i < fd->collapse; i++)
10405 {
10406 tree itype = TREE_TYPE (fd->loops[i].v);
10407 if (POINTER_TYPE_P (itype))
10408 itype = signed_type_for (itype);
10409 t = fold_convert (TREE_TYPE (fd->loops[i].v), fd->loops[i].n1);
10410 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
10411 }
10412 }
10413
10414 /* Remove the GIMPLE_OMP_FOR statement. */
10415 gsi_remove (&gsi, true);
10416
10417 if (!broken_loop)
10418 {
10419 /* Code to control the increment goes in the CONT_BB. */
10420 gsi = gsi_last_bb (cont_bb);
10421 stmt = gsi_stmt (gsi);
10422 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
10423
10424 if (POINTER_TYPE_P (type))
10425 t = fold_build_pointer_plus (fd->loop.v, fd->loop.step);
10426 else
10427 t = fold_build2 (PLUS_EXPR, type, fd->loop.v, fd->loop.step);
10428 expand_omp_build_assign (&gsi, fd->loop.v, t);
10429
10430 if (fd->collapse > 1)
10431 {
10432 i = fd->collapse - 1;
10433 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
10434 {
10435 t = fold_convert (sizetype, fd->loops[i].step);
10436 t = fold_build_pointer_plus (fd->loops[i].v, t);
10437 }
10438 else
10439 {
10440 t = fold_convert (TREE_TYPE (fd->loops[i].v),
10441 fd->loops[i].step);
10442 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
10443 fd->loops[i].v, t);
10444 }
10445 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
10446
10447 for (i = fd->collapse - 1; i > 0; i--)
10448 {
10449 tree itype = TREE_TYPE (fd->loops[i].v);
10450 tree itype2 = TREE_TYPE (fd->loops[i - 1].v);
10451 if (POINTER_TYPE_P (itype2))
10452 itype2 = signed_type_for (itype2);
10453 t = build3 (COND_EXPR, itype2,
10454 build2 (fd->loops[i].cond_code, boolean_type_node,
10455 fd->loops[i].v,
10456 fold_convert (itype, fd->loops[i].n2)),
10457 build_int_cst (itype2, 0),
10458 fold_convert (itype2, fd->loops[i - 1].step));
10459 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i - 1].v)))
10460 t = fold_build_pointer_plus (fd->loops[i - 1].v, t);
10461 else
10462 t = fold_build2 (PLUS_EXPR, itype2, fd->loops[i - 1].v, t);
10463 expand_omp_build_assign (&gsi, fd->loops[i - 1].v, t);
10464
10465 t = build3 (COND_EXPR, itype,
10466 build2 (fd->loops[i].cond_code, boolean_type_node,
10467 fd->loops[i].v,
10468 fold_convert (itype, fd->loops[i].n2)),
10469 fd->loops[i].v,
10470 fold_convert (itype, fd->loops[i].n1));
10471 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
10472 }
10473 }
10474
10475 /* Remove GIMPLE_OMP_CONTINUE. */
10476 gsi_remove (&gsi, true);
10477 }
10478
10479 /* Emit the condition in L1_BB. */
10480 gsi = gsi_start_bb (l1_bb);
10481
10482 t = fold_convert (type, n2);
10483 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
10484 false, GSI_CONTINUE_LINKING);
43895be5 10485 tree v = fd->loop.v;
10486 if (DECL_P (v) && TREE_ADDRESSABLE (v))
10487 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
10488 false, GSI_CONTINUE_LINKING);
10489 t = build2 (fd->loop.cond_code, boolean_type_node, v, t);
1a91d914 10490 cond_stmt = gimple_build_cond_empty (t);
10491 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
10492 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt), expand_omp_regimplify_p,
3d483a94 10493 NULL, NULL)
1a91d914 10494 || walk_tree (gimple_cond_rhs_ptr (cond_stmt), expand_omp_regimplify_p,
3d483a94 10495 NULL, NULL))
10496 {
1a91d914 10497 gsi = gsi_for_stmt (cond_stmt);
10498 gimple_regimplify_operands (cond_stmt, &gsi);
3d483a94 10499 }
10500
10501 /* Remove GIMPLE_OMP_RETURN. */
10502 gsi = gsi_last_bb (exit_bb);
10503 gsi_remove (&gsi, true);
10504
10505 /* Connect the new blocks. */
10506 remove_edge (FALLTHRU_EDGE (entry_bb));
10507
10508 if (!broken_loop)
10509 {
10510 remove_edge (BRANCH_EDGE (entry_bb));
10511 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
10512
10513 e = BRANCH_EDGE (l1_bb);
10514 ne = FALLTHRU_EDGE (l1_bb);
10515 e->flags = EDGE_TRUE_VALUE;
10516 }
10517 else
10518 {
10519 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
10520
10521 ne = single_succ_edge (l1_bb);
10522 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
10523
10524 }
10525 ne->flags = EDGE_FALSE_VALUE;
10526 e->probability = REG_BR_PROB_BASE * 7 / 8;
10527 ne->probability = REG_BR_PROB_BASE / 8;
10528
10529 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
10530 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
10531 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
10532
10533 if (!broken_loop)
10534 {
10535 struct loop *loop = alloc_loop ();
10536 loop->header = l1_bb;
33ee4d72 10537 loop->latch = cont_bb;
3d483a94 10538 add_loop (loop, l1_bb->loop_father);
10539 if (safelen == NULL_TREE)
10540 loop->safelen = INT_MAX;
10541 else
10542 {
10543 safelen = OMP_CLAUSE_SAFELEN_EXPR (safelen);
c3f3b68d 10544 if (TREE_CODE (safelen) != INTEGER_CST)
10545 loop->safelen = 0;
10546 else if (!tree_fits_uhwi_p (safelen)
10547 || tree_to_uhwi (safelen) > INT_MAX)
3d483a94 10548 loop->safelen = INT_MAX;
10549 else
d85a2013 10550 loop->safelen = tree_to_uhwi (safelen);
3d483a94 10551 if (loop->safelen == 1)
10552 loop->safelen = 0;
10553 }
10554 if (simduid)
10555 {
43895be5 10556 loop->simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
10557 cfun->has_simduid_loops = true;
10558 }
10559 /* If not -fno-tree-loop-vectorize, hint that we want to vectorize
10560 the loop. */
10561 if ((flag_tree_loop_vectorize
10562 || (!global_options_set.x_flag_tree_loop_vectorize
10563 && !global_options_set.x_flag_tree_vectorize))
10564 && flag_tree_loop_optimize
10565 && loop->safelen > 1)
10566 {
10567 loop->force_vectorize = true;
10568 cfun->has_force_vectorize_loops = true;
10569 }
10570 }
10571 else if (simduid)
10572 cfun->has_simduid_loops = true;
10573}
10574
10575/* Taskloop construct is represented after gimplification with
10576 two GIMPLE_OMP_FOR constructs with GIMPLE_OMP_TASK sandwiched
10577 in between them. This routine expands the outer GIMPLE_OMP_FOR,
10578 which should just compute all the needed loop temporaries
10579 for GIMPLE_OMP_TASK. */
10580
10581static void
10582expand_omp_taskloop_for_outer (struct omp_region *region,
10583 struct omp_for_data *fd,
10584 gimple *inner_stmt)
10585{
10586 tree type, bias = NULL_TREE;
10587 basic_block entry_bb, cont_bb, exit_bb;
10588 gimple_stmt_iterator gsi;
10589 gassign *assign_stmt;
10590 tree *counts = NULL;
10591 int i;
10592
10593 gcc_assert (inner_stmt);
10594 gcc_assert (region->cont);
10595 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_TASK
10596 && gimple_omp_task_taskloop_p (inner_stmt));
10597 type = TREE_TYPE (fd->loop.v);
10598
10599 /* See if we need to bias by LLONG_MIN. */
10600 if (fd->iter_type == long_long_unsigned_type_node
10601 && TREE_CODE (type) == INTEGER_TYPE
10602 && !TYPE_UNSIGNED (type))
10603 {
10604 tree n1, n2;
10605
10606 if (fd->loop.cond_code == LT_EXPR)
10607 {
10608 n1 = fd->loop.n1;
10609 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
10610 }
10611 else
10612 {
10613 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
10614 n2 = fd->loop.n1;
10615 }
10616 if (TREE_CODE (n1) != INTEGER_CST
10617 || TREE_CODE (n2) != INTEGER_CST
10618 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
10619 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
10620 }
10621
10622 entry_bb = region->entry;
10623 cont_bb = region->cont;
10624 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
10625 gcc_assert (BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
10626 exit_bb = region->exit;
10627
10628 gsi = gsi_last_bb (entry_bb);
10629 gimple *for_stmt = gsi_stmt (gsi);
10630 gcc_assert (gimple_code (for_stmt) == GIMPLE_OMP_FOR);
10631 if (fd->collapse > 1)
10632 {
10633 int first_zero_iter = -1, dummy = -1;
10634 basic_block zero_iter_bb = NULL, dummy_bb = NULL, l2_dom_bb = NULL;
10635
10636 counts = XALLOCAVEC (tree, fd->collapse);
10637 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
10638 zero_iter_bb, first_zero_iter,
10639 dummy_bb, dummy, l2_dom_bb);
10640
10641 if (zero_iter_bb)
10642 {
10643 /* Some counts[i] vars might be uninitialized if
10644 some loop has zero iterations. But the body shouldn't
10645 be executed in that case, so just avoid uninit warnings. */
10646 for (i = first_zero_iter; i < fd->collapse; i++)
10647 if (SSA_VAR_P (counts[i]))
10648 TREE_NO_WARNING (counts[i]) = 1;
10649 gsi_prev (&gsi);
10650 edge e = split_block (entry_bb, gsi_stmt (gsi));
10651 entry_bb = e->dest;
10652 make_edge (zero_iter_bb, entry_bb, EDGE_FALLTHRU);
10653 gsi = gsi_last_bb (entry_bb);
10654 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
10655 get_immediate_dominator (CDI_DOMINATORS,
10656 zero_iter_bb));
10657 }
10658 }
10659
10660 tree t0, t1;
10661 t1 = fd->loop.n2;
10662 t0 = fd->loop.n1;
10663 if (POINTER_TYPE_P (TREE_TYPE (t0))
10664 && TYPE_PRECISION (TREE_TYPE (t0))
10665 != TYPE_PRECISION (fd->iter_type))
10666 {
10667 /* Avoid casting pointers to integer of a different size. */
10668 tree itype = signed_type_for (type);
10669 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
10670 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
10671 }
10672 else
10673 {
10674 t1 = fold_convert (fd->iter_type, t1);
10675 t0 = fold_convert (fd->iter_type, t0);
10676 }
10677 if (bias)
10678 {
10679 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
10680 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
10681 }
10682
10683 tree innerc = find_omp_clause (gimple_omp_task_clauses (inner_stmt),
10684 OMP_CLAUSE__LOOPTEMP_);
10685 gcc_assert (innerc);
10686 tree startvar = OMP_CLAUSE_DECL (innerc);
10687 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc), OMP_CLAUSE__LOOPTEMP_);
10688 gcc_assert (innerc);
10689 tree endvar = OMP_CLAUSE_DECL (innerc);
10690 if (fd->collapse > 1 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
10691 {
10692 gcc_assert (innerc);
10693 for (i = 1; i < fd->collapse; i++)
10694 {
10695 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
10696 OMP_CLAUSE__LOOPTEMP_);
10697 gcc_assert (innerc);
10698 }
10699 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
10700 OMP_CLAUSE__LOOPTEMP_);
10701 if (innerc)
10702 {
10703 /* If needed (inner taskloop has lastprivate clause), propagate
10704 down the total number of iterations. */
10705 tree t = force_gimple_operand_gsi (&gsi, fd->loop.n2, false,
10706 NULL_TREE, false,
10707 GSI_CONTINUE_LINKING);
10708 assign_stmt = gimple_build_assign (OMP_CLAUSE_DECL (innerc), t);
10709 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10710 }
10711 }
10712
10713 t0 = force_gimple_operand_gsi (&gsi, t0, false, NULL_TREE, false,
10714 GSI_CONTINUE_LINKING);
10715 assign_stmt = gimple_build_assign (startvar, t0);
10716 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10717
10718 t1 = force_gimple_operand_gsi (&gsi, t1, false, NULL_TREE, false,
10719 GSI_CONTINUE_LINKING);
10720 assign_stmt = gimple_build_assign (endvar, t1);
10721 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10722 if (fd->collapse > 1)
10723 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
10724
10725 /* Remove the GIMPLE_OMP_FOR statement. */
10726 gsi = gsi_for_stmt (for_stmt);
10727 gsi_remove (&gsi, true);
10728
10729 gsi = gsi_last_bb (cont_bb);
10730 gsi_remove (&gsi, true);
10731
10732 gsi = gsi_last_bb (exit_bb);
10733 gsi_remove (&gsi, true);
10734
10735 FALLTHRU_EDGE (entry_bb)->probability = REG_BR_PROB_BASE;
10736 remove_edge (BRANCH_EDGE (entry_bb));
10737 FALLTHRU_EDGE (cont_bb)->probability = REG_BR_PROB_BASE;
10738 remove_edge (BRANCH_EDGE (cont_bb));
10739 set_immediate_dominator (CDI_DOMINATORS, exit_bb, cont_bb);
10740 set_immediate_dominator (CDI_DOMINATORS, region->entry,
10741 recompute_dominator (CDI_DOMINATORS, region->entry));
10742}
10743
10744/* Taskloop construct is represented after gimplification with
10745 two GIMPLE_OMP_FOR constructs with GIMPLE_OMP_TASK sandwiched
10746 in between them. This routine expands the inner GIMPLE_OMP_FOR.
10747 GOMP_taskloop{,_ull} function arranges for each task to be given just
10748 a single range of iterations. */
10749
10750static void
10751expand_omp_taskloop_for_inner (struct omp_region *region,
10752 struct omp_for_data *fd,
10753 gimple *inner_stmt)
10754{
10755 tree e, t, type, itype, vmain, vback, bias = NULL_TREE;
10756 basic_block entry_bb, exit_bb, body_bb, cont_bb, collapse_bb = NULL;
10757 basic_block fin_bb;
10758 gimple_stmt_iterator gsi;
10759 edge ep;
10760 bool broken_loop = region->cont == NULL;
10761 tree *counts = NULL;
10762 tree n1, n2, step;
10763
10764 itype = type = TREE_TYPE (fd->loop.v);
10765 if (POINTER_TYPE_P (type))
10766 itype = signed_type_for (type);
10767
10768 /* See if we need to bias by LLONG_MIN. */
10769 if (fd->iter_type == long_long_unsigned_type_node
10770 && TREE_CODE (type) == INTEGER_TYPE
10771 && !TYPE_UNSIGNED (type))
10772 {
10773 tree n1, n2;
10774
10775 if (fd->loop.cond_code == LT_EXPR)
10776 {
10777 n1 = fd->loop.n1;
10778 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
10779 }
10780 else
10781 {
10782 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
10783 n2 = fd->loop.n1;
10784 }
10785 if (TREE_CODE (n1) != INTEGER_CST
10786 || TREE_CODE (n2) != INTEGER_CST
10787 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
10788 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
10789 }
10790
10791 entry_bb = region->entry;
10792 cont_bb = region->cont;
10793 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
10794 fin_bb = BRANCH_EDGE (entry_bb)->dest;
10795 gcc_assert (broken_loop
10796 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
10797 body_bb = FALLTHRU_EDGE (entry_bb)->dest;
10798 if (!broken_loop)
10799 {
10800 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
10801 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
10802 }
10803 exit_bb = region->exit;
10804
10805 /* Iteration space partitioning goes in ENTRY_BB. */
10806 gsi = gsi_last_bb (entry_bb);
10807 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
10808
10809 if (fd->collapse > 1)
10810 {
10811 int first_zero_iter = -1, dummy = -1;
10812 basic_block l2_dom_bb = NULL, dummy_bb = NULL;
10813
10814 counts = XALLOCAVEC (tree, fd->collapse);
10815 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
10816 fin_bb, first_zero_iter,
10817 dummy_bb, dummy, l2_dom_bb);
10818 t = NULL_TREE;
10819 }
10820 else
10821 t = integer_one_node;
10822
10823 step = fd->loop.step;
10824 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
10825 OMP_CLAUSE__LOOPTEMP_);
10826 gcc_assert (innerc);
10827 n1 = OMP_CLAUSE_DECL (innerc);
10828 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc), OMP_CLAUSE__LOOPTEMP_);
10829 gcc_assert (innerc);
10830 n2 = OMP_CLAUSE_DECL (innerc);
10831 if (bias)
10832 {
10833 n1 = fold_build2 (PLUS_EXPR, fd->iter_type, n1, bias);
10834 n2 = fold_build2 (PLUS_EXPR, fd->iter_type, n2, bias);
10835 }
10836 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
10837 true, NULL_TREE, true, GSI_SAME_STMT);
10838 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
10839 true, NULL_TREE, true, GSI_SAME_STMT);
10840 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
10841 true, NULL_TREE, true, GSI_SAME_STMT);
10842
10843 tree startvar = fd->loop.v;
10844 tree endvar = NULL_TREE;
10845
10846 if (gimple_omp_for_combined_p (fd->for_stmt))
10847 {
10848 tree clauses = gimple_omp_for_clauses (inner_stmt);
10849 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
10850 gcc_assert (innerc);
10851 startvar = OMP_CLAUSE_DECL (innerc);
10852 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
10853 OMP_CLAUSE__LOOPTEMP_);
10854 gcc_assert (innerc);
10855 endvar = OMP_CLAUSE_DECL (innerc);
10856 }
10857 t = fold_convert (TREE_TYPE (startvar), n1);
10858 t = force_gimple_operand_gsi (&gsi, t,
10859 DECL_P (startvar)
10860 && TREE_ADDRESSABLE (startvar),
10861 NULL_TREE, false, GSI_CONTINUE_LINKING);
10862 gimple *assign_stmt = gimple_build_assign (startvar, t);
10863 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10864
10865 t = fold_convert (TREE_TYPE (startvar), n2);
10866 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
10867 false, GSI_CONTINUE_LINKING);
10868 if (endvar)
10869 {
10870 assign_stmt = gimple_build_assign (endvar, e);
10871 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10872 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
10873 assign_stmt = gimple_build_assign (fd->loop.v, e);
10874 else
10875 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
10876 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10877 }
10878 if (fd->collapse > 1)
10879 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
10880
10881 if (!broken_loop)
10882 {
10883 /* The code controlling the sequential loop replaces the
10884 GIMPLE_OMP_CONTINUE. */
10885 gsi = gsi_last_bb (cont_bb);
10886 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
10887 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
10888 vmain = gimple_omp_continue_control_use (cont_stmt);
10889 vback = gimple_omp_continue_control_def (cont_stmt);
10890
10891 if (!gimple_omp_for_combined_p (fd->for_stmt))
10892 {
10893 if (POINTER_TYPE_P (type))
10894 t = fold_build_pointer_plus (vmain, step);
10895 else
10896 t = fold_build2 (PLUS_EXPR, type, vmain, step);
10897 t = force_gimple_operand_gsi (&gsi, t,
10898 DECL_P (vback)
10899 && TREE_ADDRESSABLE (vback),
10900 NULL_TREE, true, GSI_SAME_STMT);
10901 assign_stmt = gimple_build_assign (vback, t);
10902 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
10903
10904 t = build2 (fd->loop.cond_code, boolean_type_node,
10905 DECL_P (vback) && TREE_ADDRESSABLE (vback)
10906 ? t : vback, e);
10907 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
10908 }
10909
10910 /* Remove the GIMPLE_OMP_CONTINUE statement. */
10911 gsi_remove (&gsi, true);
10912
10913 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
10914 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
10915 }
10916
10917 /* Remove the GIMPLE_OMP_FOR statement. */
10918 gsi = gsi_for_stmt (fd->for_stmt);
10919 gsi_remove (&gsi, true);
10920
10921 /* Remove the GIMPLE_OMP_RETURN statement. */
10922 gsi = gsi_last_bb (exit_bb);
10923 gsi_remove (&gsi, true);
10924
10925 FALLTHRU_EDGE (entry_bb)->probability = REG_BR_PROB_BASE;
10926 if (!broken_loop)
10927 remove_edge (BRANCH_EDGE (entry_bb));
10928 else
10929 {
10930 remove_edge_and_dominated_blocks (BRANCH_EDGE (entry_bb));
10931 region->outer->cont = NULL;
10932 }
10933
10934 /* Connect all the blocks. */
10935 if (!broken_loop)
10936 {
10937 ep = find_edge (cont_bb, body_bb);
10938 if (gimple_omp_for_combined_p (fd->for_stmt))
10939 {
10940 remove_edge (ep);
10941 ep = NULL;
3d483a94 10942 }
43895be5 10943 else if (fd->collapse > 1)
3d483a94 10944 {
43895be5 10945 remove_edge (ep);
10946 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
3d483a94 10947 }
43895be5 10948 else
10949 ep->flags = EDGE_TRUE_VALUE;
10950 find_edge (cont_bb, fin_bb)->flags
10951 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
3d483a94 10952 }
3d483a94 10953
43895be5 10954 set_immediate_dominator (CDI_DOMINATORS, body_bb,
10955 recompute_dominator (CDI_DOMINATORS, body_bb));
10956 if (!broken_loop)
10957 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
10958 recompute_dominator (CDI_DOMINATORS, fin_bb));
10959
10960 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
10961 {
10962 struct loop *loop = alloc_loop ();
10963 loop->header = body_bb;
10964 if (collapse_bb == NULL)
10965 loop->latch = cont_bb;
10966 add_loop (loop, body_bb->loop_father);
10967 }
10968}
1e8e9920 10969
a8e785ba 10970/* A subroutine of expand_omp_for. Generate code for an OpenACC
10971 partitioned loop. The lowering here is abstracted, in that the
10972 loop parameters are passed through internal functions, which are
10973 further lowered by oacc_device_lower, once we get to the target
10974 compiler. The loop is of the form:
10975
10976 for (V = B; V LTGT E; V += S) {BODY}
10977
10978 where LTGT is < or >. We may have a specified chunking size, CHUNKING
10979 (constant 0 for no chunking) and we will have a GWV partitioning
10980 mask, specifying dimensions over which the loop is to be
10981 partitioned (see note below). We generate code that looks like:
10982
10983 <entry_bb> [incoming FALL->body, BRANCH->exit]
10984 typedef signedintify (typeof (V)) T; // underlying signed integral type
10985 T range = E - B;
10986 T chunk_no = 0;
10987 T DIR = LTGT == '<' ? +1 : -1;
10988 T chunk_max = GOACC_LOOP_CHUNK (dir, range, S, CHUNK_SIZE, GWV);
10989 T step = GOACC_LOOP_STEP (dir, range, S, CHUNK_SIZE, GWV);
10990
10991 <head_bb> [created by splitting end of entry_bb]
10992 T offset = GOACC_LOOP_OFFSET (dir, range, S, CHUNK_SIZE, GWV, chunk_no);
10993 T bound = GOACC_LOOP_BOUND (dir, range, S, CHUNK_SIZE, GWV, offset);
10994 if (!(offset LTGT bound)) goto bottom_bb;
10995
10996 <body_bb> [incoming]
10997 V = B + offset;
10998 {BODY}
10999
11000 <cont_bb> [incoming, may == body_bb FALL->exit_bb, BRANCH->body_bb]
11001 offset += step;
11002 if (offset LTGT bound) goto body_bb; [*]
11003
11004 <bottom_bb> [created by splitting start of exit_bb] insert BRANCH->head_bb
11005 chunk_no++;
11006 if (chunk < chunk_max) goto head_bb;
11007
11008 <exit_bb> [incoming]
11009 V = B + ((range -/+ 1) / S +/- 1) * S [*]
11010
11011 [*] Needed if V live at end of loop
11012
11013 Note: CHUNKING & GWV mask are specified explicitly here. This is a
11014 transition, and will be specified by a more general mechanism shortly.
11015 */
11016
11017static void
11018expand_oacc_for (struct omp_region *region, struct omp_for_data *fd)
11019{
11020 tree v = fd->loop.v;
11021 enum tree_code cond_code = fd->loop.cond_code;
11022 enum tree_code plus_code = PLUS_EXPR;
11023
11024 tree chunk_size = integer_minus_one_node;
11025 tree gwv = integer_zero_node;
11026 tree iter_type = TREE_TYPE (v);
11027 tree diff_type = iter_type;
11028 tree plus_type = iter_type;
11029 struct oacc_collapse *counts = NULL;
11030
11031 gcc_checking_assert (gimple_omp_for_kind (fd->for_stmt)
11032 == GF_OMP_FOR_KIND_OACC_LOOP);
11033 gcc_assert (!gimple_omp_for_combined_into_p (fd->for_stmt));
11034 gcc_assert (cond_code == LT_EXPR || cond_code == GT_EXPR);
11035
11036 if (POINTER_TYPE_P (iter_type))
11037 {
11038 plus_code = POINTER_PLUS_EXPR;
11039 plus_type = sizetype;
11040 }
11041 if (POINTER_TYPE_P (diff_type) || TYPE_UNSIGNED (diff_type))
11042 diff_type = signed_type_for (diff_type);
11043
11044 basic_block entry_bb = region->entry; /* BB ending in OMP_FOR */
11045 basic_block exit_bb = region->exit; /* BB ending in OMP_RETURN */
11046 basic_block cont_bb = region->cont; /* BB ending in OMP_CONTINUE */
11047 basic_block bottom_bb = NULL;
11048
11049 /* entry_bb has two sucessors; the branch edge is to the exit
11050 block, fallthrough edge to body. */
11051 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2
11052 && BRANCH_EDGE (entry_bb)->dest == exit_bb);
11053
11054 /* If cont_bb non-NULL, it has 2 successors. The branch successor is
11055 body_bb, or to a block whose only successor is the body_bb. Its
11056 fallthrough successor is the final block (same as the branch
11057 successor of the entry_bb). */
11058 if (cont_bb)
11059 {
11060 basic_block body_bb = FALLTHRU_EDGE (entry_bb)->dest;
11061 basic_block bed = BRANCH_EDGE (cont_bb)->dest;
11062
11063 gcc_assert (FALLTHRU_EDGE (cont_bb)->dest == exit_bb);
11064 gcc_assert (bed == body_bb || single_succ_edge (bed)->dest == body_bb);
11065 }
11066 else
11067 gcc_assert (!gimple_in_ssa_p (cfun));
11068
11069 /* The exit block only has entry_bb and cont_bb as predecessors. */
11070 gcc_assert (EDGE_COUNT (exit_bb->preds) == 1 + (cont_bb != NULL));
11071
11072 tree chunk_no;
11073 tree chunk_max = NULL_TREE;
11074 tree bound, offset;
11075 tree step = create_tmp_var (diff_type, ".step");
11076 bool up = cond_code == LT_EXPR;
11077 tree dir = build_int_cst (diff_type, up ? +1 : -1);
11078 bool chunking = !gimple_in_ssa_p (cfun);;
11079 bool negating;
11080
11081 /* SSA instances. */
11082 tree offset_incr = NULL_TREE;
11083 tree offset_init = NULL_TREE;
11084
11085 gimple_stmt_iterator gsi;
11086 gassign *ass;
11087 gcall *call;
11088 gimple *stmt;
11089 tree expr;
11090 location_t loc;
11091 edge split, be, fte;
11092
11093 /* Split the end of entry_bb to create head_bb. */
11094 split = split_block (entry_bb, last_stmt (entry_bb));
11095 basic_block head_bb = split->dest;
11096 entry_bb = split->src;
11097
11098 /* Chunk setup goes at end of entry_bb, replacing the omp_for. */
11099 gsi = gsi_last_bb (entry_bb);
11100 gomp_for *for_stmt = as_a <gomp_for *> (gsi_stmt (gsi));
11101 loc = gimple_location (for_stmt);
11102
11103 if (gimple_in_ssa_p (cfun))
11104 {
11105 offset_init = gimple_omp_for_index (for_stmt, 0);
11106 gcc_assert (integer_zerop (fd->loop.n1));
11107 /* The SSA parallelizer does gang parallelism. */
11108 gwv = build_int_cst (integer_type_node, GOMP_DIM_MASK (GOMP_DIM_GANG));
11109 }
11110
11111 if (fd->collapse > 1)
11112 {
11113 counts = XALLOCAVEC (struct oacc_collapse, fd->collapse);
11114 tree total = expand_oacc_collapse_init (fd, &gsi, counts,
11115 TREE_TYPE (fd->loop.n2));
11116
11117 if (SSA_VAR_P (fd->loop.n2))
11118 {
11119 total = force_gimple_operand_gsi (&gsi, total, false, NULL_TREE,
11120 true, GSI_SAME_STMT);
11121 ass = gimple_build_assign (fd->loop.n2, total);
11122 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11123 }
11124
11125 }
11126
11127 tree b = fd->loop.n1;
11128 tree e = fd->loop.n2;
11129 tree s = fd->loop.step;
11130
11131 b = force_gimple_operand_gsi (&gsi, b, true, NULL_TREE, true, GSI_SAME_STMT);
11132 e = force_gimple_operand_gsi (&gsi, e, true, NULL_TREE, true, GSI_SAME_STMT);
11133
11134 /* Convert the step, avoiding possible unsigned->signed overflow. */
11135 negating = !up && TYPE_UNSIGNED (TREE_TYPE (s));
11136 if (negating)
11137 s = fold_build1 (NEGATE_EXPR, TREE_TYPE (s), s);
11138 s = fold_convert (diff_type, s);
11139 if (negating)
11140 s = fold_build1 (NEGATE_EXPR, diff_type, s);
11141 s = force_gimple_operand_gsi (&gsi, s, true, NULL_TREE, true, GSI_SAME_STMT);
11142
11143 if (!chunking)
11144 chunk_size = integer_zero_node;
11145 expr = fold_convert (diff_type, chunk_size);
11146 chunk_size = force_gimple_operand_gsi (&gsi, expr, true,
11147 NULL_TREE, true, GSI_SAME_STMT);
11148 /* Determine the range, avoiding possible unsigned->signed overflow. */
11149 negating = !up && TYPE_UNSIGNED (iter_type);
11150 expr = fold_build2 (MINUS_EXPR, plus_type,
11151 fold_convert (plus_type, negating ? b : e),
11152 fold_convert (plus_type, negating ? e : b));
11153 expr = fold_convert (diff_type, expr);
11154 if (negating)
11155 expr = fold_build1 (NEGATE_EXPR, diff_type, expr);
11156 tree range = force_gimple_operand_gsi (&gsi, expr, true,
11157 NULL_TREE, true, GSI_SAME_STMT);
11158
11159 chunk_no = build_int_cst (diff_type, 0);
11160 if (chunking)
11161 {
11162 gcc_assert (!gimple_in_ssa_p (cfun));
11163
11164 expr = chunk_no;
11165 chunk_max = create_tmp_var (diff_type, ".chunk_max");
11166 chunk_no = create_tmp_var (diff_type, ".chunk_no");
11167
11168 ass = gimple_build_assign (chunk_no, expr);
11169 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11170
11171 call = gimple_build_call_internal (IFN_GOACC_LOOP, 6,
11172 build_int_cst (integer_type_node,
11173 IFN_GOACC_LOOP_CHUNKS),
11174 dir, range, s, chunk_size, gwv);
11175 gimple_call_set_lhs (call, chunk_max);
11176 gimple_set_location (call, loc);
11177 gsi_insert_before (&gsi, call, GSI_SAME_STMT);
11178 }
11179 else
11180 chunk_size = chunk_no;
11181
11182 call = gimple_build_call_internal (IFN_GOACC_LOOP, 6,
11183 build_int_cst (integer_type_node,
11184 IFN_GOACC_LOOP_STEP),
11185 dir, range, s, chunk_size, gwv);
11186 gimple_call_set_lhs (call, step);
11187 gimple_set_location (call, loc);
11188 gsi_insert_before (&gsi, call, GSI_SAME_STMT);
11189
11190 /* Remove the GIMPLE_OMP_FOR. */
11191 gsi_remove (&gsi, true);
11192
11193 /* Fixup edges from head_bb */
11194 be = BRANCH_EDGE (head_bb);
11195 fte = FALLTHRU_EDGE (head_bb);
11196 be->flags |= EDGE_FALSE_VALUE;
11197 fte->flags ^= EDGE_FALLTHRU | EDGE_TRUE_VALUE;
11198
11199 basic_block body_bb = fte->dest;
11200
11201 if (gimple_in_ssa_p (cfun))
11202 {
11203 gsi = gsi_last_bb (cont_bb);
11204 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
11205
11206 offset = gimple_omp_continue_control_use (cont_stmt);
11207 offset_incr = gimple_omp_continue_control_def (cont_stmt);
11208 }
11209 else
11210 {
11211 offset = create_tmp_var (diff_type, ".offset");
11212 offset_init = offset_incr = offset;
11213 }
11214 bound = create_tmp_var (TREE_TYPE (offset), ".bound");
11215
11216 /* Loop offset & bound go into head_bb. */
11217 gsi = gsi_start_bb (head_bb);
11218
11219 call = gimple_build_call_internal (IFN_GOACC_LOOP, 7,
11220 build_int_cst (integer_type_node,
11221 IFN_GOACC_LOOP_OFFSET),
11222 dir, range, s,
11223 chunk_size, gwv, chunk_no);
11224 gimple_call_set_lhs (call, offset_init);
11225 gimple_set_location (call, loc);
11226 gsi_insert_after (&gsi, call, GSI_CONTINUE_LINKING);
11227
11228 call = gimple_build_call_internal (IFN_GOACC_LOOP, 7,
11229 build_int_cst (integer_type_node,
11230 IFN_GOACC_LOOP_BOUND),
11231 dir, range, s,
11232 chunk_size, gwv, offset_init);
11233 gimple_call_set_lhs (call, bound);
11234 gimple_set_location (call, loc);
11235 gsi_insert_after (&gsi, call, GSI_CONTINUE_LINKING);
11236
11237 expr = build2 (cond_code, boolean_type_node, offset_init, bound);
11238 gsi_insert_after (&gsi, gimple_build_cond_empty (expr),
11239 GSI_CONTINUE_LINKING);
11240
11241 /* V assignment goes into body_bb. */
11242 if (!gimple_in_ssa_p (cfun))
11243 {
11244 gsi = gsi_start_bb (body_bb);
11245
11246 expr = build2 (plus_code, iter_type, b,
11247 fold_convert (plus_type, offset));
11248 expr = force_gimple_operand_gsi (&gsi, expr, false, NULL_TREE,
11249 true, GSI_SAME_STMT);
11250 ass = gimple_build_assign (v, expr);
11251 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11252 if (fd->collapse > 1)
11253 expand_oacc_collapse_vars (fd, &gsi, counts, v);
11254 }
11255
11256 /* Loop increment goes into cont_bb. If this is not a loop, we
11257 will have spawned threads as if it was, and each one will
11258 execute one iteration. The specification is not explicit about
11259 whether such constructs are ill-formed or not, and they can
11260 occur, especially when noreturn routines are involved. */
11261 if (cont_bb)
11262 {
11263 gsi = gsi_last_bb (cont_bb);
11264 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
11265 loc = gimple_location (cont_stmt);
11266
11267 /* Increment offset. */
11268 if (gimple_in_ssa_p (cfun))
11269 expr= build2 (plus_code, iter_type, offset,
11270 fold_convert (plus_type, step));
11271 else
11272 expr = build2 (PLUS_EXPR, diff_type, offset, step);
11273 expr = force_gimple_operand_gsi (&gsi, expr, false, NULL_TREE,
11274 true, GSI_SAME_STMT);
11275 ass = gimple_build_assign (offset_incr, expr);
11276 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11277 expr = build2 (cond_code, boolean_type_node, offset_incr, bound);
11278 gsi_insert_before (&gsi, gimple_build_cond_empty (expr), GSI_SAME_STMT);
11279
11280 /* Remove the GIMPLE_OMP_CONTINUE. */
11281 gsi_remove (&gsi, true);
11282
11283 /* Fixup edges from cont_bb */
11284 be = BRANCH_EDGE (cont_bb);
11285 fte = FALLTHRU_EDGE (cont_bb);
11286 be->flags |= EDGE_TRUE_VALUE;
11287 fte->flags ^= EDGE_FALLTHRU | EDGE_FALSE_VALUE;
11288
11289 if (chunking)
11290 {
11291 /* Split the beginning of exit_bb to make bottom_bb. We
11292 need to insert a nop at the start, because splitting is
11293 after a stmt, not before. */
11294 gsi = gsi_start_bb (exit_bb);
11295 stmt = gimple_build_nop ();
11296 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
11297 split = split_block (exit_bb, stmt);
11298 bottom_bb = split->src;
11299 exit_bb = split->dest;
11300 gsi = gsi_last_bb (bottom_bb);
11301
11302 /* Chunk increment and test goes into bottom_bb. */
11303 expr = build2 (PLUS_EXPR, diff_type, chunk_no,
11304 build_int_cst (diff_type, 1));
11305 ass = gimple_build_assign (chunk_no, expr);
11306 gsi_insert_after (&gsi, ass, GSI_CONTINUE_LINKING);
11307
11308 /* Chunk test at end of bottom_bb. */
11309 expr = build2 (LT_EXPR, boolean_type_node, chunk_no, chunk_max);
11310 gsi_insert_after (&gsi, gimple_build_cond_empty (expr),
11311 GSI_CONTINUE_LINKING);
11312
11313 /* Fixup edges from bottom_bb. */
11314 split->flags ^= EDGE_FALLTHRU | EDGE_FALSE_VALUE;
11315 make_edge (bottom_bb, head_bb, EDGE_TRUE_VALUE);
11316 }
11317 }
11318
11319 gsi = gsi_last_bb (exit_bb);
11320 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
11321 loc = gimple_location (gsi_stmt (gsi));
11322
11323 if (!gimple_in_ssa_p (cfun))
11324 {
11325 /* Insert the final value of V, in case it is live. This is the
11326 value for the only thread that survives past the join. */
11327 expr = fold_build2 (MINUS_EXPR, diff_type, range, dir);
11328 expr = fold_build2 (PLUS_EXPR, diff_type, expr, s);
11329 expr = fold_build2 (TRUNC_DIV_EXPR, diff_type, expr, s);
11330 expr = fold_build2 (MULT_EXPR, diff_type, expr, s);
11331 expr = build2 (plus_code, iter_type, b, fold_convert (plus_type, expr));
11332 expr = force_gimple_operand_gsi (&gsi, expr, false, NULL_TREE,
11333 true, GSI_SAME_STMT);
11334 ass = gimple_build_assign (v, expr);
11335 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11336 }
11337
11338 /* Remove the OMP_RETURN. */
11339 gsi_remove (&gsi, true);
11340
11341 if (cont_bb)
11342 {
11343 /* We now have one or two nested loops. Update the loop
11344 structures. */
11345 struct loop *parent = entry_bb->loop_father;
11346 struct loop *body = body_bb->loop_father;
11347
11348 if (chunking)
11349 {
11350 struct loop *chunk_loop = alloc_loop ();
11351 chunk_loop->header = head_bb;
11352 chunk_loop->latch = bottom_bb;
11353 add_loop (chunk_loop, parent);
11354 parent = chunk_loop;
11355 }
11356 else if (parent != body)
11357 {
11358 gcc_assert (body->header == body_bb);
11359 gcc_assert (body->latch == cont_bb
11360 || single_pred (body->latch) == cont_bb);
11361 parent = NULL;
11362 }
11363
11364 if (parent)
11365 {
11366 struct loop *body_loop = alloc_loop ();
11367 body_loop->header = body_bb;
11368 body_loop->latch = cont_bb;
11369 add_loop (body_loop, parent);
11370 }
11371 }
11372}
11373
ca4c3545 11374/* Expand the OMP loop defined by REGION. */
1e8e9920 11375
773c5ba7 11376static void
42acab1c 11377expand_omp_for (struct omp_region *region, gimple *inner_stmt)
773c5ba7 11378{
11379 struct omp_for_data fd;
fd6481cf 11380 struct omp_for_data_loop *loops;
1e8e9920 11381
fd6481cf 11382 loops
11383 = (struct omp_for_data_loop *)
75a70cf9 11384 alloca (gimple_omp_for_collapse (last_stmt (region->entry))
fd6481cf 11385 * sizeof (struct omp_for_data_loop));
1a91d914 11386 extract_omp_for_data (as_a <gomp_for *> (last_stmt (region->entry)),
11387 &fd, loops);
f77459c5 11388 region->sched_kind = fd.sched_kind;
9561765e 11389 region->sched_modifiers = fd.sched_modifiers;
1e8e9920 11390
b3a3ddec 11391 gcc_assert (EDGE_COUNT (region->entry->succs) == 2);
11392 BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
11393 FALLTHRU_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
11394 if (region->cont)
11395 {
11396 gcc_assert (EDGE_COUNT (region->cont->succs) == 2);
11397 BRANCH_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
11398 FALLTHRU_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
11399 }
04c2922b 11400 else
75de4aa2 11401 /* If there isn't a continue then this is a degerate case where
04c2922b 11402 the introduction of abnormal edges during lowering will prevent
11403 original loops from being detected. Fix that up. */
11404 loops_state_set (LOOPS_NEED_FIXUP);
b3a3ddec 11405
10c55644 11406 if (gimple_omp_for_kind (fd.for_stmt) & GF_OMP_FOR_SIMD)
3d483a94 11407 expand_omp_simd (region, &fd);
40750995 11408 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
11409 expand_cilk_for (region, &fd);
a8e785ba 11410 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
11411 {
11412 gcc_assert (!inner_stmt);
11413 expand_oacc_for (region, &fd);
11414 }
43895be5 11415 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_TASKLOOP)
11416 {
11417 if (gimple_omp_for_combined_into_p (fd.for_stmt))
11418 expand_omp_taskloop_for_inner (region, &fd, inner_stmt);
11419 else
11420 expand_omp_taskloop_for_outer (region, &fd, inner_stmt);
11421 }
3d483a94 11422 else if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
bc7bff74 11423 && !fd.have_ordered)
1e8e9920 11424 {
11425 if (fd.chunk_size == NULL)
bc7bff74 11426 expand_omp_for_static_nochunk (region, &fd, inner_stmt);
1e8e9920 11427 else
bc7bff74 11428 expand_omp_for_static_chunk (region, &fd, inner_stmt);
1e8e9920 11429 }
11430 else
11431 {
fd6481cf 11432 int fn_index, start_ix, next_ix;
11433
3d483a94 11434 gcc_assert (gimple_omp_for_kind (fd.for_stmt)
11435 == GF_OMP_FOR_KIND_FOR);
0416ca72 11436 if (fd.chunk_size == NULL
11437 && fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
11438 fd.chunk_size = integer_zero_node;
fd6481cf 11439 gcc_assert (fd.sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
9561765e 11440 switch (fd.sched_kind)
11441 {
11442 case OMP_CLAUSE_SCHEDULE_RUNTIME:
11443 fn_index = 3;
11444 break;
11445 case OMP_CLAUSE_SCHEDULE_DYNAMIC:
11446 case OMP_CLAUSE_SCHEDULE_GUIDED:
11447 if ((fd.sched_modifiers & OMP_CLAUSE_SCHEDULE_NONMONOTONIC)
11448 && !fd.ordered
11449 && !fd.have_ordered)
11450 {
11451 fn_index = 3 + fd.sched_kind;
11452 break;
11453 }
11454 /* FALLTHRU */
11455 default:
11456 fn_index = fd.sched_kind;
11457 break;
11458 }
43895be5 11459 if (!fd.ordered)
9561765e 11460 fn_index += fd.have_ordered * 6;
43895be5 11461 if (fd.ordered)
11462 start_ix = ((int)BUILT_IN_GOMP_LOOP_DOACROSS_STATIC_START) + fn_index;
11463 else
11464 start_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_START) + fn_index;
b9a16870 11465 next_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT) + fn_index;
fd6481cf 11466 if (fd.iter_type == long_long_unsigned_type_node)
11467 {
b9a16870 11468 start_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
11469 - (int)BUILT_IN_GOMP_LOOP_STATIC_START);
11470 next_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
11471 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT);
fd6481cf 11472 }
b9c74b4d 11473 expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
bc7bff74 11474 (enum built_in_function) next_ix, inner_stmt);
1e8e9920 11475 }
28c92cbb 11476
083152fb 11477 if (gimple_in_ssa_p (cfun))
11478 update_ssa (TODO_update_ssa_only_virtuals);
1e8e9920 11479}
11480
1e8e9920 11481
11482/* Expand code for an OpenMP sections directive. In pseudo code, we generate
11483
1e8e9920 11484 v = GOMP_sections_start (n);
11485 L0:
11486 switch (v)
11487 {
11488 case 0:
11489 goto L2;
11490 case 1:
11491 section 1;
11492 goto L1;
11493 case 2:
11494 ...
11495 case n:
11496 ...
1e8e9920 11497 default:
11498 abort ();
11499 }
11500 L1:
11501 v = GOMP_sections_next ();
11502 goto L0;
11503 L2:
11504 reduction;
11505
773c5ba7 11506 If this is a combined parallel sections, replace the call to
79acaae1 11507 GOMP_sections_start with call to GOMP_sections_next. */
1e8e9920 11508
11509static void
773c5ba7 11510expand_omp_sections (struct omp_region *region)
1e8e9920 11511{
f018d957 11512 tree t, u, vin = NULL, vmain, vnext, l2;
75a70cf9 11513 unsigned len;
ac6e3339 11514 basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
75a70cf9 11515 gimple_stmt_iterator si, switch_si;
1a91d914 11516 gomp_sections *sections_stmt;
42acab1c 11517 gimple *stmt;
1a91d914 11518 gomp_continue *cont;
9884aaf8 11519 edge_iterator ei;
11520 edge e;
61e47ac8 11521 struct omp_region *inner;
75a70cf9 11522 unsigned i, casei;
ac6e3339 11523 bool exit_reachable = region->cont != NULL;
1e8e9920 11524
d244d9de 11525 gcc_assert (region->exit != NULL);
61e47ac8 11526 entry_bb = region->entry;
ac6e3339 11527 l0_bb = single_succ (entry_bb);
61e47ac8 11528 l1_bb = region->cont;
ac6e3339 11529 l2_bb = region->exit;
d244d9de 11530 if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
11531 l2 = gimple_block_label (l2_bb);
11532 else
03ed154b 11533 {
d244d9de 11534 /* This can happen if there are reductions. */
11535 len = EDGE_COUNT (l0_bb->succs);
11536 gcc_assert (len > 0);
11537 e = EDGE_SUCC (l0_bb, len - 1);
11538 si = gsi_last_bb (e->dest);
11539 l2 = NULL_TREE;
11540 if (gsi_end_p (si)
11541 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
11542 l2 = gimple_block_label (e->dest);
9884aaf8 11543 else
d244d9de 11544 FOR_EACH_EDGE (e, ei, l0_bb->succs)
11545 {
11546 si = gsi_last_bb (e->dest);
11547 if (gsi_end_p (si)
11548 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
9884aaf8 11549 {
d244d9de 11550 l2 = gimple_block_label (e->dest);
11551 break;
9884aaf8 11552 }
d244d9de 11553 }
03ed154b 11554 }
d244d9de 11555 if (exit_reachable)
11556 default_bb = create_empty_bb (l1_bb->prev_bb);
03ed154b 11557 else
d244d9de 11558 default_bb = create_empty_bb (l0_bb);
773c5ba7 11559
11560 /* We will build a switch() with enough cases for all the
75a70cf9 11561 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
773c5ba7 11562 and a default case to abort if something goes wrong. */
ac6e3339 11563 len = EDGE_COUNT (l0_bb->succs);
75a70cf9 11564
f1f41a6c 11565 /* Use vec::quick_push on label_vec throughout, since we know the size
75a70cf9 11566 in advance. */
c2078b80 11567 auto_vec<tree> label_vec (len);
1e8e9920 11568
61e47ac8 11569 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
75a70cf9 11570 GIMPLE_OMP_SECTIONS statement. */
11571 si = gsi_last_bb (entry_bb);
1a91d914 11572 sections_stmt = as_a <gomp_sections *> (gsi_stmt (si));
75a70cf9 11573 gcc_assert (gimple_code (sections_stmt) == GIMPLE_OMP_SECTIONS);
11574 vin = gimple_omp_sections_control (sections_stmt);
773c5ba7 11575 if (!is_combined_parallel (region))
1e8e9920 11576 {
773c5ba7 11577 /* If we are not inside a combined parallel+sections region,
11578 call GOMP_sections_start. */
39cb6d68 11579 t = build_int_cst (unsigned_type_node, len - 1);
b9a16870 11580 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START);
75a70cf9 11581 stmt = gimple_build_call (u, 1, t);
1e8e9920 11582 }
79acaae1 11583 else
11584 {
11585 /* Otherwise, call GOMP_sections_next. */
b9a16870 11586 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
75a70cf9 11587 stmt = gimple_build_call (u, 0);
79acaae1 11588 }
75a70cf9 11589 gimple_call_set_lhs (stmt, vin);
11590 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
11591 gsi_remove (&si, true);
11592
11593 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
11594 L0_BB. */
11595 switch_si = gsi_last_bb (l0_bb);
11596 gcc_assert (gimple_code (gsi_stmt (switch_si)) == GIMPLE_OMP_SECTIONS_SWITCH);
79acaae1 11597 if (exit_reachable)
11598 {
1a91d914 11599 cont = as_a <gomp_continue *> (last_stmt (l1_bb));
75a70cf9 11600 gcc_assert (gimple_code (cont) == GIMPLE_OMP_CONTINUE);
11601 vmain = gimple_omp_continue_control_use (cont);
11602 vnext = gimple_omp_continue_control_def (cont);
79acaae1 11603 }
11604 else
11605 {
11606 vmain = vin;
11607 vnext = NULL_TREE;
11608 }
1e8e9920 11609
d244d9de 11610 t = build_case_label (build_int_cst (unsigned_type_node, 0), NULL, l2);
f1f41a6c 11611 label_vec.quick_push (t);
d244d9de 11612 i = 1;
03ed154b 11613
75a70cf9 11614 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
ac6e3339 11615 for (inner = region->inner, casei = 1;
11616 inner;
11617 inner = inner->next, i++, casei++)
1e8e9920 11618 {
773c5ba7 11619 basic_block s_entry_bb, s_exit_bb;
11620
9884aaf8 11621 /* Skip optional reduction region. */
75a70cf9 11622 if (inner->type == GIMPLE_OMP_ATOMIC_LOAD)
9884aaf8 11623 {
11624 --i;
11625 --casei;
11626 continue;
11627 }
11628
61e47ac8 11629 s_entry_bb = inner->entry;
11630 s_exit_bb = inner->exit;
1e8e9920 11631
75a70cf9 11632 t = gimple_block_label (s_entry_bb);
ac6e3339 11633 u = build_int_cst (unsigned_type_node, casei);
b6e3dd65 11634 u = build_case_label (u, NULL, t);
f1f41a6c 11635 label_vec.quick_push (u);
61e47ac8 11636
75a70cf9 11637 si = gsi_last_bb (s_entry_bb);
11638 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SECTION);
11639 gcc_assert (i < len || gimple_omp_section_last_p (gsi_stmt (si)));
11640 gsi_remove (&si, true);
61e47ac8 11641 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
03ed154b 11642
11643 if (s_exit_bb == NULL)
11644 continue;
11645
75a70cf9 11646 si = gsi_last_bb (s_exit_bb);
11647 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
11648 gsi_remove (&si, true);
03ed154b 11649
773c5ba7 11650 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
1e8e9920 11651 }
11652
773c5ba7 11653 /* Error handling code goes in DEFAULT_BB. */
75a70cf9 11654 t = gimple_block_label (default_bb);
b6e3dd65 11655 u = build_case_label (NULL, NULL, t);
61e47ac8 11656 make_edge (l0_bb, default_bb, 0);
b3083327 11657 add_bb_to_loop (default_bb, current_loops->tree_root);
1e8e9920 11658
49a70175 11659 stmt = gimple_build_switch (vmain, u, label_vec);
75a70cf9 11660 gsi_insert_after (&switch_si, stmt, GSI_SAME_STMT);
11661 gsi_remove (&switch_si, true);
75a70cf9 11662
11663 si = gsi_start_bb (default_bb);
b9a16870 11664 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
75a70cf9 11665 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
773c5ba7 11666
ac6e3339 11667 if (exit_reachable)
03ed154b 11668 {
b9a16870 11669 tree bfn_decl;
11670
ac6e3339 11671 /* Code to get the next section goes in L1_BB. */
75a70cf9 11672 si = gsi_last_bb (l1_bb);
11673 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
1e8e9920 11674
b9a16870 11675 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
11676 stmt = gimple_build_call (bfn_decl, 0);
75a70cf9 11677 gimple_call_set_lhs (stmt, vnext);
11678 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
11679 gsi_remove (&si, true);
773c5ba7 11680
ac6e3339 11681 single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
03ed154b 11682 }
773c5ba7 11683
d244d9de 11684 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
11685 si = gsi_last_bb (l2_bb);
11686 if (gimple_omp_return_nowait_p (gsi_stmt (si)))
11687 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
bc7bff74 11688 else if (gimple_omp_return_lhs (gsi_stmt (si)))
11689 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL);
d244d9de 11690 else
11691 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
11692 stmt = gimple_build_call (t, 0);
bc7bff74 11693 if (gimple_omp_return_lhs (gsi_stmt (si)))
11694 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (si)));
d244d9de 11695 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
11696 gsi_remove (&si, true);
11697
79acaae1 11698 set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
773c5ba7 11699}
1e8e9920 11700
1e8e9920 11701
61e47ac8 11702/* Expand code for an OpenMP single directive. We've already expanded
11703 much of the code, here we simply place the GOMP_barrier call. */
11704
11705static void
11706expand_omp_single (struct omp_region *region)
11707{
11708 basic_block entry_bb, exit_bb;
75a70cf9 11709 gimple_stmt_iterator si;
61e47ac8 11710
11711 entry_bb = region->entry;
11712 exit_bb = region->exit;
11713
75a70cf9 11714 si = gsi_last_bb (entry_bb);
75a70cf9 11715 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE);
11716 gsi_remove (&si, true);
61e47ac8 11717 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
11718
75a70cf9 11719 si = gsi_last_bb (exit_bb);
bc7bff74 11720 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
11721 {
11722 tree t = gimple_omp_return_lhs (gsi_stmt (si));
11723 gsi_insert_after (&si, build_omp_barrier (t), GSI_SAME_STMT);
11724 }
75a70cf9 11725 gsi_remove (&si, true);
61e47ac8 11726 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
11727}
11728
11729
11730/* Generic expansion for OpenMP synchronization directives: master,
11731 ordered and critical. All we need to do here is remove the entry
11732 and exit markers for REGION. */
773c5ba7 11733
11734static void
11735expand_omp_synch (struct omp_region *region)
11736{
11737 basic_block entry_bb, exit_bb;
75a70cf9 11738 gimple_stmt_iterator si;
773c5ba7 11739
61e47ac8 11740 entry_bb = region->entry;
11741 exit_bb = region->exit;
773c5ba7 11742
75a70cf9 11743 si = gsi_last_bb (entry_bb);
11744 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE
11745 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASTER
bc7bff74 11746 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TASKGROUP
75a70cf9 11747 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ORDERED
bc7bff74 11748 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CRITICAL
11749 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TEAMS);
75a70cf9 11750 gsi_remove (&si, true);
773c5ba7 11751 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
11752
03ed154b 11753 if (exit_bb)
11754 {
75a70cf9 11755 si = gsi_last_bb (exit_bb);
11756 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
11757 gsi_remove (&si, true);
03ed154b 11758 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
11759 }
773c5ba7 11760}
1e8e9920 11761
2169f33b 11762/* A subroutine of expand_omp_atomic. Attempt to implement the atomic
11763 operation as a normal volatile load. */
11764
11765static bool
3ec11c49 11766expand_omp_atomic_load (basic_block load_bb, tree addr,
11767 tree loaded_val, int index)
2169f33b 11768{
3ec11c49 11769 enum built_in_function tmpbase;
11770 gimple_stmt_iterator gsi;
11771 basic_block store_bb;
11772 location_t loc;
42acab1c 11773 gimple *stmt;
3ec11c49 11774 tree decl, call, type, itype;
11775
11776 gsi = gsi_last_bb (load_bb);
11777 stmt = gsi_stmt (gsi);
11778 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
11779 loc = gimple_location (stmt);
11780
11781 /* ??? If the target does not implement atomic_load_optab[mode], and mode
11782 is smaller than word size, then expand_atomic_load assumes that the load
11783 is atomic. We could avoid the builtin entirely in this case. */
11784
11785 tmpbase = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
11786 decl = builtin_decl_explicit (tmpbase);
11787 if (decl == NULL_TREE)
11788 return false;
11789
11790 type = TREE_TYPE (loaded_val);
11791 itype = TREE_TYPE (TREE_TYPE (decl));
11792
11793 call = build_call_expr_loc (loc, decl, 2, addr,
bc7bff74 11794 build_int_cst (NULL,
11795 gimple_omp_atomic_seq_cst_p (stmt)
11796 ? MEMMODEL_SEQ_CST
11797 : MEMMODEL_RELAXED));
3ec11c49 11798 if (!useless_type_conversion_p (type, itype))
11799 call = fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
11800 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
11801
11802 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
11803 gsi_remove (&gsi, true);
11804
11805 store_bb = single_succ (load_bb);
11806 gsi = gsi_last_bb (store_bb);
11807 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
11808 gsi_remove (&gsi, true);
11809
11810 if (gimple_in_ssa_p (cfun))
11811 update_ssa (TODO_update_ssa_no_phi);
11812
11813 return true;
2169f33b 11814}
11815
11816/* A subroutine of expand_omp_atomic. Attempt to implement the atomic
11817 operation as a normal volatile store. */
11818
11819static bool
3ec11c49 11820expand_omp_atomic_store (basic_block load_bb, tree addr,
11821 tree loaded_val, tree stored_val, int index)
2169f33b 11822{
3ec11c49 11823 enum built_in_function tmpbase;
11824 gimple_stmt_iterator gsi;
11825 basic_block store_bb = single_succ (load_bb);
11826 location_t loc;
42acab1c 11827 gimple *stmt;
3ec11c49 11828 tree decl, call, type, itype;
3754d046 11829 machine_mode imode;
3ec11c49 11830 bool exchange;
11831
11832 gsi = gsi_last_bb (load_bb);
11833 stmt = gsi_stmt (gsi);
11834 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
11835
11836 /* If the load value is needed, then this isn't a store but an exchange. */
11837 exchange = gimple_omp_atomic_need_value_p (stmt);
11838
11839 gsi = gsi_last_bb (store_bb);
11840 stmt = gsi_stmt (gsi);
11841 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE);
11842 loc = gimple_location (stmt);
11843
11844 /* ??? If the target does not implement atomic_store_optab[mode], and mode
11845 is smaller than word size, then expand_atomic_store assumes that the store
11846 is atomic. We could avoid the builtin entirely in this case. */
11847
11848 tmpbase = (exchange ? BUILT_IN_ATOMIC_EXCHANGE_N : BUILT_IN_ATOMIC_STORE_N);
11849 tmpbase = (enum built_in_function) ((int) tmpbase + index + 1);
11850 decl = builtin_decl_explicit (tmpbase);
11851 if (decl == NULL_TREE)
11852 return false;
11853
11854 type = TREE_TYPE (stored_val);
11855
11856 /* Dig out the type of the function's second argument. */
11857 itype = TREE_TYPE (decl);
11858 itype = TYPE_ARG_TYPES (itype);
11859 itype = TREE_CHAIN (itype);
11860 itype = TREE_VALUE (itype);
11861 imode = TYPE_MODE (itype);
11862
11863 if (exchange && !can_atomic_exchange_p (imode, true))
11864 return false;
11865
11866 if (!useless_type_conversion_p (itype, type))
11867 stored_val = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, stored_val);
11868 call = build_call_expr_loc (loc, decl, 3, addr, stored_val,
bc7bff74 11869 build_int_cst (NULL,
11870 gimple_omp_atomic_seq_cst_p (stmt)
11871 ? MEMMODEL_SEQ_CST
11872 : MEMMODEL_RELAXED));
3ec11c49 11873 if (exchange)
11874 {
11875 if (!useless_type_conversion_p (type, itype))
11876 call = build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
11877 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
11878 }
11879
11880 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
11881 gsi_remove (&gsi, true);
11882
11883 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
11884 gsi = gsi_last_bb (load_bb);
11885 gsi_remove (&gsi, true);
11886
11887 if (gimple_in_ssa_p (cfun))
11888 update_ssa (TODO_update_ssa_no_phi);
11889
11890 return true;
2169f33b 11891}
11892
cb7f680b 11893/* A subroutine of expand_omp_atomic. Attempt to implement the atomic
1cd6e20d 11894 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
cb7f680b 11895 size of the data type, and thus usable to find the index of the builtin
11896 decl. Returns false if the expression is not of the proper form. */
11897
11898static bool
11899expand_omp_atomic_fetch_op (basic_block load_bb,
11900 tree addr, tree loaded_val,
11901 tree stored_val, int index)
11902{
b9a16870 11903 enum built_in_function oldbase, newbase, tmpbase;
cb7f680b 11904 tree decl, itype, call;
2169f33b 11905 tree lhs, rhs;
cb7f680b 11906 basic_block store_bb = single_succ (load_bb);
75a70cf9 11907 gimple_stmt_iterator gsi;
42acab1c 11908 gimple *stmt;
389dd41b 11909 location_t loc;
1cd6e20d 11910 enum tree_code code;
2169f33b 11911 bool need_old, need_new;
3754d046 11912 machine_mode imode;
bc7bff74 11913 bool seq_cst;
cb7f680b 11914
11915 /* We expect to find the following sequences:
48e1416a 11916
cb7f680b 11917 load_bb:
75a70cf9 11918 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
cb7f680b 11919
11920 store_bb:
11921 val = tmp OP something; (or: something OP tmp)
48e1416a 11922 GIMPLE_OMP_STORE (val)
cb7f680b 11923
48e1416a 11924 ???FIXME: Allow a more flexible sequence.
cb7f680b 11925 Perhaps use data flow to pick the statements.
48e1416a 11926
cb7f680b 11927 */
11928
75a70cf9 11929 gsi = gsi_after_labels (store_bb);
11930 stmt = gsi_stmt (gsi);
389dd41b 11931 loc = gimple_location (stmt);
75a70cf9 11932 if (!is_gimple_assign (stmt))
cb7f680b 11933 return false;
75a70cf9 11934 gsi_next (&gsi);
11935 if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE)
cb7f680b 11936 return false;
2169f33b 11937 need_new = gimple_omp_atomic_need_value_p (gsi_stmt (gsi));
11938 need_old = gimple_omp_atomic_need_value_p (last_stmt (load_bb));
bc7bff74 11939 seq_cst = gimple_omp_atomic_seq_cst_p (last_stmt (load_bb));
2169f33b 11940 gcc_checking_assert (!need_old || !need_new);
cb7f680b 11941
75a70cf9 11942 if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
cb7f680b 11943 return false;
11944
cb7f680b 11945 /* Check for one of the supported fetch-op operations. */
1cd6e20d 11946 code = gimple_assign_rhs_code (stmt);
11947 switch (code)
cb7f680b 11948 {
11949 case PLUS_EXPR:
11950 case POINTER_PLUS_EXPR:
1cd6e20d 11951 oldbase = BUILT_IN_ATOMIC_FETCH_ADD_N;
11952 newbase = BUILT_IN_ATOMIC_ADD_FETCH_N;
cb7f680b 11953 break;
11954 case MINUS_EXPR:
1cd6e20d 11955 oldbase = BUILT_IN_ATOMIC_FETCH_SUB_N;
11956 newbase = BUILT_IN_ATOMIC_SUB_FETCH_N;
cb7f680b 11957 break;
11958 case BIT_AND_EXPR:
1cd6e20d 11959 oldbase = BUILT_IN_ATOMIC_FETCH_AND_N;
11960 newbase = BUILT_IN_ATOMIC_AND_FETCH_N;
cb7f680b 11961 break;
11962 case BIT_IOR_EXPR:
1cd6e20d 11963 oldbase = BUILT_IN_ATOMIC_FETCH_OR_N;
11964 newbase = BUILT_IN_ATOMIC_OR_FETCH_N;
cb7f680b 11965 break;
11966 case BIT_XOR_EXPR:
1cd6e20d 11967 oldbase = BUILT_IN_ATOMIC_FETCH_XOR_N;
11968 newbase = BUILT_IN_ATOMIC_XOR_FETCH_N;
cb7f680b 11969 break;
11970 default:
11971 return false;
11972 }
1cd6e20d 11973
cb7f680b 11974 /* Make sure the expression is of the proper form. */
75a70cf9 11975 if (operand_equal_p (gimple_assign_rhs1 (stmt), loaded_val, 0))
11976 rhs = gimple_assign_rhs2 (stmt);
11977 else if (commutative_tree_code (gimple_assign_rhs_code (stmt))
11978 && operand_equal_p (gimple_assign_rhs2 (stmt), loaded_val, 0))
11979 rhs = gimple_assign_rhs1 (stmt);
cb7f680b 11980 else
11981 return false;
11982
b9a16870 11983 tmpbase = ((enum built_in_function)
11984 ((need_new ? newbase : oldbase) + index + 1));
11985 decl = builtin_decl_explicit (tmpbase);
0f94f46b 11986 if (decl == NULL_TREE)
11987 return false;
cb7f680b 11988 itype = TREE_TYPE (TREE_TYPE (decl));
1cd6e20d 11989 imode = TYPE_MODE (itype);
cb7f680b 11990
1cd6e20d 11991 /* We could test all of the various optabs involved, but the fact of the
11992 matter is that (with the exception of i486 vs i586 and xadd) all targets
11993 that support any atomic operaton optab also implements compare-and-swap.
11994 Let optabs.c take care of expanding any compare-and-swap loop. */
29139cdc 11995 if (!can_compare_and_swap_p (imode, true))
cb7f680b 11996 return false;
11997
75a70cf9 11998 gsi = gsi_last_bb (load_bb);
11999 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
1cd6e20d 12000
12001 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
12002 It only requires that the operation happen atomically. Thus we can
12003 use the RELAXED memory model. */
12004 call = build_call_expr_loc (loc, decl, 3, addr,
12005 fold_convert_loc (loc, itype, rhs),
bc7bff74 12006 build_int_cst (NULL,
12007 seq_cst ? MEMMODEL_SEQ_CST
12008 : MEMMODEL_RELAXED));
1cd6e20d 12009
2169f33b 12010 if (need_old || need_new)
12011 {
12012 lhs = need_old ? loaded_val : stored_val;
12013 call = fold_convert_loc (loc, TREE_TYPE (lhs), call);
12014 call = build2_loc (loc, MODIFY_EXPR, void_type_node, lhs, call);
12015 }
12016 else
12017 call = fold_convert_loc (loc, void_type_node, call);
75a70cf9 12018 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
12019 gsi_remove (&gsi, true);
cb7f680b 12020
75a70cf9 12021 gsi = gsi_last_bb (store_bb);
12022 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
12023 gsi_remove (&gsi, true);
12024 gsi = gsi_last_bb (store_bb);
12025 gsi_remove (&gsi, true);
cb7f680b 12026
12027 if (gimple_in_ssa_p (cfun))
12028 update_ssa (TODO_update_ssa_no_phi);
12029
12030 return true;
12031}
12032
12033/* A subroutine of expand_omp_atomic. Implement the atomic operation as:
12034
12035 oldval = *addr;
12036 repeat:
12037 newval = rhs; // with oldval replacing *addr in rhs
12038 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
12039 if (oldval != newval)
12040 goto repeat;
12041
12042 INDEX is log2 of the size of the data type, and thus usable to find the
12043 index of the builtin decl. */
12044
12045static bool
12046expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
12047 tree addr, tree loaded_val, tree stored_val,
12048 int index)
12049{
790368c5 12050 tree loadedi, storedi, initial, new_storedi, old_vali;
cb7f680b 12051 tree type, itype, cmpxchg, iaddr;
75a70cf9 12052 gimple_stmt_iterator si;
cb7f680b 12053 basic_block loop_header = single_succ (load_bb);
42acab1c 12054 gimple *phi, *stmt;
cb7f680b 12055 edge e;
b9a16870 12056 enum built_in_function fncode;
cb7f680b 12057
1cd6e20d 12058 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
12059 order to use the RELAXED memory model effectively. */
b9a16870 12060 fncode = (enum built_in_function)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
12061 + index + 1);
12062 cmpxchg = builtin_decl_explicit (fncode);
0f94f46b 12063 if (cmpxchg == NULL_TREE)
12064 return false;
cb7f680b 12065 type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
12066 itype = TREE_TYPE (TREE_TYPE (cmpxchg));
12067
29139cdc 12068 if (!can_compare_and_swap_p (TYPE_MODE (itype), true))
cb7f680b 12069 return false;
12070
75a70cf9 12071 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
12072 si = gsi_last_bb (load_bb);
12073 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
12074
790368c5 12075 /* For floating-point values, we'll need to view-convert them to integers
12076 so that we can perform the atomic compare and swap. Simplify the
12077 following code by always setting up the "i"ntegral variables. */
12078 if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
12079 {
75a70cf9 12080 tree iaddr_val;
12081
072f7ab1 12082 iaddr = create_tmp_reg (build_pointer_type_for_mode (itype, ptr_mode,
f9e245b2 12083 true));
75a70cf9 12084 iaddr_val
12085 = force_gimple_operand_gsi (&si,
12086 fold_convert (TREE_TYPE (iaddr), addr),
12087 false, NULL_TREE, true, GSI_SAME_STMT);
12088 stmt = gimple_build_assign (iaddr, iaddr_val);
12089 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
f9e245b2 12090 loadedi = create_tmp_var (itype);
790368c5 12091 if (gimple_in_ssa_p (cfun))
f9e245b2 12092 loadedi = make_ssa_name (loadedi);
790368c5 12093 }
12094 else
12095 {
12096 iaddr = addr;
12097 loadedi = loaded_val;
12098 }
75a70cf9 12099
2ed72821 12100 fncode = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
12101 tree loaddecl = builtin_decl_explicit (fncode);
12102 if (loaddecl)
12103 initial
12104 = fold_convert (TREE_TYPE (TREE_TYPE (iaddr)),
12105 build_call_expr (loaddecl, 2, iaddr,
12106 build_int_cst (NULL_TREE,
12107 MEMMODEL_RELAXED)));
12108 else
12109 initial = build2 (MEM_REF, TREE_TYPE (TREE_TYPE (iaddr)), iaddr,
12110 build_int_cst (TREE_TYPE (iaddr), 0));
12111
182cf5a9 12112 initial
2ed72821 12113 = force_gimple_operand_gsi (&si, initial, true, NULL_TREE, true,
12114 GSI_SAME_STMT);
790368c5 12115
12116 /* Move the value to the LOADEDI temporary. */
cb7f680b 12117 if (gimple_in_ssa_p (cfun))
12118 {
75a70cf9 12119 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header)));
790368c5 12120 phi = create_phi_node (loadedi, loop_header);
cb7f680b 12121 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)),
12122 initial);
12123 }
12124 else
75a70cf9 12125 gsi_insert_before (&si,
12126 gimple_build_assign (loadedi, initial),
12127 GSI_SAME_STMT);
790368c5 12128 if (loadedi != loaded_val)
12129 {
75a70cf9 12130 gimple_stmt_iterator gsi2;
12131 tree x;
790368c5 12132
12133 x = build1 (VIEW_CONVERT_EXPR, type, loadedi);
75a70cf9 12134 gsi2 = gsi_start_bb (loop_header);
790368c5 12135 if (gimple_in_ssa_p (cfun))
12136 {
1a91d914 12137 gassign *stmt;
75a70cf9 12138 x = force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
12139 true, GSI_SAME_STMT);
12140 stmt = gimple_build_assign (loaded_val, x);
12141 gsi_insert_before (&gsi2, stmt, GSI_SAME_STMT);
790368c5 12142 }
12143 else
12144 {
75a70cf9 12145 x = build2 (MODIFY_EXPR, TREE_TYPE (loaded_val), loaded_val, x);
12146 force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
12147 true, GSI_SAME_STMT);
790368c5 12148 }
12149 }
75a70cf9 12150 gsi_remove (&si, true);
cb7f680b 12151
75a70cf9 12152 si = gsi_last_bb (store_bb);
12153 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
cb7f680b 12154
790368c5 12155 if (iaddr == addr)
12156 storedi = stored_val;
cb7f680b 12157 else
790368c5 12158 storedi =
75a70cf9 12159 force_gimple_operand_gsi (&si,
790368c5 12160 build1 (VIEW_CONVERT_EXPR, itype,
12161 stored_val), true, NULL_TREE, true,
75a70cf9 12162 GSI_SAME_STMT);
cb7f680b 12163
12164 /* Build the compare&swap statement. */
12165 new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi);
75a70cf9 12166 new_storedi = force_gimple_operand_gsi (&si,
87f9ffa4 12167 fold_convert (TREE_TYPE (loadedi),
12168 new_storedi),
cb7f680b 12169 true, NULL_TREE,
75a70cf9 12170 true, GSI_SAME_STMT);
cb7f680b 12171
12172 if (gimple_in_ssa_p (cfun))
12173 old_vali = loadedi;
12174 else
12175 {
f9e245b2 12176 old_vali = create_tmp_var (TREE_TYPE (loadedi));
75a70cf9 12177 stmt = gimple_build_assign (old_vali, loadedi);
12178 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
cb7f680b 12179
75a70cf9 12180 stmt = gimple_build_assign (loadedi, new_storedi);
12181 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
cb7f680b 12182 }
12183
12184 /* Note that we always perform the comparison as an integer, even for
48e1416a 12185 floating point. This allows the atomic operation to properly
cb7f680b 12186 succeed even with NaNs and -0.0. */
75a70cf9 12187 stmt = gimple_build_cond_empty
12188 (build2 (NE_EXPR, boolean_type_node,
12189 new_storedi, old_vali));
12190 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
cb7f680b 12191
12192 /* Update cfg. */
12193 e = single_succ_edge (store_bb);
12194 e->flags &= ~EDGE_FALLTHRU;
12195 e->flags |= EDGE_FALSE_VALUE;
12196
12197 e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE);
12198
790368c5 12199 /* Copy the new value to loadedi (we already did that before the condition
cb7f680b 12200 if we are not in SSA). */
12201 if (gimple_in_ssa_p (cfun))
12202 {
75a70cf9 12203 phi = gimple_seq_first_stmt (phi_nodes (loop_header));
790368c5 12204 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), new_storedi);
cb7f680b 12205 }
12206
75a70cf9 12207 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
12208 gsi_remove (&si, true);
cb7f680b 12209
04c2922b 12210 struct loop *loop = alloc_loop ();
12211 loop->header = loop_header;
5f037457 12212 loop->latch = store_bb;
04c2922b 12213 add_loop (loop, loop_header->loop_father);
12214
cb7f680b 12215 if (gimple_in_ssa_p (cfun))
12216 update_ssa (TODO_update_ssa_no_phi);
12217
12218 return true;
12219}
12220
12221/* A subroutine of expand_omp_atomic. Implement the atomic operation as:
12222
12223 GOMP_atomic_start ();
12224 *addr = rhs;
12225 GOMP_atomic_end ();
12226
12227 The result is not globally atomic, but works so long as all parallel
12228 references are within #pragma omp atomic directives. According to
12229 responses received from omp@openmp.org, appears to be within spec.
12230 Which makes sense, since that's how several other compilers handle
48e1416a 12231 this situation as well.
75a70cf9 12232 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
12233 expanding. STORED_VAL is the operand of the matching
12234 GIMPLE_OMP_ATOMIC_STORE.
cb7f680b 12235
48e1416a 12236 We replace
12237 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
cb7f680b 12238 loaded_val = *addr;
12239
12240 and replace
3ec11c49 12241 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
48e1416a 12242 *addr = stored_val;
cb7f680b 12243*/
12244
12245static bool
12246expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
12247 tree addr, tree loaded_val, tree stored_val)
12248{
75a70cf9 12249 gimple_stmt_iterator si;
1a91d914 12250 gassign *stmt;
cb7f680b 12251 tree t;
12252
75a70cf9 12253 si = gsi_last_bb (load_bb);
12254 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
cb7f680b 12255
b9a16870 12256 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
414c3a2c 12257 t = build_call_expr (t, 0);
75a70cf9 12258 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
cb7f680b 12259
182cf5a9 12260 stmt = gimple_build_assign (loaded_val, build_simple_mem_ref (addr));
75a70cf9 12261 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
12262 gsi_remove (&si, true);
cb7f680b 12263
75a70cf9 12264 si = gsi_last_bb (store_bb);
12265 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
cb7f680b 12266
182cf5a9 12267 stmt = gimple_build_assign (build_simple_mem_ref (unshare_expr (addr)),
12268 stored_val);
75a70cf9 12269 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
cb7f680b 12270
b9a16870 12271 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
414c3a2c 12272 t = build_call_expr (t, 0);
75a70cf9 12273 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
12274 gsi_remove (&si, true);
cb7f680b 12275
12276 if (gimple_in_ssa_p (cfun))
12277 update_ssa (TODO_update_ssa_no_phi);
12278 return true;
12279}
12280
48e1416a 12281/* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
12282 using expand_omp_atomic_fetch_op. If it failed, we try to
cb7f680b 12283 call expand_omp_atomic_pipeline, and if it fails too, the
12284 ultimate fallback is wrapping the operation in a mutex
48e1416a 12285 (expand_omp_atomic_mutex). REGION is the atomic region built
12286 by build_omp_regions_1(). */
cb7f680b 12287
12288static void
12289expand_omp_atomic (struct omp_region *region)
12290{
12291 basic_block load_bb = region->entry, store_bb = region->exit;
1a91d914 12292 gomp_atomic_load *load = as_a <gomp_atomic_load *> (last_stmt (load_bb));
12293 gomp_atomic_store *store = as_a <gomp_atomic_store *> (last_stmt (store_bb));
75a70cf9 12294 tree loaded_val = gimple_omp_atomic_load_lhs (load);
12295 tree addr = gimple_omp_atomic_load_rhs (load);
12296 tree stored_val = gimple_omp_atomic_store_val (store);
cb7f680b 12297 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
12298 HOST_WIDE_INT index;
12299
12300 /* Make sure the type is one of the supported sizes. */
e913b5cd 12301 index = tree_to_uhwi (TYPE_SIZE_UNIT (type));
cb7f680b 12302 index = exact_log2 (index);
12303 if (index >= 0 && index <= 4)
12304 {
12305 unsigned int align = TYPE_ALIGN_UNIT (type);
12306
12307 /* __sync builtins require strict data alignment. */
dcf7024c 12308 if (exact_log2 (align) >= index)
cb7f680b 12309 {
3ec11c49 12310 /* Atomic load. */
2169f33b 12311 if (loaded_val == stored_val
12312 && (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
12313 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
12314 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
3ec11c49 12315 && expand_omp_atomic_load (load_bb, addr, loaded_val, index))
2169f33b 12316 return;
12317
3ec11c49 12318 /* Atomic store. */
2169f33b 12319 if ((GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
12320 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
12321 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
12322 && store_bb == single_succ (load_bb)
12323 && first_stmt (store_bb) == store
3ec11c49 12324 && expand_omp_atomic_store (load_bb, addr, loaded_val,
12325 stored_val, index))
2169f33b 12326 return;
12327
cb7f680b 12328 /* When possible, use specialized atomic update functions. */
12329 if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
3ec11c49 12330 && store_bb == single_succ (load_bb)
12331 && expand_omp_atomic_fetch_op (load_bb, addr,
12332 loaded_val, stored_val, index))
12333 return;
cb7f680b 12334
12335 /* If we don't have specialized __sync builtins, try and implement
12336 as a compare and swap loop. */
12337 if (expand_omp_atomic_pipeline (load_bb, store_bb, addr,
12338 loaded_val, stored_val, index))
12339 return;
12340 }
12341 }
12342
12343 /* The ultimate fallback is wrapping the operation in a mutex. */
12344 expand_omp_atomic_mutex (load_bb, store_bb, addr, loaded_val, stored_val);
12345}
12346
1e8e9920 12347
f69b8a4c 12348/* Encode an oacc launch argument. This matches the GOMP_LAUNCH_PACK
e561d5e1 12349 macro on gomp-constants.h. We do not check for overflow. */
12350
12351static tree
12352oacc_launch_pack (unsigned code, tree device, unsigned op)
12353{
12354 tree res;
12355
12356 res = build_int_cst (unsigned_type_node, GOMP_LAUNCH_PACK (code, 0, op));
12357 if (device)
12358 {
12359 device = fold_build2 (LSHIFT_EXPR, unsigned_type_node,
12360 device, build_int_cst (unsigned_type_node,
12361 GOMP_LAUNCH_DEVICE_SHIFT));
12362 res = fold_build2 (BIT_IOR_EXPR, unsigned_type_node, res, device);
12363 }
12364 return res;
12365}
12366
12367/* Look for compute grid dimension clauses and convert to an attribute
12368 attached to FN. This permits the target-side code to (a) massage
12369 the dimensions, (b) emit that data and (c) optimize. Non-constant
12370 dimensions are pushed onto ARGS.
12371
12372 The attribute value is a TREE_LIST. A set of dimensions is
12373 represented as a list of INTEGER_CST. Those that are runtime
f69b8a4c 12374 exprs are represented as an INTEGER_CST of zero.
e561d5e1 12375
12376 TOOO. Normally the attribute will just contain a single such list. If
12377 however it contains a list of lists, this will represent the use of
12378 device_type. Each member of the outer list is an assoc list of
12379 dimensions, keyed by the device type. The first entry will be the
12380 default. Well, that's the plan. */
12381
12382#define OACC_FN_ATTRIB "oacc function"
12383
12384/* Replace any existing oacc fn attribute with updated dimensions. */
12385
12386void
12387replace_oacc_fn_attrib (tree fn, tree dims)
12388{
12389 tree ident = get_identifier (OACC_FN_ATTRIB);
12390 tree attribs = DECL_ATTRIBUTES (fn);
12391
12392 /* If we happen to be present as the first attrib, drop it. */
12393 if (attribs && TREE_PURPOSE (attribs) == ident)
12394 attribs = TREE_CHAIN (attribs);
12395 DECL_ATTRIBUTES (fn) = tree_cons (ident, dims, attribs);
12396}
12397
12398/* Scan CLAUSES for launch dimensions and attach them to the oacc
12399 function attribute. Push any that are non-constant onto the ARGS
12400 list, along with an appropriate GOMP_LAUNCH_DIM tag. */
12401
12402static void
12403set_oacc_fn_attrib (tree fn, tree clauses, vec<tree> *args)
12404{
12405 /* Must match GOMP_DIM ordering. */
12406 static const omp_clause_code ids[]
12407 = { OMP_CLAUSE_NUM_GANGS, OMP_CLAUSE_NUM_WORKERS,
12408 OMP_CLAUSE_VECTOR_LENGTH };
12409 unsigned ix;
12410 tree dims[GOMP_DIM_MAX];
12411 tree attr = NULL_TREE;
12412 unsigned non_const = 0;
12413
12414 for (ix = GOMP_DIM_MAX; ix--;)
12415 {
12416 tree clause = find_omp_clause (clauses, ids[ix]);
12417 tree dim = NULL_TREE;
12418
12419 if (clause)
12420 dim = OMP_CLAUSE_EXPR (clause, ids[ix]);
12421 dims[ix] = dim;
12422 if (dim && TREE_CODE (dim) != INTEGER_CST)
12423 {
12424 dim = integer_zero_node;
12425 non_const |= GOMP_DIM_MASK (ix);
12426 }
12427 attr = tree_cons (NULL_TREE, dim, attr);
12428 }
12429
12430 replace_oacc_fn_attrib (fn, attr);
12431
12432 if (non_const)
12433 {
12434 /* Push a dynamic argument set. */
12435 args->safe_push (oacc_launch_pack (GOMP_LAUNCH_DIM,
12436 NULL_TREE, non_const));
12437 for (unsigned ix = 0; ix != GOMP_DIM_MAX; ix++)
12438 if (non_const & GOMP_DIM_MASK (ix))
12439 args->safe_push (dims[ix]);
12440 }
12441}
12442
a1b7fe4b 12443/* Process the routine's dimension clauess to generate an attribute
12444 value. Issue diagnostics as appropriate. We default to SEQ
12445 (OpenACC 2.5 clarifies this). All dimensions have a size of zero
12446 (dynamic). TREE_PURPOSE is set to indicate whether that dimension
12447 can have a loop partitioned on it. non-zero indicates
12448 yes, zero indicates no. By construction once a non-zero has been
12449 reached, further inner dimensions must also be non-zero. We set
12450 TREE_VALUE to zero for the dimensions that may be partitioned and
12451 1 for the other ones -- if a loop is (erroneously) spawned at
12452 an outer level, we don't want to try and partition it. */
12453
12454tree
12455build_oacc_routine_dims (tree clauses)
12456{
12457 /* Must match GOMP_DIM ordering. */
12458 static const omp_clause_code ids[] =
12459 {OMP_CLAUSE_GANG, OMP_CLAUSE_WORKER, OMP_CLAUSE_VECTOR, OMP_CLAUSE_SEQ};
12460 int ix;
12461 int level = -1;
12462
12463 for (; clauses; clauses = OMP_CLAUSE_CHAIN (clauses))
12464 for (ix = GOMP_DIM_MAX + 1; ix--;)
12465 if (OMP_CLAUSE_CODE (clauses) == ids[ix])
12466 {
12467 if (level >= 0)
12468 error_at (OMP_CLAUSE_LOCATION (clauses),
12469 "multiple loop axes specified for routine");
12470 level = ix;
12471 break;
12472 }
12473
12474 /* Default to SEQ. */
12475 if (level < 0)
12476 level = GOMP_DIM_MAX;
12477
12478 tree dims = NULL_TREE;
12479
12480 for (ix = GOMP_DIM_MAX; ix--;)
12481 dims = tree_cons (build_int_cst (boolean_type_node, ix >= level),
12482 build_int_cst (integer_type_node, ix < level), dims);
12483
12484 return dims;
12485}
12486
e561d5e1 12487/* Retrieve the oacc function attrib and return it. Non-oacc
12488 functions will return NULL. */
12489
12490tree
12491get_oacc_fn_attrib (tree fn)
12492{
12493 return lookup_attribute (OACC_FN_ATTRIB, DECL_ATTRIBUTES (fn));
12494}
12495
e1037942 12496/* Extract an oacc execution dimension from FN. FN must be an
12497 offloaded function or routine that has already had its execution
12498 dimensions lowered to the target-specific values. */
12499
12500int
12501get_oacc_fn_dim_size (tree fn, int axis)
12502{
12503 tree attrs = get_oacc_fn_attrib (fn);
12504
12505 gcc_assert (axis < GOMP_DIM_MAX);
12506
12507 tree dims = TREE_VALUE (attrs);
12508 while (axis--)
12509 dims = TREE_CHAIN (dims);
12510
12511 int size = TREE_INT_CST_LOW (TREE_VALUE (dims));
12512
12513 return size;
12514}
12515
12516/* Extract the dimension axis from an IFN_GOACC_DIM_POS or
12517 IFN_GOACC_DIM_SIZE call. */
12518
12519int
12520get_oacc_ifn_dim_arg (const gimple *stmt)
12521{
12522 gcc_checking_assert (gimple_call_internal_fn (stmt) == IFN_GOACC_DIM_SIZE
12523 || gimple_call_internal_fn (stmt) == IFN_GOACC_DIM_POS);
12524 tree arg = gimple_call_arg (stmt, 0);
12525 HOST_WIDE_INT axis = TREE_INT_CST_LOW (arg);
12526
12527 gcc_checking_assert (axis >= 0 && axis < GOMP_DIM_MAX);
12528 return (int) axis;
12529}
12530
1a40f20b 12531/* Mark the loops inside the kernels region starting at REGION_ENTRY and ending
12532 at REGION_EXIT. */
12533
12534static void
12535mark_loops_in_oacc_kernels_region (basic_block region_entry,
12536 basic_block region_exit)
12537{
12538 struct loop *outer = region_entry->loop_father;
12539 gcc_assert (region_exit == NULL || outer == region_exit->loop_father);
12540
12541 /* Don't parallelize the kernels region if it contains more than one outer
12542 loop. */
12543 unsigned int nr_outer_loops = 0;
12544 struct loop *single_outer;
12545 for (struct loop *loop = outer->inner; loop != NULL; loop = loop->next)
12546 {
12547 gcc_assert (loop_outer (loop) == outer);
12548
12549 if (!dominated_by_p (CDI_DOMINATORS, loop->header, region_entry))
12550 continue;
12551
12552 if (region_exit != NULL
12553 && dominated_by_p (CDI_DOMINATORS, loop->header, region_exit))
12554 continue;
12555
12556 nr_outer_loops++;
12557 single_outer = loop;
12558 }
12559 if (nr_outer_loops != 1)
12560 return;
12561
12562 for (struct loop *loop = single_outer->inner; loop != NULL; loop = loop->inner)
12563 if (loop->next)
12564 return;
12565
12566 /* Mark the loops in the region. */
12567 for (struct loop *loop = single_outer; loop != NULL; loop = loop->inner)
12568 loop->in_oacc_kernels_region = true;
12569}
12570
ca4c3545 12571/* Expand the GIMPLE_OMP_TARGET starting at REGION. */
773c5ba7 12572
12573static void
bc7bff74 12574expand_omp_target (struct omp_region *region)
773c5ba7 12575{
bc7bff74 12576 basic_block entry_bb, exit_bb, new_bb;
ca4c3545 12577 struct function *child_cfun;
12578 tree child_fn, block, t;
bc7bff74 12579 gimple_stmt_iterator gsi;
1a91d914 12580 gomp_target *entry_stmt;
42acab1c 12581 gimple *stmt;
bc7bff74 12582 edge e;
ca4c3545 12583 bool offloaded, data_region;
bc7bff74 12584
1a91d914 12585 entry_stmt = as_a <gomp_target *> (last_stmt (region->entry));
bc7bff74 12586 new_bb = region->entry;
ca4c3545 12587
12588 offloaded = is_gimple_omp_offloaded (entry_stmt);
12589 switch (gimple_omp_target_kind (entry_stmt))
12590 {
e561d5e1 12591 case GF_OMP_TARGET_KIND_REGION:
12592 case GF_OMP_TARGET_KIND_UPDATE:
43895be5 12593 case GF_OMP_TARGET_KIND_ENTER_DATA:
12594 case GF_OMP_TARGET_KIND_EXIT_DATA:
12595 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
12596 case GF_OMP_TARGET_KIND_OACC_KERNELS:
ca4c3545 12597 case GF_OMP_TARGET_KIND_OACC_UPDATE:
12598 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
2fc5e987 12599 case GF_OMP_TARGET_KIND_OACC_DECLARE:
ca4c3545 12600 data_region = false;
12601 break;
12602 case GF_OMP_TARGET_KIND_DATA:
12603 case GF_OMP_TARGET_KIND_OACC_DATA:
571b3486 12604 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
ca4c3545 12605 data_region = true;
12606 break;
12607 default:
12608 gcc_unreachable ();
12609 }
12610
12611 child_fn = NULL_TREE;
12612 child_cfun = NULL;
12613 if (offloaded)
bc7bff74 12614 {
12615 child_fn = gimple_omp_target_child_fn (entry_stmt);
12616 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
12617 }
12618
ca4c3545 12619 /* Supported by expand_omp_taskreg, but not here. */
12620 if (child_cfun != NULL)
12621 gcc_checking_assert (!child_cfun->cfg);
12622 gcc_checking_assert (!gimple_in_ssa_p (cfun));
12623
bc7bff74 12624 entry_bb = region->entry;
12625 exit_bb = region->exit;
12626
1a40f20b 12627 if (gimple_omp_target_kind (entry_stmt) == GF_OMP_TARGET_KIND_OACC_KERNELS)
12628 mark_loops_in_oacc_kernels_region (region->entry, region->exit);
12629
ca4c3545 12630 if (offloaded)
bc7bff74 12631 {
12632 unsigned srcidx, dstidx, num;
12633
ca4c3545 12634 /* If the offloading region needs data sent from the parent
bc7bff74 12635 function, then the very first statement (except possible
ca4c3545 12636 tree profile counter updates) of the offloading body
bc7bff74 12637 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
12638 &.OMP_DATA_O is passed as an argument to the child function,
12639 we need to replace it with the argument as seen by the child
12640 function.
12641
12642 In most cases, this will end up being the identity assignment
ca4c3545 12643 .OMP_DATA_I = .OMP_DATA_I. However, if the offloading body had
bc7bff74 12644 a function call that has been inlined, the original PARM_DECL
12645 .OMP_DATA_I may have been converted into a different local
12646 variable. In which case, we need to keep the assignment. */
ca4c3545 12647 tree data_arg = gimple_omp_target_data_arg (entry_stmt);
12648 if (data_arg)
bc7bff74 12649 {
12650 basic_block entry_succ_bb = single_succ (entry_bb);
12651 gimple_stmt_iterator gsi;
12652 tree arg;
42acab1c 12653 gimple *tgtcopy_stmt = NULL;
ca4c3545 12654 tree sender = TREE_VEC_ELT (data_arg, 0);
bc7bff74 12655
12656 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
12657 {
12658 gcc_assert (!gsi_end_p (gsi));
12659 stmt = gsi_stmt (gsi);
12660 if (gimple_code (stmt) != GIMPLE_ASSIGN)
12661 continue;
12662
12663 if (gimple_num_ops (stmt) == 2)
12664 {
12665 tree arg = gimple_assign_rhs1 (stmt);
12666
12667 /* We're ignoring the subcode because we're
12668 effectively doing a STRIP_NOPS. */
12669
12670 if (TREE_CODE (arg) == ADDR_EXPR
12671 && TREE_OPERAND (arg, 0) == sender)
12672 {
12673 tgtcopy_stmt = stmt;
12674 break;
12675 }
12676 }
12677 }
12678
12679 gcc_assert (tgtcopy_stmt != NULL);
12680 arg = DECL_ARGUMENTS (child_fn);
12681
12682 gcc_assert (gimple_assign_lhs (tgtcopy_stmt) == arg);
12683 gsi_remove (&gsi, true);
12684 }
12685
12686 /* Declare local variables needed in CHILD_CFUN. */
12687 block = DECL_INITIAL (child_fn);
12688 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
ca4c3545 12689 /* The gimplifier could record temporaries in the offloading block
bc7bff74 12690 rather than in containing function's local_decls chain,
12691 which would mean cgraph missed finalizing them. Do it now. */
12692 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
12693 if (TREE_CODE (t) == VAR_DECL
12694 && TREE_STATIC (t)
12695 && !DECL_EXTERNAL (t))
97221fd7 12696 varpool_node::finalize_decl (t);
bc7bff74 12697 DECL_SAVED_TREE (child_fn) = NULL;
12698 /* We'll create a CFG for child_fn, so no gimple body is needed. */
12699 gimple_set_body (child_fn, NULL);
12700 TREE_USED (block) = 1;
12701
12702 /* Reset DECL_CONTEXT on function arguments. */
12703 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
12704 DECL_CONTEXT (t) = child_fn;
12705
ca4c3545 12706 /* Split ENTRY_BB at GIMPLE_*,
bc7bff74 12707 so that it can be moved to the child function. */
12708 gsi = gsi_last_bb (entry_bb);
12709 stmt = gsi_stmt (gsi);
ca4c3545 12710 gcc_assert (stmt
12711 && gimple_code (stmt) == gimple_code (entry_stmt));
bc7bff74 12712 e = split_block (entry_bb, stmt);
923635e7 12713 gsi_remove (&gsi, true);
bc7bff74 12714 entry_bb = e->dest;
12715 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
12716
12717 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
12718 if (exit_bb)
12719 {
12720 gsi = gsi_last_bb (exit_bb);
12721 gcc_assert (!gsi_end_p (gsi)
12722 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
12723 stmt = gimple_build_return (NULL);
12724 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
12725 gsi_remove (&gsi, true);
12726 }
12727
ca4c3545 12728 /* Move the offloading region into CHILD_CFUN. */
bc7bff74 12729
12730 block = gimple_block (entry_stmt);
12731
12732 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
12733 if (exit_bb)
12734 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
12735 /* When the OMP expansion process cannot guarantee an up-to-date
12736 loop tree arrange for the child function to fixup loops. */
12737 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
12738 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
12739
12740 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
12741 num = vec_safe_length (child_cfun->local_decls);
12742 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
12743 {
12744 t = (*child_cfun->local_decls)[srcidx];
12745 if (DECL_CONTEXT (t) == cfun->decl)
12746 continue;
12747 if (srcidx != dstidx)
12748 (*child_cfun->local_decls)[dstidx] = t;
12749 dstidx++;
12750 }
12751 if (dstidx != num)
12752 vec_safe_truncate (child_cfun->local_decls, dstidx);
12753
12754 /* Inform the callgraph about the new function. */
613f2c38 12755 child_cfun->curr_properties = cfun->curr_properties;
12756 child_cfun->has_simduid_loops |= cfun->has_simduid_loops;
12757 child_cfun->has_force_vectorize_loops |= cfun->has_force_vectorize_loops;
6a77ed3d 12758 cgraph_node *node = cgraph_node::get_create (child_fn);
12759 node->parallelized_function = 1;
415d1b9a 12760 cgraph_node::add_new_function (child_fn, true);
bc7bff74 12761
dccabdd1 12762 /* Add the new function to the offload table. */
5f3001a9 12763 if (ENABLE_OFFLOADING)
12764 vec_safe_push (offload_funcs, child_fn);
dccabdd1 12765
9561765e 12766 bool need_asm = DECL_ASSEMBLER_NAME_SET_P (current_function_decl)
12767 && !DECL_ASSEMBLER_NAME_SET_P (child_fn);
12768
bc7bff74 12769 /* Fix the callgraph edges for child_cfun. Those for cfun will be
12770 fixed in a following pass. */
12771 push_cfun (child_cfun);
9561765e 12772 if (need_asm)
12773 assign_assembler_name_if_neeeded (child_fn);
35ee1c66 12774 cgraph_edge::rebuild_edges ();
bc7bff74 12775
b0c5e347 12776 /* Prevent IPA from removing child_fn as unreachable, since there are no
12777 refs from the parent function to child_fn in offload LTO mode. */
5f3001a9 12778 if (ENABLE_OFFLOADING)
12779 cgraph_node::get (child_fn)->mark_force_output ();
b0c5e347 12780
bc7bff74 12781 /* Some EH regions might become dead, see PR34608. If
12782 pass_cleanup_cfg isn't the first pass to happen with the
12783 new child, these dead EH edges might cause problems.
12784 Clean them up now. */
12785 if (flag_exceptions)
12786 {
12787 basic_block bb;
12788 bool changed = false;
12789
fc00614f 12790 FOR_EACH_BB_FN (bb, cfun)
bc7bff74 12791 changed |= gimple_purge_dead_eh_edges (bb);
12792 if (changed)
12793 cleanup_tree_cfg ();
12794 }
382ecba7 12795 if (flag_checking && !loops_state_satisfies_p (LOOPS_NEED_FIXUP))
86a932e0 12796 verify_loop_structure ();
bc7bff74 12797 pop_cfun ();
9561765e 12798
12799 if (dump_file && !gimple_in_ssa_p (cfun))
12800 {
12801 omp_any_child_fn_dumped = true;
12802 dump_function_header (dump_file, child_fn, dump_flags);
12803 dump_function_to_file (child_fn, dump_file, dump_flags);
12804 }
bc7bff74 12805 }
12806
ca4c3545 12807 /* Emit a library call to launch the offloading region, or do data
bc7bff74 12808 transfers. */
43895be5 12809 tree t1, t2, t3, t4, device, cond, depend, c, clauses;
bc7bff74 12810 enum built_in_function start_ix;
12811 location_t clause_loc;
43895be5 12812 unsigned int flags_i = 0;
bc7bff74 12813
ca4c3545 12814 switch (gimple_omp_target_kind (entry_stmt))
12815 {
12816 case GF_OMP_TARGET_KIND_REGION:
12817 start_ix = BUILT_IN_GOMP_TARGET;
12818 break;
12819 case GF_OMP_TARGET_KIND_DATA:
12820 start_ix = BUILT_IN_GOMP_TARGET_DATA;
12821 break;
12822 case GF_OMP_TARGET_KIND_UPDATE:
12823 start_ix = BUILT_IN_GOMP_TARGET_UPDATE;
12824 break;
43895be5 12825 case GF_OMP_TARGET_KIND_ENTER_DATA:
12826 start_ix = BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA;
12827 break;
12828 case GF_OMP_TARGET_KIND_EXIT_DATA:
12829 start_ix = BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA;
12830 flags_i |= GOMP_TARGET_FLAG_EXIT_DATA;
12831 break;
ca4c3545 12832 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
12833 case GF_OMP_TARGET_KIND_OACC_KERNELS:
12834 start_ix = BUILT_IN_GOACC_PARALLEL;
12835 break;
12836 case GF_OMP_TARGET_KIND_OACC_DATA:
12837 start_ix = BUILT_IN_GOACC_DATA_START;
12838 break;
12839 case GF_OMP_TARGET_KIND_OACC_UPDATE:
12840 start_ix = BUILT_IN_GOACC_UPDATE;
12841 break;
12842 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
12843 start_ix = BUILT_IN_GOACC_ENTER_EXIT_DATA;
12844 break;
2fc5e987 12845 case GF_OMP_TARGET_KIND_OACC_DECLARE:
12846 start_ix = BUILT_IN_GOACC_DECLARE;
12847 break;
571b3486 12848 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
12849 start_ix = BUILT_IN_GOACC_HOST_DATA;
12850 break;
ca4c3545 12851 default:
12852 gcc_unreachable ();
12853 }
bc7bff74 12854
ca4c3545 12855 clauses = gimple_omp_target_clauses (entry_stmt);
bc7bff74 12856
ca4c3545 12857 /* By default, the value of DEVICE is GOMP_DEVICE_ICV (let runtime
12858 library choose) and there is no conditional. */
bc7bff74 12859 cond = NULL_TREE;
ca4c3545 12860 device = build_int_cst (integer_type_node, GOMP_DEVICE_ICV);
bc7bff74 12861
12862 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
12863 if (c)
12864 cond = OMP_CLAUSE_IF_EXPR (c);
12865
12866 c = find_omp_clause (clauses, OMP_CLAUSE_DEVICE);
12867 if (c)
12868 {
ca4c3545 12869 /* Even if we pass it to all library function calls, it is currently only
12870 defined/used for the OpenMP target ones. */
12871 gcc_checking_assert (start_ix == BUILT_IN_GOMP_TARGET
12872 || start_ix == BUILT_IN_GOMP_TARGET_DATA
43895be5 12873 || start_ix == BUILT_IN_GOMP_TARGET_UPDATE
12874 || start_ix == BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA);
ca4c3545 12875
bc7bff74 12876 device = OMP_CLAUSE_DEVICE_ID (c);
12877 clause_loc = OMP_CLAUSE_LOCATION (c);
12878 }
12879 else
12880 clause_loc = gimple_location (entry_stmt);
12881
43895be5 12882 c = find_omp_clause (clauses, OMP_CLAUSE_NOWAIT);
12883 if (c)
12884 flags_i |= GOMP_TARGET_FLAG_NOWAIT;
12885
bc7bff74 12886 /* Ensure 'device' is of the correct type. */
12887 device = fold_convert_loc (clause_loc, integer_type_node, device);
12888
12889 /* If we found the clause 'if (cond)', build
ca4c3545 12890 (cond ? device : GOMP_DEVICE_HOST_FALLBACK). */
bc7bff74 12891 if (cond)
12892 {
12893 cond = gimple_boolify (cond);
12894
12895 basic_block cond_bb, then_bb, else_bb;
12896 edge e;
12897 tree tmp_var;
12898
f9e245b2 12899 tmp_var = create_tmp_var (TREE_TYPE (device));
ca4c3545 12900 if (offloaded)
4302d619 12901 e = split_block_after_labels (new_bb);
ca4c3545 12902 else
bc7bff74 12903 {
12904 gsi = gsi_last_bb (new_bb);
12905 gsi_prev (&gsi);
12906 e = split_block (new_bb, gsi_stmt (gsi));
12907 }
bc7bff74 12908 cond_bb = e->src;
12909 new_bb = e->dest;
12910 remove_edge (e);
12911
12912 then_bb = create_empty_bb (cond_bb);
12913 else_bb = create_empty_bb (then_bb);
12914 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
12915 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
12916
12917 stmt = gimple_build_cond_empty (cond);
12918 gsi = gsi_last_bb (cond_bb);
12919 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
12920
12921 gsi = gsi_start_bb (then_bb);
12922 stmt = gimple_build_assign (tmp_var, device);
12923 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
12924
12925 gsi = gsi_start_bb (else_bb);
12926 stmt = gimple_build_assign (tmp_var,
ca4c3545 12927 build_int_cst (integer_type_node,
12928 GOMP_DEVICE_HOST_FALLBACK));
bc7bff74 12929 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
12930
12931 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
12932 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
b3083327 12933 add_bb_to_loop (then_bb, cond_bb->loop_father);
12934 add_bb_to_loop (else_bb, cond_bb->loop_father);
bc7bff74 12935 make_edge (then_bb, new_bb, EDGE_FALLTHRU);
12936 make_edge (else_bb, new_bb, EDGE_FALLTHRU);
12937
12938 device = tmp_var;
12939 }
12940
12941 gsi = gsi_last_bb (new_bb);
12942 t = gimple_omp_target_data_arg (entry_stmt);
12943 if (t == NULL)
12944 {
12945 t1 = size_zero_node;
12946 t2 = build_zero_cst (ptr_type_node);
12947 t3 = t2;
12948 t4 = t2;
12949 }
12950 else
12951 {
12952 t1 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t, 1))));
12953 t1 = size_binop (PLUS_EXPR, t1, size_int (1));
12954 t2 = build_fold_addr_expr (TREE_VEC_ELT (t, 0));
12955 t3 = build_fold_addr_expr (TREE_VEC_ELT (t, 1));
12956 t4 = build_fold_addr_expr (TREE_VEC_ELT (t, 2));
12957 }
12958
42acab1c 12959 gimple *g;
e561d5e1 12960 bool tagging = false;
ca4c3545 12961 /* The maximum number used by any start_ix, without varargs. */
02c05c9b 12962 auto_vec<tree, 11> args;
12963 args.quick_push (device);
ca4c3545 12964 if (offloaded)
02c05c9b 12965 args.quick_push (build_fold_addr_expr (child_fn));
02c05c9b 12966 args.quick_push (t1);
12967 args.quick_push (t2);
12968 args.quick_push (t3);
12969 args.quick_push (t4);
ca4c3545 12970 switch (start_ix)
12971 {
12972 case BUILT_IN_GOACC_DATA_START:
2fc5e987 12973 case BUILT_IN_GOACC_DECLARE:
ca4c3545 12974 case BUILT_IN_GOMP_TARGET_DATA:
571b3486 12975 case BUILT_IN_GOACC_HOST_DATA:
43895be5 12976 break;
12977 case BUILT_IN_GOMP_TARGET:
ca4c3545 12978 case BUILT_IN_GOMP_TARGET_UPDATE:
43895be5 12979 case BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA:
12980 args.quick_push (build_int_cst (unsigned_type_node, flags_i));
12981 c = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
12982 if (c)
12983 depend = OMP_CLAUSE_DECL (c);
12984 else
12985 depend = build_int_cst (ptr_type_node, 0);
12986 args.quick_push (depend);
9561765e 12987 if (start_ix == BUILT_IN_GOMP_TARGET)
12988 {
12989 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_TEAMS);
12990 if (c)
12991 {
12992 t = fold_convert (integer_type_node,
12993 OMP_CLAUSE_NUM_TEAMS_EXPR (c));
12994 t = force_gimple_operand_gsi (&gsi, t, true, NULL,
12995 true, GSI_SAME_STMT);
12996 }
12997 else
12998 t = integer_minus_one_node;
12999 args.quick_push (t);
13000 c = find_omp_clause (clauses, OMP_CLAUSE_THREAD_LIMIT);
13001 if (c)
13002 {
13003 t = fold_convert (integer_type_node,
13004 OMP_CLAUSE_THREAD_LIMIT_EXPR (c));
13005 t = force_gimple_operand_gsi (&gsi, t, true, NULL,
13006 true, GSI_SAME_STMT);
13007 }
13008 else
13009 t = integer_minus_one_node;
13010 args.quick_push (t);
13011 }
ca4c3545 13012 break;
13013 case BUILT_IN_GOACC_PARALLEL:
13014 {
e561d5e1 13015 set_oacc_fn_attrib (child_fn, clauses, &args);
13016 tagging = true;
ca4c3545 13017 }
13018 /* FALLTHRU */
13019 case BUILT_IN_GOACC_ENTER_EXIT_DATA:
13020 case BUILT_IN_GOACC_UPDATE:
13021 {
e561d5e1 13022 tree t_async = NULL_TREE;
13023
13024 /* If present, use the value specified by the respective
ca4c3545 13025 clause, making sure that is of the correct type. */
13026 c = find_omp_clause (clauses, OMP_CLAUSE_ASYNC);
13027 if (c)
13028 t_async = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
13029 integer_type_node,
13030 OMP_CLAUSE_ASYNC_EXPR (c));
e561d5e1 13031 else if (!tagging)
13032 /* Default values for t_async. */
13033 t_async = fold_convert_loc (gimple_location (entry_stmt),
13034 integer_type_node,
13035 build_int_cst (integer_type_node,
13036 GOMP_ASYNC_SYNC));
13037 if (tagging && t_async)
ca4c3545 13038 {
e561d5e1 13039 unsigned HOST_WIDE_INT i_async;
ca4c3545 13040
e561d5e1 13041 if (TREE_CODE (t_async) == INTEGER_CST)
ca4c3545 13042 {
e561d5e1 13043 /* See if we can pack the async arg in to the tag's
13044 operand. */
13045 i_async = TREE_INT_CST_LOW (t_async);
13046
13047 if (i_async < GOMP_LAUNCH_OP_MAX)
13048 t_async = NULL_TREE;
ca4c3545 13049 }
e561d5e1 13050 if (t_async)
13051 i_async = GOMP_LAUNCH_OP_MAX;
13052 args.safe_push (oacc_launch_pack
13053 (GOMP_LAUNCH_ASYNC, NULL_TREE, i_async));
13054 }
13055 if (t_async)
13056 args.safe_push (t_async);
ca4c3545 13057
e561d5e1 13058 /* Save the argument index, and ... */
13059 unsigned t_wait_idx = args.length ();
13060 unsigned num_waits = 0;
13061 c = find_omp_clause (clauses, OMP_CLAUSE_WAIT);
13062 if (!tagging || c)
13063 /* ... push a placeholder. */
13064 args.safe_push (integer_zero_node);
13065
13066 for (; c; c = OMP_CLAUSE_CHAIN (c))
13067 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_WAIT)
13068 {
13069 args.safe_push (fold_convert_loc (OMP_CLAUSE_LOCATION (c),
13070 integer_type_node,
13071 OMP_CLAUSE_WAIT_EXPR (c)));
13072 num_waits++;
13073 }
13074
13075 if (!tagging || num_waits)
13076 {
13077 tree len;
13078
13079 /* Now that we know the number, update the placeholder. */
13080 if (tagging)
13081 len = oacc_launch_pack (GOMP_LAUNCH_WAIT, NULL_TREE, num_waits);
13082 else
13083 len = build_int_cst (integer_type_node, num_waits);
13084 len = fold_convert_loc (gimple_location (entry_stmt),
13085 unsigned_type_node, len);
13086 args[t_wait_idx] = len;
ca4c3545 13087 }
13088 }
13089 break;
13090 default:
13091 gcc_unreachable ();
bc7bff74 13092 }
e561d5e1 13093 if (tagging)
13094 /* Push terminal marker - zero. */
13095 args.safe_push (oacc_launch_pack (0, NULL_TREE, 0));
ca4c3545 13096
02c05c9b 13097 g = gimple_build_call_vec (builtin_decl_explicit (start_ix), args);
bc7bff74 13098 gimple_set_location (g, gimple_location (entry_stmt));
13099 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
ca4c3545 13100 if (!offloaded)
bc7bff74 13101 {
13102 g = gsi_stmt (gsi);
13103 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_TARGET);
13104 gsi_remove (&gsi, true);
13105 }
43895be5 13106 if (data_region && region->exit)
bc7bff74 13107 {
13108 gsi = gsi_last_bb (region->exit);
13109 g = gsi_stmt (gsi);
13110 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_RETURN);
13111 gsi_remove (&gsi, true);
13112 }
13113}
13114
13115
13116/* Expand the parallel region tree rooted at REGION. Expansion
13117 proceeds in depth-first order. Innermost regions are expanded
13118 first. This way, parallel regions that require a new function to
75a70cf9 13119 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
773c5ba7 13120 internal dependencies in their body. */
13121
13122static void
13123expand_omp (struct omp_region *region)
13124{
9561765e 13125 omp_any_child_fn_dumped = false;
773c5ba7 13126 while (region)
13127 {
1d22f541 13128 location_t saved_location;
42acab1c 13129 gimple *inner_stmt = NULL;
1d22f541 13130
d1d5b012 13131 /* First, determine whether this is a combined parallel+workshare
13132 region. */
75a70cf9 13133 if (region->type == GIMPLE_OMP_PARALLEL)
d1d5b012 13134 determine_parallel_type (region);
13135
bc7bff74 13136 if (region->type == GIMPLE_OMP_FOR
13137 && gimple_omp_for_combined_p (last_stmt (region->entry)))
13138 inner_stmt = last_stmt (region->inner->entry);
13139
773c5ba7 13140 if (region->inner)
13141 expand_omp (region->inner);
13142
1d22f541 13143 saved_location = input_location;
75a70cf9 13144 if (gimple_has_location (last_stmt (region->entry)))
13145 input_location = gimple_location (last_stmt (region->entry));
1d22f541 13146
61e47ac8 13147 switch (region->type)
773c5ba7 13148 {
75a70cf9 13149 case GIMPLE_OMP_PARALLEL:
13150 case GIMPLE_OMP_TASK:
fd6481cf 13151 expand_omp_taskreg (region);
13152 break;
13153
75a70cf9 13154 case GIMPLE_OMP_FOR:
bc7bff74 13155 expand_omp_for (region, inner_stmt);
61e47ac8 13156 break;
773c5ba7 13157
75a70cf9 13158 case GIMPLE_OMP_SECTIONS:
61e47ac8 13159 expand_omp_sections (region);
13160 break;
773c5ba7 13161
75a70cf9 13162 case GIMPLE_OMP_SECTION:
61e47ac8 13163 /* Individual omp sections are handled together with their
75a70cf9 13164 parent GIMPLE_OMP_SECTIONS region. */
61e47ac8 13165 break;
773c5ba7 13166
75a70cf9 13167 case GIMPLE_OMP_SINGLE:
61e47ac8 13168 expand_omp_single (region);
13169 break;
773c5ba7 13170
43895be5 13171 case GIMPLE_OMP_ORDERED:
13172 {
13173 gomp_ordered *ord_stmt
13174 = as_a <gomp_ordered *> (last_stmt (region->entry));
13175 if (find_omp_clause (gimple_omp_ordered_clauses (ord_stmt),
13176 OMP_CLAUSE_DEPEND))
13177 {
13178 /* We'll expand these when expanding corresponding
13179 worksharing region with ordered(n) clause. */
13180 gcc_assert (region->outer
13181 && region->outer->type == GIMPLE_OMP_FOR);
13182 region->ord_stmt = ord_stmt;
13183 break;
13184 }
13185 }
13186 /* FALLTHRU */
75a70cf9 13187 case GIMPLE_OMP_MASTER:
bc7bff74 13188 case GIMPLE_OMP_TASKGROUP:
75a70cf9 13189 case GIMPLE_OMP_CRITICAL:
bc7bff74 13190 case GIMPLE_OMP_TEAMS:
61e47ac8 13191 expand_omp_synch (region);
13192 break;
773c5ba7 13193
75a70cf9 13194 case GIMPLE_OMP_ATOMIC_LOAD:
cb7f680b 13195 expand_omp_atomic (region);
13196 break;
13197
bc7bff74 13198 case GIMPLE_OMP_TARGET:
13199 expand_omp_target (region);
13200 break;
13201
61e47ac8 13202 default:
13203 gcc_unreachable ();
13204 }
cc5982dc 13205
1d22f541 13206 input_location = saved_location;
773c5ba7 13207 region = region->next;
13208 }
9561765e 13209 if (omp_any_child_fn_dumped)
13210 {
13211 if (dump_file)
13212 dump_function_header (dump_file, current_function_decl, dump_flags);
13213 omp_any_child_fn_dumped = false;
13214 }
773c5ba7 13215}
13216
13217
13218/* Helper for build_omp_regions. Scan the dominator tree starting at
28c92cbb 13219 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
13220 true, the function ends once a single tree is built (otherwise, whole
13221 forest of OMP constructs may be built). */
773c5ba7 13222
13223static void
28c92cbb 13224build_omp_regions_1 (basic_block bb, struct omp_region *parent,
13225 bool single_tree)
773c5ba7 13226{
75a70cf9 13227 gimple_stmt_iterator gsi;
42acab1c 13228 gimple *stmt;
773c5ba7 13229 basic_block son;
13230
75a70cf9 13231 gsi = gsi_last_bb (bb);
13232 if (!gsi_end_p (gsi) && is_gimple_omp (gsi_stmt (gsi)))
773c5ba7 13233 {
13234 struct omp_region *region;
75a70cf9 13235 enum gimple_code code;
773c5ba7 13236
75a70cf9 13237 stmt = gsi_stmt (gsi);
13238 code = gimple_code (stmt);
13239 if (code == GIMPLE_OMP_RETURN)
773c5ba7 13240 {
13241 /* STMT is the return point out of region PARENT. Mark it
13242 as the exit point and make PARENT the immediately
13243 enclosing region. */
13244 gcc_assert (parent);
13245 region = parent;
61e47ac8 13246 region->exit = bb;
773c5ba7 13247 parent = parent->outer;
773c5ba7 13248 }
75a70cf9 13249 else if (code == GIMPLE_OMP_ATOMIC_STORE)
cb7f680b 13250 {
75a70cf9 13251 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
13252 GIMPLE_OMP_RETURN, but matches with
13253 GIMPLE_OMP_ATOMIC_LOAD. */
cb7f680b 13254 gcc_assert (parent);
75a70cf9 13255 gcc_assert (parent->type == GIMPLE_OMP_ATOMIC_LOAD);
cb7f680b 13256 region = parent;
13257 region->exit = bb;
13258 parent = parent->outer;
13259 }
75a70cf9 13260 else if (code == GIMPLE_OMP_CONTINUE)
61e47ac8 13261 {
13262 gcc_assert (parent);
13263 parent->cont = bb;
13264 }
75a70cf9 13265 else if (code == GIMPLE_OMP_SECTIONS_SWITCH)
ac6e3339 13266 {
75a70cf9 13267 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
13268 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
ac6e3339 13269 }
773c5ba7 13270 else
13271 {
61e47ac8 13272 region = new_omp_region (bb, code, parent);
ca4c3545 13273 /* Otherwise... */
13274 if (code == GIMPLE_OMP_TARGET)
13275 {
13276 switch (gimple_omp_target_kind (stmt))
13277 {
13278 case GF_OMP_TARGET_KIND_REGION:
13279 case GF_OMP_TARGET_KIND_DATA:
13280 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
13281 case GF_OMP_TARGET_KIND_OACC_KERNELS:
13282 case GF_OMP_TARGET_KIND_OACC_DATA:
571b3486 13283 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
ca4c3545 13284 break;
13285 case GF_OMP_TARGET_KIND_UPDATE:
43895be5 13286 case GF_OMP_TARGET_KIND_ENTER_DATA:
13287 case GF_OMP_TARGET_KIND_EXIT_DATA:
ca4c3545 13288 case GF_OMP_TARGET_KIND_OACC_UPDATE:
13289 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
2fc5e987 13290 case GF_OMP_TARGET_KIND_OACC_DECLARE:
ca4c3545 13291 /* ..., other than for those stand-alone directives... */
13292 region = NULL;
13293 break;
13294 default:
13295 gcc_unreachable ();
13296 }
13297 }
43895be5 13298 else if (code == GIMPLE_OMP_ORDERED
13299 && find_omp_clause (gimple_omp_ordered_clauses
13300 (as_a <gomp_ordered *> (stmt)),
13301 OMP_CLAUSE_DEPEND))
13302 /* #pragma omp ordered depend is also just a stand-alone
13303 directive. */
13304 region = NULL;
ca4c3545 13305 /* ..., this directive becomes the parent for a new region. */
13306 if (region)
13307 parent = region;
773c5ba7 13308 }
773c5ba7 13309 }
13310
28c92cbb 13311 if (single_tree && !parent)
13312 return;
13313
773c5ba7 13314 for (son = first_dom_son (CDI_DOMINATORS, bb);
13315 son;
13316 son = next_dom_son (CDI_DOMINATORS, son))
28c92cbb 13317 build_omp_regions_1 (son, parent, single_tree);
13318}
13319
13320/* Builds the tree of OMP regions rooted at ROOT, storing it to
13321 root_omp_region. */
13322
13323static void
13324build_omp_regions_root (basic_block root)
13325{
13326 gcc_assert (root_omp_region == NULL);
13327 build_omp_regions_1 (root, NULL, true);
13328 gcc_assert (root_omp_region != NULL);
773c5ba7 13329}
13330
28c92cbb 13331/* Expands omp construct (and its subconstructs) starting in HEAD. */
13332
13333void
13334omp_expand_local (basic_block head)
13335{
13336 build_omp_regions_root (head);
13337 if (dump_file && (dump_flags & TDF_DETAILS))
13338 {
13339 fprintf (dump_file, "\nOMP region tree\n\n");
13340 dump_omp_region (dump_file, root_omp_region, 0);
13341 fprintf (dump_file, "\n");
13342 }
13343
13344 remove_exit_barriers (root_omp_region);
13345 expand_omp (root_omp_region);
13346
13347 free_omp_regions ();
13348}
773c5ba7 13349
13350/* Scan the CFG and build a tree of OMP regions. Return the root of
13351 the OMP region tree. */
13352
13353static void
13354build_omp_regions (void)
13355{
61e47ac8 13356 gcc_assert (root_omp_region == NULL);
773c5ba7 13357 calculate_dominance_info (CDI_DOMINATORS);
34154e27 13358 build_omp_regions_1 (ENTRY_BLOCK_PTR_FOR_FN (cfun), NULL, false);
773c5ba7 13359}
13360
773c5ba7 13361/* Main entry point for expanding OMP-GIMPLE into runtime calls. */
13362
2a1990e9 13363static unsigned int
773c5ba7 13364execute_expand_omp (void)
13365{
13366 build_omp_regions ();
13367
61e47ac8 13368 if (!root_omp_region)
13369 return 0;
773c5ba7 13370
61e47ac8 13371 if (dump_file)
13372 {
13373 fprintf (dump_file, "\nOMP region tree\n\n");
13374 dump_omp_region (dump_file, root_omp_region, 0);
13375 fprintf (dump_file, "\n");
773c5ba7 13376 }
61e47ac8 13377
13378 remove_exit_barriers (root_omp_region);
13379
13380 expand_omp (root_omp_region);
13381
382ecba7 13382 if (flag_checking && !loops_state_satisfies_p (LOOPS_NEED_FIXUP))
86a932e0 13383 verify_loop_structure ();
61e47ac8 13384 cleanup_tree_cfg ();
13385
13386 free_omp_regions ();
13387
2a1990e9 13388 return 0;
773c5ba7 13389}
13390
79acaae1 13391/* OMP expansion -- the default pass, run before creation of SSA form. */
13392
7620bc82 13393namespace {
13394
13395const pass_data pass_data_expand_omp =
cbe8bda8 13396{
13397 GIMPLE_PASS, /* type */
13398 "ompexp", /* name */
13399 OPTGROUP_NONE, /* optinfo_flags */
cbe8bda8 13400 TV_NONE, /* tv_id */
13401 PROP_gimple_any, /* properties_required */
8917c50b 13402 PROP_gimple_eomp, /* properties_provided */
cbe8bda8 13403 0, /* properties_destroyed */
13404 0, /* todo_flags_start */
13405 0, /* todo_flags_finish */
773c5ba7 13406};
cbe8bda8 13407
7620bc82 13408class pass_expand_omp : public gimple_opt_pass
cbe8bda8 13409{
13410public:
9af5ce0c 13411 pass_expand_omp (gcc::context *ctxt)
13412 : gimple_opt_pass (pass_data_expand_omp, ctxt)
cbe8bda8 13413 {}
13414
13415 /* opt_pass methods: */
8917c50b 13416 virtual unsigned int execute (function *)
31315c24 13417 {
ca4c3545 13418 bool gate = ((flag_cilkplus != 0 || flag_openacc != 0 || flag_openmp != 0
13419 || flag_openmp_simd != 0)
13420 && !seen_error ());
31315c24 13421
8917c50b 13422 /* This pass always runs, to provide PROP_gimple_eomp.
ca4c3545 13423 But often, there is nothing to do. */
8917c50b 13424 if (!gate)
13425 return 0;
13426
13427 return execute_expand_omp ();
13428 }
cbe8bda8 13429
13430}; // class pass_expand_omp
13431
7620bc82 13432} // anon namespace
13433
cbe8bda8 13434gimple_opt_pass *
13435make_pass_expand_omp (gcc::context *ctxt)
13436{
13437 return new pass_expand_omp (ctxt);
13438}
8917c50b 13439
7620bc82 13440namespace {
13441
13442const pass_data pass_data_expand_omp_ssa =
8917c50b 13443{
13444 GIMPLE_PASS, /* type */
13445 "ompexpssa", /* name */
13446 OPTGROUP_NONE, /* optinfo_flags */
13447 TV_NONE, /* tv_id */
13448 PROP_cfg | PROP_ssa, /* properties_required */
13449 PROP_gimple_eomp, /* properties_provided */
13450 0, /* properties_destroyed */
13451 0, /* todo_flags_start */
13452 TODO_cleanup_cfg | TODO_rebuild_alias, /* todo_flags_finish */
13453};
13454
7620bc82 13455class pass_expand_omp_ssa : public gimple_opt_pass
8917c50b 13456{
13457public:
13458 pass_expand_omp_ssa (gcc::context *ctxt)
13459 : gimple_opt_pass (pass_data_expand_omp_ssa, ctxt)
13460 {}
13461
13462 /* opt_pass methods: */
13463 virtual bool gate (function *fun)
13464 {
13465 return !(fun->curr_properties & PROP_gimple_eomp);
13466 }
13467 virtual unsigned int execute (function *) { return execute_expand_omp (); }
e1e1688c 13468 opt_pass * clone () { return new pass_expand_omp_ssa (m_ctxt); }
8917c50b 13469
13470}; // class pass_expand_omp_ssa
13471
7620bc82 13472} // anon namespace
13473
8917c50b 13474gimple_opt_pass *
13475make_pass_expand_omp_ssa (gcc::context *ctxt)
13476{
13477 return new pass_expand_omp_ssa (ctxt);
13478}
773c5ba7 13479\f
ca4c3545 13480/* Routines to lower OMP directives into OMP-GIMPLE. */
13481
bc7bff74 13482/* If ctx is a worksharing context inside of a cancellable parallel
13483 region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
13484 and conditional branch to parallel's cancel_label to handle
13485 cancellation in the implicit barrier. */
13486
13487static void
13488maybe_add_implicit_barrier_cancel (omp_context *ctx, gimple_seq *body)
13489{
42acab1c 13490 gimple *omp_return = gimple_seq_last_stmt (*body);
bc7bff74 13491 gcc_assert (gimple_code (omp_return) == GIMPLE_OMP_RETURN);
13492 if (gimple_omp_return_nowait_p (omp_return))
13493 return;
13494 if (ctx->outer
13495 && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_PARALLEL
13496 && ctx->outer->cancellable)
13497 {
15b28553 13498 tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL);
13499 tree c_bool_type = TREE_TYPE (TREE_TYPE (fndecl));
f9e245b2 13500 tree lhs = create_tmp_var (c_bool_type);
bc7bff74 13501 gimple_omp_return_set_lhs (omp_return, lhs);
13502 tree fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
42acab1c 13503 gimple *g = gimple_build_cond (NE_EXPR, lhs,
15b28553 13504 fold_convert (c_bool_type,
13505 boolean_false_node),
bc7bff74 13506 ctx->outer->cancel_label, fallthru_label);
13507 gimple_seq_add_stmt (body, g);
13508 gimple_seq_add_stmt (body, gimple_build_label (fallthru_label));
13509 }
13510}
13511
75a70cf9 13512/* Lower the OpenMP sections directive in the current statement in GSI_P.
13513 CTX is the enclosing OMP context for the current statement. */
773c5ba7 13514
13515static void
75a70cf9 13516lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
773c5ba7 13517{
75a70cf9 13518 tree block, control;
13519 gimple_stmt_iterator tgsi;
1a91d914 13520 gomp_sections *stmt;
42acab1c 13521 gimple *t;
1a91d914 13522 gbind *new_stmt, *bind;
e3a19533 13523 gimple_seq ilist, dlist, olist, new_body;
773c5ba7 13524
1a91d914 13525 stmt = as_a <gomp_sections *> (gsi_stmt (*gsi_p));
773c5ba7 13526
8a4a28a8 13527 push_gimplify_context ();
773c5ba7 13528
13529 dlist = NULL;
13530 ilist = NULL;
75a70cf9 13531 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
bc7bff74 13532 &ilist, &dlist, ctx, NULL);
773c5ba7 13533
e3a19533 13534 new_body = gimple_omp_body (stmt);
13535 gimple_omp_set_body (stmt, NULL);
13536 tgsi = gsi_start (new_body);
13537 for (; !gsi_end_p (tgsi); gsi_next (&tgsi))
773c5ba7 13538 {
13539 omp_context *sctx;
42acab1c 13540 gimple *sec_start;
773c5ba7 13541
75a70cf9 13542 sec_start = gsi_stmt (tgsi);
773c5ba7 13543 sctx = maybe_lookup_ctx (sec_start);
13544 gcc_assert (sctx);
13545
e3a19533 13546 lower_omp (gimple_omp_body_ptr (sec_start), sctx);
13547 gsi_insert_seq_after (&tgsi, gimple_omp_body (sec_start),
13548 GSI_CONTINUE_LINKING);
75a70cf9 13549 gimple_omp_set_body (sec_start, NULL);
773c5ba7 13550
e3a19533 13551 if (gsi_one_before_end_p (tgsi))
773c5ba7 13552 {
75a70cf9 13553 gimple_seq l = NULL;
13554 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
773c5ba7 13555 &l, ctx);
e3a19533 13556 gsi_insert_seq_after (&tgsi, l, GSI_CONTINUE_LINKING);
75a70cf9 13557 gimple_omp_section_set_last (sec_start);
773c5ba7 13558 }
48e1416a 13559
e3a19533 13560 gsi_insert_after (&tgsi, gimple_build_omp_return (false),
13561 GSI_CONTINUE_LINKING);
773c5ba7 13562 }
1e8e9920 13563
13564 block = make_node (BLOCK);
e3a19533 13565 bind = gimple_build_bind (NULL, new_body, block);
1e8e9920 13566
75a70cf9 13567 olist = NULL;
13568 lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist, ctx);
773c5ba7 13569
1d22f541 13570 block = make_node (BLOCK);
75a70cf9 13571 new_stmt = gimple_build_bind (NULL, NULL, block);
e3a19533 13572 gsi_replace (gsi_p, new_stmt, true);
773c5ba7 13573
1d22f541 13574 pop_gimplify_context (new_stmt);
75a70cf9 13575 gimple_bind_append_vars (new_stmt, ctx->block_vars);
13576 BLOCK_VARS (block) = gimple_bind_vars (bind);
1d22f541 13577 if (BLOCK_VARS (block))
13578 TREE_USED (block) = 1;
13579
75a70cf9 13580 new_body = NULL;
13581 gimple_seq_add_seq (&new_body, ilist);
13582 gimple_seq_add_stmt (&new_body, stmt);
13583 gimple_seq_add_stmt (&new_body, gimple_build_omp_sections_switch ());
13584 gimple_seq_add_stmt (&new_body, bind);
61e47ac8 13585
ac6e3339 13586 control = create_tmp_var (unsigned_type_node, ".section");
75a70cf9 13587 t = gimple_build_omp_continue (control, control);
13588 gimple_omp_sections_set_control (stmt, control);
13589 gimple_seq_add_stmt (&new_body, t);
61e47ac8 13590
75a70cf9 13591 gimple_seq_add_seq (&new_body, olist);
bc7bff74 13592 if (ctx->cancellable)
13593 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
75a70cf9 13594 gimple_seq_add_seq (&new_body, dlist);
773c5ba7 13595
75a70cf9 13596 new_body = maybe_catch_exception (new_body);
aade31a0 13597
75a70cf9 13598 t = gimple_build_omp_return
13599 (!!find_omp_clause (gimple_omp_sections_clauses (stmt),
13600 OMP_CLAUSE_NOWAIT));
13601 gimple_seq_add_stmt (&new_body, t);
bc7bff74 13602 maybe_add_implicit_barrier_cancel (ctx, &new_body);
61e47ac8 13603
75a70cf9 13604 gimple_bind_set_body (new_stmt, new_body);
1e8e9920 13605}
13606
13607
773c5ba7 13608/* A subroutine of lower_omp_single. Expand the simple form of
75a70cf9 13609 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
1e8e9920 13610
13611 if (GOMP_single_start ())
13612 BODY;
13613 [ GOMP_barrier (); ] -> unless 'nowait' is present.
773c5ba7 13614
13615 FIXME. It may be better to delay expanding the logic of this until
13616 pass_expand_omp. The expanded logic may make the job more difficult
13617 to a synchronization analysis pass. */
1e8e9920 13618
13619static void
1a91d914 13620lower_omp_single_simple (gomp_single *single_stmt, gimple_seq *pre_p)
1e8e9920 13621{
e60a6f7b 13622 location_t loc = gimple_location (single_stmt);
13623 tree tlabel = create_artificial_label (loc);
13624 tree flabel = create_artificial_label (loc);
42acab1c 13625 gimple *call, *cond;
75a70cf9 13626 tree lhs, decl;
13627
b9a16870 13628 decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START);
f9e245b2 13629 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)));
75a70cf9 13630 call = gimple_build_call (decl, 0);
13631 gimple_call_set_lhs (call, lhs);
13632 gimple_seq_add_stmt (pre_p, call);
13633
13634 cond = gimple_build_cond (EQ_EXPR, lhs,
389dd41b 13635 fold_convert_loc (loc, TREE_TYPE (lhs),
13636 boolean_true_node),
75a70cf9 13637 tlabel, flabel);
13638 gimple_seq_add_stmt (pre_p, cond);
13639 gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
13640 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
13641 gimple_seq_add_stmt (pre_p, gimple_build_label (flabel));
1e8e9920 13642}
13643
773c5ba7 13644
13645/* A subroutine of lower_omp_single. Expand the simple form of
75a70cf9 13646 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
1e8e9920 13647
13648 #pragma omp single copyprivate (a, b, c)
13649
13650 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
13651
13652 {
13653 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
13654 {
13655 BODY;
13656 copyout.a = a;
13657 copyout.b = b;
13658 copyout.c = c;
13659 GOMP_single_copy_end (&copyout);
13660 }
13661 else
13662 {
13663 a = copyout_p->a;
13664 b = copyout_p->b;
13665 c = copyout_p->c;
13666 }
13667 GOMP_barrier ();
13668 }
773c5ba7 13669
13670 FIXME. It may be better to delay expanding the logic of this until
13671 pass_expand_omp. The expanded logic may make the job more difficult
13672 to a synchronization analysis pass. */
1e8e9920 13673
13674static void
1a91d914 13675lower_omp_single_copy (gomp_single *single_stmt, gimple_seq *pre_p,
13676 omp_context *ctx)
1e8e9920 13677{
b9a16870 13678 tree ptr_type, t, l0, l1, l2, bfn_decl;
75a70cf9 13679 gimple_seq copyin_seq;
e60a6f7b 13680 location_t loc = gimple_location (single_stmt);
1e8e9920 13681
13682 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
13683
13684 ptr_type = build_pointer_type (ctx->record_type);
13685 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
13686
e60a6f7b 13687 l0 = create_artificial_label (loc);
13688 l1 = create_artificial_label (loc);
13689 l2 = create_artificial_label (loc);
1e8e9920 13690
b9a16870 13691 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START);
13692 t = build_call_expr_loc (loc, bfn_decl, 0);
389dd41b 13693 t = fold_convert_loc (loc, ptr_type, t);
75a70cf9 13694 gimplify_assign (ctx->receiver_decl, t, pre_p);
1e8e9920 13695
13696 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
13697 build_int_cst (ptr_type, 0));
13698 t = build3 (COND_EXPR, void_type_node, t,
13699 build_and_jump (&l0), build_and_jump (&l1));
13700 gimplify_and_add (t, pre_p);
13701
75a70cf9 13702 gimple_seq_add_stmt (pre_p, gimple_build_label (l0));
1e8e9920 13703
75a70cf9 13704 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
1e8e9920 13705
13706 copyin_seq = NULL;
75a70cf9 13707 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
1e8e9920 13708 &copyin_seq, ctx);
13709
389dd41b 13710 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
b9a16870 13711 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END);
13712 t = build_call_expr_loc (loc, bfn_decl, 1, t);
1e8e9920 13713 gimplify_and_add (t, pre_p);
13714
13715 t = build_and_jump (&l2);
13716 gimplify_and_add (t, pre_p);
13717
75a70cf9 13718 gimple_seq_add_stmt (pre_p, gimple_build_label (l1));
1e8e9920 13719
75a70cf9 13720 gimple_seq_add_seq (pre_p, copyin_seq);
1e8e9920 13721
75a70cf9 13722 gimple_seq_add_stmt (pre_p, gimple_build_label (l2));
1e8e9920 13723}
13724
773c5ba7 13725
1e8e9920 13726/* Expand code for an OpenMP single directive. */
13727
13728static void
75a70cf9 13729lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
1e8e9920 13730{
75a70cf9 13731 tree block;
42acab1c 13732 gimple *t;
1a91d914 13733 gomp_single *single_stmt = as_a <gomp_single *> (gsi_stmt (*gsi_p));
13734 gbind *bind;
bc7bff74 13735 gimple_seq bind_body, bind_body_tail = NULL, dlist;
1e8e9920 13736
8a4a28a8 13737 push_gimplify_context ();
1e8e9920 13738
e3a19533 13739 block = make_node (BLOCK);
13740 bind = gimple_build_bind (NULL, NULL, block);
13741 gsi_replace (gsi_p, bind, true);
75a70cf9 13742 bind_body = NULL;
e3a19533 13743 dlist = NULL;
75a70cf9 13744 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt),
bc7bff74 13745 &bind_body, &dlist, ctx, NULL);
e3a19533 13746 lower_omp (gimple_omp_body_ptr (single_stmt), ctx);
1e8e9920 13747
75a70cf9 13748 gimple_seq_add_stmt (&bind_body, single_stmt);
1e8e9920 13749
13750 if (ctx->record_type)
75a70cf9 13751 lower_omp_single_copy (single_stmt, &bind_body, ctx);
1e8e9920 13752 else
75a70cf9 13753 lower_omp_single_simple (single_stmt, &bind_body);
13754
13755 gimple_omp_set_body (single_stmt, NULL);
1e8e9920 13756
75a70cf9 13757 gimple_seq_add_seq (&bind_body, dlist);
61e47ac8 13758
75a70cf9 13759 bind_body = maybe_catch_exception (bind_body);
61e47ac8 13760
48e1416a 13761 t = gimple_build_omp_return
75a70cf9 13762 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt),
13763 OMP_CLAUSE_NOWAIT));
bc7bff74 13764 gimple_seq_add_stmt (&bind_body_tail, t);
13765 maybe_add_implicit_barrier_cancel (ctx, &bind_body_tail);
13766 if (ctx->record_type)
13767 {
13768 gimple_stmt_iterator gsi = gsi_start (bind_body_tail);
13769 tree clobber = build_constructor (ctx->record_type, NULL);
13770 TREE_THIS_VOLATILE (clobber) = 1;
13771 gsi_insert_after (&gsi, gimple_build_assign (ctx->sender_decl,
13772 clobber), GSI_SAME_STMT);
13773 }
13774 gimple_seq_add_seq (&bind_body, bind_body_tail);
e3a19533 13775 gimple_bind_set_body (bind, bind_body);
61e47ac8 13776
1e8e9920 13777 pop_gimplify_context (bind);
773c5ba7 13778
75a70cf9 13779 gimple_bind_append_vars (bind, ctx->block_vars);
13780 BLOCK_VARS (block) = ctx->block_vars;
1d22f541 13781 if (BLOCK_VARS (block))
13782 TREE_USED (block) = 1;
1e8e9920 13783}
13784
773c5ba7 13785
1e8e9920 13786/* Expand code for an OpenMP master directive. */
13787
13788static void
75a70cf9 13789lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
1e8e9920 13790{
b9a16870 13791 tree block, lab = NULL, x, bfn_decl;
42acab1c 13792 gimple *stmt = gsi_stmt (*gsi_p);
1a91d914 13793 gbind *bind;
389dd41b 13794 location_t loc = gimple_location (stmt);
75a70cf9 13795 gimple_seq tseq;
1e8e9920 13796
8a4a28a8 13797 push_gimplify_context ();
1e8e9920 13798
13799 block = make_node (BLOCK);
e3a19533 13800 bind = gimple_build_bind (NULL, NULL, block);
13801 gsi_replace (gsi_p, bind, true);
13802 gimple_bind_add_stmt (bind, stmt);
61e47ac8 13803
b9a16870 13804 bfn_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
13805 x = build_call_expr_loc (loc, bfn_decl, 0);
1e8e9920 13806 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
13807 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
75a70cf9 13808 tseq = NULL;
13809 gimplify_and_add (x, &tseq);
13810 gimple_bind_add_seq (bind, tseq);
1e8e9920 13811
e3a19533 13812 lower_omp (gimple_omp_body_ptr (stmt), ctx);
75a70cf9 13813 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
13814 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
13815 gimple_omp_set_body (stmt, NULL);
1e8e9920 13816
75a70cf9 13817 gimple_bind_add_stmt (bind, gimple_build_label (lab));
61e47ac8 13818
75a70cf9 13819 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
61e47ac8 13820
1e8e9920 13821 pop_gimplify_context (bind);
773c5ba7 13822
75a70cf9 13823 gimple_bind_append_vars (bind, ctx->block_vars);
13824 BLOCK_VARS (block) = ctx->block_vars;
1e8e9920 13825}
13826
773c5ba7 13827
bc7bff74 13828/* Expand code for an OpenMP taskgroup directive. */
13829
13830static void
13831lower_omp_taskgroup (gimple_stmt_iterator *gsi_p, omp_context *ctx)
13832{
42acab1c 13833 gimple *stmt = gsi_stmt (*gsi_p);
1a91d914 13834 gcall *x;
13835 gbind *bind;
bc7bff74 13836 tree block = make_node (BLOCK);
13837
13838 bind = gimple_build_bind (NULL, NULL, block);
13839 gsi_replace (gsi_p, bind, true);
13840 gimple_bind_add_stmt (bind, stmt);
13841
13842 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START),
13843 0);
13844 gimple_bind_add_stmt (bind, x);
13845
13846 lower_omp (gimple_omp_body_ptr (stmt), ctx);
13847 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
13848 gimple_omp_set_body (stmt, NULL);
13849
13850 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
13851
13852 gimple_bind_append_vars (bind, ctx->block_vars);
13853 BLOCK_VARS (block) = ctx->block_vars;
13854}
13855
13856
43895be5 13857/* Fold the OMP_ORDERED_CLAUSES for the OMP_ORDERED in STMT if possible. */
13858
13859static void
13860lower_omp_ordered_clauses (gimple_stmt_iterator *gsi_p, gomp_ordered *ord_stmt,
13861 omp_context *ctx)
13862{
13863 struct omp_for_data fd;
13864 if (!ctx->outer || gimple_code (ctx->outer->stmt) != GIMPLE_OMP_FOR)
13865 return;
13866
13867 unsigned int len = gimple_omp_for_collapse (ctx->outer->stmt);
13868 struct omp_for_data_loop *loops = XALLOCAVEC (struct omp_for_data_loop, len);
13869 extract_omp_for_data (as_a <gomp_for *> (ctx->outer->stmt), &fd, loops);
13870 if (!fd.ordered)
13871 return;
13872
13873 tree *list_p = gimple_omp_ordered_clauses_ptr (ord_stmt);
13874 tree c = gimple_omp_ordered_clauses (ord_stmt);
13875 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
13876 && OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK)
13877 {
13878 /* Merge depend clauses from multiple adjacent
13879 #pragma omp ordered depend(sink:...) constructs
13880 into one #pragma omp ordered depend(sink:...), so that
13881 we can optimize them together. */
13882 gimple_stmt_iterator gsi = *gsi_p;
13883 gsi_next (&gsi);
13884 while (!gsi_end_p (gsi))
13885 {
13886 gimple *stmt = gsi_stmt (gsi);
13887 if (is_gimple_debug (stmt)
13888 || gimple_code (stmt) == GIMPLE_NOP)
13889 {
13890 gsi_next (&gsi);
13891 continue;
13892 }
13893 if (gimple_code (stmt) != GIMPLE_OMP_ORDERED)
13894 break;
13895 gomp_ordered *ord_stmt2 = as_a <gomp_ordered *> (stmt);
13896 c = gimple_omp_ordered_clauses (ord_stmt2);
13897 if (c == NULL_TREE
13898 || OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND
13899 || OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_SINK)
13900 break;
13901 while (*list_p)
13902 list_p = &OMP_CLAUSE_CHAIN (*list_p);
13903 *list_p = c;
13904 gsi_remove (&gsi, true);
13905 }
13906 }
13907
13908 /* Canonicalize sink dependence clauses into one folded clause if
13909 possible.
13910
13911 The basic algorithm is to create a sink vector whose first
13912 element is the GCD of all the first elements, and whose remaining
13913 elements are the minimum of the subsequent columns.
13914
13915 We ignore dependence vectors whose first element is zero because
13916 such dependencies are known to be executed by the same thread.
13917
13918 We take into account the direction of the loop, so a minimum
13919 becomes a maximum if the loop is iterating forwards. We also
13920 ignore sink clauses where the loop direction is unknown, or where
13921 the offsets are clearly invalid because they are not a multiple
13922 of the loop increment.
13923
13924 For example:
13925
13926 #pragma omp for ordered(2)
13927 for (i=0; i < N; ++i)
13928 for (j=0; j < M; ++j)
13929 {
13930 #pragma omp ordered \
13931 depend(sink:i-8,j-2) \
13932 depend(sink:i,j-1) \ // Completely ignored because i+0.
13933 depend(sink:i-4,j-3) \
13934 depend(sink:i-6,j-4)
13935 #pragma omp ordered depend(source)
13936 }
13937
13938 Folded clause is:
13939
13940 depend(sink:-gcd(8,4,6),-min(2,3,4))
13941 -or-
13942 depend(sink:-2,-2)
13943 */
13944
13945 /* FIXME: Computing GCD's where the first element is zero is
13946 non-trivial in the presence of collapsed loops. Do this later. */
13947 if (fd.collapse > 1)
13948 return;
13949
13950 wide_int *folded_deps = XALLOCAVEC (wide_int, 2 * len - 1);
13951 memset (folded_deps, 0, sizeof (*folded_deps) * (2 * len - 1));
13952 tree folded_dep = NULL_TREE;
13953 /* TRUE if the first dimension's offset is negative. */
13954 bool neg_offset_p = false;
13955
13956 list_p = gimple_omp_ordered_clauses_ptr (ord_stmt);
13957 unsigned int i;
13958 while ((c = *list_p) != NULL)
13959 {
13960 bool remove = false;
13961
13962 gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND);
13963 if (OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_SINK)
13964 goto next_ordered_clause;
13965
13966 tree vec;
13967 for (vec = OMP_CLAUSE_DECL (c), i = 0;
13968 vec && TREE_CODE (vec) == TREE_LIST;
13969 vec = TREE_CHAIN (vec), ++i)
13970 {
13971 gcc_assert (i < len);
13972
13973 /* extract_omp_for_data has canonicalized the condition. */
13974 gcc_assert (fd.loops[i].cond_code == LT_EXPR
13975 || fd.loops[i].cond_code == GT_EXPR);
13976 bool forward = fd.loops[i].cond_code == LT_EXPR;
13977 bool maybe_lexically_later = true;
13978
13979 /* While the committee makes up its mind, bail if we have any
13980 non-constant steps. */
13981 if (TREE_CODE (fd.loops[i].step) != INTEGER_CST)
13982 goto lower_omp_ordered_ret;
13983
13984 tree itype = TREE_TYPE (TREE_VALUE (vec));
13985 if (POINTER_TYPE_P (itype))
13986 itype = sizetype;
13987 wide_int offset = wide_int::from (TREE_PURPOSE (vec),
13988 TYPE_PRECISION (itype),
13989 TYPE_SIGN (itype));
13990
13991 /* Ignore invalid offsets that are not multiples of the step. */
13992 if (!wi::multiple_of_p
13993 (wi::abs (offset), wi::abs ((wide_int) fd.loops[i].step),
13994 UNSIGNED))
13995 {
13996 warning_at (OMP_CLAUSE_LOCATION (c), 0,
13997 "ignoring sink clause with offset that is not "
13998 "a multiple of the loop step");
13999 remove = true;
14000 goto next_ordered_clause;
14001 }
14002
14003 /* Calculate the first dimension. The first dimension of
14004 the folded dependency vector is the GCD of the first
14005 elements, while ignoring any first elements whose offset
14006 is 0. */
14007 if (i == 0)
14008 {
14009 /* Ignore dependence vectors whose first dimension is 0. */
14010 if (offset == 0)
14011 {
14012 remove = true;
14013 goto next_ordered_clause;
14014 }
14015 else
14016 {
14017 if (!TYPE_UNSIGNED (itype) && (forward ^ wi::neg_p (offset)))
14018 {
14019 error_at (OMP_CLAUSE_LOCATION (c),
14020 "first offset must be in opposite direction "
14021 "of loop iterations");
14022 goto lower_omp_ordered_ret;
14023 }
14024 if (forward)
14025 offset = -offset;
14026 neg_offset_p = forward;
14027 /* Initialize the first time around. */
14028 if (folded_dep == NULL_TREE)
14029 {
14030 folded_dep = c;
14031 folded_deps[0] = offset;
14032 }
14033 else
14034 folded_deps[0] = wi::gcd (folded_deps[0],
14035 offset, UNSIGNED);
14036 }
14037 }
14038 /* Calculate minimum for the remaining dimensions. */
14039 else
14040 {
14041 folded_deps[len + i - 1] = offset;
14042 if (folded_dep == c)
14043 folded_deps[i] = offset;
14044 else if (maybe_lexically_later
14045 && !wi::eq_p (folded_deps[i], offset))
14046 {
14047 if (forward ^ wi::gts_p (folded_deps[i], offset))
14048 {
14049 unsigned int j;
14050 folded_dep = c;
14051 for (j = 1; j <= i; j++)
14052 folded_deps[j] = folded_deps[len + j - 1];
14053 }
14054 else
14055 maybe_lexically_later = false;
14056 }
14057 }
14058 }
14059 gcc_assert (i == len);
14060
14061 remove = true;
14062
14063 next_ordered_clause:
14064 if (remove)
14065 *list_p = OMP_CLAUSE_CHAIN (c);
14066 else
14067 list_p = &OMP_CLAUSE_CHAIN (c);
14068 }
14069
14070 if (folded_dep)
14071 {
14072 if (neg_offset_p)
14073 folded_deps[0] = -folded_deps[0];
14074
14075 tree itype = TREE_TYPE (TREE_VALUE (OMP_CLAUSE_DECL (folded_dep)));
14076 if (POINTER_TYPE_P (itype))
14077 itype = sizetype;
14078
14079 TREE_PURPOSE (OMP_CLAUSE_DECL (folded_dep))
14080 = wide_int_to_tree (itype, folded_deps[0]);
14081 OMP_CLAUSE_CHAIN (folded_dep) = gimple_omp_ordered_clauses (ord_stmt);
14082 *gimple_omp_ordered_clauses_ptr (ord_stmt) = folded_dep;
14083 }
14084
14085 lower_omp_ordered_ret:
14086
14087 /* Ordered without clauses is #pragma omp threads, while we want
14088 a nop instead if we remove all clauses. */
14089 if (gimple_omp_ordered_clauses (ord_stmt) == NULL_TREE)
14090 gsi_replace (gsi_p, gimple_build_nop (), true);
14091}
14092
14093
1e8e9920 14094/* Expand code for an OpenMP ordered directive. */
14095
14096static void
75a70cf9 14097lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
1e8e9920 14098{
75a70cf9 14099 tree block;
42acab1c 14100 gimple *stmt = gsi_stmt (*gsi_p);
43895be5 14101 gomp_ordered *ord_stmt = as_a <gomp_ordered *> (stmt);
1a91d914 14102 gcall *x;
14103 gbind *bind;
a9833286 14104 bool simd = find_omp_clause (gimple_omp_ordered_clauses (ord_stmt),
14105 OMP_CLAUSE_SIMD);
14106 bool threads = find_omp_clause (gimple_omp_ordered_clauses (ord_stmt),
14107 OMP_CLAUSE_THREADS);
43895be5 14108
14109 if (find_omp_clause (gimple_omp_ordered_clauses (ord_stmt),
14110 OMP_CLAUSE_DEPEND))
14111 {
14112 /* FIXME: This is needs to be moved to the expansion to verify various
14113 conditions only testable on cfg with dominators computed, and also
14114 all the depend clauses to be merged still might need to be available
14115 for the runtime checks. */
14116 if (0)
14117 lower_omp_ordered_clauses (gsi_p, ord_stmt, ctx);
14118 return;
14119 }
1e8e9920 14120
8a4a28a8 14121 push_gimplify_context ();
1e8e9920 14122
14123 block = make_node (BLOCK);
e3a19533 14124 bind = gimple_build_bind (NULL, NULL, block);
14125 gsi_replace (gsi_p, bind, true);
14126 gimple_bind_add_stmt (bind, stmt);
61e47ac8 14127
43895be5 14128 if (simd)
14129 {
a9833286 14130 x = gimple_build_call_internal (IFN_GOMP_SIMD_ORDERED_START, 1,
14131 build_int_cst (NULL_TREE, threads));
43895be5 14132 cfun->has_simduid_loops = true;
14133 }
14134 else
14135 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START),
14136 0);
75a70cf9 14137 gimple_bind_add_stmt (bind, x);
1e8e9920 14138
e3a19533 14139 lower_omp (gimple_omp_body_ptr (stmt), ctx);
75a70cf9 14140 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
14141 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
14142 gimple_omp_set_body (stmt, NULL);
1e8e9920 14143
43895be5 14144 if (simd)
a9833286 14145 x = gimple_build_call_internal (IFN_GOMP_SIMD_ORDERED_END, 1,
14146 build_int_cst (NULL_TREE, threads));
43895be5 14147 else
14148 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END),
14149 0);
75a70cf9 14150 gimple_bind_add_stmt (bind, x);
61e47ac8 14151
75a70cf9 14152 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
61e47ac8 14153
1e8e9920 14154 pop_gimplify_context (bind);
773c5ba7 14155
75a70cf9 14156 gimple_bind_append_vars (bind, ctx->block_vars);
14157 BLOCK_VARS (block) = gimple_bind_vars (bind);
1e8e9920 14158}
14159
1e8e9920 14160
75a70cf9 14161/* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
1e8e9920 14162 substitution of a couple of function calls. But in the NAMED case,
14163 requires that languages coordinate a symbol name. It is therefore
14164 best put here in common code. */
14165
d4786b13 14166static GTY(()) hash_map<tree, tree> *critical_name_mutexes;
1e8e9920 14167
14168static void
75a70cf9 14169lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
1e8e9920 14170{
75a70cf9 14171 tree block;
14172 tree name, lock, unlock;
1a91d914 14173 gomp_critical *stmt = as_a <gomp_critical *> (gsi_stmt (*gsi_p));
14174 gbind *bind;
389dd41b 14175 location_t loc = gimple_location (stmt);
75a70cf9 14176 gimple_seq tbody;
1e8e9920 14177
75a70cf9 14178 name = gimple_omp_critical_name (stmt);
1e8e9920 14179 if (name)
14180 {
c2f47e15 14181 tree decl;
1e8e9920 14182
14183 if (!critical_name_mutexes)
d4786b13 14184 critical_name_mutexes = hash_map<tree, tree>::create_ggc (10);
1e8e9920 14185
d4786b13 14186 tree *n = critical_name_mutexes->get (name);
1e8e9920 14187 if (n == NULL)
14188 {
14189 char *new_str;
14190
f9e245b2 14191 decl = create_tmp_var_raw (ptr_type_node);
1e8e9920 14192
14193 new_str = ACONCAT ((".gomp_critical_user_",
14194 IDENTIFIER_POINTER (name), NULL));
14195 DECL_NAME (decl) = get_identifier (new_str);
14196 TREE_PUBLIC (decl) = 1;
14197 TREE_STATIC (decl) = 1;
14198 DECL_COMMON (decl) = 1;
14199 DECL_ARTIFICIAL (decl) = 1;
14200 DECL_IGNORED_P (decl) = 1;
b0c5e347 14201
97221fd7 14202 varpool_node::finalize_decl (decl);
1e8e9920 14203
d4786b13 14204 critical_name_mutexes->put (name, decl);
1e8e9920 14205 }
14206 else
d4786b13 14207 decl = *n;
1e8e9920 14208
ca4c3545 14209 /* If '#pragma omp critical' is inside offloaded region or
351fb0ce 14210 inside function marked as offloadable, the symbol must be
14211 marked as offloadable too. */
14212 omp_context *octx;
14213 if (cgraph_node::get (current_function_decl)->offloadable)
14214 varpool_node::get_create (decl)->offloadable = 1;
14215 else
14216 for (octx = ctx->outer; octx; octx = octx->outer)
ca4c3545 14217 if (is_gimple_omp_offloaded (octx->stmt))
351fb0ce 14218 {
14219 varpool_node::get_create (decl)->offloadable = 1;
14220 break;
14221 }
14222
b9a16870 14223 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START);
389dd41b 14224 lock = build_call_expr_loc (loc, lock, 1, build_fold_addr_expr_loc (loc, decl));
1e8e9920 14225
b9a16870 14226 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END);
389dd41b 14227 unlock = build_call_expr_loc (loc, unlock, 1,
14228 build_fold_addr_expr_loc (loc, decl));
1e8e9920 14229 }
14230 else
14231 {
b9a16870 14232 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START);
389dd41b 14233 lock = build_call_expr_loc (loc, lock, 0);
1e8e9920 14234
b9a16870 14235 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END);
389dd41b 14236 unlock = build_call_expr_loc (loc, unlock, 0);
1e8e9920 14237 }
14238
8a4a28a8 14239 push_gimplify_context ();
1e8e9920 14240
14241 block = make_node (BLOCK);
e3a19533 14242 bind = gimple_build_bind (NULL, NULL, block);
14243 gsi_replace (gsi_p, bind, true);
14244 gimple_bind_add_stmt (bind, stmt);
61e47ac8 14245
75a70cf9 14246 tbody = gimple_bind_body (bind);
14247 gimplify_and_add (lock, &tbody);
14248 gimple_bind_set_body (bind, tbody);
1e8e9920 14249
e3a19533 14250 lower_omp (gimple_omp_body_ptr (stmt), ctx);
75a70cf9 14251 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
14252 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
14253 gimple_omp_set_body (stmt, NULL);
1e8e9920 14254
75a70cf9 14255 tbody = gimple_bind_body (bind);
14256 gimplify_and_add (unlock, &tbody);
14257 gimple_bind_set_body (bind, tbody);
61e47ac8 14258
75a70cf9 14259 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
1e8e9920 14260
14261 pop_gimplify_context (bind);
75a70cf9 14262 gimple_bind_append_vars (bind, ctx->block_vars);
14263 BLOCK_VARS (block) = gimple_bind_vars (bind);
773c5ba7 14264}
14265
14266
14267/* A subroutine of lower_omp_for. Generate code to emit the predicate
14268 for a lastprivate clause. Given a loop control predicate of (V
14269 cond N2), we gate the clause on (!(V cond N2)). The lowered form
1e4afe3c 14270 is appended to *DLIST, iterator initialization is appended to
14271 *BODY_P. */
773c5ba7 14272
14273static void
75a70cf9 14274lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
14275 gimple_seq *dlist, struct omp_context *ctx)
773c5ba7 14276{
75a70cf9 14277 tree clauses, cond, vinit;
773c5ba7 14278 enum tree_code cond_code;
75a70cf9 14279 gimple_seq stmts;
48e1416a 14280
fd6481cf 14281 cond_code = fd->loop.cond_code;
773c5ba7 14282 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
14283
14284 /* When possible, use a strict equality expression. This can let VRP
14285 type optimizations deduce the value and remove a copy. */
e913b5cd 14286 if (tree_fits_shwi_p (fd->loop.step))
773c5ba7 14287 {
e913b5cd 14288 HOST_WIDE_INT step = tree_to_shwi (fd->loop.step);
773c5ba7 14289 if (step == 1 || step == -1)
14290 cond_code = EQ_EXPR;
14291 }
14292
d7729e26 14293 tree n2 = fd->loop.n2;
14294 if (fd->collapse > 1
14295 && TREE_CODE (n2) != INTEGER_CST
43895be5 14296 && gimple_omp_for_combined_into_p (fd->for_stmt))
d7729e26 14297 {
9561765e 14298 struct omp_context *taskreg_ctx = NULL;
43895be5 14299 if (gimple_code (ctx->outer->stmt) == GIMPLE_OMP_FOR)
14300 {
14301 gomp_for *gfor = as_a <gomp_for *> (ctx->outer->stmt);
9561765e 14302 if (gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_FOR
14303 || gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_DISTRIBUTE)
43895be5 14304 {
9561765e 14305 if (gimple_omp_for_combined_into_p (gfor))
14306 {
14307 gcc_assert (ctx->outer->outer
14308 && is_parallel_ctx (ctx->outer->outer));
14309 taskreg_ctx = ctx->outer->outer;
14310 }
14311 else
14312 {
14313 struct omp_for_data outer_fd;
14314 extract_omp_for_data (gfor, &outer_fd, NULL);
14315 n2 = fold_convert (TREE_TYPE (n2), outer_fd.loop.n2);
14316 }
43895be5 14317 }
14318 else if (gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_TASKLOOP)
9561765e 14319 taskreg_ctx = ctx->outer->outer;
43895be5 14320 }
9561765e 14321 else if (is_taskreg_ctx (ctx->outer))
14322 taskreg_ctx = ctx->outer;
14323 if (taskreg_ctx)
d7729e26 14324 {
43895be5 14325 int i;
14326 tree innerc
9561765e 14327 = find_omp_clause (gimple_omp_taskreg_clauses (taskreg_ctx->stmt),
43895be5 14328 OMP_CLAUSE__LOOPTEMP_);
14329 gcc_assert (innerc);
14330 for (i = 0; i < fd->collapse; i++)
14331 {
14332 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
14333 OMP_CLAUSE__LOOPTEMP_);
14334 gcc_assert (innerc);
14335 }
14336 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
14337 OMP_CLAUSE__LOOPTEMP_);
14338 if (innerc)
14339 n2 = fold_convert (TREE_TYPE (n2),
14340 lookup_decl (OMP_CLAUSE_DECL (innerc),
9561765e 14341 taskreg_ctx));
d7729e26 14342 }
14343 }
14344 cond = build2 (cond_code, boolean_type_node, fd->loop.v, n2);
773c5ba7 14345
75a70cf9 14346 clauses = gimple_omp_for_clauses (fd->for_stmt);
1e4afe3c 14347 stmts = NULL;
14348 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
75a70cf9 14349 if (!gimple_seq_empty_p (stmts))
1e4afe3c 14350 {
75a70cf9 14351 gimple_seq_add_seq (&stmts, *dlist);
fd6481cf 14352 *dlist = stmts;
1e4afe3c 14353
14354 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
fd6481cf 14355 vinit = fd->loop.n1;
1e4afe3c 14356 if (cond_code == EQ_EXPR
e913b5cd 14357 && tree_fits_shwi_p (fd->loop.n2)
fd6481cf 14358 && ! integer_zerop (fd->loop.n2))
14359 vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0);
3d483a94 14360 else
14361 vinit = unshare_expr (vinit);
1e4afe3c 14362
14363 /* Initialize the iterator variable, so that threads that don't execute
14364 any iterations don't execute the lastprivate clauses by accident. */
75a70cf9 14365 gimplify_assign (fd->loop.v, vinit, body_p);
1e4afe3c 14366 }
773c5ba7 14367}
14368
14369
ca4c3545 14370/* Lower code for an OMP loop directive. */
773c5ba7 14371
14372static void
75a70cf9 14373lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
773c5ba7 14374{
75a70cf9 14375 tree *rhs_p, block;
bc7bff74 14376 struct omp_for_data fd, *fdp = NULL;
1a91d914 14377 gomp_for *stmt = as_a <gomp_for *> (gsi_stmt (*gsi_p));
14378 gbind *new_stmt;
f018d957 14379 gimple_seq omp_for_body, body, dlist;
a8e785ba 14380 gimple_seq oacc_head = NULL, oacc_tail = NULL;
75a70cf9 14381 size_t i;
773c5ba7 14382
8a4a28a8 14383 push_gimplify_context ();
773c5ba7 14384
e3a19533 14385 lower_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
773c5ba7 14386
1d22f541 14387 block = make_node (BLOCK);
75a70cf9 14388 new_stmt = gimple_build_bind (NULL, NULL, block);
e3a19533 14389 /* Replace at gsi right away, so that 'stmt' is no member
47ae02b7 14390 of a sequence anymore as we're going to add to a different
e3a19533 14391 one below. */
14392 gsi_replace (gsi_p, new_stmt, true);
1d22f541 14393
773c5ba7 14394 /* Move declaration of temporaries in the loop body before we make
14395 it go away. */
75a70cf9 14396 omp_for_body = gimple_omp_body (stmt);
14397 if (!gimple_seq_empty_p (omp_for_body)
14398 && gimple_code (gimple_seq_first_stmt (omp_for_body)) == GIMPLE_BIND)
14399 {
1a91d914 14400 gbind *inner_bind
14401 = as_a <gbind *> (gimple_seq_first_stmt (omp_for_body));
6d5a8d89 14402 tree vars = gimple_bind_vars (inner_bind);
75a70cf9 14403 gimple_bind_append_vars (new_stmt, vars);
6d5a8d89 14404 /* bind_vars/BLOCK_VARS are being moved to new_stmt/block, don't
14405 keep them on the inner_bind and it's block. */
14406 gimple_bind_set_vars (inner_bind, NULL_TREE);
14407 if (gimple_bind_block (inner_bind))
14408 BLOCK_VARS (gimple_bind_block (inner_bind)) = NULL_TREE;
75a70cf9 14409 }
773c5ba7 14410
bc7bff74 14411 if (gimple_omp_for_combined_into_p (stmt))
14412 {
14413 extract_omp_for_data (stmt, &fd, NULL);
14414 fdp = &fd;
14415
14416 /* We need two temporaries with fd.loop.v type (istart/iend)
14417 and then (fd.collapse - 1) temporaries with the same
14418 type for count2 ... countN-1 vars if not constant. */
14419 size_t count = 2;
14420 tree type = fd.iter_type;
14421 if (fd.collapse > 1
14422 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
14423 count += fd.collapse - 1;
43895be5 14424 bool taskreg_for
14425 = (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR
14426 || gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_TASKLOOP);
bc7bff74 14427 tree outerc = NULL, *pc = gimple_omp_for_clauses_ptr (stmt);
14428 tree clauses = *pc;
43895be5 14429 if (taskreg_for)
bc7bff74 14430 outerc
43895be5 14431 = find_omp_clause (gimple_omp_taskreg_clauses (ctx->outer->stmt),
bc7bff74 14432 OMP_CLAUSE__LOOPTEMP_);
14433 for (i = 0; i < count; i++)
14434 {
14435 tree temp;
43895be5 14436 if (taskreg_for)
bc7bff74 14437 {
14438 gcc_assert (outerc);
14439 temp = lookup_decl (OMP_CLAUSE_DECL (outerc), ctx->outer);
14440 outerc = find_omp_clause (OMP_CLAUSE_CHAIN (outerc),
14441 OMP_CLAUSE__LOOPTEMP_);
14442 }
14443 else
691447ab 14444 {
f9e245b2 14445 temp = create_tmp_var (type);
691447ab 14446 insert_decl_map (&ctx->outer->cb, temp, temp);
14447 }
bc7bff74 14448 *pc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
14449 OMP_CLAUSE_DECL (*pc) = temp;
14450 pc = &OMP_CLAUSE_CHAIN (*pc);
14451 }
14452 *pc = clauses;
14453 }
14454
75a70cf9 14455 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
773c5ba7 14456 dlist = NULL;
75a70cf9 14457 body = NULL;
bc7bff74 14458 lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx,
14459 fdp);
75a70cf9 14460 gimple_seq_add_seq (&body, gimple_omp_for_pre_body (stmt));
773c5ba7 14461
3d483a94 14462 lower_omp (gimple_omp_body_ptr (stmt), ctx);
14463
773c5ba7 14464 /* Lower the header expressions. At this point, we can assume that
14465 the header is of the form:
14466
14467 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
14468
14469 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
14470 using the .omp_data_s mapping, if needed. */
75a70cf9 14471 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
fd6481cf 14472 {
75a70cf9 14473 rhs_p = gimple_omp_for_initial_ptr (stmt, i);
fd6481cf 14474 if (!is_gimple_min_invariant (*rhs_p))
75a70cf9 14475 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
fd6481cf 14476
75a70cf9 14477 rhs_p = gimple_omp_for_final_ptr (stmt, i);
fd6481cf 14478 if (!is_gimple_min_invariant (*rhs_p))
75a70cf9 14479 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
fd6481cf 14480
75a70cf9 14481 rhs_p = &TREE_OPERAND (gimple_omp_for_incr (stmt, i), 1);
fd6481cf 14482 if (!is_gimple_min_invariant (*rhs_p))
75a70cf9 14483 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
fd6481cf 14484 }
773c5ba7 14485
14486 /* Once lowered, extract the bounds and clauses. */
fd6481cf 14487 extract_omp_for_data (stmt, &fd, NULL);
773c5ba7 14488
a8e785ba 14489 if (is_gimple_omp_oacc (ctx->stmt)
14490 && !ctx_in_oacc_kernels_region (ctx))
14491 lower_oacc_head_tail (gimple_location (stmt),
14492 gimple_omp_for_clauses (stmt),
14493 &oacc_head, &oacc_tail, ctx);
14494
f69b8a4c 14495 /* Add OpenACC partitioning and reduction markers just before the loop */
a8e785ba 14496 if (oacc_head)
14497 gimple_seq_add_seq (&body, oacc_head);
14498
75a70cf9 14499 lower_omp_for_lastprivate (&fd, &body, &dlist, ctx);
773c5ba7 14500
43895be5 14501 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR)
14502 for (tree c = gimple_omp_for_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
14503 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
14504 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
14505 {
14506 OMP_CLAUSE_DECL (c) = lookup_decl (OMP_CLAUSE_DECL (c), ctx);
14507 if (DECL_P (OMP_CLAUSE_LINEAR_STEP (c)))
14508 OMP_CLAUSE_LINEAR_STEP (c)
14509 = maybe_lookup_decl_in_outer_ctx (OMP_CLAUSE_LINEAR_STEP (c),
14510 ctx);
14511 }
14512
75a70cf9 14513 gimple_seq_add_stmt (&body, stmt);
14514 gimple_seq_add_seq (&body, gimple_omp_body (stmt));
61e47ac8 14515
75a70cf9 14516 gimple_seq_add_stmt (&body, gimple_build_omp_continue (fd.loop.v,
14517 fd.loop.v));
61e47ac8 14518
773c5ba7 14519 /* After the loop, add exit clauses. */
75a70cf9 14520 lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, ctx);
bc7bff74 14521
14522 if (ctx->cancellable)
14523 gimple_seq_add_stmt (&body, gimple_build_label (ctx->cancel_label));
14524
75a70cf9 14525 gimple_seq_add_seq (&body, dlist);
773c5ba7 14526
75a70cf9 14527 body = maybe_catch_exception (body);
aade31a0 14528
61e47ac8 14529 /* Region exit marker goes at the end of the loop body. */
75a70cf9 14530 gimple_seq_add_stmt (&body, gimple_build_omp_return (fd.have_nowait));
bc7bff74 14531 maybe_add_implicit_barrier_cancel (ctx, &body);
a8e785ba 14532
14533 /* Add OpenACC joining and reduction markers just after the loop. */
14534 if (oacc_tail)
14535 gimple_seq_add_seq (&body, oacc_tail);
14536
1d22f541 14537 pop_gimplify_context (new_stmt);
75a70cf9 14538
14539 gimple_bind_append_vars (new_stmt, ctx->block_vars);
14540 BLOCK_VARS (block) = gimple_bind_vars (new_stmt);
1d22f541 14541 if (BLOCK_VARS (block))
14542 TREE_USED (block) = 1;
773c5ba7 14543
75a70cf9 14544 gimple_bind_set_body (new_stmt, body);
14545 gimple_omp_set_body (stmt, NULL);
14546 gimple_omp_for_set_pre_body (stmt, NULL);
1e8e9920 14547}
14548
48e1416a 14549/* Callback for walk_stmts. Check if the current statement only contains
a7dfc4fe 14550 GIMPLE_OMP_FOR or GIMPLE_OMP_SECTIONS. */
de7ef844 14551
14552static tree
75a70cf9 14553check_combined_parallel (gimple_stmt_iterator *gsi_p,
14554 bool *handled_ops_p,
14555 struct walk_stmt_info *wi)
de7ef844 14556{
4077bf7a 14557 int *info = (int *) wi->info;
42acab1c 14558 gimple *stmt = gsi_stmt (*gsi_p);
de7ef844 14559
75a70cf9 14560 *handled_ops_p = true;
14561 switch (gimple_code (stmt))
de7ef844 14562 {
75a70cf9 14563 WALK_SUBSTMTS;
14564
14565 case GIMPLE_OMP_FOR:
14566 case GIMPLE_OMP_SECTIONS:
de7ef844 14567 *info = *info == 0 ? 1 : -1;
14568 break;
14569 default:
14570 *info = -1;
14571 break;
14572 }
14573 return NULL;
14574}
773c5ba7 14575
fd6481cf 14576struct omp_taskcopy_context
14577{
14578 /* This field must be at the beginning, as we do "inheritance": Some
14579 callback functions for tree-inline.c (e.g., omp_copy_decl)
14580 receive a copy_body_data pointer that is up-casted to an
14581 omp_context pointer. */
14582 copy_body_data cb;
14583 omp_context *ctx;
14584};
14585
14586static tree
14587task_copyfn_copy_decl (tree var, copy_body_data *cb)
14588{
14589 struct omp_taskcopy_context *tcctx = (struct omp_taskcopy_context *) cb;
14590
14591 if (splay_tree_lookup (tcctx->ctx->sfield_map, (splay_tree_key) var))
f9e245b2 14592 return create_tmp_var (TREE_TYPE (var));
fd6481cf 14593
14594 return var;
14595}
14596
14597static tree
14598task_copyfn_remap_type (struct omp_taskcopy_context *tcctx, tree orig_type)
14599{
14600 tree name, new_fields = NULL, type, f;
14601
14602 type = lang_hooks.types.make_type (RECORD_TYPE);
14603 name = DECL_NAME (TYPE_NAME (orig_type));
e60a6f7b 14604 name = build_decl (gimple_location (tcctx->ctx->stmt),
14605 TYPE_DECL, name, type);
fd6481cf 14606 TYPE_NAME (type) = name;
14607
14608 for (f = TYPE_FIELDS (orig_type); f ; f = TREE_CHAIN (f))
14609 {
14610 tree new_f = copy_node (f);
14611 DECL_CONTEXT (new_f) = type;
14612 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &tcctx->cb);
14613 TREE_CHAIN (new_f) = new_fields;
75a70cf9 14614 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &tcctx->cb, NULL);
14615 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r, &tcctx->cb, NULL);
14616 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
14617 &tcctx->cb, NULL);
fd6481cf 14618 new_fields = new_f;
06ecf488 14619 tcctx->cb.decl_map->put (f, new_f);
fd6481cf 14620 }
14621 TYPE_FIELDS (type) = nreverse (new_fields);
14622 layout_type (type);
14623 return type;
14624}
14625
14626/* Create task copyfn. */
14627
14628static void
1a91d914 14629create_task_copyfn (gomp_task *task_stmt, omp_context *ctx)
fd6481cf 14630{
14631 struct function *child_cfun;
14632 tree child_fn, t, c, src, dst, f, sf, arg, sarg, decl;
14633 tree record_type, srecord_type, bind, list;
14634 bool record_needs_remap = false, srecord_needs_remap = false;
14635 splay_tree_node n;
14636 struct omp_taskcopy_context tcctx;
389dd41b 14637 location_t loc = gimple_location (task_stmt);
fd6481cf 14638
75a70cf9 14639 child_fn = gimple_omp_task_copy_fn (task_stmt);
fd6481cf 14640 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
14641 gcc_assert (child_cfun->cfg == NULL);
fd6481cf 14642 DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
14643
14644 /* Reset DECL_CONTEXT on function arguments. */
1767a056 14645 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
fd6481cf 14646 DECL_CONTEXT (t) = child_fn;
14647
14648 /* Populate the function. */
8a4a28a8 14649 push_gimplify_context ();
9078126c 14650 push_cfun (child_cfun);
fd6481cf 14651
14652 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
14653 TREE_SIDE_EFFECTS (bind) = 1;
14654 list = NULL;
14655 DECL_SAVED_TREE (child_fn) = bind;
75a70cf9 14656 DECL_SOURCE_LOCATION (child_fn) = gimple_location (task_stmt);
fd6481cf 14657
14658 /* Remap src and dst argument types if needed. */
14659 record_type = ctx->record_type;
14660 srecord_type = ctx->srecord_type;
1767a056 14661 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
fd6481cf 14662 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
14663 {
14664 record_needs_remap = true;
14665 break;
14666 }
1767a056 14667 for (f = TYPE_FIELDS (srecord_type); f ; f = DECL_CHAIN (f))
fd6481cf 14668 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
14669 {
14670 srecord_needs_remap = true;
14671 break;
14672 }
14673
14674 if (record_needs_remap || srecord_needs_remap)
14675 {
14676 memset (&tcctx, '\0', sizeof (tcctx));
14677 tcctx.cb.src_fn = ctx->cb.src_fn;
14678 tcctx.cb.dst_fn = child_fn;
415d1b9a 14679 tcctx.cb.src_node = cgraph_node::get (tcctx.cb.src_fn);
53f79206 14680 gcc_checking_assert (tcctx.cb.src_node);
fd6481cf 14681 tcctx.cb.dst_node = tcctx.cb.src_node;
14682 tcctx.cb.src_cfun = ctx->cb.src_cfun;
14683 tcctx.cb.copy_decl = task_copyfn_copy_decl;
e38def9c 14684 tcctx.cb.eh_lp_nr = 0;
fd6481cf 14685 tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
06ecf488 14686 tcctx.cb.decl_map = new hash_map<tree, tree>;
fd6481cf 14687 tcctx.ctx = ctx;
14688
14689 if (record_needs_remap)
14690 record_type = task_copyfn_remap_type (&tcctx, record_type);
14691 if (srecord_needs_remap)
14692 srecord_type = task_copyfn_remap_type (&tcctx, srecord_type);
14693 }
14694 else
14695 tcctx.cb.decl_map = NULL;
14696
fd6481cf 14697 arg = DECL_ARGUMENTS (child_fn);
14698 TREE_TYPE (arg) = build_pointer_type (record_type);
1767a056 14699 sarg = DECL_CHAIN (arg);
fd6481cf 14700 TREE_TYPE (sarg) = build_pointer_type (srecord_type);
14701
14702 /* First pass: initialize temporaries used in record_type and srecord_type
14703 sizes and field offsets. */
14704 if (tcctx.cb.decl_map)
75a70cf9 14705 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
fd6481cf 14706 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
14707 {
14708 tree *p;
14709
14710 decl = OMP_CLAUSE_DECL (c);
06ecf488 14711 p = tcctx.cb.decl_map->get (decl);
fd6481cf 14712 if (p == NULL)
14713 continue;
14714 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
14715 sf = (tree) n->value;
06ecf488 14716 sf = *tcctx.cb.decl_map->get (sf);
182cf5a9 14717 src = build_simple_mem_ref_loc (loc, sarg);
445d06b6 14718 src = omp_build_component_ref (src, sf);
75a70cf9 14719 t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
fd6481cf 14720 append_to_statement_list (t, &list);
14721 }
14722
14723 /* Second pass: copy shared var pointers and copy construct non-VLA
14724 firstprivate vars. */
75a70cf9 14725 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
fd6481cf 14726 switch (OMP_CLAUSE_CODE (c))
14727 {
43895be5 14728 splay_tree_key key;
fd6481cf 14729 case OMP_CLAUSE_SHARED:
14730 decl = OMP_CLAUSE_DECL (c);
43895be5 14731 key = (splay_tree_key) decl;
14732 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
14733 key = (splay_tree_key) &DECL_UID (decl);
14734 n = splay_tree_lookup (ctx->field_map, key);
fd6481cf 14735 if (n == NULL)
14736 break;
14737 f = (tree) n->value;
14738 if (tcctx.cb.decl_map)
06ecf488 14739 f = *tcctx.cb.decl_map->get (f);
43895be5 14740 n = splay_tree_lookup (ctx->sfield_map, key);
fd6481cf 14741 sf = (tree) n->value;
14742 if (tcctx.cb.decl_map)
06ecf488 14743 sf = *tcctx.cb.decl_map->get (sf);
182cf5a9 14744 src = build_simple_mem_ref_loc (loc, sarg);
445d06b6 14745 src = omp_build_component_ref (src, sf);
182cf5a9 14746 dst = build_simple_mem_ref_loc (loc, arg);
445d06b6 14747 dst = omp_build_component_ref (dst, f);
75a70cf9 14748 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
fd6481cf 14749 append_to_statement_list (t, &list);
14750 break;
14751 case OMP_CLAUSE_FIRSTPRIVATE:
14752 decl = OMP_CLAUSE_DECL (c);
14753 if (is_variable_sized (decl))
14754 break;
14755 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
14756 if (n == NULL)
14757 break;
14758 f = (tree) n->value;
14759 if (tcctx.cb.decl_map)
06ecf488 14760 f = *tcctx.cb.decl_map->get (f);
fd6481cf 14761 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
14762 if (n != NULL)
14763 {
14764 sf = (tree) n->value;
14765 if (tcctx.cb.decl_map)
06ecf488 14766 sf = *tcctx.cb.decl_map->get (sf);
182cf5a9 14767 src = build_simple_mem_ref_loc (loc, sarg);
445d06b6 14768 src = omp_build_component_ref (src, sf);
fd6481cf 14769 if (use_pointer_for_field (decl, NULL) || is_reference (decl))
182cf5a9 14770 src = build_simple_mem_ref_loc (loc, src);
fd6481cf 14771 }
14772 else
14773 src = decl;
182cf5a9 14774 dst = build_simple_mem_ref_loc (loc, arg);
445d06b6 14775 dst = omp_build_component_ref (dst, f);
fd6481cf 14776 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
14777 append_to_statement_list (t, &list);
14778 break;
14779 case OMP_CLAUSE_PRIVATE:
14780 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c))
14781 break;
14782 decl = OMP_CLAUSE_DECL (c);
14783 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
14784 f = (tree) n->value;
14785 if (tcctx.cb.decl_map)
06ecf488 14786 f = *tcctx.cb.decl_map->get (f);
fd6481cf 14787 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
14788 if (n != NULL)
14789 {
14790 sf = (tree) n->value;
14791 if (tcctx.cb.decl_map)
06ecf488 14792 sf = *tcctx.cb.decl_map->get (sf);
182cf5a9 14793 src = build_simple_mem_ref_loc (loc, sarg);
445d06b6 14794 src = omp_build_component_ref (src, sf);
fd6481cf 14795 if (use_pointer_for_field (decl, NULL))
182cf5a9 14796 src = build_simple_mem_ref_loc (loc, src);
fd6481cf 14797 }
14798 else
14799 src = decl;
182cf5a9 14800 dst = build_simple_mem_ref_loc (loc, arg);
445d06b6 14801 dst = omp_build_component_ref (dst, f);
75a70cf9 14802 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
fd6481cf 14803 append_to_statement_list (t, &list);
14804 break;
14805 default:
14806 break;
14807 }
14808
14809 /* Last pass: handle VLA firstprivates. */
14810 if (tcctx.cb.decl_map)
75a70cf9 14811 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
fd6481cf 14812 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
14813 {
14814 tree ind, ptr, df;
14815
14816 decl = OMP_CLAUSE_DECL (c);
14817 if (!is_variable_sized (decl))
14818 continue;
14819 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
14820 if (n == NULL)
14821 continue;
14822 f = (tree) n->value;
06ecf488 14823 f = *tcctx.cb.decl_map->get (f);
fd6481cf 14824 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
14825 ind = DECL_VALUE_EXPR (decl);
14826 gcc_assert (TREE_CODE (ind) == INDIRECT_REF);
14827 gcc_assert (DECL_P (TREE_OPERAND (ind, 0)));
14828 n = splay_tree_lookup (ctx->sfield_map,
14829 (splay_tree_key) TREE_OPERAND (ind, 0));
14830 sf = (tree) n->value;
06ecf488 14831 sf = *tcctx.cb.decl_map->get (sf);
182cf5a9 14832 src = build_simple_mem_ref_loc (loc, sarg);
445d06b6 14833 src = omp_build_component_ref (src, sf);
182cf5a9 14834 src = build_simple_mem_ref_loc (loc, src);
14835 dst = build_simple_mem_ref_loc (loc, arg);
445d06b6 14836 dst = omp_build_component_ref (dst, f);
fd6481cf 14837 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
14838 append_to_statement_list (t, &list);
14839 n = splay_tree_lookup (ctx->field_map,
14840 (splay_tree_key) TREE_OPERAND (ind, 0));
14841 df = (tree) n->value;
06ecf488 14842 df = *tcctx.cb.decl_map->get (df);
182cf5a9 14843 ptr = build_simple_mem_ref_loc (loc, arg);
445d06b6 14844 ptr = omp_build_component_ref (ptr, df);
75a70cf9 14845 t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
389dd41b 14846 build_fold_addr_expr_loc (loc, dst));
fd6481cf 14847 append_to_statement_list (t, &list);
14848 }
14849
14850 t = build1 (RETURN_EXPR, void_type_node, NULL);
14851 append_to_statement_list (t, &list);
14852
14853 if (tcctx.cb.decl_map)
06ecf488 14854 delete tcctx.cb.decl_map;
fd6481cf 14855 pop_gimplify_context (NULL);
14856 BIND_EXPR_BODY (bind) = list;
14857 pop_cfun ();
fd6481cf 14858}
14859
bc7bff74 14860static void
43895be5 14861lower_depend_clauses (tree *pclauses, gimple_seq *iseq, gimple_seq *oseq)
bc7bff74 14862{
14863 tree c, clauses;
42acab1c 14864 gimple *g;
bc7bff74 14865 size_t n_in = 0, n_out = 0, idx = 2, i;
14866
43895be5 14867 clauses = find_omp_clause (*pclauses, OMP_CLAUSE_DEPEND);
bc7bff74 14868 gcc_assert (clauses);
14869 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
14870 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
14871 switch (OMP_CLAUSE_DEPEND_KIND (c))
14872 {
14873 case OMP_CLAUSE_DEPEND_IN:
14874 n_in++;
14875 break;
14876 case OMP_CLAUSE_DEPEND_OUT:
14877 case OMP_CLAUSE_DEPEND_INOUT:
14878 n_out++;
14879 break;
43895be5 14880 case OMP_CLAUSE_DEPEND_SOURCE:
14881 case OMP_CLAUSE_DEPEND_SINK:
14882 /* FALLTHRU */
bc7bff74 14883 default:
14884 gcc_unreachable ();
14885 }
14886 tree type = build_array_type_nelts (ptr_type_node, n_in + n_out + 2);
f9e245b2 14887 tree array = create_tmp_var (type);
43895be5 14888 TREE_ADDRESSABLE (array) = 1;
bc7bff74 14889 tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
14890 NULL_TREE);
14891 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_in + n_out));
14892 gimple_seq_add_stmt (iseq, g);
14893 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
14894 NULL_TREE);
14895 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_out));
14896 gimple_seq_add_stmt (iseq, g);
14897 for (i = 0; i < 2; i++)
14898 {
14899 if ((i ? n_in : n_out) == 0)
14900 continue;
14901 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
14902 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
14903 && ((OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_IN) ^ i))
14904 {
14905 tree t = OMP_CLAUSE_DECL (c);
14906 t = fold_convert (ptr_type_node, t);
14907 gimplify_expr (&t, iseq, NULL, is_gimple_val, fb_rvalue);
14908 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (idx++),
14909 NULL_TREE, NULL_TREE);
14910 g = gimple_build_assign (r, t);
14911 gimple_seq_add_stmt (iseq, g);
14912 }
14913 }
bc7bff74 14914 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
14915 OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
43895be5 14916 OMP_CLAUSE_CHAIN (c) = *pclauses;
14917 *pclauses = c;
bc7bff74 14918 tree clobber = build_constructor (type, NULL);
14919 TREE_THIS_VOLATILE (clobber) = 1;
14920 g = gimple_build_assign (array, clobber);
14921 gimple_seq_add_stmt (oseq, g);
14922}
14923
75a70cf9 14924/* Lower the OpenMP parallel or task directive in the current statement
14925 in GSI_P. CTX holds context information for the directive. */
773c5ba7 14926
14927static void
75a70cf9 14928lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
773c5ba7 14929{
75a70cf9 14930 tree clauses;
14931 tree child_fn, t;
42acab1c 14932 gimple *stmt = gsi_stmt (*gsi_p);
1a91d914 14933 gbind *par_bind, *bind, *dep_bind = NULL;
bc7bff74 14934 gimple_seq par_body, olist, ilist, par_olist, par_rlist, par_ilist, new_body;
389dd41b 14935 location_t loc = gimple_location (stmt);
773c5ba7 14936
75a70cf9 14937 clauses = gimple_omp_taskreg_clauses (stmt);
1a91d914 14938 par_bind
14939 = as_a <gbind *> (gimple_seq_first_stmt (gimple_omp_body (stmt)));
75a70cf9 14940 par_body = gimple_bind_body (par_bind);
773c5ba7 14941 child_fn = ctx->cb.dst_fn;
75a70cf9 14942 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
14943 && !gimple_omp_parallel_combined_p (stmt))
de7ef844 14944 {
14945 struct walk_stmt_info wi;
14946 int ws_num = 0;
14947
14948 memset (&wi, 0, sizeof (wi));
de7ef844 14949 wi.info = &ws_num;
14950 wi.val_only = true;
75a70cf9 14951 walk_gimple_seq (par_body, check_combined_parallel, NULL, &wi);
de7ef844 14952 if (ws_num == 1)
75a70cf9 14953 gimple_omp_parallel_set_combined_p (stmt, true);
de7ef844 14954 }
bc7bff74 14955 gimple_seq dep_ilist = NULL;
14956 gimple_seq dep_olist = NULL;
14957 if (gimple_code (stmt) == GIMPLE_OMP_TASK
14958 && find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
14959 {
8a4a28a8 14960 push_gimplify_context ();
bc7bff74 14961 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
43895be5 14962 lower_depend_clauses (gimple_omp_task_clauses_ptr (stmt),
14963 &dep_ilist, &dep_olist);
bc7bff74 14964 }
14965
fd6481cf 14966 if (ctx->srecord_type)
1a91d914 14967 create_task_copyfn (as_a <gomp_task *> (stmt), ctx);
773c5ba7 14968
8a4a28a8 14969 push_gimplify_context ();
773c5ba7 14970
75a70cf9 14971 par_olist = NULL;
14972 par_ilist = NULL;
bc7bff74 14973 par_rlist = NULL;
14974 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx, NULL);
e3a19533 14975 lower_omp (&par_body, ctx);
75a70cf9 14976 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL)
bc7bff74 14977 lower_reduction_clauses (clauses, &par_rlist, ctx);
773c5ba7 14978
14979 /* Declare all the variables created by mapping and the variables
14980 declared in the scope of the parallel body. */
14981 record_vars_into (ctx->block_vars, child_fn);
75a70cf9 14982 record_vars_into (gimple_bind_vars (par_bind), child_fn);
773c5ba7 14983
14984 if (ctx->record_type)
14985 {
fd6481cf 14986 ctx->sender_decl
14987 = create_tmp_var (ctx->srecord_type ? ctx->srecord_type
14988 : ctx->record_type, ".omp_data_o");
84bfaaeb 14989 DECL_NAMELESS (ctx->sender_decl) = 1;
86f2ad37 14990 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
75a70cf9 14991 gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl);
773c5ba7 14992 }
14993
75a70cf9 14994 olist = NULL;
14995 ilist = NULL;
773c5ba7 14996 lower_send_clauses (clauses, &ilist, &olist, ctx);
14997 lower_send_shared_vars (&ilist, &olist, ctx);
14998
bc7bff74 14999 if (ctx->record_type)
15000 {
15001 tree clobber = build_constructor (TREE_TYPE (ctx->sender_decl), NULL);
15002 TREE_THIS_VOLATILE (clobber) = 1;
15003 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
15004 clobber));
15005 }
15006
773c5ba7 15007 /* Once all the expansions are done, sequence all the different
75a70cf9 15008 fragments inside gimple_omp_body. */
773c5ba7 15009
75a70cf9 15010 new_body = NULL;
773c5ba7 15011
15012 if (ctx->record_type)
15013 {
389dd41b 15014 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
cc6b725b 15015 /* fixup_child_record_type might have changed receiver_decl's type. */
389dd41b 15016 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
75a70cf9 15017 gimple_seq_add_stmt (&new_body,
15018 gimple_build_assign (ctx->receiver_decl, t));
773c5ba7 15019 }
15020
75a70cf9 15021 gimple_seq_add_seq (&new_body, par_ilist);
15022 gimple_seq_add_seq (&new_body, par_body);
bc7bff74 15023 gimple_seq_add_seq (&new_body, par_rlist);
15024 if (ctx->cancellable)
15025 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
75a70cf9 15026 gimple_seq_add_seq (&new_body, par_olist);
15027 new_body = maybe_catch_exception (new_body);
b25f70fd 15028 if (gimple_code (stmt) == GIMPLE_OMP_TASK)
15029 gimple_seq_add_stmt (&new_body,
15030 gimple_build_omp_continue (integer_zero_node,
15031 integer_zero_node));
75a70cf9 15032 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
15033 gimple_omp_set_body (stmt, new_body);
773c5ba7 15034
75a70cf9 15035 bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
bc7bff74 15036 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
15037 gimple_bind_add_seq (bind, ilist);
15038 gimple_bind_add_stmt (bind, stmt);
15039 gimple_bind_add_seq (bind, olist);
15040
15041 pop_gimplify_context (NULL);
15042
15043 if (dep_bind)
15044 {
15045 gimple_bind_add_seq (dep_bind, dep_ilist);
15046 gimple_bind_add_stmt (dep_bind, bind);
15047 gimple_bind_add_seq (dep_bind, dep_olist);
15048 pop_gimplify_context (dep_bind);
15049 }
15050}
15051
ca4c3545 15052/* Lower the GIMPLE_OMP_TARGET in the current statement
bc7bff74 15053 in GSI_P. CTX holds context information for the directive. */
15054
15055static void
15056lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
15057{
15058 tree clauses;
15059 tree child_fn, t, c;
1a91d914 15060 gomp_target *stmt = as_a <gomp_target *> (gsi_stmt (*gsi_p));
43895be5 15061 gbind *tgt_bind, *bind, *dep_bind = NULL;
b656be3a 15062 gimple_seq tgt_body, olist, ilist, fplist, new_body;
bc7bff74 15063 location_t loc = gimple_location (stmt);
ca4c3545 15064 bool offloaded, data_region;
bc7bff74 15065 unsigned int map_cnt = 0;
43895be5 15066 bool has_depend = false;
bc7bff74 15067
ca4c3545 15068 offloaded = is_gimple_omp_offloaded (stmt);
15069 switch (gimple_omp_target_kind (stmt))
15070 {
15071 case GF_OMP_TARGET_KIND_REGION:
15072 case GF_OMP_TARGET_KIND_UPDATE:
43895be5 15073 case GF_OMP_TARGET_KIND_ENTER_DATA:
15074 case GF_OMP_TARGET_KIND_EXIT_DATA:
ca4c3545 15075 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
15076 case GF_OMP_TARGET_KIND_OACC_KERNELS:
15077 case GF_OMP_TARGET_KIND_OACC_UPDATE:
15078 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
2fc5e987 15079 case GF_OMP_TARGET_KIND_OACC_DECLARE:
ca4c3545 15080 data_region = false;
15081 break;
15082 case GF_OMP_TARGET_KIND_DATA:
15083 case GF_OMP_TARGET_KIND_OACC_DATA:
571b3486 15084 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
ca4c3545 15085 data_region = true;
15086 break;
15087 default:
15088 gcc_unreachable ();
15089 }
15090
bc7bff74 15091 clauses = gimple_omp_target_clauses (stmt);
ca4c3545 15092
43895be5 15093 gimple_seq dep_ilist = NULL;
15094 gimple_seq dep_olist = NULL;
15095 if (find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
15096 {
15097 push_gimplify_context ();
15098 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
15099 lower_depend_clauses (gimple_omp_target_clauses_ptr (stmt),
15100 &dep_ilist, &dep_olist);
15101 has_depend = true;
15102 }
15103
ca4c3545 15104 tgt_bind = NULL;
15105 tgt_body = NULL;
15106 if (offloaded)
bc7bff74 15107 {
1a91d914 15108 tgt_bind = gimple_seq_first_stmt_as_a_bind (gimple_omp_body (stmt));
bc7bff74 15109 tgt_body = gimple_bind_body (tgt_bind);
15110 }
ca4c3545 15111 else if (data_region)
bc7bff74 15112 tgt_body = gimple_omp_body (stmt);
15113 child_fn = ctx->cb.dst_fn;
15114
8a4a28a8 15115 push_gimplify_context ();
b656be3a 15116 fplist = NULL;
bc7bff74 15117
15118 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
15119 switch (OMP_CLAUSE_CODE (c))
15120 {
15121 tree var, x;
15122
15123 default:
15124 break;
15125 case OMP_CLAUSE_MAP:
382ecba7 15126#if CHECKING_P
ca4c3545 15127 /* First check what we're prepared to handle in the following. */
15128 switch (OMP_CLAUSE_MAP_KIND (c))
15129 {
15130 case GOMP_MAP_ALLOC:
15131 case GOMP_MAP_TO:
15132 case GOMP_MAP_FROM:
15133 case GOMP_MAP_TOFROM:
15134 case GOMP_MAP_POINTER:
15135 case GOMP_MAP_TO_PSET:
43895be5 15136 case GOMP_MAP_FORCE_DEALLOC:
15137 case GOMP_MAP_RELEASE:
15138 case GOMP_MAP_ALWAYS_TO:
15139 case GOMP_MAP_ALWAYS_FROM:
15140 case GOMP_MAP_ALWAYS_TOFROM:
15141 case GOMP_MAP_FIRSTPRIVATE_POINTER:
9561765e 15142 case GOMP_MAP_FIRSTPRIVATE_REFERENCE:
43895be5 15143 case GOMP_MAP_STRUCT:
9561765e 15144 case GOMP_MAP_ALWAYS_POINTER:
ca4c3545 15145 break;
15146 case GOMP_MAP_FORCE_ALLOC:
15147 case GOMP_MAP_FORCE_TO:
15148 case GOMP_MAP_FORCE_FROM:
15149 case GOMP_MAP_FORCE_TOFROM:
15150 case GOMP_MAP_FORCE_PRESENT:
ca4c3545 15151 case GOMP_MAP_FORCE_DEVICEPTR:
2fc5e987 15152 case GOMP_MAP_DEVICE_RESIDENT:
15153 case GOMP_MAP_LINK:
ca4c3545 15154 gcc_assert (is_gimple_omp_oacc (stmt));
15155 break;
15156 default:
15157 gcc_unreachable ();
15158 }
15159#endif
15160 /* FALLTHRU */
bc7bff74 15161 case OMP_CLAUSE_TO:
15162 case OMP_CLAUSE_FROM:
b656be3a 15163 oacc_firstprivate:
bc7bff74 15164 var = OMP_CLAUSE_DECL (c);
15165 if (!DECL_P (var))
15166 {
15167 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
43895be5 15168 || (!OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
15169 && (OMP_CLAUSE_MAP_KIND (c)
15170 != GOMP_MAP_FIRSTPRIVATE_POINTER)))
bc7bff74 15171 map_cnt++;
15172 continue;
15173 }
15174
15175 if (DECL_SIZE (var)
15176 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
15177 {
15178 tree var2 = DECL_VALUE_EXPR (var);
15179 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
15180 var2 = TREE_OPERAND (var2, 0);
15181 gcc_assert (DECL_P (var2));
15182 var = var2;
15183 }
15184
43895be5 15185 if (offloaded
b656be3a 15186 && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
9561765e 15187 && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
15188 || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_REFERENCE))
43895be5 15189 {
15190 if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
15191 {
15192 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx))
15193 && varpool_node::get_create (var)->offloadable)
15194 continue;
15195
15196 tree type = build_pointer_type (TREE_TYPE (var));
15197 tree new_var = lookup_decl (var, ctx);
15198 x = create_tmp_var_raw (type, get_name (new_var));
15199 gimple_add_tmp_var (x);
15200 x = build_simple_mem_ref (x);
15201 SET_DECL_VALUE_EXPR (new_var, x);
15202 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15203 }
15204 continue;
15205 }
15206
bc7bff74 15207 if (!maybe_lookup_field (var, ctx))
15208 continue;
15209
ca4c3545 15210 if (offloaded)
bc7bff74 15211 {
15212 x = build_receiver_ref (var, true, ctx);
15213 tree new_var = lookup_decl (var, ctx);
43895be5 15214
b656be3a 15215 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
15216 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
bc7bff74 15217 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
15218 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
15219 x = build_simple_mem_ref (x);
b656be3a 15220 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
15221 {
15222 gcc_assert (is_gimple_omp_oacc (ctx->stmt));
15223 if (is_reference (new_var))
15224 {
15225 /* Create a local object to hold the instance
15226 value. */
15227 tree type = TREE_TYPE (TREE_TYPE (new_var));
15228 const char *id = IDENTIFIER_POINTER (DECL_NAME (new_var));
15229 tree inst = create_tmp_var (type, id);
15230 gimplify_assign (inst, fold_indirect_ref (x), &fplist);
15231 x = build_fold_addr_expr (inst);
15232 }
15233 gimplify_assign (new_var, x, &fplist);
15234 }
15235 else if (DECL_P (new_var))
15236 {
15237 SET_DECL_VALUE_EXPR (new_var, x);
15238 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15239 }
15240 else
15241 gcc_unreachable ();
bc7bff74 15242 }
15243 map_cnt++;
43895be5 15244 break;
15245
15246 case OMP_CLAUSE_FIRSTPRIVATE:
b656be3a 15247 if (is_oacc_parallel (ctx))
15248 goto oacc_firstprivate;
43895be5 15249 map_cnt++;
15250 var = OMP_CLAUSE_DECL (c);
15251 if (!is_reference (var)
15252 && !is_gimple_reg_type (TREE_TYPE (var)))
15253 {
15254 tree new_var = lookup_decl (var, ctx);
15255 if (is_variable_sized (var))
15256 {
15257 tree pvar = DECL_VALUE_EXPR (var);
15258 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15259 pvar = TREE_OPERAND (pvar, 0);
15260 gcc_assert (DECL_P (pvar));
15261 tree new_pvar = lookup_decl (pvar, ctx);
15262 x = build_fold_indirect_ref (new_pvar);
15263 TREE_THIS_NOTRAP (x) = 1;
15264 }
15265 else
15266 x = build_receiver_ref (var, true, ctx);
15267 SET_DECL_VALUE_EXPR (new_var, x);
15268 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15269 }
15270 break;
15271
15272 case OMP_CLAUSE_PRIVATE:
b656be3a 15273 if (is_gimple_omp_oacc (ctx->stmt))
15274 break;
43895be5 15275 var = OMP_CLAUSE_DECL (c);
15276 if (is_variable_sized (var))
15277 {
15278 tree new_var = lookup_decl (var, ctx);
15279 tree pvar = DECL_VALUE_EXPR (var);
15280 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15281 pvar = TREE_OPERAND (pvar, 0);
15282 gcc_assert (DECL_P (pvar));
15283 tree new_pvar = lookup_decl (pvar, ctx);
15284 x = build_fold_indirect_ref (new_pvar);
15285 TREE_THIS_NOTRAP (x) = 1;
15286 SET_DECL_VALUE_EXPR (new_var, x);
15287 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15288 }
15289 break;
15290
571b3486 15291 case OMP_CLAUSE_USE_DEVICE:
43895be5 15292 case OMP_CLAUSE_USE_DEVICE_PTR:
15293 case OMP_CLAUSE_IS_DEVICE_PTR:
15294 var = OMP_CLAUSE_DECL (c);
15295 map_cnt++;
15296 if (is_variable_sized (var))
15297 {
15298 tree new_var = lookup_decl (var, ctx);
15299 tree pvar = DECL_VALUE_EXPR (var);
15300 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15301 pvar = TREE_OPERAND (pvar, 0);
15302 gcc_assert (DECL_P (pvar));
15303 tree new_pvar = lookup_decl (pvar, ctx);
15304 x = build_fold_indirect_ref (new_pvar);
15305 TREE_THIS_NOTRAP (x) = 1;
15306 SET_DECL_VALUE_EXPR (new_var, x);
15307 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15308 }
15309 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
15310 {
15311 tree new_var = lookup_decl (var, ctx);
15312 tree type = build_pointer_type (TREE_TYPE (var));
15313 x = create_tmp_var_raw (type, get_name (new_var));
15314 gimple_add_tmp_var (x);
15315 x = build_simple_mem_ref (x);
15316 SET_DECL_VALUE_EXPR (new_var, x);
15317 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15318 }
15319 break;
bc7bff74 15320 }
15321
ca4c3545 15322 if (offloaded)
bc7bff74 15323 {
15324 target_nesting_level++;
15325 lower_omp (&tgt_body, ctx);
15326 target_nesting_level--;
15327 }
ca4c3545 15328 else if (data_region)
bc7bff74 15329 lower_omp (&tgt_body, ctx);
15330
ca4c3545 15331 if (offloaded)
bc7bff74 15332 {
15333 /* Declare all the variables created by mapping and the variables
15334 declared in the scope of the target body. */
15335 record_vars_into (ctx->block_vars, child_fn);
15336 record_vars_into (gimple_bind_vars (tgt_bind), child_fn);
15337 }
15338
15339 olist = NULL;
15340 ilist = NULL;
15341 if (ctx->record_type)
15342 {
15343 ctx->sender_decl
15344 = create_tmp_var (ctx->record_type, ".omp_data_arr");
15345 DECL_NAMELESS (ctx->sender_decl) = 1;
15346 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
15347 t = make_tree_vec (3);
15348 TREE_VEC_ELT (t, 0) = ctx->sender_decl;
15349 TREE_VEC_ELT (t, 1)
15350 = create_tmp_var (build_array_type_nelts (size_type_node, map_cnt),
15351 ".omp_data_sizes");
15352 DECL_NAMELESS (TREE_VEC_ELT (t, 1)) = 1;
15353 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 1)) = 1;
15354 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 1;
43895be5 15355 tree tkind_type = short_unsigned_type_node;
15356 int talign_shift = 8;
bc7bff74 15357 TREE_VEC_ELT (t, 2)
ca4c3545 15358 = create_tmp_var (build_array_type_nelts (tkind_type, map_cnt),
bc7bff74 15359 ".omp_data_kinds");
15360 DECL_NAMELESS (TREE_VEC_ELT (t, 2)) = 1;
15361 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 2)) = 1;
15362 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 1;
15363 gimple_omp_target_set_data_arg (stmt, t);
15364
15365 vec<constructor_elt, va_gc> *vsize;
15366 vec<constructor_elt, va_gc> *vkind;
15367 vec_alloc (vsize, map_cnt);
15368 vec_alloc (vkind, map_cnt);
15369 unsigned int map_idx = 0;
15370
15371 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
15372 switch (OMP_CLAUSE_CODE (c))
15373 {
43895be5 15374 tree ovar, nc, s, purpose, var, x, type;
15375 unsigned int talign;
bc7bff74 15376
15377 default:
15378 break;
b656be3a 15379
bc7bff74 15380 case OMP_CLAUSE_MAP:
15381 case OMP_CLAUSE_TO:
15382 case OMP_CLAUSE_FROM:
b656be3a 15383 oacc_firstprivate_map:
bc7bff74 15384 nc = c;
15385 ovar = OMP_CLAUSE_DECL (c);
43895be5 15386 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
9561765e 15387 && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
15388 || (OMP_CLAUSE_MAP_KIND (c)
15389 == GOMP_MAP_FIRSTPRIVATE_REFERENCE)))
43895be5 15390 break;
bc7bff74 15391 if (!DECL_P (ovar))
15392 {
15393 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
15394 && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
15395 {
15396 gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c))
15397 == get_base_address (ovar));
15398 nc = OMP_CLAUSE_CHAIN (c);
15399 ovar = OMP_CLAUSE_DECL (nc);
15400 }
15401 else
15402 {
15403 tree x = build_sender_ref (ovar, ctx);
15404 tree v
15405 = build_fold_addr_expr_with_type (ovar, ptr_type_node);
15406 gimplify_assign (x, v, &ilist);
15407 nc = NULL_TREE;
15408 }
15409 }
15410 else
15411 {
15412 if (DECL_SIZE (ovar)
15413 && TREE_CODE (DECL_SIZE (ovar)) != INTEGER_CST)
15414 {
15415 tree ovar2 = DECL_VALUE_EXPR (ovar);
15416 gcc_assert (TREE_CODE (ovar2) == INDIRECT_REF);
15417 ovar2 = TREE_OPERAND (ovar2, 0);
15418 gcc_assert (DECL_P (ovar2));
15419 ovar = ovar2;
15420 }
9561765e 15421 if (!maybe_lookup_field (ovar, ctx))
bc7bff74 15422 continue;
15423 }
15424
43895be5 15425 talign = TYPE_ALIGN_UNIT (TREE_TYPE (ovar));
4f3b8d78 15426 if (DECL_P (ovar) && DECL_ALIGN_UNIT (ovar) > talign)
15427 talign = DECL_ALIGN_UNIT (ovar);
bc7bff74 15428 if (nc)
15429 {
43895be5 15430 var = lookup_decl_in_outer_ctx (ovar, ctx);
9561765e 15431 x = build_sender_ref (ovar, ctx);
abe55632 15432
15433 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
b656be3a 15434 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
15435 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
15436 && TREE_CODE (TREE_TYPE (ovar)) == ARRAY_TYPE)
bc7bff74 15437 {
ca4c3545 15438 gcc_assert (offloaded);
bc7bff74 15439 tree avar
f9e245b2 15440 = create_tmp_var (TREE_TYPE (TREE_TYPE (x)));
bc7bff74 15441 mark_addressable (avar);
15442 gimplify_assign (avar, build_fold_addr_expr (var), &ilist);
4f3b8d78 15443 talign = DECL_ALIGN_UNIT (avar);
bc7bff74 15444 avar = build_fold_addr_expr (avar);
15445 gimplify_assign (x, avar, &ilist);
15446 }
b656be3a 15447 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
15448 {
15449 gcc_assert (is_gimple_omp_oacc (ctx->stmt));
15450 if (!is_reference (var))
15451 var = build_fold_addr_expr (var);
15452 else
15453 talign = TYPE_ALIGN_UNIT (TREE_TYPE (TREE_TYPE (ovar)));
15454 gimplify_assign (x, var, &ilist);
15455 }
bc7bff74 15456 else if (is_gimple_reg (var))
15457 {
ca4c3545 15458 gcc_assert (offloaded);
f9e245b2 15459 tree avar = create_tmp_var (TREE_TYPE (var));
bc7bff74 15460 mark_addressable (avar);
ca4c3545 15461 enum gomp_map_kind map_kind = OMP_CLAUSE_MAP_KIND (c);
15462 if (GOMP_MAP_COPY_TO_P (map_kind)
15463 || map_kind == GOMP_MAP_POINTER
15464 || map_kind == GOMP_MAP_TO_PSET
15465 || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
bc7bff74 15466 gimplify_assign (avar, var, &ilist);
15467 avar = build_fold_addr_expr (avar);
15468 gimplify_assign (x, avar, &ilist);
ca4c3545 15469 if ((GOMP_MAP_COPY_FROM_P (map_kind)
15470 || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
bc7bff74 15471 && !TYPE_READONLY (TREE_TYPE (var)))
15472 {
43895be5 15473 x = unshare_expr (x);
bc7bff74 15474 x = build_simple_mem_ref (x);
15475 gimplify_assign (var, x, &olist);
15476 }
15477 }
15478 else
15479 {
15480 var = build_fold_addr_expr (var);
15481 gimplify_assign (x, var, &ilist);
15482 }
15483 }
b656be3a 15484 s = NULL_TREE;
15485 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
15486 {
15487 gcc_checking_assert (is_gimple_omp_oacc (ctx->stmt));
15488 s = TREE_TYPE (ovar);
15489 if (TREE_CODE (s) == REFERENCE_TYPE)
15490 s = TREE_TYPE (s);
15491 s = TYPE_SIZE_UNIT (s);
15492 }
15493 else
15494 s = OMP_CLAUSE_SIZE (c);
bc7bff74 15495 if (s == NULL_TREE)
15496 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
15497 s = fold_convert (size_type_node, s);
43895be5 15498 purpose = size_int (map_idx++);
bc7bff74 15499 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
15500 if (TREE_CODE (s) != INTEGER_CST)
15501 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
15502
43895be5 15503 unsigned HOST_WIDE_INT tkind, tkind_zero;
bc7bff74 15504 switch (OMP_CLAUSE_CODE (c))
15505 {
15506 case OMP_CLAUSE_MAP:
15507 tkind = OMP_CLAUSE_MAP_KIND (c);
43895be5 15508 tkind_zero = tkind;
15509 if (OMP_CLAUSE_MAP_MAYBE_ZERO_LENGTH_ARRAY_SECTION (c))
15510 switch (tkind)
15511 {
15512 case GOMP_MAP_ALLOC:
15513 case GOMP_MAP_TO:
15514 case GOMP_MAP_FROM:
15515 case GOMP_MAP_TOFROM:
15516 case GOMP_MAP_ALWAYS_TO:
15517 case GOMP_MAP_ALWAYS_FROM:
15518 case GOMP_MAP_ALWAYS_TOFROM:
15519 case GOMP_MAP_RELEASE:
15520 tkind_zero = GOMP_MAP_ZERO_LEN_ARRAY_SECTION;
15521 break;
15522 case GOMP_MAP_DELETE:
15523 tkind_zero = GOMP_MAP_DELETE_ZERO_LEN_ARRAY_SECTION;
15524 default:
15525 break;
15526 }
15527 if (tkind_zero != tkind)
15528 {
15529 if (integer_zerop (s))
15530 tkind = tkind_zero;
15531 else if (integer_nonzerop (s))
15532 tkind_zero = tkind;
15533 }
bc7bff74 15534 break;
b656be3a 15535 case OMP_CLAUSE_FIRSTPRIVATE:
15536 gcc_checking_assert (is_gimple_omp_oacc (ctx->stmt));
15537 tkind = GOMP_MAP_TO;
15538 tkind_zero = tkind;
15539 break;
bc7bff74 15540 case OMP_CLAUSE_TO:
ca4c3545 15541 tkind = GOMP_MAP_TO;
43895be5 15542 tkind_zero = tkind;
bc7bff74 15543 break;
15544 case OMP_CLAUSE_FROM:
ca4c3545 15545 tkind = GOMP_MAP_FROM;
43895be5 15546 tkind_zero = tkind;
bc7bff74 15547 break;
15548 default:
15549 gcc_unreachable ();
15550 }
ca4c3545 15551 gcc_checking_assert (tkind
15552 < (HOST_WIDE_INT_C (1U) << talign_shift));
43895be5 15553 gcc_checking_assert (tkind_zero
15554 < (HOST_WIDE_INT_C (1U) << talign_shift));
bc7bff74 15555 talign = ceil_log2 (talign);
ca4c3545 15556 tkind |= talign << talign_shift;
43895be5 15557 tkind_zero |= talign << talign_shift;
ca4c3545 15558 gcc_checking_assert (tkind
15559 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
43895be5 15560 gcc_checking_assert (tkind_zero
15561 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
15562 if (tkind == tkind_zero)
15563 x = build_int_cstu (tkind_type, tkind);
15564 else
15565 {
15566 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 0;
15567 x = build3 (COND_EXPR, tkind_type,
15568 fold_build2 (EQ_EXPR, boolean_type_node,
15569 unshare_expr (s), size_zero_node),
15570 build_int_cstu (tkind_type, tkind_zero),
15571 build_int_cstu (tkind_type, tkind));
15572 }
15573 CONSTRUCTOR_APPEND_ELT (vkind, purpose, x);
bc7bff74 15574 if (nc && nc != c)
15575 c = nc;
43895be5 15576 break;
15577
15578 case OMP_CLAUSE_FIRSTPRIVATE:
b656be3a 15579 if (is_oacc_parallel (ctx))
15580 goto oacc_firstprivate_map;
43895be5 15581 ovar = OMP_CLAUSE_DECL (c);
15582 if (is_reference (ovar))
15583 talign = TYPE_ALIGN_UNIT (TREE_TYPE (TREE_TYPE (ovar)));
15584 else
15585 talign = DECL_ALIGN_UNIT (ovar);
15586 var = lookup_decl_in_outer_ctx (ovar, ctx);
15587 x = build_sender_ref (ovar, ctx);
15588 tkind = GOMP_MAP_FIRSTPRIVATE;
15589 type = TREE_TYPE (ovar);
15590 if (is_reference (ovar))
15591 type = TREE_TYPE (type);
15592 bool use_firstprivate_int, force_addr;
15593 use_firstprivate_int = false;
15594 force_addr = false;
15595 if ((INTEGRAL_TYPE_P (type)
15596 && TYPE_PRECISION (type) <= POINTER_SIZE)
15597 || TREE_CODE (type) == POINTER_TYPE)
15598 use_firstprivate_int = true;
15599 if (has_depend)
15600 {
15601 if (is_reference (var))
15602 use_firstprivate_int = false;
15603 else if (is_gimple_reg (var))
15604 {
15605 if (DECL_HAS_VALUE_EXPR_P (var))
15606 {
15607 tree v = get_base_address (var);
15608 if (DECL_P (v) && TREE_ADDRESSABLE (v))
15609 {
15610 use_firstprivate_int = false;
15611 force_addr = true;
15612 }
15613 else
15614 switch (TREE_CODE (v))
15615 {
15616 case INDIRECT_REF:
15617 case MEM_REF:
15618 use_firstprivate_int = false;
15619 force_addr = true;
15620 break;
15621 default:
15622 break;
15623 }
15624 }
15625 }
15626 else
15627 use_firstprivate_int = false;
15628 }
15629 if (use_firstprivate_int)
15630 {
15631 tkind = GOMP_MAP_FIRSTPRIVATE_INT;
15632 tree t = var;
15633 if (is_reference (var))
15634 t = build_simple_mem_ref (var);
15635 if (TREE_CODE (type) != POINTER_TYPE)
15636 t = fold_convert (pointer_sized_int_node, t);
15637 t = fold_convert (TREE_TYPE (x), t);
15638 gimplify_assign (x, t, &ilist);
15639 }
15640 else if (is_reference (var))
15641 gimplify_assign (x, var, &ilist);
15642 else if (!force_addr && is_gimple_reg (var))
15643 {
15644 tree avar = create_tmp_var (TREE_TYPE (var));
15645 mark_addressable (avar);
15646 gimplify_assign (avar, var, &ilist);
15647 avar = build_fold_addr_expr (avar);
15648 gimplify_assign (x, avar, &ilist);
15649 }
15650 else
15651 {
15652 var = build_fold_addr_expr (var);
15653 gimplify_assign (x, var, &ilist);
15654 }
15655 if (tkind == GOMP_MAP_FIRSTPRIVATE_INT)
15656 s = size_int (0);
15657 else if (is_reference (var))
15658 s = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (ovar)));
15659 else
15660 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
15661 s = fold_convert (size_type_node, s);
15662 purpose = size_int (map_idx++);
15663 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
15664 if (TREE_CODE (s) != INTEGER_CST)
15665 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
15666
15667 gcc_checking_assert (tkind
15668 < (HOST_WIDE_INT_C (1U) << talign_shift));
15669 talign = ceil_log2 (talign);
15670 tkind |= talign << talign_shift;
15671 gcc_checking_assert (tkind
15672 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
15673 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
15674 build_int_cstu (tkind_type, tkind));
15675 break;
15676
571b3486 15677 case OMP_CLAUSE_USE_DEVICE:
43895be5 15678 case OMP_CLAUSE_USE_DEVICE_PTR:
15679 case OMP_CLAUSE_IS_DEVICE_PTR:
15680 ovar = OMP_CLAUSE_DECL (c);
15681 var = lookup_decl_in_outer_ctx (ovar, ctx);
15682 x = build_sender_ref (ovar, ctx);
571b3486 15683 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_PTR
15684 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE)
43895be5 15685 tkind = GOMP_MAP_USE_DEVICE_PTR;
15686 else
15687 tkind = GOMP_MAP_FIRSTPRIVATE_INT;
15688 type = TREE_TYPE (ovar);
15689 if (TREE_CODE (type) == ARRAY_TYPE)
15690 var = build_fold_addr_expr (var);
15691 else
15692 {
15693 if (is_reference (ovar))
15694 {
15695 type = TREE_TYPE (type);
15696 if (TREE_CODE (type) != ARRAY_TYPE)
15697 var = build_simple_mem_ref (var);
15698 var = fold_convert (TREE_TYPE (x), var);
15699 }
15700 }
15701 gimplify_assign (x, var, &ilist);
15702 s = size_int (0);
15703 purpose = size_int (map_idx++);
15704 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
15705 gcc_checking_assert (tkind
15706 < (HOST_WIDE_INT_C (1U) << talign_shift));
15707 gcc_checking_assert (tkind
15708 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
15709 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
15710 build_int_cstu (tkind_type, tkind));
15711 break;
bc7bff74 15712 }
15713
15714 gcc_assert (map_idx == map_cnt);
15715
15716 DECL_INITIAL (TREE_VEC_ELT (t, 1))
15717 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)), vsize);
15718 DECL_INITIAL (TREE_VEC_ELT (t, 2))
15719 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 2)), vkind);
43895be5 15720 for (int i = 1; i <= 2; i++)
15721 if (!TREE_STATIC (TREE_VEC_ELT (t, i)))
15722 {
15723 gimple_seq initlist = NULL;
15724 force_gimple_operand (build1 (DECL_EXPR, void_type_node,
15725 TREE_VEC_ELT (t, i)),
15726 &initlist, true, NULL_TREE);
15727 gimple_seq_add_seq (&ilist, initlist);
15728
15729 tree clobber = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, i)),
15730 NULL);
15731 TREE_THIS_VOLATILE (clobber) = 1;
15732 gimple_seq_add_stmt (&olist,
15733 gimple_build_assign (TREE_VEC_ELT (t, i),
15734 clobber));
15735 }
bc7bff74 15736
15737 tree clobber = build_constructor (ctx->record_type, NULL);
15738 TREE_THIS_VOLATILE (clobber) = 1;
15739 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
15740 clobber));
15741 }
15742
15743 /* Once all the expansions are done, sequence all the different
15744 fragments inside gimple_omp_body. */
15745
15746 new_body = NULL;
15747
ca4c3545 15748 if (offloaded
15749 && ctx->record_type)
bc7bff74 15750 {
15751 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
15752 /* fixup_child_record_type might have changed receiver_decl's type. */
15753 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
15754 gimple_seq_add_stmt (&new_body,
15755 gimple_build_assign (ctx->receiver_decl, t));
15756 }
b656be3a 15757 gimple_seq_add_seq (&new_body, fplist);
bc7bff74 15758
43895be5 15759 if (offloaded || data_region)
bc7bff74 15760 {
43895be5 15761 tree prev = NULL_TREE;
15762 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
15763 switch (OMP_CLAUSE_CODE (c))
15764 {
15765 tree var, x;
15766 default:
15767 break;
15768 case OMP_CLAUSE_FIRSTPRIVATE:
b656be3a 15769 if (is_gimple_omp_oacc (ctx->stmt))
15770 break;
43895be5 15771 var = OMP_CLAUSE_DECL (c);
15772 if (is_reference (var)
15773 || is_gimple_reg_type (TREE_TYPE (var)))
15774 {
15775 tree new_var = lookup_decl (var, ctx);
15776 tree type;
15777 type = TREE_TYPE (var);
15778 if (is_reference (var))
15779 type = TREE_TYPE (type);
15780 bool use_firstprivate_int;
15781 use_firstprivate_int = false;
15782 if ((INTEGRAL_TYPE_P (type)
15783 && TYPE_PRECISION (type) <= POINTER_SIZE)
15784 || TREE_CODE (type) == POINTER_TYPE)
15785 use_firstprivate_int = true;
15786 if (has_depend)
15787 {
15788 tree v = lookup_decl_in_outer_ctx (var, ctx);
15789 if (is_reference (v))
15790 use_firstprivate_int = false;
15791 else if (is_gimple_reg (v))
15792 {
15793 if (DECL_HAS_VALUE_EXPR_P (v))
15794 {
15795 v = get_base_address (v);
15796 if (DECL_P (v) && TREE_ADDRESSABLE (v))
15797 use_firstprivate_int = false;
15798 else
15799 switch (TREE_CODE (v))
15800 {
15801 case INDIRECT_REF:
15802 case MEM_REF:
15803 use_firstprivate_int = false;
15804 break;
15805 default:
15806 break;
15807 }
15808 }
15809 }
15810 else
15811 use_firstprivate_int = false;
15812 }
15813 if (use_firstprivate_int)
15814 {
15815 x = build_receiver_ref (var, false, ctx);
15816 if (TREE_CODE (type) != POINTER_TYPE)
15817 x = fold_convert (pointer_sized_int_node, x);
15818 x = fold_convert (type, x);
15819 gimplify_expr (&x, &new_body, NULL, is_gimple_val,
15820 fb_rvalue);
15821 if (is_reference (var))
15822 {
15823 tree v = create_tmp_var_raw (type, get_name (var));
15824 gimple_add_tmp_var (v);
15825 TREE_ADDRESSABLE (v) = 1;
15826 gimple_seq_add_stmt (&new_body,
15827 gimple_build_assign (v, x));
15828 x = build_fold_addr_expr (v);
15829 }
15830 gimple_seq_add_stmt (&new_body,
15831 gimple_build_assign (new_var, x));
15832 }
15833 else
15834 {
15835 x = build_receiver_ref (var, !is_reference (var), ctx);
15836 gimplify_expr (&x, &new_body, NULL, is_gimple_val,
15837 fb_rvalue);
15838 gimple_seq_add_stmt (&new_body,
15839 gimple_build_assign (new_var, x));
15840 }
15841 }
15842 else if (is_variable_sized (var))
15843 {
15844 tree pvar = DECL_VALUE_EXPR (var);
15845 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15846 pvar = TREE_OPERAND (pvar, 0);
15847 gcc_assert (DECL_P (pvar));
15848 tree new_var = lookup_decl (pvar, ctx);
15849 x = build_receiver_ref (var, false, ctx);
15850 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
15851 gimple_seq_add_stmt (&new_body,
15852 gimple_build_assign (new_var, x));
15853 }
15854 break;
15855 case OMP_CLAUSE_PRIVATE:
b656be3a 15856 if (is_gimple_omp_oacc (ctx->stmt))
15857 break;
43895be5 15858 var = OMP_CLAUSE_DECL (c);
15859 if (is_reference (var))
15860 {
15861 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
15862 tree new_var = lookup_decl (var, ctx);
15863 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
15864 if (TREE_CONSTANT (x))
15865 {
15866 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
15867 get_name (var));
15868 gimple_add_tmp_var (x);
15869 TREE_ADDRESSABLE (x) = 1;
15870 x = build_fold_addr_expr_loc (clause_loc, x);
15871 }
15872 else
15873 {
15874 tree atmp
15875 = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
15876 tree rtype = TREE_TYPE (TREE_TYPE (new_var));
15877 tree al = size_int (TYPE_ALIGN (rtype));
15878 x = build_call_expr_loc (clause_loc, atmp, 2, x, al);
15879 }
15880
15881 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
15882 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
15883 gimple_seq_add_stmt (&new_body,
15884 gimple_build_assign (new_var, x));
15885 }
15886 break;
571b3486 15887 case OMP_CLAUSE_USE_DEVICE:
43895be5 15888 case OMP_CLAUSE_USE_DEVICE_PTR:
15889 case OMP_CLAUSE_IS_DEVICE_PTR:
15890 var = OMP_CLAUSE_DECL (c);
571b3486 15891 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_PTR
15892 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE)
43895be5 15893 x = build_sender_ref (var, ctx);
15894 else
15895 x = build_receiver_ref (var, false, ctx);
15896 if (is_variable_sized (var))
15897 {
15898 tree pvar = DECL_VALUE_EXPR (var);
15899 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15900 pvar = TREE_OPERAND (pvar, 0);
15901 gcc_assert (DECL_P (pvar));
15902 tree new_var = lookup_decl (pvar, ctx);
15903 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
15904 gimple_seq_add_stmt (&new_body,
15905 gimple_build_assign (new_var, x));
15906 }
15907 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
15908 {
15909 tree new_var = lookup_decl (var, ctx);
15910 new_var = DECL_VALUE_EXPR (new_var);
15911 gcc_assert (TREE_CODE (new_var) == MEM_REF);
15912 new_var = TREE_OPERAND (new_var, 0);
15913 gcc_assert (DECL_P (new_var));
15914 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
15915 gimple_seq_add_stmt (&new_body,
15916 gimple_build_assign (new_var, x));
15917 }
15918 else
15919 {
15920 tree type = TREE_TYPE (var);
15921 tree new_var = lookup_decl (var, ctx);
15922 if (is_reference (var))
15923 {
15924 type = TREE_TYPE (type);
15925 if (TREE_CODE (type) != ARRAY_TYPE)
15926 {
15927 tree v = create_tmp_var_raw (type, get_name (var));
15928 gimple_add_tmp_var (v);
15929 TREE_ADDRESSABLE (v) = 1;
15930 x = fold_convert (type, x);
15931 gimplify_expr (&x, &new_body, NULL, is_gimple_val,
15932 fb_rvalue);
15933 gimple_seq_add_stmt (&new_body,
15934 gimple_build_assign (v, x));
15935 x = build_fold_addr_expr (v);
15936 }
15937 }
15938 x = fold_convert (TREE_TYPE (new_var), x);
15939 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
15940 gimple_seq_add_stmt (&new_body,
15941 gimple_build_assign (new_var, x));
15942 }
15943 break;
15944 }
9561765e 15945 /* Handle GOMP_MAP_FIRSTPRIVATE_{POINTER,REFERENCE} in second pass,
43895be5 15946 so that firstprivate vars holding OMP_CLAUSE_SIZE if needed
15947 are already handled. */
b656be3a 15948 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
43895be5 15949 switch (OMP_CLAUSE_CODE (c))
15950 {
15951 tree var;
15952 default:
15953 break;
15954 case OMP_CLAUSE_MAP:
9561765e 15955 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
15956 || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_REFERENCE)
43895be5 15957 {
15958 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
15959 HOST_WIDE_INT offset = 0;
15960 gcc_assert (prev);
15961 var = OMP_CLAUSE_DECL (c);
15962 if (DECL_P (var)
15963 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
15964 && is_global_var (maybe_lookup_decl_in_outer_ctx (var,
15965 ctx))
15966 && varpool_node::get_create (var)->offloadable)
15967 break;
15968 if (TREE_CODE (var) == INDIRECT_REF
15969 && TREE_CODE (TREE_OPERAND (var, 0)) == COMPONENT_REF)
15970 var = TREE_OPERAND (var, 0);
15971 if (TREE_CODE (var) == COMPONENT_REF)
15972 {
15973 var = get_addr_base_and_unit_offset (var, &offset);
15974 gcc_assert (var != NULL_TREE && DECL_P (var));
15975 }
15976 else if (DECL_SIZE (var)
15977 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
15978 {
15979 tree var2 = DECL_VALUE_EXPR (var);
15980 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
15981 var2 = TREE_OPERAND (var2, 0);
15982 gcc_assert (DECL_P (var2));
15983 var = var2;
15984 }
15985 tree new_var = lookup_decl (var, ctx), x;
15986 tree type = TREE_TYPE (new_var);
15987 bool is_ref;
15988 if (TREE_CODE (OMP_CLAUSE_DECL (c)) == INDIRECT_REF
15989 && (TREE_CODE (TREE_OPERAND (OMP_CLAUSE_DECL (c), 0))
15990 == COMPONENT_REF))
15991 {
15992 type = TREE_TYPE (TREE_OPERAND (OMP_CLAUSE_DECL (c), 0));
15993 is_ref = true;
15994 new_var = build2 (MEM_REF, type,
15995 build_fold_addr_expr (new_var),
15996 build_int_cst (build_pointer_type (type),
15997 offset));
15998 }
15999 else if (TREE_CODE (OMP_CLAUSE_DECL (c)) == COMPONENT_REF)
16000 {
16001 type = TREE_TYPE (OMP_CLAUSE_DECL (c));
16002 is_ref = TREE_CODE (type) == REFERENCE_TYPE;
16003 new_var = build2 (MEM_REF, type,
16004 build_fold_addr_expr (new_var),
16005 build_int_cst (build_pointer_type (type),
16006 offset));
16007 }
16008 else
16009 is_ref = is_reference (var);
9561765e 16010 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_REFERENCE)
16011 is_ref = false;
43895be5 16012 bool ref_to_array = false;
16013 if (is_ref)
16014 {
16015 type = TREE_TYPE (type);
16016 if (TREE_CODE (type) == ARRAY_TYPE)
16017 {
16018 type = build_pointer_type (type);
16019 ref_to_array = true;
16020 }
16021 }
16022 else if (TREE_CODE (type) == ARRAY_TYPE)
16023 {
16024 tree decl2 = DECL_VALUE_EXPR (new_var);
16025 gcc_assert (TREE_CODE (decl2) == MEM_REF);
16026 decl2 = TREE_OPERAND (decl2, 0);
16027 gcc_assert (DECL_P (decl2));
16028 new_var = decl2;
16029 type = TREE_TYPE (new_var);
16030 }
16031 x = build_receiver_ref (OMP_CLAUSE_DECL (prev), false, ctx);
16032 x = fold_convert_loc (clause_loc, type, x);
16033 if (!integer_zerop (OMP_CLAUSE_SIZE (c)))
16034 {
16035 tree bias = OMP_CLAUSE_SIZE (c);
16036 if (DECL_P (bias))
16037 bias = lookup_decl (bias, ctx);
16038 bias = fold_convert_loc (clause_loc, sizetype, bias);
16039 bias = fold_build1_loc (clause_loc, NEGATE_EXPR, sizetype,
16040 bias);
16041 x = fold_build2_loc (clause_loc, POINTER_PLUS_EXPR,
16042 TREE_TYPE (x), x, bias);
16043 }
16044 if (ref_to_array)
16045 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
16046 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16047 if (is_ref && !ref_to_array)
16048 {
16049 tree t = create_tmp_var_raw (type, get_name (var));
16050 gimple_add_tmp_var (t);
16051 TREE_ADDRESSABLE (t) = 1;
16052 gimple_seq_add_stmt (&new_body,
16053 gimple_build_assign (t, x));
16054 x = build_fold_addr_expr_loc (clause_loc, t);
16055 }
16056 gimple_seq_add_stmt (&new_body,
16057 gimple_build_assign (new_var, x));
16058 prev = NULL_TREE;
16059 }
16060 else if (OMP_CLAUSE_CHAIN (c)
16061 && OMP_CLAUSE_CODE (OMP_CLAUSE_CHAIN (c))
16062 == OMP_CLAUSE_MAP
9561765e 16063 && (OMP_CLAUSE_MAP_KIND (OMP_CLAUSE_CHAIN (c))
16064 == GOMP_MAP_FIRSTPRIVATE_POINTER
16065 || (OMP_CLAUSE_MAP_KIND (OMP_CLAUSE_CHAIN (c))
16066 == GOMP_MAP_FIRSTPRIVATE_REFERENCE)))
43895be5 16067 prev = c;
16068 break;
16069 case OMP_CLAUSE_PRIVATE:
16070 var = OMP_CLAUSE_DECL (c);
16071 if (is_variable_sized (var))
16072 {
16073 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
16074 tree new_var = lookup_decl (var, ctx);
16075 tree pvar = DECL_VALUE_EXPR (var);
16076 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
16077 pvar = TREE_OPERAND (pvar, 0);
16078 gcc_assert (DECL_P (pvar));
16079 tree new_pvar = lookup_decl (pvar, ctx);
16080 tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
16081 tree al = size_int (DECL_ALIGN (var));
16082 tree x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
16083 x = build_call_expr_loc (clause_loc, atmp, 2, x, al);
16084 x = fold_convert_loc (clause_loc, TREE_TYPE (new_pvar), x);
16085 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16086 gimple_seq_add_stmt (&new_body,
16087 gimple_build_assign (new_pvar, x));
16088 }
16089 break;
16090 }
2eab8648 16091
641a0fa1 16092 gimple_seq fork_seq = NULL;
16093 gimple_seq join_seq = NULL;
16094
16095 if (is_oacc_parallel (ctx))
16096 {
16097 /* If there are reductions on the offloaded region itself, treat
16098 them as a dummy GANG loop. */
16099 tree level = build_int_cst (integer_type_node, GOMP_DIM_GANG);
16100
16101 lower_oacc_reductions (gimple_location (ctx->stmt), clauses, level,
16102 false, NULL, NULL, &fork_seq, &join_seq, ctx);
16103 }
16104
16105 gimple_seq_add_seq (&new_body, fork_seq);
bc7bff74 16106 gimple_seq_add_seq (&new_body, tgt_body);
641a0fa1 16107 gimple_seq_add_seq (&new_body, join_seq);
2eab8648 16108
43895be5 16109 if (offloaded)
16110 new_body = maybe_catch_exception (new_body);
2eab8648 16111
bc7bff74 16112 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
16113 gimple_omp_set_body (stmt, new_body);
16114 }
16115
16116 bind = gimple_build_bind (NULL, NULL,
16117 tgt_bind ? gimple_bind_block (tgt_bind)
16118 : NULL_TREE);
43895be5 16119 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
e3a19533 16120 gimple_bind_add_seq (bind, ilist);
16121 gimple_bind_add_stmt (bind, stmt);
16122 gimple_bind_add_seq (bind, olist);
773c5ba7 16123
75a70cf9 16124 pop_gimplify_context (NULL);
43895be5 16125
16126 if (dep_bind)
16127 {
16128 gimple_bind_add_seq (dep_bind, dep_ilist);
16129 gimple_bind_add_stmt (dep_bind, bind);
16130 gimple_bind_add_seq (dep_bind, dep_olist);
16131 pop_gimplify_context (dep_bind);
16132 }
773c5ba7 16133}
16134
bc7bff74 16135/* Expand code for an OpenMP teams directive. */
16136
16137static void
16138lower_omp_teams (gimple_stmt_iterator *gsi_p, omp_context *ctx)
16139{
1a91d914 16140 gomp_teams *teams_stmt = as_a <gomp_teams *> (gsi_stmt (*gsi_p));
8a4a28a8 16141 push_gimplify_context ();
bc7bff74 16142
16143 tree block = make_node (BLOCK);
1a91d914 16144 gbind *bind = gimple_build_bind (NULL, NULL, block);
bc7bff74 16145 gsi_replace (gsi_p, bind, true);
16146 gimple_seq bind_body = NULL;
16147 gimple_seq dlist = NULL;
16148 gimple_seq olist = NULL;
16149
16150 tree num_teams = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
16151 OMP_CLAUSE_NUM_TEAMS);
16152 if (num_teams == NULL_TREE)
16153 num_teams = build_int_cst (unsigned_type_node, 0);
16154 else
16155 {
16156 num_teams = OMP_CLAUSE_NUM_TEAMS_EXPR (num_teams);
16157 num_teams = fold_convert (unsigned_type_node, num_teams);
16158 gimplify_expr (&num_teams, &bind_body, NULL, is_gimple_val, fb_rvalue);
16159 }
16160 tree thread_limit = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
16161 OMP_CLAUSE_THREAD_LIMIT);
16162 if (thread_limit == NULL_TREE)
16163 thread_limit = build_int_cst (unsigned_type_node, 0);
16164 else
16165 {
16166 thread_limit = OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit);
16167 thread_limit = fold_convert (unsigned_type_node, thread_limit);
16168 gimplify_expr (&thread_limit, &bind_body, NULL, is_gimple_val,
16169 fb_rvalue);
16170 }
16171
16172 lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt),
16173 &bind_body, &dlist, ctx, NULL);
16174 lower_omp (gimple_omp_body_ptr (teams_stmt), ctx);
16175 lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt), &olist, ctx);
16176 gimple_seq_add_stmt (&bind_body, teams_stmt);
16177
16178 location_t loc = gimple_location (teams_stmt);
16179 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TEAMS);
42acab1c 16180 gimple *call = gimple_build_call (decl, 2, num_teams, thread_limit);
bc7bff74 16181 gimple_set_location (call, loc);
16182 gimple_seq_add_stmt (&bind_body, call);
16183
16184 gimple_seq_add_seq (&bind_body, gimple_omp_body (teams_stmt));
16185 gimple_omp_set_body (teams_stmt, NULL);
16186 gimple_seq_add_seq (&bind_body, olist);
16187 gimple_seq_add_seq (&bind_body, dlist);
16188 gimple_seq_add_stmt (&bind_body, gimple_build_omp_return (true));
16189 gimple_bind_set_body (bind, bind_body);
16190
16191 pop_gimplify_context (bind);
16192
16193 gimple_bind_append_vars (bind, ctx->block_vars);
16194 BLOCK_VARS (block) = ctx->block_vars;
16195 if (BLOCK_VARS (block))
16196 TREE_USED (block) = 1;
16197}
16198
16199
a4890dc9 16200/* Callback for lower_omp_1. Return non-NULL if *tp needs to be
75a70cf9 16201 regimplified. If DATA is non-NULL, lower_omp_1 is outside
ca4c3545 16202 of OMP context, but with task_shared_vars set. */
46515c92 16203
16204static tree
75a70cf9 16205lower_omp_regimplify_p (tree *tp, int *walk_subtrees,
16206 void *data)
46515c92 16207{
a4890dc9 16208 tree t = *tp;
46515c92 16209
a4890dc9 16210 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
75a70cf9 16211 if (TREE_CODE (t) == VAR_DECL && data == NULL && DECL_HAS_VALUE_EXPR_P (t))
9f49e155 16212 return t;
16213
16214 if (task_shared_vars
16215 && DECL_P (t)
16216 && bitmap_bit_p (task_shared_vars, DECL_UID (t)))
a4890dc9 16217 return t;
46515c92 16218
a4890dc9 16219 /* If a global variable has been privatized, TREE_CONSTANT on
16220 ADDR_EXPR might be wrong. */
75a70cf9 16221 if (data == NULL && TREE_CODE (t) == ADDR_EXPR)
a4890dc9 16222 recompute_tree_invariant_for_addr_expr (t);
46515c92 16223
43895be5 16224 *walk_subtrees = !IS_TYPE_OR_DECL_P (t);
16225 return NULL_TREE;
16226}
16227
16228/* Data to be communicated between lower_omp_regimplify_operands and
16229 lower_omp_regimplify_operands_p. */
16230
16231struct lower_omp_regimplify_operands_data
16232{
16233 omp_context *ctx;
16234 vec<tree> *decls;
16235};
16236
16237/* Helper function for lower_omp_regimplify_operands. Find
16238 omp_member_access_dummy_var vars and adjust temporarily their
16239 DECL_VALUE_EXPRs if needed. */
16240
16241static tree
16242lower_omp_regimplify_operands_p (tree *tp, int *walk_subtrees,
16243 void *data)
16244{
16245 tree t = omp_member_access_dummy_var (*tp);
16246 if (t)
16247 {
16248 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
16249 lower_omp_regimplify_operands_data *ldata
16250 = (lower_omp_regimplify_operands_data *) wi->info;
16251 tree o = maybe_lookup_decl (t, ldata->ctx);
16252 if (o != t)
16253 {
16254 ldata->decls->safe_push (DECL_VALUE_EXPR (*tp));
16255 ldata->decls->safe_push (*tp);
16256 tree v = unshare_and_remap (DECL_VALUE_EXPR (*tp), t, o);
16257 SET_DECL_VALUE_EXPR (*tp, v);
16258 }
16259 }
16260 *walk_subtrees = !IS_TYPE_OR_DECL_P (*tp);
a4890dc9 16261 return NULL_TREE;
46515c92 16262}
773c5ba7 16263
43895be5 16264/* Wrapper around gimple_regimplify_operands that adjusts DECL_VALUE_EXPRs
16265 of omp_member_access_dummy_var vars during regimplification. */
16266
16267static void
16268lower_omp_regimplify_operands (omp_context *ctx, gimple *stmt,
16269 gimple_stmt_iterator *gsi_p)
16270{
16271 auto_vec<tree, 10> decls;
16272 if (ctx)
16273 {
16274 struct walk_stmt_info wi;
16275 memset (&wi, '\0', sizeof (wi));
16276 struct lower_omp_regimplify_operands_data data;
16277 data.ctx = ctx;
16278 data.decls = &decls;
16279 wi.info = &data;
16280 walk_gimple_op (stmt, lower_omp_regimplify_operands_p, &wi);
16281 }
16282 gimple_regimplify_operands (stmt, gsi_p);
16283 while (!decls.is_empty ())
16284 {
16285 tree t = decls.pop ();
16286 tree v = decls.pop ();
16287 SET_DECL_VALUE_EXPR (t, v);
16288 }
16289}
16290
a4890dc9 16291static void
75a70cf9 16292lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
1e8e9920 16293{
42acab1c 16294 gimple *stmt = gsi_stmt (*gsi_p);
75a70cf9 16295 struct walk_stmt_info wi;
1a91d914 16296 gcall *call_stmt;
1e8e9920 16297
75a70cf9 16298 if (gimple_has_location (stmt))
16299 input_location = gimple_location (stmt);
a4890dc9 16300
75a70cf9 16301 if (task_shared_vars)
16302 memset (&wi, '\0', sizeof (wi));
a4890dc9 16303
773c5ba7 16304 /* If we have issued syntax errors, avoid doing any heavy lifting.
ca4c3545 16305 Just replace the OMP directives with a NOP to avoid
773c5ba7 16306 confusing RTL expansion. */
852f689e 16307 if (seen_error () && is_gimple_omp (stmt))
773c5ba7 16308 {
75a70cf9 16309 gsi_replace (gsi_p, gimple_build_nop (), true);
a4890dc9 16310 return;
773c5ba7 16311 }
16312
75a70cf9 16313 switch (gimple_code (stmt))
1e8e9920 16314 {
75a70cf9 16315 case GIMPLE_COND:
1a91d914 16316 {
16317 gcond *cond_stmt = as_a <gcond *> (stmt);
16318 if ((ctx || task_shared_vars)
16319 && (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
16320 lower_omp_regimplify_p,
16321 ctx ? NULL : &wi, NULL)
16322 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
16323 lower_omp_regimplify_p,
16324 ctx ? NULL : &wi, NULL)))
43895be5 16325 lower_omp_regimplify_operands (ctx, cond_stmt, gsi_p);
1a91d914 16326 }
a4890dc9 16327 break;
75a70cf9 16328 case GIMPLE_CATCH:
1a91d914 16329 lower_omp (gimple_catch_handler_ptr (as_a <gcatch *> (stmt)), ctx);
a4890dc9 16330 break;
75a70cf9 16331 case GIMPLE_EH_FILTER:
e3a19533 16332 lower_omp (gimple_eh_filter_failure_ptr (stmt), ctx);
a4890dc9 16333 break;
75a70cf9 16334 case GIMPLE_TRY:
e3a19533 16335 lower_omp (gimple_try_eval_ptr (stmt), ctx);
16336 lower_omp (gimple_try_cleanup_ptr (stmt), ctx);
a4890dc9 16337 break;
35215227 16338 case GIMPLE_TRANSACTION:
1a91d914 16339 lower_omp (gimple_transaction_body_ptr (
16340 as_a <gtransaction *> (stmt)),
16341 ctx);
35215227 16342 break;
75a70cf9 16343 case GIMPLE_BIND:
1a91d914 16344 lower_omp (gimple_bind_body_ptr (as_a <gbind *> (stmt)), ctx);
a4890dc9 16345 break;
75a70cf9 16346 case GIMPLE_OMP_PARALLEL:
16347 case GIMPLE_OMP_TASK:
16348 ctx = maybe_lookup_ctx (stmt);
bc7bff74 16349 gcc_assert (ctx);
16350 if (ctx->cancellable)
16351 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
75a70cf9 16352 lower_omp_taskreg (gsi_p, ctx);
a4890dc9 16353 break;
75a70cf9 16354 case GIMPLE_OMP_FOR:
16355 ctx = maybe_lookup_ctx (stmt);
1e8e9920 16356 gcc_assert (ctx);
bc7bff74 16357 if (ctx->cancellable)
16358 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
75a70cf9 16359 lower_omp_for (gsi_p, ctx);
1e8e9920 16360 break;
75a70cf9 16361 case GIMPLE_OMP_SECTIONS:
16362 ctx = maybe_lookup_ctx (stmt);
1e8e9920 16363 gcc_assert (ctx);
bc7bff74 16364 if (ctx->cancellable)
16365 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
75a70cf9 16366 lower_omp_sections (gsi_p, ctx);
1e8e9920 16367 break;
75a70cf9 16368 case GIMPLE_OMP_SINGLE:
16369 ctx = maybe_lookup_ctx (stmt);
1e8e9920 16370 gcc_assert (ctx);
75a70cf9 16371 lower_omp_single (gsi_p, ctx);
1e8e9920 16372 break;
75a70cf9 16373 case GIMPLE_OMP_MASTER:
16374 ctx = maybe_lookup_ctx (stmt);
1e8e9920 16375 gcc_assert (ctx);
75a70cf9 16376 lower_omp_master (gsi_p, ctx);
1e8e9920 16377 break;
bc7bff74 16378 case GIMPLE_OMP_TASKGROUP:
16379 ctx = maybe_lookup_ctx (stmt);
16380 gcc_assert (ctx);
16381 lower_omp_taskgroup (gsi_p, ctx);
16382 break;
75a70cf9 16383 case GIMPLE_OMP_ORDERED:
16384 ctx = maybe_lookup_ctx (stmt);
1e8e9920 16385 gcc_assert (ctx);
75a70cf9 16386 lower_omp_ordered (gsi_p, ctx);
1e8e9920 16387 break;
75a70cf9 16388 case GIMPLE_OMP_CRITICAL:
16389 ctx = maybe_lookup_ctx (stmt);
1e8e9920 16390 gcc_assert (ctx);
75a70cf9 16391 lower_omp_critical (gsi_p, ctx);
16392 break;
16393 case GIMPLE_OMP_ATOMIC_LOAD:
16394 if ((ctx || task_shared_vars)
1a91d914 16395 && walk_tree (gimple_omp_atomic_load_rhs_ptr (
16396 as_a <gomp_atomic_load *> (stmt)),
75a70cf9 16397 lower_omp_regimplify_p, ctx ? NULL : &wi, NULL))
43895be5 16398 lower_omp_regimplify_operands (ctx, stmt, gsi_p);
1e8e9920 16399 break;
bc7bff74 16400 case GIMPLE_OMP_TARGET:
16401 ctx = maybe_lookup_ctx (stmt);
16402 gcc_assert (ctx);
16403 lower_omp_target (gsi_p, ctx);
16404 break;
16405 case GIMPLE_OMP_TEAMS:
16406 ctx = maybe_lookup_ctx (stmt);
16407 gcc_assert (ctx);
16408 lower_omp_teams (gsi_p, ctx);
16409 break;
16410 case GIMPLE_CALL:
16411 tree fndecl;
1a91d914 16412 call_stmt = as_a <gcall *> (stmt);
16413 fndecl = gimple_call_fndecl (call_stmt);
bc7bff74 16414 if (fndecl
16415 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
16416 switch (DECL_FUNCTION_CODE (fndecl))
16417 {
16418 case BUILT_IN_GOMP_BARRIER:
16419 if (ctx == NULL)
16420 break;
16421 /* FALLTHRU */
16422 case BUILT_IN_GOMP_CANCEL:
16423 case BUILT_IN_GOMP_CANCELLATION_POINT:
16424 omp_context *cctx;
16425 cctx = ctx;
16426 if (gimple_code (cctx->stmt) == GIMPLE_OMP_SECTION)
16427 cctx = cctx->outer;
1a91d914 16428 gcc_assert (gimple_call_lhs (call_stmt) == NULL_TREE);
bc7bff74 16429 if (!cctx->cancellable)
16430 {
16431 if (DECL_FUNCTION_CODE (fndecl)
16432 == BUILT_IN_GOMP_CANCELLATION_POINT)
16433 {
16434 stmt = gimple_build_nop ();
16435 gsi_replace (gsi_p, stmt, false);
16436 }
16437 break;
16438 }
bc7bff74 16439 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
16440 {
16441 fndecl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL);
1a91d914 16442 gimple_call_set_fndecl (call_stmt, fndecl);
16443 gimple_call_set_fntype (call_stmt, TREE_TYPE (fndecl));
bc7bff74 16444 }
15b28553 16445 tree lhs;
f9e245b2 16446 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (fndecl)));
1a91d914 16447 gimple_call_set_lhs (call_stmt, lhs);
bc7bff74 16448 tree fallthru_label;
16449 fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
42acab1c 16450 gimple *g;
bc7bff74 16451 g = gimple_build_label (fallthru_label);
16452 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
15b28553 16453 g = gimple_build_cond (NE_EXPR, lhs,
16454 fold_convert (TREE_TYPE (lhs),
16455 boolean_false_node),
bc7bff74 16456 cctx->cancel_label, fallthru_label);
16457 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
16458 break;
16459 default:
16460 break;
16461 }
16462 /* FALLTHRU */
a4890dc9 16463 default:
fd6481cf 16464 if ((ctx || task_shared_vars)
75a70cf9 16465 && walk_gimple_op (stmt, lower_omp_regimplify_p,
16466 ctx ? NULL : &wi))
ef8cfd4d 16467 {
16468 /* Just remove clobbers, this should happen only if we have
16469 "privatized" local addressable variables in SIMD regions,
16470 the clobber isn't needed in that case and gimplifying address
16471 of the ARRAY_REF into a pointer and creating MEM_REF based
16472 clobber would create worse code than we get with the clobber
16473 dropped. */
16474 if (gimple_clobber_p (stmt))
16475 {
16476 gsi_replace (gsi_p, gimple_build_nop (), true);
16477 break;
16478 }
43895be5 16479 lower_omp_regimplify_operands (ctx, stmt, gsi_p);
ef8cfd4d 16480 }
1e8e9920 16481 break;
1e8e9920 16482 }
1e8e9920 16483}
16484
16485static void
e3a19533 16486lower_omp (gimple_seq *body, omp_context *ctx)
1e8e9920 16487{
1d22f541 16488 location_t saved_location = input_location;
e3a19533 16489 gimple_stmt_iterator gsi;
16490 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
75a70cf9 16491 lower_omp_1 (&gsi, ctx);
ca4c3545 16492 /* During gimplification, we haven't folded statments inside offloading
c3a81971 16493 or taskreg regions (gimplify.c:maybe_fold_stmt); do that now. */
16494 if (target_nesting_level || taskreg_nesting_level)
bc7bff74 16495 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
16496 fold_stmt (&gsi);
1d22f541 16497 input_location = saved_location;
1e8e9920 16498}
16499\f
16500/* Main entry point. */
16501
2a1990e9 16502static unsigned int
1e8e9920 16503execute_lower_omp (void)
16504{
75a70cf9 16505 gimple_seq body;
37eaded9 16506 int i;
16507 omp_context *ctx;
75a70cf9 16508
41709826 16509 /* This pass always runs, to provide PROP_gimple_lomp.
ca4c3545 16510 But often, there is nothing to do. */
16511 if (flag_cilkplus == 0 && flag_openacc == 0 && flag_openmp == 0
16512 && flag_openmp_simd == 0)
41709826 16513 return 0;
16514
1e8e9920 16515 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
16516 delete_omp_context);
16517
75a70cf9 16518 body = gimple_body (current_function_decl);
ab129075 16519 scan_omp (&body, NULL);
fd6481cf 16520 gcc_assert (taskreg_nesting_level == 0);
37eaded9 16521 FOR_EACH_VEC_ELT (taskreg_contexts, i, ctx)
16522 finish_taskreg_scan (ctx);
16523 taskreg_contexts.release ();
1e8e9920 16524
16525 if (all_contexts->root)
fd6481cf 16526 {
16527 if (task_shared_vars)
8a4a28a8 16528 push_gimplify_context ();
e3a19533 16529 lower_omp (&body, NULL);
fd6481cf 16530 if (task_shared_vars)
16531 pop_gimplify_context (NULL);
16532 }
1e8e9920 16533
773c5ba7 16534 if (all_contexts)
16535 {
16536 splay_tree_delete (all_contexts);
16537 all_contexts = NULL;
16538 }
fd6481cf 16539 BITMAP_FREE (task_shared_vars);
2a1990e9 16540 return 0;
1e8e9920 16541}
16542
7620bc82 16543namespace {
16544
16545const pass_data pass_data_lower_omp =
cbe8bda8 16546{
16547 GIMPLE_PASS, /* type */
16548 "omplower", /* name */
16549 OPTGROUP_NONE, /* optinfo_flags */
cbe8bda8 16550 TV_NONE, /* tv_id */
16551 PROP_gimple_any, /* properties_required */
16552 PROP_gimple_lomp, /* properties_provided */
16553 0, /* properties_destroyed */
16554 0, /* todo_flags_start */
16555 0, /* todo_flags_finish */
1e8e9920 16556};
cbe8bda8 16557
7620bc82 16558class pass_lower_omp : public gimple_opt_pass
cbe8bda8 16559{
16560public:
9af5ce0c 16561 pass_lower_omp (gcc::context *ctxt)
16562 : gimple_opt_pass (pass_data_lower_omp, ctxt)
cbe8bda8 16563 {}
16564
16565 /* opt_pass methods: */
65b0537f 16566 virtual unsigned int execute (function *) { return execute_lower_omp (); }
cbe8bda8 16567
16568}; // class pass_lower_omp
16569
7620bc82 16570} // anon namespace
16571
cbe8bda8 16572gimple_opt_pass *
16573make_pass_lower_omp (gcc::context *ctxt)
16574{
16575 return new pass_lower_omp (ctxt);
16576}
1e8e9920 16577\f
ca4c3545 16578/* The following is a utility to diagnose structured block violations.
61e47ac8 16579 It is not part of the "omplower" pass, as that's invoked too late. It
16580 should be invoked by the respective front ends after gimplification. */
1e8e9920 16581
16582static splay_tree all_labels;
16583
16584/* Check for mismatched contexts and generate an error if needed. Return
16585 true if an error is detected. */
16586
16587static bool
75a70cf9 16588diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
42acab1c 16589 gimple *branch_ctx, gimple *label_ctx)
1e8e9920 16590{
ca4c3545 16591 gcc_checking_assert (!branch_ctx || is_gimple_omp (branch_ctx));
16592 gcc_checking_assert (!label_ctx || is_gimple_omp (label_ctx));
16593
75a70cf9 16594 if (label_ctx == branch_ctx)
1e8e9920 16595 return false;
16596
ca4c3545 16597 const char* kind = NULL;
16598
16599 if (flag_cilkplus)
16600 {
16601 if ((branch_ctx
16602 && gimple_code (branch_ctx) == GIMPLE_OMP_FOR
16603 && gimple_omp_for_kind (branch_ctx) == GF_OMP_FOR_KIND_CILKSIMD)
16604 || (label_ctx
16605 && gimple_code (label_ctx) == GIMPLE_OMP_FOR
16606 && gimple_omp_for_kind (label_ctx) == GF_OMP_FOR_KIND_CILKSIMD))
16607 kind = "Cilk Plus";
16608 }
16609 if (flag_openacc)
16610 {
16611 if ((branch_ctx && is_gimple_omp_oacc (branch_ctx))
16612 || (label_ctx && is_gimple_omp_oacc (label_ctx)))
16613 {
16614 gcc_checking_assert (kind == NULL);
16615 kind = "OpenACC";
16616 }
16617 }
16618 if (kind == NULL)
16619 {
16620 gcc_checking_assert (flag_openmp);
16621 kind = "OpenMP";
16622 }
48e1416a 16623
75a70cf9 16624 /*
16625 Previously we kept track of the label's entire context in diagnose_sb_[12]
16626 so we could traverse it and issue a correct "exit" or "enter" error
16627 message upon a structured block violation.
16628
16629 We built the context by building a list with tree_cons'ing, but there is
16630 no easy counterpart in gimple tuples. It seems like far too much work
16631 for issuing exit/enter error messages. If someone really misses the
16632 distinct error message... patches welcome.
16633 */
48e1416a 16634
75a70cf9 16635#if 0
1e8e9920 16636 /* Try to avoid confusing the user by producing and error message
f0b5f617 16637 with correct "exit" or "enter" verbiage. We prefer "exit"
1e8e9920 16638 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
16639 if (branch_ctx == NULL)
16640 exit_p = false;
16641 else
16642 {
16643 while (label_ctx)
16644 {
16645 if (TREE_VALUE (label_ctx) == branch_ctx)
16646 {
16647 exit_p = false;
16648 break;
16649 }
16650 label_ctx = TREE_CHAIN (label_ctx);
16651 }
16652 }
16653
16654 if (exit_p)
ca4c3545 16655 error ("invalid exit from %s structured block", kind);
1e8e9920 16656 else
ca4c3545 16657 error ("invalid entry to %s structured block", kind);
75a70cf9 16658#endif
1e8e9920 16659
75a70cf9 16660 /* If it's obvious we have an invalid entry, be specific about the error. */
16661 if (branch_ctx == NULL)
ca4c3545 16662 error ("invalid entry to %s structured block", kind);
75a70cf9 16663 else
f2697631 16664 {
16665 /* Otherwise, be vague and lazy, but efficient. */
ca4c3545 16666 error ("invalid branch to/from %s structured block", kind);
f2697631 16667 }
75a70cf9 16668
16669 gsi_replace (gsi_p, gimple_build_nop (), false);
1e8e9920 16670 return true;
16671}
16672
ca4c3545 16673/* Pass 1: Create a minimal tree of structured blocks, and record
75a70cf9 16674 where each label is found. */
1e8e9920 16675
16676static tree
75a70cf9 16677diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
16678 struct walk_stmt_info *wi)
1e8e9920 16679{
42acab1c 16680 gimple *context = (gimple *) wi->info;
16681 gimple *inner_context;
16682 gimple *stmt = gsi_stmt (*gsi_p);
1e8e9920 16683
75a70cf9 16684 *handled_ops_p = true;
16685
ca4c3545 16686 switch (gimple_code (stmt))
1e8e9920 16687 {
75a70cf9 16688 WALK_SUBSTMTS;
48e1416a 16689
75a70cf9 16690 case GIMPLE_OMP_PARALLEL:
16691 case GIMPLE_OMP_TASK:
16692 case GIMPLE_OMP_SECTIONS:
16693 case GIMPLE_OMP_SINGLE:
16694 case GIMPLE_OMP_SECTION:
16695 case GIMPLE_OMP_MASTER:
16696 case GIMPLE_OMP_ORDERED:
16697 case GIMPLE_OMP_CRITICAL:
bc7bff74 16698 case GIMPLE_OMP_TARGET:
16699 case GIMPLE_OMP_TEAMS:
16700 case GIMPLE_OMP_TASKGROUP:
75a70cf9 16701 /* The minimal context here is just the current OMP construct. */
16702 inner_context = stmt;
1e8e9920 16703 wi->info = inner_context;
75a70cf9 16704 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
1e8e9920 16705 wi->info = context;
16706 break;
16707
75a70cf9 16708 case GIMPLE_OMP_FOR:
16709 inner_context = stmt;
1e8e9920 16710 wi->info = inner_context;
75a70cf9 16711 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
16712 walk them. */
16713 walk_gimple_seq (gimple_omp_for_pre_body (stmt),
16714 diagnose_sb_1, NULL, wi);
16715 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
1e8e9920 16716 wi->info = context;
16717 break;
16718
75a70cf9 16719 case GIMPLE_LABEL:
1a91d914 16720 splay_tree_insert (all_labels,
16721 (splay_tree_key) gimple_label_label (
16722 as_a <glabel *> (stmt)),
1e8e9920 16723 (splay_tree_value) context);
16724 break;
16725
16726 default:
16727 break;
16728 }
16729
16730 return NULL_TREE;
16731}
16732
16733/* Pass 2: Check each branch and see if its context differs from that of
16734 the destination label's context. */
16735
16736static tree
75a70cf9 16737diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
16738 struct walk_stmt_info *wi)
1e8e9920 16739{
42acab1c 16740 gimple *context = (gimple *) wi->info;
1e8e9920 16741 splay_tree_node n;
42acab1c 16742 gimple *stmt = gsi_stmt (*gsi_p);
1e8e9920 16743
75a70cf9 16744 *handled_ops_p = true;
16745
16746 switch (gimple_code (stmt))
1e8e9920 16747 {
75a70cf9 16748 WALK_SUBSTMTS;
16749
16750 case GIMPLE_OMP_PARALLEL:
16751 case GIMPLE_OMP_TASK:
16752 case GIMPLE_OMP_SECTIONS:
16753 case GIMPLE_OMP_SINGLE:
16754 case GIMPLE_OMP_SECTION:
16755 case GIMPLE_OMP_MASTER:
16756 case GIMPLE_OMP_ORDERED:
16757 case GIMPLE_OMP_CRITICAL:
bc7bff74 16758 case GIMPLE_OMP_TARGET:
16759 case GIMPLE_OMP_TEAMS:
16760 case GIMPLE_OMP_TASKGROUP:
75a70cf9 16761 wi->info = stmt;
e3a19533 16762 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
1e8e9920 16763 wi->info = context;
16764 break;
16765
75a70cf9 16766 case GIMPLE_OMP_FOR:
16767 wi->info = stmt;
16768 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
16769 walk them. */
e3a19533 16770 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt),
16771 diagnose_sb_2, NULL, wi);
16772 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
1e8e9920 16773 wi->info = context;
16774 break;
16775
0e1818e7 16776 case GIMPLE_COND:
16777 {
1a91d914 16778 gcond *cond_stmt = as_a <gcond *> (stmt);
16779 tree lab = gimple_cond_true_label (cond_stmt);
0e1818e7 16780 if (lab)
16781 {
16782 n = splay_tree_lookup (all_labels,
16783 (splay_tree_key) lab);
16784 diagnose_sb_0 (gsi_p, context,
42acab1c 16785 n ? (gimple *) n->value : NULL);
0e1818e7 16786 }
1a91d914 16787 lab = gimple_cond_false_label (cond_stmt);
0e1818e7 16788 if (lab)
16789 {
16790 n = splay_tree_lookup (all_labels,
16791 (splay_tree_key) lab);
16792 diagnose_sb_0 (gsi_p, context,
42acab1c 16793 n ? (gimple *) n->value : NULL);
0e1818e7 16794 }
16795 }
16796 break;
16797
75a70cf9 16798 case GIMPLE_GOTO:
1e8e9920 16799 {
75a70cf9 16800 tree lab = gimple_goto_dest (stmt);
1e8e9920 16801 if (TREE_CODE (lab) != LABEL_DECL)
16802 break;
16803
16804 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
42acab1c 16805 diagnose_sb_0 (gsi_p, context, n ? (gimple *) n->value : NULL);
1e8e9920 16806 }
16807 break;
16808
75a70cf9 16809 case GIMPLE_SWITCH:
1e8e9920 16810 {
1a91d914 16811 gswitch *switch_stmt = as_a <gswitch *> (stmt);
75a70cf9 16812 unsigned int i;
1a91d914 16813 for (i = 0; i < gimple_switch_num_labels (switch_stmt); ++i)
1e8e9920 16814 {
1a91d914 16815 tree lab = CASE_LABEL (gimple_switch_label (switch_stmt, i));
1e8e9920 16816 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
42acab1c 16817 if (n && diagnose_sb_0 (gsi_p, context, (gimple *) n->value))
1e8e9920 16818 break;
16819 }
16820 }
16821 break;
16822
75a70cf9 16823 case GIMPLE_RETURN:
16824 diagnose_sb_0 (gsi_p, context, NULL);
1e8e9920 16825 break;
16826
16827 default:
16828 break;
16829 }
16830
16831 return NULL_TREE;
16832}
16833
ca4c3545 16834/* Called from tree-cfg.c::make_edges to create cfg edges for all relevant
16835 GIMPLE_* codes. */
7740abd8 16836bool
b2c0e0b7 16837make_gimple_omp_edges (basic_block bb, struct omp_region **region,
16838 int *region_idx)
7740abd8 16839{
42acab1c 16840 gimple *last = last_stmt (bb);
7740abd8 16841 enum gimple_code code = gimple_code (last);
16842 struct omp_region *cur_region = *region;
16843 bool fallthru = false;
16844
16845 switch (code)
16846 {
16847 case GIMPLE_OMP_PARALLEL:
16848 case GIMPLE_OMP_TASK:
16849 case GIMPLE_OMP_FOR:
16850 case GIMPLE_OMP_SINGLE:
16851 case GIMPLE_OMP_TEAMS:
16852 case GIMPLE_OMP_MASTER:
16853 case GIMPLE_OMP_TASKGROUP:
7740abd8 16854 case GIMPLE_OMP_CRITICAL:
16855 case GIMPLE_OMP_SECTION:
16856 cur_region = new_omp_region (bb, code, cur_region);
16857 fallthru = true;
16858 break;
16859
43895be5 16860 case GIMPLE_OMP_ORDERED:
16861 cur_region = new_omp_region (bb, code, cur_region);
16862 fallthru = true;
16863 if (find_omp_clause (gimple_omp_ordered_clauses
16864 (as_a <gomp_ordered *> (last)),
16865 OMP_CLAUSE_DEPEND))
16866 cur_region = cur_region->outer;
16867 break;
16868
7740abd8 16869 case GIMPLE_OMP_TARGET:
16870 cur_region = new_omp_region (bb, code, cur_region);
16871 fallthru = true;
ca4c3545 16872 switch (gimple_omp_target_kind (last))
16873 {
16874 case GF_OMP_TARGET_KIND_REGION:
16875 case GF_OMP_TARGET_KIND_DATA:
16876 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
16877 case GF_OMP_TARGET_KIND_OACC_KERNELS:
16878 case GF_OMP_TARGET_KIND_OACC_DATA:
571b3486 16879 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
ca4c3545 16880 break;
16881 case GF_OMP_TARGET_KIND_UPDATE:
43895be5 16882 case GF_OMP_TARGET_KIND_ENTER_DATA:
16883 case GF_OMP_TARGET_KIND_EXIT_DATA:
ca4c3545 16884 case GF_OMP_TARGET_KIND_OACC_UPDATE:
16885 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
2fc5e987 16886 case GF_OMP_TARGET_KIND_OACC_DECLARE:
ca4c3545 16887 cur_region = cur_region->outer;
16888 break;
16889 default:
16890 gcc_unreachable ();
16891 }
7740abd8 16892 break;
16893
16894 case GIMPLE_OMP_SECTIONS:
16895 cur_region = new_omp_region (bb, code, cur_region);
16896 fallthru = true;
16897 break;
16898
16899 case GIMPLE_OMP_SECTIONS_SWITCH:
16900 fallthru = false;
16901 break;
16902
16903 case GIMPLE_OMP_ATOMIC_LOAD:
16904 case GIMPLE_OMP_ATOMIC_STORE:
16905 fallthru = true;
16906 break;
16907
16908 case GIMPLE_OMP_RETURN:
16909 /* In the case of a GIMPLE_OMP_SECTION, the edge will go
16910 somewhere other than the next block. This will be
16911 created later. */
16912 cur_region->exit = bb;
b25f70fd 16913 if (cur_region->type == GIMPLE_OMP_TASK)
16914 /* Add an edge corresponding to not scheduling the task
16915 immediately. */
16916 make_edge (cur_region->entry, bb, EDGE_ABNORMAL);
7740abd8 16917 fallthru = cur_region->type != GIMPLE_OMP_SECTION;
16918 cur_region = cur_region->outer;
16919 break;
16920
16921 case GIMPLE_OMP_CONTINUE:
16922 cur_region->cont = bb;
16923 switch (cur_region->type)
16924 {
16925 case GIMPLE_OMP_FOR:
16926 /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
16927 succs edges as abnormal to prevent splitting
16928 them. */
16929 single_succ_edge (cur_region->entry)->flags |= EDGE_ABNORMAL;
16930 /* Make the loopback edge. */
16931 make_edge (bb, single_succ (cur_region->entry),
16932 EDGE_ABNORMAL);
16933
16934 /* Create an edge from GIMPLE_OMP_FOR to exit, which
16935 corresponds to the case that the body of the loop
16936 is not executed at all. */
16937 make_edge (cur_region->entry, bb->next_bb, EDGE_ABNORMAL);
16938 make_edge (bb, bb->next_bb, EDGE_FALLTHRU | EDGE_ABNORMAL);
16939 fallthru = false;
16940 break;
16941
16942 case GIMPLE_OMP_SECTIONS:
16943 /* Wire up the edges into and out of the nested sections. */
16944 {
16945 basic_block switch_bb = single_succ (cur_region->entry);
16946
16947 struct omp_region *i;
16948 for (i = cur_region->inner; i ; i = i->next)
16949 {
16950 gcc_assert (i->type == GIMPLE_OMP_SECTION);
16951 make_edge (switch_bb, i->entry, 0);
16952 make_edge (i->exit, bb, EDGE_FALLTHRU);
16953 }
16954
16955 /* Make the loopback edge to the block with
16956 GIMPLE_OMP_SECTIONS_SWITCH. */
16957 make_edge (bb, switch_bb, 0);
16958
16959 /* Make the edge from the switch to exit. */
16960 make_edge (switch_bb, bb->next_bb, 0);
16961 fallthru = false;
16962 }
16963 break;
16964
b25f70fd 16965 case GIMPLE_OMP_TASK:
16966 fallthru = true;
16967 break;
16968
7740abd8 16969 default:
16970 gcc_unreachable ();
16971 }
16972 break;
16973
16974 default:
16975 gcc_unreachable ();
16976 }
16977
16978 if (*region != cur_region)
b2c0e0b7 16979 {
16980 *region = cur_region;
16981 if (cur_region)
16982 *region_idx = cur_region->entry->index;
16983 else
16984 *region_idx = 0;
16985 }
7740abd8 16986
16987 return fallthru;
16988}
16989
bfec3452 16990static unsigned int
16991diagnose_omp_structured_block_errors (void)
1e8e9920 16992{
1e8e9920 16993 struct walk_stmt_info wi;
bfec3452 16994 gimple_seq body = gimple_body (current_function_decl);
1e8e9920 16995
16996 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
16997
16998 memset (&wi, 0, sizeof (wi));
75a70cf9 16999 walk_gimple_seq (body, diagnose_sb_1, NULL, &wi);
1e8e9920 17000
17001 memset (&wi, 0, sizeof (wi));
1e8e9920 17002 wi.want_locations = true;
e3a19533 17003 walk_gimple_seq_mod (&body, diagnose_sb_2, NULL, &wi);
17004
17005 gimple_set_body (current_function_decl, body);
1e8e9920 17006
17007 splay_tree_delete (all_labels);
17008 all_labels = NULL;
17009
bfec3452 17010 return 0;
1e8e9920 17011}
17012
7620bc82 17013namespace {
17014
17015const pass_data pass_data_diagnose_omp_blocks =
cbe8bda8 17016{
17017 GIMPLE_PASS, /* type */
17018 "*diagnose_omp_blocks", /* name */
17019 OPTGROUP_NONE, /* optinfo_flags */
cbe8bda8 17020 TV_NONE, /* tv_id */
17021 PROP_gimple_any, /* properties_required */
17022 0, /* properties_provided */
17023 0, /* properties_destroyed */
17024 0, /* todo_flags_start */
17025 0, /* todo_flags_finish */
bfec3452 17026};
17027
7620bc82 17028class pass_diagnose_omp_blocks : public gimple_opt_pass
cbe8bda8 17029{
17030public:
9af5ce0c 17031 pass_diagnose_omp_blocks (gcc::context *ctxt)
17032 : gimple_opt_pass (pass_data_diagnose_omp_blocks, ctxt)
cbe8bda8 17033 {}
17034
17035 /* opt_pass methods: */
ca4c3545 17036 virtual bool gate (function *)
17037 {
17038 return flag_cilkplus || flag_openacc || flag_openmp;
17039 }
65b0537f 17040 virtual unsigned int execute (function *)
17041 {
17042 return diagnose_omp_structured_block_errors ();
17043 }
cbe8bda8 17044
17045}; // class pass_diagnose_omp_blocks
17046
7620bc82 17047} // anon namespace
17048
cbe8bda8 17049gimple_opt_pass *
17050make_pass_diagnose_omp_blocks (gcc::context *ctxt)
17051{
17052 return new pass_diagnose_omp_blocks (ctxt);
17053}
d09768a4 17054\f
17055/* SIMD clone supporting code. */
17056
17057/* Allocate a fresh `simd_clone' and return it. NARGS is the number
17058 of arguments to reserve space for. */
17059
17060static struct cgraph_simd_clone *
17061simd_clone_struct_alloc (int nargs)
17062{
17063 struct cgraph_simd_clone *clone_info;
17064 size_t len = (sizeof (struct cgraph_simd_clone)
17065 + nargs * sizeof (struct cgraph_simd_clone_arg));
17066 clone_info = (struct cgraph_simd_clone *)
ea7d8c7a 17067 ggc_internal_cleared_alloc (len);
d09768a4 17068 return clone_info;
17069}
17070
17071/* Make a copy of the `struct cgraph_simd_clone' in FROM to TO. */
17072
17073static inline void
17074simd_clone_struct_copy (struct cgraph_simd_clone *to,
17075 struct cgraph_simd_clone *from)
17076{
17077 memcpy (to, from, (sizeof (struct cgraph_simd_clone)
46c0fd4b 17078 + ((from->nargs - from->inbranch)
17079 * sizeof (struct cgraph_simd_clone_arg))));
d09768a4 17080}
17081
17082/* Return vector of parameter types of function FNDECL. This uses
17083 TYPE_ARG_TYPES if available, otherwise falls back to types of
17084 DECL_ARGUMENTS types. */
17085
17086vec<tree>
17087simd_clone_vector_of_formal_parm_types (tree fndecl)
17088{
17089 if (TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
17090 return ipa_get_vector_of_formal_parm_types (TREE_TYPE (fndecl));
17091 vec<tree> args = ipa_get_vector_of_formal_parms (fndecl);
17092 unsigned int i;
17093 tree arg;
17094 FOR_EACH_VEC_ELT (args, i, arg)
17095 args[i] = TREE_TYPE (args[i]);
17096 return args;
17097}
17098
17099/* Given a simd function in NODE, extract the simd specific
17100 information from the OMP clauses passed in CLAUSES, and return
17101 the struct cgraph_simd_clone * if it should be cloned. *INBRANCH_SPECIFIED
17102 is set to TRUE if the `inbranch' or `notinbranch' clause specified,
17103 otherwise set to FALSE. */
17104
17105static struct cgraph_simd_clone *
17106simd_clone_clauses_extract (struct cgraph_node *node, tree clauses,
17107 bool *inbranch_specified)
17108{
17109 vec<tree> args = simd_clone_vector_of_formal_parm_types (node->decl);
17110 tree t;
17111 int n;
17112 *inbranch_specified = false;
17113
17114 n = args.length ();
17115 if (n > 0 && args.last () == void_type_node)
17116 n--;
17117
17118 /* To distinguish from an OpenMP simd clone, Cilk Plus functions to
17119 be cloned have a distinctive artificial label in addition to "omp
17120 declare simd". */
17121 bool cilk_clone
a89e6c15 17122 = (flag_cilkplus
74acc703 17123 && lookup_attribute ("cilk simd function",
d09768a4 17124 DECL_ATTRIBUTES (node->decl)));
17125
17126 /* Allocate one more than needed just in case this is an in-branch
17127 clone which will require a mask argument. */
17128 struct cgraph_simd_clone *clone_info = simd_clone_struct_alloc (n + 1);
17129 clone_info->nargs = n;
17130 clone_info->cilk_elemental = cilk_clone;
17131
17132 if (!clauses)
17133 {
17134 args.release ();
17135 return clone_info;
17136 }
17137 clauses = TREE_VALUE (clauses);
17138 if (!clauses || TREE_CODE (clauses) != OMP_CLAUSE)
17139 return clone_info;
17140
17141 for (t = clauses; t; t = OMP_CLAUSE_CHAIN (t))
17142 {
17143 switch (OMP_CLAUSE_CODE (t))
17144 {
17145 case OMP_CLAUSE_INBRANCH:
17146 clone_info->inbranch = 1;
17147 *inbranch_specified = true;
17148 break;
17149 case OMP_CLAUSE_NOTINBRANCH:
17150 clone_info->inbranch = 0;
17151 *inbranch_specified = true;
17152 break;
17153 case OMP_CLAUSE_SIMDLEN:
17154 clone_info->simdlen
17155 = TREE_INT_CST_LOW (OMP_CLAUSE_SIMDLEN_EXPR (t));
17156 break;
17157 case OMP_CLAUSE_LINEAR:
17158 {
17159 tree decl = OMP_CLAUSE_DECL (t);
17160 tree step = OMP_CLAUSE_LINEAR_STEP (t);
17161 int argno = TREE_INT_CST_LOW (decl);
17162 if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (t))
17163 {
9561765e 17164 enum cgraph_simd_clone_arg_type arg_type;
17165 if (TREE_CODE (args[argno]) == REFERENCE_TYPE)
17166 switch (OMP_CLAUSE_LINEAR_KIND (t))
17167 {
17168 case OMP_CLAUSE_LINEAR_REF:
17169 arg_type
17170 = SIMD_CLONE_ARG_TYPE_LINEAR_REF_VARIABLE_STEP;
17171 break;
17172 case OMP_CLAUSE_LINEAR_UVAL:
17173 arg_type
17174 = SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_VARIABLE_STEP;
17175 break;
17176 case OMP_CLAUSE_LINEAR_VAL:
17177 case OMP_CLAUSE_LINEAR_DEFAULT:
17178 arg_type
17179 = SIMD_CLONE_ARG_TYPE_LINEAR_VAL_VARIABLE_STEP;
17180 break;
17181 default:
17182 gcc_unreachable ();
17183 }
17184 else
17185 arg_type = SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP;
17186 clone_info->args[argno].arg_type = arg_type;
d09768a4 17187 clone_info->args[argno].linear_step = tree_to_shwi (step);
17188 gcc_assert (clone_info->args[argno].linear_step >= 0
17189 && clone_info->args[argno].linear_step < n);
17190 }
17191 else
17192 {
17193 if (POINTER_TYPE_P (args[argno]))
17194 step = fold_convert (ssizetype, step);
17195 if (!tree_fits_shwi_p (step))
17196 {
17197 warning_at (OMP_CLAUSE_LOCATION (t), 0,
17198 "ignoring large linear step");
17199 args.release ();
17200 return NULL;
17201 }
17202 else if (integer_zerop (step))
17203 {
17204 warning_at (OMP_CLAUSE_LOCATION (t), 0,
17205 "ignoring zero linear step");
17206 args.release ();
17207 return NULL;
17208 }
17209 else
17210 {
43895be5 17211 enum cgraph_simd_clone_arg_type arg_type;
17212 if (TREE_CODE (args[argno]) == REFERENCE_TYPE)
17213 switch (OMP_CLAUSE_LINEAR_KIND (t))
17214 {
17215 case OMP_CLAUSE_LINEAR_REF:
17216 arg_type
17217 = SIMD_CLONE_ARG_TYPE_LINEAR_REF_CONSTANT_STEP;
17218 break;
17219 case OMP_CLAUSE_LINEAR_UVAL:
17220 arg_type
17221 = SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP;
17222 break;
17223 case OMP_CLAUSE_LINEAR_VAL:
17224 case OMP_CLAUSE_LINEAR_DEFAULT:
17225 arg_type
17226 = SIMD_CLONE_ARG_TYPE_LINEAR_VAL_CONSTANT_STEP;
17227 break;
17228 default:
17229 gcc_unreachable ();
17230 }
17231 else
17232 arg_type = SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP;
17233 clone_info->args[argno].arg_type = arg_type;
d09768a4 17234 clone_info->args[argno].linear_step = tree_to_shwi (step);
17235 }
17236 }
17237 break;
17238 }
17239 case OMP_CLAUSE_UNIFORM:
17240 {
17241 tree decl = OMP_CLAUSE_DECL (t);
17242 int argno = tree_to_uhwi (decl);
17243 clone_info->args[argno].arg_type
17244 = SIMD_CLONE_ARG_TYPE_UNIFORM;
17245 break;
17246 }
17247 case OMP_CLAUSE_ALIGNED:
17248 {
17249 tree decl = OMP_CLAUSE_DECL (t);
17250 int argno = tree_to_uhwi (decl);
17251 clone_info->args[argno].alignment
17252 = TREE_INT_CST_LOW (OMP_CLAUSE_ALIGNED_ALIGNMENT (t));
17253 break;
17254 }
17255 default:
17256 break;
17257 }
17258 }
17259 args.release ();
17260 return clone_info;
17261}
17262
17263/* Given a SIMD clone in NODE, calculate the characteristic data
17264 type and return the coresponding type. The characteristic data
17265 type is computed as described in the Intel Vector ABI. */
17266
17267static tree
17268simd_clone_compute_base_data_type (struct cgraph_node *node,
17269 struct cgraph_simd_clone *clone_info)
17270{
17271 tree type = integer_type_node;
17272 tree fndecl = node->decl;
17273
17274 /* a) For non-void function, the characteristic data type is the
17275 return type. */
17276 if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) != VOID_TYPE)
17277 type = TREE_TYPE (TREE_TYPE (fndecl));
17278
17279 /* b) If the function has any non-uniform, non-linear parameters,
17280 then the characteristic data type is the type of the first
17281 such parameter. */
17282 else
17283 {
17284 vec<tree> map = simd_clone_vector_of_formal_parm_types (fndecl);
17285 for (unsigned int i = 0; i < clone_info->nargs; ++i)
17286 if (clone_info->args[i].arg_type == SIMD_CLONE_ARG_TYPE_VECTOR)
17287 {
17288 type = map[i];
17289 break;
17290 }
17291 map.release ();
17292 }
17293
17294 /* c) If the characteristic data type determined by a) or b) above
17295 is struct, union, or class type which is pass-by-value (except
17296 for the type that maps to the built-in complex data type), the
17297 characteristic data type is int. */
17298 if (RECORD_OR_UNION_TYPE_P (type)
17299 && !aggregate_value_p (type, NULL)
17300 && TREE_CODE (type) != COMPLEX_TYPE)
17301 return integer_type_node;
17302
17303 /* d) If none of the above three classes is applicable, the
17304 characteristic data type is int. */
17305
17306 return type;
17307
17308 /* e) For Intel Xeon Phi native and offload compilation, if the
17309 resulting characteristic data type is 8-bit or 16-bit integer
17310 data type, the characteristic data type is int. */
17311 /* Well, we don't handle Xeon Phi yet. */
17312}
17313
17314static tree
17315simd_clone_mangle (struct cgraph_node *node,
17316 struct cgraph_simd_clone *clone_info)
17317{
17318 char vecsize_mangle = clone_info->vecsize_mangle;
17319 char mask = clone_info->inbranch ? 'M' : 'N';
17320 unsigned int simdlen = clone_info->simdlen;
17321 unsigned int n;
17322 pretty_printer pp;
17323
17324 gcc_assert (vecsize_mangle && simdlen);
17325
17326 pp_string (&pp, "_ZGV");
17327 pp_character (&pp, vecsize_mangle);
17328 pp_character (&pp, mask);
17329 pp_decimal_int (&pp, simdlen);
17330
17331 for (n = 0; n < clone_info->nargs; ++n)
17332 {
17333 struct cgraph_simd_clone_arg arg = clone_info->args[n];
17334
43895be5 17335 switch (arg.arg_type)
d09768a4 17336 {
43895be5 17337 case SIMD_CLONE_ARG_TYPE_UNIFORM:
17338 pp_character (&pp, 'u');
17339 break;
17340 case SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP:
d09768a4 17341 pp_character (&pp, 'l');
43895be5 17342 goto mangle_linear;
17343 case SIMD_CLONE_ARG_TYPE_LINEAR_REF_CONSTANT_STEP:
17344 pp_character (&pp, 'R');
17345 goto mangle_linear;
17346 case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_CONSTANT_STEP:
17347 pp_character (&pp, 'L');
17348 goto mangle_linear;
17349 case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP:
17350 pp_character (&pp, 'U');
17351 goto mangle_linear;
17352 mangle_linear:
17353 gcc_assert (arg.linear_step != 0);
d09768a4 17354 if (arg.linear_step > 1)
17355 pp_unsigned_wide_integer (&pp, arg.linear_step);
17356 else if (arg.linear_step < 0)
17357 {
17358 pp_character (&pp, 'n');
17359 pp_unsigned_wide_integer (&pp, (-(unsigned HOST_WIDE_INT)
17360 arg.linear_step));
17361 }
43895be5 17362 break;
17363 case SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP:
9561765e 17364 pp_string (&pp, "ls");
17365 pp_unsigned_wide_integer (&pp, arg.linear_step);
17366 break;
17367 case SIMD_CLONE_ARG_TYPE_LINEAR_REF_VARIABLE_STEP:
17368 pp_string (&pp, "Rs");
17369 pp_unsigned_wide_integer (&pp, arg.linear_step);
17370 break;
17371 case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_VARIABLE_STEP:
17372 pp_string (&pp, "Ls");
17373 pp_unsigned_wide_integer (&pp, arg.linear_step);
17374 break;
17375 case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_VARIABLE_STEP:
17376 pp_string (&pp, "Us");
d09768a4 17377 pp_unsigned_wide_integer (&pp, arg.linear_step);
43895be5 17378 break;
17379 default:
17380 pp_character (&pp, 'v');
d09768a4 17381 }
d09768a4 17382 if (arg.alignment)
17383 {
17384 pp_character (&pp, 'a');
17385 pp_decimal_int (&pp, arg.alignment);
17386 }
17387 }
17388
17389 pp_underscore (&pp);
4e4baaad 17390 const char *str = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl));
17391 if (*str == '*')
17392 ++str;
17393 pp_string (&pp, str);
17394 str = pp_formatted_text (&pp);
d09768a4 17395
17396 /* If there already is a SIMD clone with the same mangled name, don't
17397 add another one. This can happen e.g. for
17398 #pragma omp declare simd
17399 #pragma omp declare simd simdlen(8)
17400 int foo (int, int);
17401 if the simdlen is assumed to be 8 for the first one, etc. */
17402 for (struct cgraph_node *clone = node->simd_clones; clone;
17403 clone = clone->simdclone->next_clone)
17404 if (strcmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (clone->decl)),
17405 str) == 0)
17406 return NULL_TREE;
17407
17408 return get_identifier (str);
17409}
17410
17411/* Create a simd clone of OLD_NODE and return it. */
17412
17413static struct cgraph_node *
17414simd_clone_create (struct cgraph_node *old_node)
17415{
17416 struct cgraph_node *new_node;
17417 if (old_node->definition)
ea0695f9 17418 {
415d1b9a 17419 if (!old_node->has_gimple_body_p ())
ea0695f9 17420 return NULL;
415d1b9a 17421 old_node->get_body ();
17422 new_node = old_node->create_version_clone_with_body (vNULL, NULL, NULL,
17423 false, NULL, NULL,
17424 "simdclone");
ea0695f9 17425 }
d09768a4 17426 else
17427 {
17428 tree old_decl = old_node->decl;
17429 tree new_decl = copy_node (old_node->decl);
17430 DECL_NAME (new_decl) = clone_function_name (old_decl, "simdclone");
17431 SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl));
17432 SET_DECL_RTL (new_decl, NULL);
17433 DECL_STATIC_CONSTRUCTOR (new_decl) = 0;
17434 DECL_STATIC_DESTRUCTOR (new_decl) = 0;
415d1b9a 17435 new_node = old_node->create_version_clone (new_decl, vNULL, NULL);
64c7c74a 17436 if (old_node->in_other_partition)
17437 new_node->in_other_partition = 1;
35ee1c66 17438 symtab->call_cgraph_insertion_hooks (new_node);
d09768a4 17439 }
17440 if (new_node == NULL)
17441 return new_node;
17442
17443 TREE_PUBLIC (new_node->decl) = TREE_PUBLIC (old_node->decl);
17444
17445 /* The function cgraph_function_versioning () will force the new
17446 symbol local. Undo this, and inherit external visability from
17447 the old node. */
17448 new_node->local.local = old_node->local.local;
17449 new_node->externally_visible = old_node->externally_visible;
17450
17451 return new_node;
17452}
17453
17454/* Adjust the return type of the given function to its appropriate
17455 vector counterpart. Returns a simd array to be used throughout the
17456 function as a return value. */
17457
17458static tree
17459simd_clone_adjust_return_type (struct cgraph_node *node)
17460{
17461 tree fndecl = node->decl;
17462 tree orig_rettype = TREE_TYPE (TREE_TYPE (fndecl));
17463 unsigned int veclen;
17464 tree t;
17465
17466 /* Adjust the function return type. */
17467 if (orig_rettype == void_type_node)
17468 return NULL_TREE;
17469 TREE_TYPE (fndecl) = build_distinct_type_copy (TREE_TYPE (fndecl));
fdf7662c 17470 t = TREE_TYPE (TREE_TYPE (fndecl));
17471 if (INTEGRAL_TYPE_P (t) || POINTER_TYPE_P (t))
d09768a4 17472 veclen = node->simdclone->vecsize_int;
17473 else
17474 veclen = node->simdclone->vecsize_float;
fdf7662c 17475 veclen /= GET_MODE_BITSIZE (TYPE_MODE (t));
d09768a4 17476 if (veclen > node->simdclone->simdlen)
17477 veclen = node->simdclone->simdlen;
fdf7662c 17478 if (POINTER_TYPE_P (t))
17479 t = pointer_sized_int_node;
d09768a4 17480 if (veclen == node->simdclone->simdlen)
fdf7662c 17481 t = build_vector_type (t, node->simdclone->simdlen);
d09768a4 17482 else
17483 {
fdf7662c 17484 t = build_vector_type (t, veclen);
d09768a4 17485 t = build_array_type_nelts (t, node->simdclone->simdlen / veclen);
d09768a4 17486 }
fdf7662c 17487 TREE_TYPE (TREE_TYPE (fndecl)) = t;
d09768a4 17488 if (!node->definition)
17489 return NULL_TREE;
17490
17491 t = DECL_RESULT (fndecl);
17492 /* Adjust the DECL_RESULT. */
17493 gcc_assert (TREE_TYPE (t) != void_type_node);
17494 TREE_TYPE (t) = TREE_TYPE (TREE_TYPE (fndecl));
17495 relayout_decl (t);
17496
17497 tree atype = build_array_type_nelts (orig_rettype,
17498 node->simdclone->simdlen);
17499 if (veclen != node->simdclone->simdlen)
17500 return build1 (VIEW_CONVERT_EXPR, atype, t);
17501
17502 /* Set up a SIMD array to use as the return value. */
17503 tree retval = create_tmp_var_raw (atype, "retval");
17504 gimple_add_tmp_var (retval);
17505 return retval;
17506}
17507
17508/* Each vector argument has a corresponding array to be used locally
17509 as part of the eventual loop. Create such temporary array and
17510 return it.
17511
17512 PREFIX is the prefix to be used for the temporary.
17513
17514 TYPE is the inner element type.
17515
17516 SIMDLEN is the number of elements. */
17517
17518static tree
17519create_tmp_simd_array (const char *prefix, tree type, int simdlen)
17520{
17521 tree atype = build_array_type_nelts (type, simdlen);
17522 tree avar = create_tmp_var_raw (atype, prefix);
17523 gimple_add_tmp_var (avar);
17524 return avar;
17525}
17526
17527/* Modify the function argument types to their corresponding vector
17528 counterparts if appropriate. Also, create one array for each simd
17529 argument to be used locally when using the function arguments as
17530 part of the loop.
17531
17532 NODE is the function whose arguments are to be adjusted.
17533
17534 Returns an adjustment vector that will be filled describing how the
17535 argument types will be adjusted. */
17536
17537static ipa_parm_adjustment_vec
17538simd_clone_adjust_argument_types (struct cgraph_node *node)
17539{
17540 vec<tree> args;
17541 ipa_parm_adjustment_vec adjustments;
17542
17543 if (node->definition)
17544 args = ipa_get_vector_of_formal_parms (node->decl);
17545 else
17546 args = simd_clone_vector_of_formal_parm_types (node->decl);
17547 adjustments.create (args.length ());
17548 unsigned i, j, veclen;
17549 struct ipa_parm_adjustment adj;
17550 for (i = 0; i < node->simdclone->nargs; ++i)
17551 {
17552 memset (&adj, 0, sizeof (adj));
17553 tree parm = args[i];
17554 tree parm_type = node->definition ? TREE_TYPE (parm) : parm;
17555 adj.base_index = i;
17556 adj.base = parm;
17557
17558 node->simdclone->args[i].orig_arg = node->definition ? parm : NULL_TREE;
17559 node->simdclone->args[i].orig_type = parm_type;
17560
43895be5 17561 switch (node->simdclone->args[i].arg_type)
d09768a4 17562 {
43895be5 17563 default:
d09768a4 17564 /* No adjustment necessary for scalar arguments. */
17565 adj.op = IPA_PARM_OP_COPY;
43895be5 17566 break;
17567 case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP:
9561765e 17568 case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_VARIABLE_STEP:
43895be5 17569 if (node->definition)
17570 node->simdclone->args[i].simd_array
17571 = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm)),
17572 TREE_TYPE (parm_type),
17573 node->simdclone->simdlen);
17574 adj.op = IPA_PARM_OP_COPY;
17575 break;
17576 case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_CONSTANT_STEP:
9561765e 17577 case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_VARIABLE_STEP:
43895be5 17578 case SIMD_CLONE_ARG_TYPE_VECTOR:
d09768a4 17579 if (INTEGRAL_TYPE_P (parm_type) || POINTER_TYPE_P (parm_type))
17580 veclen = node->simdclone->vecsize_int;
17581 else
17582 veclen = node->simdclone->vecsize_float;
17583 veclen /= GET_MODE_BITSIZE (TYPE_MODE (parm_type));
17584 if (veclen > node->simdclone->simdlen)
17585 veclen = node->simdclone->simdlen;
17586 adj.arg_prefix = "simd";
fdf7662c 17587 if (POINTER_TYPE_P (parm_type))
17588 adj.type = build_vector_type (pointer_sized_int_node, veclen);
17589 else
17590 adj.type = build_vector_type (parm_type, veclen);
d09768a4 17591 node->simdclone->args[i].vector_type = adj.type;
17592 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
17593 {
17594 adjustments.safe_push (adj);
17595 if (j == veclen)
17596 {
17597 memset (&adj, 0, sizeof (adj));
17598 adj.op = IPA_PARM_OP_NEW;
17599 adj.arg_prefix = "simd";
17600 adj.base_index = i;
17601 adj.type = node->simdclone->args[i].vector_type;
17602 }
17603 }
17604
17605 if (node->definition)
17606 node->simdclone->args[i].simd_array
17607 = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm)),
17608 parm_type, node->simdclone->simdlen);
17609 }
17610 adjustments.safe_push (adj);
17611 }
17612
17613 if (node->simdclone->inbranch)
17614 {
17615 tree base_type
17616 = simd_clone_compute_base_data_type (node->simdclone->origin,
17617 node->simdclone);
17618
17619 memset (&adj, 0, sizeof (adj));
17620 adj.op = IPA_PARM_OP_NEW;
17621 adj.arg_prefix = "mask";
17622
17623 adj.base_index = i;
17624 if (INTEGRAL_TYPE_P (base_type) || POINTER_TYPE_P (base_type))
17625 veclen = node->simdclone->vecsize_int;
17626 else
17627 veclen = node->simdclone->vecsize_float;
17628 veclen /= GET_MODE_BITSIZE (TYPE_MODE (base_type));
17629 if (veclen > node->simdclone->simdlen)
17630 veclen = node->simdclone->simdlen;
fdf7662c 17631 if (POINTER_TYPE_P (base_type))
17632 adj.type = build_vector_type (pointer_sized_int_node, veclen);
17633 else
17634 adj.type = build_vector_type (base_type, veclen);
d09768a4 17635 adjustments.safe_push (adj);
17636
17637 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
17638 adjustments.safe_push (adj);
17639
17640 /* We have previously allocated one extra entry for the mask. Use
17641 it and fill it. */
17642 struct cgraph_simd_clone *sc = node->simdclone;
17643 sc->nargs++;
17644 if (node->definition)
17645 {
17646 sc->args[i].orig_arg
17647 = build_decl (UNKNOWN_LOCATION, PARM_DECL, NULL, base_type);
17648 sc->args[i].simd_array
17649 = create_tmp_simd_array ("mask", base_type, sc->simdlen);
17650 }
17651 sc->args[i].orig_type = base_type;
17652 sc->args[i].arg_type = SIMD_CLONE_ARG_TYPE_MASK;
17653 }
17654
17655 if (node->definition)
17656 ipa_modify_formal_parameters (node->decl, adjustments);
17657 else
17658 {
17659 tree new_arg_types = NULL_TREE, new_reversed;
17660 bool last_parm_void = false;
17661 if (args.length () > 0 && args.last () == void_type_node)
17662 last_parm_void = true;
17663
17664 gcc_assert (TYPE_ARG_TYPES (TREE_TYPE (node->decl)));
17665 j = adjustments.length ();
17666 for (i = 0; i < j; i++)
17667 {
17668 struct ipa_parm_adjustment *adj = &adjustments[i];
17669 tree ptype;
17670 if (adj->op == IPA_PARM_OP_COPY)
17671 ptype = args[adj->base_index];
17672 else
17673 ptype = adj->type;
17674 new_arg_types = tree_cons (NULL_TREE, ptype, new_arg_types);
17675 }
17676 new_reversed = nreverse (new_arg_types);
17677 if (last_parm_void)
17678 {
17679 if (new_reversed)
17680 TREE_CHAIN (new_arg_types) = void_list_node;
17681 else
17682 new_reversed = void_list_node;
17683 }
17684
17685 tree new_type = build_distinct_type_copy (TREE_TYPE (node->decl));
17686 TYPE_ARG_TYPES (new_type) = new_reversed;
17687 TREE_TYPE (node->decl) = new_type;
17688
17689 adjustments.release ();
17690 }
17691 args.release ();
17692 return adjustments;
17693}
17694
17695/* Initialize and copy the function arguments in NODE to their
17696 corresponding local simd arrays. Returns a fresh gimple_seq with
17697 the instruction sequence generated. */
17698
17699static gimple_seq
17700simd_clone_init_simd_arrays (struct cgraph_node *node,
17701 ipa_parm_adjustment_vec adjustments)
17702{
17703 gimple_seq seq = NULL;
17704 unsigned i = 0, j = 0, k;
17705
17706 for (tree arg = DECL_ARGUMENTS (node->decl);
17707 arg;
17708 arg = DECL_CHAIN (arg), i++, j++)
17709 {
43895be5 17710 if (adjustments[j].op == IPA_PARM_OP_COPY
17711 || POINTER_TYPE_P (TREE_TYPE (arg)))
d09768a4 17712 continue;
17713
17714 node->simdclone->args[i].vector_arg = arg;
17715
17716 tree array = node->simdclone->args[i].simd_array;
17717 if (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg)) == node->simdclone->simdlen)
17718 {
17719 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
17720 tree ptr = build_fold_addr_expr (array);
17721 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
17722 build_int_cst (ptype, 0));
17723 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
17724 gimplify_and_add (t, &seq);
17725 }
17726 else
17727 {
17728 unsigned int simdlen = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg));
17729 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
17730 for (k = 0; k < node->simdclone->simdlen; k += simdlen)
17731 {
17732 tree ptr = build_fold_addr_expr (array);
17733 int elemsize;
17734 if (k)
17735 {
17736 arg = DECL_CHAIN (arg);
17737 j++;
17738 }
17739 elemsize
17740 = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg))));
17741 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
17742 build_int_cst (ptype, k * elemsize));
17743 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
17744 gimplify_and_add (t, &seq);
17745 }
17746 }
17747 }
17748 return seq;
17749}
17750
17751/* Callback info for ipa_simd_modify_stmt_ops below. */
17752
17753struct modify_stmt_info {
17754 ipa_parm_adjustment_vec adjustments;
42acab1c 17755 gimple *stmt;
d09768a4 17756 /* True if the parent statement was modified by
17757 ipa_simd_modify_stmt_ops. */
17758 bool modified;
17759};
17760
17761/* Callback for walk_gimple_op.
17762
17763 Adjust operands from a given statement as specified in the
17764 adjustments vector in the callback data. */
17765
17766static tree
17767ipa_simd_modify_stmt_ops (tree *tp, int *walk_subtrees, void *data)
17768{
17769 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
2d78e89f 17770 struct modify_stmt_info *info = (struct modify_stmt_info *) wi->info;
17771 tree *orig_tp = tp;
17772 if (TREE_CODE (*tp) == ADDR_EXPR)
17773 tp = &TREE_OPERAND (*tp, 0);
17774 struct ipa_parm_adjustment *cand = NULL;
17775 if (TREE_CODE (*tp) == PARM_DECL)
17776 cand = ipa_get_adjustment_candidate (&tp, NULL, info->adjustments, true);
17777 else
d09768a4 17778 {
d09768a4 17779 if (TYPE_P (*tp))
17780 *walk_subtrees = 0;
d09768a4 17781 }
d09768a4 17782
2d78e89f 17783 tree repl = NULL_TREE;
17784 if (cand)
17785 repl = unshare_expr (cand->new_decl);
17786 else
d09768a4 17787 {
2d78e89f 17788 if (tp != orig_tp)
17789 {
17790 *walk_subtrees = 0;
17791 bool modified = info->modified;
17792 info->modified = false;
17793 walk_tree (tp, ipa_simd_modify_stmt_ops, wi, wi->pset);
17794 if (!info->modified)
17795 {
17796 info->modified = modified;
17797 return NULL_TREE;
17798 }
17799 info->modified = modified;
17800 repl = *tp;
17801 }
17802 else
17803 return NULL_TREE;
d09768a4 17804 }
2d78e89f 17805
17806 if (tp != orig_tp)
d09768a4 17807 {
2d78e89f 17808 repl = build_fold_addr_expr (repl);
42acab1c 17809 gimple *stmt;
9c1dd4d9 17810 if (is_gimple_debug (info->stmt))
17811 {
17812 tree vexpr = make_node (DEBUG_EXPR_DECL);
17813 stmt = gimple_build_debug_source_bind (vexpr, repl, NULL);
17814 DECL_ARTIFICIAL (vexpr) = 1;
17815 TREE_TYPE (vexpr) = TREE_TYPE (repl);
17816 DECL_MODE (vexpr) = TYPE_MODE (TREE_TYPE (repl));
17817 repl = vexpr;
17818 }
17819 else
17820 {
f9e245b2 17821 stmt = gimple_build_assign (make_ssa_name (TREE_TYPE (repl)), repl);
9c1dd4d9 17822 repl = gimple_assign_lhs (stmt);
17823 }
2d78e89f 17824 gimple_stmt_iterator gsi = gsi_for_stmt (info->stmt);
d09768a4 17825 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
2d78e89f 17826 *orig_tp = repl;
d09768a4 17827 }
2d78e89f 17828 else if (!useless_type_conversion_p (TREE_TYPE (*tp), TREE_TYPE (repl)))
d09768a4 17829 {
17830 tree vce = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (*tp), repl);
17831 *tp = vce;
17832 }
17833 else
17834 *tp = repl;
17835
17836 info->modified = true;
d09768a4 17837 return NULL_TREE;
17838}
17839
17840/* Traverse the function body and perform all modifications as
17841 described in ADJUSTMENTS. At function return, ADJUSTMENTS will be
17842 modified such that the replacement/reduction value will now be an
17843 offset into the corresponding simd_array.
17844
17845 This function will replace all function argument uses with their
17846 corresponding simd array elements, and ajust the return values
17847 accordingly. */
17848
17849static void
17850ipa_simd_modify_function_body (struct cgraph_node *node,
17851 ipa_parm_adjustment_vec adjustments,
17852 tree retval_array, tree iter)
17853{
17854 basic_block bb;
2d78e89f 17855 unsigned int i, j, l;
d09768a4 17856
17857 /* Re-use the adjustments array, but this time use it to replace
17858 every function argument use to an offset into the corresponding
17859 simd_array. */
17860 for (i = 0, j = 0; i < node->simdclone->nargs; ++i, ++j)
17861 {
17862 if (!node->simdclone->args[i].vector_arg)
17863 continue;
17864
17865 tree basetype = TREE_TYPE (node->simdclone->args[i].orig_arg);
17866 tree vectype = TREE_TYPE (node->simdclone->args[i].vector_arg);
17867 adjustments[j].new_decl
17868 = build4 (ARRAY_REF,
17869 basetype,
17870 node->simdclone->args[i].simd_array,
17871 iter,
17872 NULL_TREE, NULL_TREE);
17873 if (adjustments[j].op == IPA_PARM_OP_NONE
17874 && TYPE_VECTOR_SUBPARTS (vectype) < node->simdclone->simdlen)
17875 j += node->simdclone->simdlen / TYPE_VECTOR_SUBPARTS (vectype) - 1;
17876 }
17877
2d78e89f 17878 l = adjustments.length ();
17879 for (i = 1; i < num_ssa_names; i++)
17880 {
17881 tree name = ssa_name (i);
17882 if (name
17883 && SSA_NAME_VAR (name)
17884 && TREE_CODE (SSA_NAME_VAR (name)) == PARM_DECL)
17885 {
17886 for (j = 0; j < l; j++)
17887 if (SSA_NAME_VAR (name) == adjustments[j].base
17888 && adjustments[j].new_decl)
17889 {
17890 tree base_var;
17891 if (adjustments[j].new_ssa_base == NULL_TREE)
17892 {
17893 base_var
17894 = copy_var_decl (adjustments[j].base,
17895 DECL_NAME (adjustments[j].base),
17896 TREE_TYPE (adjustments[j].base));
17897 adjustments[j].new_ssa_base = base_var;
17898 }
17899 else
17900 base_var = adjustments[j].new_ssa_base;
17901 if (SSA_NAME_IS_DEFAULT_DEF (name))
17902 {
17903 bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
17904 gimple_stmt_iterator gsi = gsi_after_labels (bb);
17905 tree new_decl = unshare_expr (adjustments[j].new_decl);
17906 set_ssa_default_def (cfun, adjustments[j].base, NULL_TREE);
17907 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
17908 SSA_NAME_IS_DEFAULT_DEF (name) = 0;
42acab1c 17909 gimple *stmt = gimple_build_assign (name, new_decl);
2d78e89f 17910 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
17911 }
17912 else
17913 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
17914 }
17915 }
17916 }
17917
d09768a4 17918 struct modify_stmt_info info;
17919 info.adjustments = adjustments;
17920
17921 FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl))
17922 {
17923 gimple_stmt_iterator gsi;
17924
17925 gsi = gsi_start_bb (bb);
17926 while (!gsi_end_p (gsi))
17927 {
42acab1c 17928 gimple *stmt = gsi_stmt (gsi);
d09768a4 17929 info.stmt = stmt;
17930 struct walk_stmt_info wi;
17931
17932 memset (&wi, 0, sizeof (wi));
17933 info.modified = false;
17934 wi.info = &info;
17935 walk_gimple_op (stmt, ipa_simd_modify_stmt_ops, &wi);
17936
1a91d914 17937 if (greturn *return_stmt = dyn_cast <greturn *> (stmt))
d09768a4 17938 {
1a91d914 17939 tree retval = gimple_return_retval (return_stmt);
d09768a4 17940 if (!retval)
17941 {
17942 gsi_remove (&gsi, true);
17943 continue;
17944 }
17945
17946 /* Replace `return foo' with `retval_array[iter] = foo'. */
17947 tree ref = build4 (ARRAY_REF, TREE_TYPE (retval),
17948 retval_array, iter, NULL, NULL);
17949 stmt = gimple_build_assign (ref, retval);
17950 gsi_replace (&gsi, stmt, true);
17951 info.modified = true;
17952 }
17953
17954 if (info.modified)
17955 {
17956 update_stmt (stmt);
17957 if (maybe_clean_eh_stmt (stmt))
17958 gimple_purge_dead_eh_edges (gimple_bb (stmt));
17959 }
17960 gsi_next (&gsi);
17961 }
17962 }
17963}
17964
9561765e 17965/* Helper function of simd_clone_adjust, return linear step addend
17966 of Ith argument. */
17967
17968static tree
17969simd_clone_linear_addend (struct cgraph_node *node, unsigned int i,
17970 tree addtype, basic_block entry_bb)
17971{
17972 tree ptype = NULL_TREE;
17973 switch (node->simdclone->args[i].arg_type)
17974 {
17975 case SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP:
17976 case SIMD_CLONE_ARG_TYPE_LINEAR_REF_CONSTANT_STEP:
17977 case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_CONSTANT_STEP:
17978 case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP:
17979 return build_int_cst (addtype, node->simdclone->args[i].linear_step);
17980 case SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP:
17981 case SIMD_CLONE_ARG_TYPE_LINEAR_REF_VARIABLE_STEP:
17982 ptype = TREE_TYPE (node->simdclone->args[i].orig_arg);
17983 break;
17984 case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_VARIABLE_STEP:
17985 case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_VARIABLE_STEP:
17986 ptype = TREE_TYPE (TREE_TYPE (node->simdclone->args[i].orig_arg));
17987 break;
17988 default:
17989 gcc_unreachable ();
17990 }
17991
17992 unsigned int idx = node->simdclone->args[i].linear_step;
17993 tree arg = node->simdclone->args[idx].orig_arg;
17994 gcc_assert (is_gimple_reg_type (TREE_TYPE (arg)));
17995 gimple_stmt_iterator gsi = gsi_after_labels (entry_bb);
17996 gimple *g;
17997 tree ret;
17998 if (is_gimple_reg (arg))
17999 ret = get_or_create_ssa_default_def (cfun, arg);
18000 else
18001 {
18002 g = gimple_build_assign (make_ssa_name (TREE_TYPE (arg)), arg);
18003 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
18004 ret = gimple_assign_lhs (g);
18005 }
18006 if (TREE_CODE (TREE_TYPE (arg)) == REFERENCE_TYPE)
18007 {
18008 g = gimple_build_assign (make_ssa_name (TREE_TYPE (TREE_TYPE (arg))),
18009 build_simple_mem_ref (ret));
18010 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
18011 ret = gimple_assign_lhs (g);
18012 }
18013 if (!useless_type_conversion_p (addtype, TREE_TYPE (ret)))
18014 {
18015 g = gimple_build_assign (make_ssa_name (addtype), NOP_EXPR, ret);
18016 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
18017 ret = gimple_assign_lhs (g);
18018 }
18019 if (POINTER_TYPE_P (ptype))
18020 {
18021 tree size = TYPE_SIZE_UNIT (TREE_TYPE (ptype));
18022 if (size && TREE_CODE (size) == INTEGER_CST)
18023 {
18024 g = gimple_build_assign (make_ssa_name (addtype), MULT_EXPR,
18025 ret, fold_convert (addtype, size));
18026 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
18027 ret = gimple_assign_lhs (g);
18028 }
18029 }
18030 return ret;
18031}
18032
d09768a4 18033/* Adjust the argument types in NODE to their appropriate vector
18034 counterparts. */
18035
18036static void
18037simd_clone_adjust (struct cgraph_node *node)
18038{
18039 push_cfun (DECL_STRUCT_FUNCTION (node->decl));
18040
18041 targetm.simd_clone.adjust (node);
18042
18043 tree retval = simd_clone_adjust_return_type (node);
18044 ipa_parm_adjustment_vec adjustments
18045 = simd_clone_adjust_argument_types (node);
18046
18047 push_gimplify_context ();
18048
18049 gimple_seq seq = simd_clone_init_simd_arrays (node, adjustments);
18050
18051 /* Adjust all uses of vector arguments accordingly. Adjust all
18052 return values accordingly. */
18053 tree iter = create_tmp_var (unsigned_type_node, "iter");
f9e245b2 18054 tree iter1 = make_ssa_name (iter);
18055 tree iter2 = make_ssa_name (iter);
d09768a4 18056 ipa_simd_modify_function_body (node, adjustments, retval, iter1);
18057
18058 /* Initialize the iteration variable. */
18059 basic_block entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
18060 basic_block body_bb = split_block_after_labels (entry_bb)->dest;
18061 gimple_stmt_iterator gsi = gsi_after_labels (entry_bb);
18062 /* Insert the SIMD array and iv initialization at function
18063 entry. */
18064 gsi_insert_seq_before (&gsi, seq, GSI_NEW_STMT);
18065
18066 pop_gimplify_context (NULL);
18067
18068 /* Create a new BB right before the original exit BB, to hold the
18069 iteration increment and the condition/branch. */
18070 basic_block orig_exit = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), 0)->src;
18071 basic_block incr_bb = create_empty_bb (orig_exit);
343ee723 18072 add_bb_to_loop (incr_bb, body_bb->loop_father);
d09768a4 18073 /* The succ of orig_exit was EXIT_BLOCK_PTR_FOR_FN (cfun), with an empty
18074 flag. Set it now to be a FALLTHRU_EDGE. */
18075 gcc_assert (EDGE_COUNT (orig_exit->succs) == 1);
18076 EDGE_SUCC (orig_exit, 0)->flags |= EDGE_FALLTHRU;
18077 for (unsigned i = 0;
18078 i < EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds); ++i)
18079 {
18080 edge e = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), i);
18081 redirect_edge_succ (e, incr_bb);
18082 }
18083 edge e = make_edge (incr_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
18084 e->probability = REG_BR_PROB_BASE;
18085 gsi = gsi_last_bb (incr_bb);
42acab1c 18086 gimple *g = gimple_build_assign (iter2, PLUS_EXPR, iter1,
e9cf809e 18087 build_int_cst (unsigned_type_node, 1));
d09768a4 18088 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
18089
18090 /* Mostly annotate the loop for the vectorizer (the rest is done below). */
18091 struct loop *loop = alloc_loop ();
4c73695b 18092 cfun->has_force_vectorize_loops = true;
d09768a4 18093 loop->safelen = node->simdclone->simdlen;
4c73695b 18094 loop->force_vectorize = true;
d09768a4 18095 loop->header = body_bb;
d09768a4 18096
18097 /* Branch around the body if the mask applies. */
18098 if (node->simdclone->inbranch)
18099 {
18100 gimple_stmt_iterator gsi = gsi_last_bb (loop->header);
18101 tree mask_array
18102 = node->simdclone->args[node->simdclone->nargs - 1].simd_array;
f9e245b2 18103 tree mask = make_ssa_name (TREE_TYPE (TREE_TYPE (mask_array)));
d09768a4 18104 tree aref = build4 (ARRAY_REF,
18105 TREE_TYPE (TREE_TYPE (mask_array)),
18106 mask_array, iter1,
18107 NULL, NULL);
18108 g = gimple_build_assign (mask, aref);
18109 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
18110 int bitsize = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (aref)));
18111 if (!INTEGRAL_TYPE_P (TREE_TYPE (aref)))
18112 {
18113 aref = build1 (VIEW_CONVERT_EXPR,
18114 build_nonstandard_integer_type (bitsize, 0), mask);
f9e245b2 18115 mask = make_ssa_name (TREE_TYPE (aref));
d09768a4 18116 g = gimple_build_assign (mask, aref);
18117 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
18118 }
18119
18120 g = gimple_build_cond (EQ_EXPR, mask, build_zero_cst (TREE_TYPE (mask)),
18121 NULL, NULL);
18122 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
18123 make_edge (loop->header, incr_bb, EDGE_TRUE_VALUE);
18124 FALLTHRU_EDGE (loop->header)->flags = EDGE_FALSE_VALUE;
18125 }
18126
18127 /* Generate the condition. */
18128 g = gimple_build_cond (LT_EXPR,
18129 iter2,
18130 build_int_cst (unsigned_type_node,
18131 node->simdclone->simdlen),
18132 NULL, NULL);
18133 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
18134 e = split_block (incr_bb, gsi_stmt (gsi));
18135 basic_block latch_bb = e->dest;
343ee723 18136 basic_block new_exit_bb;
4302d619 18137 new_exit_bb = split_block_after_labels (latch_bb)->dest;
d09768a4 18138 loop->latch = latch_bb;
18139
18140 redirect_edge_succ (FALLTHRU_EDGE (latch_bb), body_bb);
18141
18142 make_edge (incr_bb, new_exit_bb, EDGE_FALSE_VALUE);
18143 /* The successor of incr_bb is already pointing to latch_bb; just
18144 change the flags.
18145 make_edge (incr_bb, latch_bb, EDGE_TRUE_VALUE); */
18146 FALLTHRU_EDGE (incr_bb)->flags = EDGE_TRUE_VALUE;
18147
1a91d914 18148 gphi *phi = create_phi_node (iter1, body_bb);
d09768a4 18149 edge preheader_edge = find_edge (entry_bb, body_bb);
18150 edge latch_edge = single_succ_edge (latch_bb);
18151 add_phi_arg (phi, build_zero_cst (unsigned_type_node), preheader_edge,
18152 UNKNOWN_LOCATION);
18153 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
18154
18155 /* Generate the new return. */
18156 gsi = gsi_last_bb (new_exit_bb);
18157 if (retval
18158 && TREE_CODE (retval) == VIEW_CONVERT_EXPR
18159 && TREE_CODE (TREE_OPERAND (retval, 0)) == RESULT_DECL)
18160 retval = TREE_OPERAND (retval, 0);
18161 else if (retval)
18162 {
18163 retval = build1 (VIEW_CONVERT_EXPR,
18164 TREE_TYPE (TREE_TYPE (node->decl)),
18165 retval);
18166 retval = force_gimple_operand_gsi (&gsi, retval, true, NULL,
18167 false, GSI_CONTINUE_LINKING);
18168 }
18169 g = gimple_build_return (retval);
18170 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
18171
18172 /* Handle aligned clauses by replacing default defs of the aligned
18173 uniform args with __builtin_assume_aligned (arg_N(D), alignment)
18174 lhs. Handle linear by adding PHIs. */
18175 for (unsigned i = 0; i < node->simdclone->nargs; i++)
97a82d40 18176 if (node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
18177 && (TREE_ADDRESSABLE (node->simdclone->args[i].orig_arg)
18178 || !is_gimple_reg_type
18179 (TREE_TYPE (node->simdclone->args[i].orig_arg))))
18180 {
18181 tree orig_arg = node->simdclone->args[i].orig_arg;
18182 if (is_gimple_reg_type (TREE_TYPE (orig_arg)))
18183 iter1 = make_ssa_name (TREE_TYPE (orig_arg));
18184 else
18185 {
18186 iter1 = create_tmp_var_raw (TREE_TYPE (orig_arg));
18187 gimple_add_tmp_var (iter1);
18188 }
18189 gsi = gsi_after_labels (entry_bb);
18190 g = gimple_build_assign (iter1, orig_arg);
18191 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
18192 gsi = gsi_after_labels (body_bb);
18193 g = gimple_build_assign (orig_arg, iter1);
18194 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
18195 }
18196 else if (node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
18197 && DECL_BY_REFERENCE (node->simdclone->args[i].orig_arg)
18198 && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
18199 == REFERENCE_TYPE
18200 && TREE_ADDRESSABLE
18201 (TREE_TYPE (TREE_TYPE (node->simdclone->args[i].orig_arg))))
18202 {
18203 tree orig_arg = node->simdclone->args[i].orig_arg;
18204 tree def = ssa_default_def (cfun, orig_arg);
18205 if (def && !has_zero_uses (def))
18206 {
18207 iter1 = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (orig_arg)));
18208 gimple_add_tmp_var (iter1);
18209 gsi = gsi_after_labels (entry_bb);
18210 g = gimple_build_assign (iter1, build_simple_mem_ref (def));
18211 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
18212 gsi = gsi_after_labels (body_bb);
18213 g = gimple_build_assign (build_simple_mem_ref (def), iter1);
18214 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
18215 }
18216 }
18217 else if (node->simdclone->args[i].alignment
18218 && node->simdclone->args[i].arg_type
18219 == SIMD_CLONE_ARG_TYPE_UNIFORM
18220 && (node->simdclone->args[i].alignment
18221 & (node->simdclone->args[i].alignment - 1)) == 0
18222 && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
18223 == POINTER_TYPE)
d09768a4 18224 {
18225 unsigned int alignment = node->simdclone->args[i].alignment;
18226 tree orig_arg = node->simdclone->args[i].orig_arg;
18227 tree def = ssa_default_def (cfun, orig_arg);
6db33a3d 18228 if (def && !has_zero_uses (def))
d09768a4 18229 {
18230 tree fn = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
18231 gimple_seq seq = NULL;
18232 bool need_cvt = false;
1a91d914 18233 gcall *call
d09768a4 18234 = gimple_build_call (fn, 2, def, size_int (alignment));
18235 g = call;
18236 if (!useless_type_conversion_p (TREE_TYPE (orig_arg),
18237 ptr_type_node))
18238 need_cvt = true;
f9e245b2 18239 tree t = make_ssa_name (need_cvt ? ptr_type_node : orig_arg);
d09768a4 18240 gimple_call_set_lhs (g, t);
18241 gimple_seq_add_stmt_without_update (&seq, g);
18242 if (need_cvt)
18243 {
f9e245b2 18244 t = make_ssa_name (orig_arg);
e9cf809e 18245 g = gimple_build_assign (t, NOP_EXPR, gimple_call_lhs (g));
d09768a4 18246 gimple_seq_add_stmt_without_update (&seq, g);
18247 }
18248 gsi_insert_seq_on_edge_immediate
18249 (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)), seq);
18250
18251 entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
18252 int freq = compute_call_stmt_bb_frequency (current_function_decl,
18253 entry_bb);
415d1b9a 18254 node->create_edge (cgraph_node::get_create (fn),
18255 call, entry_bb->count, freq);
d09768a4 18256
18257 imm_use_iterator iter;
18258 use_operand_p use_p;
42acab1c 18259 gimple *use_stmt;
d09768a4 18260 tree repl = gimple_get_lhs (g);
18261 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
18262 if (is_gimple_debug (use_stmt) || use_stmt == call)
18263 continue;
18264 else
18265 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
18266 SET_USE (use_p, repl);
18267 }
18268 }
43895be5 18269 else if ((node->simdclone->args[i].arg_type
18270 == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
18271 || (node->simdclone->args[i].arg_type
9561765e 18272 == SIMD_CLONE_ARG_TYPE_LINEAR_REF_CONSTANT_STEP)
18273 || (node->simdclone->args[i].arg_type
18274 == SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP)
18275 || (node->simdclone->args[i].arg_type
18276 == SIMD_CLONE_ARG_TYPE_LINEAR_REF_VARIABLE_STEP))
d09768a4 18277 {
18278 tree orig_arg = node->simdclone->args[i].orig_arg;
d09768a4 18279 gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
18280 || POINTER_TYPE_P (TREE_TYPE (orig_arg)));
97a82d40 18281 tree def = NULL_TREE;
18282 if (TREE_ADDRESSABLE (orig_arg))
18283 {
18284 def = make_ssa_name (TREE_TYPE (orig_arg));
18285 iter1 = make_ssa_name (TREE_TYPE (orig_arg));
18286 iter2 = make_ssa_name (TREE_TYPE (orig_arg));
18287 gsi = gsi_after_labels (entry_bb);
18288 g = gimple_build_assign (def, orig_arg);
18289 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
18290 }
18291 else
18292 {
18293 def = ssa_default_def (cfun, orig_arg);
18294 if (!def || has_zero_uses (def))
18295 def = NULL_TREE;
18296 else
18297 {
18298 iter1 = make_ssa_name (orig_arg);
18299 iter2 = make_ssa_name (orig_arg);
18300 }
18301 }
18302 if (def)
d09768a4 18303 {
d09768a4 18304 phi = create_phi_node (iter1, body_bb);
18305 add_phi_arg (phi, def, preheader_edge, UNKNOWN_LOCATION);
18306 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
18307 enum tree_code code = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
18308 ? PLUS_EXPR : POINTER_PLUS_EXPR;
18309 tree addtype = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
18310 ? TREE_TYPE (orig_arg) : sizetype;
9561765e 18311 tree addcst = simd_clone_linear_addend (node, i, addtype,
18312 entry_bb);
d09768a4 18313 gsi = gsi_last_bb (incr_bb);
9561765e 18314 g = gimple_build_assign (iter2, code, iter1, addcst);
d09768a4 18315 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
18316
18317 imm_use_iterator iter;
18318 use_operand_p use_p;
42acab1c 18319 gimple *use_stmt;
97a82d40 18320 if (TREE_ADDRESSABLE (orig_arg))
18321 {
18322 gsi = gsi_after_labels (body_bb);
18323 g = gimple_build_assign (orig_arg, iter1);
18324 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
18325 }
18326 else
18327 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
18328 if (use_stmt == phi)
18329 continue;
18330 else
18331 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
18332 SET_USE (use_p, iter1);
d09768a4 18333 }
18334 }
43895be5 18335 else if (node->simdclone->args[i].arg_type
9561765e 18336 == SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP
18337 || (node->simdclone->args[i].arg_type
18338 == SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_VARIABLE_STEP))
43895be5 18339 {
18340 tree orig_arg = node->simdclone->args[i].orig_arg;
18341 tree def = ssa_default_def (cfun, orig_arg);
18342 gcc_assert (!TREE_ADDRESSABLE (orig_arg)
18343 && TREE_CODE (TREE_TYPE (orig_arg)) == REFERENCE_TYPE);
18344 if (def && !has_zero_uses (def))
18345 {
18346 tree rtype = TREE_TYPE (TREE_TYPE (orig_arg));
18347 iter1 = make_ssa_name (orig_arg);
18348 iter2 = make_ssa_name (orig_arg);
18349 tree iter3 = make_ssa_name (rtype);
18350 tree iter4 = make_ssa_name (rtype);
18351 tree iter5 = make_ssa_name (rtype);
18352 gsi = gsi_after_labels (entry_bb);
18353 gimple *load
18354 = gimple_build_assign (iter3, build_simple_mem_ref (def));
18355 gsi_insert_before (&gsi, load, GSI_NEW_STMT);
18356
18357 tree array = node->simdclone->args[i].simd_array;
18358 TREE_ADDRESSABLE (array) = 1;
18359 tree ptr = build_fold_addr_expr (array);
18360 phi = create_phi_node (iter1, body_bb);
18361 add_phi_arg (phi, ptr, preheader_edge, UNKNOWN_LOCATION);
18362 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
18363 g = gimple_build_assign (iter2, POINTER_PLUS_EXPR, iter1,
18364 TYPE_SIZE_UNIT (TREE_TYPE (iter3)));
18365 gsi = gsi_last_bb (incr_bb);
18366 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
18367
18368 phi = create_phi_node (iter4, body_bb);
18369 add_phi_arg (phi, iter3, preheader_edge, UNKNOWN_LOCATION);
18370 add_phi_arg (phi, iter5, latch_edge, UNKNOWN_LOCATION);
18371 enum tree_code code = INTEGRAL_TYPE_P (TREE_TYPE (iter3))
18372 ? PLUS_EXPR : POINTER_PLUS_EXPR;
18373 tree addtype = INTEGRAL_TYPE_P (TREE_TYPE (iter3))
18374 ? TREE_TYPE (iter3) : sizetype;
9561765e 18375 tree addcst = simd_clone_linear_addend (node, i, addtype,
18376 entry_bb);
43895be5 18377 g = gimple_build_assign (iter5, code, iter4, addcst);
18378 gsi = gsi_last_bb (incr_bb);
18379 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
18380
18381 g = gimple_build_assign (build_simple_mem_ref (iter1), iter4);
18382 gsi = gsi_after_labels (body_bb);
18383 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
18384
18385 imm_use_iterator iter;
18386 use_operand_p use_p;
18387 gimple *use_stmt;
18388 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
18389 if (use_stmt == load)
18390 continue;
18391 else
18392 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
18393 SET_USE (use_p, iter1);
18394
18395 if (!TYPE_READONLY (rtype))
18396 {
18397 tree v = make_ssa_name (rtype);
18398 tree aref = build4 (ARRAY_REF, rtype, array,
18399 size_zero_node, NULL_TREE,
18400 NULL_TREE);
18401 gsi = gsi_after_labels (new_exit_bb);
18402 g = gimple_build_assign (v, aref);
18403 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
18404 g = gimple_build_assign (build_simple_mem_ref (def), v);
18405 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
18406 }
18407 }
18408 }
d09768a4 18409
18410 calculate_dominance_info (CDI_DOMINATORS);
18411 add_loop (loop, loop->header->loop_father);
18412 update_ssa (TODO_update_ssa);
18413
18414 pop_cfun ();
18415}
18416
18417/* If the function in NODE is tagged as an elemental SIMD function,
18418 create the appropriate SIMD clones. */
18419
18420static void
18421expand_simd_clones (struct cgraph_node *node)
18422{
d09768a4 18423 tree attr = lookup_attribute ("omp declare simd",
18424 DECL_ATTRIBUTES (node->decl));
ea0695f9 18425 if (attr == NULL_TREE
18426 || node->global.inlined_to
18427 || lookup_attribute ("noclone", DECL_ATTRIBUTES (node->decl)))
d09768a4 18428 return;
ea0695f9 18429
d09768a4 18430 /* Ignore
18431 #pragma omp declare simd
18432 extern int foo ();
18433 in C, there we don't know the argument types at all. */
18434 if (!node->definition
18435 && TYPE_ARG_TYPES (TREE_TYPE (node->decl)) == NULL_TREE)
18436 return;
18437
b2fbac0f 18438 /* Call this before creating clone_info, as it might ggc_collect. */
18439 if (node->definition && node->has_gimple_body_p ())
18440 node->get_body ();
18441
d09768a4 18442 do
18443 {
18444 /* Start with parsing the "omp declare simd" attribute(s). */
18445 bool inbranch_clause_specified;
18446 struct cgraph_simd_clone *clone_info
18447 = simd_clone_clauses_extract (node, TREE_VALUE (attr),
18448 &inbranch_clause_specified);
18449 if (clone_info == NULL)
18450 continue;
18451
18452 int orig_simdlen = clone_info->simdlen;
18453 tree base_type = simd_clone_compute_base_data_type (node, clone_info);
18454 /* The target can return 0 (no simd clones should be created),
18455 1 (just one ISA of simd clones should be created) or higher
18456 count of ISA variants. In that case, clone_info is initialized
18457 for the first ISA variant. */
18458 int count
18459 = targetm.simd_clone.compute_vecsize_and_simdlen (node, clone_info,
18460 base_type, 0);
18461 if (count == 0)
18462 continue;
18463
18464 /* Loop over all COUNT ISA variants, and if !INBRANCH_CLAUSE_SPECIFIED,
18465 also create one inbranch and one !inbranch clone of it. */
18466 for (int i = 0; i < count * 2; i++)
18467 {
18468 struct cgraph_simd_clone *clone = clone_info;
18469 if (inbranch_clause_specified && (i & 1) != 0)
18470 continue;
18471
18472 if (i != 0)
18473 {
18474 clone = simd_clone_struct_alloc (clone_info->nargs
d09768a4 18475 + ((i & 1) != 0));
18476 simd_clone_struct_copy (clone, clone_info);
18477 /* Undo changes targetm.simd_clone.compute_vecsize_and_simdlen
18478 and simd_clone_adjust_argument_types did to the first
18479 clone's info. */
18480 clone->nargs -= clone_info->inbranch;
18481 clone->simdlen = orig_simdlen;
18482 /* And call the target hook again to get the right ISA. */
18483 targetm.simd_clone.compute_vecsize_and_simdlen (node, clone,
18484 base_type,
18485 i / 2);
18486 if ((i & 1) != 0)
18487 clone->inbranch = 1;
18488 }
18489
18490 /* simd_clone_mangle might fail if such a clone has been created
18491 already. */
18492 tree id = simd_clone_mangle (node, clone);
18493 if (id == NULL_TREE)
18494 continue;
18495
18496 /* Only when we are sure we want to create the clone actually
18497 clone the function (or definitions) or create another
18498 extern FUNCTION_DECL (for prototypes without definitions). */
18499 struct cgraph_node *n = simd_clone_create (node);
18500 if (n == NULL)
18501 continue;
18502
18503 n->simdclone = clone;
18504 clone->origin = node;
18505 clone->next_clone = NULL;
18506 if (node->simd_clones == NULL)
18507 {
18508 clone->prev_clone = n;
18509 node->simd_clones = n;
18510 }
18511 else
18512 {
18513 clone->prev_clone = node->simd_clones->simdclone->prev_clone;
18514 clone->prev_clone->simdclone->next_clone = n;
18515 node->simd_clones->simdclone->prev_clone = n;
18516 }
35ee1c66 18517 symtab->change_decl_assembler_name (n->decl, id);
d09768a4 18518 /* And finally adjust the return type, parameters and for
18519 definitions also function body. */
18520 if (node->definition)
18521 simd_clone_adjust (n);
18522 else
18523 {
18524 simd_clone_adjust_return_type (n);
18525 simd_clone_adjust_argument_types (n);
18526 }
18527 }
18528 }
18529 while ((attr = lookup_attribute ("omp declare simd", TREE_CHAIN (attr))));
18530}
18531
18532/* Entry point for IPA simd clone creation pass. */
18533
18534static unsigned int
18535ipa_omp_simd_clone (void)
18536{
18537 struct cgraph_node *node;
18538 FOR_EACH_FUNCTION (node)
18539 expand_simd_clones (node);
18540 return 0;
18541}
18542
7620bc82 18543namespace {
18544
18545const pass_data pass_data_omp_simd_clone =
d09768a4 18546{
18547 SIMPLE_IPA_PASS, /* type */
18548 "simdclone", /* name */
18549 OPTGROUP_NONE, /* optinfo_flags */
d09768a4 18550 TV_NONE, /* tv_id */
18551 ( PROP_ssa | PROP_cfg ), /* properties_required */
18552 0, /* properties_provided */
18553 0, /* properties_destroyed */
18554 0, /* todo_flags_start */
18555 0, /* todo_flags_finish */
18556};
18557
7620bc82 18558class pass_omp_simd_clone : public simple_ipa_opt_pass
d09768a4 18559{
18560public:
18561 pass_omp_simd_clone(gcc::context *ctxt)
18562 : simple_ipa_opt_pass(pass_data_omp_simd_clone, ctxt)
18563 {}
18564
18565 /* opt_pass methods: */
31315c24 18566 virtual bool gate (function *);
65b0537f 18567 virtual unsigned int execute (function *) { return ipa_omp_simd_clone (); }
d09768a4 18568};
18569
31315c24 18570bool
18571pass_omp_simd_clone::gate (function *)
18572{
c58a4cfd 18573 return targetm.simd_clone.compute_vecsize_and_simdlen != NULL;
31315c24 18574}
18575
7620bc82 18576} // anon namespace
18577
d09768a4 18578simple_ipa_opt_pass *
18579make_pass_omp_simd_clone (gcc::context *ctxt)
18580{
18581 return new pass_omp_simd_clone (ctxt);
18582}
cbe8bda8 18583
dccabdd1 18584/* Helper function for omp_finish_file routine. Takes decls from V_DECLS and
18585 adds their addresses and sizes to constructor-vector V_CTOR. */
18586static void
18587add_decls_addresses_to_decl_constructor (vec<tree, va_gc> *v_decls,
18588 vec<constructor_elt, va_gc> *v_ctor)
18589{
18590 unsigned len = vec_safe_length (v_decls);
18591 for (unsigned i = 0; i < len; i++)
18592 {
18593 tree it = (*v_decls)[i];
c0998828 18594 bool is_var = TREE_CODE (it) == VAR_DECL;
18595 bool is_link_var
18596 = is_var
18597#ifdef ACCEL_COMPILER
18598 && DECL_HAS_VALUE_EXPR_P (it)
18599#endif
18600 && lookup_attribute ("omp declare target link", DECL_ATTRIBUTES (it));
dccabdd1 18601
c0998828 18602 tree size = NULL_TREE;
18603 if (is_var)
18604 size = fold_convert (const_ptr_type_node, DECL_SIZE_UNIT (it));
18605
18606 tree addr;
18607 if (!is_link_var)
18608 addr = build_fold_addr_expr (it);
18609 else
18610 {
18611#ifdef ACCEL_COMPILER
18612 /* For "omp declare target link" vars add address of the pointer to
18613 the target table, instead of address of the var. */
18614 tree value_expr = DECL_VALUE_EXPR (it);
18615 tree link_ptr_decl = TREE_OPERAND (value_expr, 0);
18616 varpool_node::finalize_decl (link_ptr_decl);
18617 addr = build_fold_addr_expr (link_ptr_decl);
18618#else
18619 addr = build_fold_addr_expr (it);
18620#endif
18621
18622 /* Most significant bit of the size marks "omp declare target link"
18623 vars in host and target tables. */
18624 unsigned HOST_WIDE_INT isize = tree_to_uhwi (size);
18625 isize |= 1ULL << (int_size_in_bytes (const_ptr_type_node)
18626 * BITS_PER_UNIT - 1);
18627 size = wide_int_to_tree (const_ptr_type_node, isize);
18628 }
18629
18630 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE, addr);
18631 if (is_var)
18632 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE, size);
dccabdd1 18633 }
18634}
18635
18636/* Create new symbols containing (address, size) pairs for global variables,
18637 marked with "omp declare target" attribute, as well as addresses for the
ca4c3545 18638 functions, which are outlined offloading regions. */
dccabdd1 18639void
18640omp_finish_file (void)
18641{
18642 unsigned num_funcs = vec_safe_length (offload_funcs);
18643 unsigned num_vars = vec_safe_length (offload_vars);
18644
18645 if (num_funcs == 0 && num_vars == 0)
18646 return;
18647
18648 if (targetm_common.have_named_sections)
18649 {
18650 vec<constructor_elt, va_gc> *v_f, *v_v;
18651 vec_alloc (v_f, num_funcs);
18652 vec_alloc (v_v, num_vars * 2);
18653
18654 add_decls_addresses_to_decl_constructor (offload_funcs, v_f);
18655 add_decls_addresses_to_decl_constructor (offload_vars, v_v);
18656
18657 tree vars_decl_type = build_array_type_nelts (pointer_sized_int_node,
18658 num_vars * 2);
18659 tree funcs_decl_type = build_array_type_nelts (pointer_sized_int_node,
18660 num_funcs);
18661 TYPE_ALIGN (vars_decl_type) = TYPE_ALIGN (pointer_sized_int_node);
18662 TYPE_ALIGN (funcs_decl_type) = TYPE_ALIGN (pointer_sized_int_node);
18663 tree ctor_v = build_constructor (vars_decl_type, v_v);
18664 tree ctor_f = build_constructor (funcs_decl_type, v_f);
18665 TREE_CONSTANT (ctor_v) = TREE_CONSTANT (ctor_f) = 1;
18666 TREE_STATIC (ctor_v) = TREE_STATIC (ctor_f) = 1;
18667 tree funcs_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
18668 get_identifier (".offload_func_table"),
18669 funcs_decl_type);
18670 tree vars_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
18671 get_identifier (".offload_var_table"),
18672 vars_decl_type);
18673 TREE_STATIC (funcs_decl) = TREE_STATIC (vars_decl) = 1;
18674 /* Do not align tables more than TYPE_ALIGN (pointer_sized_int_node),
18675 otherwise a joint table in a binary will contain padding between
18676 tables from multiple object files. */
18677 DECL_USER_ALIGN (funcs_decl) = DECL_USER_ALIGN (vars_decl) = 1;
18678 DECL_ALIGN (funcs_decl) = TYPE_ALIGN (funcs_decl_type);
18679 DECL_ALIGN (vars_decl) = TYPE_ALIGN (vars_decl_type);
18680 DECL_INITIAL (funcs_decl) = ctor_f;
18681 DECL_INITIAL (vars_decl) = ctor_v;
18682 set_decl_section_name (funcs_decl, OFFLOAD_FUNC_TABLE_SECTION_NAME);
18683 set_decl_section_name (vars_decl, OFFLOAD_VAR_TABLE_SECTION_NAME);
18684
18685 varpool_node::finalize_decl (vars_decl);
18686 varpool_node::finalize_decl (funcs_decl);
7114ebdd 18687 }
dccabdd1 18688 else
18689 {
18690 for (unsigned i = 0; i < num_funcs; i++)
18691 {
18692 tree it = (*offload_funcs)[i];
18693 targetm.record_offload_symbol (it);
18694 }
18695 for (unsigned i = 0; i < num_vars; i++)
18696 {
18697 tree it = (*offload_vars)[i];
18698 targetm.record_offload_symbol (it);
18699 }
18700 }
18701}
18702
cbba99a0 18703/* Find the number of threads (POS = false), or thread number (POS =
18704 true) for an OpenACC region partitioned as MASK. Setup code
18705 required for the calculation is added to SEQ. */
18706
18707static tree
18708oacc_thread_numbers (bool pos, int mask, gimple_seq *seq)
18709{
18710 tree res = pos ? NULL_TREE : build_int_cst (unsigned_type_node, 1);
18711 unsigned ix;
18712
18713 /* Start at gang level, and examine relevant dimension indices. */
18714 for (ix = GOMP_DIM_GANG; ix != GOMP_DIM_MAX; ix++)
18715 if (GOMP_DIM_MASK (ix) & mask)
18716 {
18717 tree arg = build_int_cst (unsigned_type_node, ix);
18718
18719 if (res)
18720 {
18721 /* We had an outer index, so scale that by the size of
18722 this dimension. */
18723 tree n = create_tmp_var (integer_type_node);
18724 gimple *call
18725 = gimple_build_call_internal (IFN_GOACC_DIM_SIZE, 1, arg);
18726
18727 gimple_call_set_lhs (call, n);
18728 gimple_seq_add_stmt (seq, call);
18729 res = fold_build2 (MULT_EXPR, integer_type_node, res, n);
18730 }
18731 if (pos)
18732 {
18733 /* Determine index in this dimension. */
18734 tree id = create_tmp_var (integer_type_node);
18735 gimple *call = gimple_build_call_internal
18736 (IFN_GOACC_DIM_POS, 1, arg);
18737
18738 gimple_call_set_lhs (call, id);
18739 gimple_seq_add_stmt (seq, call);
18740 if (res)
18741 res = fold_build2 (PLUS_EXPR, integer_type_node, res, id);
18742 else
18743 res = id;
18744 }
18745 }
18746
18747 if (res == NULL_TREE)
18748 res = integer_zero_node;
18749
18750 return res;
18751}
18752
18753/* Transform IFN_GOACC_LOOP calls to actual code. See
18754 expand_oacc_for for where these are generated. At the vector
18755 level, we stride loops, such that each member of a warp will
18756 operate on adjacent iterations. At the worker and gang level,
18757 each gang/warp executes a set of contiguous iterations. Chunking
18758 can override this such that each iteration engine executes a
18759 contiguous chunk, and then moves on to stride to the next chunk. */
18760
18761static void
18762oacc_xform_loop (gcall *call)
18763{
18764 gimple_stmt_iterator gsi = gsi_for_stmt (call);
18765 enum ifn_goacc_loop_kind code
18766 = (enum ifn_goacc_loop_kind) TREE_INT_CST_LOW (gimple_call_arg (call, 0));
18767 tree dir = gimple_call_arg (call, 1);
18768 tree range = gimple_call_arg (call, 2);
18769 tree step = gimple_call_arg (call, 3);
18770 tree chunk_size = NULL_TREE;
18771 unsigned mask = (unsigned) TREE_INT_CST_LOW (gimple_call_arg (call, 5));
18772 tree lhs = gimple_call_lhs (call);
18773 tree type = TREE_TYPE (lhs);
18774 tree diff_type = TREE_TYPE (range);
18775 tree r = NULL_TREE;
18776 gimple_seq seq = NULL;
18777 bool chunking = false, striding = true;
18778 unsigned outer_mask = mask & (~mask + 1); // Outermost partitioning
18779 unsigned inner_mask = mask & ~outer_mask; // Inner partitioning (if any)
18780
18781#ifdef ACCEL_COMPILER
18782 chunk_size = gimple_call_arg (call, 4);
18783 if (integer_minus_onep (chunk_size) /* Force static allocation. */
18784 || integer_zerop (chunk_size)) /* Default (also static). */
18785 {
18786 /* If we're at the gang level, we want each to execute a
18787 contiguous run of iterations. Otherwise we want each element
18788 to stride. */
18789 striding = !(outer_mask & GOMP_DIM_MASK (GOMP_DIM_GANG));
18790 chunking = false;
18791 }
18792 else
18793 {
18794 /* Chunk of size 1 is striding. */
18795 striding = integer_onep (chunk_size);
18796 chunking = !striding;
18797 }
18798#endif
18799
18800 /* striding=true, chunking=true
18801 -> invalid.
18802 striding=true, chunking=false
18803 -> chunks=1
18804 striding=false,chunking=true
18805 -> chunks=ceil (range/(chunksize*threads*step))
18806 striding=false,chunking=false
18807 -> chunk_size=ceil(range/(threads*step)),chunks=1 */
18808 push_gimplify_context (true);
18809
18810 switch (code)
18811 {
18812 default: gcc_unreachable ();
18813
18814 case IFN_GOACC_LOOP_CHUNKS:
18815 if (!chunking)
18816 r = build_int_cst (type, 1);
18817 else
18818 {
18819 /* chunk_max
18820 = (range - dir) / (chunks * step * num_threads) + dir */
18821 tree per = oacc_thread_numbers (false, mask, &seq);
18822 per = fold_convert (type, per);
18823 chunk_size = fold_convert (type, chunk_size);
18824 per = fold_build2 (MULT_EXPR, type, per, chunk_size);
18825 per = fold_build2 (MULT_EXPR, type, per, step);
18826 r = build2 (MINUS_EXPR, type, range, dir);
18827 r = build2 (PLUS_EXPR, type, r, per);
18828 r = build2 (TRUNC_DIV_EXPR, type, r, per);
18829 }
18830 break;
18831
18832 case IFN_GOACC_LOOP_STEP:
18833 {
18834 /* If striding, step by the entire compute volume, otherwise
18835 step by the inner volume. */
18836 unsigned volume = striding ? mask : inner_mask;
18837
18838 r = oacc_thread_numbers (false, volume, &seq);
18839 r = build2 (MULT_EXPR, type, fold_convert (type, r), step);
18840 }
18841 break;
18842
18843 case IFN_GOACC_LOOP_OFFSET:
18844 if (striding)
18845 {
18846 r = oacc_thread_numbers (true, mask, &seq);
18847 r = fold_convert (diff_type, r);
18848 }
18849 else
18850 {
18851 tree inner_size = oacc_thread_numbers (false, inner_mask, &seq);
18852 tree outer_size = oacc_thread_numbers (false, outer_mask, &seq);
18853 tree volume = fold_build2 (MULT_EXPR, TREE_TYPE (inner_size),
18854 inner_size, outer_size);
18855
18856 volume = fold_convert (diff_type, volume);
18857 if (chunking)
18858 chunk_size = fold_convert (diff_type, chunk_size);
18859 else
18860 {
18861 tree per = fold_build2 (MULT_EXPR, diff_type, volume, step);
18862
18863 chunk_size = build2 (MINUS_EXPR, diff_type, range, dir);
18864 chunk_size = build2 (PLUS_EXPR, diff_type, chunk_size, per);
18865 chunk_size = build2 (TRUNC_DIV_EXPR, diff_type, chunk_size, per);
18866 }
18867
18868 tree span = build2 (MULT_EXPR, diff_type, chunk_size,
18869 fold_convert (diff_type, inner_size));
18870 r = oacc_thread_numbers (true, outer_mask, &seq);
18871 r = fold_convert (diff_type, r);
18872 r = build2 (MULT_EXPR, diff_type, r, span);
18873
18874 tree inner = oacc_thread_numbers (true, inner_mask, &seq);
18875 inner = fold_convert (diff_type, inner);
18876 r = fold_build2 (PLUS_EXPR, diff_type, r, inner);
18877
18878 if (chunking)
18879 {
18880 tree chunk = fold_convert (diff_type, gimple_call_arg (call, 6));
18881 tree per
18882 = fold_build2 (MULT_EXPR, diff_type, volume, chunk_size);
18883 per = build2 (MULT_EXPR, diff_type, per, chunk);
18884
18885 r = build2 (PLUS_EXPR, diff_type, r, per);
18886 }
18887 }
18888 r = fold_build2 (MULT_EXPR, diff_type, r, step);
18889 if (type != diff_type)
18890 r = fold_convert (type, r);
18891 break;
18892
18893 case IFN_GOACC_LOOP_BOUND:
18894 if (striding)
18895 r = range;
18896 else
18897 {
18898 tree inner_size = oacc_thread_numbers (false, inner_mask, &seq);
18899 tree outer_size = oacc_thread_numbers (false, outer_mask, &seq);
18900 tree volume = fold_build2 (MULT_EXPR, TREE_TYPE (inner_size),
18901 inner_size, outer_size);
18902
18903 volume = fold_convert (diff_type, volume);
18904 if (chunking)
18905 chunk_size = fold_convert (diff_type, chunk_size);
18906 else
18907 {
18908 tree per = fold_build2 (MULT_EXPR, diff_type, volume, step);
18909
18910 chunk_size = build2 (MINUS_EXPR, diff_type, range, dir);
18911 chunk_size = build2 (PLUS_EXPR, diff_type, chunk_size, per);
18912 chunk_size = build2 (TRUNC_DIV_EXPR, diff_type, chunk_size, per);
18913 }
18914
18915 tree span = build2 (MULT_EXPR, diff_type, chunk_size,
18916 fold_convert (diff_type, inner_size));
18917
18918 r = fold_build2 (MULT_EXPR, diff_type, span, step);
18919
18920 tree offset = gimple_call_arg (call, 6);
18921 r = build2 (PLUS_EXPR, diff_type, r,
18922 fold_convert (diff_type, offset));
18923 r = build2 (integer_onep (dir) ? MIN_EXPR : MAX_EXPR,
18924 diff_type, r, range);
18925 }
18926 if (diff_type != type)
18927 r = fold_convert (type, r);
18928 break;
18929 }
18930
18931 gimplify_assign (lhs, r, &seq);
18932
18933 pop_gimplify_context (NULL);
18934
18935 gsi_replace_with_seq (&gsi, seq, true);
18936}
18937
0bb0f256 18938/* Validate and update the dimensions for offloaded FN. ATTRS is the
18939 raw attribute. DIMS is an array of dimensions, which is returned.
18940 Returns the function level dimensionality -- the level at which an
18941 offload routine wishes to partition a loop. */
18942
18943static int
18944oacc_validate_dims (tree fn, tree attrs, int *dims)
18945{
18946 tree purpose[GOMP_DIM_MAX];
18947 unsigned ix;
18948 tree pos = TREE_VALUE (attrs);
18949 int fn_level = -1;
18950
18951 /* Make sure the attribute creator attached the dimension
18952 information. */
18953 gcc_assert (pos);
18954
18955 for (ix = 0; ix != GOMP_DIM_MAX; ix++)
18956 {
18957 purpose[ix] = TREE_PURPOSE (pos);
18958
18959 if (purpose[ix])
18960 {
18961 if (integer_zerop (purpose[ix]))
18962 fn_level = ix + 1;
18963 else if (fn_level < 0)
18964 fn_level = ix;
18965 }
18966
18967 tree val = TREE_VALUE (pos);
18968 dims[ix] = val ? TREE_INT_CST_LOW (val) : -1;
18969 pos = TREE_CHAIN (pos);
18970 }
18971
18972 bool changed = targetm.goacc.validate_dims (fn, dims, fn_level);
18973
18974 /* Default anything left to 1. */
18975 for (ix = 0; ix != GOMP_DIM_MAX; ix++)
18976 if (dims[ix] < 0)
18977 {
18978 dims[ix] = 1;
18979 changed = true;
18980 }
18981
18982 if (changed)
18983 {
18984 /* Replace the attribute with new values. */
18985 pos = NULL_TREE;
18986 for (ix = GOMP_DIM_MAX; ix--;)
18987 pos = tree_cons (purpose[ix],
18988 build_int_cst (integer_type_node, dims[ix]),
18989 pos);
18990 replace_oacc_fn_attrib (fn, pos);
18991 }
18992
18993 return fn_level;
18994}
18995
cbba99a0 18996/* Create an empty OpenACC loop structure at LOC. */
18997
18998static oacc_loop *
18999new_oacc_loop_raw (oacc_loop *parent, location_t loc)
19000{
19001 oacc_loop *loop = XCNEW (oacc_loop);
19002
19003 loop->parent = parent;
19004 loop->child = loop->sibling = NULL;
19005
19006 if (parent)
19007 {
19008 loop->sibling = parent->child;
19009 parent->child = loop;
19010 }
19011
19012 loop->loc = loc;
19013 loop->marker = NULL;
19014 memset (loop->heads, 0, sizeof (loop->heads));
19015 memset (loop->tails, 0, sizeof (loop->tails));
19016 loop->routine = NULL_TREE;
19017
19018 loop->mask = loop->flags = 0;
19019 loop->chunk_size = 0;
19020 loop->head_end = NULL;
19021
19022 return loop;
19023}
19024
19025/* Create an outermost, dummy OpenACC loop for offloaded function
19026 DECL. */
19027
19028static oacc_loop *
19029new_oacc_loop_outer (tree decl)
19030{
19031 return new_oacc_loop_raw (NULL, DECL_SOURCE_LOCATION (decl));
19032}
19033
19034/* Start a new OpenACC loop structure beginning at head marker HEAD.
19035 Link into PARENT loop. Return the new loop. */
19036
19037static oacc_loop *
19038new_oacc_loop (oacc_loop *parent, gcall *marker)
19039{
19040 oacc_loop *loop = new_oacc_loop_raw (parent, gimple_location (marker));
19041
19042 loop->marker = marker;
19043
19044 /* TODO: This is where device_type flattening would occur for the loop
19045 flags. */
19046
19047 loop->flags = TREE_INT_CST_LOW (gimple_call_arg (marker, 3));
19048
19049 tree chunk_size = integer_zero_node;
19050 if (loop->flags & OLF_GANG_STATIC)
19051 chunk_size = gimple_call_arg (marker, 4);
19052 loop->chunk_size = chunk_size;
19053
19054 return loop;
19055}
19056
19057/* Create a dummy loop encompassing a call to a openACC routine.
19058 Extract the routine's partitioning requirements. */
19059
19060static void
19061new_oacc_loop_routine (oacc_loop *parent, gcall *call, tree decl, tree attrs)
19062{
19063 oacc_loop *loop = new_oacc_loop_raw (parent, gimple_location (call));
19064 int dims[GOMP_DIM_MAX];
19065 int level = oacc_validate_dims (decl, attrs, dims);
19066
19067 gcc_assert (level >= 0);
19068
19069 loop->marker = call;
19070 loop->routine = decl;
19071 loop->mask = ((GOMP_DIM_MASK (GOMP_DIM_MAX) - 1)
19072 ^ (GOMP_DIM_MASK (level) - 1));
19073}
19074
19075/* Finish off the current OpenACC loop ending at tail marker TAIL.
19076 Return the parent loop. */
19077
19078static oacc_loop *
19079finish_oacc_loop (oacc_loop *loop)
19080{
19081 return loop->parent;
19082}
19083
19084/* Free all OpenACC loop structures within LOOP (inclusive). */
19085
19086static void
19087free_oacc_loop (oacc_loop *loop)
19088{
19089 if (loop->sibling)
19090 free_oacc_loop (loop->sibling);
19091 if (loop->child)
19092 free_oacc_loop (loop->child);
19093
19094 free (loop);
19095}
19096
19097/* Dump out the OpenACC loop head or tail beginning at FROM. */
19098
19099static void
19100dump_oacc_loop_part (FILE *file, gcall *from, int depth,
19101 const char *title, int level)
19102{
19103 enum ifn_unique_kind kind
19104 = (enum ifn_unique_kind) TREE_INT_CST_LOW (gimple_call_arg (from, 0));
19105
19106 fprintf (file, "%*s%s-%d:\n", depth * 2, "", title, level);
19107 for (gimple_stmt_iterator gsi = gsi_for_stmt (from);;)
19108 {
19109 gimple *stmt = gsi_stmt (gsi);
19110
19111 if (is_gimple_call (stmt)
19112 && gimple_call_internal_p (stmt)
19113 && gimple_call_internal_fn (stmt) == IFN_UNIQUE)
19114 {
19115 enum ifn_unique_kind k
19116 = ((enum ifn_unique_kind) TREE_INT_CST_LOW
19117 (gimple_call_arg (stmt, 0)));
19118
19119 if (k == kind && stmt != from)
19120 break;
19121 }
19122 print_gimple_stmt (file, stmt, depth * 2 + 2, 0);
19123
19124 gsi_next (&gsi);
19125 while (gsi_end_p (gsi))
19126 gsi = gsi_start_bb (single_succ (gsi_bb (gsi)));
19127 }
19128}
19129
19130/* Dump OpenACC loops LOOP, its siblings and its children. */
19131
19132static void
19133dump_oacc_loop (FILE *file, oacc_loop *loop, int depth)
19134{
19135 int ix;
19136
19137 fprintf (file, "%*sLoop %x(%x) %s:%u\n", depth * 2, "",
19138 loop->flags, loop->mask,
19139 LOCATION_FILE (loop->loc), LOCATION_LINE (loop->loc));
19140
19141 if (loop->marker)
19142 print_gimple_stmt (file, loop->marker, depth * 2, 0);
19143
19144 if (loop->routine)
19145 fprintf (file, "%*sRoutine %s:%u:%s\n",
19146 depth * 2, "", DECL_SOURCE_FILE (loop->routine),
19147 DECL_SOURCE_LINE (loop->routine),
19148 IDENTIFIER_POINTER (DECL_NAME (loop->routine)));
19149
19150 for (ix = GOMP_DIM_GANG; ix != GOMP_DIM_MAX; ix++)
19151 if (loop->heads[ix])
19152 dump_oacc_loop_part (file, loop->heads[ix], depth, "Head", ix);
19153 for (ix = GOMP_DIM_MAX; ix--;)
19154 if (loop->tails[ix])
19155 dump_oacc_loop_part (file, loop->tails[ix], depth, "Tail", ix);
19156
19157 if (loop->child)
19158 dump_oacc_loop (file, loop->child, depth + 1);
19159 if (loop->sibling)
19160 dump_oacc_loop (file, loop->sibling, depth);
19161}
19162
19163void debug_oacc_loop (oacc_loop *);
19164
19165/* Dump loops to stderr. */
19166
19167DEBUG_FUNCTION void
19168debug_oacc_loop (oacc_loop *loop)
19169{
19170 dump_oacc_loop (stderr, loop, 0);
19171}
19172
19173/* DFS walk of basic blocks BB onwards, creating OpenACC loop
19174 structures as we go. By construction these loops are properly
19175 nested. */
19176
19177static void
19178oacc_loop_discover_walk (oacc_loop *loop, basic_block bb)
19179{
19180 int marker = 0;
19181 int remaining = 0;
19182
19183 if (bb->flags & BB_VISITED)
19184 return;
19185
19186 follow:
19187 bb->flags |= BB_VISITED;
19188
19189 /* Scan for loop markers. */
19190 for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);
19191 gsi_next (&gsi))
19192 {
19193 gimple *stmt = gsi_stmt (gsi);
19194
19195 if (!is_gimple_call (stmt))
19196 continue;
19197
19198 gcall *call = as_a <gcall *> (stmt);
19199
19200 /* If this is a routine, make a dummy loop for it. */
19201 if (tree decl = gimple_call_fndecl (call))
19202 if (tree attrs = get_oacc_fn_attrib (decl))
19203 {
19204 gcc_assert (!marker);
19205 new_oacc_loop_routine (loop, call, decl, attrs);
19206 }
19207
19208 if (!gimple_call_internal_p (call))
19209 continue;
19210
19211 if (gimple_call_internal_fn (call) != IFN_UNIQUE)
19212 continue;
19213
19214 enum ifn_unique_kind kind
19215 = (enum ifn_unique_kind) TREE_INT_CST_LOW (gimple_call_arg (call, 0));
19216 if (kind == IFN_UNIQUE_OACC_HEAD_MARK
19217 || kind == IFN_UNIQUE_OACC_TAIL_MARK)
19218 {
19219 if (gimple_call_num_args (call) == 2)
19220 {
19221 gcc_assert (marker && !remaining);
19222 marker = 0;
19223 if (kind == IFN_UNIQUE_OACC_TAIL_MARK)
19224 loop = finish_oacc_loop (loop);
19225 else
19226 loop->head_end = call;
19227 }
19228 else
19229 {
19230 int count = TREE_INT_CST_LOW (gimple_call_arg (call, 2));
19231
19232 if (!marker)
19233 {
19234 if (kind == IFN_UNIQUE_OACC_HEAD_MARK)
19235 loop = new_oacc_loop (loop, call);
19236 remaining = count;
19237 }
19238 gcc_assert (count == remaining);
19239 if (remaining)
19240 {
19241 remaining--;
19242 if (kind == IFN_UNIQUE_OACC_HEAD_MARK)
19243 loop->heads[marker] = call;
19244 else
19245 loop->tails[remaining] = call;
19246 }
19247 marker++;
19248 }
19249 }
19250 }
19251 if (remaining || marker)
19252 {
19253 bb = single_succ (bb);
19254 gcc_assert (single_pred_p (bb) && !(bb->flags & BB_VISITED));
19255 goto follow;
19256 }
19257
19258 /* Walk successor blocks. */
19259 edge e;
19260 edge_iterator ei;
19261
19262 FOR_EACH_EDGE (e, ei, bb->succs)
19263 oacc_loop_discover_walk (loop, e->dest);
19264}
19265
19266/* LOOP is the first sibling. Reverse the order in place and return
19267 the new first sibling. Recurse to child loops. */
19268
19269static oacc_loop *
19270oacc_loop_sibling_nreverse (oacc_loop *loop)
19271{
19272 oacc_loop *last = NULL;
19273 do
19274 {
19275 if (loop->child)
19276 loop->child = oacc_loop_sibling_nreverse (loop->child);
19277
19278 oacc_loop *next = loop->sibling;
19279 loop->sibling = last;
19280 last = loop;
19281 loop = next;
19282 }
19283 while (loop);
19284
19285 return last;
19286}
19287
19288/* Discover the OpenACC loops marked up by HEAD and TAIL markers for
19289 the current function. */
19290
19291static oacc_loop *
19292oacc_loop_discovery ()
19293{
19294 basic_block bb;
19295
19296 oacc_loop *top = new_oacc_loop_outer (current_function_decl);
19297 oacc_loop_discover_walk (top, ENTRY_BLOCK_PTR_FOR_FN (cfun));
19298
19299 /* The siblings were constructed in reverse order, reverse them so
19300 that diagnostics come out in an unsurprising order. */
19301 top = oacc_loop_sibling_nreverse (top);
19302
19303 /* Reset the visited flags. */
19304 FOR_ALL_BB_FN (bb, cfun)
19305 bb->flags &= ~BB_VISITED;
19306
19307 return top;
19308}
19309
19310/* Transform the abstract internal function markers starting at FROM
19311 to be for partitioning level LEVEL. Stop when we meet another HEAD
19312 or TAIL marker. */
19313
19314static void
19315oacc_loop_xform_head_tail (gcall *from, int level)
19316{
19317 enum ifn_unique_kind kind
19318 = (enum ifn_unique_kind) TREE_INT_CST_LOW (gimple_call_arg (from, 0));
19319 tree replacement = build_int_cst (unsigned_type_node, level);
19320
19321 for (gimple_stmt_iterator gsi = gsi_for_stmt (from);;)
19322 {
19323 gimple *stmt = gsi_stmt (gsi);
19324
19325 if (is_gimple_call (stmt)
19326 && gimple_call_internal_p (stmt)
19327 && gimple_call_internal_fn (stmt) == IFN_UNIQUE)
19328 {
19329 enum ifn_unique_kind k
19330 = ((enum ifn_unique_kind)
19331 TREE_INT_CST_LOW (gimple_call_arg (stmt, 0)));
19332
19333 if (k == IFN_UNIQUE_OACC_FORK || k == IFN_UNIQUE_OACC_JOIN)
19334 *gimple_call_arg_ptr (stmt, 2) = replacement;
19335 else if (k == kind && stmt != from)
19336 break;
19337 }
641a0fa1 19338 else if (is_gimple_call (stmt)
19339 && gimple_call_internal_p (stmt)
19340 && gimple_call_internal_fn (stmt) == IFN_GOACC_REDUCTION)
19341 *gimple_call_arg_ptr (stmt, 3) = replacement;
19342
cbba99a0 19343 gsi_next (&gsi);
19344 while (gsi_end_p (gsi))
19345 gsi = gsi_start_bb (single_succ (gsi_bb (gsi)));
19346 }
19347}
19348
19349/* Transform the IFN_GOACC_LOOP internal functions by providing the
19350 determined partitioning mask and chunking argument. */
19351
19352static void
19353oacc_loop_xform_loop (gcall *end_marker, tree mask_arg, tree chunk_arg)
19354{
19355 gimple_stmt_iterator gsi = gsi_for_stmt (end_marker);
19356
19357 for (;;)
19358 {
19359 for (; !gsi_end_p (gsi); gsi_next (&gsi))
19360 {
19361 gimple *stmt = gsi_stmt (gsi);
19362
19363 if (!is_gimple_call (stmt))
19364 continue;
19365
19366 gcall *call = as_a <gcall *> (stmt);
19367
19368 if (!gimple_call_internal_p (call))
19369 continue;
19370
19371 if (gimple_call_internal_fn (call) != IFN_GOACC_LOOP)
19372 continue;
19373
19374 *gimple_call_arg_ptr (call, 5) = mask_arg;
19375 *gimple_call_arg_ptr (call, 4) = chunk_arg;
19376 if (TREE_INT_CST_LOW (gimple_call_arg (call, 0))
19377 == IFN_GOACC_LOOP_BOUND)
19378 return;
19379 }
19380
19381 /* If we didn't see LOOP_BOUND, it should be in the single
19382 successor block. */
19383 basic_block bb = single_succ (gsi_bb (gsi));
19384 gsi = gsi_start_bb (bb);
19385 }
19386}
19387
19388/* Process the discovered OpenACC loops, setting the correct
19389 partitioning level etc. */
19390
19391static void
19392oacc_loop_process (oacc_loop *loop)
19393{
19394 if (loop->child)
19395 oacc_loop_process (loop->child);
19396
19397 if (loop->mask && !loop->routine)
19398 {
19399 int ix;
19400 unsigned mask = loop->mask;
19401 unsigned dim = GOMP_DIM_GANG;
19402 tree mask_arg = build_int_cst (unsigned_type_node, mask);
19403 tree chunk_arg = loop->chunk_size;
19404
19405 oacc_loop_xform_loop (loop->head_end, mask_arg, chunk_arg);
19406
19407 for (ix = 0; ix != GOMP_DIM_MAX && loop->heads[ix]; ix++)
19408 {
19409 gcc_assert (mask);
19410
19411 while (!(GOMP_DIM_MASK (dim) & mask))
19412 dim++;
19413
19414 oacc_loop_xform_head_tail (loop->heads[ix], dim);
19415 oacc_loop_xform_head_tail (loop->tails[ix], dim);
19416
19417 mask ^= GOMP_DIM_MASK (dim);
19418 }
19419 }
19420
19421 if (loop->sibling)
19422 oacc_loop_process (loop->sibling);
19423}
19424
19425/* Walk the OpenACC loop heirarchy checking and assigning the
19426 programmer-specified partitionings. OUTER_MASK is the partitioning
f4f5b4b4 19427 this loop is contained within. Return true if we contain an
19428 auto-partitionable loop. */
cbba99a0 19429
f4f5b4b4 19430static bool
cbba99a0 19431oacc_loop_fixed_partitions (oacc_loop *loop, unsigned outer_mask)
19432{
19433 unsigned this_mask = loop->mask;
19434 bool has_auto = false;
19435 bool noisy = true;
19436
19437#ifdef ACCEL_COMPILER
19438 /* When device_type is supported, we want the device compiler to be
19439 noisy, if the loop parameters are device_type-specific. */
19440 noisy = false;
19441#endif
19442
19443 if (!loop->routine)
19444 {
19445 bool auto_par = (loop->flags & OLF_AUTO) != 0;
19446 bool seq_par = (loop->flags & OLF_SEQ) != 0;
19447
19448 this_mask = ((loop->flags >> OLF_DIM_BASE)
19449 & (GOMP_DIM_MASK (GOMP_DIM_MAX) - 1));
19450
19451 if ((this_mask != 0) + auto_par + seq_par > 1)
19452 {
19453 if (noisy)
19454 error_at (loop->loc,
19455 seq_par
19456 ? "%<seq%> overrides other OpenACC loop specifiers"
19457 : "%<auto%> conflicts with other OpenACC loop specifiers");
19458 auto_par = false;
19459 loop->flags &= ~OLF_AUTO;
19460 if (seq_par)
19461 {
19462 loop->flags &=
19463 ~((GOMP_DIM_MASK (GOMP_DIM_MAX) - 1) << OLF_DIM_BASE);
19464 this_mask = 0;
19465 }
19466 }
19467 if (auto_par && (loop->flags & OLF_INDEPENDENT))
19468 has_auto = true;
19469 }
19470
19471 if (this_mask & outer_mask)
19472 {
19473 const oacc_loop *outer;
19474 for (outer = loop->parent; outer; outer = outer->parent)
19475 if (outer->mask & this_mask)
19476 break;
19477
19478 if (noisy)
19479 {
19480 if (outer)
19481 {
19482 error_at (loop->loc,
19483 "%s uses same OpenACC parallelism as containing loop",
19484 loop->routine ? "routine call" : "inner loop");
19485 inform (outer->loc, "containing loop here");
19486 }
19487 else
19488 error_at (loop->loc,
19489 "%s uses OpenACC parallelism disallowed by containing routine",
19490 loop->routine ? "routine call" : "loop");
19491
19492 if (loop->routine)
19493 inform (DECL_SOURCE_LOCATION (loop->routine),
19494 "routine %qD declared here", loop->routine);
19495 }
19496 this_mask &= ~outer_mask;
19497 }
19498 else
19499 {
19500 unsigned outermost = this_mask & -this_mask;
19501
19502 if (outermost && outermost <= outer_mask)
19503 {
19504 if (noisy)
19505 {
19506 error_at (loop->loc,
19507 "incorrectly nested OpenACC loop parallelism");
19508
19509 const oacc_loop *outer;
19510 for (outer = loop->parent;
19511 outer->flags && outer->flags < outermost;
19512 outer = outer->parent)
19513 continue;
19514 inform (outer->loc, "containing loop here");
19515 }
19516
19517 this_mask &= ~outermost;
19518 }
19519 }
19520
19521 loop->mask = this_mask;
19522
19523 if (loop->child
19524 && oacc_loop_fixed_partitions (loop->child, outer_mask | this_mask))
19525 has_auto = true;
19526
19527 if (loop->sibling
19528 && oacc_loop_fixed_partitions (loop->sibling, outer_mask))
19529 has_auto = true;
19530
19531 return has_auto;
19532}
19533
f4f5b4b4 19534/* Walk the OpenACC loop heirarchy to assign auto-partitioned loops.
19535 OUTER_MASK is the partitioning this loop is contained within.
19536 Return the cumulative partitioning used by this loop, siblings and
19537 children. */
19538
19539static unsigned
19540oacc_loop_auto_partitions (oacc_loop *loop, unsigned outer_mask)
19541{
19542 unsigned inner_mask = 0;
19543 bool noisy = true;
19544
19545#ifdef ACCEL_COMPILER
19546 /* When device_type is supported, we want the device compiler to be
19547 noisy, if the loop parameters are device_type-specific. */
19548 noisy = false;
19549#endif
19550
19551 if (loop->child)
19552 inner_mask |= oacc_loop_auto_partitions (loop->child,
19553 outer_mask | loop->mask);
19554
19555 if ((loop->flags & OLF_AUTO) && (loop->flags & OLF_INDEPENDENT))
19556 {
19557 unsigned this_mask = 0;
19558
19559 /* Determine the outermost partitioning used within this loop. */
19560 this_mask = inner_mask | GOMP_DIM_MASK (GOMP_DIM_MAX);
19561 this_mask = (this_mask & -this_mask);
19562
19563 /* Pick the partitioning just inside that one. */
19564 this_mask >>= 1;
19565
19566 /* And avoid picking one use by an outer loop. */
19567 this_mask &= ~outer_mask;
19568
19569 if (!this_mask && noisy)
19570 warning_at (loop->loc, 0,
19571 "insufficient partitioning available to parallelize loop");
19572
19573 loop->mask = this_mask;
19574 }
19575 inner_mask |= loop->mask;
19576
19577 if (loop->sibling)
19578 inner_mask |= oacc_loop_auto_partitions (loop->sibling, outer_mask);
19579
19580 return inner_mask;
19581}
19582
cbba99a0 19583/* Walk the OpenACC loop heirarchy to check and assign partitioning
19584 axes. */
19585
19586static void
f4f5b4b4 19587oacc_loop_partition (oacc_loop *loop, unsigned outer_mask)
cbba99a0 19588{
f4f5b4b4 19589 if (oacc_loop_fixed_partitions (loop, outer_mask))
19590 oacc_loop_auto_partitions (loop, outer_mask);
cbba99a0 19591}
19592
c25f1934 19593/* Default fork/join early expander. Delete the function calls if
19594 there is no RTL expander. */
19595
19596bool
19597default_goacc_fork_join (gcall *ARG_UNUSED (call),
19598 const int *ARG_UNUSED (dims), bool is_fork)
19599{
19600 if (is_fork)
19601 return targetm.have_oacc_fork ();
19602 else
19603 return targetm.have_oacc_join ();
19604}
19605
641a0fa1 19606/* Default goacc.reduction early expander.
19607
19608 LHS-opt = IFN_REDUCTION (KIND, RES_PTR, VAR, LEVEL, OP, OFFSET)
19609 If RES_PTR is not integer-zerop:
19610 SETUP - emit 'LHS = *RES_PTR', LHS = NULL
19611 TEARDOWN - emit '*RES_PTR = VAR'
19612 If LHS is not NULL
19613 emit 'LHS = VAR' */
19614
19615void
19616default_goacc_reduction (gcall *call)
19617{
19618 unsigned code = (unsigned)TREE_INT_CST_LOW (gimple_call_arg (call, 0));
19619 gimple_stmt_iterator gsi = gsi_for_stmt (call);
19620 tree lhs = gimple_call_lhs (call);
19621 tree var = gimple_call_arg (call, 2);
19622 gimple_seq seq = NULL;
19623
19624 if (code == IFN_GOACC_REDUCTION_SETUP
19625 || code == IFN_GOACC_REDUCTION_TEARDOWN)
19626 {
19627 /* Setup and Teardown need to copy from/to the receiver object,
19628 if there is one. */
19629 tree ref_to_res = gimple_call_arg (call, 1);
19630
19631 if (!integer_zerop (ref_to_res))
19632 {
19633 tree dst = build_simple_mem_ref (ref_to_res);
19634 tree src = var;
19635
19636 if (code == IFN_GOACC_REDUCTION_SETUP)
19637 {
19638 src = dst;
19639 dst = lhs;
19640 lhs = NULL;
19641 }
19642 gimple_seq_add_stmt (&seq, gimple_build_assign (dst, src));
19643 }
19644 }
19645
19646 /* Copy VAR to LHS, if there is an LHS. */
19647 if (lhs)
19648 gimple_seq_add_stmt (&seq, gimple_build_assign (lhs, var));
19649
19650 gsi_replace_with_seq (&gsi, seq, true);
19651}
19652
0bb0f256 19653/* Main entry point for oacc transformations which run on the device
19654 compiler after LTO, so we know what the target device is at this
19655 point (including the host fallback). */
19656
19657static unsigned int
19658execute_oacc_device_lower ()
19659{
19660 tree attrs = get_oacc_fn_attrib (current_function_decl);
19661 int dims[GOMP_DIM_MAX];
19662
19663 if (!attrs)
19664 /* Not an offloaded function. */
19665 return 0;
19666
cbba99a0 19667 int fn_level = oacc_validate_dims (current_function_decl, attrs, dims);
19668
19669 /* Discover, partition and process the loops. */
19670 oacc_loop *loops = oacc_loop_discovery ();
f4f5b4b4 19671 unsigned outer_mask = fn_level >= 0 ? GOMP_DIM_MASK (fn_level) - 1 : 0;
19672 oacc_loop_partition (loops, outer_mask);
cbba99a0 19673 oacc_loop_process (loops);
19674 if (dump_file)
19675 {
19676 fprintf (dump_file, "OpenACC loops\n");
19677 dump_oacc_loop (dump_file, loops, 0);
19678 fprintf (dump_file, "\n");
19679 }
19680
641a0fa1 19681 /* Offloaded targets may introduce new basic blocks, which require
19682 dominance information to update SSA. */
19683 calculate_dominance_info (CDI_DOMINATORS);
19684
cbba99a0 19685 /* Now lower internal loop functions to target-specific code
19686 sequences. */
19687 basic_block bb;
19688 FOR_ALL_BB_FN (bb, cfun)
19689 for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);)
19690 {
19691 gimple *stmt = gsi_stmt (gsi);
19692 if (!is_gimple_call (stmt))
19693 {
19694 gsi_next (&gsi);
19695 continue;
19696 }
19697
19698 gcall *call = as_a <gcall *> (stmt);
19699 if (!gimple_call_internal_p (call))
19700 {
19701 gsi_next (&gsi);
19702 continue;
19703 }
19704
19705 /* Rewind to allow rescan. */
19706 gsi_prev (&gsi);
19707 bool rescan = false, remove = false;
19708 enum internal_fn ifn_code = gimple_call_internal_fn (call);
19709
19710 switch (ifn_code)
19711 {
19712 default: break;
19713
19714 case IFN_GOACC_LOOP:
19715 oacc_xform_loop (call);
19716 rescan = true;
19717 break;
19718
641a0fa1 19719 case IFN_GOACC_REDUCTION:
19720 /* Mark the function for SSA renaming. */
19721 mark_virtual_operands_for_renaming (cfun);
19722
19723 /* If the level is -1, this ended up being an unused
19724 axis. Handle as a default. */
19725 if (integer_minus_onep (gimple_call_arg (call, 3)))
19726 default_goacc_reduction (call);
19727 else
19728 targetm.goacc.reduction (call);
19729 rescan = true;
19730 break;
19731
cbba99a0 19732 case IFN_UNIQUE:
19733 {
19734 enum ifn_unique_kind kind
19735 = ((enum ifn_unique_kind)
19736 TREE_INT_CST_LOW (gimple_call_arg (call, 0)));
19737
19738 switch (kind)
19739 {
19740 default:
19741 gcc_unreachable ();
19742
19743 case IFN_UNIQUE_OACC_FORK:
19744 case IFN_UNIQUE_OACC_JOIN:
19745 if (integer_minus_onep (gimple_call_arg (call, 2)))
19746 remove = true;
19747 else if (!targetm.goacc.fork_join
19748 (call, dims, kind == IFN_UNIQUE_OACC_FORK))
19749 remove = true;
19750 break;
19751
19752 case IFN_UNIQUE_OACC_HEAD_MARK:
19753 case IFN_UNIQUE_OACC_TAIL_MARK:
19754 remove = true;
19755 break;
19756 }
19757 break;
19758 }
19759 }
19760
19761 if (gsi_end_p (gsi))
19762 /* We rewound past the beginning of the BB. */
19763 gsi = gsi_start_bb (bb);
19764 else
19765 /* Undo the rewind. */
19766 gsi_next (&gsi);
19767
19768 if (remove)
19769 {
19770 if (gimple_vdef (call))
19771 replace_uses_by (gimple_vdef (call), gimple_vuse (call));
19772 if (gimple_call_lhs (call))
19773 {
19774 /* Propagate the data dependency var. */
19775 gimple *ass = gimple_build_assign (gimple_call_lhs (call),
19776 gimple_call_arg (call, 1));
19777 gsi_replace (&gsi, ass, false);
19778 }
19779 else
19780 gsi_remove (&gsi, true);
19781 }
19782 else if (!rescan)
19783 /* If not rescanning, advance over the call. */
19784 gsi_next (&gsi);
19785 }
19786
19787 free_oacc_loop (loops);
19788
0bb0f256 19789 return 0;
19790}
19791
19792/* Default launch dimension validator. Force everything to 1. A
19793 backend that wants to provide larger dimensions must override this
19794 hook. */
19795
19796bool
19797default_goacc_validate_dims (tree ARG_UNUSED (decl), int *dims,
19798 int ARG_UNUSED (fn_level))
19799{
19800 bool changed = false;
19801
19802 for (unsigned ix = 0; ix != GOMP_DIM_MAX; ix++)
19803 {
19804 if (dims[ix] != 1)
19805 {
19806 dims[ix] = 1;
19807 changed = true;
19808 }
19809 }
19810
19811 return changed;
19812}
19813
e1037942 19814/* Default dimension bound is unknown on accelerator and 1 on host. */
19815
19816int
19817default_goacc_dim_limit (int ARG_UNUSED (axis))
19818{
19819#ifdef ACCEL_COMPILER
19820 return 0;
19821#else
19822 return 1;
19823#endif
19824}
19825
0bb0f256 19826namespace {
19827
19828const pass_data pass_data_oacc_device_lower =
19829{
19830 GIMPLE_PASS, /* type */
19831 "oaccdevlow", /* name */
19832 OPTGROUP_NONE, /* optinfo_flags */
19833 TV_NONE, /* tv_id */
19834 PROP_cfg, /* properties_required */
19835 0 /* Possibly PROP_gimple_eomp. */, /* properties_provided */
19836 0, /* properties_destroyed */
19837 0, /* todo_flags_start */
19838 TODO_update_ssa | TODO_cleanup_cfg, /* todo_flags_finish */
19839};
19840
19841class pass_oacc_device_lower : public gimple_opt_pass
19842{
19843public:
19844 pass_oacc_device_lower (gcc::context *ctxt)
19845 : gimple_opt_pass (pass_data_oacc_device_lower, ctxt)
19846 {}
19847
19848 /* opt_pass methods: */
19849 virtual unsigned int execute (function *)
19850 {
173dfdf5 19851 bool gate = flag_openacc != 0;
0bb0f256 19852
19853 if (!gate)
19854 return 0;
19855
19856 return execute_oacc_device_lower ();
19857 }
19858
f69b8a4c 19859}; // class pass_oacc_device_lower
0bb0f256 19860
19861} // anon namespace
19862
19863gimple_opt_pass *
19864make_pass_oacc_device_lower (gcc::context *ctxt)
19865{
19866 return new pass_oacc_device_lower (ctxt);
19867}
19868
c0998828 19869/* "omp declare target link" handling pass. */
19870
19871namespace {
19872
19873const pass_data pass_data_omp_target_link =
19874{
19875 GIMPLE_PASS, /* type */
19876 "omptargetlink", /* name */
19877 OPTGROUP_NONE, /* optinfo_flags */
19878 TV_NONE, /* tv_id */
19879 PROP_ssa, /* properties_required */
19880 0, /* properties_provided */
19881 0, /* properties_destroyed */
19882 0, /* todo_flags_start */
19883 TODO_update_ssa, /* todo_flags_finish */
19884};
19885
19886class pass_omp_target_link : public gimple_opt_pass
19887{
19888public:
19889 pass_omp_target_link (gcc::context *ctxt)
19890 : gimple_opt_pass (pass_data_omp_target_link, ctxt)
19891 {}
19892
19893 /* opt_pass methods: */
19894 virtual bool gate (function *fun)
19895 {
19896#ifdef ACCEL_COMPILER
19897 tree attrs = DECL_ATTRIBUTES (fun->decl);
19898 return lookup_attribute ("omp declare target", attrs)
19899 || lookup_attribute ("omp target entrypoint", attrs);
19900#else
19901 (void) fun;
19902 return false;
19903#endif
19904 }
19905
19906 virtual unsigned execute (function *);
19907};
19908
19909/* Callback for walk_gimple_stmt used to scan for link var operands. */
19910
19911static tree
19912find_link_var_op (tree *tp, int *walk_subtrees, void *)
19913{
19914 tree t = *tp;
19915
19916 if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t)
19917 && lookup_attribute ("omp declare target link", DECL_ATTRIBUTES (t)))
19918 {
19919 *walk_subtrees = 0;
19920 return t;
19921 }
19922
19923 return NULL_TREE;
19924}
19925
19926unsigned
19927pass_omp_target_link::execute (function *fun)
19928{
19929 basic_block bb;
19930 FOR_EACH_BB_FN (bb, fun)
19931 {
19932 gimple_stmt_iterator gsi;
19933 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
19934 if (walk_gimple_stmt (&gsi, NULL, find_link_var_op, NULL))
19935 gimple_regimplify_operands (gsi_stmt (gsi), &gsi);
19936 }
19937
19938 return 0;
19939}
19940
19941} // anon namespace
19942
19943gimple_opt_pass *
19944make_pass_omp_target_link (gcc::context *ctxt)
19945{
19946 return new pass_omp_target_link (ctxt);
19947}
19948
1e8e9920 19949#include "gt-omp-low.h"