]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/omp-low.c
Add pass_oacc_kernels
[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
1e8e9920 1369/* Add a new field for VAR inside the structure CTX->SENDER_DECL. */
1370
1371static void
fd6481cf 1372install_var_field (tree var, bool by_ref, int mask, omp_context *ctx)
1e8e9920 1373{
fd6481cf 1374 tree field, type, sfield = NULL_TREE;
43895be5 1375 splay_tree_key key = (splay_tree_key) var;
1e8e9920 1376
43895be5 1377 if ((mask & 8) != 0)
1378 {
1379 key = (splay_tree_key) &DECL_UID (var);
1380 gcc_checking_assert (key != (splay_tree_key) var);
1381 }
fd6481cf 1382 gcc_assert ((mask & 1) == 0
43895be5 1383 || !splay_tree_lookup (ctx->field_map, key));
fd6481cf 1384 gcc_assert ((mask & 2) == 0 || !ctx->sfield_map
43895be5 1385 || !splay_tree_lookup (ctx->sfield_map, key));
ca4c3545 1386 gcc_assert ((mask & 3) == 3
1387 || !is_gimple_omp_oacc (ctx->stmt));
1e8e9920 1388
1389 type = TREE_TYPE (var);
bc7bff74 1390 if (mask & 4)
1391 {
1392 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
1393 type = build_pointer_type (build_pointer_type (type));
1394 }
1395 else if (by_ref)
1e8e9920 1396 type = build_pointer_type (type);
fd6481cf 1397 else if ((mask & 3) == 1 && is_reference (var))
1398 type = TREE_TYPE (type);
1e8e9920 1399
e60a6f7b 1400 field = build_decl (DECL_SOURCE_LOCATION (var),
1401 FIELD_DECL, DECL_NAME (var), type);
1e8e9920 1402
1403 /* Remember what variable this field was created for. This does have a
1404 side effect of making dwarf2out ignore this member, so for helpful
1405 debugging we clear it later in delete_omp_context. */
1406 DECL_ABSTRACT_ORIGIN (field) = var;
fd6481cf 1407 if (type == TREE_TYPE (var))
1408 {
1409 DECL_ALIGN (field) = DECL_ALIGN (var);
1410 DECL_USER_ALIGN (field) = DECL_USER_ALIGN (var);
1411 TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (var);
1412 }
1413 else
1414 DECL_ALIGN (field) = TYPE_ALIGN (type);
1e8e9920 1415
fd6481cf 1416 if ((mask & 3) == 3)
1417 {
1418 insert_field_into_struct (ctx->record_type, field);
1419 if (ctx->srecord_type)
1420 {
e60a6f7b 1421 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1422 FIELD_DECL, DECL_NAME (var), type);
fd6481cf 1423 DECL_ABSTRACT_ORIGIN (sfield) = var;
1424 DECL_ALIGN (sfield) = DECL_ALIGN (field);
1425 DECL_USER_ALIGN (sfield) = DECL_USER_ALIGN (field);
1426 TREE_THIS_VOLATILE (sfield) = TREE_THIS_VOLATILE (field);
1427 insert_field_into_struct (ctx->srecord_type, sfield);
1428 }
1429 }
1430 else
1431 {
1432 if (ctx->srecord_type == NULL_TREE)
1433 {
1434 tree t;
1435
1436 ctx->srecord_type = lang_hooks.types.make_type (RECORD_TYPE);
1437 ctx->sfield_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1438 for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
1439 {
43895be5 1440 sfield = build_decl (DECL_SOURCE_LOCATION (t),
e60a6f7b 1441 FIELD_DECL, DECL_NAME (t), TREE_TYPE (t));
fd6481cf 1442 DECL_ABSTRACT_ORIGIN (sfield) = DECL_ABSTRACT_ORIGIN (t);
1443 insert_field_into_struct (ctx->srecord_type, sfield);
1444 splay_tree_insert (ctx->sfield_map,
1445 (splay_tree_key) DECL_ABSTRACT_ORIGIN (t),
1446 (splay_tree_value) sfield);
1447 }
1448 }
1449 sfield = field;
1450 insert_field_into_struct ((mask & 1) ? ctx->record_type
1451 : ctx->srecord_type, field);
1452 }
1e8e9920 1453
fd6481cf 1454 if (mask & 1)
43895be5 1455 splay_tree_insert (ctx->field_map, key, (splay_tree_value) field);
fd6481cf 1456 if ((mask & 2) && ctx->sfield_map)
43895be5 1457 splay_tree_insert (ctx->sfield_map, key, (splay_tree_value) sfield);
1e8e9920 1458}
1459
1460static tree
1461install_var_local (tree var, omp_context *ctx)
1462{
1463 tree new_var = omp_copy_decl_1 (var, ctx);
1464 insert_decl_map (&ctx->cb, var, new_var);
1465 return new_var;
1466}
1467
1468/* Adjust the replacement for DECL in CTX for the new context. This means
1469 copying the DECL_VALUE_EXPR, and fixing up the type. */
1470
1471static void
1472fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug)
1473{
1474 tree new_decl, size;
1475
1476 new_decl = lookup_decl (decl, ctx);
1477
1478 TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb);
1479
1480 if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug)
1481 && DECL_HAS_VALUE_EXPR_P (decl))
1482 {
1483 tree ve = DECL_VALUE_EXPR (decl);
75a70cf9 1484 walk_tree (&ve, copy_tree_body_r, &ctx->cb, NULL);
1e8e9920 1485 SET_DECL_VALUE_EXPR (new_decl, ve);
1486 DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
1487 }
1488
1489 if (!TREE_CONSTANT (DECL_SIZE (new_decl)))
1490 {
1491 size = remap_decl (DECL_SIZE (decl), &ctx->cb);
1492 if (size == error_mark_node)
1493 size = TYPE_SIZE (TREE_TYPE (new_decl));
1494 DECL_SIZE (new_decl) = size;
1495
1496 size = remap_decl (DECL_SIZE_UNIT (decl), &ctx->cb);
1497 if (size == error_mark_node)
1498 size = TYPE_SIZE_UNIT (TREE_TYPE (new_decl));
1499 DECL_SIZE_UNIT (new_decl) = size;
1500 }
1501}
1502
1503/* The callback for remap_decl. Search all containing contexts for a
1504 mapping of the variable; this avoids having to duplicate the splay
1505 tree ahead of time. We know a mapping doesn't already exist in the
1506 given context. Create new mappings to implement default semantics. */
1507
1508static tree
1509omp_copy_decl (tree var, copy_body_data *cb)
1510{
1511 omp_context *ctx = (omp_context *) cb;
1512 tree new_var;
1513
1e8e9920 1514 if (TREE_CODE (var) == LABEL_DECL)
1515 {
e60a6f7b 1516 new_var = create_artificial_label (DECL_SOURCE_LOCATION (var));
773c5ba7 1517 DECL_CONTEXT (new_var) = current_function_decl;
1e8e9920 1518 insert_decl_map (&ctx->cb, var, new_var);
1519 return new_var;
1520 }
1521
fd6481cf 1522 while (!is_taskreg_ctx (ctx))
1e8e9920 1523 {
1524 ctx = ctx->outer;
1525 if (ctx == NULL)
1526 return var;
1527 new_var = maybe_lookup_decl (var, ctx);
1528 if (new_var)
1529 return new_var;
1530 }
1531
f49d7bb5 1532 if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn)
1533 return var;
1534
1e8e9920 1535 return error_mark_node;
1536}
1537
773c5ba7 1538
773c5ba7 1539/* Debugging dumps for parallel regions. */
1540void dump_omp_region (FILE *, struct omp_region *, int);
1541void debug_omp_region (struct omp_region *);
1542void debug_all_omp_regions (void);
1543
1544/* Dump the parallel region tree rooted at REGION. */
1545
1546void
1547dump_omp_region (FILE *file, struct omp_region *region, int indent)
1548{
61e47ac8 1549 fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index,
75a70cf9 1550 gimple_code_name[region->type]);
773c5ba7 1551
1552 if (region->inner)
1553 dump_omp_region (file, region->inner, indent + 4);
1554
61e47ac8 1555 if (region->cont)
1556 {
75a70cf9 1557 fprintf (file, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent, "",
61e47ac8 1558 region->cont->index);
1559 }
48e1416a 1560
773c5ba7 1561 if (region->exit)
75a70cf9 1562 fprintf (file, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent, "",
61e47ac8 1563 region->exit->index);
773c5ba7 1564 else
61e47ac8 1565 fprintf (file, "%*s[no exit marker]\n", indent, "");
773c5ba7 1566
1567 if (region->next)
61e47ac8 1568 dump_omp_region (file, region->next, indent);
773c5ba7 1569}
1570
4b987fac 1571DEBUG_FUNCTION void
773c5ba7 1572debug_omp_region (struct omp_region *region)
1573{
1574 dump_omp_region (stderr, region, 0);
1575}
1576
4b987fac 1577DEBUG_FUNCTION void
773c5ba7 1578debug_all_omp_regions (void)
1579{
1580 dump_omp_region (stderr, root_omp_region, 0);
1581}
1582
1583
1584/* Create a new parallel region starting at STMT inside region PARENT. */
1585
7740abd8 1586static struct omp_region *
75a70cf9 1587new_omp_region (basic_block bb, enum gimple_code type,
1588 struct omp_region *parent)
773c5ba7 1589{
4077bf7a 1590 struct omp_region *region = XCNEW (struct omp_region);
773c5ba7 1591
1592 region->outer = parent;
61e47ac8 1593 region->entry = bb;
1594 region->type = type;
773c5ba7 1595
1596 if (parent)
1597 {
1598 /* This is a nested region. Add it to the list of inner
1599 regions in PARENT. */
1600 region->next = parent->inner;
1601 parent->inner = region;
1602 }
61e47ac8 1603 else
773c5ba7 1604 {
1605 /* This is a toplevel region. Add it to the list of toplevel
1606 regions in ROOT_OMP_REGION. */
1607 region->next = root_omp_region;
1608 root_omp_region = region;
1609 }
61e47ac8 1610
1611 return region;
1612}
1613
1614/* Release the memory associated with the region tree rooted at REGION. */
1615
1616static void
1617free_omp_region_1 (struct omp_region *region)
1618{
1619 struct omp_region *i, *n;
1620
1621 for (i = region->inner; i ; i = n)
773c5ba7 1622 {
61e47ac8 1623 n = i->next;
1624 free_omp_region_1 (i);
773c5ba7 1625 }
1626
61e47ac8 1627 free (region);
1628}
773c5ba7 1629
61e47ac8 1630/* Release the memory for the entire omp region tree. */
1631
1632void
1633free_omp_regions (void)
1634{
1635 struct omp_region *r, *n;
1636 for (r = root_omp_region; r ; r = n)
1637 {
1638 n = r->next;
1639 free_omp_region_1 (r);
1640 }
1641 root_omp_region = NULL;
773c5ba7 1642}
1643
1644
1e8e9920 1645/* Create a new context, with OUTER_CTX being the surrounding context. */
1646
1647static omp_context *
42acab1c 1648new_omp_context (gimple *stmt, omp_context *outer_ctx)
1e8e9920 1649{
1650 omp_context *ctx = XCNEW (omp_context);
1651
1652 splay_tree_insert (all_contexts, (splay_tree_key) stmt,
1653 (splay_tree_value) ctx);
1654 ctx->stmt = stmt;
1655
1656 if (outer_ctx)
1657 {
1658 ctx->outer = outer_ctx;
1659 ctx->cb = outer_ctx->cb;
1660 ctx->cb.block = NULL;
1661 ctx->depth = outer_ctx->depth + 1;
1662 }
1663 else
1664 {
1665 ctx->cb.src_fn = current_function_decl;
1666 ctx->cb.dst_fn = current_function_decl;
415d1b9a 1667 ctx->cb.src_node = cgraph_node::get (current_function_decl);
53f79206 1668 gcc_checking_assert (ctx->cb.src_node);
1e8e9920 1669 ctx->cb.dst_node = ctx->cb.src_node;
1670 ctx->cb.src_cfun = cfun;
1671 ctx->cb.copy_decl = omp_copy_decl;
e38def9c 1672 ctx->cb.eh_lp_nr = 0;
1e8e9920 1673 ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
1674 ctx->depth = 1;
1675 }
1676
06ecf488 1677 ctx->cb.decl_map = new hash_map<tree, tree>;
1e8e9920 1678
1679 return ctx;
1680}
1681
75a70cf9 1682static gimple_seq maybe_catch_exception (gimple_seq);
f6430caa 1683
1684/* Finalize task copyfn. */
1685
1686static void
1a91d914 1687finalize_task_copyfn (gomp_task *task_stmt)
f6430caa 1688{
1689 struct function *child_cfun;
9078126c 1690 tree child_fn;
e3a19533 1691 gimple_seq seq = NULL, new_seq;
1a91d914 1692 gbind *bind;
f6430caa 1693
75a70cf9 1694 child_fn = gimple_omp_task_copy_fn (task_stmt);
f6430caa 1695 if (child_fn == NULL_TREE)
1696 return;
1697
1698 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
82b40354 1699 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
f6430caa 1700
f6430caa 1701 push_cfun (child_cfun);
7e3aae05 1702 bind = gimplify_body (child_fn, false);
75a70cf9 1703 gimple_seq_add_stmt (&seq, bind);
1704 new_seq = maybe_catch_exception (seq);
1705 if (new_seq != seq)
1706 {
1707 bind = gimple_build_bind (NULL, new_seq, NULL);
e3a19533 1708 seq = NULL;
75a70cf9 1709 gimple_seq_add_stmt (&seq, bind);
1710 }
1711 gimple_set_body (child_fn, seq);
f6430caa 1712 pop_cfun ();
f6430caa 1713
82b40354 1714 /* Inform the callgraph about the new function. */
47300487 1715 cgraph_node *node = cgraph_node::get_create (child_fn);
1716 node->parallelized_function = 1;
415d1b9a 1717 cgraph_node::add_new_function (child_fn, false);
f6430caa 1718}
1719
1e8e9920 1720/* Destroy a omp_context data structures. Called through the splay tree
1721 value delete callback. */
1722
1723static void
1724delete_omp_context (splay_tree_value value)
1725{
1726 omp_context *ctx = (omp_context *) value;
1727
06ecf488 1728 delete ctx->cb.decl_map;
1e8e9920 1729
1730 if (ctx->field_map)
1731 splay_tree_delete (ctx->field_map);
fd6481cf 1732 if (ctx->sfield_map)
1733 splay_tree_delete (ctx->sfield_map);
1e8e9920 1734
1735 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
1736 it produces corrupt debug information. */
1737 if (ctx->record_type)
1738 {
1739 tree t;
1767a056 1740 for (t = TYPE_FIELDS (ctx->record_type); t ; t = DECL_CHAIN (t))
1e8e9920 1741 DECL_ABSTRACT_ORIGIN (t) = NULL;
1742 }
fd6481cf 1743 if (ctx->srecord_type)
1744 {
1745 tree t;
1767a056 1746 for (t = TYPE_FIELDS (ctx->srecord_type); t ; t = DECL_CHAIN (t))
fd6481cf 1747 DECL_ABSTRACT_ORIGIN (t) = NULL;
1748 }
1e8e9920 1749
f6430caa 1750 if (is_task_ctx (ctx))
1a91d914 1751 finalize_task_copyfn (as_a <gomp_task *> (ctx->stmt));
f6430caa 1752
1e8e9920 1753 XDELETE (ctx);
1754}
1755
1756/* Fix up RECEIVER_DECL with a type that has been remapped to the child
1757 context. */
1758
1759static void
1760fixup_child_record_type (omp_context *ctx)
1761{
1762 tree f, type = ctx->record_type;
1763
1764 /* ??? It isn't sufficient to just call remap_type here, because
1765 variably_modified_type_p doesn't work the way we expect for
1766 record types. Testing each field for whether it needs remapping
1767 and creating a new record by hand works, however. */
1767a056 1768 for (f = TYPE_FIELDS (type); f ; f = DECL_CHAIN (f))
1e8e9920 1769 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
1770 break;
1771 if (f)
1772 {
1773 tree name, new_fields = NULL;
1774
1775 type = lang_hooks.types.make_type (RECORD_TYPE);
1776 name = DECL_NAME (TYPE_NAME (ctx->record_type));
e60a6f7b 1777 name = build_decl (DECL_SOURCE_LOCATION (ctx->receiver_decl),
1778 TYPE_DECL, name, type);
1e8e9920 1779 TYPE_NAME (type) = name;
1780
1767a056 1781 for (f = TYPE_FIELDS (ctx->record_type); f ; f = DECL_CHAIN (f))
1e8e9920 1782 {
1783 tree new_f = copy_node (f);
1784 DECL_CONTEXT (new_f) = type;
1785 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
1767a056 1786 DECL_CHAIN (new_f) = new_fields;
75a70cf9 1787 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &ctx->cb, NULL);
1788 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r,
1789 &ctx->cb, NULL);
1790 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
1791 &ctx->cb, NULL);
1e8e9920 1792 new_fields = new_f;
1793
1794 /* Arrange to be able to look up the receiver field
1795 given the sender field. */
1796 splay_tree_insert (ctx->field_map, (splay_tree_key) f,
1797 (splay_tree_value) new_f);
1798 }
1799 TYPE_FIELDS (type) = nreverse (new_fields);
1800 layout_type (type);
1801 }
1802
43895be5 1803 /* In a target region we never modify any of the pointers in *.omp_data_i,
1804 so attempt to help the optimizers. */
1805 if (is_gimple_omp_offloaded (ctx->stmt))
1806 type = build_qualified_type (type, TYPE_QUAL_CONST);
1807
5455b100 1808 TREE_TYPE (ctx->receiver_decl)
1809 = build_qualified_type (build_reference_type (type), TYPE_QUAL_RESTRICT);
1e8e9920 1810}
1811
1812/* Instantiate decls as necessary in CTX to satisfy the data sharing
1813 specified by CLAUSES. */
1814
1815static void
1816scan_sharing_clauses (tree clauses, omp_context *ctx)
1817{
1818 tree c, decl;
1819 bool scan_array_reductions = false;
1820
1821 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1822 {
1823 bool by_ref;
1824
55d6e7cd 1825 switch (OMP_CLAUSE_CODE (c))
1e8e9920 1826 {
1827 case OMP_CLAUSE_PRIVATE:
1828 decl = OMP_CLAUSE_DECL (c);
fd6481cf 1829 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
1830 goto do_private;
1831 else if (!is_variable_sized (decl))
1e8e9920 1832 install_var_local (decl, ctx);
1833 break;
1834
1835 case OMP_CLAUSE_SHARED:
5fddcf34 1836 decl = OMP_CLAUSE_DECL (c);
bc7bff74 1837 /* Ignore shared directives in teams construct. */
1838 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
5fddcf34 1839 {
1840 /* Global variables don't need to be copied,
1841 the receiver side will use them directly. */
1842 tree odecl = maybe_lookup_decl_in_outer_ctx (decl, ctx);
1843 if (is_global_var (odecl))
1844 break;
1845 insert_decl_map (&ctx->cb, decl, odecl);
1846 break;
1847 }
fd6481cf 1848 gcc_assert (is_taskreg_ctx (ctx));
e7327393 1849 gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl))
1850 || !is_variable_sized (decl));
f49d7bb5 1851 /* Global variables don't need to be copied,
1852 the receiver side will use them directly. */
1853 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1854 break;
fd6481cf 1855 by_ref = use_pointer_for_field (decl, ctx);
43895be5 1856 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
1857 break;
1e8e9920 1858 if (! TREE_READONLY (decl)
1859 || TREE_ADDRESSABLE (decl)
1860 || by_ref
1861 || is_reference (decl))
1862 {
fd6481cf 1863 install_var_field (decl, by_ref, 3, ctx);
1e8e9920 1864 install_var_local (decl, ctx);
1865 break;
1866 }
1867 /* We don't need to copy const scalar vars back. */
55d6e7cd 1868 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
1e8e9920 1869 goto do_private;
1870
43895be5 1871 case OMP_CLAUSE_REDUCTION:
1872 decl = OMP_CLAUSE_DECL (c);
1873 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1874 && TREE_CODE (decl) == MEM_REF)
1875 {
1876 tree t = TREE_OPERAND (decl, 0);
9561765e 1877 if (TREE_CODE (t) == POINTER_PLUS_EXPR)
1878 t = TREE_OPERAND (t, 0);
43895be5 1879 if (TREE_CODE (t) == INDIRECT_REF
1880 || TREE_CODE (t) == ADDR_EXPR)
1881 t = TREE_OPERAND (t, 0);
1882 install_var_local (t, ctx);
1883 if (is_taskreg_ctx (ctx)
1884 && !is_global_var (maybe_lookup_decl_in_outer_ctx (t, ctx))
1885 && !is_variable_sized (t))
1886 {
1887 by_ref = use_pointer_for_field (t, ctx);
1888 install_var_field (t, by_ref, 3, ctx);
1889 }
1890 break;
1891 }
1892 goto do_private;
1893
1e8e9920 1894 case OMP_CLAUSE_LASTPRIVATE:
1895 /* Let the corresponding firstprivate clause create
1896 the variable. */
1897 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1898 break;
1899 /* FALLTHRU */
1900
1901 case OMP_CLAUSE_FIRSTPRIVATE:
3d483a94 1902 case OMP_CLAUSE_LINEAR:
1e8e9920 1903 decl = OMP_CLAUSE_DECL (c);
1904 do_private:
43895be5 1905 if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
1906 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IS_DEVICE_PTR)
1907 && is_gimple_omp_offloaded (ctx->stmt))
1908 {
1909 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
1910 install_var_field (decl, !is_reference (decl), 3, ctx);
1911 else if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1912 install_var_field (decl, true, 3, ctx);
1913 else
1914 install_var_field (decl, false, 3, ctx);
1915 }
1e8e9920 1916 if (is_variable_sized (decl))
1e8e9920 1917 {
fd6481cf 1918 if (is_task_ctx (ctx))
1919 install_var_field (decl, false, 1, ctx);
1920 break;
1921 }
1922 else if (is_taskreg_ctx (ctx))
1923 {
1924 bool global
1925 = is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx));
e8a588af 1926 by_ref = use_pointer_for_field (decl, NULL);
fd6481cf 1927
1928 if (is_task_ctx (ctx)
1929 && (global || by_ref || is_reference (decl)))
1930 {
1931 install_var_field (decl, false, 1, ctx);
1932 if (!global)
1933 install_var_field (decl, by_ref, 2, ctx);
1934 }
1935 else if (!global)
1936 install_var_field (decl, by_ref, 3, ctx);
1e8e9920 1937 }
1938 install_var_local (decl, ctx);
1939 break;
1940
43895be5 1941 case OMP_CLAUSE_USE_DEVICE_PTR:
1942 decl = OMP_CLAUSE_DECL (c);
1943 if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1944 install_var_field (decl, true, 3, ctx);
1945 else
1946 install_var_field (decl, false, 3, ctx);
1947 if (DECL_SIZE (decl)
1948 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1949 {
1950 tree decl2 = DECL_VALUE_EXPR (decl);
1951 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1952 decl2 = TREE_OPERAND (decl2, 0);
1953 gcc_assert (DECL_P (decl2));
1954 install_var_local (decl2, ctx);
1955 }
1956 install_var_local (decl, ctx);
1957 break;
1958
1959 case OMP_CLAUSE_IS_DEVICE_PTR:
1960 decl = OMP_CLAUSE_DECL (c);
1961 goto do_private;
1962
bc7bff74 1963 case OMP_CLAUSE__LOOPTEMP_:
43895be5 1964 gcc_assert (is_taskreg_ctx (ctx));
bc7bff74 1965 decl = OMP_CLAUSE_DECL (c);
1966 install_var_field (decl, false, 3, ctx);
1967 install_var_local (decl, ctx);
1968 break;
1969
1e8e9920 1970 case OMP_CLAUSE_COPYPRIVATE:
1e8e9920 1971 case OMP_CLAUSE_COPYIN:
1972 decl = OMP_CLAUSE_DECL (c);
e8a588af 1973 by_ref = use_pointer_for_field (decl, NULL);
fd6481cf 1974 install_var_field (decl, by_ref, 3, ctx);
1e8e9920 1975 break;
1976
1977 case OMP_CLAUSE_DEFAULT:
1978 ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
1979 break;
1980
2169f33b 1981 case OMP_CLAUSE_FINAL:
1e8e9920 1982 case OMP_CLAUSE_IF:
1983 case OMP_CLAUSE_NUM_THREADS:
bc7bff74 1984 case OMP_CLAUSE_NUM_TEAMS:
1985 case OMP_CLAUSE_THREAD_LIMIT:
1986 case OMP_CLAUSE_DEVICE:
1e8e9920 1987 case OMP_CLAUSE_SCHEDULE:
bc7bff74 1988 case OMP_CLAUSE_DIST_SCHEDULE:
1989 case OMP_CLAUSE_DEPEND:
43895be5 1990 case OMP_CLAUSE_PRIORITY:
1991 case OMP_CLAUSE_GRAINSIZE:
1992 case OMP_CLAUSE_NUM_TASKS:
40750995 1993 case OMP_CLAUSE__CILK_FOR_COUNT_:
ca4c3545 1994 case OMP_CLAUSE_NUM_GANGS:
1995 case OMP_CLAUSE_NUM_WORKERS:
1996 case OMP_CLAUSE_VECTOR_LENGTH:
1e8e9920 1997 if (ctx->outer)
75a70cf9 1998 scan_omp_op (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
1e8e9920 1999 break;
2000
bc7bff74 2001 case OMP_CLAUSE_TO:
2002 case OMP_CLAUSE_FROM:
2003 case OMP_CLAUSE_MAP:
2004 if (ctx->outer)
2005 scan_omp_op (&OMP_CLAUSE_SIZE (c), ctx->outer);
2006 decl = OMP_CLAUSE_DECL (c);
2007 /* Global variables with "omp declare target" attribute
2008 don't need to be copied, the receiver side will use them
2009 directly. */
2010 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
2011 && DECL_P (decl)
9561765e 2012 && ((OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_FIRSTPRIVATE_POINTER
2013 && (OMP_CLAUSE_MAP_KIND (c)
2014 != GOMP_MAP_FIRSTPRIVATE_REFERENCE))
43895be5 2015 || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
bc7bff74 2016 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
b0c5e347 2017 && varpool_node::get_create (decl)->offloadable)
bc7bff74 2018 break;
2019 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
ca4c3545 2020 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER)
bc7bff74 2021 {
ca4c3545 2022 /* Ignore GOMP_MAP_POINTER kind for arrays in regions that are
2023 not offloaded; there is nothing to map for those. */
2024 if (!is_gimple_omp_offloaded (ctx->stmt)
c1a114c2 2025 && !POINTER_TYPE_P (TREE_TYPE (decl))
2026 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
bc7bff74 2027 break;
2028 }
43895be5 2029 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
9561765e 2030 && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
2031 || (OMP_CLAUSE_MAP_KIND (c)
2032 == GOMP_MAP_FIRSTPRIVATE_REFERENCE)))
43895be5 2033 {
2034 if (TREE_CODE (decl) == COMPONENT_REF
2035 || (TREE_CODE (decl) == INDIRECT_REF
2036 && TREE_CODE (TREE_OPERAND (decl, 0)) == COMPONENT_REF
2037 && (TREE_CODE (TREE_TYPE (TREE_OPERAND (decl, 0)))
2038 == REFERENCE_TYPE)))
2039 break;
2040 if (DECL_SIZE (decl)
2041 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
2042 {
2043 tree decl2 = DECL_VALUE_EXPR (decl);
2044 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2045 decl2 = TREE_OPERAND (decl2, 0);
2046 gcc_assert (DECL_P (decl2));
2047 install_var_local (decl2, ctx);
2048 }
2049 install_var_local (decl, ctx);
2050 break;
2051 }
bc7bff74 2052 if (DECL_P (decl))
2053 {
2054 if (DECL_SIZE (decl)
2055 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
2056 {
2057 tree decl2 = DECL_VALUE_EXPR (decl);
2058 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2059 decl2 = TREE_OPERAND (decl2, 0);
2060 gcc_assert (DECL_P (decl2));
9561765e 2061 install_var_field (decl2, true, 3, ctx);
bc7bff74 2062 install_var_local (decl2, ctx);
2063 install_var_local (decl, ctx);
2064 }
2065 else
2066 {
2067 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
ca4c3545 2068 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
bc7bff74 2069 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
2070 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
2071 install_var_field (decl, true, 7, ctx);
2072 else
2073 install_var_field (decl, true, 3, ctx);
ca4c3545 2074 if (is_gimple_omp_offloaded (ctx->stmt))
bc7bff74 2075 install_var_local (decl, ctx);
2076 }
2077 }
2078 else
2079 {
2080 tree base = get_base_address (decl);
2081 tree nc = OMP_CLAUSE_CHAIN (c);
2082 if (DECL_P (base)
2083 && nc != NULL_TREE
2084 && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
2085 && OMP_CLAUSE_DECL (nc) == base
ca4c3545 2086 && OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_POINTER
bc7bff74 2087 && integer_zerop (OMP_CLAUSE_SIZE (nc)))
2088 {
2089 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c) = 1;
2090 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (nc) = 1;
2091 }
2092 else
2093 {
691447ab 2094 if (ctx->outer)
2095 {
2096 scan_omp_op (&OMP_CLAUSE_DECL (c), ctx->outer);
2097 decl = OMP_CLAUSE_DECL (c);
2098 }
bc7bff74 2099 gcc_assert (!splay_tree_lookup (ctx->field_map,
2100 (splay_tree_key) decl));
2101 tree field
2102 = build_decl (OMP_CLAUSE_LOCATION (c),
2103 FIELD_DECL, NULL_TREE, ptr_type_node);
2104 DECL_ALIGN (field) = TYPE_ALIGN (ptr_type_node);
2105 insert_field_into_struct (ctx->record_type, field);
2106 splay_tree_insert (ctx->field_map, (splay_tree_key) decl,
2107 (splay_tree_value) field);
2108 }
2109 }
2110 break;
2111
1e8e9920 2112 case OMP_CLAUSE_NOWAIT:
2113 case OMP_CLAUSE_ORDERED:
fd6481cf 2114 case OMP_CLAUSE_COLLAPSE:
2115 case OMP_CLAUSE_UNTIED:
2169f33b 2116 case OMP_CLAUSE_MERGEABLE:
bc7bff74 2117 case OMP_CLAUSE_PROC_BIND:
3d483a94 2118 case OMP_CLAUSE_SAFELEN:
43895be5 2119 case OMP_CLAUSE_SIMDLEN:
2120 case OMP_CLAUSE_THREADS:
2121 case OMP_CLAUSE_SIMD:
2122 case OMP_CLAUSE_NOGROUP:
2123 case OMP_CLAUSE_DEFAULTMAP:
ca4c3545 2124 case OMP_CLAUSE_ASYNC:
2125 case OMP_CLAUSE_WAIT:
2126 case OMP_CLAUSE_GANG:
2127 case OMP_CLAUSE_WORKER:
2128 case OMP_CLAUSE_VECTOR:
ef014f95 2129 case OMP_CLAUSE_TILE:
f4f5b4b4 2130 case OMP_CLAUSE_INDEPENDENT:
2131 case OMP_CLAUSE_AUTO:
2132 case OMP_CLAUSE_SEQ:
1e8e9920 2133 break;
2134
bc7bff74 2135 case OMP_CLAUSE_ALIGNED:
2136 decl = OMP_CLAUSE_DECL (c);
2137 if (is_global_var (decl)
2138 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
2139 install_var_local (decl, ctx);
2140 break;
2141
ca4c3545 2142 case OMP_CLAUSE_DEVICE_RESIDENT:
2143 case OMP_CLAUSE_USE_DEVICE:
2144 case OMP_CLAUSE__CACHE_:
ca4c3545 2145 sorry ("Clause not supported yet");
2146 break;
2147
1e8e9920 2148 default:
2149 gcc_unreachable ();
2150 }
2151 }
2152
2153 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2154 {
55d6e7cd 2155 switch (OMP_CLAUSE_CODE (c))
1e8e9920 2156 {
2157 case OMP_CLAUSE_LASTPRIVATE:
2158 /* Let the corresponding firstprivate clause create
2159 the variable. */
75a70cf9 2160 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
fd6481cf 2161 scan_array_reductions = true;
1e8e9920 2162 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
2163 break;
2164 /* FALLTHRU */
2165
1e8e9920 2166 case OMP_CLAUSE_FIRSTPRIVATE:
ca4c3545 2167 case OMP_CLAUSE_PRIVATE:
3d483a94 2168 case OMP_CLAUSE_LINEAR:
43895be5 2169 case OMP_CLAUSE_IS_DEVICE_PTR:
1e8e9920 2170 decl = OMP_CLAUSE_DECL (c);
2171 if (is_variable_sized (decl))
43895be5 2172 {
2173 if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
2174 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IS_DEVICE_PTR)
2175 && is_gimple_omp_offloaded (ctx->stmt))
2176 {
2177 tree decl2 = DECL_VALUE_EXPR (decl);
2178 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2179 decl2 = TREE_OPERAND (decl2, 0);
2180 gcc_assert (DECL_P (decl2));
2181 install_var_local (decl2, ctx);
2182 fixup_remapped_decl (decl2, ctx, false);
2183 }
2184 install_var_local (decl, ctx);
2185 }
1e8e9920 2186 fixup_remapped_decl (decl, ctx,
55d6e7cd 2187 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
1e8e9920 2188 && OMP_CLAUSE_PRIVATE_DEBUG (c));
43895be5 2189 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
2190 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
1e8e9920 2191 scan_array_reductions = true;
43895be5 2192 break;
2193
2194 case OMP_CLAUSE_REDUCTION:
2195 decl = OMP_CLAUSE_DECL (c);
2196 if (TREE_CODE (decl) != MEM_REF)
2197 {
2198 if (is_variable_sized (decl))
2199 install_var_local (decl, ctx);
2200 fixup_remapped_decl (decl, ctx, false);
2201 }
2202 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2b536a17 2203 scan_array_reductions = true;
1e8e9920 2204 break;
2205
2206 case OMP_CLAUSE_SHARED:
bc7bff74 2207 /* Ignore shared directives in teams construct. */
2208 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
2209 break;
1e8e9920 2210 decl = OMP_CLAUSE_DECL (c);
43895be5 2211 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
2212 break;
2213 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
2214 {
2215 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl,
2216 ctx->outer)))
2217 break;
2218 bool by_ref = use_pointer_for_field (decl, ctx);
2219 install_var_field (decl, by_ref, 11, ctx);
2220 break;
2221 }
2222 fixup_remapped_decl (decl, ctx, false);
1e8e9920 2223 break;
2224
bc7bff74 2225 case OMP_CLAUSE_MAP:
ca4c3545 2226 if (!is_gimple_omp_offloaded (ctx->stmt))
bc7bff74 2227 break;
2228 decl = OMP_CLAUSE_DECL (c);
2229 if (DECL_P (decl)
9561765e 2230 && ((OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_FIRSTPRIVATE_POINTER
2231 && (OMP_CLAUSE_MAP_KIND (c)
2232 != GOMP_MAP_FIRSTPRIVATE_REFERENCE))
43895be5 2233 || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
bc7bff74 2234 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
b0c5e347 2235 && varpool_node::get_create (decl)->offloadable)
bc7bff74 2236 break;
2237 if (DECL_P (decl))
2238 {
43895be5 2239 if ((OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
2240 || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER)
bc7bff74 2241 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
2242 && !COMPLETE_TYPE_P (TREE_TYPE (decl)))
2243 {
2244 tree new_decl = lookup_decl (decl, ctx);
2245 TREE_TYPE (new_decl)
2246 = remap_type (TREE_TYPE (decl), &ctx->cb);
2247 }
2248 else if (DECL_SIZE (decl)
2249 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
2250 {
2251 tree decl2 = DECL_VALUE_EXPR (decl);
2252 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2253 decl2 = TREE_OPERAND (decl2, 0);
2254 gcc_assert (DECL_P (decl2));
2255 fixup_remapped_decl (decl2, ctx, false);
2256 fixup_remapped_decl (decl, ctx, true);
2257 }
2258 else
2259 fixup_remapped_decl (decl, ctx, false);
2260 }
2261 break;
2262
1e8e9920 2263 case OMP_CLAUSE_COPYPRIVATE:
2264 case OMP_CLAUSE_COPYIN:
2265 case OMP_CLAUSE_DEFAULT:
2266 case OMP_CLAUSE_IF:
2267 case OMP_CLAUSE_NUM_THREADS:
bc7bff74 2268 case OMP_CLAUSE_NUM_TEAMS:
2269 case OMP_CLAUSE_THREAD_LIMIT:
2270 case OMP_CLAUSE_DEVICE:
1e8e9920 2271 case OMP_CLAUSE_SCHEDULE:
bc7bff74 2272 case OMP_CLAUSE_DIST_SCHEDULE:
1e8e9920 2273 case OMP_CLAUSE_NOWAIT:
2274 case OMP_CLAUSE_ORDERED:
fd6481cf 2275 case OMP_CLAUSE_COLLAPSE:
2276 case OMP_CLAUSE_UNTIED:
2169f33b 2277 case OMP_CLAUSE_FINAL:
2278 case OMP_CLAUSE_MERGEABLE:
bc7bff74 2279 case OMP_CLAUSE_PROC_BIND:
3d483a94 2280 case OMP_CLAUSE_SAFELEN:
43895be5 2281 case OMP_CLAUSE_SIMDLEN:
bc7bff74 2282 case OMP_CLAUSE_ALIGNED:
2283 case OMP_CLAUSE_DEPEND:
2284 case OMP_CLAUSE__LOOPTEMP_:
2285 case OMP_CLAUSE_TO:
2286 case OMP_CLAUSE_FROM:
43895be5 2287 case OMP_CLAUSE_PRIORITY:
2288 case OMP_CLAUSE_GRAINSIZE:
2289 case OMP_CLAUSE_NUM_TASKS:
2290 case OMP_CLAUSE_THREADS:
2291 case OMP_CLAUSE_SIMD:
2292 case OMP_CLAUSE_NOGROUP:
2293 case OMP_CLAUSE_DEFAULTMAP:
2294 case OMP_CLAUSE_USE_DEVICE_PTR:
40750995 2295 case OMP_CLAUSE__CILK_FOR_COUNT_:
ca4c3545 2296 case OMP_CLAUSE_ASYNC:
2297 case OMP_CLAUSE_WAIT:
2298 case OMP_CLAUSE_NUM_GANGS:
2299 case OMP_CLAUSE_NUM_WORKERS:
2300 case OMP_CLAUSE_VECTOR_LENGTH:
2301 case OMP_CLAUSE_GANG:
2302 case OMP_CLAUSE_WORKER:
2303 case OMP_CLAUSE_VECTOR:
ef014f95 2304 case OMP_CLAUSE_TILE:
f4f5b4b4 2305 case OMP_CLAUSE_INDEPENDENT:
2306 case OMP_CLAUSE_AUTO:
2307 case OMP_CLAUSE_SEQ:
ca4c3545 2308 break;
2309
2310 case OMP_CLAUSE_DEVICE_RESIDENT:
2311 case OMP_CLAUSE_USE_DEVICE:
2312 case OMP_CLAUSE__CACHE_:
ca4c3545 2313 sorry ("Clause not supported yet");
1e8e9920 2314 break;
2315
2316 default:
2317 gcc_unreachable ();
2318 }
2319 }
2320
ca4c3545 2321 gcc_checking_assert (!scan_array_reductions
2322 || !is_gimple_omp_oacc (ctx->stmt));
1e8e9920 2323 if (scan_array_reductions)
2324 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
55d6e7cd 2325 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1e8e9920 2326 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2327 {
ab129075 2328 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
2329 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
1e8e9920 2330 }
fd6481cf 2331 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
75a70cf9 2332 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
ab129075 2333 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
2b536a17 2334 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
2335 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
2336 scan_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
1e8e9920 2337}
2338
40750995 2339/* Create a new name for omp child function. Returns an identifier. If
2340 IS_CILK_FOR is true then the suffix for the child function is
2341 "_cilk_for_fn." */
1e8e9920 2342
1e8e9920 2343static tree
40750995 2344create_omp_child_function_name (bool task_copy, bool is_cilk_for)
1e8e9920 2345{
40750995 2346 if (is_cilk_for)
2347 return clone_function_name (current_function_decl, "_cilk_for_fn");
2348 return clone_function_name (current_function_decl,
2349 task_copy ? "_omp_cpyfn" : "_omp_fn");
2350}
2351
2352/* Returns the type of the induction variable for the child function for
2353 _Cilk_for and the types for _high and _low variables based on TYPE. */
2354
2355static tree
2356cilk_for_check_loop_diff_type (tree type)
2357{
2358 if (TYPE_PRECISION (type) <= TYPE_PRECISION (uint32_type_node))
2359 {
2360 if (TYPE_UNSIGNED (type))
2361 return uint32_type_node;
2362 else
2363 return integer_type_node;
2364 }
2365 else
2366 {
2367 if (TYPE_UNSIGNED (type))
2368 return uint64_type_node;
2369 else
2370 return long_long_integer_type_node;
2371 }
1e8e9920 2372}
2373
2374/* Build a decl for the omp child function. It'll not contain a body
2375 yet, just the bare decl. */
2376
2377static void
fd6481cf 2378create_omp_child_function (omp_context *ctx, bool task_copy)
1e8e9920 2379{
2380 tree decl, type, name, t;
2381
40750995 2382 tree cilk_for_count
2383 = (flag_cilkplus && gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2384 ? find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
2385 OMP_CLAUSE__CILK_FOR_COUNT_) : NULL_TREE;
2386 tree cilk_var_type = NULL_TREE;
2387
2388 name = create_omp_child_function_name (task_copy,
2389 cilk_for_count != NULL_TREE);
fd6481cf 2390 if (task_copy)
2391 type = build_function_type_list (void_type_node, ptr_type_node,
2392 ptr_type_node, NULL_TREE);
40750995 2393 else if (cilk_for_count)
2394 {
2395 type = TREE_TYPE (OMP_CLAUSE_OPERAND (cilk_for_count, 0));
2396 cilk_var_type = cilk_for_check_loop_diff_type (type);
2397 type = build_function_type_list (void_type_node, ptr_type_node,
2398 cilk_var_type, cilk_var_type, NULL_TREE);
2399 }
fd6481cf 2400 else
2401 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
1e8e9920 2402
40750995 2403 decl = build_decl (gimple_location (ctx->stmt), FUNCTION_DECL, name, type);
1e8e9920 2404
ca4c3545 2405 gcc_checking_assert (!is_gimple_omp_oacc (ctx->stmt)
2406 || !task_copy);
fd6481cf 2407 if (!task_copy)
2408 ctx->cb.dst_fn = decl;
2409 else
75a70cf9 2410 gimple_omp_task_set_copy_fn (ctx->stmt, decl);
1e8e9920 2411
2412 TREE_STATIC (decl) = 1;
2413 TREE_USED (decl) = 1;
2414 DECL_ARTIFICIAL (decl) = 1;
2415 DECL_IGNORED_P (decl) = 0;
2416 TREE_PUBLIC (decl) = 0;
2417 DECL_UNINLINABLE (decl) = 1;
2418 DECL_EXTERNAL (decl) = 0;
2419 DECL_CONTEXT (decl) = NULL_TREE;
773c5ba7 2420 DECL_INITIAL (decl) = make_node (BLOCK);
b0c5e347 2421 if (cgraph_node::get (current_function_decl)->offloadable)
2422 cgraph_node::get_create (decl)->offloadable = 1;
bc7bff74 2423 else
2424 {
2425 omp_context *octx;
2426 for (octx = ctx; octx; octx = octx->outer)
ca4c3545 2427 if (is_gimple_omp_offloaded (octx->stmt))
bc7bff74 2428 {
b0c5e347 2429 cgraph_node::get_create (decl)->offloadable = 1;
5f3001a9 2430 if (ENABLE_OFFLOADING)
2431 g->have_offload = true;
2432
bc7bff74 2433 break;
2434 }
2435 }
1e8e9920 2436
ec12b31a 2437 if (cgraph_node::get_create (decl)->offloadable
2438 && !lookup_attribute ("omp declare target",
2439 DECL_ATTRIBUTES (current_function_decl)))
2440 DECL_ATTRIBUTES (decl)
2441 = tree_cons (get_identifier ("omp target entrypoint"),
2442 NULL_TREE, DECL_ATTRIBUTES (decl));
2443
e60a6f7b 2444 t = build_decl (DECL_SOURCE_LOCATION (decl),
2445 RESULT_DECL, NULL_TREE, void_type_node);
1e8e9920 2446 DECL_ARTIFICIAL (t) = 1;
2447 DECL_IGNORED_P (t) = 1;
8e5b4ed6 2448 DECL_CONTEXT (t) = decl;
1e8e9920 2449 DECL_RESULT (decl) = t;
2450
40750995 2451 /* _Cilk_for's child function requires two extra parameters called
2452 __low and __high that are set the by Cilk runtime when it calls this
2453 function. */
2454 if (cilk_for_count)
2455 {
2456 t = build_decl (DECL_SOURCE_LOCATION (decl),
2457 PARM_DECL, get_identifier ("__high"), cilk_var_type);
2458 DECL_ARTIFICIAL (t) = 1;
2459 DECL_NAMELESS (t) = 1;
2460 DECL_ARG_TYPE (t) = ptr_type_node;
2461 DECL_CONTEXT (t) = current_function_decl;
2462 TREE_USED (t) = 1;
2463 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2464 DECL_ARGUMENTS (decl) = t;
2465
2466 t = build_decl (DECL_SOURCE_LOCATION (decl),
2467 PARM_DECL, get_identifier ("__low"), cilk_var_type);
2468 DECL_ARTIFICIAL (t) = 1;
2469 DECL_NAMELESS (t) = 1;
2470 DECL_ARG_TYPE (t) = ptr_type_node;
2471 DECL_CONTEXT (t) = current_function_decl;
2472 TREE_USED (t) = 1;
2473 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2474 DECL_ARGUMENTS (decl) = t;
2475 }
2476
2477 tree data_name = get_identifier (".omp_data_i");
2478 t = build_decl (DECL_SOURCE_LOCATION (decl), PARM_DECL, data_name,
2479 ptr_type_node);
1e8e9920 2480 DECL_ARTIFICIAL (t) = 1;
84bfaaeb 2481 DECL_NAMELESS (t) = 1;
1e8e9920 2482 DECL_ARG_TYPE (t) = ptr_type_node;
773c5ba7 2483 DECL_CONTEXT (t) = current_function_decl;
1e8e9920 2484 TREE_USED (t) = 1;
43895be5 2485 TREE_READONLY (t) = 1;
40750995 2486 if (cilk_for_count)
2487 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
1e8e9920 2488 DECL_ARGUMENTS (decl) = t;
fd6481cf 2489 if (!task_copy)
2490 ctx->receiver_decl = t;
2491 else
2492 {
e60a6f7b 2493 t = build_decl (DECL_SOURCE_LOCATION (decl),
2494 PARM_DECL, get_identifier (".omp_data_o"),
fd6481cf 2495 ptr_type_node);
2496 DECL_ARTIFICIAL (t) = 1;
84bfaaeb 2497 DECL_NAMELESS (t) = 1;
fd6481cf 2498 DECL_ARG_TYPE (t) = ptr_type_node;
2499 DECL_CONTEXT (t) = current_function_decl;
2500 TREE_USED (t) = 1;
86f2ad37 2501 TREE_ADDRESSABLE (t) = 1;
1767a056 2502 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
fd6481cf 2503 DECL_ARGUMENTS (decl) = t;
2504 }
1e8e9920 2505
48e1416a 2506 /* Allocate memory for the function structure. The call to
773c5ba7 2507 allocate_struct_function clobbers CFUN, so we need to restore
1e8e9920 2508 it afterward. */
87d4aa85 2509 push_struct_function (decl);
75a70cf9 2510 cfun->function_end_locus = gimple_location (ctx->stmt);
87d4aa85 2511 pop_cfun ();
1e8e9920 2512}
2513
bc7bff74 2514/* Callback for walk_gimple_seq. Check if combined parallel
2515 contains gimple_omp_for_combined_into_p OMP_FOR. */
2516
2517static tree
2518find_combined_for (gimple_stmt_iterator *gsi_p,
2519 bool *handled_ops_p,
2520 struct walk_stmt_info *wi)
2521{
42acab1c 2522 gimple *stmt = gsi_stmt (*gsi_p);
bc7bff74 2523
2524 *handled_ops_p = true;
2525 switch (gimple_code (stmt))
2526 {
2527 WALK_SUBSTMTS;
2528
2529 case GIMPLE_OMP_FOR:
2530 if (gimple_omp_for_combined_into_p (stmt)
43895be5 2531 && gimple_omp_for_kind (stmt)
2532 == *(const enum gf_mask *) (wi->info))
bc7bff74 2533 {
2534 wi->info = stmt;
2535 return integer_zero_node;
2536 }
2537 break;
2538 default:
2539 break;
2540 }
2541 return NULL;
2542}
2543
43895be5 2544/* Add _LOOPTEMP_ clauses on OpenMP parallel or task. */
2545
2546static void
2547add_taskreg_looptemp_clauses (enum gf_mask msk, gimple *stmt,
2548 omp_context *outer_ctx)
2549{
2550 struct walk_stmt_info wi;
2551
2552 memset (&wi, 0, sizeof (wi));
2553 wi.val_only = true;
2554 wi.info = (void *) &msk;
2555 walk_gimple_seq (gimple_omp_body (stmt), find_combined_for, NULL, &wi);
2556 if (wi.info != (void *) &msk)
2557 {
2558 gomp_for *for_stmt = as_a <gomp_for *> ((gimple *) wi.info);
2559 struct omp_for_data fd;
2560 extract_omp_for_data (for_stmt, &fd, NULL);
2561 /* We need two temporaries with fd.loop.v type (istart/iend)
2562 and then (fd.collapse - 1) temporaries with the same
2563 type for count2 ... countN-1 vars if not constant. */
2564 size_t count = 2, i;
2565 tree type = fd.iter_type;
2566 if (fd.collapse > 1
2567 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
2568 {
2569 count += fd.collapse - 1;
9561765e 2570 /* If there are lastprivate clauses on the inner
43895be5 2571 GIMPLE_OMP_FOR, add one more temporaries for the total number
2572 of iterations (product of count1 ... countN-1). */
9561765e 2573 if (find_omp_clause (gimple_omp_for_clauses (for_stmt),
2574 OMP_CLAUSE_LASTPRIVATE))
2575 count++;
2576 else if (msk == GF_OMP_FOR_KIND_FOR
2577 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
2578 OMP_CLAUSE_LASTPRIVATE))
43895be5 2579 count++;
2580 }
2581 for (i = 0; i < count; i++)
2582 {
2583 tree temp = create_tmp_var (type);
2584 tree c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
2585 insert_decl_map (&outer_ctx->cb, temp, temp);
2586 OMP_CLAUSE_DECL (c) = temp;
2587 OMP_CLAUSE_CHAIN (c) = gimple_omp_taskreg_clauses (stmt);
2588 gimple_omp_taskreg_set_clauses (stmt, c);
2589 }
2590 }
2591}
2592
1e8e9920 2593/* Scan an OpenMP parallel directive. */
2594
2595static void
75a70cf9 2596scan_omp_parallel (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
1e8e9920 2597{
2598 omp_context *ctx;
2599 tree name;
1a91d914 2600 gomp_parallel *stmt = as_a <gomp_parallel *> (gsi_stmt (*gsi));
1e8e9920 2601
2602 /* Ignore parallel directives with empty bodies, unless there
2603 are copyin clauses. */
2604 if (optimize > 0
75a70cf9 2605 && empty_body_p (gimple_omp_body (stmt))
2606 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
2607 OMP_CLAUSE_COPYIN) == NULL)
1e8e9920 2608 {
75a70cf9 2609 gsi_replace (gsi, gimple_build_nop (), false);
1e8e9920 2610 return;
2611 }
2612
bc7bff74 2613 if (gimple_omp_parallel_combined_p (stmt))
43895be5 2614 add_taskreg_looptemp_clauses (GF_OMP_FOR_KIND_FOR, stmt, outer_ctx);
bc7bff74 2615
75a70cf9 2616 ctx = new_omp_context (stmt, outer_ctx);
37eaded9 2617 taskreg_contexts.safe_push (ctx);
fd6481cf 2618 if (taskreg_nesting_level > 1)
773c5ba7 2619 ctx->is_nested = true;
1e8e9920 2620 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1e8e9920 2621 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2622 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
1e8e9920 2623 name = create_tmp_var_name (".omp_data_s");
e60a6f7b 2624 name = build_decl (gimple_location (stmt),
2625 TYPE_DECL, name, ctx->record_type);
84bfaaeb 2626 DECL_ARTIFICIAL (name) = 1;
2627 DECL_NAMELESS (name) = 1;
1e8e9920 2628 TYPE_NAME (ctx->record_type) = name;
240131b5 2629 TYPE_ARTIFICIAL (ctx->record_type) = 1;
fd6481cf 2630 create_omp_child_function (ctx, false);
75a70cf9 2631 gimple_omp_parallel_set_child_fn (stmt, ctx->cb.dst_fn);
1e8e9920 2632
75a70cf9 2633 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt), ctx);
ab129075 2634 scan_omp (gimple_omp_body_ptr (stmt), ctx);
1e8e9920 2635
2636 if (TYPE_FIELDS (ctx->record_type) == NULL)
2637 ctx->record_type = ctx->receiver_decl = NULL;
1e8e9920 2638}
2639
fd6481cf 2640/* Scan an OpenMP task directive. */
2641
2642static void
75a70cf9 2643scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
fd6481cf 2644{
2645 omp_context *ctx;
75a70cf9 2646 tree name, t;
1a91d914 2647 gomp_task *stmt = as_a <gomp_task *> (gsi_stmt (*gsi));
fd6481cf 2648
2649 /* Ignore task directives with empty bodies. */
2650 if (optimize > 0
75a70cf9 2651 && empty_body_p (gimple_omp_body (stmt)))
fd6481cf 2652 {
75a70cf9 2653 gsi_replace (gsi, gimple_build_nop (), false);
fd6481cf 2654 return;
2655 }
2656
43895be5 2657 if (gimple_omp_task_taskloop_p (stmt))
2658 add_taskreg_looptemp_clauses (GF_OMP_FOR_KIND_TASKLOOP, stmt, outer_ctx);
2659
75a70cf9 2660 ctx = new_omp_context (stmt, outer_ctx);
37eaded9 2661 taskreg_contexts.safe_push (ctx);
fd6481cf 2662 if (taskreg_nesting_level > 1)
2663 ctx->is_nested = true;
2664 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2665 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2666 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2667 name = create_tmp_var_name (".omp_data_s");
e60a6f7b 2668 name = build_decl (gimple_location (stmt),
2669 TYPE_DECL, name, ctx->record_type);
84bfaaeb 2670 DECL_ARTIFICIAL (name) = 1;
2671 DECL_NAMELESS (name) = 1;
fd6481cf 2672 TYPE_NAME (ctx->record_type) = name;
240131b5 2673 TYPE_ARTIFICIAL (ctx->record_type) = 1;
fd6481cf 2674 create_omp_child_function (ctx, false);
75a70cf9 2675 gimple_omp_task_set_child_fn (stmt, ctx->cb.dst_fn);
fd6481cf 2676
75a70cf9 2677 scan_sharing_clauses (gimple_omp_task_clauses (stmt), ctx);
fd6481cf 2678
2679 if (ctx->srecord_type)
2680 {
2681 name = create_tmp_var_name (".omp_data_a");
e60a6f7b 2682 name = build_decl (gimple_location (stmt),
2683 TYPE_DECL, name, ctx->srecord_type);
84bfaaeb 2684 DECL_ARTIFICIAL (name) = 1;
2685 DECL_NAMELESS (name) = 1;
fd6481cf 2686 TYPE_NAME (ctx->srecord_type) = name;
240131b5 2687 TYPE_ARTIFICIAL (ctx->srecord_type) = 1;
fd6481cf 2688 create_omp_child_function (ctx, true);
2689 }
2690
ab129075 2691 scan_omp (gimple_omp_body_ptr (stmt), ctx);
fd6481cf 2692
2693 if (TYPE_FIELDS (ctx->record_type) == NULL)
2694 {
2695 ctx->record_type = ctx->receiver_decl = NULL;
75a70cf9 2696 t = build_int_cst (long_integer_type_node, 0);
2697 gimple_omp_task_set_arg_size (stmt, t);
2698 t = build_int_cst (long_integer_type_node, 1);
2699 gimple_omp_task_set_arg_align (stmt, t);
fd6481cf 2700 }
37eaded9 2701}
2702
2703
2704/* If any decls have been made addressable during scan_omp,
2705 adjust their fields if needed, and layout record types
2706 of parallel/task constructs. */
2707
2708static void
2709finish_taskreg_scan (omp_context *ctx)
2710{
2711 if (ctx->record_type == NULL_TREE)
2712 return;
2713
2714 /* If any task_shared_vars were needed, verify all
2715 OMP_CLAUSE_SHARED clauses on GIMPLE_OMP_{PARALLEL,TASK}
2716 statements if use_pointer_for_field hasn't changed
2717 because of that. If it did, update field types now. */
2718 if (task_shared_vars)
2719 {
2720 tree c;
2721
2722 for (c = gimple_omp_taskreg_clauses (ctx->stmt);
2723 c; c = OMP_CLAUSE_CHAIN (c))
43895be5 2724 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
2725 && !OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
37eaded9 2726 {
2727 tree decl = OMP_CLAUSE_DECL (c);
2728
2729 /* Global variables don't need to be copied,
2730 the receiver side will use them directly. */
2731 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
2732 continue;
2733 if (!bitmap_bit_p (task_shared_vars, DECL_UID (decl))
2734 || !use_pointer_for_field (decl, ctx))
2735 continue;
2736 tree field = lookup_field (decl, ctx);
2737 if (TREE_CODE (TREE_TYPE (field)) == POINTER_TYPE
2738 && TREE_TYPE (TREE_TYPE (field)) == TREE_TYPE (decl))
2739 continue;
2740 TREE_TYPE (field) = build_pointer_type (TREE_TYPE (decl));
2741 TREE_THIS_VOLATILE (field) = 0;
2742 DECL_USER_ALIGN (field) = 0;
2743 DECL_ALIGN (field) = TYPE_ALIGN (TREE_TYPE (field));
2744 if (TYPE_ALIGN (ctx->record_type) < DECL_ALIGN (field))
2745 TYPE_ALIGN (ctx->record_type) = DECL_ALIGN (field);
2746 if (ctx->srecord_type)
2747 {
2748 tree sfield = lookup_sfield (decl, ctx);
2749 TREE_TYPE (sfield) = TREE_TYPE (field);
2750 TREE_THIS_VOLATILE (sfield) = 0;
2751 DECL_USER_ALIGN (sfield) = 0;
2752 DECL_ALIGN (sfield) = DECL_ALIGN (field);
2753 if (TYPE_ALIGN (ctx->srecord_type) < DECL_ALIGN (sfield))
2754 TYPE_ALIGN (ctx->srecord_type) = DECL_ALIGN (sfield);
2755 }
2756 }
2757 }
2758
2759 if (gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2760 {
2761 layout_type (ctx->record_type);
2762 fixup_child_record_type (ctx);
2763 }
fd6481cf 2764 else
2765 {
37eaded9 2766 location_t loc = gimple_location (ctx->stmt);
fd6481cf 2767 tree *p, vla_fields = NULL_TREE, *q = &vla_fields;
2768 /* Move VLA fields to the end. */
2769 p = &TYPE_FIELDS (ctx->record_type);
2770 while (*p)
2771 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p))
2772 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p))))
2773 {
2774 *q = *p;
2775 *p = TREE_CHAIN (*p);
2776 TREE_CHAIN (*q) = NULL_TREE;
2777 q = &TREE_CHAIN (*q);
2778 }
2779 else
1767a056 2780 p = &DECL_CHAIN (*p);
fd6481cf 2781 *p = vla_fields;
43895be5 2782 if (gimple_omp_task_taskloop_p (ctx->stmt))
2783 {
2784 /* Move fields corresponding to first and second _looptemp_
2785 clause first. There are filled by GOMP_taskloop
2786 and thus need to be in specific positions. */
2787 tree c1 = gimple_omp_task_clauses (ctx->stmt);
2788 c1 = find_omp_clause (c1, OMP_CLAUSE__LOOPTEMP_);
2789 tree c2 = find_omp_clause (OMP_CLAUSE_CHAIN (c1),
2790 OMP_CLAUSE__LOOPTEMP_);
2791 tree f1 = lookup_field (OMP_CLAUSE_DECL (c1), ctx);
2792 tree f2 = lookup_field (OMP_CLAUSE_DECL (c2), ctx);
2793 p = &TYPE_FIELDS (ctx->record_type);
2794 while (*p)
2795 if (*p == f1 || *p == f2)
2796 *p = DECL_CHAIN (*p);
2797 else
2798 p = &DECL_CHAIN (*p);
2799 DECL_CHAIN (f1) = f2;
2800 DECL_CHAIN (f2) = TYPE_FIELDS (ctx->record_type);
2801 TYPE_FIELDS (ctx->record_type) = f1;
2802 if (ctx->srecord_type)
2803 {
2804 f1 = lookup_sfield (OMP_CLAUSE_DECL (c1), ctx);
2805 f2 = lookup_sfield (OMP_CLAUSE_DECL (c2), ctx);
2806 p = &TYPE_FIELDS (ctx->srecord_type);
2807 while (*p)
2808 if (*p == f1 || *p == f2)
2809 *p = DECL_CHAIN (*p);
2810 else
2811 p = &DECL_CHAIN (*p);
2812 DECL_CHAIN (f1) = f2;
2813 DECL_CHAIN (f2) = TYPE_FIELDS (ctx->srecord_type);
2814 TYPE_FIELDS (ctx->srecord_type) = f1;
2815 }
2816 }
fd6481cf 2817 layout_type (ctx->record_type);
2818 fixup_child_record_type (ctx);
2819 if (ctx->srecord_type)
2820 layout_type (ctx->srecord_type);
37eaded9 2821 tree t = fold_convert_loc (loc, long_integer_type_node,
2822 TYPE_SIZE_UNIT (ctx->record_type));
2823 gimple_omp_task_set_arg_size (ctx->stmt, t);
75a70cf9 2824 t = build_int_cst (long_integer_type_node,
fd6481cf 2825 TYPE_ALIGN_UNIT (ctx->record_type));
37eaded9 2826 gimple_omp_task_set_arg_align (ctx->stmt, t);
fd6481cf 2827 }
2828}
2829
a8e785ba 2830/* Find the enclosing offload context. */
1e8e9920 2831
ca4c3545 2832static omp_context *
2833enclosing_target_ctx (omp_context *ctx)
2834{
a8e785ba 2835 for (; ctx; ctx = ctx->outer)
2836 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET)
2837 break;
2838
ca4c3545 2839 return ctx;
2840}
2841
a8e785ba 2842/* Return true if ctx is part of an oacc kernels region. */
2843
ca4c3545 2844static bool
a8e785ba 2845ctx_in_oacc_kernels_region (omp_context *ctx)
ca4c3545 2846{
a8e785ba 2847 for (;ctx != NULL; ctx = ctx->outer)
2848 {
2849 gimple *stmt = ctx->stmt;
2850 if (gimple_code (stmt) == GIMPLE_OMP_TARGET
2851 && gimple_omp_target_kind (stmt) == GF_OMP_TARGET_KIND_OACC_KERNELS)
2852 return true;
2853 }
2854
2855 return false;
2856}
2857
2858/* Check the parallelism clauses inside a kernels regions.
2859 Until kernels handling moves to use the same loop indirection
2860 scheme as parallel, we need to do this checking early. */
2861
2862static unsigned
2863check_oacc_kernel_gwv (gomp_for *stmt, omp_context *ctx)
2864{
2865 bool checking = true;
2866 unsigned outer_mask = 0;
2867 unsigned this_mask = 0;
2868 bool has_seq = false, has_auto = false;
2869
2870 if (ctx->outer)
2871 outer_mask = check_oacc_kernel_gwv (NULL, ctx->outer);
2872 if (!stmt)
2873 {
2874 checking = false;
2875 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR)
2876 return outer_mask;
2877 stmt = as_a <gomp_for *> (ctx->stmt);
2878 }
2879
2880 for (tree c = gimple_omp_for_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
2881 {
2882 switch (OMP_CLAUSE_CODE (c))
2883 {
2884 case OMP_CLAUSE_GANG:
2885 this_mask |= GOMP_DIM_MASK (GOMP_DIM_GANG);
2886 break;
2887 case OMP_CLAUSE_WORKER:
2888 this_mask |= GOMP_DIM_MASK (GOMP_DIM_WORKER);
2889 break;
2890 case OMP_CLAUSE_VECTOR:
2891 this_mask |= GOMP_DIM_MASK (GOMP_DIM_VECTOR);
2892 break;
2893 case OMP_CLAUSE_SEQ:
2894 has_seq = true;
2895 break;
2896 case OMP_CLAUSE_AUTO:
2897 has_auto = true;
2898 break;
2899 default:
2900 break;
2901 }
2902 }
2903
2904 if (checking)
2905 {
2906 if (has_seq && (this_mask || has_auto))
2907 error_at (gimple_location (stmt), "%<seq%> overrides other"
2908 " OpenACC loop specifiers");
2909 else if (has_auto && this_mask)
2910 error_at (gimple_location (stmt), "%<auto%> conflicts with other"
2911 " OpenACC loop specifiers");
2912
2913 if (this_mask & outer_mask)
2914 error_at (gimple_location (stmt), "inner loop uses same"
2915 " OpenACC parallelism as containing loop");
2916 }
2917
2918 return outer_mask | this_mask;
ca4c3545 2919}
2920
2921/* Scan a GIMPLE_OMP_FOR. */
1e8e9920 2922
2923static void
1a91d914 2924scan_omp_for (gomp_for *stmt, omp_context *outer_ctx)
1e8e9920 2925{
773c5ba7 2926 omp_context *ctx;
75a70cf9 2927 size_t i;
ca4c3545 2928 tree clauses = gimple_omp_for_clauses (stmt);
2929
773c5ba7 2930 ctx = new_omp_context (stmt, outer_ctx);
1e8e9920 2931
ca4c3545 2932 if (is_gimple_omp_oacc (stmt))
2933 {
a8e785ba 2934 omp_context *tgt = enclosing_target_ctx (outer_ctx);
2935
2936 if (!tgt || is_oacc_parallel (tgt))
2937 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2938 {
2939 char const *check = NULL;
2940
2941 switch (OMP_CLAUSE_CODE (c))
2942 {
2943 case OMP_CLAUSE_GANG:
2944 check = "gang";
2945 break;
2946
2947 case OMP_CLAUSE_WORKER:
2948 check = "worker";
2949 break;
2950
2951 case OMP_CLAUSE_VECTOR:
2952 check = "vector";
2953 break;
2954
2955 default:
2956 break;
2957 }
2958
2959 if (check && OMP_CLAUSE_OPERAND (c, 0))
2960 error_at (gimple_location (stmt),
2961 "argument not permitted on %qs clause in"
2962 " OpenACC %<parallel%>", check);
2963 }
2964
2965 if (tgt && is_oacc_kernels (tgt))
2966 {
2967 /* Strip out reductions, as they are not handled yet. */
2968 tree *prev_ptr = &clauses;
2969
2970 while (tree probe = *prev_ptr)
ca4c3545 2971 {
a8e785ba 2972 tree *next_ptr = &OMP_CLAUSE_CHAIN (probe);
2973
2974 if (OMP_CLAUSE_CODE (probe) == OMP_CLAUSE_REDUCTION)
2975 *prev_ptr = *next_ptr;
2976 else
2977 prev_ptr = next_ptr;
ca4c3545 2978 }
a8e785ba 2979
2980 gimple_omp_for_set_clauses (stmt, clauses);
2981 check_oacc_kernel_gwv (stmt, ctx);
ca4c3545 2982 }
2983 }
2984
2985 scan_sharing_clauses (clauses, ctx);
1e8e9920 2986
ab129075 2987 scan_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
75a70cf9 2988 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
fd6481cf 2989 {
75a70cf9 2990 scan_omp_op (gimple_omp_for_index_ptr (stmt, i), ctx);
2991 scan_omp_op (gimple_omp_for_initial_ptr (stmt, i), ctx);
2992 scan_omp_op (gimple_omp_for_final_ptr (stmt, i), ctx);
2993 scan_omp_op (gimple_omp_for_incr_ptr (stmt, i), ctx);
fd6481cf 2994 }
ab129075 2995 scan_omp (gimple_omp_body_ptr (stmt), ctx);
1e8e9920 2996}
2997
2998/* Scan an OpenMP sections directive. */
2999
3000static void
1a91d914 3001scan_omp_sections (gomp_sections *stmt, omp_context *outer_ctx)
1e8e9920 3002{
1e8e9920 3003 omp_context *ctx;
3004
3005 ctx = new_omp_context (stmt, outer_ctx);
75a70cf9 3006 scan_sharing_clauses (gimple_omp_sections_clauses (stmt), ctx);
ab129075 3007 scan_omp (gimple_omp_body_ptr (stmt), ctx);
1e8e9920 3008}
3009
3010/* Scan an OpenMP single directive. */
3011
3012static void
1a91d914 3013scan_omp_single (gomp_single *stmt, omp_context *outer_ctx)
1e8e9920 3014{
1e8e9920 3015 omp_context *ctx;
3016 tree name;
3017
3018 ctx = new_omp_context (stmt, outer_ctx);
3019 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
3020 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
3021 name = create_tmp_var_name (".omp_copy_s");
e60a6f7b 3022 name = build_decl (gimple_location (stmt),
3023 TYPE_DECL, name, ctx->record_type);
1e8e9920 3024 TYPE_NAME (ctx->record_type) = name;
3025
75a70cf9 3026 scan_sharing_clauses (gimple_omp_single_clauses (stmt), ctx);
ab129075 3027 scan_omp (gimple_omp_body_ptr (stmt), ctx);
1e8e9920 3028
3029 if (TYPE_FIELDS (ctx->record_type) == NULL)
3030 ctx->record_type = NULL;
3031 else
3032 layout_type (ctx->record_type);
3033}
3034
ca4c3545 3035/* Scan a GIMPLE_OMP_TARGET. */
bc7bff74 3036
3037static void
1a91d914 3038scan_omp_target (gomp_target *stmt, omp_context *outer_ctx)
bc7bff74 3039{
3040 omp_context *ctx;
3041 tree name;
ca4c3545 3042 bool offloaded = is_gimple_omp_offloaded (stmt);
3043 tree clauses = gimple_omp_target_clauses (stmt);
bc7bff74 3044
3045 ctx = new_omp_context (stmt, outer_ctx);
3046 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
3047 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
3048 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
3049 name = create_tmp_var_name (".omp_data_t");
3050 name = build_decl (gimple_location (stmt),
3051 TYPE_DECL, name, ctx->record_type);
3052 DECL_ARTIFICIAL (name) = 1;
3053 DECL_NAMELESS (name) = 1;
3054 TYPE_NAME (ctx->record_type) = name;
240131b5 3055 TYPE_ARTIFICIAL (ctx->record_type) = 1;
ca4c3545 3056 if (offloaded)
bc7bff74 3057 {
3058 create_omp_child_function (ctx, false);
3059 gimple_omp_target_set_child_fn (stmt, ctx->cb.dst_fn);
3060 }
3061
ca4c3545 3062 scan_sharing_clauses (clauses, ctx);
bc7bff74 3063 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3064
3065 if (TYPE_FIELDS (ctx->record_type) == NULL)
3066 ctx->record_type = ctx->receiver_decl = NULL;
3067 else
3068 {
3069 TYPE_FIELDS (ctx->record_type)
3070 = nreverse (TYPE_FIELDS (ctx->record_type));
382ecba7 3071 if (flag_checking)
3072 {
3073 unsigned int align = DECL_ALIGN (TYPE_FIELDS (ctx->record_type));
3074 for (tree field = TYPE_FIELDS (ctx->record_type);
3075 field;
3076 field = DECL_CHAIN (field))
3077 gcc_assert (DECL_ALIGN (field) == align);
3078 }
bc7bff74 3079 layout_type (ctx->record_type);
ca4c3545 3080 if (offloaded)
bc7bff74 3081 fixup_child_record_type (ctx);
3082 }
3083}
3084
3085/* Scan an OpenMP teams directive. */
3086
3087static void
1a91d914 3088scan_omp_teams (gomp_teams *stmt, omp_context *outer_ctx)
bc7bff74 3089{
3090 omp_context *ctx = new_omp_context (stmt, outer_ctx);
3091 scan_sharing_clauses (gimple_omp_teams_clauses (stmt), ctx);
3092 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3093}
1e8e9920 3094
ca4c3545 3095/* Check nesting restrictions. */
ab129075 3096static bool
42acab1c 3097check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx)
c1d127dd 3098{
43895be5 3099 tree c;
3100
ca4c3545 3101 /* No nesting of non-OpenACC STMT (that is, an OpenMP one, or a GOMP builtin)
3102 inside an OpenACC CTX. */
3103 if (!(is_gimple_omp (stmt)
3104 && is_gimple_omp_oacc (stmt)))
3105 {
7821c1b5 3106 for (omp_context *octx = ctx; octx != NULL; octx = octx->outer)
3107 if (is_gimple_omp (octx->stmt)
3108 && is_gimple_omp_oacc (octx->stmt)
9e10bfb7 3109 /* Except for atomic codes that we share with OpenMP. */
3110 && ! (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD
3111 || gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE))
ca4c3545 3112 {
3113 error_at (gimple_location (stmt),
3114 "non-OpenACC construct inside of OpenACC region");
3115 return false;
3116 }
3117 }
3118
3d483a94 3119 if (ctx != NULL)
3120 {
3121 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
10c55644 3122 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3d483a94 3123 {
43895be5 3124 c = NULL_TREE;
3125 if (gimple_code (stmt) == GIMPLE_OMP_ORDERED)
3126 {
3127 c = gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt));
7821c1b5 3128 if (find_omp_clause (c, OMP_CLAUSE_SIMD))
3129 {
3130 if (find_omp_clause (c, OMP_CLAUSE_THREADS)
3131 && (ctx->outer == NULL
3132 || !gimple_omp_for_combined_into_p (ctx->stmt)
3133 || gimple_code (ctx->outer->stmt) != GIMPLE_OMP_FOR
3134 || (gimple_omp_for_kind (ctx->outer->stmt)
3135 != GF_OMP_FOR_KIND_FOR)
3136 || !gimple_omp_for_combined_p (ctx->outer->stmt)))
3137 {
3138 error_at (gimple_location (stmt),
3139 "%<ordered simd threads%> must be closely "
3140 "nested inside of %<for simd%> region");
3141 return false;
3142 }
3143 return true;
3144 }
43895be5 3145 }
3d483a94 3146 error_at (gimple_location (stmt),
43895be5 3147 "OpenMP constructs other than %<#pragma omp ordered simd%>"
7821c1b5 3148 " may not be nested inside %<simd%> region");
3d483a94 3149 return false;
3150 }
bc7bff74 3151 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3152 {
3153 if ((gimple_code (stmt) != GIMPLE_OMP_FOR
3154 || (gimple_omp_for_kind (stmt)
3155 != GF_OMP_FOR_KIND_DISTRIBUTE))
3156 && gimple_code (stmt) != GIMPLE_OMP_PARALLEL)
3157 {
3158 error_at (gimple_location (stmt),
7821c1b5 3159 "only %<distribute%> or %<parallel%> regions are "
3160 "allowed to be strictly nested inside %<teams%> "
3161 "region");
bc7bff74 3162 return false;
3163 }
3164 }
3d483a94 3165 }
75a70cf9 3166 switch (gimple_code (stmt))
c1d127dd 3167 {
75a70cf9 3168 case GIMPLE_OMP_FOR:
10c55644 3169 if (gimple_omp_for_kind (stmt) & GF_OMP_FOR_SIMD)
3d483a94 3170 return true;
bc7bff74 3171 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
3172 {
3173 if (ctx != NULL && gimple_code (ctx->stmt) != GIMPLE_OMP_TEAMS)
3174 {
3175 error_at (gimple_location (stmt),
7821c1b5 3176 "%<distribute%> region must be strictly nested "
3177 "inside %<teams%> construct");
bc7bff74 3178 return false;
3179 }
3180 return true;
3181 }
43895be5 3182 /* We split taskloop into task and nested taskloop in it. */
3183 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_TASKLOOP)
3184 return true;
7a1ed40d 3185 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
3186 {
3187 bool ok = false;
3188
3189 if (ctx)
3190 switch (gimple_code (ctx->stmt))
3191 {
3192 case GIMPLE_OMP_FOR:
3193 ok = (gimple_omp_for_kind (ctx->stmt)
3194 == GF_OMP_FOR_KIND_OACC_LOOP);
3195 break;
3196
3197 case GIMPLE_OMP_TARGET:
3198 switch (gimple_omp_target_kind (ctx->stmt))
3199 {
3200 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
3201 case GF_OMP_TARGET_KIND_OACC_KERNELS:
3202 ok = true;
3203 break;
3204
3205 default:
3206 break;
3207 }
3208
3209 default:
3210 break;
3211 }
3212 else if (get_oacc_fn_attrib (current_function_decl))
3213 ok = true;
3214 if (!ok)
3215 {
3216 error_at (gimple_location (stmt),
3217 "OpenACC loop directive must be associated with"
3218 " an OpenACC compute region");
3219 return false;
3220 }
3221 }
bc7bff74 3222 /* FALLTHRU */
3223 case GIMPLE_CALL:
3224 if (is_gimple_call (stmt)
3225 && (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3226 == BUILT_IN_GOMP_CANCEL
3227 || DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3228 == BUILT_IN_GOMP_CANCELLATION_POINT))
3229 {
3230 const char *bad = NULL;
3231 const char *kind = NULL;
7821c1b5 3232 const char *construct
3233 = (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3234 == BUILT_IN_GOMP_CANCEL)
3235 ? "#pragma omp cancel"
3236 : "#pragma omp cancellation point";
bc7bff74 3237 if (ctx == NULL)
3238 {
3239 error_at (gimple_location (stmt), "orphaned %qs construct",
7821c1b5 3240 construct);
bc7bff74 3241 return false;
3242 }
6b409616 3243 switch (tree_fits_shwi_p (gimple_call_arg (stmt, 0))
3244 ? tree_to_shwi (gimple_call_arg (stmt, 0))
bc7bff74 3245 : 0)
3246 {
3247 case 1:
3248 if (gimple_code (ctx->stmt) != GIMPLE_OMP_PARALLEL)
3249 bad = "#pragma omp parallel";
3250 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3251 == BUILT_IN_GOMP_CANCEL
3252 && !integer_zerop (gimple_call_arg (stmt, 1)))
3253 ctx->cancellable = true;
3254 kind = "parallel";
3255 break;
3256 case 2:
3257 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
3258 || gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR)
3259 bad = "#pragma omp for";
3260 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3261 == BUILT_IN_GOMP_CANCEL
3262 && !integer_zerop (gimple_call_arg (stmt, 1)))
3263 {
3264 ctx->cancellable = true;
3265 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3266 OMP_CLAUSE_NOWAIT))
3267 warning_at (gimple_location (stmt), 0,
3268 "%<#pragma omp cancel for%> inside "
3269 "%<nowait%> for construct");
3270 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3271 OMP_CLAUSE_ORDERED))
3272 warning_at (gimple_location (stmt), 0,
3273 "%<#pragma omp cancel for%> inside "
3274 "%<ordered%> for construct");
3275 }
3276 kind = "for";
3277 break;
3278 case 4:
3279 if (gimple_code (ctx->stmt) != GIMPLE_OMP_SECTIONS
3280 && gimple_code (ctx->stmt) != GIMPLE_OMP_SECTION)
3281 bad = "#pragma omp sections";
3282 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3283 == BUILT_IN_GOMP_CANCEL
3284 && !integer_zerop (gimple_call_arg (stmt, 1)))
3285 {
3286 if (gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS)
3287 {
3288 ctx->cancellable = true;
3289 if (find_omp_clause (gimple_omp_sections_clauses
3290 (ctx->stmt),
3291 OMP_CLAUSE_NOWAIT))
3292 warning_at (gimple_location (stmt), 0,
3293 "%<#pragma omp cancel sections%> inside "
3294 "%<nowait%> sections construct");
3295 }
3296 else
3297 {
3298 gcc_assert (ctx->outer
3299 && gimple_code (ctx->outer->stmt)
3300 == GIMPLE_OMP_SECTIONS);
3301 ctx->outer->cancellable = true;
3302 if (find_omp_clause (gimple_omp_sections_clauses
3303 (ctx->outer->stmt),
3304 OMP_CLAUSE_NOWAIT))
3305 warning_at (gimple_location (stmt), 0,
3306 "%<#pragma omp cancel sections%> inside "
3307 "%<nowait%> sections construct");
3308 }
3309 }
3310 kind = "sections";
3311 break;
3312 case 8:
3313 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TASK)
3314 bad = "#pragma omp task";
3315 else
7821c1b5 3316 {
3317 for (omp_context *octx = ctx->outer;
3318 octx; octx = octx->outer)
3319 {
3320 switch (gimple_code (octx->stmt))
3321 {
3322 case GIMPLE_OMP_TASKGROUP:
3323 break;
3324 case GIMPLE_OMP_TARGET:
3325 if (gimple_omp_target_kind (octx->stmt)
3326 != GF_OMP_TARGET_KIND_REGION)
3327 continue;
3328 /* FALLTHRU */
3329 case GIMPLE_OMP_PARALLEL:
3330 case GIMPLE_OMP_TEAMS:
3331 error_at (gimple_location (stmt),
3332 "%<%s taskgroup%> construct not closely "
3333 "nested inside of %<taskgroup%> region",
3334 construct);
3335 return false;
3336 default:
3337 continue;
3338 }
3339 break;
3340 }
3341 ctx->cancellable = true;
3342 }
bc7bff74 3343 kind = "taskgroup";
3344 break;
3345 default:
3346 error_at (gimple_location (stmt), "invalid arguments");
3347 return false;
3348 }
3349 if (bad)
3350 {
3351 error_at (gimple_location (stmt),
3352 "%<%s %s%> construct not closely nested inside of %qs",
7821c1b5 3353 construct, kind, bad);
bc7bff74 3354 return false;
3355 }
3356 }
3d483a94 3357 /* FALLTHRU */
75a70cf9 3358 case GIMPLE_OMP_SECTIONS:
3359 case GIMPLE_OMP_SINGLE:
c1d127dd 3360 for (; ctx != NULL; ctx = ctx->outer)
75a70cf9 3361 switch (gimple_code (ctx->stmt))
c1d127dd 3362 {
75a70cf9 3363 case GIMPLE_OMP_FOR:
7821c1b5 3364 if (gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR
3365 && gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_TASKLOOP)
3366 break;
3367 /* FALLTHRU */
75a70cf9 3368 case GIMPLE_OMP_SECTIONS:
3369 case GIMPLE_OMP_SINGLE:
3370 case GIMPLE_OMP_ORDERED:
3371 case GIMPLE_OMP_MASTER:
3372 case GIMPLE_OMP_TASK:
bc7bff74 3373 case GIMPLE_OMP_CRITICAL:
75a70cf9 3374 if (is_gimple_call (stmt))
fd6481cf 3375 {
bc7bff74 3376 if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3377 != BUILT_IN_GOMP_BARRIER)
3378 return true;
ab129075 3379 error_at (gimple_location (stmt),
3380 "barrier region may not be closely nested inside "
7821c1b5 3381 "of work-sharing, %<critical%>, %<ordered%>, "
3382 "%<master%>, explicit %<task%> or %<taskloop%> "
3383 "region");
ab129075 3384 return false;
fd6481cf 3385 }
ab129075 3386 error_at (gimple_location (stmt),
3387 "work-sharing region may not be closely nested inside "
7821c1b5 3388 "of work-sharing, %<critical%>, %<ordered%>, "
3389 "%<master%>, explicit %<task%> or %<taskloop%> region");
ab129075 3390 return false;
75a70cf9 3391 case GIMPLE_OMP_PARALLEL:
7821c1b5 3392 case GIMPLE_OMP_TEAMS:
ab129075 3393 return true;
7821c1b5 3394 case GIMPLE_OMP_TARGET:
3395 if (gimple_omp_target_kind (ctx->stmt)
3396 == GF_OMP_TARGET_KIND_REGION)
3397 return true;
3398 break;
c1d127dd 3399 default:
3400 break;
3401 }
3402 break;
75a70cf9 3403 case GIMPLE_OMP_MASTER:
c1d127dd 3404 for (; ctx != NULL; ctx = ctx->outer)
75a70cf9 3405 switch (gimple_code (ctx->stmt))
c1d127dd 3406 {
75a70cf9 3407 case GIMPLE_OMP_FOR:
7821c1b5 3408 if (gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR
3409 && gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_TASKLOOP)
3410 break;
3411 /* FALLTHRU */
75a70cf9 3412 case GIMPLE_OMP_SECTIONS:
3413 case GIMPLE_OMP_SINGLE:
3414 case GIMPLE_OMP_TASK:
ab129075 3415 error_at (gimple_location (stmt),
7821c1b5 3416 "%<master%> region may not be closely nested inside "
3417 "of work-sharing, explicit %<task%> or %<taskloop%> "
3418 "region");
ab129075 3419 return false;
75a70cf9 3420 case GIMPLE_OMP_PARALLEL:
7821c1b5 3421 case GIMPLE_OMP_TEAMS:
ab129075 3422 return true;
7821c1b5 3423 case GIMPLE_OMP_TARGET:
3424 if (gimple_omp_target_kind (ctx->stmt)
3425 == GF_OMP_TARGET_KIND_REGION)
3426 return true;
3427 break;
c1d127dd 3428 default:
3429 break;
3430 }
3431 break;
43895be5 3432 case GIMPLE_OMP_TASK:
3433 for (c = gimple_omp_task_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
3434 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
3435 && (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE
3436 || OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK))
3437 {
3438 enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c);
3439 error_at (OMP_CLAUSE_LOCATION (c),
3440 "%<depend(%s)%> is only allowed in %<omp ordered%>",
3441 kind == OMP_CLAUSE_DEPEND_SOURCE ? "source" : "sink");
3442 return false;
3443 }
3444 break;
75a70cf9 3445 case GIMPLE_OMP_ORDERED:
43895be5 3446 for (c = gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt));
3447 c; c = OMP_CLAUSE_CHAIN (c))
3448 {
3449 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND)
3450 {
3451 gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_THREADS
7821c1b5 3452 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SIMD);
43895be5 3453 continue;
3454 }
3455 enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c);
3456 if (kind == OMP_CLAUSE_DEPEND_SOURCE
3457 || kind == OMP_CLAUSE_DEPEND_SINK)
3458 {
3459 tree oclause;
3460 /* Look for containing ordered(N) loop. */
3461 if (ctx == NULL
3462 || gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
3463 || (oclause
3464 = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3465 OMP_CLAUSE_ORDERED)) == NULL_TREE)
3466 {
3467 error_at (OMP_CLAUSE_LOCATION (c),
7821c1b5 3468 "%<ordered%> construct with %<depend%> clause "
3469 "must be closely nested inside an %<ordered%> "
3470 "loop");
43895be5 3471 return false;
3472 }
3473 else if (OMP_CLAUSE_ORDERED_EXPR (oclause) == NULL_TREE)
3474 {
3475 error_at (OMP_CLAUSE_LOCATION (c),
7821c1b5 3476 "%<ordered%> construct with %<depend%> clause "
3477 "must be closely nested inside a loop with "
3478 "%<ordered%> clause with a parameter");
43895be5 3479 return false;
3480 }
3481 }
3482 else
3483 {
3484 error_at (OMP_CLAUSE_LOCATION (c),
7821c1b5 3485 "invalid depend kind in omp %<ordered%> %<depend%>");
3486 return false;
3487 }
3488 }
3489 c = gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt));
3490 if (find_omp_clause (c, OMP_CLAUSE_SIMD))
3491 {
3492 /* ordered simd must be closely nested inside of simd region,
3493 and simd region must not encounter constructs other than
3494 ordered simd, therefore ordered simd may be either orphaned,
3495 or ctx->stmt must be simd. The latter case is handled already
3496 earlier. */
3497 if (ctx != NULL)
3498 {
3499 error_at (gimple_location (stmt),
3500 "%<ordered%> %<simd%> must be closely nested inside "
3501 "%<simd%> region");
43895be5 3502 return false;
3503 }
3504 }
c1d127dd 3505 for (; ctx != NULL; ctx = ctx->outer)
75a70cf9 3506 switch (gimple_code (ctx->stmt))
c1d127dd 3507 {
75a70cf9 3508 case GIMPLE_OMP_CRITICAL:
3509 case GIMPLE_OMP_TASK:
7821c1b5 3510 case GIMPLE_OMP_ORDERED:
3511 ordered_in_taskloop:
ab129075 3512 error_at (gimple_location (stmt),
7821c1b5 3513 "%<ordered%> region may not be closely nested inside "
3514 "of %<critical%>, %<ordered%>, explicit %<task%> or "
3515 "%<taskloop%> region");
ab129075 3516 return false;
75a70cf9 3517 case GIMPLE_OMP_FOR:
7821c1b5 3518 if (gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_TASKLOOP)
3519 goto ordered_in_taskloop;
75a70cf9 3520 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
c1d127dd 3521 OMP_CLAUSE_ORDERED) == NULL)
ab129075 3522 {
3523 error_at (gimple_location (stmt),
7821c1b5 3524 "%<ordered%> region must be closely nested inside "
3525 "a loop region with an %<ordered%> clause");
ab129075 3526 return false;
3527 }
3528 return true;
7821c1b5 3529 case GIMPLE_OMP_TARGET:
3530 if (gimple_omp_target_kind (ctx->stmt)
3531 != GF_OMP_TARGET_KIND_REGION)
3532 break;
3533 /* FALLTHRU */
75a70cf9 3534 case GIMPLE_OMP_PARALLEL:
7821c1b5 3535 case GIMPLE_OMP_TEAMS:
bc7bff74 3536 error_at (gimple_location (stmt),
7821c1b5 3537 "%<ordered%> region must be closely nested inside "
3538 "a loop region with an %<ordered%> clause");
bc7bff74 3539 return false;
c1d127dd 3540 default:
3541 break;
3542 }
3543 break;
75a70cf9 3544 case GIMPLE_OMP_CRITICAL:
1a91d914 3545 {
3546 tree this_stmt_name
3547 = gimple_omp_critical_name (as_a <gomp_critical *> (stmt));
3548 for (; ctx != NULL; ctx = ctx->outer)
3549 if (gomp_critical *other_crit
3550 = dyn_cast <gomp_critical *> (ctx->stmt))
3551 if (this_stmt_name == gimple_omp_critical_name (other_crit))
3552 {
3553 error_at (gimple_location (stmt),
7821c1b5 3554 "%<critical%> region may not be nested inside "
3555 "a %<critical%> region with the same name");
1a91d914 3556 return false;
3557 }
3558 }
c1d127dd 3559 break;
bc7bff74 3560 case GIMPLE_OMP_TEAMS:
3561 if (ctx == NULL
3562 || gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET
3563 || gimple_omp_target_kind (ctx->stmt) != GF_OMP_TARGET_KIND_REGION)
3564 {
3565 error_at (gimple_location (stmt),
7821c1b5 3566 "%<teams%> construct not closely nested inside of "
3567 "%<target%> construct");
bc7bff74 3568 return false;
3569 }
3570 break;
691447ab 3571 case GIMPLE_OMP_TARGET:
43895be5 3572 for (c = gimple_omp_target_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
3573 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
3574 && (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE
3575 || OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK))
3576 {
3577 enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c);
3578 error_at (OMP_CLAUSE_LOCATION (c),
3579 "%<depend(%s)%> is only allowed in %<omp ordered%>",
3580 kind == OMP_CLAUSE_DEPEND_SOURCE ? "source" : "sink");
3581 return false;
3582 }
691447ab 3583 for (; ctx != NULL; ctx = ctx->outer)
ca4c3545 3584 {
3585 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET)
3586 {
3587 if (is_gimple_omp (stmt)
3588 && is_gimple_omp_oacc (stmt)
3589 && is_gimple_omp (ctx->stmt))
3590 {
3591 error_at (gimple_location (stmt),
3592 "OpenACC construct inside of non-OpenACC region");
3593 return false;
3594 }
3595 continue;
3596 }
3597
3598 const char *stmt_name, *ctx_stmt_name;
3599 switch (gimple_omp_target_kind (stmt))
3600 {
3601 case GF_OMP_TARGET_KIND_REGION: stmt_name = "target"; break;
3602 case GF_OMP_TARGET_KIND_DATA: stmt_name = "target data"; break;
3603 case GF_OMP_TARGET_KIND_UPDATE: stmt_name = "target update"; break;
43895be5 3604 case GF_OMP_TARGET_KIND_ENTER_DATA:
3605 stmt_name = "target enter data"; break;
3606 case GF_OMP_TARGET_KIND_EXIT_DATA:
3607 stmt_name = "target exit data"; break;
ca4c3545 3608 case GF_OMP_TARGET_KIND_OACC_PARALLEL: stmt_name = "parallel"; break;
3609 case GF_OMP_TARGET_KIND_OACC_KERNELS: stmt_name = "kernels"; break;
3610 case GF_OMP_TARGET_KIND_OACC_DATA: stmt_name = "data"; break;
3611 case GF_OMP_TARGET_KIND_OACC_UPDATE: stmt_name = "update"; break;
43895be5 3612 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
3613 stmt_name = "enter/exit data"; break;
ca4c3545 3614 default: gcc_unreachable ();
3615 }
3616 switch (gimple_omp_target_kind (ctx->stmt))
3617 {
3618 case GF_OMP_TARGET_KIND_REGION: ctx_stmt_name = "target"; break;
3619 case GF_OMP_TARGET_KIND_DATA: ctx_stmt_name = "target data"; break;
43895be5 3620 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
3621 ctx_stmt_name = "parallel"; break;
3622 case GF_OMP_TARGET_KIND_OACC_KERNELS:
3623 ctx_stmt_name = "kernels"; break;
ca4c3545 3624 case GF_OMP_TARGET_KIND_OACC_DATA: ctx_stmt_name = "data"; break;
3625 default: gcc_unreachable ();
3626 }
3627
3628 /* OpenACC/OpenMP mismatch? */
3629 if (is_gimple_omp_oacc (stmt)
3630 != is_gimple_omp_oacc (ctx->stmt))
3631 {
3632 error_at (gimple_location (stmt),
7821c1b5 3633 "%s %qs construct inside of %s %qs region",
ca4c3545 3634 (is_gimple_omp_oacc (stmt)
3635 ? "OpenACC" : "OpenMP"), stmt_name,
3636 (is_gimple_omp_oacc (ctx->stmt)
3637 ? "OpenACC" : "OpenMP"), ctx_stmt_name);
3638 return false;
3639 }
3640 if (is_gimple_omp_offloaded (ctx->stmt))
3641 {
3642 /* No GIMPLE_OMP_TARGET inside offloaded OpenACC CTX. */
3643 if (is_gimple_omp_oacc (ctx->stmt))
3644 {
3645 error_at (gimple_location (stmt),
7821c1b5 3646 "%qs construct inside of %qs region",
ca4c3545 3647 stmt_name, ctx_stmt_name);
3648 return false;
3649 }
3650 else
3651 {
ca4c3545 3652 warning_at (gimple_location (stmt), 0,
7821c1b5 3653 "%qs construct inside of %qs region",
ca4c3545 3654 stmt_name, ctx_stmt_name);
3655 }
3656 }
3657 }
691447ab 3658 break;
c1d127dd 3659 default:
3660 break;
3661 }
ab129075 3662 return true;
c1d127dd 3663}
3664
3665
75a70cf9 3666/* Helper function scan_omp.
3667
3668 Callback for walk_tree or operators in walk_gimple_stmt used to
ca4c3545 3669 scan for OMP directives in TP. */
1e8e9920 3670
3671static tree
75a70cf9 3672scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
1e8e9920 3673{
4077bf7a 3674 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
3675 omp_context *ctx = (omp_context *) wi->info;
1e8e9920 3676 tree t = *tp;
3677
75a70cf9 3678 switch (TREE_CODE (t))
3679 {
3680 case VAR_DECL:
3681 case PARM_DECL:
3682 case LABEL_DECL:
3683 case RESULT_DECL:
3684 if (ctx)
3685 *tp = remap_decl (t, &ctx->cb);
3686 break;
3687
3688 default:
3689 if (ctx && TYPE_P (t))
3690 *tp = remap_type (t, &ctx->cb);
3691 else if (!DECL_P (t))
7cf869dd 3692 {
3693 *walk_subtrees = 1;
3694 if (ctx)
182cf5a9 3695 {
3696 tree tem = remap_type (TREE_TYPE (t), &ctx->cb);
3697 if (tem != TREE_TYPE (t))
3698 {
3699 if (TREE_CODE (t) == INTEGER_CST)
e913b5cd 3700 *tp = wide_int_to_tree (tem, t);
182cf5a9 3701 else
3702 TREE_TYPE (t) = tem;
3703 }
3704 }
7cf869dd 3705 }
75a70cf9 3706 break;
3707 }
3708
3709 return NULL_TREE;
3710}
3711
f2697631 3712/* Return true if FNDECL is a setjmp or a longjmp. */
3713
3714static bool
3715setjmp_or_longjmp_p (const_tree fndecl)
3716{
3717 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
3718 && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_SETJMP
3719 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LONGJMP))
3720 return true;
3721
3722 tree declname = DECL_NAME (fndecl);
3723 if (!declname)
3724 return false;
3725 const char *name = IDENTIFIER_POINTER (declname);
3726 return !strcmp (name, "setjmp") || !strcmp (name, "longjmp");
3727}
3728
75a70cf9 3729
3730/* Helper function for scan_omp.
3731
ca4c3545 3732 Callback for walk_gimple_stmt used to scan for OMP directives in
75a70cf9 3733 the current statement in GSI. */
3734
3735static tree
3736scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
3737 struct walk_stmt_info *wi)
3738{
42acab1c 3739 gimple *stmt = gsi_stmt (*gsi);
75a70cf9 3740 omp_context *ctx = (omp_context *) wi->info;
3741
3742 if (gimple_has_location (stmt))
3743 input_location = gimple_location (stmt);
1e8e9920 3744
ca4c3545 3745 /* Check the nesting restrictions. */
bc7bff74 3746 bool remove = false;
3747 if (is_gimple_omp (stmt))
3748 remove = !check_omp_nesting_restrictions (stmt, ctx);
3749 else if (is_gimple_call (stmt))
3750 {
3751 tree fndecl = gimple_call_fndecl (stmt);
f2697631 3752 if (fndecl)
3753 {
3754 if (setjmp_or_longjmp_p (fndecl)
3755 && ctx
3756 && gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
10c55644 3757 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
f2697631 3758 {
3759 remove = true;
3760 error_at (gimple_location (stmt),
3761 "setjmp/longjmp inside simd construct");
3762 }
3763 else if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
3764 switch (DECL_FUNCTION_CODE (fndecl))
3765 {
3766 case BUILT_IN_GOMP_BARRIER:
3767 case BUILT_IN_GOMP_CANCEL:
3768 case BUILT_IN_GOMP_CANCELLATION_POINT:
3769 case BUILT_IN_GOMP_TASKYIELD:
3770 case BUILT_IN_GOMP_TASKWAIT:
3771 case BUILT_IN_GOMP_TASKGROUP_START:
3772 case BUILT_IN_GOMP_TASKGROUP_END:
3773 remove = !check_omp_nesting_restrictions (stmt, ctx);
3774 break;
3775 default:
3776 break;
3777 }
3778 }
bc7bff74 3779 }
3780 if (remove)
3781 {
3782 stmt = gimple_build_nop ();
3783 gsi_replace (gsi, stmt, false);
fd6481cf 3784 }
c1d127dd 3785
75a70cf9 3786 *handled_ops_p = true;
3787
3788 switch (gimple_code (stmt))
1e8e9920 3789 {
75a70cf9 3790 case GIMPLE_OMP_PARALLEL:
fd6481cf 3791 taskreg_nesting_level++;
75a70cf9 3792 scan_omp_parallel (gsi, ctx);
fd6481cf 3793 taskreg_nesting_level--;
3794 break;
3795
75a70cf9 3796 case GIMPLE_OMP_TASK:
fd6481cf 3797 taskreg_nesting_level++;
75a70cf9 3798 scan_omp_task (gsi, ctx);
fd6481cf 3799 taskreg_nesting_level--;
1e8e9920 3800 break;
3801
75a70cf9 3802 case GIMPLE_OMP_FOR:
1a91d914 3803 scan_omp_for (as_a <gomp_for *> (stmt), ctx);
1e8e9920 3804 break;
3805
75a70cf9 3806 case GIMPLE_OMP_SECTIONS:
1a91d914 3807 scan_omp_sections (as_a <gomp_sections *> (stmt), ctx);
1e8e9920 3808 break;
3809
75a70cf9 3810 case GIMPLE_OMP_SINGLE:
1a91d914 3811 scan_omp_single (as_a <gomp_single *> (stmt), ctx);
1e8e9920 3812 break;
3813
75a70cf9 3814 case GIMPLE_OMP_SECTION:
3815 case GIMPLE_OMP_MASTER:
bc7bff74 3816 case GIMPLE_OMP_TASKGROUP:
75a70cf9 3817 case GIMPLE_OMP_ORDERED:
3818 case GIMPLE_OMP_CRITICAL:
3819 ctx = new_omp_context (stmt, ctx);
ab129075 3820 scan_omp (gimple_omp_body_ptr (stmt), ctx);
1e8e9920 3821 break;
3822
bc7bff74 3823 case GIMPLE_OMP_TARGET:
1a91d914 3824 scan_omp_target (as_a <gomp_target *> (stmt), ctx);
bc7bff74 3825 break;
3826
3827 case GIMPLE_OMP_TEAMS:
1a91d914 3828 scan_omp_teams (as_a <gomp_teams *> (stmt), ctx);
bc7bff74 3829 break;
3830
75a70cf9 3831 case GIMPLE_BIND:
1e8e9920 3832 {
3833 tree var;
1e8e9920 3834
75a70cf9 3835 *handled_ops_p = false;
3836 if (ctx)
1a91d914 3837 for (var = gimple_bind_vars (as_a <gbind *> (stmt));
3838 var ;
3839 var = DECL_CHAIN (var))
75a70cf9 3840 insert_decl_map (&ctx->cb, var, var);
1e8e9920 3841 }
3842 break;
1e8e9920 3843 default:
75a70cf9 3844 *handled_ops_p = false;
1e8e9920 3845 break;
3846 }
3847
3848 return NULL_TREE;
3849}
3850
3851
75a70cf9 3852/* Scan all the statements starting at the current statement. CTX
ca4c3545 3853 contains context information about the OMP directives and
75a70cf9 3854 clauses found during the scan. */
1e8e9920 3855
3856static void
ab129075 3857scan_omp (gimple_seq *body_p, omp_context *ctx)
1e8e9920 3858{
3859 location_t saved_location;
3860 struct walk_stmt_info wi;
3861
3862 memset (&wi, 0, sizeof (wi));
1e8e9920 3863 wi.info = ctx;
1e8e9920 3864 wi.want_locations = true;
3865
3866 saved_location = input_location;
ab129075 3867 walk_gimple_seq_mod (body_p, scan_omp_1_stmt, scan_omp_1_op, &wi);
1e8e9920 3868 input_location = saved_location;
3869}
3870\f
3871/* Re-gimplification and code generation routines. */
3872
3873/* Build a call to GOMP_barrier. */
3874
42acab1c 3875static gimple *
bc7bff74 3876build_omp_barrier (tree lhs)
3877{
3878 tree fndecl = builtin_decl_explicit (lhs ? BUILT_IN_GOMP_BARRIER_CANCEL
3879 : BUILT_IN_GOMP_BARRIER);
1a91d914 3880 gcall *g = gimple_build_call (fndecl, 0);
bc7bff74 3881 if (lhs)
3882 gimple_call_set_lhs (g, lhs);
3883 return g;
1e8e9920 3884}
3885
3886/* If a context was created for STMT when it was scanned, return it. */
3887
3888static omp_context *
42acab1c 3889maybe_lookup_ctx (gimple *stmt)
1e8e9920 3890{
3891 splay_tree_node n;
3892 n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
3893 return n ? (omp_context *) n->value : NULL;
3894}
3895
773c5ba7 3896
3897/* Find the mapping for DECL in CTX or the immediately enclosing
3898 context that has a mapping for DECL.
3899
3900 If CTX is a nested parallel directive, we may have to use the decl
3901 mappings created in CTX's parent context. Suppose that we have the
3902 following parallel nesting (variable UIDs showed for clarity):
3903
3904 iD.1562 = 0;
3905 #omp parallel shared(iD.1562) -> outer parallel
3906 iD.1562 = iD.1562 + 1;
3907
3908 #omp parallel shared (iD.1562) -> inner parallel
3909 iD.1562 = iD.1562 - 1;
3910
3911 Each parallel structure will create a distinct .omp_data_s structure
3912 for copying iD.1562 in/out of the directive:
3913
3914 outer parallel .omp_data_s.1.i -> iD.1562
3915 inner parallel .omp_data_s.2.i -> iD.1562
3916
3917 A shared variable mapping will produce a copy-out operation before
3918 the parallel directive and a copy-in operation after it. So, in
3919 this case we would have:
3920
3921 iD.1562 = 0;
3922 .omp_data_o.1.i = iD.1562;
3923 #omp parallel shared(iD.1562) -> outer parallel
3924 .omp_data_i.1 = &.omp_data_o.1
3925 .omp_data_i.1->i = .omp_data_i.1->i + 1;
3926
3927 .omp_data_o.2.i = iD.1562; -> **
3928 #omp parallel shared(iD.1562) -> inner parallel
3929 .omp_data_i.2 = &.omp_data_o.2
3930 .omp_data_i.2->i = .omp_data_i.2->i - 1;
3931
3932
3933 ** This is a problem. The symbol iD.1562 cannot be referenced
3934 inside the body of the outer parallel region. But since we are
3935 emitting this copy operation while expanding the inner parallel
3936 directive, we need to access the CTX structure of the outer
3937 parallel directive to get the correct mapping:
3938
3939 .omp_data_o.2.i = .omp_data_i.1->i
3940
3941 Since there may be other workshare or parallel directives enclosing
3942 the parallel directive, it may be necessary to walk up the context
3943 parent chain. This is not a problem in general because nested
3944 parallelism happens only rarely. */
3945
3946static tree
3947lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
3948{
3949 tree t;
3950 omp_context *up;
3951
773c5ba7 3952 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
3953 t = maybe_lookup_decl (decl, up);
3954
87b31375 3955 gcc_assert (!ctx->is_nested || t || is_global_var (decl));
773c5ba7 3956
c37594c7 3957 return t ? t : decl;
773c5ba7 3958}
3959
3960
f49d7bb5 3961/* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
3962 in outer contexts. */
3963
3964static tree
3965maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
3966{
3967 tree t = NULL;
3968 omp_context *up;
3969
87b31375 3970 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
3971 t = maybe_lookup_decl (decl, up);
f49d7bb5 3972
3973 return t ? t : decl;
3974}
3975
3976
df67b98c 3977/* Construct the initialization value for reduction operation OP. */
1e8e9920 3978
3979tree
df67b98c 3980omp_reduction_init_op (location_t loc, enum tree_code op, tree type)
1e8e9920 3981{
df67b98c 3982 switch (op)
1e8e9920 3983 {
3984 case PLUS_EXPR:
3985 case MINUS_EXPR:
3986 case BIT_IOR_EXPR:
3987 case BIT_XOR_EXPR:
3988 case TRUTH_OR_EXPR:
3989 case TRUTH_ORIF_EXPR:
3990 case TRUTH_XOR_EXPR:
3991 case NE_EXPR:
385f3f36 3992 return build_zero_cst (type);
1e8e9920 3993
3994 case MULT_EXPR:
3995 case TRUTH_AND_EXPR:
3996 case TRUTH_ANDIF_EXPR:
3997 case EQ_EXPR:
389dd41b 3998 return fold_convert_loc (loc, type, integer_one_node);
1e8e9920 3999
4000 case BIT_AND_EXPR:
389dd41b 4001 return fold_convert_loc (loc, type, integer_minus_one_node);
1e8e9920 4002
4003 case MAX_EXPR:
4004 if (SCALAR_FLOAT_TYPE_P (type))
4005 {
4006 REAL_VALUE_TYPE max, min;
fe994837 4007 if (HONOR_INFINITIES (type))
1e8e9920 4008 {
4009 real_inf (&max);
4010 real_arithmetic (&min, NEGATE_EXPR, &max, NULL);
4011 }
4012 else
4013 real_maxval (&min, 1, TYPE_MODE (type));
4014 return build_real (type, min);
4015 }
5902cce5 4016 else if (POINTER_TYPE_P (type))
4017 {
4018 wide_int min
4019 = wi::min_value (TYPE_PRECISION (type), TYPE_SIGN (type));
4020 return wide_int_to_tree (type, min);
4021 }
1e8e9920 4022 else
4023 {
4024 gcc_assert (INTEGRAL_TYPE_P (type));
4025 return TYPE_MIN_VALUE (type);
4026 }
4027
4028 case MIN_EXPR:
4029 if (SCALAR_FLOAT_TYPE_P (type))
4030 {
4031 REAL_VALUE_TYPE max;
fe994837 4032 if (HONOR_INFINITIES (type))
1e8e9920 4033 real_inf (&max);
4034 else
4035 real_maxval (&max, 0, TYPE_MODE (type));
4036 return build_real (type, max);
4037 }
5902cce5 4038 else if (POINTER_TYPE_P (type))
4039 {
4040 wide_int max
4041 = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type));
4042 return wide_int_to_tree (type, max);
4043 }
1e8e9920 4044 else
4045 {
4046 gcc_assert (INTEGRAL_TYPE_P (type));
4047 return TYPE_MAX_VALUE (type);
4048 }
4049
4050 default:
4051 gcc_unreachable ();
4052 }
4053}
4054
df67b98c 4055/* Construct the initialization value for reduction CLAUSE. */
4056
4057tree
4058omp_reduction_init (tree clause, tree type)
4059{
4060 return omp_reduction_init_op (OMP_CLAUSE_LOCATION (clause),
4061 OMP_CLAUSE_REDUCTION_CODE (clause), type);
4062}
4063
bc7bff74 4064/* Return alignment to be assumed for var in CLAUSE, which should be
4065 OMP_CLAUSE_ALIGNED. */
4066
4067static tree
4068omp_clause_aligned_alignment (tree clause)
4069{
4070 if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause))
4071 return OMP_CLAUSE_ALIGNED_ALIGNMENT (clause);
4072
4073 /* Otherwise return implementation defined alignment. */
4074 unsigned int al = 1;
3754d046 4075 machine_mode mode, vmode;
bc7bff74 4076 int vs = targetm.vectorize.autovectorize_vector_sizes ();
4077 if (vs)
4078 vs = 1 << floor_log2 (vs);
4079 static enum mode_class classes[]
4080 = { MODE_INT, MODE_VECTOR_INT, MODE_FLOAT, MODE_VECTOR_FLOAT };
4081 for (int i = 0; i < 4; i += 2)
4082 for (mode = GET_CLASS_NARROWEST_MODE (classes[i]);
4083 mode != VOIDmode;
4084 mode = GET_MODE_WIDER_MODE (mode))
4085 {
4086 vmode = targetm.vectorize.preferred_simd_mode (mode);
4087 if (GET_MODE_CLASS (vmode) != classes[i + 1])
4088 continue;
4089 while (vs
4090 && GET_MODE_SIZE (vmode) < vs
4091 && GET_MODE_2XWIDER_MODE (vmode) != VOIDmode)
4092 vmode = GET_MODE_2XWIDER_MODE (vmode);
4093
4094 tree type = lang_hooks.types.type_for_mode (mode, 1);
4095 if (type == NULL_TREE || TYPE_MODE (type) != mode)
4096 continue;
4097 type = build_vector_type (type, GET_MODE_SIZE (vmode)
4098 / GET_MODE_SIZE (mode));
4099 if (TYPE_MODE (type) != vmode)
4100 continue;
4101 if (TYPE_ALIGN_UNIT (type) > al)
4102 al = TYPE_ALIGN_UNIT (type);
4103 }
4104 return build_int_cst (integer_type_node, al);
4105}
4106
3d483a94 4107/* Return maximum possible vectorization factor for the target. */
4108
4109static int
4110omp_max_vf (void)
4111{
4112 if (!optimize
4113 || optimize_debug
ad45e43e 4114 || !flag_tree_loop_optimize
043115ec 4115 || (!flag_tree_loop_vectorize
4116 && (global_options_set.x_flag_tree_loop_vectorize
4117 || global_options_set.x_flag_tree_vectorize)))
3d483a94 4118 return 1;
4119
4120 int vs = targetm.vectorize.autovectorize_vector_sizes ();
4121 if (vs)
4122 {
4123 vs = 1 << floor_log2 (vs);
4124 return vs;
4125 }
3754d046 4126 machine_mode vqimode = targetm.vectorize.preferred_simd_mode (QImode);
3d483a94 4127 if (GET_MODE_CLASS (vqimode) == MODE_VECTOR_INT)
4128 return GET_MODE_NUNITS (vqimode);
4129 return 1;
4130}
4131
4132/* Helper function of lower_rec_input_clauses, used for #pragma omp simd
4133 privatization. */
4134
4135static bool
4136lower_rec_simd_input_clauses (tree new_var, omp_context *ctx, int &max_vf,
4137 tree &idx, tree &lane, tree &ivar, tree &lvar)
4138{
4139 if (max_vf == 0)
4140 {
4141 max_vf = omp_max_vf ();
4142 if (max_vf > 1)
4143 {
4144 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
4145 OMP_CLAUSE_SAFELEN);
c3f3b68d 4146 if (c && TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) != INTEGER_CST)
4147 max_vf = 1;
4148 else if (c && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
4149 max_vf) == -1)
d85a2013 4150 max_vf = tree_to_shwi (OMP_CLAUSE_SAFELEN_EXPR (c));
3d483a94 4151 }
4152 if (max_vf > 1)
4153 {
f9e245b2 4154 idx = create_tmp_var (unsigned_type_node);
4155 lane = create_tmp_var (unsigned_type_node);
3d483a94 4156 }
4157 }
4158 if (max_vf == 1)
4159 return false;
4160
4161 tree atype = build_array_type_nelts (TREE_TYPE (new_var), max_vf);
f9e245b2 4162 tree avar = create_tmp_var_raw (atype);
3d483a94 4163 if (TREE_ADDRESSABLE (new_var))
4164 TREE_ADDRESSABLE (avar) = 1;
4165 DECL_ATTRIBUTES (avar)
4166 = tree_cons (get_identifier ("omp simd array"), NULL,
4167 DECL_ATTRIBUTES (avar));
4168 gimple_add_tmp_var (avar);
4169 ivar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, idx,
4170 NULL_TREE, NULL_TREE);
4171 lvar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, lane,
4172 NULL_TREE, NULL_TREE);
bc7bff74 4173 if (DECL_P (new_var))
4174 {
4175 SET_DECL_VALUE_EXPR (new_var, lvar);
4176 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4177 }
3d483a94 4178 return true;
4179}
4180
2712b6de 4181/* Helper function of lower_rec_input_clauses. For a reference
4182 in simd reduction, add an underlying variable it will reference. */
4183
4184static void
4185handle_simd_reference (location_t loc, tree new_vard, gimple_seq *ilist)
4186{
4187 tree z = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard)));
4188 if (TREE_CONSTANT (z))
4189 {
43895be5 4190 z = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_vard)),
4191 get_name (new_vard));
2712b6de 4192 gimple_add_tmp_var (z);
4193 TREE_ADDRESSABLE (z) = 1;
4194 z = build_fold_addr_expr_loc (loc, z);
4195 gimplify_assign (new_vard, z, ilist);
4196 }
4197}
4198
1e8e9920 4199/* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
4200 from the receiver (aka child) side and initializers for REFERENCE_TYPE
4201 private variables. Initialization statements go in ILIST, while calls
4202 to destructors go in DLIST. */
4203
4204static void
75a70cf9 4205lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
bc7bff74 4206 omp_context *ctx, struct omp_for_data *fd)
1e8e9920 4207{
c2f47e15 4208 tree c, dtor, copyin_seq, x, ptr;
1e8e9920 4209 bool copyin_by_ref = false;
f49d7bb5 4210 bool lastprivate_firstprivate = false;
bc7bff74 4211 bool reduction_omp_orig_ref = false;
1e8e9920 4212 int pass;
3d483a94 4213 bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
10c55644 4214 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD);
3d483a94 4215 int max_vf = 0;
4216 tree lane = NULL_TREE, idx = NULL_TREE;
4217 tree ivar = NULL_TREE, lvar = NULL_TREE;
4218 gimple_seq llist[2] = { NULL, NULL };
1e8e9920 4219
1e8e9920 4220 copyin_seq = NULL;
4221
3d483a94 4222 /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
4223 with data sharing clauses referencing variable sized vars. That
4224 is unnecessarily hard to support and very unlikely to result in
4225 vectorized code anyway. */
4226 if (is_simd)
4227 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4228 switch (OMP_CLAUSE_CODE (c))
4229 {
9580cb79 4230 case OMP_CLAUSE_LINEAR:
4231 if (OMP_CLAUSE_LINEAR_ARRAY (c))
4232 max_vf = 1;
4233 /* FALLTHRU */
3d483a94 4234 case OMP_CLAUSE_PRIVATE:
4235 case OMP_CLAUSE_FIRSTPRIVATE:
4236 case OMP_CLAUSE_LASTPRIVATE:
3d483a94 4237 if (is_variable_sized (OMP_CLAUSE_DECL (c)))
4238 max_vf = 1;
4239 break;
43895be5 4240 case OMP_CLAUSE_REDUCTION:
4241 if (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF
4242 || is_variable_sized (OMP_CLAUSE_DECL (c)))
4243 max_vf = 1;
4244 break;
3d483a94 4245 default:
4246 continue;
4247 }
4248
1e8e9920 4249 /* Do all the fixed sized types in the first pass, and the variable sized
4250 types in the second pass. This makes sure that the scalar arguments to
48e1416a 4251 the variable sized types are processed before we use them in the
1e8e9920 4252 variable sized operations. */
4253 for (pass = 0; pass < 2; ++pass)
4254 {
4255 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4256 {
55d6e7cd 4257 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
1e8e9920 4258 tree var, new_var;
4259 bool by_ref;
389dd41b 4260 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
1e8e9920 4261
4262 switch (c_kind)
4263 {
4264 case OMP_CLAUSE_PRIVATE:
4265 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
4266 continue;
4267 break;
4268 case OMP_CLAUSE_SHARED:
bc7bff74 4269 /* Ignore shared directives in teams construct. */
4270 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
4271 continue;
f49d7bb5 4272 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
4273 {
43895be5 4274 gcc_assert (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c)
4275 || is_global_var (OMP_CLAUSE_DECL (c)));
f49d7bb5 4276 continue;
4277 }
1e8e9920 4278 case OMP_CLAUSE_FIRSTPRIVATE:
1e8e9920 4279 case OMP_CLAUSE_COPYIN:
43895be5 4280 break;
bc7bff74 4281 case OMP_CLAUSE_LINEAR:
43895be5 4282 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c)
4283 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
4284 lastprivate_firstprivate = true;
bc7bff74 4285 break;
1e8e9920 4286 case OMP_CLAUSE_REDUCTION:
bc7bff74 4287 if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
4288 reduction_omp_orig_ref = true;
1e8e9920 4289 break;
bc7bff74 4290 case OMP_CLAUSE__LOOPTEMP_:
43895be5 4291 /* Handle _looptemp_ clauses only on parallel/task. */
bc7bff74 4292 if (fd)
4293 continue;
3d483a94 4294 break;
df2c34fc 4295 case OMP_CLAUSE_LASTPRIVATE:
f49d7bb5 4296 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4297 {
4298 lastprivate_firstprivate = true;
43895be5 4299 if (pass != 0 || is_taskloop_ctx (ctx))
f49d7bb5 4300 continue;
4301 }
cf5f881f 4302 /* Even without corresponding firstprivate, if
4303 decl is Fortran allocatable, it needs outer var
4304 reference. */
4305 else if (pass == 0
4306 && lang_hooks.decls.omp_private_outer_ref
4307 (OMP_CLAUSE_DECL (c)))
4308 lastprivate_firstprivate = true;
df2c34fc 4309 break;
bc7bff74 4310 case OMP_CLAUSE_ALIGNED:
4311 if (pass == 0)
4312 continue;
4313 var = OMP_CLAUSE_DECL (c);
4314 if (TREE_CODE (TREE_TYPE (var)) == POINTER_TYPE
4315 && !is_global_var (var))
4316 {
4317 new_var = maybe_lookup_decl (var, ctx);
4318 if (new_var == NULL_TREE)
4319 new_var = maybe_lookup_decl_in_outer_ctx (var, ctx);
4320 x = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
4321 x = build_call_expr_loc (clause_loc, x, 2, new_var,
4322 omp_clause_aligned_alignment (c));
4323 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
4324 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
4325 gimplify_and_add (x, ilist);
4326 }
4327 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
4328 && is_global_var (var))
4329 {
4330 tree ptype = build_pointer_type (TREE_TYPE (var)), t, t2;
4331 new_var = lookup_decl (var, ctx);
4332 t = maybe_lookup_decl_in_outer_ctx (var, ctx);
4333 t = build_fold_addr_expr_loc (clause_loc, t);
4334 t2 = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
4335 t = build_call_expr_loc (clause_loc, t2, 2, t,
4336 omp_clause_aligned_alignment (c));
4337 t = fold_convert_loc (clause_loc, ptype, t);
f9e245b2 4338 x = create_tmp_var (ptype);
bc7bff74 4339 t = build2 (MODIFY_EXPR, ptype, x, t);
4340 gimplify_and_add (t, ilist);
4341 t = build_simple_mem_ref_loc (clause_loc, x);
4342 SET_DECL_VALUE_EXPR (new_var, t);
4343 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4344 }
4345 continue;
1e8e9920 4346 default:
4347 continue;
4348 }
4349
4350 new_var = var = OMP_CLAUSE_DECL (c);
43895be5 4351 if (c_kind == OMP_CLAUSE_REDUCTION && TREE_CODE (var) == MEM_REF)
4352 {
4353 var = TREE_OPERAND (var, 0);
9561765e 4354 if (TREE_CODE (var) == POINTER_PLUS_EXPR)
4355 var = TREE_OPERAND (var, 0);
43895be5 4356 if (TREE_CODE (var) == INDIRECT_REF
4357 || TREE_CODE (var) == ADDR_EXPR)
4358 var = TREE_OPERAND (var, 0);
4359 if (is_variable_sized (var))
4360 {
4361 gcc_assert (DECL_HAS_VALUE_EXPR_P (var));
4362 var = DECL_VALUE_EXPR (var);
4363 gcc_assert (TREE_CODE (var) == INDIRECT_REF);
4364 var = TREE_OPERAND (var, 0);
4365 gcc_assert (DECL_P (var));
4366 }
4367 new_var = var;
4368 }
1e8e9920 4369 if (c_kind != OMP_CLAUSE_COPYIN)
4370 new_var = lookup_decl (var, ctx);
4371
4372 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
4373 {
4374 if (pass != 0)
4375 continue;
4376 }
43895be5 4377 /* C/C++ array section reductions. */
4378 else if (c_kind == OMP_CLAUSE_REDUCTION
4379 && var != OMP_CLAUSE_DECL (c))
1e8e9920 4380 {
4381 if (pass == 0)
4382 continue;
4383
9561765e 4384 tree bias = TREE_OPERAND (OMP_CLAUSE_DECL (c), 1);
43895be5 4385 tree orig_var = TREE_OPERAND (OMP_CLAUSE_DECL (c), 0);
9561765e 4386 if (TREE_CODE (orig_var) == POINTER_PLUS_EXPR)
4387 {
4388 tree b = TREE_OPERAND (orig_var, 1);
4389 b = maybe_lookup_decl (b, ctx);
4390 if (b == NULL)
4391 {
4392 b = TREE_OPERAND (orig_var, 1);
4393 b = maybe_lookup_decl_in_outer_ctx (b, ctx);
4394 }
4395 if (integer_zerop (bias))
4396 bias = b;
4397 else
4398 {
4399 bias = fold_convert_loc (clause_loc,
4400 TREE_TYPE (b), bias);
4401 bias = fold_build2_loc (clause_loc, PLUS_EXPR,
4402 TREE_TYPE (b), b, bias);
4403 }
4404 orig_var = TREE_OPERAND (orig_var, 0);
4405 }
43895be5 4406 if (TREE_CODE (orig_var) == INDIRECT_REF
4407 || TREE_CODE (orig_var) == ADDR_EXPR)
4408 orig_var = TREE_OPERAND (orig_var, 0);
4409 tree d = OMP_CLAUSE_DECL (c);
4410 tree type = TREE_TYPE (d);
4411 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
4412 tree v = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
4413 const char *name = get_name (orig_var);
4414 if (TREE_CONSTANT (v))
fd6481cf 4415 {
43895be5 4416 x = create_tmp_var_raw (type, name);
4417 gimple_add_tmp_var (x);
4418 TREE_ADDRESSABLE (x) = 1;
4419 x = build_fold_addr_expr_loc (clause_loc, x);
4420 }
4421 else
4422 {
4423 tree atmp
4424 = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
4425 tree t = maybe_lookup_decl (v, ctx);
4426 if (t)
4427 v = t;
4428 else
4429 v = maybe_lookup_decl_in_outer_ctx (v, ctx);
4430 gimplify_expr (&v, ilist, NULL, is_gimple_val, fb_rvalue);
4431 t = fold_build2_loc (clause_loc, PLUS_EXPR,
4432 TREE_TYPE (v), v,
4433 build_int_cst (TREE_TYPE (v), 1));
4434 t = fold_build2_loc (clause_loc, MULT_EXPR,
4435 TREE_TYPE (v), t,
4436 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4437 tree al = size_int (TYPE_ALIGN (TREE_TYPE (type)));
4438 x = build_call_expr_loc (clause_loc, atmp, 2, t, al);
4439 }
4440
4441 tree ptype = build_pointer_type (TREE_TYPE (type));
4442 x = fold_convert_loc (clause_loc, ptype, x);
4443 tree y = create_tmp_var (ptype, name);
4444 gimplify_assign (y, x, ilist);
4445 x = y;
9561765e 4446 tree yb = y;
4447
4448 if (!integer_zerop (bias))
4449 {
219e09fc 4450 bias = fold_convert_loc (clause_loc, pointer_sized_int_node,
4451 bias);
4452 yb = fold_convert_loc (clause_loc, pointer_sized_int_node,
4453 x);
4454 yb = fold_build2_loc (clause_loc, MINUS_EXPR,
4455 pointer_sized_int_node, yb, bias);
4456 x = fold_convert_loc (clause_loc, TREE_TYPE (x), yb);
9561765e 4457 yb = create_tmp_var (ptype, name);
4458 gimplify_assign (yb, x, ilist);
4459 x = yb;
4460 }
4461
4462 d = TREE_OPERAND (d, 0);
4463 if (TREE_CODE (d) == POINTER_PLUS_EXPR)
4464 d = TREE_OPERAND (d, 0);
4465 if (TREE_CODE (d) == ADDR_EXPR)
43895be5 4466 {
4467 if (orig_var != var)
4468 {
4469 gcc_assert (is_variable_sized (orig_var));
4470 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var),
4471 x);
4472 gimplify_assign (new_var, x, ilist);
4473 tree new_orig_var = lookup_decl (orig_var, ctx);
4474 tree t = build_fold_indirect_ref (new_var);
4475 DECL_IGNORED_P (new_var) = 0;
4476 TREE_THIS_NOTRAP (t);
4477 SET_DECL_VALUE_EXPR (new_orig_var, t);
4478 DECL_HAS_VALUE_EXPR_P (new_orig_var) = 1;
4479 }
4480 else
4481 {
4482 x = build2 (MEM_REF, TREE_TYPE (new_var), x,
4483 build_int_cst (ptype, 0));
4484 SET_DECL_VALUE_EXPR (new_var, x);
4485 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4486 }
4487 }
4488 else
4489 {
4490 gcc_assert (orig_var == var);
9561765e 4491 if (TREE_CODE (d) == INDIRECT_REF)
43895be5 4492 {
4493 x = create_tmp_var (ptype, name);
4494 TREE_ADDRESSABLE (x) = 1;
9561765e 4495 gimplify_assign (x, yb, ilist);
43895be5 4496 x = build_fold_addr_expr_loc (clause_loc, x);
4497 }
4498 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
4499 gimplify_assign (new_var, x, ilist);
4500 }
4501 tree y1 = create_tmp_var (ptype, NULL);
4502 gimplify_assign (y1, y, ilist);
4503 tree i2 = NULL_TREE, y2 = NULL_TREE;
4504 tree body2 = NULL_TREE, end2 = NULL_TREE;
4505 tree y3 = NULL_TREE, y4 = NULL_TREE;
4506 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) || is_simd)
4507 {
4508 y2 = create_tmp_var (ptype, NULL);
4509 gimplify_assign (y2, y, ilist);
4510 tree ref = build_outer_var_ref (var, ctx);
4511 /* For ref build_outer_var_ref already performs this. */
9561765e 4512 if (TREE_CODE (d) == INDIRECT_REF)
43895be5 4513 gcc_assert (is_reference (var));
9561765e 4514 else if (TREE_CODE (d) == ADDR_EXPR)
43895be5 4515 ref = build_fold_addr_expr (ref);
4516 else if (is_reference (var))
4517 ref = build_fold_addr_expr (ref);
4518 ref = fold_convert_loc (clause_loc, ptype, ref);
4519 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
4520 && OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
4521 {
4522 y3 = create_tmp_var (ptype, NULL);
4523 gimplify_assign (y3, unshare_expr (ref), ilist);
4524 }
4525 if (is_simd)
4526 {
4527 y4 = create_tmp_var (ptype, NULL);
4528 gimplify_assign (y4, ref, dlist);
4529 }
4530 }
4531 tree i = create_tmp_var (TREE_TYPE (v), NULL);
4532 gimplify_assign (i, build_int_cst (TREE_TYPE (v), 0), ilist);
4533 tree body = create_artificial_label (UNKNOWN_LOCATION);
4534 tree end = create_artificial_label (UNKNOWN_LOCATION);
4535 gimple_seq_add_stmt (ilist, gimple_build_label (body));
4536 if (y2)
4537 {
4538 i2 = create_tmp_var (TREE_TYPE (v), NULL);
4539 gimplify_assign (i2, build_int_cst (TREE_TYPE (v), 0), dlist);
4540 body2 = create_artificial_label (UNKNOWN_LOCATION);
4541 end2 = create_artificial_label (UNKNOWN_LOCATION);
4542 gimple_seq_add_stmt (dlist, gimple_build_label (body2));
4543 }
4544 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4545 {
4546 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
4547 tree decl_placeholder
4548 = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c);
4549 SET_DECL_VALUE_EXPR (decl_placeholder,
4550 build_simple_mem_ref (y1));
4551 DECL_HAS_VALUE_EXPR_P (decl_placeholder) = 1;
4552 SET_DECL_VALUE_EXPR (placeholder,
4553 y3 ? build_simple_mem_ref (y3)
4554 : error_mark_node);
4555 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
4556 x = lang_hooks.decls.omp_clause_default_ctor
4557 (c, build_simple_mem_ref (y1),
4558 y3 ? build_simple_mem_ref (y3) : NULL_TREE);
4559 if (x)
4560 gimplify_and_add (x, ilist);
4561 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
4562 {
4563 gimple_seq tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
4564 lower_omp (&tseq, ctx);
4565 gimple_seq_add_seq (ilist, tseq);
4566 }
4567 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
4568 if (is_simd)
4569 {
4570 SET_DECL_VALUE_EXPR (decl_placeholder,
4571 build_simple_mem_ref (y2));
4572 SET_DECL_VALUE_EXPR (placeholder,
4573 build_simple_mem_ref (y4));
4574 gimple_seq tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
4575 lower_omp (&tseq, ctx);
4576 gimple_seq_add_seq (dlist, tseq);
4577 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4578 }
4579 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
4580 DECL_HAS_VALUE_EXPR_P (decl_placeholder) = 0;
4581 x = lang_hooks.decls.omp_clause_dtor
4582 (c, build_simple_mem_ref (y2));
4583 if (x)
4584 {
4585 gimple_seq tseq = NULL;
4586 dtor = x;
4587 gimplify_stmt (&dtor, &tseq);
4588 gimple_seq_add_seq (dlist, tseq);
4589 }
4590 }
4591 else
4592 {
4593 x = omp_reduction_init (c, TREE_TYPE (type));
4594 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
4595
4596 /* reduction(-:var) sums up the partial results, so it
4597 acts identically to reduction(+:var). */
4598 if (code == MINUS_EXPR)
4599 code = PLUS_EXPR;
4600
4601 gimplify_assign (build_simple_mem_ref (y1), x, ilist);
4602 if (is_simd)
4603 {
4604 x = build2 (code, TREE_TYPE (type),
4605 build_simple_mem_ref (y4),
4606 build_simple_mem_ref (y2));
4607 gimplify_assign (build_simple_mem_ref (y4), x, dlist);
4608 }
4609 }
4610 gimple *g
4611 = gimple_build_assign (y1, POINTER_PLUS_EXPR, y1,
4612 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4613 gimple_seq_add_stmt (ilist, g);
4614 if (y3)
4615 {
4616 g = gimple_build_assign (y3, POINTER_PLUS_EXPR, y3,
4617 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4618 gimple_seq_add_stmt (ilist, g);
4619 }
4620 g = gimple_build_assign (i, PLUS_EXPR, i,
4621 build_int_cst (TREE_TYPE (i), 1));
4622 gimple_seq_add_stmt (ilist, g);
4623 g = gimple_build_cond (LE_EXPR, i, v, body, end);
4624 gimple_seq_add_stmt (ilist, g);
4625 gimple_seq_add_stmt (ilist, gimple_build_label (end));
4626 if (y2)
4627 {
4628 g = gimple_build_assign (y2, POINTER_PLUS_EXPR, y2,
4629 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4630 gimple_seq_add_stmt (dlist, g);
4631 if (y4)
4632 {
4633 g = gimple_build_assign
4634 (y4, POINTER_PLUS_EXPR, y4,
4635 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4636 gimple_seq_add_stmt (dlist, g);
4637 }
4638 g = gimple_build_assign (i2, PLUS_EXPR, i2,
4639 build_int_cst (TREE_TYPE (i2), 1));
4640 gimple_seq_add_stmt (dlist, g);
4641 g = gimple_build_cond (LE_EXPR, i2, v, body2, end2);
4642 gimple_seq_add_stmt (dlist, g);
4643 gimple_seq_add_stmt (dlist, gimple_build_label (end2));
4644 }
4645 continue;
4646 }
4647 else if (is_variable_sized (var))
4648 {
4649 /* For variable sized types, we need to allocate the
4650 actual storage here. Call alloca and store the
4651 result in the pointer decl that we created elsewhere. */
4652 if (pass == 0)
4653 continue;
4654
4655 if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
4656 {
4657 gcall *stmt;
4658 tree tmp, atmp;
4659
4660 ptr = DECL_VALUE_EXPR (new_var);
4661 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
4662 ptr = TREE_OPERAND (ptr, 0);
fd6481cf 4663 gcc_assert (DECL_P (ptr));
4664 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
75a70cf9 4665
4666 /* void *tmp = __builtin_alloca */
43895be5 4667 atmp = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
4668 stmt = gimple_build_call (atmp, 2, x,
4669 size_int (DECL_ALIGN (var)));
f9e245b2 4670 tmp = create_tmp_var_raw (ptr_type_node);
75a70cf9 4671 gimple_add_tmp_var (tmp);
4672 gimple_call_set_lhs (stmt, tmp);
4673
4674 gimple_seq_add_stmt (ilist, stmt);
4675
389dd41b 4676 x = fold_convert_loc (clause_loc, TREE_TYPE (ptr), tmp);
75a70cf9 4677 gimplify_assign (ptr, x, ilist);
fd6481cf 4678 }
1e8e9920 4679 }
b656be3a 4680 else if (is_reference (var) && !is_oacc_parallel (ctx))
1e8e9920 4681 {
773c5ba7 4682 /* For references that are being privatized for Fortran,
4683 allocate new backing storage for the new pointer
4684 variable. This allows us to avoid changing all the
4685 code that expects a pointer to something that expects
bc7bff74 4686 a direct variable. */
1e8e9920 4687 if (pass == 0)
4688 continue;
4689
4690 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
fd6481cf 4691 if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx))
4692 {
4693 x = build_receiver_ref (var, false, ctx);
389dd41b 4694 x = build_fold_addr_expr_loc (clause_loc, x);
fd6481cf 4695 }
4696 else if (TREE_CONSTANT (x))
1e8e9920 4697 {
2712b6de 4698 /* For reduction in SIMD loop, defer adding the
4699 initialization of the reference, because if we decide
4700 to use SIMD array for it, the initilization could cause
4701 expansion ICE. */
4702 if (c_kind == OMP_CLAUSE_REDUCTION && is_simd)
09d1c205 4703 x = NULL_TREE;
4704 else
4705 {
09d1c205 4706 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
43895be5 4707 get_name (var));
09d1c205 4708 gimple_add_tmp_var (x);
4709 TREE_ADDRESSABLE (x) = 1;
4710 x = build_fold_addr_expr_loc (clause_loc, x);
4711 }
1e8e9920 4712 }
4713 else
4714 {
43895be5 4715 tree atmp
4716 = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
4717 tree rtype = TREE_TYPE (TREE_TYPE (new_var));
4718 tree al = size_int (TYPE_ALIGN (rtype));
4719 x = build_call_expr_loc (clause_loc, atmp, 2, x, al);
1e8e9920 4720 }
4721
09d1c205 4722 if (x)
4723 {
4724 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
4725 gimplify_assign (new_var, x, ilist);
4726 }
1e8e9920 4727
182cf5a9 4728 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
1e8e9920 4729 }
4730 else if (c_kind == OMP_CLAUSE_REDUCTION
4731 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4732 {
4733 if (pass == 0)
4734 continue;
4735 }
4736 else if (pass != 0)
4737 continue;
4738
55d6e7cd 4739 switch (OMP_CLAUSE_CODE (c))
1e8e9920 4740 {
4741 case OMP_CLAUSE_SHARED:
bc7bff74 4742 /* Ignore shared directives in teams construct. */
4743 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
4744 continue;
f49d7bb5 4745 /* Shared global vars are just accessed directly. */
4746 if (is_global_var (new_var))
4747 break;
43895be5 4748 /* For taskloop firstprivate/lastprivate, represented
4749 as firstprivate and shared clause on the task, new_var
4750 is the firstprivate var. */
4751 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
4752 break;
1e8e9920 4753 /* Set up the DECL_VALUE_EXPR for shared variables now. This
4754 needs to be delayed until after fixup_child_record_type so
4755 that we get the correct type during the dereference. */
e8a588af 4756 by_ref = use_pointer_for_field (var, ctx);
1e8e9920 4757 x = build_receiver_ref (var, by_ref, ctx);
4758 SET_DECL_VALUE_EXPR (new_var, x);
4759 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4760
4761 /* ??? If VAR is not passed by reference, and the variable
4762 hasn't been initialized yet, then we'll get a warning for
4763 the store into the omp_data_s structure. Ideally, we'd be
48e1416a 4764 able to notice this and not store anything at all, but
1e8e9920 4765 we're generating code too early. Suppress the warning. */
4766 if (!by_ref)
4767 TREE_NO_WARNING (var) = 1;
4768 break;
4769
4770 case OMP_CLAUSE_LASTPRIVATE:
4771 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4772 break;
4773 /* FALLTHRU */
4774
4775 case OMP_CLAUSE_PRIVATE:
fd6481cf 4776 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE)
4777 x = build_outer_var_ref (var, ctx);
4778 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
4779 {
4780 if (is_task_ctx (ctx))
4781 x = build_receiver_ref (var, false, ctx);
4782 else
4783 x = build_outer_var_ref (var, ctx);
4784 }
4785 else
4786 x = NULL;
3d483a94 4787 do_private:
bc7bff74 4788 tree nx;
43895be5 4789 nx = lang_hooks.decls.omp_clause_default_ctor
4790 (c, unshare_expr (new_var), x);
3d483a94 4791 if (is_simd)
4792 {
4793 tree y = lang_hooks.decls.omp_clause_dtor (c, new_var);
bc7bff74 4794 if ((TREE_ADDRESSABLE (new_var) || nx || y
3d483a94 4795 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
4796 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4797 idx, lane, ivar, lvar))
4798 {
bc7bff74 4799 if (nx)
3d483a94 4800 x = lang_hooks.decls.omp_clause_default_ctor
4801 (c, unshare_expr (ivar), x);
bc7bff74 4802 if (nx && x)
3d483a94 4803 gimplify_and_add (x, &llist[0]);
4804 if (y)
4805 {
4806 y = lang_hooks.decls.omp_clause_dtor (c, ivar);
4807 if (y)
4808 {
4809 gimple_seq tseq = NULL;
4810
4811 dtor = y;
4812 gimplify_stmt (&dtor, &tseq);
4813 gimple_seq_add_seq (&llist[1], tseq);
4814 }
4815 }
4816 break;
4817 }
4818 }
bc7bff74 4819 if (nx)
4820 gimplify_and_add (nx, ilist);
1e8e9920 4821 /* FALLTHRU */
4822
4823 do_dtor:
4824 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
4825 if (x)
4826 {
75a70cf9 4827 gimple_seq tseq = NULL;
4828
1e8e9920 4829 dtor = x;
75a70cf9 4830 gimplify_stmt (&dtor, &tseq);
e3a19533 4831 gimple_seq_add_seq (dlist, tseq);
1e8e9920 4832 }
4833 break;
4834
3d483a94 4835 case OMP_CLAUSE_LINEAR:
4836 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c))
4837 goto do_firstprivate;
4838 if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
4839 x = NULL;
4840 else
4841 x = build_outer_var_ref (var, ctx);
4842 goto do_private;
4843
1e8e9920 4844 case OMP_CLAUSE_FIRSTPRIVATE:
fd6481cf 4845 if (is_task_ctx (ctx))
4846 {
4847 if (is_reference (var) || is_variable_sized (var))
4848 goto do_dtor;
4849 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var,
4850 ctx))
4851 || use_pointer_for_field (var, NULL))
4852 {
4853 x = build_receiver_ref (var, false, ctx);
4854 SET_DECL_VALUE_EXPR (new_var, x);
4855 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4856 goto do_dtor;
4857 }
4858 }
3d483a94 4859 do_firstprivate:
1e8e9920 4860 x = build_outer_var_ref (var, ctx);
3d483a94 4861 if (is_simd)
4862 {
bc7bff74 4863 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
4864 && gimple_omp_for_combined_into_p (ctx->stmt))
4865 {
9580cb79 4866 tree t = OMP_CLAUSE_LINEAR_STEP (c);
4867 tree stept = TREE_TYPE (t);
4868 tree ct = find_omp_clause (clauses,
4869 OMP_CLAUSE__LOOPTEMP_);
4870 gcc_assert (ct);
4871 tree l = OMP_CLAUSE_DECL (ct);
e471cc6f 4872 tree n1 = fd->loop.n1;
4873 tree step = fd->loop.step;
4874 tree itype = TREE_TYPE (l);
4875 if (POINTER_TYPE_P (itype))
4876 itype = signed_type_for (itype);
4877 l = fold_build2 (MINUS_EXPR, itype, l, n1);
4878 if (TYPE_UNSIGNED (itype)
4879 && fd->loop.cond_code == GT_EXPR)
4880 l = fold_build2 (TRUNC_DIV_EXPR, itype,
4881 fold_build1 (NEGATE_EXPR, itype, l),
4882 fold_build1 (NEGATE_EXPR,
4883 itype, step));
4884 else
4885 l = fold_build2 (TRUNC_DIV_EXPR, itype, l, step);
bc7bff74 4886 t = fold_build2 (MULT_EXPR, stept,
4887 fold_convert (stept, l), t);
9580cb79 4888
4889 if (OMP_CLAUSE_LINEAR_ARRAY (c))
4890 {
4891 x = lang_hooks.decls.omp_clause_linear_ctor
4892 (c, new_var, x, t);
4893 gimplify_and_add (x, ilist);
4894 goto do_dtor;
4895 }
4896
bc7bff74 4897 if (POINTER_TYPE_P (TREE_TYPE (x)))
4898 x = fold_build2 (POINTER_PLUS_EXPR,
4899 TREE_TYPE (x), x, t);
4900 else
4901 x = fold_build2 (PLUS_EXPR, TREE_TYPE (x), x, t);
4902 }
4903
3d483a94 4904 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
4905 || TREE_ADDRESSABLE (new_var))
4906 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4907 idx, lane, ivar, lvar))
4908 {
4909 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR)
4910 {
f9e245b2 4911 tree iv = create_tmp_var (TREE_TYPE (new_var));
3d483a94 4912 x = lang_hooks.decls.omp_clause_copy_ctor (c, iv, x);
4913 gimplify_and_add (x, ilist);
4914 gimple_stmt_iterator gsi
4915 = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
1a91d914 4916 gassign *g
3d483a94 4917 = gimple_build_assign (unshare_expr (lvar), iv);
4918 gsi_insert_before_without_update (&gsi, g,
4919 GSI_SAME_STMT);
9580cb79 4920 tree t = OMP_CLAUSE_LINEAR_STEP (c);
3d483a94 4921 enum tree_code code = PLUS_EXPR;
4922 if (POINTER_TYPE_P (TREE_TYPE (new_var)))
4923 code = POINTER_PLUS_EXPR;
e9cf809e 4924 g = gimple_build_assign (iv, code, iv, t);
3d483a94 4925 gsi_insert_before_without_update (&gsi, g,
4926 GSI_SAME_STMT);
4927 break;
4928 }
4929 x = lang_hooks.decls.omp_clause_copy_ctor
4930 (c, unshare_expr (ivar), x);
4931 gimplify_and_add (x, &llist[0]);
4932 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
4933 if (x)
4934 {
4935 gimple_seq tseq = NULL;
4936
4937 dtor = x;
4938 gimplify_stmt (&dtor, &tseq);
4939 gimple_seq_add_seq (&llist[1], tseq);
4940 }
4941 break;
4942 }
4943 }
43895be5 4944 x = lang_hooks.decls.omp_clause_copy_ctor
4945 (c, unshare_expr (new_var), x);
1e8e9920 4946 gimplify_and_add (x, ilist);
4947 goto do_dtor;
1e8e9920 4948
bc7bff74 4949 case OMP_CLAUSE__LOOPTEMP_:
43895be5 4950 gcc_assert (is_taskreg_ctx (ctx));
bc7bff74 4951 x = build_outer_var_ref (var, ctx);
4952 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
4953 gimplify_and_add (x, ilist);
4954 break;
4955
1e8e9920 4956 case OMP_CLAUSE_COPYIN:
e8a588af 4957 by_ref = use_pointer_for_field (var, NULL);
1e8e9920 4958 x = build_receiver_ref (var, by_ref, ctx);
4959 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
4960 append_to_statement_list (x, &copyin_seq);
4961 copyin_by_ref |= by_ref;
4962 break;
4963
4964 case OMP_CLAUSE_REDUCTION:
641a0fa1 4965 /* OpenACC reductions are initialized using the
4966 GOACC_REDUCTION internal function. */
4967 if (is_gimple_omp_oacc (ctx->stmt))
4968 break;
1e8e9920 4969 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4970 {
fd6481cf 4971 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
42acab1c 4972 gimple *tseq;
fd6481cf 4973 x = build_outer_var_ref (var, ctx);
4974
bc7bff74 4975 if (is_reference (var)
4976 && !useless_type_conversion_p (TREE_TYPE (placeholder),
4977 TREE_TYPE (x)))
389dd41b 4978 x = build_fold_addr_expr_loc (clause_loc, x);
fd6481cf 4979 SET_DECL_VALUE_EXPR (placeholder, x);
4980 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
bc7bff74 4981 tree new_vard = new_var;
4982 if (is_reference (var))
4983 {
4984 gcc_assert (TREE_CODE (new_var) == MEM_REF);
4985 new_vard = TREE_OPERAND (new_var, 0);
4986 gcc_assert (DECL_P (new_vard));
4987 }
3d483a94 4988 if (is_simd
4989 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4990 idx, lane, ivar, lvar))
4991 {
bc7bff74 4992 if (new_vard == new_var)
4993 {
4994 gcc_assert (DECL_VALUE_EXPR (new_var) == lvar);
4995 SET_DECL_VALUE_EXPR (new_var, ivar);
4996 }
4997 else
4998 {
4999 SET_DECL_VALUE_EXPR (new_vard,
5000 build_fold_addr_expr (ivar));
5001 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
5002 }
5003 x = lang_hooks.decls.omp_clause_default_ctor
5004 (c, unshare_expr (ivar),
5005 build_outer_var_ref (var, ctx));
5006 if (x)
5007 gimplify_and_add (x, &llist[0]);
5008 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
5009 {
5010 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
5011 lower_omp (&tseq, ctx);
5012 gimple_seq_add_seq (&llist[0], tseq);
5013 }
5014 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
5015 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
5016 lower_omp (&tseq, ctx);
5017 gimple_seq_add_seq (&llist[1], tseq);
5018 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
5019 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
5020 if (new_vard == new_var)
5021 SET_DECL_VALUE_EXPR (new_var, lvar);
5022 else
5023 SET_DECL_VALUE_EXPR (new_vard,
5024 build_fold_addr_expr (lvar));
5025 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
5026 if (x)
5027 {
5028 tseq = NULL;
5029 dtor = x;
5030 gimplify_stmt (&dtor, &tseq);
5031 gimple_seq_add_seq (&llist[1], tseq);
5032 }
5033 break;
5034 }
09d1c205 5035 /* If this is a reference to constant size reduction var
5036 with placeholder, we haven't emitted the initializer
5037 for it because it is undesirable if SIMD arrays are used.
5038 But if they aren't used, we need to emit the deferred
5039 initialization now. */
5040 else if (is_reference (var) && is_simd)
2712b6de 5041 handle_simd_reference (clause_loc, new_vard, ilist);
bc7bff74 5042 x = lang_hooks.decls.omp_clause_default_ctor
cf5f881f 5043 (c, unshare_expr (new_var),
5044 build_outer_var_ref (var, ctx));
bc7bff74 5045 if (x)
5046 gimplify_and_add (x, ilist);
5047 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
5048 {
5049 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
5050 lower_omp (&tseq, ctx);
5051 gimple_seq_add_seq (ilist, tseq);
5052 }
75a70cf9 5053 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
bc7bff74 5054 if (is_simd)
5055 {
5056 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
5057 lower_omp (&tseq, ctx);
5058 gimple_seq_add_seq (dlist, tseq);
5059 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
5060 }
fd6481cf 5061 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
bc7bff74 5062 goto do_dtor;
1e8e9920 5063 }
5064 else
5065 {
5066 x = omp_reduction_init (c, TREE_TYPE (new_var));
5067 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
c22ad515 5068 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
5069
5070 /* reduction(-:var) sums up the partial results, so it
5071 acts identically to reduction(+:var). */
5072 if (code == MINUS_EXPR)
5073 code = PLUS_EXPR;
5074
2712b6de 5075 tree new_vard = new_var;
5076 if (is_simd && is_reference (var))
5077 {
5078 gcc_assert (TREE_CODE (new_var) == MEM_REF);
5079 new_vard = TREE_OPERAND (new_var, 0);
5080 gcc_assert (DECL_P (new_vard));
5081 }
3d483a94 5082 if (is_simd
5083 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
5084 idx, lane, ivar, lvar))
5085 {
3d483a94 5086 tree ref = build_outer_var_ref (var, ctx);
5087
5088 gimplify_assign (unshare_expr (ivar), x, &llist[0]);
5089
3d483a94 5090 x = build2 (code, TREE_TYPE (ref), ref, ivar);
5091 ref = build_outer_var_ref (var, ctx);
5092 gimplify_assign (ref, x, &llist[1]);
2712b6de 5093
5094 if (new_vard != new_var)
5095 {
5096 SET_DECL_VALUE_EXPR (new_vard,
5097 build_fold_addr_expr (lvar));
5098 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
5099 }
3d483a94 5100 }
5101 else
5102 {
2712b6de 5103 if (is_reference (var) && is_simd)
5104 handle_simd_reference (clause_loc, new_vard, ilist);
3d483a94 5105 gimplify_assign (new_var, x, ilist);
5106 if (is_simd)
c22ad515 5107 {
5108 tree ref = build_outer_var_ref (var, ctx);
5109
5110 x = build2 (code, TREE_TYPE (ref), ref, new_var);
5111 ref = build_outer_var_ref (var, ctx);
5112 gimplify_assign (ref, x, dlist);
5113 }
3d483a94 5114 }
1e8e9920 5115 }
5116 break;
5117
5118 default:
5119 gcc_unreachable ();
5120 }
5121 }
5122 }
5123
3d483a94 5124 if (lane)
5125 {
5126 tree uid = create_tmp_var (ptr_type_node, "simduid");
8e1a382d 5127 /* Don't want uninit warnings on simduid, it is always uninitialized,
5128 but we use it not for the value, but for the DECL_UID only. */
5129 TREE_NO_WARNING (uid) = 1;
42acab1c 5130 gimple *g
3d483a94 5131 = gimple_build_call_internal (IFN_GOMP_SIMD_LANE, 1, uid);
5132 gimple_call_set_lhs (g, lane);
5133 gimple_stmt_iterator gsi = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
5134 gsi_insert_before_without_update (&gsi, g, GSI_SAME_STMT);
5135 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SIMDUID_);
5136 OMP_CLAUSE__SIMDUID__DECL (c) = uid;
5137 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
5138 gimple_omp_for_set_clauses (ctx->stmt, c);
e9cf809e 5139 g = gimple_build_assign (lane, INTEGER_CST,
5140 build_int_cst (unsigned_type_node, 0));
3d483a94 5141 gimple_seq_add_stmt (ilist, g);
5142 for (int i = 0; i < 2; i++)
5143 if (llist[i])
5144 {
f9e245b2 5145 tree vf = create_tmp_var (unsigned_type_node);
3d483a94 5146 g = gimple_build_call_internal (IFN_GOMP_SIMD_VF, 1, uid);
5147 gimple_call_set_lhs (g, vf);
5148 gimple_seq *seq = i == 0 ? ilist : dlist;
5149 gimple_seq_add_stmt (seq, g);
5150 tree t = build_int_cst (unsigned_type_node, 0);
e9cf809e 5151 g = gimple_build_assign (idx, INTEGER_CST, t);
3d483a94 5152 gimple_seq_add_stmt (seq, g);
5153 tree body = create_artificial_label (UNKNOWN_LOCATION);
5154 tree header = create_artificial_label (UNKNOWN_LOCATION);
5155 tree end = create_artificial_label (UNKNOWN_LOCATION);
5156 gimple_seq_add_stmt (seq, gimple_build_goto (header));
5157 gimple_seq_add_stmt (seq, gimple_build_label (body));
5158 gimple_seq_add_seq (seq, llist[i]);
5159 t = build_int_cst (unsigned_type_node, 1);
e9cf809e 5160 g = gimple_build_assign (idx, PLUS_EXPR, idx, t);
3d483a94 5161 gimple_seq_add_stmt (seq, g);
5162 gimple_seq_add_stmt (seq, gimple_build_label (header));
5163 g = gimple_build_cond (LT_EXPR, idx, vf, body, end);
5164 gimple_seq_add_stmt (seq, g);
5165 gimple_seq_add_stmt (seq, gimple_build_label (end));
5166 }
5167 }
5168
1e8e9920 5169 /* The copyin sequence is not to be executed by the main thread, since
5170 that would result in self-copies. Perhaps not visible to scalars,
5171 but it certainly is to C++ operator=. */
5172 if (copyin_seq)
5173 {
b9a16870 5174 x = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM),
5175 0);
1e8e9920 5176 x = build2 (NE_EXPR, boolean_type_node, x,
5177 build_int_cst (TREE_TYPE (x), 0));
5178 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
5179 gimplify_and_add (x, ilist);
5180 }
5181
5182 /* If any copyin variable is passed by reference, we must ensure the
5183 master thread doesn't modify it before it is copied over in all
f49d7bb5 5184 threads. Similarly for variables in both firstprivate and
5185 lastprivate clauses we need to ensure the lastprivate copying
bc7bff74 5186 happens after firstprivate copying in all threads. And similarly
5187 for UDRs if initializer expression refers to omp_orig. */
5188 if (copyin_by_ref || lastprivate_firstprivate || reduction_omp_orig_ref)
3d483a94 5189 {
5190 /* Don't add any barrier for #pragma omp simd or
5191 #pragma omp distribute. */
5192 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
7c01fa6c 5193 || gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_FOR)
bc7bff74 5194 gimple_seq_add_stmt (ilist, build_omp_barrier (NULL_TREE));
3d483a94 5195 }
5196
5197 /* If max_vf is non-zero, then we can use only a vectorization factor
5198 up to the max_vf we chose. So stick it into the safelen clause. */
5199 if (max_vf)
5200 {
5201 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
5202 OMP_CLAUSE_SAFELEN);
5203 if (c == NULL_TREE
c3f3b68d 5204 || (TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) == INTEGER_CST
5205 && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
5206 max_vf) == 1))
3d483a94 5207 {
5208 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_SAFELEN);
5209 OMP_CLAUSE_SAFELEN_EXPR (c) = build_int_cst (integer_type_node,
5210 max_vf);
5211 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
5212 gimple_omp_for_set_clauses (ctx->stmt, c);
5213 }
5214 }
1e8e9920 5215}
5216
773c5ba7 5217
1e8e9920 5218/* Generate code to implement the LASTPRIVATE clauses. This is used for
5219 both parallel and workshare constructs. PREDICATE may be NULL if it's
5220 always true. */
5221
5222static void
75a70cf9 5223lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
bc7bff74 5224 omp_context *ctx)
1e8e9920 5225{
3d483a94 5226 tree x, c, label = NULL, orig_clauses = clauses;
fd6481cf 5227 bool par_clauses = false;
3d483a94 5228 tree simduid = NULL, lastlane = NULL;
1e8e9920 5229
3d483a94 5230 /* Early exit if there are no lastprivate or linear clauses. */
5231 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
5232 if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LASTPRIVATE
5233 || (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LINEAR
5234 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses)))
5235 break;
1e8e9920 5236 if (clauses == NULL)
5237 {
5238 /* If this was a workshare clause, see if it had been combined
5239 with its parallel. In that case, look for the clauses on the
5240 parallel statement itself. */
5241 if (is_parallel_ctx (ctx))
5242 return;
5243
5244 ctx = ctx->outer;
5245 if (ctx == NULL || !is_parallel_ctx (ctx))
5246 return;
5247
75a70cf9 5248 clauses = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
1e8e9920 5249 OMP_CLAUSE_LASTPRIVATE);
5250 if (clauses == NULL)
5251 return;
fd6481cf 5252 par_clauses = true;
1e8e9920 5253 }
5254
75a70cf9 5255 if (predicate)
5256 {
1a91d914 5257 gcond *stmt;
75a70cf9 5258 tree label_true, arm1, arm2;
5259
e60a6f7b 5260 label = create_artificial_label (UNKNOWN_LOCATION);
5261 label_true = create_artificial_label (UNKNOWN_LOCATION);
75a70cf9 5262 arm1 = TREE_OPERAND (predicate, 0);
5263 arm2 = TREE_OPERAND (predicate, 1);
5264 gimplify_expr (&arm1, stmt_list, NULL, is_gimple_val, fb_rvalue);
5265 gimplify_expr (&arm2, stmt_list, NULL, is_gimple_val, fb_rvalue);
5266 stmt = gimple_build_cond (TREE_CODE (predicate), arm1, arm2,
5267 label_true, label);
5268 gimple_seq_add_stmt (stmt_list, stmt);
5269 gimple_seq_add_stmt (stmt_list, gimple_build_label (label_true));
5270 }
1e8e9920 5271
3d483a94 5272 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
10c55644 5273 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3d483a94 5274 {
5275 simduid = find_omp_clause (orig_clauses, OMP_CLAUSE__SIMDUID_);
5276 if (simduid)
5277 simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
5278 }
5279
fd6481cf 5280 for (c = clauses; c ;)
1e8e9920 5281 {
5282 tree var, new_var;
389dd41b 5283 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
1e8e9920 5284
3d483a94 5285 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5286 || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
5287 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
fd6481cf 5288 {
5289 var = OMP_CLAUSE_DECL (c);
43895be5 5290 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5291 && OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c)
5292 && is_taskloop_ctx (ctx))
5293 {
5294 gcc_checking_assert (ctx->outer && is_task_ctx (ctx->outer));
5295 new_var = lookup_decl (var, ctx->outer);
5296 }
5297 else
5298 new_var = lookup_decl (var, ctx);
1e8e9920 5299
3d483a94 5300 if (simduid && DECL_HAS_VALUE_EXPR_P (new_var))
5301 {
5302 tree val = DECL_VALUE_EXPR (new_var);
5303 if (TREE_CODE (val) == ARRAY_REF
5304 && VAR_P (TREE_OPERAND (val, 0))
5305 && lookup_attribute ("omp simd array",
5306 DECL_ATTRIBUTES (TREE_OPERAND (val,
5307 0))))
5308 {
5309 if (lastlane == NULL)
5310 {
f9e245b2 5311 lastlane = create_tmp_var (unsigned_type_node);
1a91d914 5312 gcall *g
3d483a94 5313 = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE,
5314 2, simduid,
5315 TREE_OPERAND (val, 1));
5316 gimple_call_set_lhs (g, lastlane);
5317 gimple_seq_add_stmt (stmt_list, g);
5318 }
5319 new_var = build4 (ARRAY_REF, TREE_TYPE (val),
5320 TREE_OPERAND (val, 0), lastlane,
5321 NULL_TREE, NULL_TREE);
5322 }
5323 }
5324
5325 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5326 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
75a70cf9 5327 {
e3a19533 5328 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
75a70cf9 5329 gimple_seq_add_seq (stmt_list,
5330 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
3d483a94 5331 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) = NULL;
75a70cf9 5332 }
2b536a17 5333 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
5334 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
5335 {
5336 lower_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
5337 gimple_seq_add_seq (stmt_list,
5338 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c));
5339 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c) = NULL;
5340 }
1e8e9920 5341
43895be5 5342 x = NULL_TREE;
5343 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5344 && OMP_CLAUSE_LASTPRIVATE_TASKLOOP_IV (c))
5345 {
5346 gcc_checking_assert (is_taskloop_ctx (ctx));
5347 tree ovar = maybe_lookup_decl_in_outer_ctx (var,
5348 ctx->outer->outer);
5349 if (is_global_var (ovar))
5350 x = ovar;
5351 }
5352 if (!x)
5353 x = build_outer_var_ref (var, ctx, true);
fd6481cf 5354 if (is_reference (var))
182cf5a9 5355 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
fd6481cf 5356 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
75a70cf9 5357 gimplify_and_add (x, stmt_list);
fd6481cf 5358 }
5359 c = OMP_CLAUSE_CHAIN (c);
5360 if (c == NULL && !par_clauses)
5361 {
5362 /* If this was a workshare clause, see if it had been combined
5363 with its parallel. In that case, continue looking for the
5364 clauses also on the parallel statement itself. */
5365 if (is_parallel_ctx (ctx))
5366 break;
5367
5368 ctx = ctx->outer;
5369 if (ctx == NULL || !is_parallel_ctx (ctx))
5370 break;
5371
75a70cf9 5372 c = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
fd6481cf 5373 OMP_CLAUSE_LASTPRIVATE);
5374 par_clauses = true;
5375 }
1e8e9920 5376 }
5377
75a70cf9 5378 if (label)
5379 gimple_seq_add_stmt (stmt_list, gimple_build_label (label));
1e8e9920 5380}
5381
641a0fa1 5382/* Lower the OpenACC reductions of CLAUSES for compute axis LEVEL
5383 (which might be a placeholder). INNER is true if this is an inner
5384 axis of a multi-axis loop. FORK and JOIN are (optional) fork and
5385 join markers. Generate the before-loop forking sequence in
5386 FORK_SEQ and the after-loop joining sequence to JOIN_SEQ. The
5387 general form of these sequences is
5388
5389 GOACC_REDUCTION_SETUP
5390 GOACC_FORK
5391 GOACC_REDUCTION_INIT
5392 ...
5393 GOACC_REDUCTION_FINI
5394 GOACC_JOIN
5395 GOACC_REDUCTION_TEARDOWN. */
5396
ca4c3545 5397static void
641a0fa1 5398lower_oacc_reductions (location_t loc, tree clauses, tree level, bool inner,
5399 gcall *fork, gcall *join, gimple_seq *fork_seq,
5400 gimple_seq *join_seq, omp_context *ctx)
ca4c3545 5401{
641a0fa1 5402 gimple_seq before_fork = NULL;
5403 gimple_seq after_fork = NULL;
5404 gimple_seq before_join = NULL;
5405 gimple_seq after_join = NULL;
5406 tree init_code = NULL_TREE, fini_code = NULL_TREE,
5407 setup_code = NULL_TREE, teardown_code = NULL_TREE;
5408 unsigned offset = 0;
5409
5410 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
5411 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
5412 {
5413 tree orig = OMP_CLAUSE_DECL (c);
5414 tree var = maybe_lookup_decl (orig, ctx);
5415 tree ref_to_res = NULL_TREE;
5416 tree incoming, outgoing;
5417
5418 enum tree_code rcode = OMP_CLAUSE_REDUCTION_CODE (c);
5419 if (rcode == MINUS_EXPR)
5420 rcode = PLUS_EXPR;
5421 else if (rcode == TRUTH_ANDIF_EXPR)
5422 rcode = BIT_AND_EXPR;
5423 else if (rcode == TRUTH_ORIF_EXPR)
5424 rcode = BIT_IOR_EXPR;
5425 tree op = build_int_cst (unsigned_type_node, rcode);
5426
5427 if (!var)
5428 var = orig;
5429 gcc_assert (!is_reference (var));
5430
5431 incoming = outgoing = var;
5432
5433 if (!inner)
5434 {
5435 /* See if an outer construct also reduces this variable. */
5436 omp_context *outer = ctx;
ca4c3545 5437
641a0fa1 5438 while (omp_context *probe = outer->outer)
5439 {
5440 enum gimple_code type = gimple_code (probe->stmt);
5441 tree cls;
ca4c3545 5442
641a0fa1 5443 switch (type)
5444 {
5445 case GIMPLE_OMP_FOR:
5446 cls = gimple_omp_for_clauses (probe->stmt);
5447 break;
ca4c3545 5448
641a0fa1 5449 case GIMPLE_OMP_TARGET:
5450 if (gimple_omp_target_kind (probe->stmt)
5451 != GF_OMP_TARGET_KIND_OACC_PARALLEL)
5452 goto do_lookup;
ca4c3545 5453
641a0fa1 5454 cls = gimple_omp_target_clauses (probe->stmt);
5455 break;
ca4c3545 5456
641a0fa1 5457 default:
5458 goto do_lookup;
5459 }
5460
5461 outer = probe;
5462 for (; cls; cls = OMP_CLAUSE_CHAIN (cls))
5463 if (OMP_CLAUSE_CODE (cls) == OMP_CLAUSE_REDUCTION
5464 && orig == OMP_CLAUSE_DECL (cls))
5465 goto has_outer_reduction;
5466 }
ca4c3545 5467
641a0fa1 5468 do_lookup:
5469 /* This is the outermost construct with this reduction,
5470 see if there's a mapping for it. */
5471 if (gimple_code (outer->stmt) == GIMPLE_OMP_TARGET
5472 && maybe_lookup_field (orig, outer))
5473 {
5474 ref_to_res = build_receiver_ref (orig, false, outer);
5475 if (is_reference (orig))
5476 ref_to_res = build_simple_mem_ref (ref_to_res);
ca4c3545 5477
641a0fa1 5478 outgoing = var;
5479 incoming = omp_reduction_init_op (loc, rcode, TREE_TYPE (var));
5480 }
5481 else
5482 incoming = outgoing = orig;
5483
5484 has_outer_reduction:;
5485 }
ca4c3545 5486
641a0fa1 5487 if (!ref_to_res)
5488 ref_to_res = integer_zero_node;
ca4c3545 5489
641a0fa1 5490 /* Determine position in reduction buffer, which may be used
5491 by target. */
5492 enum machine_mode mode = TYPE_MODE (TREE_TYPE (var));
5493 unsigned align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
5494 offset = (offset + align - 1) & ~(align - 1);
5495 tree off = build_int_cst (sizetype, offset);
5496 offset += GET_MODE_SIZE (mode);
ca4c3545 5497
641a0fa1 5498 if (!init_code)
5499 {
5500 init_code = build_int_cst (integer_type_node,
5501 IFN_GOACC_REDUCTION_INIT);
5502 fini_code = build_int_cst (integer_type_node,
5503 IFN_GOACC_REDUCTION_FINI);
5504 setup_code = build_int_cst (integer_type_node,
5505 IFN_GOACC_REDUCTION_SETUP);
5506 teardown_code = build_int_cst (integer_type_node,
5507 IFN_GOACC_REDUCTION_TEARDOWN);
5508 }
5509
5510 tree setup_call
5511 = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
5512 TREE_TYPE (var), 6, setup_code,
5513 unshare_expr (ref_to_res),
5514 incoming, level, op, off);
5515 tree init_call
5516 = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
5517 TREE_TYPE (var), 6, init_code,
5518 unshare_expr (ref_to_res),
5519 var, level, op, off);
5520 tree fini_call
5521 = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
5522 TREE_TYPE (var), 6, fini_code,
5523 unshare_expr (ref_to_res),
5524 var, level, op, off);
5525 tree teardown_call
5526 = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
5527 TREE_TYPE (var), 6, teardown_code,
5528 ref_to_res, var, level, op, off);
5529
5530 gimplify_assign (var, setup_call, &before_fork);
5531 gimplify_assign (var, init_call, &after_fork);
5532 gimplify_assign (var, fini_call, &before_join);
5533 gimplify_assign (outgoing, teardown_call, &after_join);
5534 }
5535
5536 /* Now stitch things together. */
5537 gimple_seq_add_seq (fork_seq, before_fork);
5538 if (fork)
5539 gimple_seq_add_stmt (fork_seq, fork);
5540 gimple_seq_add_seq (fork_seq, after_fork);
5541
5542 gimple_seq_add_seq (join_seq, before_join);
5543 if (join)
5544 gimple_seq_add_stmt (join_seq, join);
5545 gimple_seq_add_seq (join_seq, after_join);
ca4c3545 5546}
773c5ba7 5547
1e8e9920 5548/* Generate code to implement the REDUCTION clauses. */
5549
5550static void
75a70cf9 5551lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
1e8e9920 5552{
75a70cf9 5553 gimple_seq sub_seq = NULL;
42acab1c 5554 gimple *stmt;
f69b8a4c 5555 tree x, c;
1e8e9920 5556 int count = 0;
5557
641a0fa1 5558 /* OpenACC loop reductions are handled elsewhere. */
5559 if (is_gimple_omp_oacc (ctx->stmt))
5560 return;
5561
3d483a94 5562 /* SIMD reductions are handled in lower_rec_input_clauses. */
5563 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
10c55644 5564 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3d483a94 5565 return;
5566
1e8e9920 5567 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
5568 update in that case, otherwise use a lock. */
5569 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
55d6e7cd 5570 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
1e8e9920 5571 {
43895be5 5572 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
5573 || TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF)
1e8e9920 5574 {
bc7bff74 5575 /* Never use OMP_ATOMIC for array reductions or UDRs. */
1e8e9920 5576 count = -1;
5577 break;
5578 }
5579 count++;
5580 }
5581
5582 if (count == 0)
5583 return;
5584
5585 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
5586 {
43895be5 5587 tree var, ref, new_var, orig_var;
1e8e9920 5588 enum tree_code code;
389dd41b 5589 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
1e8e9920 5590
55d6e7cd 5591 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
1e8e9920 5592 continue;
5593
43895be5 5594 orig_var = var = OMP_CLAUSE_DECL (c);
5595 if (TREE_CODE (var) == MEM_REF)
5596 {
5597 var = TREE_OPERAND (var, 0);
9561765e 5598 if (TREE_CODE (var) == POINTER_PLUS_EXPR)
5599 var = TREE_OPERAND (var, 0);
43895be5 5600 if (TREE_CODE (var) == INDIRECT_REF
5601 || TREE_CODE (var) == ADDR_EXPR)
5602 var = TREE_OPERAND (var, 0);
5603 orig_var = var;
5604 if (is_variable_sized (var))
5605 {
5606 gcc_assert (DECL_HAS_VALUE_EXPR_P (var));
5607 var = DECL_VALUE_EXPR (var);
5608 gcc_assert (TREE_CODE (var) == INDIRECT_REF);
5609 var = TREE_OPERAND (var, 0);
5610 gcc_assert (DECL_P (var));
5611 }
5612 }
1e8e9920 5613 new_var = lookup_decl (var, ctx);
43895be5 5614 if (var == OMP_CLAUSE_DECL (c) && is_reference (var))
182cf5a9 5615 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
1e8e9920 5616 ref = build_outer_var_ref (var, ctx);
5617 code = OMP_CLAUSE_REDUCTION_CODE (c);
773c5ba7 5618
5619 /* reduction(-:var) sums up the partial results, so it acts
5620 identically to reduction(+:var). */
1e8e9920 5621 if (code == MINUS_EXPR)
5622 code = PLUS_EXPR;
5623
641a0fa1 5624 if (count == 1)
1e8e9920 5625 {
389dd41b 5626 tree addr = build_fold_addr_expr_loc (clause_loc, ref);
1e8e9920 5627
5628 addr = save_expr (addr);
5629 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
389dd41b 5630 x = fold_build2_loc (clause_loc, code, TREE_TYPE (ref), ref, new_var);
1e8e9920 5631 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
75a70cf9 5632 gimplify_and_add (x, stmt_seqp);
1e8e9920 5633 return;
5634 }
43895be5 5635 else if (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF)
5636 {
5637 tree d = OMP_CLAUSE_DECL (c);
5638 tree type = TREE_TYPE (d);
5639 tree v = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
5640 tree i = create_tmp_var (TREE_TYPE (v), NULL);
5641 tree ptype = build_pointer_type (TREE_TYPE (type));
9561765e 5642 tree bias = TREE_OPERAND (d, 1);
5643 d = TREE_OPERAND (d, 0);
5644 if (TREE_CODE (d) == POINTER_PLUS_EXPR)
5645 {
5646 tree b = TREE_OPERAND (d, 1);
5647 b = maybe_lookup_decl (b, ctx);
5648 if (b == NULL)
5649 {
5650 b = TREE_OPERAND (d, 1);
5651 b = maybe_lookup_decl_in_outer_ctx (b, ctx);
5652 }
5653 if (integer_zerop (bias))
5654 bias = b;
5655 else
5656 {
5657 bias = fold_convert_loc (clause_loc, TREE_TYPE (b), bias);
5658 bias = fold_build2_loc (clause_loc, PLUS_EXPR,
5659 TREE_TYPE (b), b, bias);
5660 }
5661 d = TREE_OPERAND (d, 0);
5662 }
43895be5 5663 /* For ref build_outer_var_ref already performs this, so
5664 only new_var needs a dereference. */
9561765e 5665 if (TREE_CODE (d) == INDIRECT_REF)
43895be5 5666 {
5667 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
5668 gcc_assert (is_reference (var) && var == orig_var);
5669 }
9561765e 5670 else if (TREE_CODE (d) == ADDR_EXPR)
43895be5 5671 {
5672 if (orig_var == var)
5673 {
5674 new_var = build_fold_addr_expr (new_var);
5675 ref = build_fold_addr_expr (ref);
5676 }
5677 }
5678 else
5679 {
5680 gcc_assert (orig_var == var);
5681 if (is_reference (var))
5682 ref = build_fold_addr_expr (ref);
5683 }
5684 if (DECL_P (v))
5685 {
5686 tree t = maybe_lookup_decl (v, ctx);
5687 if (t)
5688 v = t;
5689 else
5690 v = maybe_lookup_decl_in_outer_ctx (v, ctx);
5691 gimplify_expr (&v, stmt_seqp, NULL, is_gimple_val, fb_rvalue);
5692 }
9561765e 5693 if (!integer_zerop (bias))
5694 {
5695 bias = fold_convert_loc (clause_loc, sizetype, bias);
5696 new_var = fold_build2_loc (clause_loc, POINTER_PLUS_EXPR,
5697 TREE_TYPE (new_var), new_var,
5698 unshare_expr (bias));
5699 ref = fold_build2_loc (clause_loc, POINTER_PLUS_EXPR,
5700 TREE_TYPE (ref), ref, bias);
5701 }
43895be5 5702 new_var = fold_convert_loc (clause_loc, ptype, new_var);
5703 ref = fold_convert_loc (clause_loc, ptype, ref);
5704 tree m = create_tmp_var (ptype, NULL);
5705 gimplify_assign (m, new_var, stmt_seqp);
5706 new_var = m;
5707 m = create_tmp_var (ptype, NULL);
5708 gimplify_assign (m, ref, stmt_seqp);
5709 ref = m;
5710 gimplify_assign (i, build_int_cst (TREE_TYPE (v), 0), stmt_seqp);
5711 tree body = create_artificial_label (UNKNOWN_LOCATION);
5712 tree end = create_artificial_label (UNKNOWN_LOCATION);
5713 gimple_seq_add_stmt (&sub_seq, gimple_build_label (body));
5714 tree priv = build_simple_mem_ref_loc (clause_loc, new_var);
5715 tree out = build_simple_mem_ref_loc (clause_loc, ref);
5716 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
5717 {
5718 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
5719 tree decl_placeholder
5720 = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c);
5721 SET_DECL_VALUE_EXPR (placeholder, out);
5722 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
5723 SET_DECL_VALUE_EXPR (decl_placeholder, priv);
5724 DECL_HAS_VALUE_EXPR_P (decl_placeholder) = 1;
5725 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
5726 gimple_seq_add_seq (&sub_seq,
5727 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
5728 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
5729 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
5730 OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c) = NULL;
5731 }
5732 else
5733 {
5734 x = build2 (code, TREE_TYPE (out), out, priv);
5735 out = unshare_expr (out);
5736 gimplify_assign (out, x, &sub_seq);
5737 }
5738 gimple *g = gimple_build_assign (new_var, POINTER_PLUS_EXPR, new_var,
5739 TYPE_SIZE_UNIT (TREE_TYPE (type)));
5740 gimple_seq_add_stmt (&sub_seq, g);
5741 g = gimple_build_assign (ref, POINTER_PLUS_EXPR, ref,
5742 TYPE_SIZE_UNIT (TREE_TYPE (type)));
5743 gimple_seq_add_stmt (&sub_seq, g);
5744 g = gimple_build_assign (i, PLUS_EXPR, i,
5745 build_int_cst (TREE_TYPE (i), 1));
5746 gimple_seq_add_stmt (&sub_seq, g);
5747 g = gimple_build_cond (LE_EXPR, i, v, body, end);
5748 gimple_seq_add_stmt (&sub_seq, g);
5749 gimple_seq_add_stmt (&sub_seq, gimple_build_label (end));
5750 }
ca4c3545 5751 else if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1e8e9920 5752 {
5753 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
5754
bc7bff74 5755 if (is_reference (var)
5756 && !useless_type_conversion_p (TREE_TYPE (placeholder),
5757 TREE_TYPE (ref)))
389dd41b 5758 ref = build_fold_addr_expr_loc (clause_loc, ref);
1e8e9920 5759 SET_DECL_VALUE_EXPR (placeholder, ref);
5760 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
e3a19533 5761 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
75a70cf9 5762 gimple_seq_add_seq (&sub_seq, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
5763 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
1e8e9920 5764 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
5765 }
5766 else
5767 {
5768 x = build2 (code, TREE_TYPE (ref), ref, new_var);
5769 ref = build_outer_var_ref (var, ctx);
75a70cf9 5770 gimplify_assign (ref, x, &sub_seq);
1e8e9920 5771 }
5772 }
5773
ca4c3545 5774 if (is_gimple_omp_oacc (ctx->stmt))
5775 return;
5776
b9a16870 5777 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START),
5778 0);
75a70cf9 5779 gimple_seq_add_stmt (stmt_seqp, stmt);
1e8e9920 5780
75a70cf9 5781 gimple_seq_add_seq (stmt_seqp, sub_seq);
1e8e9920 5782
b9a16870 5783 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END),
5784 0);
75a70cf9 5785 gimple_seq_add_stmt (stmt_seqp, stmt);
1e8e9920 5786}
5787
773c5ba7 5788
1e8e9920 5789/* Generate code to implement the COPYPRIVATE clauses. */
5790
5791static void
75a70cf9 5792lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist,
1e8e9920 5793 omp_context *ctx)
5794{
5795 tree c;
5796
5797 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
5798 {
cb561506 5799 tree var, new_var, ref, x;
1e8e9920 5800 bool by_ref;
389dd41b 5801 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
1e8e9920 5802
55d6e7cd 5803 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
1e8e9920 5804 continue;
5805
5806 var = OMP_CLAUSE_DECL (c);
e8a588af 5807 by_ref = use_pointer_for_field (var, NULL);
1e8e9920 5808
5809 ref = build_sender_ref (var, ctx);
cb561506 5810 x = new_var = lookup_decl_in_outer_ctx (var, ctx);
5811 if (by_ref)
5812 {
5813 x = build_fold_addr_expr_loc (clause_loc, new_var);
5814 x = fold_convert_loc (clause_loc, TREE_TYPE (ref), x);
5815 }
75a70cf9 5816 gimplify_assign (ref, x, slist);
1e8e9920 5817
cb561506 5818 ref = build_receiver_ref (var, false, ctx);
5819 if (by_ref)
5820 {
5821 ref = fold_convert_loc (clause_loc,
5822 build_pointer_type (TREE_TYPE (new_var)),
5823 ref);
5824 ref = build_fold_indirect_ref_loc (clause_loc, ref);
5825 }
1e8e9920 5826 if (is_reference (var))
5827 {
cb561506 5828 ref = fold_convert_loc (clause_loc, TREE_TYPE (new_var), ref);
182cf5a9 5829 ref = build_simple_mem_ref_loc (clause_loc, ref);
5830 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
1e8e9920 5831 }
cb561506 5832 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, ref);
1e8e9920 5833 gimplify_and_add (x, rlist);
5834 }
5835}
5836
773c5ba7 5837
1e8e9920 5838/* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
5839 and REDUCTION from the sender (aka parent) side. */
5840
5841static void
75a70cf9 5842lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
5843 omp_context *ctx)
1e8e9920 5844{
43895be5 5845 tree c, t;
5846 int ignored_looptemp = 0;
5847 bool is_taskloop = false;
5848
5849 /* For taskloop, ignore first two _looptemp_ clauses, those are initialized
5850 by GOMP_taskloop. */
5851 if (is_task_ctx (ctx) && gimple_omp_task_taskloop_p (ctx->stmt))
5852 {
5853 ignored_looptemp = 2;
5854 is_taskloop = true;
5855 }
1e8e9920 5856
5857 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
5858 {
773c5ba7 5859 tree val, ref, x, var;
1e8e9920 5860 bool by_ref, do_in = false, do_out = false;
389dd41b 5861 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
1e8e9920 5862
55d6e7cd 5863 switch (OMP_CLAUSE_CODE (c))
1e8e9920 5864 {
fd6481cf 5865 case OMP_CLAUSE_PRIVATE:
5866 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
5867 break;
5868 continue;
1e8e9920 5869 case OMP_CLAUSE_FIRSTPRIVATE:
5870 case OMP_CLAUSE_COPYIN:
5871 case OMP_CLAUSE_LASTPRIVATE:
5872 case OMP_CLAUSE_REDUCTION:
43895be5 5873 break;
5874 case OMP_CLAUSE_SHARED:
5875 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
5876 break;
5877 continue;
bc7bff74 5878 case OMP_CLAUSE__LOOPTEMP_:
43895be5 5879 if (ignored_looptemp)
5880 {
5881 ignored_looptemp--;
5882 continue;
5883 }
1e8e9920 5884 break;
5885 default:
5886 continue;
5887 }
5888
87b31375 5889 val = OMP_CLAUSE_DECL (c);
43895be5 5890 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
5891 && TREE_CODE (val) == MEM_REF)
5892 {
5893 val = TREE_OPERAND (val, 0);
9561765e 5894 if (TREE_CODE (val) == POINTER_PLUS_EXPR)
5895 val = TREE_OPERAND (val, 0);
43895be5 5896 if (TREE_CODE (val) == INDIRECT_REF
5897 || TREE_CODE (val) == ADDR_EXPR)
5898 val = TREE_OPERAND (val, 0);
5899 if (is_variable_sized (val))
5900 continue;
5901 }
5902
5903 /* For OMP_CLAUSE_SHARED_FIRSTPRIVATE, look beyond the
5904 outer taskloop region. */
5905 omp_context *ctx_for_o = ctx;
5906 if (is_taskloop
5907 && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
5908 && OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
5909 ctx_for_o = ctx->outer;
5910
5911 var = lookup_decl_in_outer_ctx (val, ctx_for_o);
773c5ba7 5912
f49d7bb5 5913 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
5914 && is_global_var (var))
5915 continue;
43895be5 5916
5917 t = omp_member_access_dummy_var (var);
5918 if (t)
5919 {
5920 var = DECL_VALUE_EXPR (var);
5921 tree o = maybe_lookup_decl_in_outer_ctx (t, ctx_for_o);
5922 if (o != t)
5923 var = unshare_and_remap (var, t, o);
5924 else
5925 var = unshare_expr (var);
5926 }
5927
5928 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED)
5929 {
5930 /* Handle taskloop firstprivate/lastprivate, where the
5931 lastprivate on GIMPLE_OMP_TASK is represented as
5932 OMP_CLAUSE_SHARED_FIRSTPRIVATE. */
5933 tree f = lookup_sfield ((splay_tree_key) &DECL_UID (val), ctx);
5934 x = omp_build_component_ref (ctx->sender_decl, f);
5935 if (use_pointer_for_field (val, ctx))
5936 var = build_fold_addr_expr (var);
5937 gimplify_assign (x, var, ilist);
5938 DECL_ABSTRACT_ORIGIN (f) = NULL;
5939 continue;
5940 }
5941
5942 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION
5943 || val == OMP_CLAUSE_DECL (c))
5944 && is_variable_sized (val))
1e8e9920 5945 continue;
e8a588af 5946 by_ref = use_pointer_for_field (val, NULL);
1e8e9920 5947
55d6e7cd 5948 switch (OMP_CLAUSE_CODE (c))
1e8e9920 5949 {
fd6481cf 5950 case OMP_CLAUSE_PRIVATE:
1e8e9920 5951 case OMP_CLAUSE_FIRSTPRIVATE:
5952 case OMP_CLAUSE_COPYIN:
bc7bff74 5953 case OMP_CLAUSE__LOOPTEMP_:
1e8e9920 5954 do_in = true;
5955 break;
5956
5957 case OMP_CLAUSE_LASTPRIVATE:
5958 if (by_ref || is_reference (val))
5959 {
5960 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
5961 continue;
5962 do_in = true;
5963 }
5964 else
fd6481cf 5965 {
5966 do_out = true;
5967 if (lang_hooks.decls.omp_private_outer_ref (val))
5968 do_in = true;
5969 }
1e8e9920 5970 break;
5971
5972 case OMP_CLAUSE_REDUCTION:
5973 do_in = true;
43895be5 5974 if (val == OMP_CLAUSE_DECL (c))
5975 do_out = !(by_ref || is_reference (val));
5976 else
5977 by_ref = TREE_CODE (TREE_TYPE (val)) == ARRAY_TYPE;
1e8e9920 5978 break;
5979
5980 default:
5981 gcc_unreachable ();
5982 }
5983
5984 if (do_in)
5985 {
5986 ref = build_sender_ref (val, ctx);
389dd41b 5987 x = by_ref ? build_fold_addr_expr_loc (clause_loc, var) : var;
75a70cf9 5988 gimplify_assign (ref, x, ilist);
fd6481cf 5989 if (is_task_ctx (ctx))
5990 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref, 1)) = NULL;
1e8e9920 5991 }
773c5ba7 5992
1e8e9920 5993 if (do_out)
5994 {
5995 ref = build_sender_ref (val, ctx);
75a70cf9 5996 gimplify_assign (var, ref, olist);
1e8e9920 5997 }
5998 }
5999}
6000
75a70cf9 6001/* Generate code to implement SHARED from the sender (aka parent)
6002 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
6003 list things that got automatically shared. */
1e8e9920 6004
6005static void
75a70cf9 6006lower_send_shared_vars (gimple_seq *ilist, gimple_seq *olist, omp_context *ctx)
1e8e9920 6007{
43895be5 6008 tree var, ovar, nvar, t, f, x, record_type;
1e8e9920 6009
6010 if (ctx->record_type == NULL)
6011 return;
773c5ba7 6012
fd6481cf 6013 record_type = ctx->srecord_type ? ctx->srecord_type : ctx->record_type;
1767a056 6014 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
1e8e9920 6015 {
6016 ovar = DECL_ABSTRACT_ORIGIN (f);
43895be5 6017 if (!ovar || TREE_CODE (ovar) == FIELD_DECL)
6018 continue;
6019
1e8e9920 6020 nvar = maybe_lookup_decl (ovar, ctx);
6021 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
6022 continue;
6023
773c5ba7 6024 /* If CTX is a nested parallel directive. Find the immediately
6025 enclosing parallel or workshare construct that contains a
6026 mapping for OVAR. */
87b31375 6027 var = lookup_decl_in_outer_ctx (ovar, ctx);
773c5ba7 6028
43895be5 6029 t = omp_member_access_dummy_var (var);
6030 if (t)
6031 {
6032 var = DECL_VALUE_EXPR (var);
6033 tree o = maybe_lookup_decl_in_outer_ctx (t, ctx);
6034 if (o != t)
6035 var = unshare_and_remap (var, t, o);
6036 else
6037 var = unshare_expr (var);
6038 }
6039
e8a588af 6040 if (use_pointer_for_field (ovar, ctx))
1e8e9920 6041 {
6042 x = build_sender_ref (ovar, ctx);
773c5ba7 6043 var = build_fold_addr_expr (var);
75a70cf9 6044 gimplify_assign (x, var, ilist);
1e8e9920 6045 }
6046 else
6047 {
6048 x = build_sender_ref (ovar, ctx);
75a70cf9 6049 gimplify_assign (x, var, ilist);
1e8e9920 6050
d2263ebb 6051 if (!TREE_READONLY (var)
6052 /* We don't need to receive a new reference to a result
6053 or parm decl. In fact we may not store to it as we will
6054 invalidate any pending RSO and generate wrong gimple
6055 during inlining. */
6056 && !((TREE_CODE (var) == RESULT_DECL
6057 || TREE_CODE (var) == PARM_DECL)
6058 && DECL_BY_REFERENCE (var)))
fd6481cf 6059 {
6060 x = build_sender_ref (ovar, ctx);
75a70cf9 6061 gimplify_assign (var, x, olist);
fd6481cf 6062 }
1e8e9920 6063 }
6064 }
6065}
6066
a8e785ba 6067/* Emit an OpenACC head marker call, encapulating the partitioning and
6068 other information that must be processed by the target compiler.
6069 Return the maximum number of dimensions the associated loop might
6070 be partitioned over. */
6071
6072static unsigned
6073lower_oacc_head_mark (location_t loc, tree ddvar, tree clauses,
6074 gimple_seq *seq, omp_context *ctx)
6075{
6076 unsigned levels = 0;
6077 unsigned tag = 0;
6078 tree gang_static = NULL_TREE;
6079 auto_vec<tree, 5> args;
6080
6081 args.quick_push (build_int_cst
6082 (integer_type_node, IFN_UNIQUE_OACC_HEAD_MARK));
6083 args.quick_push (ddvar);
6084 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
6085 {
6086 switch (OMP_CLAUSE_CODE (c))
6087 {
6088 case OMP_CLAUSE_GANG:
6089 tag |= OLF_DIM_GANG;
6090 gang_static = OMP_CLAUSE_GANG_STATIC_EXPR (c);
6091 /* static:* is represented by -1, and we can ignore it, as
6092 scheduling is always static. */
6093 if (gang_static && integer_minus_onep (gang_static))
6094 gang_static = NULL_TREE;
6095 levels++;
6096 break;
6097
6098 case OMP_CLAUSE_WORKER:
6099 tag |= OLF_DIM_WORKER;
6100 levels++;
6101 break;
6102
6103 case OMP_CLAUSE_VECTOR:
6104 tag |= OLF_DIM_VECTOR;
6105 levels++;
6106 break;
6107
6108 case OMP_CLAUSE_SEQ:
6109 tag |= OLF_SEQ;
6110 break;
6111
6112 case OMP_CLAUSE_AUTO:
6113 tag |= OLF_AUTO;
6114 break;
6115
6116 case OMP_CLAUSE_INDEPENDENT:
6117 tag |= OLF_INDEPENDENT;
6118 break;
6119
6120 default:
6121 continue;
6122 }
6123 }
6124
6125 if (gang_static)
6126 {
6127 if (DECL_P (gang_static))
6128 gang_static = build_outer_var_ref (gang_static, ctx);
6129 tag |= OLF_GANG_STATIC;
6130 }
6131
6132 /* In a parallel region, loops are implicitly INDEPENDENT. */
6133 omp_context *tgt = enclosing_target_ctx (ctx);
6134 if (!tgt || is_oacc_parallel (tgt))
6135 tag |= OLF_INDEPENDENT;
6136
6137 /* A loop lacking SEQ, GANG, WORKER and/or VECTOR is implicitly AUTO. */
6138 if (!(tag & (((GOMP_DIM_MASK (GOMP_DIM_MAX) - 1) << OLF_DIM_BASE)
6139 | OLF_SEQ)))
6140 tag |= OLF_AUTO;
6141
6142 /* Ensure at least one level. */
6143 if (!levels)
6144 levels++;
6145
6146 args.quick_push (build_int_cst (integer_type_node, levels));
6147 args.quick_push (build_int_cst (integer_type_node, tag));
6148 if (gang_static)
6149 args.quick_push (gang_static);
6150
6151 gcall *call = gimple_build_call_internal_vec (IFN_UNIQUE, args);
6152 gimple_set_location (call, loc);
6153 gimple_set_lhs (call, ddvar);
6154 gimple_seq_add_stmt (seq, call);
6155
6156 return levels;
6157}
6158
6159/* Emit an OpenACC lopp head or tail marker to SEQ. LEVEL is the
6160 partitioning level of the enclosed region. */
6161
6162static void
6163lower_oacc_loop_marker (location_t loc, tree ddvar, bool head,
6164 tree tofollow, gimple_seq *seq)
6165{
6166 int marker_kind = (head ? IFN_UNIQUE_OACC_HEAD_MARK
6167 : IFN_UNIQUE_OACC_TAIL_MARK);
6168 tree marker = build_int_cst (integer_type_node, marker_kind);
6169 int nargs = 2 + (tofollow != NULL_TREE);
6170 gcall *call = gimple_build_call_internal (IFN_UNIQUE, nargs,
6171 marker, ddvar, tofollow);
6172 gimple_set_location (call, loc);
6173 gimple_set_lhs (call, ddvar);
6174 gimple_seq_add_stmt (seq, call);
6175}
6176
6177/* Generate the before and after OpenACC loop sequences. CLAUSES are
6178 the loop clauses, from which we extract reductions. Initialize
6179 HEAD and TAIL. */
6180
6181static void
6182lower_oacc_head_tail (location_t loc, tree clauses,
6183 gimple_seq *head, gimple_seq *tail, omp_context *ctx)
6184{
6185 bool inner = false;
6186 tree ddvar = create_tmp_var (integer_type_node, ".data_dep");
6187 gimple_seq_add_stmt (head, gimple_build_assign (ddvar, integer_zero_node));
6188
6189 unsigned count = lower_oacc_head_mark (loc, ddvar, clauses, head, ctx);
6190 if (!count)
6191 lower_oacc_loop_marker (loc, ddvar, false, integer_zero_node, tail);
6192
6193 tree fork_kind = build_int_cst (unsigned_type_node, IFN_UNIQUE_OACC_FORK);
6194 tree join_kind = build_int_cst (unsigned_type_node, IFN_UNIQUE_OACC_JOIN);
6195
6196 for (unsigned done = 1; count; count--, done++)
6197 {
6198 gimple_seq fork_seq = NULL;
6199 gimple_seq join_seq = NULL;
6200
6201 tree place = build_int_cst (integer_type_node, -1);
6202 gcall *fork = gimple_build_call_internal (IFN_UNIQUE, 3,
6203 fork_kind, ddvar, place);
6204 gimple_set_location (fork, loc);
6205 gimple_set_lhs (fork, ddvar);
6206
6207 gcall *join = gimple_build_call_internal (IFN_UNIQUE, 3,
6208 join_kind, ddvar, place);
6209 gimple_set_location (join, loc);
6210 gimple_set_lhs (join, ddvar);
6211
6212 /* Mark the beginning of this level sequence. */
6213 if (inner)
6214 lower_oacc_loop_marker (loc, ddvar, true,
6215 build_int_cst (integer_type_node, count),
6216 &fork_seq);
6217 lower_oacc_loop_marker (loc, ddvar, false,
6218 build_int_cst (integer_type_node, done),
6219 &join_seq);
6220
641a0fa1 6221 lower_oacc_reductions (loc, clauses, place, inner,
6222 fork, join, &fork_seq, &join_seq, ctx);
a8e785ba 6223
6224 /* Append this level to head. */
6225 gimple_seq_add_seq (head, fork_seq);
6226 /* Prepend it to tail. */
6227 gimple_seq_add_seq (&join_seq, *tail);
6228 *tail = join_seq;
6229
6230 inner = true;
6231 }
6232
6233 /* Mark the end of the sequence. */
6234 lower_oacc_loop_marker (loc, ddvar, true, NULL_TREE, head);
6235 lower_oacc_loop_marker (loc, ddvar, false, NULL_TREE, tail);
6236}
75a70cf9 6237
6238/* A convenience function to build an empty GIMPLE_COND with just the
6239 condition. */
6240
1a91d914 6241static gcond *
75a70cf9 6242gimple_build_cond_empty (tree cond)
6243{
6244 enum tree_code pred_code;
6245 tree lhs, rhs;
6246
6247 gimple_cond_get_ops_from_tree (cond, &pred_code, &lhs, &rhs);
6248 return gimple_build_cond (pred_code, lhs, rhs, NULL_TREE, NULL_TREE);
6249}
6250
43895be5 6251static void expand_omp_build_assign (gimple_stmt_iterator *, tree, tree,
6252 bool = false);
75a70cf9 6253
48e1416a 6254/* Build the function calls to GOMP_parallel_start etc to actually
773c5ba7 6255 generate the parallel operation. REGION is the parallel region
6256 being expanded. BB is the block where to insert the code. WS_ARGS
6257 will be set if this is a call to a combined parallel+workshare
6258 construct, it contains the list of additional arguments needed by
6259 the workshare construct. */
1e8e9920 6260
6261static void
61e47ac8 6262expand_parallel_call (struct omp_region *region, basic_block bb,
1a91d914 6263 gomp_parallel *entry_stmt,
6264 vec<tree, va_gc> *ws_args)
1e8e9920 6265{
bc7bff74 6266 tree t, t1, t2, val, cond, c, clauses, flags;
75a70cf9 6267 gimple_stmt_iterator gsi;
42acab1c 6268 gimple *stmt;
b9a16870 6269 enum built_in_function start_ix;
6270 int start_ix2;
389dd41b 6271 location_t clause_loc;
f1f41a6c 6272 vec<tree, va_gc> *args;
773c5ba7 6273
75a70cf9 6274 clauses = gimple_omp_parallel_clauses (entry_stmt);
773c5ba7 6275
bc7bff74 6276 /* Determine what flavor of GOMP_parallel we will be
773c5ba7 6277 emitting. */
bc7bff74 6278 start_ix = BUILT_IN_GOMP_PARALLEL;
773c5ba7 6279 if (is_combined_parallel (region))
6280 {
61e47ac8 6281 switch (region->inner->type)
773c5ba7 6282 {
75a70cf9 6283 case GIMPLE_OMP_FOR:
fd6481cf 6284 gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
9561765e 6285 switch (region->inner->sched_kind)
6286 {
6287 case OMP_CLAUSE_SCHEDULE_RUNTIME:
6288 start_ix2 = 3;
6289 break;
6290 case OMP_CLAUSE_SCHEDULE_DYNAMIC:
6291 case OMP_CLAUSE_SCHEDULE_GUIDED:
6292 if (region->inner->sched_modifiers
6293 & OMP_CLAUSE_SCHEDULE_NONMONOTONIC)
6294 {
6295 start_ix2 = 3 + region->inner->sched_kind;
6296 break;
6297 }
6298 /* FALLTHRU */
6299 default:
6300 start_ix2 = region->inner->sched_kind;
6301 break;
6302 }
6303 start_ix2 += (int) BUILT_IN_GOMP_PARALLEL_LOOP_STATIC;
6304 start_ix = (enum built_in_function) start_ix2;
61e47ac8 6305 break;
75a70cf9 6306 case GIMPLE_OMP_SECTIONS:
bc7bff74 6307 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS;
61e47ac8 6308 break;
6309 default:
6310 gcc_unreachable ();
773c5ba7 6311 }
773c5ba7 6312 }
1e8e9920 6313
6314 /* By default, the value of NUM_THREADS is zero (selected at run time)
6315 and there is no conditional. */
6316 cond = NULL_TREE;
6317 val = build_int_cst (unsigned_type_node, 0);
bc7bff74 6318 flags = build_int_cst (unsigned_type_node, 0);
1e8e9920 6319
6320 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
6321 if (c)
6322 cond = OMP_CLAUSE_IF_EXPR (c);
6323
6324 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
6325 if (c)
389dd41b 6326 {
6327 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
6328 clause_loc = OMP_CLAUSE_LOCATION (c);
6329 }
6330 else
6331 clause_loc = gimple_location (entry_stmt);
1e8e9920 6332
bc7bff74 6333 c = find_omp_clause (clauses, OMP_CLAUSE_PROC_BIND);
6334 if (c)
6335 flags = build_int_cst (unsigned_type_node, OMP_CLAUSE_PROC_BIND_KIND (c));
6336
1e8e9920 6337 /* Ensure 'val' is of the correct type. */
389dd41b 6338 val = fold_convert_loc (clause_loc, unsigned_type_node, val);
1e8e9920 6339
6340 /* If we found the clause 'if (cond)', build either
6341 (cond != 0) or (cond ? val : 1u). */
6342 if (cond)
6343 {
773c5ba7 6344 cond = gimple_boolify (cond);
6345
1e8e9920 6346 if (integer_zerop (val))
389dd41b 6347 val = fold_build2_loc (clause_loc,
6348 EQ_EXPR, unsigned_type_node, cond,
79acaae1 6349 build_int_cst (TREE_TYPE (cond), 0));
1e8e9920 6350 else
773c5ba7 6351 {
6352 basic_block cond_bb, then_bb, else_bb;
79acaae1 6353 edge e, e_then, e_else;
75a70cf9 6354 tree tmp_then, tmp_else, tmp_join, tmp_var;
79acaae1 6355
f9e245b2 6356 tmp_var = create_tmp_var (TREE_TYPE (val));
79acaae1 6357 if (gimple_in_ssa_p (cfun))
6358 {
f9e245b2 6359 tmp_then = make_ssa_name (tmp_var);
6360 tmp_else = make_ssa_name (tmp_var);
6361 tmp_join = make_ssa_name (tmp_var);
79acaae1 6362 }
6363 else
6364 {
6365 tmp_then = tmp_var;
6366 tmp_else = tmp_var;
6367 tmp_join = tmp_var;
6368 }
773c5ba7 6369
4302d619 6370 e = split_block_after_labels (bb);
773c5ba7 6371 cond_bb = e->src;
6372 bb = e->dest;
6373 remove_edge (e);
6374
6375 then_bb = create_empty_bb (cond_bb);
6376 else_bb = create_empty_bb (then_bb);
79acaae1 6377 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
6378 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
773c5ba7 6379
75a70cf9 6380 stmt = gimple_build_cond_empty (cond);
6381 gsi = gsi_start_bb (cond_bb);
6382 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
773c5ba7 6383
75a70cf9 6384 gsi = gsi_start_bb (then_bb);
43895be5 6385 expand_omp_build_assign (&gsi, tmp_then, val, true);
773c5ba7 6386
75a70cf9 6387 gsi = gsi_start_bb (else_bb);
43895be5 6388 expand_omp_build_assign (&gsi, tmp_else,
6389 build_int_cst (unsigned_type_node, 1),
6390 true);
773c5ba7 6391
6392 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
6393 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
b3083327 6394 add_bb_to_loop (then_bb, cond_bb->loop_father);
6395 add_bb_to_loop (else_bb, cond_bb->loop_father);
79acaae1 6396 e_then = make_edge (then_bb, bb, EDGE_FALLTHRU);
6397 e_else = make_edge (else_bb, bb, EDGE_FALLTHRU);
773c5ba7 6398
79acaae1 6399 if (gimple_in_ssa_p (cfun))
6400 {
1a91d914 6401 gphi *phi = create_phi_node (tmp_join, bb);
60d535d2 6402 add_phi_arg (phi, tmp_then, e_then, UNKNOWN_LOCATION);
6403 add_phi_arg (phi, tmp_else, e_else, UNKNOWN_LOCATION);
79acaae1 6404 }
6405
6406 val = tmp_join;
773c5ba7 6407 }
6408
75a70cf9 6409 gsi = gsi_start_bb (bb);
6410 val = force_gimple_operand_gsi (&gsi, val, true, NULL_TREE,
6411 false, GSI_CONTINUE_LINKING);
1e8e9920 6412 }
6413
75a70cf9 6414 gsi = gsi_last_bb (bb);
6415 t = gimple_omp_parallel_data_arg (entry_stmt);
1e8e9920 6416 if (t == NULL)
c2f47e15 6417 t1 = null_pointer_node;
1e8e9920 6418 else
c2f47e15 6419 t1 = build_fold_addr_expr (t);
75a70cf9 6420 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
773c5ba7 6421
bc7bff74 6422 vec_alloc (args, 4 + vec_safe_length (ws_args));
f1f41a6c 6423 args->quick_push (t2);
6424 args->quick_push (t1);
6425 args->quick_push (val);
6426 if (ws_args)
6427 args->splice (*ws_args);
bc7bff74 6428 args->quick_push (flags);
414c3a2c 6429
6430 t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
b9a16870 6431 builtin_decl_explicit (start_ix), args);
773c5ba7 6432
75a70cf9 6433 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6434 false, GSI_CONTINUE_LINKING);
1e8e9920 6435}
6436
40750995 6437/* Insert a function call whose name is FUNC_NAME with the information from
6438 ENTRY_STMT into the basic_block BB. */
6439
6440static void
1a91d914 6441expand_cilk_for_call (basic_block bb, gomp_parallel *entry_stmt,
40750995 6442 vec <tree, va_gc> *ws_args)
6443{
6444 tree t, t1, t2;
6445 gimple_stmt_iterator gsi;
6446 vec <tree, va_gc> *args;
6447
6448 gcc_assert (vec_safe_length (ws_args) == 2);
6449 tree func_name = (*ws_args)[0];
6450 tree grain = (*ws_args)[1];
6451
6452 tree clauses = gimple_omp_parallel_clauses (entry_stmt);
6453 tree count = find_omp_clause (clauses, OMP_CLAUSE__CILK_FOR_COUNT_);
6454 gcc_assert (count != NULL_TREE);
6455 count = OMP_CLAUSE_OPERAND (count, 0);
6456
6457 gsi = gsi_last_bb (bb);
6458 t = gimple_omp_parallel_data_arg (entry_stmt);
6459 if (t == NULL)
6460 t1 = null_pointer_node;
6461 else
6462 t1 = build_fold_addr_expr (t);
6463 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
6464
6465 vec_alloc (args, 4);
6466 args->quick_push (t2);
6467 args->quick_push (t1);
6468 args->quick_push (count);
6469 args->quick_push (grain);
6470 t = build_call_expr_loc_vec (UNKNOWN_LOCATION, func_name, args);
6471
6472 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, false,
6473 GSI_CONTINUE_LINKING);
6474}
773c5ba7 6475
fd6481cf 6476/* Build the function call to GOMP_task to actually
6477 generate the task operation. BB is the block where to insert the code. */
6478
6479static void
43895be5 6480expand_task_call (struct omp_region *region, basic_block bb,
6481 gomp_task *entry_stmt)
fd6481cf 6482{
43895be5 6483 tree t1, t2, t3;
75a70cf9 6484 gimple_stmt_iterator gsi;
389dd41b 6485 location_t loc = gimple_location (entry_stmt);
fd6481cf 6486
43895be5 6487 tree clauses = gimple_omp_task_clauses (entry_stmt);
6488
6489 tree ifc = find_omp_clause (clauses, OMP_CLAUSE_IF);
6490 tree untied = find_omp_clause (clauses, OMP_CLAUSE_UNTIED);
6491 tree mergeable = find_omp_clause (clauses, OMP_CLAUSE_MERGEABLE);
6492 tree depend = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
6493 tree finalc = find_omp_clause (clauses, OMP_CLAUSE_FINAL);
6494 tree priority = find_omp_clause (clauses, OMP_CLAUSE_PRIORITY);
6495
6496 unsigned int iflags
6497 = (untied ? GOMP_TASK_FLAG_UNTIED : 0)
6498 | (mergeable ? GOMP_TASK_FLAG_MERGEABLE : 0)
6499 | (depend ? GOMP_TASK_FLAG_DEPEND : 0);
6500
6501 bool taskloop_p = gimple_omp_task_taskloop_p (entry_stmt);
6502 tree startvar = NULL_TREE, endvar = NULL_TREE, step = NULL_TREE;
6503 tree num_tasks = NULL_TREE;
6504 bool ull = false;
6505 if (taskloop_p)
6506 {
6507 gimple *g = last_stmt (region->outer->entry);
6508 gcc_assert (gimple_code (g) == GIMPLE_OMP_FOR
6509 && gimple_omp_for_kind (g) == GF_OMP_FOR_KIND_TASKLOOP);
6510 struct omp_for_data fd;
6511 extract_omp_for_data (as_a <gomp_for *> (g), &fd, NULL);
6512 startvar = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
6513 endvar = find_omp_clause (OMP_CLAUSE_CHAIN (startvar),
6514 OMP_CLAUSE__LOOPTEMP_);
6515 startvar = OMP_CLAUSE_DECL (startvar);
6516 endvar = OMP_CLAUSE_DECL (endvar);
6517 step = fold_convert_loc (loc, fd.iter_type, fd.loop.step);
6518 if (fd.loop.cond_code == LT_EXPR)
6519 iflags |= GOMP_TASK_FLAG_UP;
6520 tree tclauses = gimple_omp_for_clauses (g);
6521 num_tasks = find_omp_clause (tclauses, OMP_CLAUSE_NUM_TASKS);
6522 if (num_tasks)
6523 num_tasks = OMP_CLAUSE_NUM_TASKS_EXPR (num_tasks);
6524 else
6525 {
6526 num_tasks = find_omp_clause (tclauses, OMP_CLAUSE_GRAINSIZE);
6527 if (num_tasks)
6528 {
6529 iflags |= GOMP_TASK_FLAG_GRAINSIZE;
6530 num_tasks = OMP_CLAUSE_GRAINSIZE_EXPR (num_tasks);
6531 }
6532 else
6533 num_tasks = integer_zero_node;
6534 }
6535 num_tasks = fold_convert_loc (loc, long_integer_type_node, num_tasks);
6536 if (ifc == NULL_TREE)
6537 iflags |= GOMP_TASK_FLAG_IF;
6538 if (find_omp_clause (tclauses, OMP_CLAUSE_NOGROUP))
6539 iflags |= GOMP_TASK_FLAG_NOGROUP;
6540 ull = fd.iter_type == long_long_unsigned_type_node;
6541 }
6542 else if (priority)
6543 iflags |= GOMP_TASK_FLAG_PRIORITY;
fd6481cf 6544
43895be5 6545 tree flags = build_int_cst (unsigned_type_node, iflags);
fd6481cf 6546
43895be5 6547 tree cond = boolean_true_node;
6548 if (ifc)
6549 {
6550 if (taskloop_p)
6551 {
6552 tree t = gimple_boolify (OMP_CLAUSE_IF_EXPR (ifc));
6553 t = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, t,
6554 build_int_cst (unsigned_type_node,
6555 GOMP_TASK_FLAG_IF),
6556 build_int_cst (unsigned_type_node, 0));
6557 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node,
6558 flags, t);
6559 }
6560 else
6561 cond = gimple_boolify (OMP_CLAUSE_IF_EXPR (ifc));
6562 }
2169f33b 6563
43895be5 6564 if (finalc)
2169f33b 6565 {
43895be5 6566 tree t = gimple_boolify (OMP_CLAUSE_FINAL_EXPR (finalc));
6567 t = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, t,
6568 build_int_cst (unsigned_type_node,
6569 GOMP_TASK_FLAG_FINAL),
2169f33b 6570 build_int_cst (unsigned_type_node, 0));
43895be5 6571 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node, flags, t);
2169f33b 6572 }
bc7bff74 6573 if (depend)
6574 depend = OMP_CLAUSE_DECL (depend);
6575 else
6576 depend = build_int_cst (ptr_type_node, 0);
43895be5 6577 if (priority)
6578 priority = fold_convert (integer_type_node,
6579 OMP_CLAUSE_PRIORITY_EXPR (priority));
6580 else
6581 priority = integer_zero_node;
fd6481cf 6582
75a70cf9 6583 gsi = gsi_last_bb (bb);
43895be5 6584 tree t = gimple_omp_task_data_arg (entry_stmt);
fd6481cf 6585 if (t == NULL)
6586 t2 = null_pointer_node;
6587 else
389dd41b 6588 t2 = build_fold_addr_expr_loc (loc, t);
6589 t1 = build_fold_addr_expr_loc (loc, gimple_omp_task_child_fn (entry_stmt));
75a70cf9 6590 t = gimple_omp_task_copy_fn (entry_stmt);
fd6481cf 6591 if (t == NULL)
6592 t3 = null_pointer_node;
6593 else
389dd41b 6594 t3 = build_fold_addr_expr_loc (loc, t);
fd6481cf 6595
43895be5 6596 if (taskloop_p)
6597 t = build_call_expr (ull
6598 ? builtin_decl_explicit (BUILT_IN_GOMP_TASKLOOP_ULL)
6599 : builtin_decl_explicit (BUILT_IN_GOMP_TASKLOOP),
6600 11, t1, t2, t3,
6601 gimple_omp_task_arg_size (entry_stmt),
6602 gimple_omp_task_arg_align (entry_stmt), flags,
6603 num_tasks, priority, startvar, endvar, step);
6604 else
6605 t = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK),
6606 9, t1, t2, t3,
6607 gimple_omp_task_arg_size (entry_stmt),
6608 gimple_omp_task_arg_align (entry_stmt), cond, flags,
6609 depend, priority);
fd6481cf 6610
75a70cf9 6611 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6612 false, GSI_CONTINUE_LINKING);
fd6481cf 6613}
6614
6615
75a70cf9 6616/* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
6617 catch handler and return it. This prevents programs from violating the
6618 structured block semantics with throws. */
1e8e9920 6619
75a70cf9 6620static gimple_seq
6621maybe_catch_exception (gimple_seq body)
1e8e9920 6622{
42acab1c 6623 gimple *g;
e38def9c 6624 tree decl;
1e8e9920 6625
6626 if (!flag_exceptions)
75a70cf9 6627 return body;
1e8e9920 6628
596981c8 6629 if (lang_hooks.eh_protect_cleanup_actions != NULL)
6630 decl = lang_hooks.eh_protect_cleanup_actions ();
1e8e9920 6631 else
b9a16870 6632 decl = builtin_decl_explicit (BUILT_IN_TRAP);
75a70cf9 6633
e38def9c 6634 g = gimple_build_eh_must_not_throw (decl);
6635 g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g),
75a70cf9 6636 GIMPLE_TRY_CATCH);
1e8e9920 6637
e38def9c 6638 return gimple_seq_alloc_with_stmt (g);
1e8e9920 6639}
6640
773c5ba7 6641/* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
1e8e9920 6642
773c5ba7 6643static tree
f1f41a6c 6644vec2chain (vec<tree, va_gc> *v)
1e8e9920 6645{
2ab2ce89 6646 tree chain = NULL_TREE, t;
6647 unsigned ix;
1e8e9920 6648
f1f41a6c 6649 FOR_EACH_VEC_SAFE_ELT_REVERSE (v, ix, t)
773c5ba7 6650 {
1767a056 6651 DECL_CHAIN (t) = chain;
2ab2ce89 6652 chain = t;
773c5ba7 6653 }
1e8e9920 6654
2ab2ce89 6655 return chain;
773c5ba7 6656}
1e8e9920 6657
1e8e9920 6658
773c5ba7 6659/* Remove barriers in REGION->EXIT's block. Note that this is only
75a70cf9 6660 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
6661 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
6662 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
773c5ba7 6663 removed. */
1e8e9920 6664
773c5ba7 6665static void
6666remove_exit_barrier (struct omp_region *region)
6667{
75a70cf9 6668 gimple_stmt_iterator gsi;
773c5ba7 6669 basic_block exit_bb;
61e47ac8 6670 edge_iterator ei;
6671 edge e;
42acab1c 6672 gimple *stmt;
4a04f4b4 6673 int any_addressable_vars = -1;
1e8e9920 6674
61e47ac8 6675 exit_bb = region->exit;
1e8e9920 6676
5056ba1a 6677 /* If the parallel region doesn't return, we don't have REGION->EXIT
6678 block at all. */
6679 if (! exit_bb)
6680 return;
6681
75a70cf9 6682 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
6683 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
61e47ac8 6684 statements that can appear in between are extremely limited -- no
6685 memory operations at all. Here, we allow nothing at all, so the
75a70cf9 6686 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
6687 gsi = gsi_last_bb (exit_bb);
6688 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
6689 gsi_prev (&gsi);
6690 if (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
773c5ba7 6691 return;
1e8e9920 6692
61e47ac8 6693 FOR_EACH_EDGE (e, ei, exit_bb->preds)
6694 {
75a70cf9 6695 gsi = gsi_last_bb (e->src);
6696 if (gsi_end_p (gsi))
61e47ac8 6697 continue;
75a70cf9 6698 stmt = gsi_stmt (gsi);
4a04f4b4 6699 if (gimple_code (stmt) == GIMPLE_OMP_RETURN
6700 && !gimple_omp_return_nowait_p (stmt))
6701 {
6702 /* OpenMP 3.0 tasks unfortunately prevent this optimization
6703 in many cases. If there could be tasks queued, the barrier
6704 might be needed to let the tasks run before some local
6705 variable of the parallel that the task uses as shared
6706 runs out of scope. The task can be spawned either
6707 from within current function (this would be easy to check)
6708 or from some function it calls and gets passed an address
6709 of such a variable. */
6710 if (any_addressable_vars < 0)
6711 {
1a91d914 6712 gomp_parallel *parallel_stmt
6713 = as_a <gomp_parallel *> (last_stmt (region->entry));
4a04f4b4 6714 tree child_fun = gimple_omp_parallel_child_fn (parallel_stmt);
2ab2ce89 6715 tree local_decls, block, decl;
6716 unsigned ix;
4a04f4b4 6717
6718 any_addressable_vars = 0;
2ab2ce89 6719 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun), ix, decl)
6720 if (TREE_ADDRESSABLE (decl))
4a04f4b4 6721 {
6722 any_addressable_vars = 1;
6723 break;
6724 }
6725 for (block = gimple_block (stmt);
6726 !any_addressable_vars
6727 && block
6728 && TREE_CODE (block) == BLOCK;
6729 block = BLOCK_SUPERCONTEXT (block))
6730 {
6731 for (local_decls = BLOCK_VARS (block);
6732 local_decls;
1767a056 6733 local_decls = DECL_CHAIN (local_decls))
4a04f4b4 6734 if (TREE_ADDRESSABLE (local_decls))
6735 {
6736 any_addressable_vars = 1;
6737 break;
6738 }
6739 if (block == gimple_block (parallel_stmt))
6740 break;
6741 }
6742 }
6743 if (!any_addressable_vars)
6744 gimple_omp_return_set_nowait (stmt);
6745 }
61e47ac8 6746 }
1e8e9920 6747}
6748
61e47ac8 6749static void
6750remove_exit_barriers (struct omp_region *region)
6751{
75a70cf9 6752 if (region->type == GIMPLE_OMP_PARALLEL)
61e47ac8 6753 remove_exit_barrier (region);
6754
6755 if (region->inner)
6756 {
6757 region = region->inner;
6758 remove_exit_barriers (region);
6759 while (region->next)
6760 {
6761 region = region->next;
6762 remove_exit_barriers (region);
6763 }
6764 }
6765}
773c5ba7 6766
658b4427 6767/* Optimize omp_get_thread_num () and omp_get_num_threads ()
6768 calls. These can't be declared as const functions, but
6769 within one parallel body they are constant, so they can be
6770 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
fd6481cf 6771 which are declared const. Similarly for task body, except
6772 that in untied task omp_get_thread_num () can change at any task
6773 scheduling point. */
658b4427 6774
6775static void
42acab1c 6776optimize_omp_library_calls (gimple *entry_stmt)
658b4427 6777{
6778 basic_block bb;
75a70cf9 6779 gimple_stmt_iterator gsi;
b9a16870 6780 tree thr_num_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
6781 tree thr_num_id = DECL_ASSEMBLER_NAME (thr_num_tree);
6782 tree num_thr_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
6783 tree num_thr_id = DECL_ASSEMBLER_NAME (num_thr_tree);
75a70cf9 6784 bool untied_task = (gimple_code (entry_stmt) == GIMPLE_OMP_TASK
6785 && find_omp_clause (gimple_omp_task_clauses (entry_stmt),
fd6481cf 6786 OMP_CLAUSE_UNTIED) != NULL);
658b4427 6787
fc00614f 6788 FOR_EACH_BB_FN (bb, cfun)
75a70cf9 6789 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
658b4427 6790 {
42acab1c 6791 gimple *call = gsi_stmt (gsi);
658b4427 6792 tree decl;
6793
75a70cf9 6794 if (is_gimple_call (call)
6795 && (decl = gimple_call_fndecl (call))
658b4427 6796 && DECL_EXTERNAL (decl)
6797 && TREE_PUBLIC (decl)
6798 && DECL_INITIAL (decl) == NULL)
6799 {
6800 tree built_in;
6801
6802 if (DECL_NAME (decl) == thr_num_id)
fd6481cf 6803 {
6804 /* In #pragma omp task untied omp_get_thread_num () can change
6805 during the execution of the task region. */
6806 if (untied_task)
6807 continue;
b9a16870 6808 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
fd6481cf 6809 }
658b4427 6810 else if (DECL_NAME (decl) == num_thr_id)
b9a16870 6811 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
658b4427 6812 else
6813 continue;
6814
6815 if (DECL_ASSEMBLER_NAME (decl) != DECL_ASSEMBLER_NAME (built_in)
75a70cf9 6816 || gimple_call_num_args (call) != 0)
658b4427 6817 continue;
6818
6819 if (flag_exceptions && !TREE_NOTHROW (decl))
6820 continue;
6821
6822 if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
1ea6a73c 6823 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl)),
6824 TREE_TYPE (TREE_TYPE (built_in))))
658b4427 6825 continue;
6826
0acacf9e 6827 gimple_call_set_fndecl (call, built_in);
658b4427 6828 }
6829 }
6830}
6831
8e6b4515 6832/* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
6833 regimplified. */
6834
6835static tree
6836expand_omp_regimplify_p (tree *tp, int *walk_subtrees, void *)
6837{
6838 tree t = *tp;
6839
6840 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
6841 if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t))
6842 return t;
6843
6844 if (TREE_CODE (t) == ADDR_EXPR)
6845 recompute_tree_invariant_for_addr_expr (t);
6846
6847 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
6848 return NULL_TREE;
6849}
6850
43895be5 6851/* Prepend or append TO = FROM assignment before or after *GSI_P. */
3d483a94 6852
6853static void
43895be5 6854expand_omp_build_assign (gimple_stmt_iterator *gsi_p, tree to, tree from,
6855 bool after)
3d483a94 6856{
6857 bool simple_p = DECL_P (to) && TREE_ADDRESSABLE (to);
6858 from = force_gimple_operand_gsi (gsi_p, from, simple_p, NULL_TREE,
43895be5 6859 !after, after ? GSI_CONTINUE_LINKING
6860 : GSI_SAME_STMT);
42acab1c 6861 gimple *stmt = gimple_build_assign (to, from);
43895be5 6862 if (after)
6863 gsi_insert_after (gsi_p, stmt, GSI_CONTINUE_LINKING);
6864 else
6865 gsi_insert_before (gsi_p, stmt, GSI_SAME_STMT);
3d483a94 6866 if (walk_tree (&from, expand_omp_regimplify_p, NULL, NULL)
6867 || walk_tree (&to, expand_omp_regimplify_p, NULL, NULL))
6868 {
6869 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
6870 gimple_regimplify_operands (stmt, &gsi);
6871 }
6872}
6873
fd6481cf 6874/* Expand the OpenMP parallel or task directive starting at REGION. */
1e8e9920 6875
6876static void
fd6481cf 6877expand_omp_taskreg (struct omp_region *region)
1e8e9920 6878{
773c5ba7 6879 basic_block entry_bb, exit_bb, new_bb;
87d4aa85 6880 struct function *child_cfun;
414c3a2c 6881 tree child_fn, block, t;
75a70cf9 6882 gimple_stmt_iterator gsi;
42acab1c 6883 gimple *entry_stmt, *stmt;
773c5ba7 6884 edge e;
f1f41a6c 6885 vec<tree, va_gc> *ws_args;
773c5ba7 6886
61e47ac8 6887 entry_stmt = last_stmt (region->entry);
75a70cf9 6888 child_fn = gimple_omp_taskreg_child_fn (entry_stmt);
773c5ba7 6889 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
773c5ba7 6890
61e47ac8 6891 entry_bb = region->entry;
b25f70fd 6892 if (gimple_code (entry_stmt) == GIMPLE_OMP_TASK)
6893 exit_bb = region->cont;
6894 else
6895 exit_bb = region->exit;
773c5ba7 6896
40750995 6897 bool is_cilk_for
6898 = (flag_cilkplus
6899 && gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL
6900 && find_omp_clause (gimple_omp_parallel_clauses (entry_stmt),
6901 OMP_CLAUSE__CILK_FOR_COUNT_) != NULL_TREE);
6902
6903 if (is_cilk_for)
6904 /* If it is a _Cilk_for statement, it is modelled *like* a parallel for,
6905 and the inner statement contains the name of the built-in function
6906 and grain. */
6907 ws_args = region->inner->ws_args;
6908 else if (is_combined_parallel (region))
61e47ac8 6909 ws_args = region->ws_args;
773c5ba7 6910 else
414c3a2c 6911 ws_args = NULL;
1e8e9920 6912
61e47ac8 6913 if (child_cfun->cfg)
1e8e9920 6914 {
773c5ba7 6915 /* Due to inlining, it may happen that we have already outlined
6916 the region, in which case all we need to do is make the
6917 sub-graph unreachable and emit the parallel call. */
6918 edge entry_succ_e, exit_succ_e;
773c5ba7 6919
6920 entry_succ_e = single_succ_edge (entry_bb);
773c5ba7 6921
75a70cf9 6922 gsi = gsi_last_bb (entry_bb);
6923 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_PARALLEL
6924 || gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_TASK);
6925 gsi_remove (&gsi, true);
773c5ba7 6926
6927 new_bb = entry_bb;
03ed154b 6928 if (exit_bb)
6929 {
6930 exit_succ_e = single_succ_edge (exit_bb);
6931 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
6932 }
79acaae1 6933 remove_edge_and_dominated_blocks (entry_succ_e);
1e8e9920 6934 }
773c5ba7 6935 else
6936 {
501bdd19 6937 unsigned srcidx, dstidx, num;
2ab2ce89 6938
773c5ba7 6939 /* If the parallel region needs data sent from the parent
3480139d 6940 function, then the very first statement (except possible
6941 tree profile counter updates) of the parallel body
773c5ba7 6942 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
6943 &.OMP_DATA_O is passed as an argument to the child function,
6944 we need to replace it with the argument as seen by the child
6945 function.
6946
6947 In most cases, this will end up being the identity assignment
6948 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
6949 a function call that has been inlined, the original PARM_DECL
6950 .OMP_DATA_I may have been converted into a different local
6951 variable. In which case, we need to keep the assignment. */
75a70cf9 6952 if (gimple_omp_taskreg_data_arg (entry_stmt))
773c5ba7 6953 {
b25f70fd 6954 basic_block entry_succ_bb
6955 = single_succ_p (entry_bb) ? single_succ (entry_bb)
6956 : FALLTHRU_EDGE (entry_bb)->dest;
883f001d 6957 tree arg;
42acab1c 6958 gimple *parcopy_stmt = NULL;
1e8e9920 6959
75a70cf9 6960 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
3480139d 6961 {
42acab1c 6962 gimple *stmt;
3480139d 6963
75a70cf9 6964 gcc_assert (!gsi_end_p (gsi));
6965 stmt = gsi_stmt (gsi);
6966 if (gimple_code (stmt) != GIMPLE_ASSIGN)
cc6b725b 6967 continue;
6968
75a70cf9 6969 if (gimple_num_ops (stmt) == 2)
3480139d 6970 {
75a70cf9 6971 tree arg = gimple_assign_rhs1 (stmt);
6972
6973 /* We're ignore the subcode because we're
6974 effectively doing a STRIP_NOPS. */
6975
6976 if (TREE_CODE (arg) == ADDR_EXPR
6977 && TREE_OPERAND (arg, 0)
6978 == gimple_omp_taskreg_data_arg (entry_stmt))
6979 {
6980 parcopy_stmt = stmt;
6981 break;
6982 }
3480139d 6983 }
6984 }
79acaae1 6985
75a70cf9 6986 gcc_assert (parcopy_stmt != NULL);
79acaae1 6987 arg = DECL_ARGUMENTS (child_fn);
6988
6989 if (!gimple_in_ssa_p (cfun))
6990 {
75a70cf9 6991 if (gimple_assign_lhs (parcopy_stmt) == arg)
6992 gsi_remove (&gsi, true);
79acaae1 6993 else
75a70cf9 6994 {
6995 /* ?? Is setting the subcode really necessary ?? */
6996 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (arg));
6997 gimple_assign_set_rhs1 (parcopy_stmt, arg);
6998 }
79acaae1 6999 }
7000 else
7001 {
883f001d 7002 tree lhs = gimple_assign_lhs (parcopy_stmt);
7003 gcc_assert (SSA_NAME_VAR (lhs) == arg);
7004 /* We'd like to set the rhs to the default def in the child_fn,
7005 but it's too early to create ssa names in the child_fn.
7006 Instead, we set the rhs to the parm. In
7007 move_sese_region_to_fn, we introduce a default def for the
7008 parm, map the parm to it's default def, and once we encounter
7009 this stmt, replace the parm with the default def. */
7010 gimple_assign_set_rhs1 (parcopy_stmt, arg);
79acaae1 7011 update_stmt (parcopy_stmt);
7012 }
773c5ba7 7013 }
7014
7015 /* Declare local variables needed in CHILD_CFUN. */
7016 block = DECL_INITIAL (child_fn);
2ab2ce89 7017 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
e1a7ccb9 7018 /* The gimplifier could record temporaries in parallel/task block
7019 rather than in containing function's local_decls chain,
7020 which would mean cgraph missed finalizing them. Do it now. */
1767a056 7021 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
e1a7ccb9 7022 if (TREE_CODE (t) == VAR_DECL
7023 && TREE_STATIC (t)
7024 && !DECL_EXTERNAL (t))
97221fd7 7025 varpool_node::finalize_decl (t);
75a70cf9 7026 DECL_SAVED_TREE (child_fn) = NULL;
e3a19533 7027 /* We'll create a CFG for child_fn, so no gimple body is needed. */
7028 gimple_set_body (child_fn, NULL);
1d22f541 7029 TREE_USED (block) = 1;
773c5ba7 7030
79acaae1 7031 /* Reset DECL_CONTEXT on function arguments. */
1767a056 7032 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
773c5ba7 7033 DECL_CONTEXT (t) = child_fn;
7034
75a70cf9 7035 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
7036 so that it can be moved to the child function. */
7037 gsi = gsi_last_bb (entry_bb);
7038 stmt = gsi_stmt (gsi);
7039 gcc_assert (stmt && (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
7040 || gimple_code (stmt) == GIMPLE_OMP_TASK));
75a70cf9 7041 e = split_block (entry_bb, stmt);
923635e7 7042 gsi_remove (&gsi, true);
773c5ba7 7043 entry_bb = e->dest;
b25f70fd 7044 edge e2 = NULL;
7045 if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
7046 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7047 else
7048 {
7049 e2 = make_edge (e->src, BRANCH_EDGE (entry_bb)->dest, EDGE_ABNORMAL);
7050 gcc_assert (e2->dest == region->exit);
7051 remove_edge (BRANCH_EDGE (entry_bb));
7052 set_immediate_dominator (CDI_DOMINATORS, e2->dest, e->src);
7053 gsi = gsi_last_bb (region->exit);
7054 gcc_assert (!gsi_end_p (gsi)
7055 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
7056 gsi_remove (&gsi, true);
7057 }
773c5ba7 7058
b25f70fd 7059 /* Convert GIMPLE_OMP_{RETURN,CONTINUE} into a RETURN_EXPR. */
5056ba1a 7060 if (exit_bb)
7061 {
75a70cf9 7062 gsi = gsi_last_bb (exit_bb);
7063 gcc_assert (!gsi_end_p (gsi)
b25f70fd 7064 && (gimple_code (gsi_stmt (gsi))
7065 == (e2 ? GIMPLE_OMP_CONTINUE : GIMPLE_OMP_RETURN)));
75a70cf9 7066 stmt = gimple_build_return (NULL);
7067 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
7068 gsi_remove (&gsi, true);
5056ba1a 7069 }
79acaae1 7070
7071 /* Move the parallel region into CHILD_CFUN. */
48e1416a 7072
79acaae1 7073 if (gimple_in_ssa_p (cfun))
7074 {
bcaa2770 7075 init_tree_ssa (child_cfun);
5084b2e4 7076 init_ssa_operands (child_cfun);
7077 child_cfun->gimple_df->in_ssa_p = true;
1d22f541 7078 block = NULL_TREE;
79acaae1 7079 }
1d22f541 7080 else
75a70cf9 7081 block = gimple_block (entry_stmt);
1d22f541 7082
7083 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
79acaae1 7084 if (exit_bb)
7085 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
b25f70fd 7086 if (e2)
7087 {
7088 basic_block dest_bb = e2->dest;
7089 if (!exit_bb)
7090 make_edge (new_bb, dest_bb, EDGE_FALLTHRU);
7091 remove_edge (e2);
7092 set_immediate_dominator (CDI_DOMINATORS, dest_bb, new_bb);
7093 }
04c2922b 7094 /* When the OMP expansion process cannot guarantee an up-to-date
7095 loop tree arrange for the child function to fixup loops. */
7096 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
7097 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
79acaae1 7098
1d22f541 7099 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
f1f41a6c 7100 num = vec_safe_length (child_cfun->local_decls);
501bdd19 7101 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
7102 {
f1f41a6c 7103 t = (*child_cfun->local_decls)[srcidx];
501bdd19 7104 if (DECL_CONTEXT (t) == cfun->decl)
7105 continue;
7106 if (srcidx != dstidx)
f1f41a6c 7107 (*child_cfun->local_decls)[dstidx] = t;
501bdd19 7108 dstidx++;
7109 }
7110 if (dstidx != num)
f1f41a6c 7111 vec_safe_truncate (child_cfun->local_decls, dstidx);
1d22f541 7112
79acaae1 7113 /* Inform the callgraph about the new function. */
9918db44 7114 child_cfun->curr_properties = cfun->curr_properties;
7115 child_cfun->has_simduid_loops |= cfun->has_simduid_loops;
7116 child_cfun->has_force_vectorize_loops |= cfun->has_force_vectorize_loops;
47300487 7117 cgraph_node *node = cgraph_node::get_create (child_fn);
7118 node->parallelized_function = 1;
415d1b9a 7119 cgraph_node::add_new_function (child_fn, true);
79acaae1 7120
9561765e 7121 bool need_asm = DECL_ASSEMBLER_NAME_SET_P (current_function_decl)
7122 && !DECL_ASSEMBLER_NAME_SET_P (child_fn);
7123
79acaae1 7124 /* Fix the callgraph edges for child_cfun. Those for cfun will be
7125 fixed in a following pass. */
7126 push_cfun (child_cfun);
9561765e 7127 if (need_asm)
7128 assign_assembler_name_if_neeeded (child_fn);
7129
658b4427 7130 if (optimize)
fd6481cf 7131 optimize_omp_library_calls (entry_stmt);
35ee1c66 7132 cgraph_edge::rebuild_edges ();
fbe86b1b 7133
7134 /* Some EH regions might become dead, see PR34608. If
7135 pass_cleanup_cfg isn't the first pass to happen with the
7136 new child, these dead EH edges might cause problems.
7137 Clean them up now. */
7138 if (flag_exceptions)
7139 {
7140 basic_block bb;
fbe86b1b 7141 bool changed = false;
7142
fc00614f 7143 FOR_EACH_BB_FN (bb, cfun)
75a70cf9 7144 changed |= gimple_purge_dead_eh_edges (bb);
fbe86b1b 7145 if (changed)
7146 cleanup_tree_cfg ();
fbe86b1b 7147 }
dd277d48 7148 if (gimple_in_ssa_p (cfun))
7149 update_ssa (TODO_update_ssa);
382ecba7 7150 if (flag_checking && !loops_state_satisfies_p (LOOPS_NEED_FIXUP))
86a932e0 7151 verify_loop_structure ();
79acaae1 7152 pop_cfun ();
9561765e 7153
7154 if (dump_file && !gimple_in_ssa_p (cfun))
7155 {
7156 omp_any_child_fn_dumped = true;
7157 dump_function_header (dump_file, child_fn, dump_flags);
7158 dump_function_to_file (child_fn, dump_file, dump_flags);
7159 }
773c5ba7 7160 }
48e1416a 7161
773c5ba7 7162 /* Emit a library call to launch the children threads. */
40750995 7163 if (is_cilk_for)
1a91d914 7164 expand_cilk_for_call (new_bb,
7165 as_a <gomp_parallel *> (entry_stmt), ws_args);
40750995 7166 else if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
1a91d914 7167 expand_parallel_call (region, new_bb,
7168 as_a <gomp_parallel *> (entry_stmt), ws_args);
fd6481cf 7169 else
43895be5 7170 expand_task_call (region, new_bb, as_a <gomp_task *> (entry_stmt));
083152fb 7171 if (gimple_in_ssa_p (cfun))
7172 update_ssa (TODO_update_ssa_only_virtuals);
1e8e9920 7173}
7174
a8e785ba 7175/* Information about members of an OpenACC collapsed loop nest. */
7176
7177struct oacc_collapse
7178{
7179 tree base; /* Base value. */
7180 tree iters; /* Number of steps. */
7181 tree step; /* step size. */
7182};
7183
7184/* Helper for expand_oacc_for. Determine collapsed loop information.
7185 Fill in COUNTS array. Emit any initialization code before GSI.
7186 Return the calculated outer loop bound of BOUND_TYPE. */
7187
7188static tree
7189expand_oacc_collapse_init (const struct omp_for_data *fd,
7190 gimple_stmt_iterator *gsi,
7191 oacc_collapse *counts, tree bound_type)
7192{
7193 tree total = build_int_cst (bound_type, 1);
7194 int ix;
7195
7196 gcc_assert (integer_onep (fd->loop.step));
7197 gcc_assert (integer_zerop (fd->loop.n1));
7198
7199 for (ix = 0; ix != fd->collapse; ix++)
7200 {
7201 const omp_for_data_loop *loop = &fd->loops[ix];
7202
7203 tree iter_type = TREE_TYPE (loop->v);
7204 tree diff_type = iter_type;
7205 tree plus_type = iter_type;
7206
7207 gcc_assert (loop->cond_code == fd->loop.cond_code);
7208
7209 if (POINTER_TYPE_P (iter_type))
7210 plus_type = sizetype;
7211 if (POINTER_TYPE_P (diff_type) || TYPE_UNSIGNED (diff_type))
7212 diff_type = signed_type_for (diff_type);
7213
7214 tree b = loop->n1;
7215 tree e = loop->n2;
7216 tree s = loop->step;
7217 bool up = loop->cond_code == LT_EXPR;
7218 tree dir = build_int_cst (diff_type, up ? +1 : -1);
7219 bool negating;
7220 tree expr;
7221
7222 b = force_gimple_operand_gsi (gsi, b, true, NULL_TREE,
7223 true, GSI_SAME_STMT);
7224 e = force_gimple_operand_gsi (gsi, e, true, NULL_TREE,
7225 true, GSI_SAME_STMT);
7226
7227 /* Convert the step, avoiding possible unsigned->signed overflow. */
7228 negating = !up && TYPE_UNSIGNED (TREE_TYPE (s));
7229 if (negating)
7230 s = fold_build1 (NEGATE_EXPR, TREE_TYPE (s), s);
7231 s = fold_convert (diff_type, s);
7232 if (negating)
7233 s = fold_build1 (NEGATE_EXPR, diff_type, s);
7234 s = force_gimple_operand_gsi (gsi, s, true, NULL_TREE,
7235 true, GSI_SAME_STMT);
7236
7237 /* Determine the range, avoiding possible unsigned->signed overflow. */
7238 negating = !up && TYPE_UNSIGNED (iter_type);
7239 expr = fold_build2 (MINUS_EXPR, plus_type,
7240 fold_convert (plus_type, negating ? b : e),
7241 fold_convert (plus_type, negating ? e : b));
7242 expr = fold_convert (diff_type, expr);
7243 if (negating)
7244 expr = fold_build1 (NEGATE_EXPR, diff_type, expr);
7245 tree range = force_gimple_operand_gsi
7246 (gsi, expr, true, NULL_TREE, true, GSI_SAME_STMT);
7247
7248 /* Determine number of iterations. */
7249 expr = fold_build2 (MINUS_EXPR, diff_type, range, dir);
7250 expr = fold_build2 (PLUS_EXPR, diff_type, expr, s);
7251 expr = fold_build2 (TRUNC_DIV_EXPR, diff_type, expr, s);
7252
7253 tree iters = force_gimple_operand_gsi (gsi, expr, true, NULL_TREE,
7254 true, GSI_SAME_STMT);
7255
7256 counts[ix].base = b;
7257 counts[ix].iters = iters;
7258 counts[ix].step = s;
7259
7260 total = fold_build2 (MULT_EXPR, bound_type, total,
7261 fold_convert (bound_type, iters));
7262 }
7263
7264 return total;
7265}
7266
7267/* Emit initializers for collapsed loop members. IVAR is the outer
7268 loop iteration variable, from which collapsed loop iteration values
7269 are calculated. COUNTS array has been initialized by
7270 expand_oacc_collapse_inits. */
7271
7272static void
7273expand_oacc_collapse_vars (const struct omp_for_data *fd,
7274 gimple_stmt_iterator *gsi,
7275 const oacc_collapse *counts, tree ivar)
7276{
7277 tree ivar_type = TREE_TYPE (ivar);
7278
7279 /* The most rapidly changing iteration variable is the innermost
7280 one. */
7281 for (int ix = fd->collapse; ix--;)
7282 {
7283 const omp_for_data_loop *loop = &fd->loops[ix];
7284 const oacc_collapse *collapse = &counts[ix];
7285 tree iter_type = TREE_TYPE (loop->v);
7286 tree diff_type = TREE_TYPE (collapse->step);
7287 tree plus_type = iter_type;
7288 enum tree_code plus_code = PLUS_EXPR;
7289 tree expr;
7290
7291 if (POINTER_TYPE_P (iter_type))
7292 {
7293 plus_code = POINTER_PLUS_EXPR;
7294 plus_type = sizetype;
7295 }
7296
7297 expr = fold_build2 (TRUNC_MOD_EXPR, ivar_type, ivar,
7298 fold_convert (ivar_type, collapse->iters));
7299 expr = fold_build2 (MULT_EXPR, diff_type, fold_convert (diff_type, expr),
7300 collapse->step);
7301 expr = fold_build2 (plus_code, iter_type, collapse->base,
7302 fold_convert (plus_type, expr));
7303 expr = force_gimple_operand_gsi (gsi, expr, false, NULL_TREE,
7304 true, GSI_SAME_STMT);
7305 gassign *ass = gimple_build_assign (loop->v, expr);
7306 gsi_insert_before (gsi, ass, GSI_SAME_STMT);
7307
7308 if (ix)
7309 {
7310 expr = fold_build2 (TRUNC_DIV_EXPR, ivar_type, ivar,
7311 fold_convert (ivar_type, collapse->iters));
7312 ivar = force_gimple_operand_gsi (gsi, expr, true, NULL_TREE,
7313 true, GSI_SAME_STMT);
7314 }
7315 }
7316}
7317
773c5ba7 7318
3d483a94 7319/* Helper function for expand_omp_{for_*,simd}. If this is the outermost
7320 of the combined collapse > 1 loop constructs, generate code like:
7321 if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
7322 if (cond3 is <)
7323 adj = STEP3 - 1;
7324 else
7325 adj = STEP3 + 1;
7326 count3 = (adj + N32 - N31) / STEP3;
7327 if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
7328 if (cond2 is <)
7329 adj = STEP2 - 1;
7330 else
7331 adj = STEP2 + 1;
7332 count2 = (adj + N22 - N21) / STEP2;
7333 if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
7334 if (cond1 is <)
7335 adj = STEP1 - 1;
7336 else
7337 adj = STEP1 + 1;
7338 count1 = (adj + N12 - N11) / STEP1;
7339 count = count1 * count2 * count3;
7340 Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
7341 count = 0;
bc7bff74 7342 and set ZERO_ITER_BB to that bb. If this isn't the outermost
7343 of the combined loop constructs, just initialize COUNTS array
7344 from the _looptemp_ clauses. */
3d483a94 7345
7346/* NOTE: It *could* be better to moosh all of the BBs together,
7347 creating one larger BB with all the computation and the unexpected
7348 jump at the end. I.e.
7349
7350 bool zero3, zero2, zero1, zero;
7351
7352 zero3 = N32 c3 N31;
7353 count3 = (N32 - N31) /[cl] STEP3;
7354 zero2 = N22 c2 N21;
7355 count2 = (N22 - N21) /[cl] STEP2;
7356 zero1 = N12 c1 N11;
7357 count1 = (N12 - N11) /[cl] STEP1;
7358 zero = zero3 || zero2 || zero1;
7359 count = count1 * count2 * count3;
7360 if (__builtin_expect(zero, false)) goto zero_iter_bb;
7361
7362 After all, we expect the zero=false, and thus we expect to have to
7363 evaluate all of the comparison expressions, so short-circuiting
7364 oughtn't be a win. Since the condition isn't protecting a
7365 denominator, we're not concerned about divide-by-zero, so we can
7366 fully evaluate count even if a numerator turned out to be wrong.
7367
7368 It seems like putting this all together would create much better
7369 scheduling opportunities, and less pressure on the chip's branch
7370 predictor. */
7371
7372static void
7373expand_omp_for_init_counts (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
7374 basic_block &entry_bb, tree *counts,
43895be5 7375 basic_block &zero_iter1_bb, int &first_zero_iter1,
7376 basic_block &zero_iter2_bb, int &first_zero_iter2,
3d483a94 7377 basic_block &l2_dom_bb)
7378{
7379 tree t, type = TREE_TYPE (fd->loop.v);
3d483a94 7380 edge e, ne;
7381 int i;
7382
7383 /* Collapsed loops need work for expansion into SSA form. */
7384 gcc_assert (!gimple_in_ssa_p (cfun));
7385
bc7bff74 7386 if (gimple_omp_for_combined_into_p (fd->for_stmt)
7387 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
7388 {
43895be5 7389 gcc_assert (fd->ordered == 0);
bc7bff74 7390 /* First two _looptemp_ clauses are for istart/iend, counts[0]
7391 isn't supposed to be handled, as the inner loop doesn't
7392 use it. */
7393 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7394 OMP_CLAUSE__LOOPTEMP_);
7395 gcc_assert (innerc);
7396 for (i = 0; i < fd->collapse; i++)
7397 {
7398 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7399 OMP_CLAUSE__LOOPTEMP_);
7400 gcc_assert (innerc);
7401 if (i)
7402 counts[i] = OMP_CLAUSE_DECL (innerc);
7403 else
7404 counts[0] = NULL_TREE;
7405 }
7406 return;
7407 }
7408
43895be5 7409 for (i = fd->collapse; i < fd->ordered; i++)
7410 {
7411 tree itype = TREE_TYPE (fd->loops[i].v);
7412 counts[i] = NULL_TREE;
7413 t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
7414 fold_convert (itype, fd->loops[i].n1),
7415 fold_convert (itype, fd->loops[i].n2));
7416 if (t && integer_zerop (t))
7417 {
7418 for (i = fd->collapse; i < fd->ordered; i++)
7419 counts[i] = build_int_cst (type, 0);
7420 break;
7421 }
7422 }
7423 for (i = 0; i < (fd->ordered ? fd->ordered : fd->collapse); i++)
3d483a94 7424 {
7425 tree itype = TREE_TYPE (fd->loops[i].v);
7426
43895be5 7427 if (i >= fd->collapse && counts[i])
7428 continue;
7429 if ((SSA_VAR_P (fd->loop.n2) || i >= fd->collapse)
3d483a94 7430 && ((t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
7431 fold_convert (itype, fd->loops[i].n1),
7432 fold_convert (itype, fd->loops[i].n2)))
7433 == NULL_TREE || !integer_onep (t)))
7434 {
1a91d914 7435 gcond *cond_stmt;
3d483a94 7436 tree n1, n2;
7437 n1 = fold_convert (itype, unshare_expr (fd->loops[i].n1));
7438 n1 = force_gimple_operand_gsi (gsi, n1, true, NULL_TREE,
7439 true, GSI_SAME_STMT);
7440 n2 = fold_convert (itype, unshare_expr (fd->loops[i].n2));
7441 n2 = force_gimple_operand_gsi (gsi, n2, true, NULL_TREE,
7442 true, GSI_SAME_STMT);
1a91d914 7443 cond_stmt = gimple_build_cond (fd->loops[i].cond_code, n1, n2,
7444 NULL_TREE, NULL_TREE);
7445 gsi_insert_before (gsi, cond_stmt, GSI_SAME_STMT);
7446 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
3d483a94 7447 expand_omp_regimplify_p, NULL, NULL)
1a91d914 7448 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
3d483a94 7449 expand_omp_regimplify_p, NULL, NULL))
7450 {
1a91d914 7451 *gsi = gsi_for_stmt (cond_stmt);
7452 gimple_regimplify_operands (cond_stmt, gsi);
3d483a94 7453 }
1a91d914 7454 e = split_block (entry_bb, cond_stmt);
43895be5 7455 basic_block &zero_iter_bb
7456 = i < fd->collapse ? zero_iter1_bb : zero_iter2_bb;
7457 int &first_zero_iter
7458 = i < fd->collapse ? first_zero_iter1 : first_zero_iter2;
3d483a94 7459 if (zero_iter_bb == NULL)
7460 {
1a91d914 7461 gassign *assign_stmt;
3d483a94 7462 first_zero_iter = i;
7463 zero_iter_bb = create_empty_bb (entry_bb);
b3083327 7464 add_bb_to_loop (zero_iter_bb, entry_bb->loop_father);
3d483a94 7465 *gsi = gsi_after_labels (zero_iter_bb);
43895be5 7466 if (i < fd->collapse)
7467 assign_stmt = gimple_build_assign (fd->loop.n2,
7468 build_zero_cst (type));
7469 else
7470 {
7471 counts[i] = create_tmp_reg (type, ".count");
7472 assign_stmt
7473 = gimple_build_assign (counts[i], build_zero_cst (type));
7474 }
1a91d914 7475 gsi_insert_before (gsi, assign_stmt, GSI_SAME_STMT);
3d483a94 7476 set_immediate_dominator (CDI_DOMINATORS, zero_iter_bb,
7477 entry_bb);
7478 }
7479 ne = make_edge (entry_bb, zero_iter_bb, EDGE_FALSE_VALUE);
7480 ne->probability = REG_BR_PROB_BASE / 2000 - 1;
7481 e->flags = EDGE_TRUE_VALUE;
7482 e->probability = REG_BR_PROB_BASE - ne->probability;
7483 if (l2_dom_bb == NULL)
7484 l2_dom_bb = entry_bb;
7485 entry_bb = e->dest;
7486 *gsi = gsi_last_bb (entry_bb);
7487 }
7488
7489 if (POINTER_TYPE_P (itype))
7490 itype = signed_type_for (itype);
7491 t = build_int_cst (itype, (fd->loops[i].cond_code == LT_EXPR
7492 ? -1 : 1));
7493 t = fold_build2 (PLUS_EXPR, itype,
7494 fold_convert (itype, fd->loops[i].step), t);
7495 t = fold_build2 (PLUS_EXPR, itype, t,
7496 fold_convert (itype, fd->loops[i].n2));
7497 t = fold_build2 (MINUS_EXPR, itype, t,
7498 fold_convert (itype, fd->loops[i].n1));
7499 /* ?? We could probably use CEIL_DIV_EXPR instead of
7500 TRUNC_DIV_EXPR and adjusting by hand. Unless we can't
7501 generate the same code in the end because generically we
7502 don't know that the values involved must be negative for
7503 GT?? */
7504 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
7505 t = fold_build2 (TRUNC_DIV_EXPR, itype,
7506 fold_build1 (NEGATE_EXPR, itype, t),
7507 fold_build1 (NEGATE_EXPR, itype,
7508 fold_convert (itype,
7509 fd->loops[i].step)));
7510 else
7511 t = fold_build2 (TRUNC_DIV_EXPR, itype, t,
7512 fold_convert (itype, fd->loops[i].step));
7513 t = fold_convert (type, t);
7514 if (TREE_CODE (t) == INTEGER_CST)
7515 counts[i] = t;
7516 else
7517 {
43895be5 7518 if (i < fd->collapse || i != first_zero_iter2)
7519 counts[i] = create_tmp_reg (type, ".count");
3d483a94 7520 expand_omp_build_assign (gsi, counts[i], t);
7521 }
43895be5 7522 if (SSA_VAR_P (fd->loop.n2) && i < fd->collapse)
3d483a94 7523 {
7524 if (i == 0)
7525 t = counts[0];
7526 else
7527 t = fold_build2 (MULT_EXPR, type, fd->loop.n2, counts[i]);
7528 expand_omp_build_assign (gsi, fd->loop.n2, t);
7529 }
7530 }
7531}
7532
7533
7534/* Helper function for expand_omp_{for_*,simd}. Generate code like:
7535 T = V;
7536 V3 = N31 + (T % count3) * STEP3;
7537 T = T / count3;
7538 V2 = N21 + (T % count2) * STEP2;
7539 T = T / count2;
7540 V1 = N11 + T * STEP1;
bc7bff74 7541 if this loop doesn't have an inner loop construct combined with it.
7542 If it does have an inner loop construct combined with it and the
7543 iteration count isn't known constant, store values from counts array
7544 into its _looptemp_ temporaries instead. */
3d483a94 7545
7546static void
7547expand_omp_for_init_vars (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
42acab1c 7548 tree *counts, gimple *inner_stmt, tree startvar)
3d483a94 7549{
7550 int i;
bc7bff74 7551 if (gimple_omp_for_combined_p (fd->for_stmt))
7552 {
7553 /* If fd->loop.n2 is constant, then no propagation of the counts
7554 is needed, they are constant. */
7555 if (TREE_CODE (fd->loop.n2) == INTEGER_CST)
7556 return;
7557
43895be5 7558 tree clauses = gimple_code (inner_stmt) != GIMPLE_OMP_FOR
7559 ? gimple_omp_taskreg_clauses (inner_stmt)
bc7bff74 7560 : gimple_omp_for_clauses (inner_stmt);
7561 /* First two _looptemp_ clauses are for istart/iend, counts[0]
7562 isn't supposed to be handled, as the inner loop doesn't
7563 use it. */
7564 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
7565 gcc_assert (innerc);
7566 for (i = 0; i < fd->collapse; i++)
7567 {
7568 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7569 OMP_CLAUSE__LOOPTEMP_);
7570 gcc_assert (innerc);
7571 if (i)
7572 {
7573 tree tem = OMP_CLAUSE_DECL (innerc);
7574 tree t = fold_convert (TREE_TYPE (tem), counts[i]);
7575 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
7576 false, GSI_CONTINUE_LINKING);
1a91d914 7577 gassign *stmt = gimple_build_assign (tem, t);
bc7bff74 7578 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7579 }
7580 }
7581 return;
7582 }
7583
3d483a94 7584 tree type = TREE_TYPE (fd->loop.v);
7585 tree tem = create_tmp_reg (type, ".tem");
1a91d914 7586 gassign *stmt = gimple_build_assign (tem, startvar);
3d483a94 7587 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7588
7589 for (i = fd->collapse - 1; i >= 0; i--)
7590 {
7591 tree vtype = TREE_TYPE (fd->loops[i].v), itype, t;
7592 itype = vtype;
7593 if (POINTER_TYPE_P (vtype))
7594 itype = signed_type_for (vtype);
7595 if (i != 0)
7596 t = fold_build2 (TRUNC_MOD_EXPR, type, tem, counts[i]);
7597 else
7598 t = tem;
7599 t = fold_convert (itype, t);
7600 t = fold_build2 (MULT_EXPR, itype, t,
7601 fold_convert (itype, fd->loops[i].step));
7602 if (POINTER_TYPE_P (vtype))
7603 t = fold_build_pointer_plus (fd->loops[i].n1, t);
7604 else
7605 t = fold_build2 (PLUS_EXPR, itype, fd->loops[i].n1, t);
7606 t = force_gimple_operand_gsi (gsi, t,
7607 DECL_P (fd->loops[i].v)
7608 && TREE_ADDRESSABLE (fd->loops[i].v),
7609 NULL_TREE, false,
7610 GSI_CONTINUE_LINKING);
7611 stmt = gimple_build_assign (fd->loops[i].v, t);
7612 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7613 if (i != 0)
7614 {
7615 t = fold_build2 (TRUNC_DIV_EXPR, type, tem, counts[i]);
7616 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
7617 false, GSI_CONTINUE_LINKING);
7618 stmt = gimple_build_assign (tem, t);
7619 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7620 }
7621 }
7622}
7623
7624
7625/* Helper function for expand_omp_for_*. Generate code like:
7626 L10:
7627 V3 += STEP3;
7628 if (V3 cond3 N32) goto BODY_BB; else goto L11;
7629 L11:
7630 V3 = N31;
7631 V2 += STEP2;
7632 if (V2 cond2 N22) goto BODY_BB; else goto L12;
7633 L12:
7634 V2 = N21;
7635 V1 += STEP1;
7636 goto BODY_BB; */
7637
7638static basic_block
7639extract_omp_for_update_vars (struct omp_for_data *fd, basic_block cont_bb,
7640 basic_block body_bb)
7641{
7642 basic_block last_bb, bb, collapse_bb = NULL;
7643 int i;
7644 gimple_stmt_iterator gsi;
7645 edge e;
7646 tree t;
42acab1c 7647 gimple *stmt;
3d483a94 7648
7649 last_bb = cont_bb;
7650 for (i = fd->collapse - 1; i >= 0; i--)
7651 {
7652 tree vtype = TREE_TYPE (fd->loops[i].v);
7653
7654 bb = create_empty_bb (last_bb);
b3083327 7655 add_bb_to_loop (bb, last_bb->loop_father);
3d483a94 7656 gsi = gsi_start_bb (bb);
7657
7658 if (i < fd->collapse - 1)
7659 {
7660 e = make_edge (last_bb, bb, EDGE_FALSE_VALUE);
7661 e->probability = REG_BR_PROB_BASE / 8;
7662
7663 t = fd->loops[i + 1].n1;
7664 t = force_gimple_operand_gsi (&gsi, t,
7665 DECL_P (fd->loops[i + 1].v)
7666 && TREE_ADDRESSABLE (fd->loops[i
7667 + 1].v),
7668 NULL_TREE, false,
7669 GSI_CONTINUE_LINKING);
7670 stmt = gimple_build_assign (fd->loops[i + 1].v, t);
7671 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7672 }
7673 else
7674 collapse_bb = bb;
7675
7676 set_immediate_dominator (CDI_DOMINATORS, bb, last_bb);
7677
7678 if (POINTER_TYPE_P (vtype))
7679 t = fold_build_pointer_plus (fd->loops[i].v, fd->loops[i].step);
7680 else
7681 t = fold_build2 (PLUS_EXPR, vtype, fd->loops[i].v, fd->loops[i].step);
7682 t = force_gimple_operand_gsi (&gsi, t,
7683 DECL_P (fd->loops[i].v)
7684 && TREE_ADDRESSABLE (fd->loops[i].v),
7685 NULL_TREE, false, GSI_CONTINUE_LINKING);
7686 stmt = gimple_build_assign (fd->loops[i].v, t);
7687 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7688
7689 if (i > 0)
7690 {
7691 t = fd->loops[i].n2;
7692 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7693 false, GSI_CONTINUE_LINKING);
7694 tree v = fd->loops[i].v;
7695 if (DECL_P (v) && TREE_ADDRESSABLE (v))
7696 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
7697 false, GSI_CONTINUE_LINKING);
7698 t = fold_build2 (fd->loops[i].cond_code, boolean_type_node, v, t);
7699 stmt = gimple_build_cond_empty (t);
7700 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7701 e = make_edge (bb, body_bb, EDGE_TRUE_VALUE);
7702 e->probability = REG_BR_PROB_BASE * 7 / 8;
7703 }
7704 else
7705 make_edge (bb, body_bb, EDGE_FALLTHRU);
7706 last_bb = bb;
7707 }
7708
7709 return collapse_bb;
7710}
7711
7712
43895be5 7713/* Expand #pragma omp ordered depend(source). */
1e8e9920 7714
43895be5 7715static void
7716expand_omp_ordered_source (gimple_stmt_iterator *gsi, struct omp_for_data *fd,
7717 tree *counts, location_t loc)
7718{
7719 enum built_in_function source_ix
7720 = fd->iter_type == long_integer_type_node
7721 ? BUILT_IN_GOMP_DOACROSS_POST : BUILT_IN_GOMP_DOACROSS_ULL_POST;
7722 gimple *g
7723 = gimple_build_call (builtin_decl_explicit (source_ix), 1,
7724 build_fold_addr_expr (counts[fd->ordered]));
7725 gimple_set_location (g, loc);
7726 gsi_insert_before (gsi, g, GSI_SAME_STMT);
7727}
1e8e9920 7728
43895be5 7729/* Expand a single depend from #pragma omp ordered depend(sink:...). */
1e8e9920 7730
43895be5 7731static void
7732expand_omp_ordered_sink (gimple_stmt_iterator *gsi, struct omp_for_data *fd,
7733 tree *counts, tree c, location_t loc)
7734{
7735 auto_vec<tree, 10> args;
7736 enum built_in_function sink_ix
7737 = fd->iter_type == long_integer_type_node
7738 ? BUILT_IN_GOMP_DOACROSS_WAIT : BUILT_IN_GOMP_DOACROSS_ULL_WAIT;
7739 tree t, off, coff = NULL_TREE, deps = OMP_CLAUSE_DECL (c), cond = NULL_TREE;
7740 int i;
7741 gimple_stmt_iterator gsi2 = *gsi;
7742 bool warned_step = false;
fd6481cf 7743
43895be5 7744 for (i = 0; i < fd->ordered; i++)
7745 {
7746 off = TREE_PURPOSE (deps);
7747 if (!integer_zerop (off))
7748 {
7749 gcc_assert (fd->loops[i].cond_code == LT_EXPR
7750 || fd->loops[i].cond_code == GT_EXPR);
7751 bool forward = fd->loops[i].cond_code == LT_EXPR;
7752 if (forward ^ OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
7753 warning_at (loc, 0, "%<depend(sink)%> clause waiting for "
7754 "lexically later iteration");
7755 break;
7756 }
7757 deps = TREE_CHAIN (deps);
7758 }
7759 /* If all offsets corresponding to the collapsed loops are zero,
7760 this depend clause can be ignored. FIXME: but there is still a
7761 flush needed. We need to emit one __sync_synchronize () for it
7762 though (perhaps conditionally)? Solve this together with the
7763 conservative dependence folding optimization.
7764 if (i >= fd->collapse)
7765 return; */
fd6481cf 7766
43895be5 7767 deps = OMP_CLAUSE_DECL (c);
7768 gsi_prev (&gsi2);
7769 edge e1 = split_block (gsi_bb (gsi2), gsi_stmt (gsi2));
7770 edge e2 = split_block_after_labels (e1->dest);
fd6481cf 7771
43895be5 7772 *gsi = gsi_after_labels (e1->dest);
7773 for (i = 0; i < fd->ordered; i++)
7774 {
7775 tree itype = TREE_TYPE (fd->loops[i].v);
7776 if (POINTER_TYPE_P (itype))
7777 itype = sizetype;
7778 if (i)
7779 deps = TREE_CHAIN (deps);
7780 off = TREE_PURPOSE (deps);
7781 tree s = fold_convert_loc (loc, itype, fd->loops[i].step);
7782
7783 if (integer_zerop (off))
7784 t = boolean_true_node;
7785 else
7786 {
7787 tree a;
7788 tree co = fold_convert_loc (loc, itype, off);
7789 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
7790 {
7791 if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
7792 co = fold_build1_loc (loc, NEGATE_EXPR, itype, co);
7793 a = fold_build2_loc (loc, POINTER_PLUS_EXPR,
7794 TREE_TYPE (fd->loops[i].v), fd->loops[i].v,
7795 co);
7796 }
7797 else if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
7798 a = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (fd->loops[i].v),
7799 fd->loops[i].v, co);
7800 else
7801 a = fold_build2_loc (loc, PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
7802 fd->loops[i].v, co);
7803 if (fd->loops[i].cond_code == LT_EXPR)
7804 {
7805 if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
7806 t = fold_build2_loc (loc, GE_EXPR, boolean_type_node, a,
7807 fd->loops[i].n1);
7808 else
7809 t = fold_build2_loc (loc, LT_EXPR, boolean_type_node, a,
7810 fd->loops[i].n2);
7811 }
7812 else if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
7813 t = fold_build2_loc (loc, GT_EXPR, boolean_type_node, a,
7814 fd->loops[i].n2);
7815 else
7816 t = fold_build2_loc (loc, LE_EXPR, boolean_type_node, a,
7817 fd->loops[i].n1);
7818 }
7819 if (cond)
7820 cond = fold_build2_loc (loc, BIT_AND_EXPR, boolean_type_node, cond, t);
7821 else
7822 cond = t;
7823
7824 off = fold_convert_loc (loc, itype, off);
7825
7826 if (fd->loops[i].cond_code == LT_EXPR
7827 ? !integer_onep (fd->loops[i].step)
7828 : !integer_minus_onep (fd->loops[i].step))
7829 {
7830 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
7831 t = fold_build2_loc (loc, TRUNC_MOD_EXPR, itype, off,
7832 fold_build1_loc (loc, NEGATE_EXPR, itype,
7833 s));
7834 else
7835 t = fold_build2_loc (loc, TRUNC_MOD_EXPR, itype, off, s);
7836 t = fold_build2_loc (loc, EQ_EXPR, boolean_type_node, t,
7837 build_int_cst (itype, 0));
7838 if (integer_zerop (t) && !warned_step)
7839 {
7840 warning_at (loc, 0, "%<depend(sink)%> refers to iteration never "
7841 "in the iteration space");
7842 warned_step = true;
7843 }
7844 cond = fold_build2_loc (loc, BIT_AND_EXPR, boolean_type_node,
7845 cond, t);
7846 }
7847
7848 if (i <= fd->collapse - 1 && fd->collapse > 1)
7849 t = fd->loop.v;
7850 else if (counts[i])
7851 t = counts[i];
7852 else
7853 {
7854 t = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (fd->loops[i].v),
7855 fd->loops[i].v, fd->loops[i].n1);
7856 t = fold_convert_loc (loc, fd->iter_type, t);
7857 }
7858 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
7859 off = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, off,
7860 fold_build1_loc (loc, NEGATE_EXPR, itype,
7861 s));
7862 else
7863 off = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, off, s);
7864 if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
7865 off = fold_build1_loc (loc, NEGATE_EXPR, itype, off);
7866 off = fold_convert_loc (loc, fd->iter_type, off);
7867 if (i <= fd->collapse - 1 && fd->collapse > 1)
7868 {
7869 if (i)
7870 off = fold_build2_loc (loc, PLUS_EXPR, fd->iter_type, coff,
7871 off);
7872 if (i < fd->collapse - 1)
7873 {
7874 coff = fold_build2_loc (loc, MULT_EXPR, fd->iter_type, off,
7875 counts[i]);
7876 continue;
7877 }
7878 }
7879 off = unshare_expr (off);
7880 t = fold_build2_loc (loc, PLUS_EXPR, fd->iter_type, t, off);
7881 t = force_gimple_operand_gsi (gsi, t, true, NULL_TREE,
7882 true, GSI_SAME_STMT);
7883 args.safe_push (t);
7884 }
7885 gimple *g = gimple_build_call_vec (builtin_decl_explicit (sink_ix), args);
7886 gimple_set_location (g, loc);
7887 gsi_insert_before (gsi, g, GSI_SAME_STMT);
7888
7889 *gsi = gsi_last_bb (e1->src);
7890 cond = unshare_expr (cond);
7891 cond = force_gimple_operand_gsi (gsi, cond, true, NULL_TREE, false,
7892 GSI_CONTINUE_LINKING);
7893 gsi_insert_after (gsi, gimple_build_cond_empty (cond), GSI_NEW_STMT);
7894 edge e3 = make_edge (e1->src, e2->dest, EDGE_FALSE_VALUE);
7895 e3->probability = REG_BR_PROB_BASE / 8;
7896 e1->probability = REG_BR_PROB_BASE - e3->probability;
7897 e1->flags = EDGE_TRUE_VALUE;
7898 set_immediate_dominator (CDI_DOMINATORS, e2->dest, e1->src);
7899
7900 *gsi = gsi_after_labels (e2->dest);
7901}
7902
7903/* Expand all #pragma omp ordered depend(source) and
7904 #pragma omp ordered depend(sink:...) constructs in the current
7905 #pragma omp for ordered(n) region. */
7906
7907static void
7908expand_omp_ordered_source_sink (struct omp_region *region,
7909 struct omp_for_data *fd, tree *counts,
7910 basic_block cont_bb)
7911{
7912 struct omp_region *inner;
7913 int i;
7914 for (i = fd->collapse - 1; i < fd->ordered; i++)
7915 if (i == fd->collapse - 1 && fd->collapse > 1)
7916 counts[i] = NULL_TREE;
7917 else if (i >= fd->collapse && !cont_bb)
7918 counts[i] = build_zero_cst (fd->iter_type);
7919 else if (!POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v))
7920 && integer_onep (fd->loops[i].step))
7921 counts[i] = NULL_TREE;
7922 else
7923 counts[i] = create_tmp_var (fd->iter_type, ".orditer");
7924 tree atype
7925 = build_array_type_nelts (fd->iter_type, fd->ordered - fd->collapse + 1);
7926 counts[fd->ordered] = create_tmp_var (atype, ".orditera");
7927 TREE_ADDRESSABLE (counts[fd->ordered]) = 1;
7928
7929 for (inner = region->inner; inner; inner = inner->next)
7930 if (inner->type == GIMPLE_OMP_ORDERED)
7931 {
7932 gomp_ordered *ord_stmt = inner->ord_stmt;
7933 gimple_stmt_iterator gsi = gsi_for_stmt (ord_stmt);
7934 location_t loc = gimple_location (ord_stmt);
7935 tree c;
7936 for (c = gimple_omp_ordered_clauses (ord_stmt);
7937 c; c = OMP_CLAUSE_CHAIN (c))
7938 if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE)
7939 break;
7940 if (c)
7941 expand_omp_ordered_source (&gsi, fd, counts, loc);
7942 for (c = gimple_omp_ordered_clauses (ord_stmt);
7943 c; c = OMP_CLAUSE_CHAIN (c))
7944 if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK)
7945 expand_omp_ordered_sink (&gsi, fd, counts, c, loc);
7946 gsi_remove (&gsi, true);
7947 }
7948}
7949
7950/* Wrap the body into fd->ordered - fd->collapse loops that aren't
7951 collapsed. */
7952
7953static basic_block
7954expand_omp_for_ordered_loops (struct omp_for_data *fd, tree *counts,
7955 basic_block cont_bb, basic_block body_bb,
7956 bool ordered_lastprivate)
7957{
7958 if (fd->ordered == fd->collapse)
7959 return cont_bb;
7960
7961 if (!cont_bb)
7962 {
7963 gimple_stmt_iterator gsi = gsi_after_labels (body_bb);
7964 for (int i = fd->collapse; i < fd->ordered; i++)
7965 {
7966 tree type = TREE_TYPE (fd->loops[i].v);
7967 tree n1 = fold_convert (type, fd->loops[i].n1);
7968 expand_omp_build_assign (&gsi, fd->loops[i].v, n1);
7969 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
7970 size_int (i - fd->collapse + 1),
7971 NULL_TREE, NULL_TREE);
7972 expand_omp_build_assign (&gsi, aref, build_zero_cst (fd->iter_type));
7973 }
7974 return NULL;
7975 }
7976
7977 for (int i = fd->ordered - 1; i >= fd->collapse; i--)
7978 {
7979 tree t, type = TREE_TYPE (fd->loops[i].v);
7980 gimple_stmt_iterator gsi = gsi_after_labels (body_bb);
7981 expand_omp_build_assign (&gsi, fd->loops[i].v,
7982 fold_convert (type, fd->loops[i].n1));
7983 if (counts[i])
7984 expand_omp_build_assign (&gsi, counts[i],
7985 build_zero_cst (fd->iter_type));
7986 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
7987 size_int (i - fd->collapse + 1),
7988 NULL_TREE, NULL_TREE);
7989 expand_omp_build_assign (&gsi, aref, build_zero_cst (fd->iter_type));
7990 if (!gsi_end_p (gsi))
7991 gsi_prev (&gsi);
7992 else
7993 gsi = gsi_last_bb (body_bb);
7994 edge e1 = split_block (body_bb, gsi_stmt (gsi));
7995 basic_block new_body = e1->dest;
7996 if (body_bb == cont_bb)
7997 cont_bb = new_body;
7998 edge e2 = NULL;
7999 basic_block new_header;
8000 if (EDGE_COUNT (cont_bb->preds) > 0)
8001 {
8002 gsi = gsi_last_bb (cont_bb);
8003 if (POINTER_TYPE_P (type))
8004 t = fold_build_pointer_plus (fd->loops[i].v,
8005 fold_convert (sizetype,
8006 fd->loops[i].step));
8007 else
8008 t = fold_build2 (PLUS_EXPR, type, fd->loops[i].v,
8009 fold_convert (type, fd->loops[i].step));
8010 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
8011 if (counts[i])
8012 {
8013 t = fold_build2 (PLUS_EXPR, fd->iter_type, counts[i],
8014 build_int_cst (fd->iter_type, 1));
8015 expand_omp_build_assign (&gsi, counts[i], t);
8016 t = counts[i];
8017 }
8018 else
8019 {
8020 t = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->loops[i].v),
8021 fd->loops[i].v, fd->loops[i].n1);
8022 t = fold_convert (fd->iter_type, t);
8023 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8024 true, GSI_SAME_STMT);
8025 }
8026 aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8027 size_int (i - fd->collapse + 1),
8028 NULL_TREE, NULL_TREE);
8029 expand_omp_build_assign (&gsi, aref, t);
8030 gsi_prev (&gsi);
8031 e2 = split_block (cont_bb, gsi_stmt (gsi));
8032 new_header = e2->dest;
8033 }
8034 else
8035 new_header = cont_bb;
8036 gsi = gsi_after_labels (new_header);
8037 tree v = force_gimple_operand_gsi (&gsi, fd->loops[i].v, true, NULL_TREE,
8038 true, GSI_SAME_STMT);
8039 tree n2
8040 = force_gimple_operand_gsi (&gsi, fold_convert (type, fd->loops[i].n2),
8041 true, NULL_TREE, true, GSI_SAME_STMT);
8042 t = build2 (fd->loops[i].cond_code, boolean_type_node, v, n2);
8043 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_NEW_STMT);
8044 edge e3 = split_block (new_header, gsi_stmt (gsi));
8045 cont_bb = e3->dest;
8046 remove_edge (e1);
8047 make_edge (body_bb, new_header, EDGE_FALLTHRU);
8048 e3->flags = EDGE_FALSE_VALUE;
8049 e3->probability = REG_BR_PROB_BASE / 8;
8050 e1 = make_edge (new_header, new_body, EDGE_TRUE_VALUE);
8051 e1->probability = REG_BR_PROB_BASE - e3->probability;
8052
8053 set_immediate_dominator (CDI_DOMINATORS, new_header, body_bb);
8054 set_immediate_dominator (CDI_DOMINATORS, new_body, new_header);
8055
8056 if (e2)
8057 {
8058 struct loop *loop = alloc_loop ();
8059 loop->header = new_header;
8060 loop->latch = e2->src;
8061 add_loop (loop, body_bb->loop_father);
8062 }
8063 }
8064
8065 /* If there are any lastprivate clauses and it is possible some loops
8066 might have zero iterations, ensure all the decls are initialized,
8067 otherwise we could crash evaluating C++ class iterators with lastprivate
8068 clauses. */
8069 bool need_inits = false;
8070 for (int i = fd->collapse; ordered_lastprivate && i < fd->ordered; i++)
8071 if (need_inits)
8072 {
8073 tree type = TREE_TYPE (fd->loops[i].v);
8074 gimple_stmt_iterator gsi = gsi_after_labels (body_bb);
8075 expand_omp_build_assign (&gsi, fd->loops[i].v,
8076 fold_convert (type, fd->loops[i].n1));
8077 }
8078 else
8079 {
8080 tree type = TREE_TYPE (fd->loops[i].v);
8081 tree this_cond = fold_build2 (fd->loops[i].cond_code,
8082 boolean_type_node,
8083 fold_convert (type, fd->loops[i].n1),
8084 fold_convert (type, fd->loops[i].n2));
8085 if (!integer_onep (this_cond))
8086 need_inits = true;
8087 }
8088
8089 return cont_bb;
8090}
8091
8092
8093/* A subroutine of expand_omp_for. Generate code for a parallel
8094 loop with any schedule. Given parameters:
8095
8096 for (V = N1; V cond N2; V += STEP) BODY;
8097
8098 where COND is "<" or ">", we generate pseudocode
8099
8100 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
8101 if (more) goto L0; else goto L3;
8102 L0:
8103 V = istart0;
8104 iend = iend0;
8105 L1:
8106 BODY;
8107 V += STEP;
8108 if (V cond iend) goto L1; else goto L2;
8109 L2:
8110 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
8111 L3:
8112
8113 If this is a combined omp parallel loop, instead of the call to
8114 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
8115 If this is gimple_omp_for_combined_p loop, then instead of assigning
8116 V and iend in L0 we assign the first two _looptemp_ clause decls of the
8117 inner GIMPLE_OMP_FOR and V += STEP; and
8118 if (V cond iend) goto L1; else goto L2; are removed.
8119
8120 For collapsed loops, given parameters:
8121 collapse(3)
8122 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
8123 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
8124 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
8125 BODY;
8126
8127 we generate pseudocode
8128
8129 if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
8130 if (cond3 is <)
8131 adj = STEP3 - 1;
8132 else
8133 adj = STEP3 + 1;
8134 count3 = (adj + N32 - N31) / STEP3;
8135 if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
8136 if (cond2 is <)
8137 adj = STEP2 - 1;
8138 else
8139 adj = STEP2 + 1;
fd6481cf 8140 count2 = (adj + N22 - N21) / STEP2;
8e6b4515 8141 if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
fd6481cf 8142 if (cond1 is <)
8143 adj = STEP1 - 1;
8144 else
8145 adj = STEP1 + 1;
8146 count1 = (adj + N12 - N11) / STEP1;
8147 count = count1 * count2 * count3;
8e6b4515 8148 goto Z1;
8149 Z0:
8150 count = 0;
8151 Z1:
fd6481cf 8152 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
8153 if (more) goto L0; else goto L3;
8154 L0:
8155 V = istart0;
8156 T = V;
8157 V3 = N31 + (T % count3) * STEP3;
8158 T = T / count3;
8159 V2 = N21 + (T % count2) * STEP2;
8160 T = T / count2;
8161 V1 = N11 + T * STEP1;
8162 iend = iend0;
8163 L1:
8164 BODY;
8165 V += 1;
8166 if (V < iend) goto L10; else goto L2;
8167 L10:
8168 V3 += STEP3;
8169 if (V3 cond3 N32) goto L1; else goto L11;
8170 L11:
8171 V3 = N31;
8172 V2 += STEP2;
8173 if (V2 cond2 N22) goto L1; else goto L12;
8174 L12:
8175 V2 = N21;
8176 V1 += STEP1;
8177 goto L1;
8178 L2:
8179 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
8180 L3:
8181
8182 */
1e8e9920 8183
61e47ac8 8184static void
773c5ba7 8185expand_omp_for_generic (struct omp_region *region,
8186 struct omp_for_data *fd,
1e8e9920 8187 enum built_in_function start_fn,
bc7bff74 8188 enum built_in_function next_fn,
42acab1c 8189 gimple *inner_stmt)
1e8e9920 8190{
75a70cf9 8191 tree type, istart0, iend0, iend;
fd6481cf 8192 tree t, vmain, vback, bias = NULL_TREE;
8193 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, collapse_bb;
03ed154b 8194 basic_block l2_bb = NULL, l3_bb = NULL;
75a70cf9 8195 gimple_stmt_iterator gsi;
1a91d914 8196 gassign *assign_stmt;
773c5ba7 8197 bool in_combined_parallel = is_combined_parallel (region);
ac6e3339 8198 bool broken_loop = region->cont == NULL;
79acaae1 8199 edge e, ne;
fd6481cf 8200 tree *counts = NULL;
8201 int i;
43895be5 8202 bool ordered_lastprivate = false;
ac6e3339 8203
8204 gcc_assert (!broken_loop || !in_combined_parallel);
fd6481cf 8205 gcc_assert (fd->iter_type == long_integer_type_node
8206 || !in_combined_parallel);
1e8e9920 8207
61e47ac8 8208 entry_bb = region->entry;
03ed154b 8209 cont_bb = region->cont;
fd6481cf 8210 collapse_bb = NULL;
ac6e3339 8211 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
8212 gcc_assert (broken_loop
8213 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
8214 l0_bb = split_edge (FALLTHRU_EDGE (entry_bb));
8215 l1_bb = single_succ (l0_bb);
8216 if (!broken_loop)
03ed154b 8217 {
8218 l2_bb = create_empty_bb (cont_bb);
95cd5725 8219 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb
8220 || (single_succ_edge (BRANCH_EDGE (cont_bb)->dest)->dest
8221 == l1_bb));
ac6e3339 8222 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
03ed154b 8223 }
ac6e3339 8224 else
8225 l2_bb = NULL;
8226 l3_bb = BRANCH_EDGE (entry_bb)->dest;
8227 exit_bb = region->exit;
773c5ba7 8228
75a70cf9 8229 gsi = gsi_last_bb (entry_bb);
fd6481cf 8230
75a70cf9 8231 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
43895be5 8232 if (fd->ordered
8233 && find_omp_clause (gimple_omp_for_clauses (gsi_stmt (gsi)),
8234 OMP_CLAUSE_LASTPRIVATE))
8235 ordered_lastprivate = false;
8236 if (fd->collapse > 1 || fd->ordered)
fd6481cf 8237 {
43895be5 8238 int first_zero_iter1 = -1, first_zero_iter2 = -1;
8239 basic_block zero_iter1_bb = NULL, zero_iter2_bb = NULL, l2_dom_bb = NULL;
8e6b4515 8240
43895be5 8241 counts = XALLOCAVEC (tree, fd->ordered ? fd->ordered + 1 : fd->collapse);
3d483a94 8242 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
43895be5 8243 zero_iter1_bb, first_zero_iter1,
8244 zero_iter2_bb, first_zero_iter2, l2_dom_bb);
fd6481cf 8245
43895be5 8246 if (zero_iter1_bb)
8e6b4515 8247 {
8248 /* Some counts[i] vars might be uninitialized if
8249 some loop has zero iterations. But the body shouldn't
8250 be executed in that case, so just avoid uninit warnings. */
43895be5 8251 for (i = first_zero_iter1;
8252 i < (fd->ordered ? fd->ordered : fd->collapse); i++)
8e6b4515 8253 if (SSA_VAR_P (counts[i]))
8254 TREE_NO_WARNING (counts[i]) = 1;
8255 gsi_prev (&gsi);
8256 e = split_block (entry_bb, gsi_stmt (gsi));
8257 entry_bb = e->dest;
43895be5 8258 make_edge (zero_iter1_bb, entry_bb, EDGE_FALLTHRU);
8e6b4515 8259 gsi = gsi_last_bb (entry_bb);
8260 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
8261 get_immediate_dominator (CDI_DOMINATORS,
43895be5 8262 zero_iter1_bb));
8263 }
8264 if (zero_iter2_bb)
8265 {
8266 /* Some counts[i] vars might be uninitialized if
8267 some loop has zero iterations. But the body shouldn't
8268 be executed in that case, so just avoid uninit warnings. */
8269 for (i = first_zero_iter2; i < fd->ordered; i++)
8270 if (SSA_VAR_P (counts[i]))
8271 TREE_NO_WARNING (counts[i]) = 1;
8272 if (zero_iter1_bb)
8273 make_edge (zero_iter2_bb, entry_bb, EDGE_FALLTHRU);
8274 else
8275 {
8276 gsi_prev (&gsi);
8277 e = split_block (entry_bb, gsi_stmt (gsi));
8278 entry_bb = e->dest;
8279 make_edge (zero_iter2_bb, entry_bb, EDGE_FALLTHRU);
8280 gsi = gsi_last_bb (entry_bb);
8281 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
8282 get_immediate_dominator
8283 (CDI_DOMINATORS, zero_iter2_bb));
8284 }
8285 }
8286 if (fd->collapse == 1)
8287 {
8288 counts[0] = fd->loop.n2;
8289 fd->loop = fd->loops[0];
8290 }
8291 }
8292
8293 type = TREE_TYPE (fd->loop.v);
8294 istart0 = create_tmp_var (fd->iter_type, ".istart0");
8295 iend0 = create_tmp_var (fd->iter_type, ".iend0");
8296 TREE_ADDRESSABLE (istart0) = 1;
8297 TREE_ADDRESSABLE (iend0) = 1;
8298
8299 /* See if we need to bias by LLONG_MIN. */
8300 if (fd->iter_type == long_long_unsigned_type_node
8301 && TREE_CODE (type) == INTEGER_TYPE
8302 && !TYPE_UNSIGNED (type)
8303 && fd->ordered == 0)
8304 {
8305 tree n1, n2;
8306
8307 if (fd->loop.cond_code == LT_EXPR)
8308 {
8309 n1 = fd->loop.n1;
8310 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
8e6b4515 8311 }
43895be5 8312 else
8313 {
8314 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
8315 n2 = fd->loop.n1;
8316 }
8317 if (TREE_CODE (n1) != INTEGER_CST
8318 || TREE_CODE (n2) != INTEGER_CST
8319 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
8320 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
fd6481cf 8321 }
43895be5 8322
8323 gimple_stmt_iterator gsif = gsi;
8324 gsi_prev (&gsif);
8325
8326 tree arr = NULL_TREE;
79acaae1 8327 if (in_combined_parallel)
8328 {
43895be5 8329 gcc_assert (fd->ordered == 0);
79acaae1 8330 /* In a combined parallel loop, emit a call to
8331 GOMP_loop_foo_next. */
b9a16870 8332 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
79acaae1 8333 build_fold_addr_expr (istart0),
8334 build_fold_addr_expr (iend0));
8335 }
8336 else
1e8e9920 8337 {
c2f47e15 8338 tree t0, t1, t2, t3, t4;
773c5ba7 8339 /* If this is not a combined parallel loop, emit a call to
8340 GOMP_loop_foo_start in ENTRY_BB. */
c2f47e15 8341 t4 = build_fold_addr_expr (iend0);
8342 t3 = build_fold_addr_expr (istart0);
43895be5 8343 if (fd->ordered)
c799f233 8344 {
43895be5 8345 t0 = build_int_cst (unsigned_type_node,
8346 fd->ordered - fd->collapse + 1);
8347 arr = create_tmp_var (build_array_type_nelts (fd->iter_type,
8348 fd->ordered
8349 - fd->collapse + 1),
8350 ".omp_counts");
8351 DECL_NAMELESS (arr) = 1;
8352 TREE_ADDRESSABLE (arr) = 1;
8353 TREE_STATIC (arr) = 1;
8354 vec<constructor_elt, va_gc> *v;
8355 vec_alloc (v, fd->ordered - fd->collapse + 1);
8356 int idx;
8357
8358 for (idx = 0; idx < fd->ordered - fd->collapse + 1; idx++)
8359 {
8360 tree c;
8361 if (idx == 0 && fd->collapse > 1)
8362 c = fd->loop.n2;
8363 else
8364 c = counts[idx + fd->collapse - 1];
8365 tree purpose = size_int (idx);
8366 CONSTRUCTOR_APPEND_ELT (v, purpose, c);
8367 if (TREE_CODE (c) != INTEGER_CST)
8368 TREE_STATIC (arr) = 0;
8369 }
8370
8371 DECL_INITIAL (arr) = build_constructor (TREE_TYPE (arr), v);
8372 if (!TREE_STATIC (arr))
8373 force_gimple_operand_gsi (&gsi, build1 (DECL_EXPR,
8374 void_type_node, arr),
8375 true, NULL_TREE, true, GSI_SAME_STMT);
8376 t1 = build_fold_addr_expr (arr);
8377 t2 = NULL_TREE;
c799f233 8378 }
8379 else
8380 {
43895be5 8381 t2 = fold_convert (fd->iter_type, fd->loop.step);
8382 t1 = fd->loop.n2;
8383 t0 = fd->loop.n1;
8384 if (gimple_omp_for_combined_into_p (fd->for_stmt))
8385 {
8386 tree innerc
8387 = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
8388 OMP_CLAUSE__LOOPTEMP_);
8389 gcc_assert (innerc);
8390 t0 = OMP_CLAUSE_DECL (innerc);
8391 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
8392 OMP_CLAUSE__LOOPTEMP_);
8393 gcc_assert (innerc);
8394 t1 = OMP_CLAUSE_DECL (innerc);
8395 }
8396 if (POINTER_TYPE_P (TREE_TYPE (t0))
8397 && TYPE_PRECISION (TREE_TYPE (t0))
8398 != TYPE_PRECISION (fd->iter_type))
8399 {
8400 /* Avoid casting pointers to integer of a different size. */
8401 tree itype = signed_type_for (type);
8402 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
8403 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
8404 }
8405 else
8406 {
8407 t1 = fold_convert (fd->iter_type, t1);
8408 t0 = fold_convert (fd->iter_type, t0);
8409 }
8410 if (bias)
8411 {
8412 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
8413 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
8414 }
fd6481cf 8415 }
43895be5 8416 if (fd->iter_type == long_integer_type_node || fd->ordered)
fd6481cf 8417 {
8418 if (fd->chunk_size)
8419 {
8420 t = fold_convert (fd->iter_type, fd->chunk_size);
43895be5 8421 t = omp_adjust_chunk_size (t, fd->simd_schedule);
8422 if (fd->ordered)
8423 t = build_call_expr (builtin_decl_explicit (start_fn),
8424 5, t0, t1, t, t3, t4);
8425 else
8426 t = build_call_expr (builtin_decl_explicit (start_fn),
8427 6, t0, t1, t2, t, t3, t4);
fd6481cf 8428 }
43895be5 8429 else if (fd->ordered)
8430 t = build_call_expr (builtin_decl_explicit (start_fn),
8431 4, t0, t1, t3, t4);
fd6481cf 8432 else
b9a16870 8433 t = build_call_expr (builtin_decl_explicit (start_fn),
8434 5, t0, t1, t2, t3, t4);
1e8e9920 8435 }
c2f47e15 8436 else
fd6481cf 8437 {
8438 tree t5;
8439 tree c_bool_type;
b9a16870 8440 tree bfn_decl;
fd6481cf 8441
8442 /* The GOMP_loop_ull_*start functions have additional boolean
8443 argument, true for < loops and false for > loops.
8444 In Fortran, the C bool type can be different from
8445 boolean_type_node. */
b9a16870 8446 bfn_decl = builtin_decl_explicit (start_fn);
8447 c_bool_type = TREE_TYPE (TREE_TYPE (bfn_decl));
fd6481cf 8448 t5 = build_int_cst (c_bool_type,
8449 fd->loop.cond_code == LT_EXPR ? 1 : 0);
8450 if (fd->chunk_size)
8451 {
b9a16870 8452 tree bfn_decl = builtin_decl_explicit (start_fn);
fd6481cf 8453 t = fold_convert (fd->iter_type, fd->chunk_size);
43895be5 8454 t = omp_adjust_chunk_size (t, fd->simd_schedule);
b9a16870 8455 t = build_call_expr (bfn_decl, 7, t5, t0, t1, t2, t, t3, t4);
fd6481cf 8456 }
8457 else
b9a16870 8458 t = build_call_expr (builtin_decl_explicit (start_fn),
8459 6, t5, t0, t1, t2, t3, t4);
fd6481cf 8460 }
1e8e9920 8461 }
fd6481cf 8462 if (TREE_TYPE (t) != boolean_type_node)
8463 t = fold_build2 (NE_EXPR, boolean_type_node,
8464 t, build_int_cst (TREE_TYPE (t), 0));
75a70cf9 8465 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8466 true, GSI_SAME_STMT);
43895be5 8467 if (arr && !TREE_STATIC (arr))
8468 {
8469 tree clobber = build_constructor (TREE_TYPE (arr), NULL);
8470 TREE_THIS_VOLATILE (clobber) = 1;
8471 gsi_insert_before (&gsi, gimple_build_assign (arr, clobber),
8472 GSI_SAME_STMT);
8473 }
75a70cf9 8474 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
79acaae1 8475
75a70cf9 8476 /* Remove the GIMPLE_OMP_FOR statement. */
8477 gsi_remove (&gsi, true);
1e8e9920 8478
43895be5 8479 if (gsi_end_p (gsif))
8480 gsif = gsi_after_labels (gsi_bb (gsif));
8481 gsi_next (&gsif);
8482
773c5ba7 8483 /* Iteration setup for sequential loop goes in L0_BB. */
3d483a94 8484 tree startvar = fd->loop.v;
8485 tree endvar = NULL_TREE;
8486
bc7bff74 8487 if (gimple_omp_for_combined_p (fd->for_stmt))
8488 {
8489 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_FOR
8490 && gimple_omp_for_kind (inner_stmt)
8491 == GF_OMP_FOR_KIND_SIMD);
8492 tree innerc = find_omp_clause (gimple_omp_for_clauses (inner_stmt),
8493 OMP_CLAUSE__LOOPTEMP_);
8494 gcc_assert (innerc);
8495 startvar = OMP_CLAUSE_DECL (innerc);
8496 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
8497 OMP_CLAUSE__LOOPTEMP_);
8498 gcc_assert (innerc);
8499 endvar = OMP_CLAUSE_DECL (innerc);
8500 }
8501
75a70cf9 8502 gsi = gsi_start_bb (l0_bb);
1efcacec 8503 t = istart0;
43895be5 8504 if (fd->ordered && fd->collapse == 1)
8505 t = fold_build2 (MULT_EXPR, fd->iter_type, t,
8506 fold_convert (fd->iter_type, fd->loop.step));
8507 else if (bias)
1efcacec 8508 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
43895be5 8509 if (fd->ordered && fd->collapse == 1)
8510 {
8511 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8512 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (startvar),
8513 fd->loop.n1, fold_convert (sizetype, t));
8514 else
8515 {
8516 t = fold_convert (TREE_TYPE (startvar), t);
8517 t = fold_build2 (PLUS_EXPR, TREE_TYPE (startvar),
8518 fd->loop.n1, t);
8519 }
8520 }
8521 else
8522 {
8523 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8524 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
8525 t = fold_convert (TREE_TYPE (startvar), t);
8526 }
4abecb72 8527 t = force_gimple_operand_gsi (&gsi, t,
3d483a94 8528 DECL_P (startvar)
8529 && TREE_ADDRESSABLE (startvar),
4abecb72 8530 NULL_TREE, false, GSI_CONTINUE_LINKING);
1a91d914 8531 assign_stmt = gimple_build_assign (startvar, t);
8532 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
1e8e9920 8533
1efcacec 8534 t = iend0;
43895be5 8535 if (fd->ordered && fd->collapse == 1)
8536 t = fold_build2 (MULT_EXPR, fd->iter_type, t,
8537 fold_convert (fd->iter_type, fd->loop.step));
8538 else if (bias)
1efcacec 8539 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
43895be5 8540 if (fd->ordered && fd->collapse == 1)
fd6481cf 8541 {
43895be5 8542 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8543 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (startvar),
8544 fd->loop.n1, fold_convert (sizetype, t));
8545 else
8546 {
8547 t = fold_convert (TREE_TYPE (startvar), t);
8548 t = fold_build2 (PLUS_EXPR, TREE_TYPE (startvar),
8549 fd->loop.n1, t);
8550 }
8551 }
8552 else
8553 {
8554 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8555 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
8556 t = fold_convert (TREE_TYPE (startvar), t);
8557 }
8558 iend = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8559 false, GSI_CONTINUE_LINKING);
8560 if (endvar)
8561 {
8562 assign_stmt = gimple_build_assign (endvar, iend);
1a91d914 8563 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
d44f2f7c 8564 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (iend)))
1a91d914 8565 assign_stmt = gimple_build_assign (fd->loop.v, iend);
d44f2f7c 8566 else
e9cf809e 8567 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, iend);
1a91d914 8568 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
fd6481cf 8569 }
43895be5 8570 /* Handle linear clause adjustments. */
8571 tree itercnt = NULL_TREE;
8572 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_FOR)
8573 for (tree c = gimple_omp_for_clauses (fd->for_stmt);
8574 c; c = OMP_CLAUSE_CHAIN (c))
8575 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
8576 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
8577 {
8578 tree d = OMP_CLAUSE_DECL (c);
8579 bool is_ref = is_reference (d);
8580 tree t = d, a, dest;
8581 if (is_ref)
8582 t = build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c), t);
8583 tree type = TREE_TYPE (t);
8584 if (POINTER_TYPE_P (type))
8585 type = sizetype;
8586 dest = unshare_expr (t);
8587 tree v = create_tmp_var (TREE_TYPE (t), NULL);
8588 expand_omp_build_assign (&gsif, v, t);
8589 if (itercnt == NULL_TREE)
8590 {
8591 itercnt = startvar;
8592 tree n1 = fd->loop.n1;
8593 if (POINTER_TYPE_P (TREE_TYPE (itercnt)))
8594 {
8595 itercnt
8596 = fold_convert (signed_type_for (TREE_TYPE (itercnt)),
8597 itercnt);
8598 n1 = fold_convert (TREE_TYPE (itercnt), n1);
8599 }
8600 itercnt = fold_build2 (MINUS_EXPR, TREE_TYPE (itercnt),
8601 itercnt, n1);
8602 itercnt = fold_build2 (EXACT_DIV_EXPR, TREE_TYPE (itercnt),
8603 itercnt, fd->loop.step);
8604 itercnt = force_gimple_operand_gsi (&gsi, itercnt, true,
8605 NULL_TREE, false,
8606 GSI_CONTINUE_LINKING);
8607 }
8608 a = fold_build2 (MULT_EXPR, type,
8609 fold_convert (type, itercnt),
8610 fold_convert (type, OMP_CLAUSE_LINEAR_STEP (c)));
8611 t = fold_build2 (type == TREE_TYPE (t) ? PLUS_EXPR
8612 : POINTER_PLUS_EXPR, TREE_TYPE (t), v, a);
8613 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8614 false, GSI_CONTINUE_LINKING);
8615 assign_stmt = gimple_build_assign (dest, t);
8616 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
8617 }
3d483a94 8618 if (fd->collapse > 1)
bc7bff74 8619 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
773c5ba7 8620
43895be5 8621 if (fd->ordered)
8622 {
8623 /* Until now, counts array contained number of iterations or
8624 variable containing it for ith loop. From now on, we need
8625 those counts only for collapsed loops, and only for the 2nd
8626 till the last collapsed one. Move those one element earlier,
8627 we'll use counts[fd->collapse - 1] for the first source/sink
8628 iteration counter and so on and counts[fd->ordered]
8629 as the array holding the current counter values for
8630 depend(source). */
8631 if (fd->collapse > 1)
8632 memmove (counts, counts + 1, (fd->collapse - 1) * sizeof (counts[0]));
8633 if (broken_loop)
8634 {
8635 int i;
8636 for (i = fd->collapse; i < fd->ordered; i++)
8637 {
8638 tree type = TREE_TYPE (fd->loops[i].v);
8639 tree this_cond
8640 = fold_build2 (fd->loops[i].cond_code, boolean_type_node,
8641 fold_convert (type, fd->loops[i].n1),
8642 fold_convert (type, fd->loops[i].n2));
8643 if (!integer_onep (this_cond))
8644 break;
8645 }
8646 if (i < fd->ordered)
8647 {
8648 cont_bb
8649 = create_empty_bb (EXIT_BLOCK_PTR_FOR_FN (cfun)->prev_bb);
8650 add_bb_to_loop (cont_bb, l1_bb->loop_father);
8651 gimple_stmt_iterator gsi = gsi_after_labels (cont_bb);
8652 gimple *g = gimple_build_omp_continue (fd->loop.v, fd->loop.v);
8653 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
8654 make_edge (cont_bb, l3_bb, EDGE_FALLTHRU);
8655 make_edge (cont_bb, l1_bb, 0);
8656 l2_bb = create_empty_bb (cont_bb);
8657 broken_loop = false;
8658 }
8659 }
8660 expand_omp_ordered_source_sink (region, fd, counts, cont_bb);
8661 cont_bb = expand_omp_for_ordered_loops (fd, counts, cont_bb, l1_bb,
8662 ordered_lastprivate);
8663 if (counts[fd->collapse - 1])
8664 {
8665 gcc_assert (fd->collapse == 1);
8666 gsi = gsi_last_bb (l0_bb);
8667 expand_omp_build_assign (&gsi, counts[fd->collapse - 1],
8668 istart0, true);
8669 gsi = gsi_last_bb (cont_bb);
8670 t = fold_build2 (PLUS_EXPR, fd->iter_type, counts[fd->collapse - 1],
8671 build_int_cst (fd->iter_type, 1));
8672 expand_omp_build_assign (&gsi, counts[fd->collapse - 1], t);
8673 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8674 size_zero_node, NULL_TREE, NULL_TREE);
8675 expand_omp_build_assign (&gsi, aref, counts[fd->collapse - 1]);
8676 t = counts[fd->collapse - 1];
8677 }
8678 else if (fd->collapse > 1)
8679 t = fd->loop.v;
8680 else
8681 {
8682 t = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->loops[0].v),
8683 fd->loops[0].v, fd->loops[0].n1);
8684 t = fold_convert (fd->iter_type, t);
8685 }
8686 gsi = gsi_last_bb (l0_bb);
8687 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8688 size_zero_node, NULL_TREE, NULL_TREE);
8689 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8690 false, GSI_CONTINUE_LINKING);
8691 expand_omp_build_assign (&gsi, aref, t, true);
8692 }
8693
ac6e3339 8694 if (!broken_loop)
03ed154b 8695 {
ac6e3339 8696 /* Code to control the increment and predicate for the sequential
8697 loop goes in the CONT_BB. */
75a70cf9 8698 gsi = gsi_last_bb (cont_bb);
1a91d914 8699 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
8700 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
8701 vmain = gimple_omp_continue_control_use (cont_stmt);
8702 vback = gimple_omp_continue_control_def (cont_stmt);
79acaae1 8703
bc7bff74 8704 if (!gimple_omp_for_combined_p (fd->for_stmt))
3d483a94 8705 {
8706 if (POINTER_TYPE_P (type))
8707 t = fold_build_pointer_plus (vmain, fd->loop.step);
8708 else
8709 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
8710 t = force_gimple_operand_gsi (&gsi, t,
8711 DECL_P (vback)
8712 && TREE_ADDRESSABLE (vback),
8713 NULL_TREE, true, GSI_SAME_STMT);
1a91d914 8714 assign_stmt = gimple_build_assign (vback, t);
8715 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
3d483a94 8716
43895be5 8717 if (fd->ordered && counts[fd->collapse - 1] == NULL_TREE)
8718 {
8719 if (fd->collapse > 1)
8720 t = fd->loop.v;
8721 else
8722 {
8723 t = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->loops[0].v),
8724 fd->loops[0].v, fd->loops[0].n1);
8725 t = fold_convert (fd->iter_type, t);
8726 }
8727 tree aref = build4 (ARRAY_REF, fd->iter_type,
8728 counts[fd->ordered], size_zero_node,
8729 NULL_TREE, NULL_TREE);
8730 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8731 true, GSI_SAME_STMT);
8732 expand_omp_build_assign (&gsi, aref, t);
8733 }
8734
3d483a94 8735 t = build2 (fd->loop.cond_code, boolean_type_node,
8736 DECL_P (vback) && TREE_ADDRESSABLE (vback) ? t : vback,
8737 iend);
1a91d914 8738 gcond *cond_stmt = gimple_build_cond_empty (t);
8739 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
3d483a94 8740 }
773c5ba7 8741
75a70cf9 8742 /* Remove GIMPLE_OMP_CONTINUE. */
8743 gsi_remove (&gsi, true);
773c5ba7 8744
bc7bff74 8745 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
3d483a94 8746 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, l1_bb);
fd6481cf 8747
ac6e3339 8748 /* Emit code to get the next parallel iteration in L2_BB. */
75a70cf9 8749 gsi = gsi_start_bb (l2_bb);
773c5ba7 8750
b9a16870 8751 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
ac6e3339 8752 build_fold_addr_expr (istart0),
8753 build_fold_addr_expr (iend0));
75a70cf9 8754 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8755 false, GSI_CONTINUE_LINKING);
fd6481cf 8756 if (TREE_TYPE (t) != boolean_type_node)
8757 t = fold_build2 (NE_EXPR, boolean_type_node,
8758 t, build_int_cst (TREE_TYPE (t), 0));
1a91d914 8759 gcond *cond_stmt = gimple_build_cond_empty (t);
8760 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
ac6e3339 8761 }
1e8e9920 8762
61e47ac8 8763 /* Add the loop cleanup function. */
75a70cf9 8764 gsi = gsi_last_bb (exit_bb);
8765 if (gimple_omp_return_nowait_p (gsi_stmt (gsi)))
b9a16870 8766 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
bc7bff74 8767 else if (gimple_omp_return_lhs (gsi_stmt (gsi)))
8768 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL);
61e47ac8 8769 else
b9a16870 8770 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END);
1a91d914 8771 gcall *call_stmt = gimple_build_call (t, 0);
bc7bff74 8772 if (gimple_omp_return_lhs (gsi_stmt (gsi)))
1a91d914 8773 gimple_call_set_lhs (call_stmt, gimple_omp_return_lhs (gsi_stmt (gsi)));
8774 gsi_insert_after (&gsi, call_stmt, GSI_SAME_STMT);
43895be5 8775 if (fd->ordered)
8776 {
8777 tree arr = counts[fd->ordered];
8778 tree clobber = build_constructor (TREE_TYPE (arr), NULL);
8779 TREE_THIS_VOLATILE (clobber) = 1;
8780 gsi_insert_after (&gsi, gimple_build_assign (arr, clobber),
8781 GSI_SAME_STMT);
8782 }
75a70cf9 8783 gsi_remove (&gsi, true);
773c5ba7 8784
8785 /* Connect the new blocks. */
79acaae1 8786 find_edge (entry_bb, l0_bb)->flags = EDGE_TRUE_VALUE;
8787 find_edge (entry_bb, l3_bb)->flags = EDGE_FALSE_VALUE;
1e8e9920 8788
ac6e3339 8789 if (!broken_loop)
8790 {
75a70cf9 8791 gimple_seq phis;
8792
79acaae1 8793 e = find_edge (cont_bb, l3_bb);
8794 ne = make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
8795
75a70cf9 8796 phis = phi_nodes (l3_bb);
8797 for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi))
8798 {
42acab1c 8799 gimple *phi = gsi_stmt (gsi);
75a70cf9 8800 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, ne),
8801 PHI_ARG_DEF_FROM_EDGE (phi, e));
8802 }
79acaae1 8803 remove_edge (e);
8804
ac6e3339 8805 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
3d483a94 8806 e = find_edge (cont_bb, l1_bb);
95cd5725 8807 if (e == NULL)
8808 {
8809 e = BRANCH_EDGE (cont_bb);
8810 gcc_assert (single_succ (e->dest) == l1_bb);
8811 }
bc7bff74 8812 if (gimple_omp_for_combined_p (fd->for_stmt))
8813 {
8814 remove_edge (e);
8815 e = NULL;
8816 }
3d483a94 8817 else if (fd->collapse > 1)
fd6481cf 8818 {
fd6481cf 8819 remove_edge (e);
8820 e = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
8821 }
8822 else
3d483a94 8823 e->flags = EDGE_TRUE_VALUE;
8824 if (e)
fd6481cf 8825 {
3d483a94 8826 e->probability = REG_BR_PROB_BASE * 7 / 8;
8827 find_edge (cont_bb, l2_bb)->probability = REG_BR_PROB_BASE / 8;
8828 }
8829 else
8830 {
8831 e = find_edge (cont_bb, l2_bb);
8832 e->flags = EDGE_FALLTHRU;
fd6481cf 8833 }
ac6e3339 8834 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
79acaae1 8835
2131a1a9 8836 if (gimple_in_ssa_p (cfun))
8837 {
8838 /* Add phis to the outer loop that connect to the phis in the inner,
8839 original loop, and move the loop entry value of the inner phi to
8840 the loop entry value of the outer phi. */
8841 gphi_iterator psi;
8842 for (psi = gsi_start_phis (l3_bb); !gsi_end_p (psi); gsi_next (&psi))
8843 {
8844 source_location locus;
8845 gphi *nphi;
8846 gphi *exit_phi = psi.phi ();
8847
8848 edge l2_to_l3 = find_edge (l2_bb, l3_bb);
8849 tree exit_res = PHI_ARG_DEF_FROM_EDGE (exit_phi, l2_to_l3);
8850
8851 basic_block latch = BRANCH_EDGE (cont_bb)->dest;
8852 edge latch_to_l1 = find_edge (latch, l1_bb);
8853 gphi *inner_phi
8854 = find_phi_with_arg_on_edge (exit_res, latch_to_l1);
8855
8856 tree t = gimple_phi_result (exit_phi);
8857 tree new_res = copy_ssa_name (t, NULL);
8858 nphi = create_phi_node (new_res, l0_bb);
8859
8860 edge l0_to_l1 = find_edge (l0_bb, l1_bb);
8861 t = PHI_ARG_DEF_FROM_EDGE (inner_phi, l0_to_l1);
8862 locus = gimple_phi_arg_location_from_edge (inner_phi, l0_to_l1);
8863 edge entry_to_l0 = find_edge (entry_bb, l0_bb);
8864 add_phi_arg (nphi, t, entry_to_l0, locus);
8865
8866 edge l2_to_l0 = find_edge (l2_bb, l0_bb);
8867 add_phi_arg (nphi, exit_res, l2_to_l0, UNKNOWN_LOCATION);
8868
8869 add_phi_arg (inner_phi, new_res, l0_to_l1, UNKNOWN_LOCATION);
8870 };
8871 }
8872
79acaae1 8873 set_immediate_dominator (CDI_DOMINATORS, l2_bb,
8874 recompute_dominator (CDI_DOMINATORS, l2_bb));
8875 set_immediate_dominator (CDI_DOMINATORS, l3_bb,
8876 recompute_dominator (CDI_DOMINATORS, l3_bb));
8877 set_immediate_dominator (CDI_DOMINATORS, l0_bb,
8878 recompute_dominator (CDI_DOMINATORS, l0_bb));
8879 set_immediate_dominator (CDI_DOMINATORS, l1_bb,
8880 recompute_dominator (CDI_DOMINATORS, l1_bb));
04c2922b 8881
1c6a437b 8882 /* We enter expand_omp_for_generic with a loop. This original loop may
8883 have its own loop struct, or it may be part of an outer loop struct
8884 (which may be the fake loop). */
8885 struct loop *outer_loop = entry_bb->loop_father;
8886 bool orig_loop_has_loop_struct = l1_bb->loop_father != outer_loop;
8887
8888 add_bb_to_loop (l2_bb, outer_loop);
8889
8890 /* We've added a new loop around the original loop. Allocate the
8891 corresponding loop struct. */
8892 struct loop *new_loop = alloc_loop ();
8893 new_loop->header = l0_bb;
8894 new_loop->latch = l2_bb;
8895 add_loop (new_loop, outer_loop);
8896
8897 /* Allocate a loop structure for the original loop unless we already
8898 had one. */
8899 if (!orig_loop_has_loop_struct
8900 && !gimple_omp_for_combined_p (fd->for_stmt))
3d483a94 8901 {
1c6a437b 8902 struct loop *orig_loop = alloc_loop ();
8903 orig_loop->header = l1_bb;
3d483a94 8904 /* The loop may have multiple latches. */
1c6a437b 8905 add_loop (orig_loop, new_loop);
9c822ac8 8906 orig_loop->latch = find_single_latch (orig_loop);
3d483a94 8907 }
ac6e3339 8908 }
1e8e9920 8909}
8910
8911
773c5ba7 8912/* A subroutine of expand_omp_for. Generate code for a parallel
8913 loop with static schedule and no specified chunk size. Given
8914 parameters:
1e8e9920 8915
8916 for (V = N1; V cond N2; V += STEP) BODY;
8917
8918 where COND is "<" or ">", we generate pseudocode
8919
8e6b4515 8920 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
1e8e9920 8921 if (cond is <)
8922 adj = STEP - 1;
8923 else
8924 adj = STEP + 1;
fd6481cf 8925 if ((__typeof (V)) -1 > 0 && cond is >)
8926 n = -(adj + N2 - N1) / -STEP;
8927 else
8928 n = (adj + N2 - N1) / STEP;
1e8e9920 8929 q = n / nthreads;
31712e83 8930 tt = n % nthreads;
8931 if (threadid < tt) goto L3; else goto L4;
8932 L3:
8933 tt = 0;
8934 q = q + 1;
8935 L4:
8936 s0 = q * threadid + tt;
8937 e0 = s0 + q;
79acaae1 8938 V = s0 * STEP + N1;
1e8e9920 8939 if (s0 >= e0) goto L2; else goto L0;
8940 L0:
1e8e9920 8941 e = e0 * STEP + N1;
8942 L1:
8943 BODY;
8944 V += STEP;
8945 if (V cond e) goto L1;
1e8e9920 8946 L2:
8947*/
8948
61e47ac8 8949static void
773c5ba7 8950expand_omp_for_static_nochunk (struct omp_region *region,
bc7bff74 8951 struct omp_for_data *fd,
42acab1c 8952 gimple *inner_stmt)
1e8e9920 8953{
31712e83 8954 tree n, q, s0, e0, e, t, tt, nthreads, threadid;
fd6481cf 8955 tree type, itype, vmain, vback;
31712e83 8956 basic_block entry_bb, second_bb, third_bb, exit_bb, seq_start_bb;
bc7bff74 8957 basic_block body_bb, cont_bb, collapse_bb = NULL;
61e47ac8 8958 basic_block fin_bb;
75a70cf9 8959 gimple_stmt_iterator gsi;
31712e83 8960 edge ep;
bc7bff74 8961 bool broken_loop = region->cont == NULL;
8962 tree *counts = NULL;
8963 tree n1, n2, step;
1e8e9920 8964
fd6481cf 8965 itype = type = TREE_TYPE (fd->loop.v);
8966 if (POINTER_TYPE_P (type))
3cea8318 8967 itype = signed_type_for (type);
1e8e9920 8968
61e47ac8 8969 entry_bb = region->entry;
61e47ac8 8970 cont_bb = region->cont;
ac6e3339 8971 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
bc7bff74 8972 fin_bb = BRANCH_EDGE (entry_bb)->dest;
8973 gcc_assert (broken_loop
8974 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
ac6e3339 8975 seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb));
8976 body_bb = single_succ (seq_start_bb);
bc7bff74 8977 if (!broken_loop)
8978 {
86a932e0 8979 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb
8980 || single_succ (BRANCH_EDGE (cont_bb)->dest) == body_bb);
bc7bff74 8981 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
8982 }
61e47ac8 8983 exit_bb = region->exit;
8984
773c5ba7 8985 /* Iteration space partitioning goes in ENTRY_BB. */
75a70cf9 8986 gsi = gsi_last_bb (entry_bb);
8987 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
61e47ac8 8988
bc7bff74 8989 if (fd->collapse > 1)
8990 {
43895be5 8991 int first_zero_iter = -1, dummy = -1;
8992 basic_block l2_dom_bb = NULL, dummy_bb = NULL;
bc7bff74 8993
8994 counts = XALLOCAVEC (tree, fd->collapse);
8995 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
8996 fin_bb, first_zero_iter,
43895be5 8997 dummy_bb, dummy, l2_dom_bb);
bc7bff74 8998 t = NULL_TREE;
8999 }
9000 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
9001 t = integer_one_node;
9002 else
9003 t = fold_binary (fd->loop.cond_code, boolean_type_node,
9004 fold_convert (type, fd->loop.n1),
9005 fold_convert (type, fd->loop.n2));
9006 if (fd->collapse == 1
9007 && TYPE_UNSIGNED (type)
8e6b4515 9008 && (t == NULL_TREE || !integer_onep (t)))
9009 {
8e6b4515 9010 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
9011 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
9012 true, GSI_SAME_STMT);
9013 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
9014 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
9015 true, GSI_SAME_STMT);
1a91d914 9016 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
9017 NULL_TREE, NULL_TREE);
9018 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
9019 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
8e6b4515 9020 expand_omp_regimplify_p, NULL, NULL)
1a91d914 9021 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
8e6b4515 9022 expand_omp_regimplify_p, NULL, NULL))
9023 {
1a91d914 9024 gsi = gsi_for_stmt (cond_stmt);
9025 gimple_regimplify_operands (cond_stmt, &gsi);
8e6b4515 9026 }
1a91d914 9027 ep = split_block (entry_bb, cond_stmt);
8e6b4515 9028 ep->flags = EDGE_TRUE_VALUE;
9029 entry_bb = ep->dest;
9030 ep->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
9031 ep = make_edge (ep->src, fin_bb, EDGE_FALSE_VALUE);
9032 ep->probability = REG_BR_PROB_BASE / 2000 - 1;
9033 if (gimple_in_ssa_p (cfun))
9034 {
9035 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
1a91d914 9036 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
9037 !gsi_end_p (gpi); gsi_next (&gpi))
8e6b4515 9038 {
1a91d914 9039 gphi *phi = gpi.phi ();
8e6b4515 9040 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
9041 ep, UNKNOWN_LOCATION);
9042 }
9043 }
9044 gsi = gsi_last_bb (entry_bb);
9045 }
9046
ca4c3545 9047 switch (gimple_omp_for_kind (fd->for_stmt))
9048 {
9049 case GF_OMP_FOR_KIND_FOR:
9050 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
9051 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
9052 break;
9053 case GF_OMP_FOR_KIND_DISTRIBUTE:
9054 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
9055 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
9056 break;
ca4c3545 9057 default:
9058 gcc_unreachable ();
9059 }
9060 nthreads = build_call_expr (nthreads, 0);
9061 nthreads = fold_convert (itype, nthreads);
9062 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
75a70cf9 9063 true, GSI_SAME_STMT);
ca4c3545 9064 threadid = build_call_expr (threadid, 0);
9065 threadid = fold_convert (itype, threadid);
9066 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
75a70cf9 9067 true, GSI_SAME_STMT);
1e8e9920 9068
bc7bff74 9069 n1 = fd->loop.n1;
9070 n2 = fd->loop.n2;
9071 step = fd->loop.step;
9072 if (gimple_omp_for_combined_into_p (fd->for_stmt))
9073 {
9074 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
9075 OMP_CLAUSE__LOOPTEMP_);
9076 gcc_assert (innerc);
9077 n1 = OMP_CLAUSE_DECL (innerc);
9078 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9079 OMP_CLAUSE__LOOPTEMP_);
9080 gcc_assert (innerc);
9081 n2 = OMP_CLAUSE_DECL (innerc);
9082 }
9083 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
9084 true, NULL_TREE, true, GSI_SAME_STMT);
9085 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
9086 true, NULL_TREE, true, GSI_SAME_STMT);
9087 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
9088 true, NULL_TREE, true, GSI_SAME_STMT);
fd6481cf 9089
9090 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
bc7bff74 9091 t = fold_build2 (PLUS_EXPR, itype, step, t);
9092 t = fold_build2 (PLUS_EXPR, itype, t, n2);
9093 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
fd6481cf 9094 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
9095 t = fold_build2 (TRUNC_DIV_EXPR, itype,
9096 fold_build1 (NEGATE_EXPR, itype, t),
bc7bff74 9097 fold_build1 (NEGATE_EXPR, itype, step));
fd6481cf 9098 else
bc7bff74 9099 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
fd6481cf 9100 t = fold_convert (itype, t);
75a70cf9 9101 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
1e8e9920 9102
072f7ab1 9103 q = create_tmp_reg (itype, "q");
fd6481cf 9104 t = fold_build2 (TRUNC_DIV_EXPR, itype, n, nthreads);
31712e83 9105 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
9106 gsi_insert_before (&gsi, gimple_build_assign (q, t), GSI_SAME_STMT);
9107
072f7ab1 9108 tt = create_tmp_reg (itype, "tt");
31712e83 9109 t = fold_build2 (TRUNC_MOD_EXPR, itype, n, nthreads);
9110 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
9111 gsi_insert_before (&gsi, gimple_build_assign (tt, t), GSI_SAME_STMT);
1e8e9920 9112
31712e83 9113 t = build2 (LT_EXPR, boolean_type_node, threadid, tt);
1a91d914 9114 gcond *cond_stmt = gimple_build_cond_empty (t);
9115 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
31712e83 9116
1a91d914 9117 second_bb = split_block (entry_bb, cond_stmt)->dest;
31712e83 9118 gsi = gsi_last_bb (second_bb);
9119 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
9120
9121 gsi_insert_before (&gsi, gimple_build_assign (tt, build_int_cst (itype, 0)),
9122 GSI_SAME_STMT);
1a91d914 9123 gassign *assign_stmt
e9cf809e 9124 = gimple_build_assign (q, PLUS_EXPR, q, build_int_cst (itype, 1));
1a91d914 9125 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
31712e83 9126
1a91d914 9127 third_bb = split_block (second_bb, assign_stmt)->dest;
31712e83 9128 gsi = gsi_last_bb (third_bb);
9129 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
1e8e9920 9130
fd6481cf 9131 t = build2 (MULT_EXPR, itype, q, threadid);
31712e83 9132 t = build2 (PLUS_EXPR, itype, t, tt);
75a70cf9 9133 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
1e8e9920 9134
fd6481cf 9135 t = fold_build2 (PLUS_EXPR, itype, s0, q);
75a70cf9 9136 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
79acaae1 9137
1e8e9920 9138 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
75a70cf9 9139 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
773c5ba7 9140
75a70cf9 9141 /* Remove the GIMPLE_OMP_FOR statement. */
9142 gsi_remove (&gsi, true);
773c5ba7 9143
9144 /* Setup code for sequential iteration goes in SEQ_START_BB. */
75a70cf9 9145 gsi = gsi_start_bb (seq_start_bb);
1e8e9920 9146
bc7bff74 9147 tree startvar = fd->loop.v;
9148 tree endvar = NULL_TREE;
9149
9150 if (gimple_omp_for_combined_p (fd->for_stmt))
9151 {
9152 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
9153 ? gimple_omp_parallel_clauses (inner_stmt)
9154 : gimple_omp_for_clauses (inner_stmt);
9155 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
9156 gcc_assert (innerc);
9157 startvar = OMP_CLAUSE_DECL (innerc);
9158 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9159 OMP_CLAUSE__LOOPTEMP_);
9160 gcc_assert (innerc);
9161 endvar = OMP_CLAUSE_DECL (innerc);
9561765e 9162 if (fd->collapse > 1 && TREE_CODE (fd->loop.n2) != INTEGER_CST
9163 && gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
9164 {
9165 int i;
9166 for (i = 1; i < fd->collapse; i++)
9167 {
9168 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9169 OMP_CLAUSE__LOOPTEMP_);
9170 gcc_assert (innerc);
9171 }
9172 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9173 OMP_CLAUSE__LOOPTEMP_);
9174 if (innerc)
9175 {
9176 /* If needed (distribute parallel for with lastprivate),
9177 propagate down the total number of iterations. */
9178 tree t = fold_convert (TREE_TYPE (OMP_CLAUSE_DECL (innerc)),
9179 fd->loop.n2);
9180 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, false,
9181 GSI_CONTINUE_LINKING);
9182 assign_stmt = gimple_build_assign (OMP_CLAUSE_DECL (innerc), t);
9183 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9184 }
9185 }
bc7bff74 9186 }
fd6481cf 9187 t = fold_convert (itype, s0);
bc7bff74 9188 t = fold_build2 (MULT_EXPR, itype, t, step);
fd6481cf 9189 if (POINTER_TYPE_P (type))
bc7bff74 9190 t = fold_build_pointer_plus (n1, t);
fd6481cf 9191 else
bc7bff74 9192 t = fold_build2 (PLUS_EXPR, type, t, n1);
9193 t = fold_convert (TREE_TYPE (startvar), t);
4abecb72 9194 t = force_gimple_operand_gsi (&gsi, t,
bc7bff74 9195 DECL_P (startvar)
9196 && TREE_ADDRESSABLE (startvar),
4abecb72 9197 NULL_TREE, false, GSI_CONTINUE_LINKING);
1a91d914 9198 assign_stmt = gimple_build_assign (startvar, t);
9199 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
48e1416a 9200
fd6481cf 9201 t = fold_convert (itype, e0);
bc7bff74 9202 t = fold_build2 (MULT_EXPR, itype, t, step);
fd6481cf 9203 if (POINTER_TYPE_P (type))
bc7bff74 9204 t = fold_build_pointer_plus (n1, t);
fd6481cf 9205 else
bc7bff74 9206 t = fold_build2 (PLUS_EXPR, type, t, n1);
9207 t = fold_convert (TREE_TYPE (startvar), t);
75a70cf9 9208 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9209 false, GSI_CONTINUE_LINKING);
bc7bff74 9210 if (endvar)
9211 {
1a91d914 9212 assign_stmt = gimple_build_assign (endvar, e);
9213 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
d44f2f7c 9214 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
1a91d914 9215 assign_stmt = gimple_build_assign (fd->loop.v, e);
d44f2f7c 9216 else
e9cf809e 9217 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
1a91d914 9218 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
bc7bff74 9219 }
43895be5 9220 /* Handle linear clause adjustments. */
9221 tree itercnt = NULL_TREE;
9222 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_FOR)
9223 for (tree c = gimple_omp_for_clauses (fd->for_stmt);
9224 c; c = OMP_CLAUSE_CHAIN (c))
9225 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
9226 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
9227 {
9228 tree d = OMP_CLAUSE_DECL (c);
9229 bool is_ref = is_reference (d);
9230 tree t = d, a, dest;
9231 if (is_ref)
9232 t = build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c), t);
9233 if (itercnt == NULL_TREE)
9234 {
9235 if (gimple_omp_for_combined_into_p (fd->for_stmt))
9236 {
9237 itercnt = fold_build2 (MINUS_EXPR, itype,
9238 fold_convert (itype, n1),
9239 fold_convert (itype, fd->loop.n1));
9240 itercnt = fold_build2 (EXACT_DIV_EXPR, itype, itercnt, step);
9241 itercnt = fold_build2 (PLUS_EXPR, itype, itercnt, s0);
9242 itercnt = force_gimple_operand_gsi (&gsi, itercnt, true,
9243 NULL_TREE, false,
9244 GSI_CONTINUE_LINKING);
9245 }
9246 else
9247 itercnt = s0;
9248 }
9249 tree type = TREE_TYPE (t);
9250 if (POINTER_TYPE_P (type))
9251 type = sizetype;
9252 a = fold_build2 (MULT_EXPR, type,
9253 fold_convert (type, itercnt),
9254 fold_convert (type, OMP_CLAUSE_LINEAR_STEP (c)));
9255 dest = unshare_expr (t);
9256 t = fold_build2 (type == TREE_TYPE (t) ? PLUS_EXPR
9257 : POINTER_PLUS_EXPR, TREE_TYPE (t), t, a);
9258 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9259 false, GSI_CONTINUE_LINKING);
9260 assign_stmt = gimple_build_assign (dest, t);
9261 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9262 }
bc7bff74 9263 if (fd->collapse > 1)
9264 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
1e8e9920 9265
bc7bff74 9266 if (!broken_loop)
9267 {
9268 /* The code controlling the sequential loop replaces the
9269 GIMPLE_OMP_CONTINUE. */
9270 gsi = gsi_last_bb (cont_bb);
1a91d914 9271 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
9272 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
9273 vmain = gimple_omp_continue_control_use (cont_stmt);
9274 vback = gimple_omp_continue_control_def (cont_stmt);
79acaae1 9275
bc7bff74 9276 if (!gimple_omp_for_combined_p (fd->for_stmt))
9277 {
9278 if (POINTER_TYPE_P (type))
9279 t = fold_build_pointer_plus (vmain, step);
9280 else
9281 t = fold_build2 (PLUS_EXPR, type, vmain, step);
9282 t = force_gimple_operand_gsi (&gsi, t,
9283 DECL_P (vback)
9284 && TREE_ADDRESSABLE (vback),
9285 NULL_TREE, true, GSI_SAME_STMT);
1a91d914 9286 assign_stmt = gimple_build_assign (vback, t);
9287 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
79acaae1 9288
bc7bff74 9289 t = build2 (fd->loop.cond_code, boolean_type_node,
9290 DECL_P (vback) && TREE_ADDRESSABLE (vback)
9291 ? t : vback, e);
9292 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
9293 }
1e8e9920 9294
bc7bff74 9295 /* Remove the GIMPLE_OMP_CONTINUE statement. */
9296 gsi_remove (&gsi, true);
9297
9298 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
9299 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
9300 }
773c5ba7 9301
75a70cf9 9302 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
9303 gsi = gsi_last_bb (exit_bb);
9304 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
bc7bff74 9305 {
9306 t = gimple_omp_return_lhs (gsi_stmt (gsi));
a8e785ba 9307 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
bc7bff74 9308 }
75a70cf9 9309 gsi_remove (&gsi, true);
773c5ba7 9310
9311 /* Connect all the blocks. */
31712e83 9312 ep = make_edge (entry_bb, third_bb, EDGE_FALSE_VALUE);
9313 ep->probability = REG_BR_PROB_BASE / 4 * 3;
9314 ep = find_edge (entry_bb, second_bb);
9315 ep->flags = EDGE_TRUE_VALUE;
9316 ep->probability = REG_BR_PROB_BASE / 4;
9317 find_edge (third_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
9318 find_edge (third_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
79acaae1 9319
bc7bff74 9320 if (!broken_loop)
9321 {
9322 ep = find_edge (cont_bb, body_bb);
86a932e0 9323 if (ep == NULL)
9324 {
9325 ep = BRANCH_EDGE (cont_bb);
9326 gcc_assert (single_succ (ep->dest) == body_bb);
9327 }
bc7bff74 9328 if (gimple_omp_for_combined_p (fd->for_stmt))
9329 {
9330 remove_edge (ep);
9331 ep = NULL;
9332 }
9333 else if (fd->collapse > 1)
9334 {
9335 remove_edge (ep);
9336 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
9337 }
9338 else
9339 ep->flags = EDGE_TRUE_VALUE;
9340 find_edge (cont_bb, fin_bb)->flags
9341 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
9342 }
48e1416a 9343
31712e83 9344 set_immediate_dominator (CDI_DOMINATORS, second_bb, entry_bb);
9345 set_immediate_dominator (CDI_DOMINATORS, third_bb, entry_bb);
9346 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, third_bb);
bc7bff74 9347
79acaae1 9348 set_immediate_dominator (CDI_DOMINATORS, body_bb,
9349 recompute_dominator (CDI_DOMINATORS, body_bb));
9350 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
9351 recompute_dominator (CDI_DOMINATORS, fin_bb));
04c2922b 9352
86a932e0 9353 struct loop *loop = body_bb->loop_father;
9354 if (loop != entry_bb->loop_father)
9355 {
9356 gcc_assert (loop->header == body_bb);
9357 gcc_assert (broken_loop
9358 || loop->latch == region->cont
9359 || single_pred (loop->latch) == region->cont);
9360 return;
9361 }
9362
bc7bff74 9363 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
9364 {
86a932e0 9365 loop = alloc_loop ();
bc7bff74 9366 loop->header = body_bb;
9367 if (collapse_bb == NULL)
9368 loop->latch = cont_bb;
9369 add_loop (loop, body_bb->loop_father);
9370 }
1e8e9920 9371}
9372
281001a9 9373/* Return phi in E->DEST with ARG on edge E. */
9374
9375static gphi *
9376find_phi_with_arg_on_edge (tree arg, edge e)
9377{
9378 basic_block bb = e->dest;
9379
9380 for (gphi_iterator gpi = gsi_start_phis (bb);
9381 !gsi_end_p (gpi);
9382 gsi_next (&gpi))
9383 {
9384 gphi *phi = gpi.phi ();
9385 if (PHI_ARG_DEF_FROM_EDGE (phi, e) == arg)
9386 return phi;
9387 }
9388
9389 return NULL;
9390}
773c5ba7 9391
9392/* A subroutine of expand_omp_for. Generate code for a parallel
9393 loop with static schedule and a specified chunk size. Given
9394 parameters:
1e8e9920 9395
9396 for (V = N1; V cond N2; V += STEP) BODY;
9397
9398 where COND is "<" or ">", we generate pseudocode
9399
8e6b4515 9400 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
1e8e9920 9401 if (cond is <)
9402 adj = STEP - 1;
9403 else
9404 adj = STEP + 1;
fd6481cf 9405 if ((__typeof (V)) -1 > 0 && cond is >)
9406 n = -(adj + N2 - N1) / -STEP;
9407 else
9408 n = (adj + N2 - N1) / STEP;
1e8e9920 9409 trip = 0;
79acaae1 9410 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
9411 here so that V is defined
9412 if the loop is not entered
1e8e9920 9413 L0:
9414 s0 = (trip * nthreads + threadid) * CHUNK;
9415 e0 = min(s0 + CHUNK, n);
9416 if (s0 < n) goto L1; else goto L4;
9417 L1:
9418 V = s0 * STEP + N1;
9419 e = e0 * STEP + N1;
9420 L2:
9421 BODY;
9422 V += STEP;
9423 if (V cond e) goto L2; else goto L3;
9424 L3:
9425 trip += 1;
9426 goto L0;
9427 L4:
1e8e9920 9428*/
9429
61e47ac8 9430static void
bc7bff74 9431expand_omp_for_static_chunk (struct omp_region *region,
42acab1c 9432 struct omp_for_data *fd, gimple *inner_stmt)
1e8e9920 9433{
75a70cf9 9434 tree n, s0, e0, e, t;
79acaae1 9435 tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
93481288 9436 tree type, itype, vmain, vback, vextra;
773c5ba7 9437 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
bc7bff74 9438 basic_block trip_update_bb = NULL, cont_bb, collapse_bb = NULL, fin_bb;
93481288 9439 gimple_stmt_iterator gsi;
75a70cf9 9440 edge se;
bc7bff74 9441 bool broken_loop = region->cont == NULL;
9442 tree *counts = NULL;
9443 tree n1, n2, step;
1e8e9920 9444
fd6481cf 9445 itype = type = TREE_TYPE (fd->loop.v);
9446 if (POINTER_TYPE_P (type))
3cea8318 9447 itype = signed_type_for (type);
1e8e9920 9448
61e47ac8 9449 entry_bb = region->entry;
ac6e3339 9450 se = split_block (entry_bb, last_stmt (entry_bb));
9451 entry_bb = se->src;
9452 iter_part_bb = se->dest;
61e47ac8 9453 cont_bb = region->cont;
ac6e3339 9454 gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
bc7bff74 9455 fin_bb = BRANCH_EDGE (iter_part_bb)->dest;
9456 gcc_assert (broken_loop
9457 || fin_bb == FALLTHRU_EDGE (cont_bb)->dest);
ac6e3339 9458 seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
9459 body_bb = single_succ (seq_start_bb);
bc7bff74 9460 if (!broken_loop)
9461 {
fc1d58e3 9462 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb
9463 || single_succ (BRANCH_EDGE (cont_bb)->dest) == body_bb);
bc7bff74 9464 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
9465 trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
9466 }
61e47ac8 9467 exit_bb = region->exit;
773c5ba7 9468
773c5ba7 9469 /* Trip and adjustment setup goes in ENTRY_BB. */
93481288 9470 gsi = gsi_last_bb (entry_bb);
9471 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
773c5ba7 9472
bc7bff74 9473 if (fd->collapse > 1)
9474 {
43895be5 9475 int first_zero_iter = -1, dummy = -1;
9476 basic_block l2_dom_bb = NULL, dummy_bb = NULL;
bc7bff74 9477
9478 counts = XALLOCAVEC (tree, fd->collapse);
93481288 9479 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
bc7bff74 9480 fin_bb, first_zero_iter,
43895be5 9481 dummy_bb, dummy, l2_dom_bb);
bc7bff74 9482 t = NULL_TREE;
9483 }
9484 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
9485 t = integer_one_node;
9486 else
9487 t = fold_binary (fd->loop.cond_code, boolean_type_node,
9488 fold_convert (type, fd->loop.n1),
9489 fold_convert (type, fd->loop.n2));
9490 if (fd->collapse == 1
9491 && TYPE_UNSIGNED (type)
8e6b4515 9492 && (t == NULL_TREE || !integer_onep (t)))
9493 {
8e6b4515 9494 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
93481288 9495 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
8e6b4515 9496 true, GSI_SAME_STMT);
9497 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
93481288 9498 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
8e6b4515 9499 true, GSI_SAME_STMT);
1a91d914 9500 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
9501 NULL_TREE, NULL_TREE);
9502 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
9503 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
8e6b4515 9504 expand_omp_regimplify_p, NULL, NULL)
1a91d914 9505 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
8e6b4515 9506 expand_omp_regimplify_p, NULL, NULL))
9507 {
1a91d914 9508 gsi = gsi_for_stmt (cond_stmt);
9509 gimple_regimplify_operands (cond_stmt, &gsi);
8e6b4515 9510 }
1a91d914 9511 se = split_block (entry_bb, cond_stmt);
8e6b4515 9512 se->flags = EDGE_TRUE_VALUE;
9513 entry_bb = se->dest;
9514 se->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
9515 se = make_edge (se->src, fin_bb, EDGE_FALSE_VALUE);
9516 se->probability = REG_BR_PROB_BASE / 2000 - 1;
9517 if (gimple_in_ssa_p (cfun))
9518 {
264aa959 9519 int dest_idx = find_edge (iter_part_bb, fin_bb)->dest_idx;
1a91d914 9520 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
9521 !gsi_end_p (gpi); gsi_next (&gpi))
8e6b4515 9522 {
1a91d914 9523 gphi *phi = gpi.phi ();
8e6b4515 9524 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
9525 se, UNKNOWN_LOCATION);
9526 }
9527 }
93481288 9528 gsi = gsi_last_bb (entry_bb);
8e6b4515 9529 }
9530
ca4c3545 9531 switch (gimple_omp_for_kind (fd->for_stmt))
9532 {
9533 case GF_OMP_FOR_KIND_FOR:
9534 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
9535 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
9536 break;
9537 case GF_OMP_FOR_KIND_DISTRIBUTE:
9538 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
9539 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
9540 break;
ca4c3545 9541 default:
9542 gcc_unreachable ();
9543 }
9544 nthreads = build_call_expr (nthreads, 0);
9545 nthreads = fold_convert (itype, nthreads);
9546 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
75a70cf9 9547 true, GSI_SAME_STMT);
ca4c3545 9548 threadid = build_call_expr (threadid, 0);
9549 threadid = fold_convert (itype, threadid);
9550 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
75a70cf9 9551 true, GSI_SAME_STMT);
79acaae1 9552
bc7bff74 9553 n1 = fd->loop.n1;
9554 n2 = fd->loop.n2;
9555 step = fd->loop.step;
9556 if (gimple_omp_for_combined_into_p (fd->for_stmt))
9557 {
9558 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
9559 OMP_CLAUSE__LOOPTEMP_);
9560 gcc_assert (innerc);
9561 n1 = OMP_CLAUSE_DECL (innerc);
9562 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9563 OMP_CLAUSE__LOOPTEMP_);
9564 gcc_assert (innerc);
9565 n2 = OMP_CLAUSE_DECL (innerc);
9566 }
93481288 9567 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
bc7bff74 9568 true, NULL_TREE, true, GSI_SAME_STMT);
93481288 9569 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
bc7bff74 9570 true, NULL_TREE, true, GSI_SAME_STMT);
93481288 9571 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
bc7bff74 9572 true, NULL_TREE, true, GSI_SAME_STMT);
43895be5 9573 tree chunk_size = fold_convert (itype, fd->chunk_size);
9574 chunk_size = omp_adjust_chunk_size (chunk_size, fd->simd_schedule);
9575 chunk_size
9576 = force_gimple_operand_gsi (&gsi, chunk_size, true, NULL_TREE, true,
9577 GSI_SAME_STMT);
fd6481cf 9578
9579 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
bc7bff74 9580 t = fold_build2 (PLUS_EXPR, itype, step, t);
9581 t = fold_build2 (PLUS_EXPR, itype, t, n2);
9582 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
fd6481cf 9583 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
9584 t = fold_build2 (TRUNC_DIV_EXPR, itype,
9585 fold_build1 (NEGATE_EXPR, itype, t),
bc7bff74 9586 fold_build1 (NEGATE_EXPR, itype, step));
fd6481cf 9587 else
bc7bff74 9588 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
fd6481cf 9589 t = fold_convert (itype, t);
93481288 9590 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
75a70cf9 9591 true, GSI_SAME_STMT);
79acaae1 9592
083152fb 9593 trip_var = create_tmp_reg (itype, ".trip");
79acaae1 9594 if (gimple_in_ssa_p (cfun))
9595 {
f9e245b2 9596 trip_init = make_ssa_name (trip_var);
9597 trip_main = make_ssa_name (trip_var);
9598 trip_back = make_ssa_name (trip_var);
79acaae1 9599 }
1e8e9920 9600 else
79acaae1 9601 {
9602 trip_init = trip_var;
9603 trip_main = trip_var;
9604 trip_back = trip_var;
9605 }
1e8e9920 9606
1a91d914 9607 gassign *assign_stmt
9608 = gimple_build_assign (trip_init, build_int_cst (itype, 0));
9609 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
773c5ba7 9610
43895be5 9611 t = fold_build2 (MULT_EXPR, itype, threadid, chunk_size);
bc7bff74 9612 t = fold_build2 (MULT_EXPR, itype, t, step);
fd6481cf 9613 if (POINTER_TYPE_P (type))
bc7bff74 9614 t = fold_build_pointer_plus (n1, t);
fd6481cf 9615 else
bc7bff74 9616 t = fold_build2 (PLUS_EXPR, type, t, n1);
93481288 9617 vextra = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9618 true, GSI_SAME_STMT);
79acaae1 9619
75a70cf9 9620 /* Remove the GIMPLE_OMP_FOR. */
93481288 9621 gsi_remove (&gsi, true);
773c5ba7 9622
43895be5 9623 gimple_stmt_iterator gsif = gsi;
9624
773c5ba7 9625 /* Iteration space partitioning goes in ITER_PART_BB. */
93481288 9626 gsi = gsi_last_bb (iter_part_bb);
1e8e9920 9627
fd6481cf 9628 t = fold_build2 (MULT_EXPR, itype, trip_main, nthreads);
9629 t = fold_build2 (PLUS_EXPR, itype, t, threadid);
43895be5 9630 t = fold_build2 (MULT_EXPR, itype, t, chunk_size);
93481288 9631 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
75a70cf9 9632 false, GSI_CONTINUE_LINKING);
1e8e9920 9633
43895be5 9634 t = fold_build2 (PLUS_EXPR, itype, s0, chunk_size);
fd6481cf 9635 t = fold_build2 (MIN_EXPR, itype, t, n);
93481288 9636 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
75a70cf9 9637 false, GSI_CONTINUE_LINKING);
1e8e9920 9638
9639 t = build2 (LT_EXPR, boolean_type_node, s0, n);
93481288 9640 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_CONTINUE_LINKING);
773c5ba7 9641
9642 /* Setup code for sequential iteration goes in SEQ_START_BB. */
93481288 9643 gsi = gsi_start_bb (seq_start_bb);
1e8e9920 9644
bc7bff74 9645 tree startvar = fd->loop.v;
9646 tree endvar = NULL_TREE;
9647
9648 if (gimple_omp_for_combined_p (fd->for_stmt))
9649 {
9650 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
9651 ? gimple_omp_parallel_clauses (inner_stmt)
9652 : gimple_omp_for_clauses (inner_stmt);
9653 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
9654 gcc_assert (innerc);
9655 startvar = OMP_CLAUSE_DECL (innerc);
9656 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9657 OMP_CLAUSE__LOOPTEMP_);
9658 gcc_assert (innerc);
9659 endvar = OMP_CLAUSE_DECL (innerc);
9561765e 9660 if (fd->collapse > 1 && TREE_CODE (fd->loop.n2) != INTEGER_CST
9661 && gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
9662 {
9663 int i;
9664 for (i = 1; i < fd->collapse; i++)
9665 {
9666 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9667 OMP_CLAUSE__LOOPTEMP_);
9668 gcc_assert (innerc);
9669 }
9670 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9671 OMP_CLAUSE__LOOPTEMP_);
9672 if (innerc)
9673 {
9674 /* If needed (distribute parallel for with lastprivate),
9675 propagate down the total number of iterations. */
9676 tree t = fold_convert (TREE_TYPE (OMP_CLAUSE_DECL (innerc)),
9677 fd->loop.n2);
9678 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, false,
9679 GSI_CONTINUE_LINKING);
9680 assign_stmt = gimple_build_assign (OMP_CLAUSE_DECL (innerc), t);
9681 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9682 }
9683 }
bc7bff74 9684 }
9685
fd6481cf 9686 t = fold_convert (itype, s0);
bc7bff74 9687 t = fold_build2 (MULT_EXPR, itype, t, step);
fd6481cf 9688 if (POINTER_TYPE_P (type))
bc7bff74 9689 t = fold_build_pointer_plus (n1, t);
fd6481cf 9690 else
bc7bff74 9691 t = fold_build2 (PLUS_EXPR, type, t, n1);
9692 t = fold_convert (TREE_TYPE (startvar), t);
93481288 9693 t = force_gimple_operand_gsi (&gsi, t,
bc7bff74 9694 DECL_P (startvar)
9695 && TREE_ADDRESSABLE (startvar),
4abecb72 9696 NULL_TREE, false, GSI_CONTINUE_LINKING);
1a91d914 9697 assign_stmt = gimple_build_assign (startvar, t);
9698 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
1e8e9920 9699
fd6481cf 9700 t = fold_convert (itype, e0);
bc7bff74 9701 t = fold_build2 (MULT_EXPR, itype, t, step);
fd6481cf 9702 if (POINTER_TYPE_P (type))
bc7bff74 9703 t = fold_build_pointer_plus (n1, t);
fd6481cf 9704 else
bc7bff74 9705 t = fold_build2 (PLUS_EXPR, type, t, n1);
9706 t = fold_convert (TREE_TYPE (startvar), t);
93481288 9707 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
75a70cf9 9708 false, GSI_CONTINUE_LINKING);
bc7bff74 9709 if (endvar)
9710 {
1a91d914 9711 assign_stmt = gimple_build_assign (endvar, e);
9712 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
d44f2f7c 9713 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
1a91d914 9714 assign_stmt = gimple_build_assign (fd->loop.v, e);
d44f2f7c 9715 else
e9cf809e 9716 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
1a91d914 9717 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
bc7bff74 9718 }
43895be5 9719 /* Handle linear clause adjustments. */
9720 tree itercnt = NULL_TREE, itercntbias = NULL_TREE;
9721 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_FOR)
9722 for (tree c = gimple_omp_for_clauses (fd->for_stmt);
9723 c; c = OMP_CLAUSE_CHAIN (c))
9724 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
9725 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
9726 {
9727 tree d = OMP_CLAUSE_DECL (c);
9728 bool is_ref = is_reference (d);
9729 tree t = d, a, dest;
9730 if (is_ref)
9731 t = build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c), t);
9732 tree type = TREE_TYPE (t);
9733 if (POINTER_TYPE_P (type))
9734 type = sizetype;
9735 dest = unshare_expr (t);
9736 tree v = create_tmp_var (TREE_TYPE (t), NULL);
9737 expand_omp_build_assign (&gsif, v, t);
9738 if (itercnt == NULL_TREE)
9739 {
9740 if (gimple_omp_for_combined_into_p (fd->for_stmt))
9741 {
9742 itercntbias
9743 = fold_build2 (MINUS_EXPR, itype, fold_convert (itype, n1),
9744 fold_convert (itype, fd->loop.n1));
9745 itercntbias = fold_build2 (EXACT_DIV_EXPR, itype,
9746 itercntbias, step);
9747 itercntbias
9748 = force_gimple_operand_gsi (&gsif, itercntbias, true,
9749 NULL_TREE, true,
9750 GSI_SAME_STMT);
9751 itercnt = fold_build2 (PLUS_EXPR, itype, itercntbias, s0);
9752 itercnt = force_gimple_operand_gsi (&gsi, itercnt, true,
9753 NULL_TREE, false,
9754 GSI_CONTINUE_LINKING);
9755 }
9756 else
9757 itercnt = s0;
9758 }
9759 a = fold_build2 (MULT_EXPR, type,
9760 fold_convert (type, itercnt),
9761 fold_convert (type, OMP_CLAUSE_LINEAR_STEP (c)));
9762 t = fold_build2 (type == TREE_TYPE (t) ? PLUS_EXPR
9763 : POINTER_PLUS_EXPR, TREE_TYPE (t), v, a);
9764 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9765 false, GSI_CONTINUE_LINKING);
9766 assign_stmt = gimple_build_assign (dest, t);
9767 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9768 }
bc7bff74 9769 if (fd->collapse > 1)
93481288 9770 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
bc7bff74 9771
9772 if (!broken_loop)
9773 {
9774 /* The code controlling the sequential loop goes in CONT_BB,
9775 replacing the GIMPLE_OMP_CONTINUE. */
93481288 9776 gsi = gsi_last_bb (cont_bb);
1a91d914 9777 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
9778 vmain = gimple_omp_continue_control_use (cont_stmt);
9779 vback = gimple_omp_continue_control_def (cont_stmt);
1e8e9920 9780
bc7bff74 9781 if (!gimple_omp_for_combined_p (fd->for_stmt))
9782 {
9783 if (POINTER_TYPE_P (type))
93481288 9784 t = fold_build_pointer_plus (vmain, step);
bc7bff74 9785 else
93481288 9786 t = fold_build2 (PLUS_EXPR, type, vmain, step);
9787 if (DECL_P (vback) && TREE_ADDRESSABLE (vback))
9788 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
bc7bff74 9789 true, GSI_SAME_STMT);
1a91d914 9790 assign_stmt = gimple_build_assign (vback, t);
9791 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
79acaae1 9792
345f9789 9793 if (tree_int_cst_equal (fd->chunk_size, integer_one_node))
9794 t = build2 (EQ_EXPR, boolean_type_node,
9795 build_int_cst (itype, 0),
9796 build_int_cst (itype, 1));
9797 else
9798 t = build2 (fd->loop.cond_code, boolean_type_node,
9799 DECL_P (vback) && TREE_ADDRESSABLE (vback)
9800 ? t : vback, e);
93481288 9801 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
bc7bff74 9802 }
79acaae1 9803
bc7bff74 9804 /* Remove GIMPLE_OMP_CONTINUE. */
93481288 9805 gsi_remove (&gsi, true);
48e1416a 9806
bc7bff74 9807 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
9808 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
773c5ba7 9809
bc7bff74 9810 /* Trip update code goes into TRIP_UPDATE_BB. */
93481288 9811 gsi = gsi_start_bb (trip_update_bb);
1e8e9920 9812
bc7bff74 9813 t = build_int_cst (itype, 1);
9814 t = build2 (PLUS_EXPR, itype, trip_main, t);
1a91d914 9815 assign_stmt = gimple_build_assign (trip_back, t);
9816 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
bc7bff74 9817 }
1e8e9920 9818
75a70cf9 9819 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
93481288 9820 gsi = gsi_last_bb (exit_bb);
9821 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
bc7bff74 9822 {
93481288 9823 t = gimple_omp_return_lhs (gsi_stmt (gsi));
a8e785ba 9824 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
bc7bff74 9825 }
93481288 9826 gsi_remove (&gsi, true);
1e8e9920 9827
773c5ba7 9828 /* Connect the new blocks. */
ac6e3339 9829 find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
9830 find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
79acaae1 9831
bc7bff74 9832 if (!broken_loop)
9833 {
9834 se = find_edge (cont_bb, body_bb);
fc1d58e3 9835 if (se == NULL)
9836 {
9837 se = BRANCH_EDGE (cont_bb);
9838 gcc_assert (single_succ (se->dest) == body_bb);
9839 }
bc7bff74 9840 if (gimple_omp_for_combined_p (fd->for_stmt))
9841 {
9842 remove_edge (se);
9843 se = NULL;
9844 }
9845 else if (fd->collapse > 1)
9846 {
9847 remove_edge (se);
9848 se = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
9849 }
9850 else
9851 se->flags = EDGE_TRUE_VALUE;
9852 find_edge (cont_bb, trip_update_bb)->flags
9853 = se ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
79acaae1 9854
bc7bff74 9855 redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb);
9856 }
79acaae1 9857
9858 if (gimple_in_ssa_p (cfun))
9859 {
1a91d914 9860 gphi_iterator psi;
9861 gphi *phi;
75a70cf9 9862 edge re, ene;
75a70cf9 9863 edge_var_map *vm;
9864 size_t i;
9865
bc7bff74 9866 gcc_assert (fd->collapse == 1 && !broken_loop);
9867
79acaae1 9868 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
9869 remove arguments of the phi nodes in fin_bb. We need to create
9870 appropriate phi nodes in iter_part_bb instead. */
264aa959 9871 se = find_edge (iter_part_bb, fin_bb);
79acaae1 9872 re = single_succ_edge (trip_update_bb);
06ecf488 9873 vec<edge_var_map> *head = redirect_edge_var_map_vector (re);
79acaae1 9874 ene = single_succ_edge (entry_bb);
9875
75a70cf9 9876 psi = gsi_start_phis (fin_bb);
f1f41a6c 9877 for (i = 0; !gsi_end_p (psi) && head->iterate (i, &vm);
75a70cf9 9878 gsi_next (&psi), ++i)
79acaae1 9879 {
1a91d914 9880 gphi *nphi;
efbcb6de 9881 source_location locus;
75a70cf9 9882
1a91d914 9883 phi = psi.phi ();
75a70cf9 9884 t = gimple_phi_result (phi);
9885 gcc_assert (t == redirect_edge_var_map_result (vm));
264aa959 9886
9887 if (!single_pred_p (fin_bb))
9888 t = copy_ssa_name (t, phi);
9889
79acaae1 9890 nphi = create_phi_node (t, iter_part_bb);
79acaae1 9891
9892 t = PHI_ARG_DEF_FROM_EDGE (phi, se);
efbcb6de 9893 locus = gimple_phi_arg_location_from_edge (phi, se);
9894
fd6481cf 9895 /* A special case -- fd->loop.v is not yet computed in
93481288 9896 iter_part_bb, we need to use vextra instead. */
fd6481cf 9897 if (t == fd->loop.v)
93481288 9898 t = vextra;
60d535d2 9899 add_phi_arg (nphi, t, ene, locus);
efbcb6de 9900 locus = redirect_edge_var_map_location (vm);
281001a9 9901 tree back_arg = redirect_edge_var_map_def (vm);
9902 add_phi_arg (nphi, back_arg, re, locus);
9903 edge ce = find_edge (cont_bb, body_bb);
9904 if (ce == NULL)
9905 {
9906 ce = BRANCH_EDGE (cont_bb);
9907 gcc_assert (single_succ (ce->dest) == body_bb);
9908 ce = single_succ_edge (ce->dest);
9909 }
9910 gphi *inner_loop_phi = find_phi_with_arg_on_edge (back_arg, ce);
9911 gcc_assert (inner_loop_phi != NULL);
9912 add_phi_arg (inner_loop_phi, gimple_phi_result (nphi),
9913 find_edge (seq_start_bb, body_bb), locus);
264aa959 9914
9915 if (!single_pred_p (fin_bb))
9916 add_phi_arg (phi, gimple_phi_result (nphi), se, locus);
75a70cf9 9917 }
4d556e29 9918 gcc_assert (gsi_end_p (psi) && (head == NULL || i == head->length ()));
75a70cf9 9919 redirect_edge_var_map_clear (re);
264aa959 9920 if (single_pred_p (fin_bb))
9921 while (1)
9922 {
9923 psi = gsi_start_phis (fin_bb);
9924 if (gsi_end_p (psi))
9925 break;
9926 remove_phi_node (&psi, false);
9927 }
79acaae1 9928
9929 /* Make phi node for trip. */
9930 phi = create_phi_node (trip_main, iter_part_bb);
efbcb6de 9931 add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb),
60d535d2 9932 UNKNOWN_LOCATION);
efbcb6de 9933 add_phi_arg (phi, trip_init, single_succ_edge (entry_bb),
60d535d2 9934 UNKNOWN_LOCATION);
79acaae1 9935 }
9936
bc7bff74 9937 if (!broken_loop)
9938 set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
79acaae1 9939 set_immediate_dominator (CDI_DOMINATORS, iter_part_bb,
9940 recompute_dominator (CDI_DOMINATORS, iter_part_bb));
9941 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
9942 recompute_dominator (CDI_DOMINATORS, fin_bb));
9943 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb,
9944 recompute_dominator (CDI_DOMINATORS, seq_start_bb));
9945 set_immediate_dominator (CDI_DOMINATORS, body_bb,
9946 recompute_dominator (CDI_DOMINATORS, body_bb));
04c2922b 9947
bc7bff74 9948 if (!broken_loop)
9949 {
fc1d58e3 9950 struct loop *loop = body_bb->loop_father;
bc7bff74 9951 struct loop *trip_loop = alloc_loop ();
9952 trip_loop->header = iter_part_bb;
9953 trip_loop->latch = trip_update_bb;
9954 add_loop (trip_loop, iter_part_bb->loop_father);
04c2922b 9955
fc1d58e3 9956 if (loop != entry_bb->loop_father)
9957 {
9958 gcc_assert (loop->header == body_bb);
9959 gcc_assert (loop->latch == region->cont
9960 || single_pred (loop->latch) == region->cont);
9961 trip_loop->inner = loop;
9962 return;
9963 }
9964
bc7bff74 9965 if (!gimple_omp_for_combined_p (fd->for_stmt))
9966 {
fc1d58e3 9967 loop = alloc_loop ();
bc7bff74 9968 loop->header = body_bb;
33ee4d72 9969 if (collapse_bb == NULL)
9970 loop->latch = cont_bb;
bc7bff74 9971 add_loop (loop, trip_loop);
9972 }
9973 }
1e8e9920 9974}
9975
40750995 9976/* A subroutine of expand_omp_for. Generate code for _Cilk_for loop.
9977 Given parameters:
9978 for (V = N1; V cond N2; V += STEP) BODY;
9979
9980 where COND is "<" or ">" or "!=", we generate pseudocode
9981
9982 for (ind_var = low; ind_var < high; ind_var++)
9983 {
9984 V = n1 + (ind_var * STEP)
9985
9986 <BODY>
9987 }
9988
9989 In the above pseudocode, low and high are function parameters of the
9990 child function. In the function below, we are inserting a temp.
9991 variable that will be making a call to two OMP functions that will not be
9992 found in the body of _Cilk_for (since OMP_FOR cannot be mixed
9993 with _Cilk_for). These functions are replaced with low and high
9994 by the function that handles taskreg. */
9995
9996
9997static void
9998expand_cilk_for (struct omp_region *region, struct omp_for_data *fd)
9999{
10000 bool broken_loop = region->cont == NULL;
10001 basic_block entry_bb = region->entry;
10002 basic_block cont_bb = region->cont;
10003
10004 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
10005 gcc_assert (broken_loop
10006 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
10007 basic_block l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
10008 basic_block l1_bb, l2_bb;
10009
10010 if (!broken_loop)
10011 {
10012 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
10013 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
10014 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
10015 l2_bb = BRANCH_EDGE (entry_bb)->dest;
10016 }
10017 else
10018 {
10019 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
10020 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
10021 l2_bb = single_succ (l1_bb);
10022 }
10023 basic_block exit_bb = region->exit;
10024 basic_block l2_dom_bb = NULL;
10025
10026 gimple_stmt_iterator gsi = gsi_last_bb (entry_bb);
10027
10028 /* Below statements until the "tree high_val = ..." are pseudo statements
10029 used to pass information to be used by expand_omp_taskreg.
10030 low_val and high_val will be replaced by the __low and __high
10031 parameter from the child function.
10032
10033 The call_exprs part is a place-holder, it is mainly used
10034 to distinctly identify to the top-level part that this is
10035 where we should put low and high (reasoning given in header
10036 comment). */
10037
10038 tree child_fndecl
1a91d914 10039 = gimple_omp_parallel_child_fn (
10040 as_a <gomp_parallel *> (last_stmt (region->outer->entry)));
40750995 10041 tree t, low_val = NULL_TREE, high_val = NULL_TREE;
10042 for (t = DECL_ARGUMENTS (child_fndecl); t; t = TREE_CHAIN (t))
10043 {
10044 if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__high"))
10045 high_val = t;
10046 else if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__low"))
10047 low_val = t;
10048 }
10049 gcc_assert (low_val && high_val);
10050
10051 tree type = TREE_TYPE (low_val);
10052 tree ind_var = create_tmp_reg (type, "__cilk_ind_var");
10053 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
10054
10055 /* Not needed in SSA form right now. */
10056 gcc_assert (!gimple_in_ssa_p (cfun));
10057 if (l2_dom_bb == NULL)
10058 l2_dom_bb = l1_bb;
10059
10060 tree n1 = low_val;
10061 tree n2 = high_val;
10062
42acab1c 10063 gimple *stmt = gimple_build_assign (ind_var, n1);
40750995 10064
10065 /* Replace the GIMPLE_OMP_FOR statement. */
10066 gsi_replace (&gsi, stmt, true);
10067
10068 if (!broken_loop)
10069 {
10070 /* Code to control the increment goes in the CONT_BB. */
10071 gsi = gsi_last_bb (cont_bb);
10072 stmt = gsi_stmt (gsi);
10073 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
e9cf809e 10074 stmt = gimple_build_assign (ind_var, PLUS_EXPR, ind_var,
10075 build_one_cst (type));
40750995 10076
10077 /* Replace GIMPLE_OMP_CONTINUE. */
10078 gsi_replace (&gsi, stmt, true);
10079 }
10080
10081 /* Emit the condition in L1_BB. */
10082 gsi = gsi_after_labels (l1_bb);
10083 t = fold_build2 (MULT_EXPR, TREE_TYPE (fd->loop.step),
10084 fold_convert (TREE_TYPE (fd->loop.step), ind_var),
10085 fd->loop.step);
10086 if (POINTER_TYPE_P (TREE_TYPE (fd->loop.n1)))
10087 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (fd->loop.n1),
10088 fd->loop.n1, fold_convert (sizetype, t));
10089 else
10090 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loop.n1),
10091 fd->loop.n1, fold_convert (TREE_TYPE (fd->loop.n1), t));
10092 t = fold_convert (TREE_TYPE (fd->loop.v), t);
10093 expand_omp_build_assign (&gsi, fd->loop.v, t);
10094
10095 /* The condition is always '<' since the runtime will fill in the low
10096 and high values. */
10097 stmt = gimple_build_cond (LT_EXPR, ind_var, n2, NULL_TREE, NULL_TREE);
10098 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
10099
10100 /* Remove GIMPLE_OMP_RETURN. */
10101 gsi = gsi_last_bb (exit_bb);
10102 gsi_remove (&gsi, true);
10103
10104 /* Connect the new blocks. */
10105 remove_edge (FALLTHRU_EDGE (entry_bb));
10106
10107 edge e, ne;
10108 if (!broken_loop)
10109 {
10110 remove_edge (BRANCH_EDGE (entry_bb));
10111 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
10112
10113 e = BRANCH_EDGE (l1_bb);
10114 ne = FALLTHRU_EDGE (l1_bb);
10115 e->flags = EDGE_TRUE_VALUE;
10116 }
10117 else
10118 {
10119 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
10120
10121 ne = single_succ_edge (l1_bb);
10122 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
10123
10124 }
10125 ne->flags = EDGE_FALSE_VALUE;
10126 e->probability = REG_BR_PROB_BASE * 7 / 8;
10127 ne->probability = REG_BR_PROB_BASE / 8;
10128
10129 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
10130 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
10131 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
10132
10133 if (!broken_loop)
10134 {
10135 struct loop *loop = alloc_loop ();
10136 loop->header = l1_bb;
10137 loop->latch = cont_bb;
10138 add_loop (loop, l1_bb->loop_father);
10139 loop->safelen = INT_MAX;
10140 }
10141
10142 /* Pick the correct library function based on the precision of the
10143 induction variable type. */
10144 tree lib_fun = NULL_TREE;
10145 if (TYPE_PRECISION (type) == 32)
10146 lib_fun = cilk_for_32_fndecl;
10147 else if (TYPE_PRECISION (type) == 64)
10148 lib_fun = cilk_for_64_fndecl;
10149 else
10150 gcc_unreachable ();
10151
10152 gcc_assert (fd->sched_kind == OMP_CLAUSE_SCHEDULE_CILKFOR);
10153
10154 /* WS_ARGS contains the library function flavor to call:
10155 __libcilkrts_cilk_for_64 or __libcilkrts_cilk_for_32), and the
10156 user-defined grain value. If the user does not define one, then zero
10157 is passed in by the parser. */
10158 vec_alloc (region->ws_args, 2);
10159 region->ws_args->quick_push (lib_fun);
10160 region->ws_args->quick_push (fd->chunk_size);
10161}
bc7bff74 10162
3d483a94 10163/* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
10164 loop. Given parameters:
10165
10166 for (V = N1; V cond N2; V += STEP) BODY;
10167
10168 where COND is "<" or ">", we generate pseudocode
10169
10170 V = N1;
10171 goto L1;
10172 L0:
10173 BODY;
10174 V += STEP;
10175 L1:
10176 if (V cond N2) goto L0; else goto L2;
10177 L2:
10178
10179 For collapsed loops, given parameters:
10180 collapse(3)
10181 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
10182 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
10183 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
10184 BODY;
10185
10186 we generate pseudocode
10187
10188 if (cond3 is <)
10189 adj = STEP3 - 1;
10190 else
10191 adj = STEP3 + 1;
10192 count3 = (adj + N32 - N31) / STEP3;
10193 if (cond2 is <)
10194 adj = STEP2 - 1;
10195 else
10196 adj = STEP2 + 1;
10197 count2 = (adj + N22 - N21) / STEP2;
10198 if (cond1 is <)
10199 adj = STEP1 - 1;
10200 else
10201 adj = STEP1 + 1;
10202 count1 = (adj + N12 - N11) / STEP1;
10203 count = count1 * count2 * count3;
10204 V = 0;
10205 V1 = N11;
10206 V2 = N21;
10207 V3 = N31;
10208 goto L1;
10209 L0:
10210 BODY;
10211 V += 1;
10212 V3 += STEP3;
10213 V2 += (V3 cond3 N32) ? 0 : STEP2;
10214 V3 = (V3 cond3 N32) ? V3 : N31;
10215 V1 += (V2 cond2 N22) ? 0 : STEP1;
10216 V2 = (V2 cond2 N22) ? V2 : N21;
10217 L1:
10218 if (V < count) goto L0; else goto L2;
10219 L2:
10220
10221 */
10222
10223static void
10224expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
10225{
10226 tree type, t;
10227 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, l2_bb, l2_dom_bb;
10228 gimple_stmt_iterator gsi;
42acab1c 10229 gimple *stmt;
1a91d914 10230 gcond *cond_stmt;
3d483a94 10231 bool broken_loop = region->cont == NULL;
10232 edge e, ne;
10233 tree *counts = NULL;
10234 int i;
10235 tree safelen = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
10236 OMP_CLAUSE_SAFELEN);
10237 tree simduid = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
10238 OMP_CLAUSE__SIMDUID_);
bc7bff74 10239 tree n1, n2;
3d483a94 10240
10241 type = TREE_TYPE (fd->loop.v);
10242 entry_bb = region->entry;
10243 cont_bb = region->cont;
10244 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
10245 gcc_assert (broken_loop
10246 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
10247 l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
10248 if (!broken_loop)
10249 {
10250 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
10251 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
10252 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
10253 l2_bb = BRANCH_EDGE (entry_bb)->dest;
10254 }
10255 else
10256 {
10257 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
10258 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
10259 l2_bb = single_succ (l1_bb);
10260 }
10261 exit_bb = region->exit;
10262 l2_dom_bb = NULL;
10263
10264 gsi = gsi_last_bb (entry_bb);
10265
10266 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
10267 /* Not needed in SSA form right now. */
10268 gcc_assert (!gimple_in_ssa_p (cfun));
10269 if (fd->collapse > 1)
10270 {
43895be5 10271 int first_zero_iter = -1, dummy = -1;
10272 basic_block zero_iter_bb = l2_bb, dummy_bb = NULL;
3d483a94 10273
10274 counts = XALLOCAVEC (tree, fd->collapse);
10275 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
10276 zero_iter_bb, first_zero_iter,
43895be5 10277 dummy_bb, dummy, l2_dom_bb);
3d483a94 10278 }
10279 if (l2_dom_bb == NULL)
10280 l2_dom_bb = l1_bb;
10281
bc7bff74 10282 n1 = fd->loop.n1;
3d483a94 10283 n2 = fd->loop.n2;
bc7bff74 10284 if (gimple_omp_for_combined_into_p (fd->for_stmt))
10285 {
10286 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
10287 OMP_CLAUSE__LOOPTEMP_);
10288 gcc_assert (innerc);
10289 n1 = OMP_CLAUSE_DECL (innerc);
10290 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
10291 OMP_CLAUSE__LOOPTEMP_);
10292 gcc_assert (innerc);
10293 n2 = OMP_CLAUSE_DECL (innerc);
10294 expand_omp_build_assign (&gsi, fd->loop.v,
10295 fold_convert (type, n1));
10296 if (fd->collapse > 1)
10297 {
10298 gsi_prev (&gsi);
10299 expand_omp_for_init_vars (fd, &gsi, counts, NULL, n1);
10300 gsi_next (&gsi);
10301 }
10302 }
3d483a94 10303 else
10304 {
10305 expand_omp_build_assign (&gsi, fd->loop.v,
10306 fold_convert (type, fd->loop.n1));
10307 if (fd->collapse > 1)
10308 for (i = 0; i < fd->collapse; i++)
10309 {
10310 tree itype = TREE_TYPE (fd->loops[i].v);
10311 if (POINTER_TYPE_P (itype))
10312 itype = signed_type_for (itype);
10313 t = fold_convert (TREE_TYPE (fd->loops[i].v), fd->loops[i].n1);
10314 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
10315 }
10316 }
10317
10318 /* Remove the GIMPLE_OMP_FOR statement. */
10319 gsi_remove (&gsi, true);
10320
10321 if (!broken_loop)
10322 {
10323 /* Code to control the increment goes in the CONT_BB. */
10324 gsi = gsi_last_bb (cont_bb);
10325 stmt = gsi_stmt (gsi);
10326 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
10327
10328 if (POINTER_TYPE_P (type))
10329 t = fold_build_pointer_plus (fd->loop.v, fd->loop.step);
10330 else
10331 t = fold_build2 (PLUS_EXPR, type, fd->loop.v, fd->loop.step);
10332 expand_omp_build_assign (&gsi, fd->loop.v, t);
10333
10334 if (fd->collapse > 1)
10335 {
10336 i = fd->collapse - 1;
10337 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
10338 {
10339 t = fold_convert (sizetype, fd->loops[i].step);
10340 t = fold_build_pointer_plus (fd->loops[i].v, t);
10341 }
10342 else
10343 {
10344 t = fold_convert (TREE_TYPE (fd->loops[i].v),
10345 fd->loops[i].step);
10346 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
10347 fd->loops[i].v, t);
10348 }
10349 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
10350
10351 for (i = fd->collapse - 1; i > 0; i--)
10352 {
10353 tree itype = TREE_TYPE (fd->loops[i].v);
10354 tree itype2 = TREE_TYPE (fd->loops[i - 1].v);
10355 if (POINTER_TYPE_P (itype2))
10356 itype2 = signed_type_for (itype2);
10357 t = build3 (COND_EXPR, itype2,
10358 build2 (fd->loops[i].cond_code, boolean_type_node,
10359 fd->loops[i].v,
10360 fold_convert (itype, fd->loops[i].n2)),
10361 build_int_cst (itype2, 0),
10362 fold_convert (itype2, fd->loops[i - 1].step));
10363 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i - 1].v)))
10364 t = fold_build_pointer_plus (fd->loops[i - 1].v, t);
10365 else
10366 t = fold_build2 (PLUS_EXPR, itype2, fd->loops[i - 1].v, t);
10367 expand_omp_build_assign (&gsi, fd->loops[i - 1].v, t);
10368
10369 t = build3 (COND_EXPR, itype,
10370 build2 (fd->loops[i].cond_code, boolean_type_node,
10371 fd->loops[i].v,
10372 fold_convert (itype, fd->loops[i].n2)),
10373 fd->loops[i].v,
10374 fold_convert (itype, fd->loops[i].n1));
10375 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
10376 }
10377 }
10378
10379 /* Remove GIMPLE_OMP_CONTINUE. */
10380 gsi_remove (&gsi, true);
10381 }
10382
10383 /* Emit the condition in L1_BB. */
10384 gsi = gsi_start_bb (l1_bb);
10385
10386 t = fold_convert (type, n2);
10387 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
10388 false, GSI_CONTINUE_LINKING);
43895be5 10389 tree v = fd->loop.v;
10390 if (DECL_P (v) && TREE_ADDRESSABLE (v))
10391 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
10392 false, GSI_CONTINUE_LINKING);
10393 t = build2 (fd->loop.cond_code, boolean_type_node, v, t);
1a91d914 10394 cond_stmt = gimple_build_cond_empty (t);
10395 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
10396 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt), expand_omp_regimplify_p,
3d483a94 10397 NULL, NULL)
1a91d914 10398 || walk_tree (gimple_cond_rhs_ptr (cond_stmt), expand_omp_regimplify_p,
3d483a94 10399 NULL, NULL))
10400 {
1a91d914 10401 gsi = gsi_for_stmt (cond_stmt);
10402 gimple_regimplify_operands (cond_stmt, &gsi);
3d483a94 10403 }
10404
10405 /* Remove GIMPLE_OMP_RETURN. */
10406 gsi = gsi_last_bb (exit_bb);
10407 gsi_remove (&gsi, true);
10408
10409 /* Connect the new blocks. */
10410 remove_edge (FALLTHRU_EDGE (entry_bb));
10411
10412 if (!broken_loop)
10413 {
10414 remove_edge (BRANCH_EDGE (entry_bb));
10415 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
10416
10417 e = BRANCH_EDGE (l1_bb);
10418 ne = FALLTHRU_EDGE (l1_bb);
10419 e->flags = EDGE_TRUE_VALUE;
10420 }
10421 else
10422 {
10423 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
10424
10425 ne = single_succ_edge (l1_bb);
10426 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
10427
10428 }
10429 ne->flags = EDGE_FALSE_VALUE;
10430 e->probability = REG_BR_PROB_BASE * 7 / 8;
10431 ne->probability = REG_BR_PROB_BASE / 8;
10432
10433 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
10434 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
10435 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
10436
10437 if (!broken_loop)
10438 {
10439 struct loop *loop = alloc_loop ();
10440 loop->header = l1_bb;
33ee4d72 10441 loop->latch = cont_bb;
3d483a94 10442 add_loop (loop, l1_bb->loop_father);
10443 if (safelen == NULL_TREE)
10444 loop->safelen = INT_MAX;
10445 else
10446 {
10447 safelen = OMP_CLAUSE_SAFELEN_EXPR (safelen);
c3f3b68d 10448 if (TREE_CODE (safelen) != INTEGER_CST)
10449 loop->safelen = 0;
10450 else if (!tree_fits_uhwi_p (safelen)
10451 || tree_to_uhwi (safelen) > INT_MAX)
3d483a94 10452 loop->safelen = INT_MAX;
10453 else
d85a2013 10454 loop->safelen = tree_to_uhwi (safelen);
3d483a94 10455 if (loop->safelen == 1)
10456 loop->safelen = 0;
10457 }
10458 if (simduid)
10459 {
43895be5 10460 loop->simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
10461 cfun->has_simduid_loops = true;
10462 }
10463 /* If not -fno-tree-loop-vectorize, hint that we want to vectorize
10464 the loop. */
10465 if ((flag_tree_loop_vectorize
10466 || (!global_options_set.x_flag_tree_loop_vectorize
10467 && !global_options_set.x_flag_tree_vectorize))
10468 && flag_tree_loop_optimize
10469 && loop->safelen > 1)
10470 {
10471 loop->force_vectorize = true;
10472 cfun->has_force_vectorize_loops = true;
10473 }
10474 }
10475 else if (simduid)
10476 cfun->has_simduid_loops = true;
10477}
10478
10479/* Taskloop construct is represented after gimplification with
10480 two GIMPLE_OMP_FOR constructs with GIMPLE_OMP_TASK sandwiched
10481 in between them. This routine expands the outer GIMPLE_OMP_FOR,
10482 which should just compute all the needed loop temporaries
10483 for GIMPLE_OMP_TASK. */
10484
10485static void
10486expand_omp_taskloop_for_outer (struct omp_region *region,
10487 struct omp_for_data *fd,
10488 gimple *inner_stmt)
10489{
10490 tree type, bias = NULL_TREE;
10491 basic_block entry_bb, cont_bb, exit_bb;
10492 gimple_stmt_iterator gsi;
10493 gassign *assign_stmt;
10494 tree *counts = NULL;
10495 int i;
10496
10497 gcc_assert (inner_stmt);
10498 gcc_assert (region->cont);
10499 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_TASK
10500 && gimple_omp_task_taskloop_p (inner_stmt));
10501 type = TREE_TYPE (fd->loop.v);
10502
10503 /* See if we need to bias by LLONG_MIN. */
10504 if (fd->iter_type == long_long_unsigned_type_node
10505 && TREE_CODE (type) == INTEGER_TYPE
10506 && !TYPE_UNSIGNED (type))
10507 {
10508 tree n1, n2;
10509
10510 if (fd->loop.cond_code == LT_EXPR)
10511 {
10512 n1 = fd->loop.n1;
10513 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
10514 }
10515 else
10516 {
10517 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
10518 n2 = fd->loop.n1;
10519 }
10520 if (TREE_CODE (n1) != INTEGER_CST
10521 || TREE_CODE (n2) != INTEGER_CST
10522 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
10523 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
10524 }
10525
10526 entry_bb = region->entry;
10527 cont_bb = region->cont;
10528 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
10529 gcc_assert (BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
10530 exit_bb = region->exit;
10531
10532 gsi = gsi_last_bb (entry_bb);
10533 gimple *for_stmt = gsi_stmt (gsi);
10534 gcc_assert (gimple_code (for_stmt) == GIMPLE_OMP_FOR);
10535 if (fd->collapse > 1)
10536 {
10537 int first_zero_iter = -1, dummy = -1;
10538 basic_block zero_iter_bb = NULL, dummy_bb = NULL, l2_dom_bb = NULL;
10539
10540 counts = XALLOCAVEC (tree, fd->collapse);
10541 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
10542 zero_iter_bb, first_zero_iter,
10543 dummy_bb, dummy, l2_dom_bb);
10544
10545 if (zero_iter_bb)
10546 {
10547 /* Some counts[i] vars might be uninitialized if
10548 some loop has zero iterations. But the body shouldn't
10549 be executed in that case, so just avoid uninit warnings. */
10550 for (i = first_zero_iter; i < fd->collapse; i++)
10551 if (SSA_VAR_P (counts[i]))
10552 TREE_NO_WARNING (counts[i]) = 1;
10553 gsi_prev (&gsi);
10554 edge e = split_block (entry_bb, gsi_stmt (gsi));
10555 entry_bb = e->dest;
10556 make_edge (zero_iter_bb, entry_bb, EDGE_FALLTHRU);
10557 gsi = gsi_last_bb (entry_bb);
10558 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
10559 get_immediate_dominator (CDI_DOMINATORS,
10560 zero_iter_bb));
10561 }
10562 }
10563
10564 tree t0, t1;
10565 t1 = fd->loop.n2;
10566 t0 = fd->loop.n1;
10567 if (POINTER_TYPE_P (TREE_TYPE (t0))
10568 && TYPE_PRECISION (TREE_TYPE (t0))
10569 != TYPE_PRECISION (fd->iter_type))
10570 {
10571 /* Avoid casting pointers to integer of a different size. */
10572 tree itype = signed_type_for (type);
10573 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
10574 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
10575 }
10576 else
10577 {
10578 t1 = fold_convert (fd->iter_type, t1);
10579 t0 = fold_convert (fd->iter_type, t0);
10580 }
10581 if (bias)
10582 {
10583 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
10584 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
10585 }
10586
10587 tree innerc = find_omp_clause (gimple_omp_task_clauses (inner_stmt),
10588 OMP_CLAUSE__LOOPTEMP_);
10589 gcc_assert (innerc);
10590 tree startvar = OMP_CLAUSE_DECL (innerc);
10591 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc), OMP_CLAUSE__LOOPTEMP_);
10592 gcc_assert (innerc);
10593 tree endvar = OMP_CLAUSE_DECL (innerc);
10594 if (fd->collapse > 1 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
10595 {
10596 gcc_assert (innerc);
10597 for (i = 1; i < fd->collapse; i++)
10598 {
10599 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
10600 OMP_CLAUSE__LOOPTEMP_);
10601 gcc_assert (innerc);
10602 }
10603 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
10604 OMP_CLAUSE__LOOPTEMP_);
10605 if (innerc)
10606 {
10607 /* If needed (inner taskloop has lastprivate clause), propagate
10608 down the total number of iterations. */
10609 tree t = force_gimple_operand_gsi (&gsi, fd->loop.n2, false,
10610 NULL_TREE, false,
10611 GSI_CONTINUE_LINKING);
10612 assign_stmt = gimple_build_assign (OMP_CLAUSE_DECL (innerc), t);
10613 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10614 }
10615 }
10616
10617 t0 = force_gimple_operand_gsi (&gsi, t0, false, NULL_TREE, false,
10618 GSI_CONTINUE_LINKING);
10619 assign_stmt = gimple_build_assign (startvar, t0);
10620 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10621
10622 t1 = force_gimple_operand_gsi (&gsi, t1, false, NULL_TREE, false,
10623 GSI_CONTINUE_LINKING);
10624 assign_stmt = gimple_build_assign (endvar, t1);
10625 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10626 if (fd->collapse > 1)
10627 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
10628
10629 /* Remove the GIMPLE_OMP_FOR statement. */
10630 gsi = gsi_for_stmt (for_stmt);
10631 gsi_remove (&gsi, true);
10632
10633 gsi = gsi_last_bb (cont_bb);
10634 gsi_remove (&gsi, true);
10635
10636 gsi = gsi_last_bb (exit_bb);
10637 gsi_remove (&gsi, true);
10638
10639 FALLTHRU_EDGE (entry_bb)->probability = REG_BR_PROB_BASE;
10640 remove_edge (BRANCH_EDGE (entry_bb));
10641 FALLTHRU_EDGE (cont_bb)->probability = REG_BR_PROB_BASE;
10642 remove_edge (BRANCH_EDGE (cont_bb));
10643 set_immediate_dominator (CDI_DOMINATORS, exit_bb, cont_bb);
10644 set_immediate_dominator (CDI_DOMINATORS, region->entry,
10645 recompute_dominator (CDI_DOMINATORS, region->entry));
10646}
10647
10648/* Taskloop construct is represented after gimplification with
10649 two GIMPLE_OMP_FOR constructs with GIMPLE_OMP_TASK sandwiched
10650 in between them. This routine expands the inner GIMPLE_OMP_FOR.
10651 GOMP_taskloop{,_ull} function arranges for each task to be given just
10652 a single range of iterations. */
10653
10654static void
10655expand_omp_taskloop_for_inner (struct omp_region *region,
10656 struct omp_for_data *fd,
10657 gimple *inner_stmt)
10658{
10659 tree e, t, type, itype, vmain, vback, bias = NULL_TREE;
10660 basic_block entry_bb, exit_bb, body_bb, cont_bb, collapse_bb = NULL;
10661 basic_block fin_bb;
10662 gimple_stmt_iterator gsi;
10663 edge ep;
10664 bool broken_loop = region->cont == NULL;
10665 tree *counts = NULL;
10666 tree n1, n2, step;
10667
10668 itype = type = TREE_TYPE (fd->loop.v);
10669 if (POINTER_TYPE_P (type))
10670 itype = signed_type_for (type);
10671
10672 /* See if we need to bias by LLONG_MIN. */
10673 if (fd->iter_type == long_long_unsigned_type_node
10674 && TREE_CODE (type) == INTEGER_TYPE
10675 && !TYPE_UNSIGNED (type))
10676 {
10677 tree n1, n2;
10678
10679 if (fd->loop.cond_code == LT_EXPR)
10680 {
10681 n1 = fd->loop.n1;
10682 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
10683 }
10684 else
10685 {
10686 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
10687 n2 = fd->loop.n1;
10688 }
10689 if (TREE_CODE (n1) != INTEGER_CST
10690 || TREE_CODE (n2) != INTEGER_CST
10691 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
10692 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
10693 }
10694
10695 entry_bb = region->entry;
10696 cont_bb = region->cont;
10697 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
10698 fin_bb = BRANCH_EDGE (entry_bb)->dest;
10699 gcc_assert (broken_loop
10700 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
10701 body_bb = FALLTHRU_EDGE (entry_bb)->dest;
10702 if (!broken_loop)
10703 {
10704 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
10705 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
10706 }
10707 exit_bb = region->exit;
10708
10709 /* Iteration space partitioning goes in ENTRY_BB. */
10710 gsi = gsi_last_bb (entry_bb);
10711 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
10712
10713 if (fd->collapse > 1)
10714 {
10715 int first_zero_iter = -1, dummy = -1;
10716 basic_block l2_dom_bb = NULL, dummy_bb = NULL;
10717
10718 counts = XALLOCAVEC (tree, fd->collapse);
10719 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
10720 fin_bb, first_zero_iter,
10721 dummy_bb, dummy, l2_dom_bb);
10722 t = NULL_TREE;
10723 }
10724 else
10725 t = integer_one_node;
10726
10727 step = fd->loop.step;
10728 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
10729 OMP_CLAUSE__LOOPTEMP_);
10730 gcc_assert (innerc);
10731 n1 = OMP_CLAUSE_DECL (innerc);
10732 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc), OMP_CLAUSE__LOOPTEMP_);
10733 gcc_assert (innerc);
10734 n2 = OMP_CLAUSE_DECL (innerc);
10735 if (bias)
10736 {
10737 n1 = fold_build2 (PLUS_EXPR, fd->iter_type, n1, bias);
10738 n2 = fold_build2 (PLUS_EXPR, fd->iter_type, n2, bias);
10739 }
10740 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
10741 true, NULL_TREE, true, GSI_SAME_STMT);
10742 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
10743 true, NULL_TREE, true, GSI_SAME_STMT);
10744 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
10745 true, NULL_TREE, true, GSI_SAME_STMT);
10746
10747 tree startvar = fd->loop.v;
10748 tree endvar = NULL_TREE;
10749
10750 if (gimple_omp_for_combined_p (fd->for_stmt))
10751 {
10752 tree clauses = gimple_omp_for_clauses (inner_stmt);
10753 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
10754 gcc_assert (innerc);
10755 startvar = OMP_CLAUSE_DECL (innerc);
10756 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
10757 OMP_CLAUSE__LOOPTEMP_);
10758 gcc_assert (innerc);
10759 endvar = OMP_CLAUSE_DECL (innerc);
10760 }
10761 t = fold_convert (TREE_TYPE (startvar), n1);
10762 t = force_gimple_operand_gsi (&gsi, t,
10763 DECL_P (startvar)
10764 && TREE_ADDRESSABLE (startvar),
10765 NULL_TREE, false, GSI_CONTINUE_LINKING);
10766 gimple *assign_stmt = gimple_build_assign (startvar, t);
10767 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10768
10769 t = fold_convert (TREE_TYPE (startvar), n2);
10770 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
10771 false, GSI_CONTINUE_LINKING);
10772 if (endvar)
10773 {
10774 assign_stmt = gimple_build_assign (endvar, e);
10775 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10776 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
10777 assign_stmt = gimple_build_assign (fd->loop.v, e);
10778 else
10779 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
10780 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10781 }
10782 if (fd->collapse > 1)
10783 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
10784
10785 if (!broken_loop)
10786 {
10787 /* The code controlling the sequential loop replaces the
10788 GIMPLE_OMP_CONTINUE. */
10789 gsi = gsi_last_bb (cont_bb);
10790 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
10791 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
10792 vmain = gimple_omp_continue_control_use (cont_stmt);
10793 vback = gimple_omp_continue_control_def (cont_stmt);
10794
10795 if (!gimple_omp_for_combined_p (fd->for_stmt))
10796 {
10797 if (POINTER_TYPE_P (type))
10798 t = fold_build_pointer_plus (vmain, step);
10799 else
10800 t = fold_build2 (PLUS_EXPR, type, vmain, step);
10801 t = force_gimple_operand_gsi (&gsi, t,
10802 DECL_P (vback)
10803 && TREE_ADDRESSABLE (vback),
10804 NULL_TREE, true, GSI_SAME_STMT);
10805 assign_stmt = gimple_build_assign (vback, t);
10806 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
10807
10808 t = build2 (fd->loop.cond_code, boolean_type_node,
10809 DECL_P (vback) && TREE_ADDRESSABLE (vback)
10810 ? t : vback, e);
10811 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
10812 }
10813
10814 /* Remove the GIMPLE_OMP_CONTINUE statement. */
10815 gsi_remove (&gsi, true);
10816
10817 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
10818 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
10819 }
10820
10821 /* Remove the GIMPLE_OMP_FOR statement. */
10822 gsi = gsi_for_stmt (fd->for_stmt);
10823 gsi_remove (&gsi, true);
10824
10825 /* Remove the GIMPLE_OMP_RETURN statement. */
10826 gsi = gsi_last_bb (exit_bb);
10827 gsi_remove (&gsi, true);
10828
10829 FALLTHRU_EDGE (entry_bb)->probability = REG_BR_PROB_BASE;
10830 if (!broken_loop)
10831 remove_edge (BRANCH_EDGE (entry_bb));
10832 else
10833 {
10834 remove_edge_and_dominated_blocks (BRANCH_EDGE (entry_bb));
10835 region->outer->cont = NULL;
10836 }
10837
10838 /* Connect all the blocks. */
10839 if (!broken_loop)
10840 {
10841 ep = find_edge (cont_bb, body_bb);
10842 if (gimple_omp_for_combined_p (fd->for_stmt))
10843 {
10844 remove_edge (ep);
10845 ep = NULL;
3d483a94 10846 }
43895be5 10847 else if (fd->collapse > 1)
3d483a94 10848 {
43895be5 10849 remove_edge (ep);
10850 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
3d483a94 10851 }
43895be5 10852 else
10853 ep->flags = EDGE_TRUE_VALUE;
10854 find_edge (cont_bb, fin_bb)->flags
10855 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
3d483a94 10856 }
3d483a94 10857
43895be5 10858 set_immediate_dominator (CDI_DOMINATORS, body_bb,
10859 recompute_dominator (CDI_DOMINATORS, body_bb));
10860 if (!broken_loop)
10861 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
10862 recompute_dominator (CDI_DOMINATORS, fin_bb));
10863
10864 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
10865 {
10866 struct loop *loop = alloc_loop ();
10867 loop->header = body_bb;
10868 if (collapse_bb == NULL)
10869 loop->latch = cont_bb;
10870 add_loop (loop, body_bb->loop_father);
10871 }
10872}
1e8e9920 10873
a8e785ba 10874/* A subroutine of expand_omp_for. Generate code for an OpenACC
10875 partitioned loop. The lowering here is abstracted, in that the
10876 loop parameters are passed through internal functions, which are
10877 further lowered by oacc_device_lower, once we get to the target
10878 compiler. The loop is of the form:
10879
10880 for (V = B; V LTGT E; V += S) {BODY}
10881
10882 where LTGT is < or >. We may have a specified chunking size, CHUNKING
10883 (constant 0 for no chunking) and we will have a GWV partitioning
10884 mask, specifying dimensions over which the loop is to be
10885 partitioned (see note below). We generate code that looks like:
10886
10887 <entry_bb> [incoming FALL->body, BRANCH->exit]
10888 typedef signedintify (typeof (V)) T; // underlying signed integral type
10889 T range = E - B;
10890 T chunk_no = 0;
10891 T DIR = LTGT == '<' ? +1 : -1;
10892 T chunk_max = GOACC_LOOP_CHUNK (dir, range, S, CHUNK_SIZE, GWV);
10893 T step = GOACC_LOOP_STEP (dir, range, S, CHUNK_SIZE, GWV);
10894
10895 <head_bb> [created by splitting end of entry_bb]
10896 T offset = GOACC_LOOP_OFFSET (dir, range, S, CHUNK_SIZE, GWV, chunk_no);
10897 T bound = GOACC_LOOP_BOUND (dir, range, S, CHUNK_SIZE, GWV, offset);
10898 if (!(offset LTGT bound)) goto bottom_bb;
10899
10900 <body_bb> [incoming]
10901 V = B + offset;
10902 {BODY}
10903
10904 <cont_bb> [incoming, may == body_bb FALL->exit_bb, BRANCH->body_bb]
10905 offset += step;
10906 if (offset LTGT bound) goto body_bb; [*]
10907
10908 <bottom_bb> [created by splitting start of exit_bb] insert BRANCH->head_bb
10909 chunk_no++;
10910 if (chunk < chunk_max) goto head_bb;
10911
10912 <exit_bb> [incoming]
10913 V = B + ((range -/+ 1) / S +/- 1) * S [*]
10914
10915 [*] Needed if V live at end of loop
10916
10917 Note: CHUNKING & GWV mask are specified explicitly here. This is a
10918 transition, and will be specified by a more general mechanism shortly.
10919 */
10920
10921static void
10922expand_oacc_for (struct omp_region *region, struct omp_for_data *fd)
10923{
10924 tree v = fd->loop.v;
10925 enum tree_code cond_code = fd->loop.cond_code;
10926 enum tree_code plus_code = PLUS_EXPR;
10927
10928 tree chunk_size = integer_minus_one_node;
10929 tree gwv = integer_zero_node;
10930 tree iter_type = TREE_TYPE (v);
10931 tree diff_type = iter_type;
10932 tree plus_type = iter_type;
10933 struct oacc_collapse *counts = NULL;
10934
10935 gcc_checking_assert (gimple_omp_for_kind (fd->for_stmt)
10936 == GF_OMP_FOR_KIND_OACC_LOOP);
10937 gcc_assert (!gimple_omp_for_combined_into_p (fd->for_stmt));
10938 gcc_assert (cond_code == LT_EXPR || cond_code == GT_EXPR);
10939
10940 if (POINTER_TYPE_P (iter_type))
10941 {
10942 plus_code = POINTER_PLUS_EXPR;
10943 plus_type = sizetype;
10944 }
10945 if (POINTER_TYPE_P (diff_type) || TYPE_UNSIGNED (diff_type))
10946 diff_type = signed_type_for (diff_type);
10947
10948 basic_block entry_bb = region->entry; /* BB ending in OMP_FOR */
10949 basic_block exit_bb = region->exit; /* BB ending in OMP_RETURN */
10950 basic_block cont_bb = region->cont; /* BB ending in OMP_CONTINUE */
10951 basic_block bottom_bb = NULL;
10952
10953 /* entry_bb has two sucessors; the branch edge is to the exit
10954 block, fallthrough edge to body. */
10955 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2
10956 && BRANCH_EDGE (entry_bb)->dest == exit_bb);
10957
10958 /* If cont_bb non-NULL, it has 2 successors. The branch successor is
10959 body_bb, or to a block whose only successor is the body_bb. Its
10960 fallthrough successor is the final block (same as the branch
10961 successor of the entry_bb). */
10962 if (cont_bb)
10963 {
10964 basic_block body_bb = FALLTHRU_EDGE (entry_bb)->dest;
10965 basic_block bed = BRANCH_EDGE (cont_bb)->dest;
10966
10967 gcc_assert (FALLTHRU_EDGE (cont_bb)->dest == exit_bb);
10968 gcc_assert (bed == body_bb || single_succ_edge (bed)->dest == body_bb);
10969 }
10970 else
10971 gcc_assert (!gimple_in_ssa_p (cfun));
10972
10973 /* The exit block only has entry_bb and cont_bb as predecessors. */
10974 gcc_assert (EDGE_COUNT (exit_bb->preds) == 1 + (cont_bb != NULL));
10975
10976 tree chunk_no;
10977 tree chunk_max = NULL_TREE;
10978 tree bound, offset;
10979 tree step = create_tmp_var (diff_type, ".step");
10980 bool up = cond_code == LT_EXPR;
10981 tree dir = build_int_cst (diff_type, up ? +1 : -1);
10982 bool chunking = !gimple_in_ssa_p (cfun);;
10983 bool negating;
10984
10985 /* SSA instances. */
10986 tree offset_incr = NULL_TREE;
10987 tree offset_init = NULL_TREE;
10988
10989 gimple_stmt_iterator gsi;
10990 gassign *ass;
10991 gcall *call;
10992 gimple *stmt;
10993 tree expr;
10994 location_t loc;
10995 edge split, be, fte;
10996
10997 /* Split the end of entry_bb to create head_bb. */
10998 split = split_block (entry_bb, last_stmt (entry_bb));
10999 basic_block head_bb = split->dest;
11000 entry_bb = split->src;
11001
11002 /* Chunk setup goes at end of entry_bb, replacing the omp_for. */
11003 gsi = gsi_last_bb (entry_bb);
11004 gomp_for *for_stmt = as_a <gomp_for *> (gsi_stmt (gsi));
11005 loc = gimple_location (for_stmt);
11006
11007 if (gimple_in_ssa_p (cfun))
11008 {
11009 offset_init = gimple_omp_for_index (for_stmt, 0);
11010 gcc_assert (integer_zerop (fd->loop.n1));
11011 /* The SSA parallelizer does gang parallelism. */
11012 gwv = build_int_cst (integer_type_node, GOMP_DIM_MASK (GOMP_DIM_GANG));
11013 }
11014
11015 if (fd->collapse > 1)
11016 {
11017 counts = XALLOCAVEC (struct oacc_collapse, fd->collapse);
11018 tree total = expand_oacc_collapse_init (fd, &gsi, counts,
11019 TREE_TYPE (fd->loop.n2));
11020
11021 if (SSA_VAR_P (fd->loop.n2))
11022 {
11023 total = force_gimple_operand_gsi (&gsi, total, false, NULL_TREE,
11024 true, GSI_SAME_STMT);
11025 ass = gimple_build_assign (fd->loop.n2, total);
11026 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11027 }
11028
11029 }
11030
11031 tree b = fd->loop.n1;
11032 tree e = fd->loop.n2;
11033 tree s = fd->loop.step;
11034
11035 b = force_gimple_operand_gsi (&gsi, b, true, NULL_TREE, true, GSI_SAME_STMT);
11036 e = force_gimple_operand_gsi (&gsi, e, true, NULL_TREE, true, GSI_SAME_STMT);
11037
11038 /* Convert the step, avoiding possible unsigned->signed overflow. */
11039 negating = !up && TYPE_UNSIGNED (TREE_TYPE (s));
11040 if (negating)
11041 s = fold_build1 (NEGATE_EXPR, TREE_TYPE (s), s);
11042 s = fold_convert (diff_type, s);
11043 if (negating)
11044 s = fold_build1 (NEGATE_EXPR, diff_type, s);
11045 s = force_gimple_operand_gsi (&gsi, s, true, NULL_TREE, true, GSI_SAME_STMT);
11046
11047 if (!chunking)
11048 chunk_size = integer_zero_node;
11049 expr = fold_convert (diff_type, chunk_size);
11050 chunk_size = force_gimple_operand_gsi (&gsi, expr, true,
11051 NULL_TREE, true, GSI_SAME_STMT);
11052 /* Determine the range, avoiding possible unsigned->signed overflow. */
11053 negating = !up && TYPE_UNSIGNED (iter_type);
11054 expr = fold_build2 (MINUS_EXPR, plus_type,
11055 fold_convert (plus_type, negating ? b : e),
11056 fold_convert (plus_type, negating ? e : b));
11057 expr = fold_convert (diff_type, expr);
11058 if (negating)
11059 expr = fold_build1 (NEGATE_EXPR, diff_type, expr);
11060 tree range = force_gimple_operand_gsi (&gsi, expr, true,
11061 NULL_TREE, true, GSI_SAME_STMT);
11062
11063 chunk_no = build_int_cst (diff_type, 0);
11064 if (chunking)
11065 {
11066 gcc_assert (!gimple_in_ssa_p (cfun));
11067
11068 expr = chunk_no;
11069 chunk_max = create_tmp_var (diff_type, ".chunk_max");
11070 chunk_no = create_tmp_var (diff_type, ".chunk_no");
11071
11072 ass = gimple_build_assign (chunk_no, expr);
11073 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11074
11075 call = gimple_build_call_internal (IFN_GOACC_LOOP, 6,
11076 build_int_cst (integer_type_node,
11077 IFN_GOACC_LOOP_CHUNKS),
11078 dir, range, s, chunk_size, gwv);
11079 gimple_call_set_lhs (call, chunk_max);
11080 gimple_set_location (call, loc);
11081 gsi_insert_before (&gsi, call, GSI_SAME_STMT);
11082 }
11083 else
11084 chunk_size = chunk_no;
11085
11086 call = gimple_build_call_internal (IFN_GOACC_LOOP, 6,
11087 build_int_cst (integer_type_node,
11088 IFN_GOACC_LOOP_STEP),
11089 dir, range, s, chunk_size, gwv);
11090 gimple_call_set_lhs (call, step);
11091 gimple_set_location (call, loc);
11092 gsi_insert_before (&gsi, call, GSI_SAME_STMT);
11093
11094 /* Remove the GIMPLE_OMP_FOR. */
11095 gsi_remove (&gsi, true);
11096
11097 /* Fixup edges from head_bb */
11098 be = BRANCH_EDGE (head_bb);
11099 fte = FALLTHRU_EDGE (head_bb);
11100 be->flags |= EDGE_FALSE_VALUE;
11101 fte->flags ^= EDGE_FALLTHRU | EDGE_TRUE_VALUE;
11102
11103 basic_block body_bb = fte->dest;
11104
11105 if (gimple_in_ssa_p (cfun))
11106 {
11107 gsi = gsi_last_bb (cont_bb);
11108 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
11109
11110 offset = gimple_omp_continue_control_use (cont_stmt);
11111 offset_incr = gimple_omp_continue_control_def (cont_stmt);
11112 }
11113 else
11114 {
11115 offset = create_tmp_var (diff_type, ".offset");
11116 offset_init = offset_incr = offset;
11117 }
11118 bound = create_tmp_var (TREE_TYPE (offset), ".bound");
11119
11120 /* Loop offset & bound go into head_bb. */
11121 gsi = gsi_start_bb (head_bb);
11122
11123 call = gimple_build_call_internal (IFN_GOACC_LOOP, 7,
11124 build_int_cst (integer_type_node,
11125 IFN_GOACC_LOOP_OFFSET),
11126 dir, range, s,
11127 chunk_size, gwv, chunk_no);
11128 gimple_call_set_lhs (call, offset_init);
11129 gimple_set_location (call, loc);
11130 gsi_insert_after (&gsi, call, GSI_CONTINUE_LINKING);
11131
11132 call = gimple_build_call_internal (IFN_GOACC_LOOP, 7,
11133 build_int_cst (integer_type_node,
11134 IFN_GOACC_LOOP_BOUND),
11135 dir, range, s,
11136 chunk_size, gwv, offset_init);
11137 gimple_call_set_lhs (call, bound);
11138 gimple_set_location (call, loc);
11139 gsi_insert_after (&gsi, call, GSI_CONTINUE_LINKING);
11140
11141 expr = build2 (cond_code, boolean_type_node, offset_init, bound);
11142 gsi_insert_after (&gsi, gimple_build_cond_empty (expr),
11143 GSI_CONTINUE_LINKING);
11144
11145 /* V assignment goes into body_bb. */
11146 if (!gimple_in_ssa_p (cfun))
11147 {
11148 gsi = gsi_start_bb (body_bb);
11149
11150 expr = build2 (plus_code, iter_type, b,
11151 fold_convert (plus_type, offset));
11152 expr = force_gimple_operand_gsi (&gsi, expr, false, NULL_TREE,
11153 true, GSI_SAME_STMT);
11154 ass = gimple_build_assign (v, expr);
11155 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11156 if (fd->collapse > 1)
11157 expand_oacc_collapse_vars (fd, &gsi, counts, v);
11158 }
11159
11160 /* Loop increment goes into cont_bb. If this is not a loop, we
11161 will have spawned threads as if it was, and each one will
11162 execute one iteration. The specification is not explicit about
11163 whether such constructs are ill-formed or not, and they can
11164 occur, especially when noreturn routines are involved. */
11165 if (cont_bb)
11166 {
11167 gsi = gsi_last_bb (cont_bb);
11168 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
11169 loc = gimple_location (cont_stmt);
11170
11171 /* Increment offset. */
11172 if (gimple_in_ssa_p (cfun))
11173 expr= build2 (plus_code, iter_type, offset,
11174 fold_convert (plus_type, step));
11175 else
11176 expr = build2 (PLUS_EXPR, diff_type, offset, step);
11177 expr = force_gimple_operand_gsi (&gsi, expr, false, NULL_TREE,
11178 true, GSI_SAME_STMT);
11179 ass = gimple_build_assign (offset_incr, expr);
11180 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11181 expr = build2 (cond_code, boolean_type_node, offset_incr, bound);
11182 gsi_insert_before (&gsi, gimple_build_cond_empty (expr), GSI_SAME_STMT);
11183
11184 /* Remove the GIMPLE_OMP_CONTINUE. */
11185 gsi_remove (&gsi, true);
11186
11187 /* Fixup edges from cont_bb */
11188 be = BRANCH_EDGE (cont_bb);
11189 fte = FALLTHRU_EDGE (cont_bb);
11190 be->flags |= EDGE_TRUE_VALUE;
11191 fte->flags ^= EDGE_FALLTHRU | EDGE_FALSE_VALUE;
11192
11193 if (chunking)
11194 {
11195 /* Split the beginning of exit_bb to make bottom_bb. We
11196 need to insert a nop at the start, because splitting is
11197 after a stmt, not before. */
11198 gsi = gsi_start_bb (exit_bb);
11199 stmt = gimple_build_nop ();
11200 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
11201 split = split_block (exit_bb, stmt);
11202 bottom_bb = split->src;
11203 exit_bb = split->dest;
11204 gsi = gsi_last_bb (bottom_bb);
11205
11206 /* Chunk increment and test goes into bottom_bb. */
11207 expr = build2 (PLUS_EXPR, diff_type, chunk_no,
11208 build_int_cst (diff_type, 1));
11209 ass = gimple_build_assign (chunk_no, expr);
11210 gsi_insert_after (&gsi, ass, GSI_CONTINUE_LINKING);
11211
11212 /* Chunk test at end of bottom_bb. */
11213 expr = build2 (LT_EXPR, boolean_type_node, chunk_no, chunk_max);
11214 gsi_insert_after (&gsi, gimple_build_cond_empty (expr),
11215 GSI_CONTINUE_LINKING);
11216
11217 /* Fixup edges from bottom_bb. */
11218 split->flags ^= EDGE_FALLTHRU | EDGE_FALSE_VALUE;
11219 make_edge (bottom_bb, head_bb, EDGE_TRUE_VALUE);
11220 }
11221 }
11222
11223 gsi = gsi_last_bb (exit_bb);
11224 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
11225 loc = gimple_location (gsi_stmt (gsi));
11226
11227 if (!gimple_in_ssa_p (cfun))
11228 {
11229 /* Insert the final value of V, in case it is live. This is the
11230 value for the only thread that survives past the join. */
11231 expr = fold_build2 (MINUS_EXPR, diff_type, range, dir);
11232 expr = fold_build2 (PLUS_EXPR, diff_type, expr, s);
11233 expr = fold_build2 (TRUNC_DIV_EXPR, diff_type, expr, s);
11234 expr = fold_build2 (MULT_EXPR, diff_type, expr, s);
11235 expr = build2 (plus_code, iter_type, b, fold_convert (plus_type, expr));
11236 expr = force_gimple_operand_gsi (&gsi, expr, false, NULL_TREE,
11237 true, GSI_SAME_STMT);
11238 ass = gimple_build_assign (v, expr);
11239 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11240 }
11241
11242 /* Remove the OMP_RETURN. */
11243 gsi_remove (&gsi, true);
11244
11245 if (cont_bb)
11246 {
11247 /* We now have one or two nested loops. Update the loop
11248 structures. */
11249 struct loop *parent = entry_bb->loop_father;
11250 struct loop *body = body_bb->loop_father;
11251
11252 if (chunking)
11253 {
11254 struct loop *chunk_loop = alloc_loop ();
11255 chunk_loop->header = head_bb;
11256 chunk_loop->latch = bottom_bb;
11257 add_loop (chunk_loop, parent);
11258 parent = chunk_loop;
11259 }
11260 else if (parent != body)
11261 {
11262 gcc_assert (body->header == body_bb);
11263 gcc_assert (body->latch == cont_bb
11264 || single_pred (body->latch) == cont_bb);
11265 parent = NULL;
11266 }
11267
11268 if (parent)
11269 {
11270 struct loop *body_loop = alloc_loop ();
11271 body_loop->header = body_bb;
11272 body_loop->latch = cont_bb;
11273 add_loop (body_loop, parent);
11274 }
11275 }
11276}
11277
ca4c3545 11278/* Expand the OMP loop defined by REGION. */
1e8e9920 11279
773c5ba7 11280static void
42acab1c 11281expand_omp_for (struct omp_region *region, gimple *inner_stmt)
773c5ba7 11282{
11283 struct omp_for_data fd;
fd6481cf 11284 struct omp_for_data_loop *loops;
1e8e9920 11285
fd6481cf 11286 loops
11287 = (struct omp_for_data_loop *)
75a70cf9 11288 alloca (gimple_omp_for_collapse (last_stmt (region->entry))
fd6481cf 11289 * sizeof (struct omp_for_data_loop));
1a91d914 11290 extract_omp_for_data (as_a <gomp_for *> (last_stmt (region->entry)),
11291 &fd, loops);
f77459c5 11292 region->sched_kind = fd.sched_kind;
9561765e 11293 region->sched_modifiers = fd.sched_modifiers;
1e8e9920 11294
b3a3ddec 11295 gcc_assert (EDGE_COUNT (region->entry->succs) == 2);
11296 BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
11297 FALLTHRU_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
11298 if (region->cont)
11299 {
11300 gcc_assert (EDGE_COUNT (region->cont->succs) == 2);
11301 BRANCH_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
11302 FALLTHRU_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
11303 }
04c2922b 11304 else
75de4aa2 11305 /* If there isn't a continue then this is a degerate case where
04c2922b 11306 the introduction of abnormal edges during lowering will prevent
11307 original loops from being detected. Fix that up. */
11308 loops_state_set (LOOPS_NEED_FIXUP);
b3a3ddec 11309
10c55644 11310 if (gimple_omp_for_kind (fd.for_stmt) & GF_OMP_FOR_SIMD)
3d483a94 11311 expand_omp_simd (region, &fd);
40750995 11312 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
11313 expand_cilk_for (region, &fd);
a8e785ba 11314 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
11315 {
11316 gcc_assert (!inner_stmt);
11317 expand_oacc_for (region, &fd);
11318 }
43895be5 11319 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_TASKLOOP)
11320 {
11321 if (gimple_omp_for_combined_into_p (fd.for_stmt))
11322 expand_omp_taskloop_for_inner (region, &fd, inner_stmt);
11323 else
11324 expand_omp_taskloop_for_outer (region, &fd, inner_stmt);
11325 }
3d483a94 11326 else if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
bc7bff74 11327 && !fd.have_ordered)
1e8e9920 11328 {
11329 if (fd.chunk_size == NULL)
bc7bff74 11330 expand_omp_for_static_nochunk (region, &fd, inner_stmt);
1e8e9920 11331 else
bc7bff74 11332 expand_omp_for_static_chunk (region, &fd, inner_stmt);
1e8e9920 11333 }
11334 else
11335 {
fd6481cf 11336 int fn_index, start_ix, next_ix;
11337
3d483a94 11338 gcc_assert (gimple_omp_for_kind (fd.for_stmt)
11339 == GF_OMP_FOR_KIND_FOR);
0416ca72 11340 if (fd.chunk_size == NULL
11341 && fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
11342 fd.chunk_size = integer_zero_node;
fd6481cf 11343 gcc_assert (fd.sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
9561765e 11344 switch (fd.sched_kind)
11345 {
11346 case OMP_CLAUSE_SCHEDULE_RUNTIME:
11347 fn_index = 3;
11348 break;
11349 case OMP_CLAUSE_SCHEDULE_DYNAMIC:
11350 case OMP_CLAUSE_SCHEDULE_GUIDED:
11351 if ((fd.sched_modifiers & OMP_CLAUSE_SCHEDULE_NONMONOTONIC)
11352 && !fd.ordered
11353 && !fd.have_ordered)
11354 {
11355 fn_index = 3 + fd.sched_kind;
11356 break;
11357 }
11358 /* FALLTHRU */
11359 default:
11360 fn_index = fd.sched_kind;
11361 break;
11362 }
43895be5 11363 if (!fd.ordered)
9561765e 11364 fn_index += fd.have_ordered * 6;
43895be5 11365 if (fd.ordered)
11366 start_ix = ((int)BUILT_IN_GOMP_LOOP_DOACROSS_STATIC_START) + fn_index;
11367 else
11368 start_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_START) + fn_index;
b9a16870 11369 next_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT) + fn_index;
fd6481cf 11370 if (fd.iter_type == long_long_unsigned_type_node)
11371 {
b9a16870 11372 start_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
11373 - (int)BUILT_IN_GOMP_LOOP_STATIC_START);
11374 next_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
11375 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT);
fd6481cf 11376 }
b9c74b4d 11377 expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
bc7bff74 11378 (enum built_in_function) next_ix, inner_stmt);
1e8e9920 11379 }
28c92cbb 11380
083152fb 11381 if (gimple_in_ssa_p (cfun))
11382 update_ssa (TODO_update_ssa_only_virtuals);
1e8e9920 11383}
11384
1e8e9920 11385
11386/* Expand code for an OpenMP sections directive. In pseudo code, we generate
11387
1e8e9920 11388 v = GOMP_sections_start (n);
11389 L0:
11390 switch (v)
11391 {
11392 case 0:
11393 goto L2;
11394 case 1:
11395 section 1;
11396 goto L1;
11397 case 2:
11398 ...
11399 case n:
11400 ...
1e8e9920 11401 default:
11402 abort ();
11403 }
11404 L1:
11405 v = GOMP_sections_next ();
11406 goto L0;
11407 L2:
11408 reduction;
11409
773c5ba7 11410 If this is a combined parallel sections, replace the call to
79acaae1 11411 GOMP_sections_start with call to GOMP_sections_next. */
1e8e9920 11412
11413static void
773c5ba7 11414expand_omp_sections (struct omp_region *region)
1e8e9920 11415{
f018d957 11416 tree t, u, vin = NULL, vmain, vnext, l2;
75a70cf9 11417 unsigned len;
ac6e3339 11418 basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
75a70cf9 11419 gimple_stmt_iterator si, switch_si;
1a91d914 11420 gomp_sections *sections_stmt;
42acab1c 11421 gimple *stmt;
1a91d914 11422 gomp_continue *cont;
9884aaf8 11423 edge_iterator ei;
11424 edge e;
61e47ac8 11425 struct omp_region *inner;
75a70cf9 11426 unsigned i, casei;
ac6e3339 11427 bool exit_reachable = region->cont != NULL;
1e8e9920 11428
d244d9de 11429 gcc_assert (region->exit != NULL);
61e47ac8 11430 entry_bb = region->entry;
ac6e3339 11431 l0_bb = single_succ (entry_bb);
61e47ac8 11432 l1_bb = region->cont;
ac6e3339 11433 l2_bb = region->exit;
d244d9de 11434 if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
11435 l2 = gimple_block_label (l2_bb);
11436 else
03ed154b 11437 {
d244d9de 11438 /* This can happen if there are reductions. */
11439 len = EDGE_COUNT (l0_bb->succs);
11440 gcc_assert (len > 0);
11441 e = EDGE_SUCC (l0_bb, len - 1);
11442 si = gsi_last_bb (e->dest);
11443 l2 = NULL_TREE;
11444 if (gsi_end_p (si)
11445 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
11446 l2 = gimple_block_label (e->dest);
9884aaf8 11447 else
d244d9de 11448 FOR_EACH_EDGE (e, ei, l0_bb->succs)
11449 {
11450 si = gsi_last_bb (e->dest);
11451 if (gsi_end_p (si)
11452 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
9884aaf8 11453 {
d244d9de 11454 l2 = gimple_block_label (e->dest);
11455 break;
9884aaf8 11456 }
d244d9de 11457 }
03ed154b 11458 }
d244d9de 11459 if (exit_reachable)
11460 default_bb = create_empty_bb (l1_bb->prev_bb);
03ed154b 11461 else
d244d9de 11462 default_bb = create_empty_bb (l0_bb);
773c5ba7 11463
11464 /* We will build a switch() with enough cases for all the
75a70cf9 11465 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
773c5ba7 11466 and a default case to abort if something goes wrong. */
ac6e3339 11467 len = EDGE_COUNT (l0_bb->succs);
75a70cf9 11468
f1f41a6c 11469 /* Use vec::quick_push on label_vec throughout, since we know the size
75a70cf9 11470 in advance. */
c2078b80 11471 auto_vec<tree> label_vec (len);
1e8e9920 11472
61e47ac8 11473 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
75a70cf9 11474 GIMPLE_OMP_SECTIONS statement. */
11475 si = gsi_last_bb (entry_bb);
1a91d914 11476 sections_stmt = as_a <gomp_sections *> (gsi_stmt (si));
75a70cf9 11477 gcc_assert (gimple_code (sections_stmt) == GIMPLE_OMP_SECTIONS);
11478 vin = gimple_omp_sections_control (sections_stmt);
773c5ba7 11479 if (!is_combined_parallel (region))
1e8e9920 11480 {
773c5ba7 11481 /* If we are not inside a combined parallel+sections region,
11482 call GOMP_sections_start. */
39cb6d68 11483 t = build_int_cst (unsigned_type_node, len - 1);
b9a16870 11484 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START);
75a70cf9 11485 stmt = gimple_build_call (u, 1, t);
1e8e9920 11486 }
79acaae1 11487 else
11488 {
11489 /* Otherwise, call GOMP_sections_next. */
b9a16870 11490 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
75a70cf9 11491 stmt = gimple_build_call (u, 0);
79acaae1 11492 }
75a70cf9 11493 gimple_call_set_lhs (stmt, vin);
11494 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
11495 gsi_remove (&si, true);
11496
11497 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
11498 L0_BB. */
11499 switch_si = gsi_last_bb (l0_bb);
11500 gcc_assert (gimple_code (gsi_stmt (switch_si)) == GIMPLE_OMP_SECTIONS_SWITCH);
79acaae1 11501 if (exit_reachable)
11502 {
1a91d914 11503 cont = as_a <gomp_continue *> (last_stmt (l1_bb));
75a70cf9 11504 gcc_assert (gimple_code (cont) == GIMPLE_OMP_CONTINUE);
11505 vmain = gimple_omp_continue_control_use (cont);
11506 vnext = gimple_omp_continue_control_def (cont);
79acaae1 11507 }
11508 else
11509 {
11510 vmain = vin;
11511 vnext = NULL_TREE;
11512 }
1e8e9920 11513
d244d9de 11514 t = build_case_label (build_int_cst (unsigned_type_node, 0), NULL, l2);
f1f41a6c 11515 label_vec.quick_push (t);
d244d9de 11516 i = 1;
03ed154b 11517
75a70cf9 11518 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
ac6e3339 11519 for (inner = region->inner, casei = 1;
11520 inner;
11521 inner = inner->next, i++, casei++)
1e8e9920 11522 {
773c5ba7 11523 basic_block s_entry_bb, s_exit_bb;
11524
9884aaf8 11525 /* Skip optional reduction region. */
75a70cf9 11526 if (inner->type == GIMPLE_OMP_ATOMIC_LOAD)
9884aaf8 11527 {
11528 --i;
11529 --casei;
11530 continue;
11531 }
11532
61e47ac8 11533 s_entry_bb = inner->entry;
11534 s_exit_bb = inner->exit;
1e8e9920 11535
75a70cf9 11536 t = gimple_block_label (s_entry_bb);
ac6e3339 11537 u = build_int_cst (unsigned_type_node, casei);
b6e3dd65 11538 u = build_case_label (u, NULL, t);
f1f41a6c 11539 label_vec.quick_push (u);
61e47ac8 11540
75a70cf9 11541 si = gsi_last_bb (s_entry_bb);
11542 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SECTION);
11543 gcc_assert (i < len || gimple_omp_section_last_p (gsi_stmt (si)));
11544 gsi_remove (&si, true);
61e47ac8 11545 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
03ed154b 11546
11547 if (s_exit_bb == NULL)
11548 continue;
11549
75a70cf9 11550 si = gsi_last_bb (s_exit_bb);
11551 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
11552 gsi_remove (&si, true);
03ed154b 11553
773c5ba7 11554 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
1e8e9920 11555 }
11556
773c5ba7 11557 /* Error handling code goes in DEFAULT_BB. */
75a70cf9 11558 t = gimple_block_label (default_bb);
b6e3dd65 11559 u = build_case_label (NULL, NULL, t);
61e47ac8 11560 make_edge (l0_bb, default_bb, 0);
b3083327 11561 add_bb_to_loop (default_bb, current_loops->tree_root);
1e8e9920 11562
49a70175 11563 stmt = gimple_build_switch (vmain, u, label_vec);
75a70cf9 11564 gsi_insert_after (&switch_si, stmt, GSI_SAME_STMT);
11565 gsi_remove (&switch_si, true);
75a70cf9 11566
11567 si = gsi_start_bb (default_bb);
b9a16870 11568 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
75a70cf9 11569 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
773c5ba7 11570
ac6e3339 11571 if (exit_reachable)
03ed154b 11572 {
b9a16870 11573 tree bfn_decl;
11574
ac6e3339 11575 /* Code to get the next section goes in L1_BB. */
75a70cf9 11576 si = gsi_last_bb (l1_bb);
11577 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
1e8e9920 11578
b9a16870 11579 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
11580 stmt = gimple_build_call (bfn_decl, 0);
75a70cf9 11581 gimple_call_set_lhs (stmt, vnext);
11582 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
11583 gsi_remove (&si, true);
773c5ba7 11584
ac6e3339 11585 single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
03ed154b 11586 }
773c5ba7 11587
d244d9de 11588 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
11589 si = gsi_last_bb (l2_bb);
11590 if (gimple_omp_return_nowait_p (gsi_stmt (si)))
11591 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
bc7bff74 11592 else if (gimple_omp_return_lhs (gsi_stmt (si)))
11593 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL);
d244d9de 11594 else
11595 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
11596 stmt = gimple_build_call (t, 0);
bc7bff74 11597 if (gimple_omp_return_lhs (gsi_stmt (si)))
11598 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (si)));
d244d9de 11599 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
11600 gsi_remove (&si, true);
11601
79acaae1 11602 set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
773c5ba7 11603}
1e8e9920 11604
1e8e9920 11605
61e47ac8 11606/* Expand code for an OpenMP single directive. We've already expanded
11607 much of the code, here we simply place the GOMP_barrier call. */
11608
11609static void
11610expand_omp_single (struct omp_region *region)
11611{
11612 basic_block entry_bb, exit_bb;
75a70cf9 11613 gimple_stmt_iterator si;
61e47ac8 11614
11615 entry_bb = region->entry;
11616 exit_bb = region->exit;
11617
75a70cf9 11618 si = gsi_last_bb (entry_bb);
75a70cf9 11619 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE);
11620 gsi_remove (&si, true);
61e47ac8 11621 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
11622
75a70cf9 11623 si = gsi_last_bb (exit_bb);
bc7bff74 11624 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
11625 {
11626 tree t = gimple_omp_return_lhs (gsi_stmt (si));
11627 gsi_insert_after (&si, build_omp_barrier (t), GSI_SAME_STMT);
11628 }
75a70cf9 11629 gsi_remove (&si, true);
61e47ac8 11630 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
11631}
11632
11633
11634/* Generic expansion for OpenMP synchronization directives: master,
11635 ordered and critical. All we need to do here is remove the entry
11636 and exit markers for REGION. */
773c5ba7 11637
11638static void
11639expand_omp_synch (struct omp_region *region)
11640{
11641 basic_block entry_bb, exit_bb;
75a70cf9 11642 gimple_stmt_iterator si;
773c5ba7 11643
61e47ac8 11644 entry_bb = region->entry;
11645 exit_bb = region->exit;
773c5ba7 11646
75a70cf9 11647 si = gsi_last_bb (entry_bb);
11648 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE
11649 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASTER
bc7bff74 11650 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TASKGROUP
75a70cf9 11651 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ORDERED
bc7bff74 11652 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CRITICAL
11653 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TEAMS);
75a70cf9 11654 gsi_remove (&si, true);
773c5ba7 11655 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
11656
03ed154b 11657 if (exit_bb)
11658 {
75a70cf9 11659 si = gsi_last_bb (exit_bb);
11660 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
11661 gsi_remove (&si, true);
03ed154b 11662 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
11663 }
773c5ba7 11664}
1e8e9920 11665
2169f33b 11666/* A subroutine of expand_omp_atomic. Attempt to implement the atomic
11667 operation as a normal volatile load. */
11668
11669static bool
3ec11c49 11670expand_omp_atomic_load (basic_block load_bb, tree addr,
11671 tree loaded_val, int index)
2169f33b 11672{
3ec11c49 11673 enum built_in_function tmpbase;
11674 gimple_stmt_iterator gsi;
11675 basic_block store_bb;
11676 location_t loc;
42acab1c 11677 gimple *stmt;
3ec11c49 11678 tree decl, call, type, itype;
11679
11680 gsi = gsi_last_bb (load_bb);
11681 stmt = gsi_stmt (gsi);
11682 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
11683 loc = gimple_location (stmt);
11684
11685 /* ??? If the target does not implement atomic_load_optab[mode], and mode
11686 is smaller than word size, then expand_atomic_load assumes that the load
11687 is atomic. We could avoid the builtin entirely in this case. */
11688
11689 tmpbase = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
11690 decl = builtin_decl_explicit (tmpbase);
11691 if (decl == NULL_TREE)
11692 return false;
11693
11694 type = TREE_TYPE (loaded_val);
11695 itype = TREE_TYPE (TREE_TYPE (decl));
11696
11697 call = build_call_expr_loc (loc, decl, 2, addr,
bc7bff74 11698 build_int_cst (NULL,
11699 gimple_omp_atomic_seq_cst_p (stmt)
11700 ? MEMMODEL_SEQ_CST
11701 : MEMMODEL_RELAXED));
3ec11c49 11702 if (!useless_type_conversion_p (type, itype))
11703 call = fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
11704 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
11705
11706 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
11707 gsi_remove (&gsi, true);
11708
11709 store_bb = single_succ (load_bb);
11710 gsi = gsi_last_bb (store_bb);
11711 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
11712 gsi_remove (&gsi, true);
11713
11714 if (gimple_in_ssa_p (cfun))
11715 update_ssa (TODO_update_ssa_no_phi);
11716
11717 return true;
2169f33b 11718}
11719
11720/* A subroutine of expand_omp_atomic. Attempt to implement the atomic
11721 operation as a normal volatile store. */
11722
11723static bool
3ec11c49 11724expand_omp_atomic_store (basic_block load_bb, tree addr,
11725 tree loaded_val, tree stored_val, int index)
2169f33b 11726{
3ec11c49 11727 enum built_in_function tmpbase;
11728 gimple_stmt_iterator gsi;
11729 basic_block store_bb = single_succ (load_bb);
11730 location_t loc;
42acab1c 11731 gimple *stmt;
3ec11c49 11732 tree decl, call, type, itype;
3754d046 11733 machine_mode imode;
3ec11c49 11734 bool exchange;
11735
11736 gsi = gsi_last_bb (load_bb);
11737 stmt = gsi_stmt (gsi);
11738 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
11739
11740 /* If the load value is needed, then this isn't a store but an exchange. */
11741 exchange = gimple_omp_atomic_need_value_p (stmt);
11742
11743 gsi = gsi_last_bb (store_bb);
11744 stmt = gsi_stmt (gsi);
11745 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE);
11746 loc = gimple_location (stmt);
11747
11748 /* ??? If the target does not implement atomic_store_optab[mode], and mode
11749 is smaller than word size, then expand_atomic_store assumes that the store
11750 is atomic. We could avoid the builtin entirely in this case. */
11751
11752 tmpbase = (exchange ? BUILT_IN_ATOMIC_EXCHANGE_N : BUILT_IN_ATOMIC_STORE_N);
11753 tmpbase = (enum built_in_function) ((int) tmpbase + index + 1);
11754 decl = builtin_decl_explicit (tmpbase);
11755 if (decl == NULL_TREE)
11756 return false;
11757
11758 type = TREE_TYPE (stored_val);
11759
11760 /* Dig out the type of the function's second argument. */
11761 itype = TREE_TYPE (decl);
11762 itype = TYPE_ARG_TYPES (itype);
11763 itype = TREE_CHAIN (itype);
11764 itype = TREE_VALUE (itype);
11765 imode = TYPE_MODE (itype);
11766
11767 if (exchange && !can_atomic_exchange_p (imode, true))
11768 return false;
11769
11770 if (!useless_type_conversion_p (itype, type))
11771 stored_val = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, stored_val);
11772 call = build_call_expr_loc (loc, decl, 3, addr, stored_val,
bc7bff74 11773 build_int_cst (NULL,
11774 gimple_omp_atomic_seq_cst_p (stmt)
11775 ? MEMMODEL_SEQ_CST
11776 : MEMMODEL_RELAXED));
3ec11c49 11777 if (exchange)
11778 {
11779 if (!useless_type_conversion_p (type, itype))
11780 call = build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
11781 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
11782 }
11783
11784 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
11785 gsi_remove (&gsi, true);
11786
11787 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
11788 gsi = gsi_last_bb (load_bb);
11789 gsi_remove (&gsi, true);
11790
11791 if (gimple_in_ssa_p (cfun))
11792 update_ssa (TODO_update_ssa_no_phi);
11793
11794 return true;
2169f33b 11795}
11796
cb7f680b 11797/* A subroutine of expand_omp_atomic. Attempt to implement the atomic
1cd6e20d 11798 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
cb7f680b 11799 size of the data type, and thus usable to find the index of the builtin
11800 decl. Returns false if the expression is not of the proper form. */
11801
11802static bool
11803expand_omp_atomic_fetch_op (basic_block load_bb,
11804 tree addr, tree loaded_val,
11805 tree stored_val, int index)
11806{
b9a16870 11807 enum built_in_function oldbase, newbase, tmpbase;
cb7f680b 11808 tree decl, itype, call;
2169f33b 11809 tree lhs, rhs;
cb7f680b 11810 basic_block store_bb = single_succ (load_bb);
75a70cf9 11811 gimple_stmt_iterator gsi;
42acab1c 11812 gimple *stmt;
389dd41b 11813 location_t loc;
1cd6e20d 11814 enum tree_code code;
2169f33b 11815 bool need_old, need_new;
3754d046 11816 machine_mode imode;
bc7bff74 11817 bool seq_cst;
cb7f680b 11818
11819 /* We expect to find the following sequences:
48e1416a 11820
cb7f680b 11821 load_bb:
75a70cf9 11822 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
cb7f680b 11823
11824 store_bb:
11825 val = tmp OP something; (or: something OP tmp)
48e1416a 11826 GIMPLE_OMP_STORE (val)
cb7f680b 11827
48e1416a 11828 ???FIXME: Allow a more flexible sequence.
cb7f680b 11829 Perhaps use data flow to pick the statements.
48e1416a 11830
cb7f680b 11831 */
11832
75a70cf9 11833 gsi = gsi_after_labels (store_bb);
11834 stmt = gsi_stmt (gsi);
389dd41b 11835 loc = gimple_location (stmt);
75a70cf9 11836 if (!is_gimple_assign (stmt))
cb7f680b 11837 return false;
75a70cf9 11838 gsi_next (&gsi);
11839 if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE)
cb7f680b 11840 return false;
2169f33b 11841 need_new = gimple_omp_atomic_need_value_p (gsi_stmt (gsi));
11842 need_old = gimple_omp_atomic_need_value_p (last_stmt (load_bb));
bc7bff74 11843 seq_cst = gimple_omp_atomic_seq_cst_p (last_stmt (load_bb));
2169f33b 11844 gcc_checking_assert (!need_old || !need_new);
cb7f680b 11845
75a70cf9 11846 if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
cb7f680b 11847 return false;
11848
cb7f680b 11849 /* Check for one of the supported fetch-op operations. */
1cd6e20d 11850 code = gimple_assign_rhs_code (stmt);
11851 switch (code)
cb7f680b 11852 {
11853 case PLUS_EXPR:
11854 case POINTER_PLUS_EXPR:
1cd6e20d 11855 oldbase = BUILT_IN_ATOMIC_FETCH_ADD_N;
11856 newbase = BUILT_IN_ATOMIC_ADD_FETCH_N;
cb7f680b 11857 break;
11858 case MINUS_EXPR:
1cd6e20d 11859 oldbase = BUILT_IN_ATOMIC_FETCH_SUB_N;
11860 newbase = BUILT_IN_ATOMIC_SUB_FETCH_N;
cb7f680b 11861 break;
11862 case BIT_AND_EXPR:
1cd6e20d 11863 oldbase = BUILT_IN_ATOMIC_FETCH_AND_N;
11864 newbase = BUILT_IN_ATOMIC_AND_FETCH_N;
cb7f680b 11865 break;
11866 case BIT_IOR_EXPR:
1cd6e20d 11867 oldbase = BUILT_IN_ATOMIC_FETCH_OR_N;
11868 newbase = BUILT_IN_ATOMIC_OR_FETCH_N;
cb7f680b 11869 break;
11870 case BIT_XOR_EXPR:
1cd6e20d 11871 oldbase = BUILT_IN_ATOMIC_FETCH_XOR_N;
11872 newbase = BUILT_IN_ATOMIC_XOR_FETCH_N;
cb7f680b 11873 break;
11874 default:
11875 return false;
11876 }
1cd6e20d 11877
cb7f680b 11878 /* Make sure the expression is of the proper form. */
75a70cf9 11879 if (operand_equal_p (gimple_assign_rhs1 (stmt), loaded_val, 0))
11880 rhs = gimple_assign_rhs2 (stmt);
11881 else if (commutative_tree_code (gimple_assign_rhs_code (stmt))
11882 && operand_equal_p (gimple_assign_rhs2 (stmt), loaded_val, 0))
11883 rhs = gimple_assign_rhs1 (stmt);
cb7f680b 11884 else
11885 return false;
11886
b9a16870 11887 tmpbase = ((enum built_in_function)
11888 ((need_new ? newbase : oldbase) + index + 1));
11889 decl = builtin_decl_explicit (tmpbase);
0f94f46b 11890 if (decl == NULL_TREE)
11891 return false;
cb7f680b 11892 itype = TREE_TYPE (TREE_TYPE (decl));
1cd6e20d 11893 imode = TYPE_MODE (itype);
cb7f680b 11894
1cd6e20d 11895 /* We could test all of the various optabs involved, but the fact of the
11896 matter is that (with the exception of i486 vs i586 and xadd) all targets
11897 that support any atomic operaton optab also implements compare-and-swap.
11898 Let optabs.c take care of expanding any compare-and-swap loop. */
29139cdc 11899 if (!can_compare_and_swap_p (imode, true))
cb7f680b 11900 return false;
11901
75a70cf9 11902 gsi = gsi_last_bb (load_bb);
11903 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
1cd6e20d 11904
11905 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
11906 It only requires that the operation happen atomically. Thus we can
11907 use the RELAXED memory model. */
11908 call = build_call_expr_loc (loc, decl, 3, addr,
11909 fold_convert_loc (loc, itype, rhs),
bc7bff74 11910 build_int_cst (NULL,
11911 seq_cst ? MEMMODEL_SEQ_CST
11912 : MEMMODEL_RELAXED));
1cd6e20d 11913
2169f33b 11914 if (need_old || need_new)
11915 {
11916 lhs = need_old ? loaded_val : stored_val;
11917 call = fold_convert_loc (loc, TREE_TYPE (lhs), call);
11918 call = build2_loc (loc, MODIFY_EXPR, void_type_node, lhs, call);
11919 }
11920 else
11921 call = fold_convert_loc (loc, void_type_node, call);
75a70cf9 11922 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
11923 gsi_remove (&gsi, true);
cb7f680b 11924
75a70cf9 11925 gsi = gsi_last_bb (store_bb);
11926 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
11927 gsi_remove (&gsi, true);
11928 gsi = gsi_last_bb (store_bb);
11929 gsi_remove (&gsi, true);
cb7f680b 11930
11931 if (gimple_in_ssa_p (cfun))
11932 update_ssa (TODO_update_ssa_no_phi);
11933
11934 return true;
11935}
11936
11937/* A subroutine of expand_omp_atomic. Implement the atomic operation as:
11938
11939 oldval = *addr;
11940 repeat:
11941 newval = rhs; // with oldval replacing *addr in rhs
11942 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
11943 if (oldval != newval)
11944 goto repeat;
11945
11946 INDEX is log2 of the size of the data type, and thus usable to find the
11947 index of the builtin decl. */
11948
11949static bool
11950expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
11951 tree addr, tree loaded_val, tree stored_val,
11952 int index)
11953{
790368c5 11954 tree loadedi, storedi, initial, new_storedi, old_vali;
cb7f680b 11955 tree type, itype, cmpxchg, iaddr;
75a70cf9 11956 gimple_stmt_iterator si;
cb7f680b 11957 basic_block loop_header = single_succ (load_bb);
42acab1c 11958 gimple *phi, *stmt;
cb7f680b 11959 edge e;
b9a16870 11960 enum built_in_function fncode;
cb7f680b 11961
1cd6e20d 11962 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
11963 order to use the RELAXED memory model effectively. */
b9a16870 11964 fncode = (enum built_in_function)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
11965 + index + 1);
11966 cmpxchg = builtin_decl_explicit (fncode);
0f94f46b 11967 if (cmpxchg == NULL_TREE)
11968 return false;
cb7f680b 11969 type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
11970 itype = TREE_TYPE (TREE_TYPE (cmpxchg));
11971
29139cdc 11972 if (!can_compare_and_swap_p (TYPE_MODE (itype), true))
cb7f680b 11973 return false;
11974
75a70cf9 11975 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
11976 si = gsi_last_bb (load_bb);
11977 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
11978
790368c5 11979 /* For floating-point values, we'll need to view-convert them to integers
11980 so that we can perform the atomic compare and swap. Simplify the
11981 following code by always setting up the "i"ntegral variables. */
11982 if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
11983 {
75a70cf9 11984 tree iaddr_val;
11985
072f7ab1 11986 iaddr = create_tmp_reg (build_pointer_type_for_mode (itype, ptr_mode,
f9e245b2 11987 true));
75a70cf9 11988 iaddr_val
11989 = force_gimple_operand_gsi (&si,
11990 fold_convert (TREE_TYPE (iaddr), addr),
11991 false, NULL_TREE, true, GSI_SAME_STMT);
11992 stmt = gimple_build_assign (iaddr, iaddr_val);
11993 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
f9e245b2 11994 loadedi = create_tmp_var (itype);
790368c5 11995 if (gimple_in_ssa_p (cfun))
f9e245b2 11996 loadedi = make_ssa_name (loadedi);
790368c5 11997 }
11998 else
11999 {
12000 iaddr = addr;
12001 loadedi = loaded_val;
12002 }
75a70cf9 12003
2ed72821 12004 fncode = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
12005 tree loaddecl = builtin_decl_explicit (fncode);
12006 if (loaddecl)
12007 initial
12008 = fold_convert (TREE_TYPE (TREE_TYPE (iaddr)),
12009 build_call_expr (loaddecl, 2, iaddr,
12010 build_int_cst (NULL_TREE,
12011 MEMMODEL_RELAXED)));
12012 else
12013 initial = build2 (MEM_REF, TREE_TYPE (TREE_TYPE (iaddr)), iaddr,
12014 build_int_cst (TREE_TYPE (iaddr), 0));
12015
182cf5a9 12016 initial
2ed72821 12017 = force_gimple_operand_gsi (&si, initial, true, NULL_TREE, true,
12018 GSI_SAME_STMT);
790368c5 12019
12020 /* Move the value to the LOADEDI temporary. */
cb7f680b 12021 if (gimple_in_ssa_p (cfun))
12022 {
75a70cf9 12023 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header)));
790368c5 12024 phi = create_phi_node (loadedi, loop_header);
cb7f680b 12025 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)),
12026 initial);
12027 }
12028 else
75a70cf9 12029 gsi_insert_before (&si,
12030 gimple_build_assign (loadedi, initial),
12031 GSI_SAME_STMT);
790368c5 12032 if (loadedi != loaded_val)
12033 {
75a70cf9 12034 gimple_stmt_iterator gsi2;
12035 tree x;
790368c5 12036
12037 x = build1 (VIEW_CONVERT_EXPR, type, loadedi);
75a70cf9 12038 gsi2 = gsi_start_bb (loop_header);
790368c5 12039 if (gimple_in_ssa_p (cfun))
12040 {
1a91d914 12041 gassign *stmt;
75a70cf9 12042 x = force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
12043 true, GSI_SAME_STMT);
12044 stmt = gimple_build_assign (loaded_val, x);
12045 gsi_insert_before (&gsi2, stmt, GSI_SAME_STMT);
790368c5 12046 }
12047 else
12048 {
75a70cf9 12049 x = build2 (MODIFY_EXPR, TREE_TYPE (loaded_val), loaded_val, x);
12050 force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
12051 true, GSI_SAME_STMT);
790368c5 12052 }
12053 }
75a70cf9 12054 gsi_remove (&si, true);
cb7f680b 12055
75a70cf9 12056 si = gsi_last_bb (store_bb);
12057 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
cb7f680b 12058
790368c5 12059 if (iaddr == addr)
12060 storedi = stored_val;
cb7f680b 12061 else
790368c5 12062 storedi =
75a70cf9 12063 force_gimple_operand_gsi (&si,
790368c5 12064 build1 (VIEW_CONVERT_EXPR, itype,
12065 stored_val), true, NULL_TREE, true,
75a70cf9 12066 GSI_SAME_STMT);
cb7f680b 12067
12068 /* Build the compare&swap statement. */
12069 new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi);
75a70cf9 12070 new_storedi = force_gimple_operand_gsi (&si,
87f9ffa4 12071 fold_convert (TREE_TYPE (loadedi),
12072 new_storedi),
cb7f680b 12073 true, NULL_TREE,
75a70cf9 12074 true, GSI_SAME_STMT);
cb7f680b 12075
12076 if (gimple_in_ssa_p (cfun))
12077 old_vali = loadedi;
12078 else
12079 {
f9e245b2 12080 old_vali = create_tmp_var (TREE_TYPE (loadedi));
75a70cf9 12081 stmt = gimple_build_assign (old_vali, loadedi);
12082 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
cb7f680b 12083
75a70cf9 12084 stmt = gimple_build_assign (loadedi, new_storedi);
12085 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
cb7f680b 12086 }
12087
12088 /* Note that we always perform the comparison as an integer, even for
48e1416a 12089 floating point. This allows the atomic operation to properly
cb7f680b 12090 succeed even with NaNs and -0.0. */
75a70cf9 12091 stmt = gimple_build_cond_empty
12092 (build2 (NE_EXPR, boolean_type_node,
12093 new_storedi, old_vali));
12094 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
cb7f680b 12095
12096 /* Update cfg. */
12097 e = single_succ_edge (store_bb);
12098 e->flags &= ~EDGE_FALLTHRU;
12099 e->flags |= EDGE_FALSE_VALUE;
12100
12101 e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE);
12102
790368c5 12103 /* Copy the new value to loadedi (we already did that before the condition
cb7f680b 12104 if we are not in SSA). */
12105 if (gimple_in_ssa_p (cfun))
12106 {
75a70cf9 12107 phi = gimple_seq_first_stmt (phi_nodes (loop_header));
790368c5 12108 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), new_storedi);
cb7f680b 12109 }
12110
75a70cf9 12111 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
12112 gsi_remove (&si, true);
cb7f680b 12113
04c2922b 12114 struct loop *loop = alloc_loop ();
12115 loop->header = loop_header;
5f037457 12116 loop->latch = store_bb;
04c2922b 12117 add_loop (loop, loop_header->loop_father);
12118
cb7f680b 12119 if (gimple_in_ssa_p (cfun))
12120 update_ssa (TODO_update_ssa_no_phi);
12121
12122 return true;
12123}
12124
12125/* A subroutine of expand_omp_atomic. Implement the atomic operation as:
12126
12127 GOMP_atomic_start ();
12128 *addr = rhs;
12129 GOMP_atomic_end ();
12130
12131 The result is not globally atomic, but works so long as all parallel
12132 references are within #pragma omp atomic directives. According to
12133 responses received from omp@openmp.org, appears to be within spec.
12134 Which makes sense, since that's how several other compilers handle
48e1416a 12135 this situation as well.
75a70cf9 12136 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
12137 expanding. STORED_VAL is the operand of the matching
12138 GIMPLE_OMP_ATOMIC_STORE.
cb7f680b 12139
48e1416a 12140 We replace
12141 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
cb7f680b 12142 loaded_val = *addr;
12143
12144 and replace
3ec11c49 12145 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
48e1416a 12146 *addr = stored_val;
cb7f680b 12147*/
12148
12149static bool
12150expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
12151 tree addr, tree loaded_val, tree stored_val)
12152{
75a70cf9 12153 gimple_stmt_iterator si;
1a91d914 12154 gassign *stmt;
cb7f680b 12155 tree t;
12156
75a70cf9 12157 si = gsi_last_bb (load_bb);
12158 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
cb7f680b 12159
b9a16870 12160 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
414c3a2c 12161 t = build_call_expr (t, 0);
75a70cf9 12162 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
cb7f680b 12163
182cf5a9 12164 stmt = gimple_build_assign (loaded_val, build_simple_mem_ref (addr));
75a70cf9 12165 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
12166 gsi_remove (&si, true);
cb7f680b 12167
75a70cf9 12168 si = gsi_last_bb (store_bb);
12169 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
cb7f680b 12170
182cf5a9 12171 stmt = gimple_build_assign (build_simple_mem_ref (unshare_expr (addr)),
12172 stored_val);
75a70cf9 12173 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
cb7f680b 12174
b9a16870 12175 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
414c3a2c 12176 t = build_call_expr (t, 0);
75a70cf9 12177 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
12178 gsi_remove (&si, true);
cb7f680b 12179
12180 if (gimple_in_ssa_p (cfun))
12181 update_ssa (TODO_update_ssa_no_phi);
12182 return true;
12183}
12184
48e1416a 12185/* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
12186 using expand_omp_atomic_fetch_op. If it failed, we try to
cb7f680b 12187 call expand_omp_atomic_pipeline, and if it fails too, the
12188 ultimate fallback is wrapping the operation in a mutex
48e1416a 12189 (expand_omp_atomic_mutex). REGION is the atomic region built
12190 by build_omp_regions_1(). */
cb7f680b 12191
12192static void
12193expand_omp_atomic (struct omp_region *region)
12194{
12195 basic_block load_bb = region->entry, store_bb = region->exit;
1a91d914 12196 gomp_atomic_load *load = as_a <gomp_atomic_load *> (last_stmt (load_bb));
12197 gomp_atomic_store *store = as_a <gomp_atomic_store *> (last_stmt (store_bb));
75a70cf9 12198 tree loaded_val = gimple_omp_atomic_load_lhs (load);
12199 tree addr = gimple_omp_atomic_load_rhs (load);
12200 tree stored_val = gimple_omp_atomic_store_val (store);
cb7f680b 12201 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
12202 HOST_WIDE_INT index;
12203
12204 /* Make sure the type is one of the supported sizes. */
e913b5cd 12205 index = tree_to_uhwi (TYPE_SIZE_UNIT (type));
cb7f680b 12206 index = exact_log2 (index);
12207 if (index >= 0 && index <= 4)
12208 {
12209 unsigned int align = TYPE_ALIGN_UNIT (type);
12210
12211 /* __sync builtins require strict data alignment. */
dcf7024c 12212 if (exact_log2 (align) >= index)
cb7f680b 12213 {
3ec11c49 12214 /* Atomic load. */
2169f33b 12215 if (loaded_val == stored_val
12216 && (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
12217 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
12218 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
3ec11c49 12219 && expand_omp_atomic_load (load_bb, addr, loaded_val, index))
2169f33b 12220 return;
12221
3ec11c49 12222 /* Atomic store. */
2169f33b 12223 if ((GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
12224 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
12225 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
12226 && store_bb == single_succ (load_bb)
12227 && first_stmt (store_bb) == store
3ec11c49 12228 && expand_omp_atomic_store (load_bb, addr, loaded_val,
12229 stored_val, index))
2169f33b 12230 return;
12231
cb7f680b 12232 /* When possible, use specialized atomic update functions. */
12233 if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
3ec11c49 12234 && store_bb == single_succ (load_bb)
12235 && expand_omp_atomic_fetch_op (load_bb, addr,
12236 loaded_val, stored_val, index))
12237 return;
cb7f680b 12238
12239 /* If we don't have specialized __sync builtins, try and implement
12240 as a compare and swap loop. */
12241 if (expand_omp_atomic_pipeline (load_bb, store_bb, addr,
12242 loaded_val, stored_val, index))
12243 return;
12244 }
12245 }
12246
12247 /* The ultimate fallback is wrapping the operation in a mutex. */
12248 expand_omp_atomic_mutex (load_bb, store_bb, addr, loaded_val, stored_val);
12249}
12250
1e8e9920 12251
f69b8a4c 12252/* Encode an oacc launch argument. This matches the GOMP_LAUNCH_PACK
e561d5e1 12253 macro on gomp-constants.h. We do not check for overflow. */
12254
12255static tree
12256oacc_launch_pack (unsigned code, tree device, unsigned op)
12257{
12258 tree res;
12259
12260 res = build_int_cst (unsigned_type_node, GOMP_LAUNCH_PACK (code, 0, op));
12261 if (device)
12262 {
12263 device = fold_build2 (LSHIFT_EXPR, unsigned_type_node,
12264 device, build_int_cst (unsigned_type_node,
12265 GOMP_LAUNCH_DEVICE_SHIFT));
12266 res = fold_build2 (BIT_IOR_EXPR, unsigned_type_node, res, device);
12267 }
12268 return res;
12269}
12270
12271/* Look for compute grid dimension clauses and convert to an attribute
12272 attached to FN. This permits the target-side code to (a) massage
12273 the dimensions, (b) emit that data and (c) optimize. Non-constant
12274 dimensions are pushed onto ARGS.
12275
12276 The attribute value is a TREE_LIST. A set of dimensions is
12277 represented as a list of INTEGER_CST. Those that are runtime
f69b8a4c 12278 exprs are represented as an INTEGER_CST of zero.
e561d5e1 12279
12280 TOOO. Normally the attribute will just contain a single such list. If
12281 however it contains a list of lists, this will represent the use of
12282 device_type. Each member of the outer list is an assoc list of
12283 dimensions, keyed by the device type. The first entry will be the
12284 default. Well, that's the plan. */
12285
12286#define OACC_FN_ATTRIB "oacc function"
12287
12288/* Replace any existing oacc fn attribute with updated dimensions. */
12289
12290void
12291replace_oacc_fn_attrib (tree fn, tree dims)
12292{
12293 tree ident = get_identifier (OACC_FN_ATTRIB);
12294 tree attribs = DECL_ATTRIBUTES (fn);
12295
12296 /* If we happen to be present as the first attrib, drop it. */
12297 if (attribs && TREE_PURPOSE (attribs) == ident)
12298 attribs = TREE_CHAIN (attribs);
12299 DECL_ATTRIBUTES (fn) = tree_cons (ident, dims, attribs);
12300}
12301
12302/* Scan CLAUSES for launch dimensions and attach them to the oacc
12303 function attribute. Push any that are non-constant onto the ARGS
12304 list, along with an appropriate GOMP_LAUNCH_DIM tag. */
12305
12306static void
12307set_oacc_fn_attrib (tree fn, tree clauses, vec<tree> *args)
12308{
12309 /* Must match GOMP_DIM ordering. */
12310 static const omp_clause_code ids[]
12311 = { OMP_CLAUSE_NUM_GANGS, OMP_CLAUSE_NUM_WORKERS,
12312 OMP_CLAUSE_VECTOR_LENGTH };
12313 unsigned ix;
12314 tree dims[GOMP_DIM_MAX];
12315 tree attr = NULL_TREE;
12316 unsigned non_const = 0;
12317
12318 for (ix = GOMP_DIM_MAX; ix--;)
12319 {
12320 tree clause = find_omp_clause (clauses, ids[ix]);
12321 tree dim = NULL_TREE;
12322
12323 if (clause)
12324 dim = OMP_CLAUSE_EXPR (clause, ids[ix]);
12325 dims[ix] = dim;
12326 if (dim && TREE_CODE (dim) != INTEGER_CST)
12327 {
12328 dim = integer_zero_node;
12329 non_const |= GOMP_DIM_MASK (ix);
12330 }
12331 attr = tree_cons (NULL_TREE, dim, attr);
12332 }
12333
12334 replace_oacc_fn_attrib (fn, attr);
12335
12336 if (non_const)
12337 {
12338 /* Push a dynamic argument set. */
12339 args->safe_push (oacc_launch_pack (GOMP_LAUNCH_DIM,
12340 NULL_TREE, non_const));
12341 for (unsigned ix = 0; ix != GOMP_DIM_MAX; ix++)
12342 if (non_const & GOMP_DIM_MASK (ix))
12343 args->safe_push (dims[ix]);
12344 }
12345}
12346
a1b7fe4b 12347/* Process the routine's dimension clauess to generate an attribute
12348 value. Issue diagnostics as appropriate. We default to SEQ
12349 (OpenACC 2.5 clarifies this). All dimensions have a size of zero
12350 (dynamic). TREE_PURPOSE is set to indicate whether that dimension
12351 can have a loop partitioned on it. non-zero indicates
12352 yes, zero indicates no. By construction once a non-zero has been
12353 reached, further inner dimensions must also be non-zero. We set
12354 TREE_VALUE to zero for the dimensions that may be partitioned and
12355 1 for the other ones -- if a loop is (erroneously) spawned at
12356 an outer level, we don't want to try and partition it. */
12357
12358tree
12359build_oacc_routine_dims (tree clauses)
12360{
12361 /* Must match GOMP_DIM ordering. */
12362 static const omp_clause_code ids[] =
12363 {OMP_CLAUSE_GANG, OMP_CLAUSE_WORKER, OMP_CLAUSE_VECTOR, OMP_CLAUSE_SEQ};
12364 int ix;
12365 int level = -1;
12366
12367 for (; clauses; clauses = OMP_CLAUSE_CHAIN (clauses))
12368 for (ix = GOMP_DIM_MAX + 1; ix--;)
12369 if (OMP_CLAUSE_CODE (clauses) == ids[ix])
12370 {
12371 if (level >= 0)
12372 error_at (OMP_CLAUSE_LOCATION (clauses),
12373 "multiple loop axes specified for routine");
12374 level = ix;
12375 break;
12376 }
12377
12378 /* Default to SEQ. */
12379 if (level < 0)
12380 level = GOMP_DIM_MAX;
12381
12382 tree dims = NULL_TREE;
12383
12384 for (ix = GOMP_DIM_MAX; ix--;)
12385 dims = tree_cons (build_int_cst (boolean_type_node, ix >= level),
12386 build_int_cst (integer_type_node, ix < level), dims);
12387
12388 return dims;
12389}
12390
e561d5e1 12391/* Retrieve the oacc function attrib and return it. Non-oacc
12392 functions will return NULL. */
12393
12394tree
12395get_oacc_fn_attrib (tree fn)
12396{
12397 return lookup_attribute (OACC_FN_ATTRIB, DECL_ATTRIBUTES (fn));
12398}
12399
e1037942 12400/* Extract an oacc execution dimension from FN. FN must be an
12401 offloaded function or routine that has already had its execution
12402 dimensions lowered to the target-specific values. */
12403
12404int
12405get_oacc_fn_dim_size (tree fn, int axis)
12406{
12407 tree attrs = get_oacc_fn_attrib (fn);
12408
12409 gcc_assert (axis < GOMP_DIM_MAX);
12410
12411 tree dims = TREE_VALUE (attrs);
12412 while (axis--)
12413 dims = TREE_CHAIN (dims);
12414
12415 int size = TREE_INT_CST_LOW (TREE_VALUE (dims));
12416
12417 return size;
12418}
12419
12420/* Extract the dimension axis from an IFN_GOACC_DIM_POS or
12421 IFN_GOACC_DIM_SIZE call. */
12422
12423int
12424get_oacc_ifn_dim_arg (const gimple *stmt)
12425{
12426 gcc_checking_assert (gimple_call_internal_fn (stmt) == IFN_GOACC_DIM_SIZE
12427 || gimple_call_internal_fn (stmt) == IFN_GOACC_DIM_POS);
12428 tree arg = gimple_call_arg (stmt, 0);
12429 HOST_WIDE_INT axis = TREE_INT_CST_LOW (arg);
12430
12431 gcc_checking_assert (axis >= 0 && axis < GOMP_DIM_MAX);
12432 return (int) axis;
12433}
12434
1a40f20b 12435/* Mark the loops inside the kernels region starting at REGION_ENTRY and ending
12436 at REGION_EXIT. */
12437
12438static void
12439mark_loops_in_oacc_kernels_region (basic_block region_entry,
12440 basic_block region_exit)
12441{
12442 struct loop *outer = region_entry->loop_father;
12443 gcc_assert (region_exit == NULL || outer == region_exit->loop_father);
12444
12445 /* Don't parallelize the kernels region if it contains more than one outer
12446 loop. */
12447 unsigned int nr_outer_loops = 0;
12448 struct loop *single_outer;
12449 for (struct loop *loop = outer->inner; loop != NULL; loop = loop->next)
12450 {
12451 gcc_assert (loop_outer (loop) == outer);
12452
12453 if (!dominated_by_p (CDI_DOMINATORS, loop->header, region_entry))
12454 continue;
12455
12456 if (region_exit != NULL
12457 && dominated_by_p (CDI_DOMINATORS, loop->header, region_exit))
12458 continue;
12459
12460 nr_outer_loops++;
12461 single_outer = loop;
12462 }
12463 if (nr_outer_loops != 1)
12464 return;
12465
12466 for (struct loop *loop = single_outer->inner; loop != NULL; loop = loop->inner)
12467 if (loop->next)
12468 return;
12469
12470 /* Mark the loops in the region. */
12471 for (struct loop *loop = single_outer; loop != NULL; loop = loop->inner)
12472 loop->in_oacc_kernels_region = true;
12473}
12474
ca4c3545 12475/* Expand the GIMPLE_OMP_TARGET starting at REGION. */
773c5ba7 12476
12477static void
bc7bff74 12478expand_omp_target (struct omp_region *region)
773c5ba7 12479{
bc7bff74 12480 basic_block entry_bb, exit_bb, new_bb;
ca4c3545 12481 struct function *child_cfun;
12482 tree child_fn, block, t;
bc7bff74 12483 gimple_stmt_iterator gsi;
1a91d914 12484 gomp_target *entry_stmt;
42acab1c 12485 gimple *stmt;
bc7bff74 12486 edge e;
ca4c3545 12487 bool offloaded, data_region;
bc7bff74 12488
1a91d914 12489 entry_stmt = as_a <gomp_target *> (last_stmt (region->entry));
bc7bff74 12490 new_bb = region->entry;
ca4c3545 12491
12492 offloaded = is_gimple_omp_offloaded (entry_stmt);
12493 switch (gimple_omp_target_kind (entry_stmt))
12494 {
e561d5e1 12495 case GF_OMP_TARGET_KIND_REGION:
12496 case GF_OMP_TARGET_KIND_UPDATE:
43895be5 12497 case GF_OMP_TARGET_KIND_ENTER_DATA:
12498 case GF_OMP_TARGET_KIND_EXIT_DATA:
12499 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
12500 case GF_OMP_TARGET_KIND_OACC_KERNELS:
ca4c3545 12501 case GF_OMP_TARGET_KIND_OACC_UPDATE:
12502 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
2fc5e987 12503 case GF_OMP_TARGET_KIND_OACC_DECLARE:
ca4c3545 12504 data_region = false;
12505 break;
12506 case GF_OMP_TARGET_KIND_DATA:
12507 case GF_OMP_TARGET_KIND_OACC_DATA:
12508 data_region = true;
12509 break;
12510 default:
12511 gcc_unreachable ();
12512 }
12513
12514 child_fn = NULL_TREE;
12515 child_cfun = NULL;
12516 if (offloaded)
bc7bff74 12517 {
12518 child_fn = gimple_omp_target_child_fn (entry_stmt);
12519 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
12520 }
12521
ca4c3545 12522 /* Supported by expand_omp_taskreg, but not here. */
12523 if (child_cfun != NULL)
12524 gcc_checking_assert (!child_cfun->cfg);
12525 gcc_checking_assert (!gimple_in_ssa_p (cfun));
12526
bc7bff74 12527 entry_bb = region->entry;
12528 exit_bb = region->exit;
12529
1a40f20b 12530 if (gimple_omp_target_kind (entry_stmt) == GF_OMP_TARGET_KIND_OACC_KERNELS)
12531 mark_loops_in_oacc_kernels_region (region->entry, region->exit);
12532
ca4c3545 12533 if (offloaded)
bc7bff74 12534 {
12535 unsigned srcidx, dstidx, num;
12536
ca4c3545 12537 /* If the offloading region needs data sent from the parent
bc7bff74 12538 function, then the very first statement (except possible
ca4c3545 12539 tree profile counter updates) of the offloading body
bc7bff74 12540 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
12541 &.OMP_DATA_O is passed as an argument to the child function,
12542 we need to replace it with the argument as seen by the child
12543 function.
12544
12545 In most cases, this will end up being the identity assignment
ca4c3545 12546 .OMP_DATA_I = .OMP_DATA_I. However, if the offloading body had
bc7bff74 12547 a function call that has been inlined, the original PARM_DECL
12548 .OMP_DATA_I may have been converted into a different local
12549 variable. In which case, we need to keep the assignment. */
ca4c3545 12550 tree data_arg = gimple_omp_target_data_arg (entry_stmt);
12551 if (data_arg)
bc7bff74 12552 {
12553 basic_block entry_succ_bb = single_succ (entry_bb);
12554 gimple_stmt_iterator gsi;
12555 tree arg;
42acab1c 12556 gimple *tgtcopy_stmt = NULL;
ca4c3545 12557 tree sender = TREE_VEC_ELT (data_arg, 0);
bc7bff74 12558
12559 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
12560 {
12561 gcc_assert (!gsi_end_p (gsi));
12562 stmt = gsi_stmt (gsi);
12563 if (gimple_code (stmt) != GIMPLE_ASSIGN)
12564 continue;
12565
12566 if (gimple_num_ops (stmt) == 2)
12567 {
12568 tree arg = gimple_assign_rhs1 (stmt);
12569
12570 /* We're ignoring the subcode because we're
12571 effectively doing a STRIP_NOPS. */
12572
12573 if (TREE_CODE (arg) == ADDR_EXPR
12574 && TREE_OPERAND (arg, 0) == sender)
12575 {
12576 tgtcopy_stmt = stmt;
12577 break;
12578 }
12579 }
12580 }
12581
12582 gcc_assert (tgtcopy_stmt != NULL);
12583 arg = DECL_ARGUMENTS (child_fn);
12584
12585 gcc_assert (gimple_assign_lhs (tgtcopy_stmt) == arg);
12586 gsi_remove (&gsi, true);
12587 }
12588
12589 /* Declare local variables needed in CHILD_CFUN. */
12590 block = DECL_INITIAL (child_fn);
12591 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
ca4c3545 12592 /* The gimplifier could record temporaries in the offloading block
bc7bff74 12593 rather than in containing function's local_decls chain,
12594 which would mean cgraph missed finalizing them. Do it now. */
12595 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
12596 if (TREE_CODE (t) == VAR_DECL
12597 && TREE_STATIC (t)
12598 && !DECL_EXTERNAL (t))
97221fd7 12599 varpool_node::finalize_decl (t);
bc7bff74 12600 DECL_SAVED_TREE (child_fn) = NULL;
12601 /* We'll create a CFG for child_fn, so no gimple body is needed. */
12602 gimple_set_body (child_fn, NULL);
12603 TREE_USED (block) = 1;
12604
12605 /* Reset DECL_CONTEXT on function arguments. */
12606 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
12607 DECL_CONTEXT (t) = child_fn;
12608
ca4c3545 12609 /* Split ENTRY_BB at GIMPLE_*,
bc7bff74 12610 so that it can be moved to the child function. */
12611 gsi = gsi_last_bb (entry_bb);
12612 stmt = gsi_stmt (gsi);
ca4c3545 12613 gcc_assert (stmt
12614 && gimple_code (stmt) == gimple_code (entry_stmt));
bc7bff74 12615 e = split_block (entry_bb, stmt);
923635e7 12616 gsi_remove (&gsi, true);
bc7bff74 12617 entry_bb = e->dest;
12618 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
12619
12620 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
12621 if (exit_bb)
12622 {
12623 gsi = gsi_last_bb (exit_bb);
12624 gcc_assert (!gsi_end_p (gsi)
12625 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
12626 stmt = gimple_build_return (NULL);
12627 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
12628 gsi_remove (&gsi, true);
12629 }
12630
ca4c3545 12631 /* Move the offloading region into CHILD_CFUN. */
bc7bff74 12632
12633 block = gimple_block (entry_stmt);
12634
12635 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
12636 if (exit_bb)
12637 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
12638 /* When the OMP expansion process cannot guarantee an up-to-date
12639 loop tree arrange for the child function to fixup loops. */
12640 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
12641 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
12642
12643 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
12644 num = vec_safe_length (child_cfun->local_decls);
12645 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
12646 {
12647 t = (*child_cfun->local_decls)[srcidx];
12648 if (DECL_CONTEXT (t) == cfun->decl)
12649 continue;
12650 if (srcidx != dstidx)
12651 (*child_cfun->local_decls)[dstidx] = t;
12652 dstidx++;
12653 }
12654 if (dstidx != num)
12655 vec_safe_truncate (child_cfun->local_decls, dstidx);
12656
12657 /* Inform the callgraph about the new function. */
613f2c38 12658 child_cfun->curr_properties = cfun->curr_properties;
12659 child_cfun->has_simduid_loops |= cfun->has_simduid_loops;
12660 child_cfun->has_force_vectorize_loops |= cfun->has_force_vectorize_loops;
6a77ed3d 12661 cgraph_node *node = cgraph_node::get_create (child_fn);
12662 node->parallelized_function = 1;
415d1b9a 12663 cgraph_node::add_new_function (child_fn, true);
bc7bff74 12664
dccabdd1 12665 /* Add the new function to the offload table. */
5f3001a9 12666 if (ENABLE_OFFLOADING)
12667 vec_safe_push (offload_funcs, child_fn);
dccabdd1 12668
9561765e 12669 bool need_asm = DECL_ASSEMBLER_NAME_SET_P (current_function_decl)
12670 && !DECL_ASSEMBLER_NAME_SET_P (child_fn);
12671
bc7bff74 12672 /* Fix the callgraph edges for child_cfun. Those for cfun will be
12673 fixed in a following pass. */
12674 push_cfun (child_cfun);
9561765e 12675 if (need_asm)
12676 assign_assembler_name_if_neeeded (child_fn);
35ee1c66 12677 cgraph_edge::rebuild_edges ();
bc7bff74 12678
b0c5e347 12679 /* Prevent IPA from removing child_fn as unreachable, since there are no
12680 refs from the parent function to child_fn in offload LTO mode. */
5f3001a9 12681 if (ENABLE_OFFLOADING)
12682 cgraph_node::get (child_fn)->mark_force_output ();
b0c5e347 12683
bc7bff74 12684 /* Some EH regions might become dead, see PR34608. If
12685 pass_cleanup_cfg isn't the first pass to happen with the
12686 new child, these dead EH edges might cause problems.
12687 Clean them up now. */
12688 if (flag_exceptions)
12689 {
12690 basic_block bb;
12691 bool changed = false;
12692
fc00614f 12693 FOR_EACH_BB_FN (bb, cfun)
bc7bff74 12694 changed |= gimple_purge_dead_eh_edges (bb);
12695 if (changed)
12696 cleanup_tree_cfg ();
12697 }
382ecba7 12698 if (flag_checking && !loops_state_satisfies_p (LOOPS_NEED_FIXUP))
86a932e0 12699 verify_loop_structure ();
bc7bff74 12700 pop_cfun ();
9561765e 12701
12702 if (dump_file && !gimple_in_ssa_p (cfun))
12703 {
12704 omp_any_child_fn_dumped = true;
12705 dump_function_header (dump_file, child_fn, dump_flags);
12706 dump_function_to_file (child_fn, dump_file, dump_flags);
12707 }
bc7bff74 12708 }
12709
ca4c3545 12710 /* Emit a library call to launch the offloading region, or do data
bc7bff74 12711 transfers. */
43895be5 12712 tree t1, t2, t3, t4, device, cond, depend, c, clauses;
bc7bff74 12713 enum built_in_function start_ix;
12714 location_t clause_loc;
43895be5 12715 unsigned int flags_i = 0;
bc7bff74 12716
ca4c3545 12717 switch (gimple_omp_target_kind (entry_stmt))
12718 {
12719 case GF_OMP_TARGET_KIND_REGION:
12720 start_ix = BUILT_IN_GOMP_TARGET;
12721 break;
12722 case GF_OMP_TARGET_KIND_DATA:
12723 start_ix = BUILT_IN_GOMP_TARGET_DATA;
12724 break;
12725 case GF_OMP_TARGET_KIND_UPDATE:
12726 start_ix = BUILT_IN_GOMP_TARGET_UPDATE;
12727 break;
43895be5 12728 case GF_OMP_TARGET_KIND_ENTER_DATA:
12729 start_ix = BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA;
12730 break;
12731 case GF_OMP_TARGET_KIND_EXIT_DATA:
12732 start_ix = BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA;
12733 flags_i |= GOMP_TARGET_FLAG_EXIT_DATA;
12734 break;
ca4c3545 12735 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
12736 case GF_OMP_TARGET_KIND_OACC_KERNELS:
12737 start_ix = BUILT_IN_GOACC_PARALLEL;
12738 break;
12739 case GF_OMP_TARGET_KIND_OACC_DATA:
12740 start_ix = BUILT_IN_GOACC_DATA_START;
12741 break;
12742 case GF_OMP_TARGET_KIND_OACC_UPDATE:
12743 start_ix = BUILT_IN_GOACC_UPDATE;
12744 break;
12745 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
12746 start_ix = BUILT_IN_GOACC_ENTER_EXIT_DATA;
12747 break;
2fc5e987 12748 case GF_OMP_TARGET_KIND_OACC_DECLARE:
12749 start_ix = BUILT_IN_GOACC_DECLARE;
12750 break;
ca4c3545 12751 default:
12752 gcc_unreachable ();
12753 }
bc7bff74 12754
ca4c3545 12755 clauses = gimple_omp_target_clauses (entry_stmt);
bc7bff74 12756
ca4c3545 12757 /* By default, the value of DEVICE is GOMP_DEVICE_ICV (let runtime
12758 library choose) and there is no conditional. */
bc7bff74 12759 cond = NULL_TREE;
ca4c3545 12760 device = build_int_cst (integer_type_node, GOMP_DEVICE_ICV);
bc7bff74 12761
12762 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
12763 if (c)
12764 cond = OMP_CLAUSE_IF_EXPR (c);
12765
12766 c = find_omp_clause (clauses, OMP_CLAUSE_DEVICE);
12767 if (c)
12768 {
ca4c3545 12769 /* Even if we pass it to all library function calls, it is currently only
12770 defined/used for the OpenMP target ones. */
12771 gcc_checking_assert (start_ix == BUILT_IN_GOMP_TARGET
12772 || start_ix == BUILT_IN_GOMP_TARGET_DATA
43895be5 12773 || start_ix == BUILT_IN_GOMP_TARGET_UPDATE
12774 || start_ix == BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA);
ca4c3545 12775
bc7bff74 12776 device = OMP_CLAUSE_DEVICE_ID (c);
12777 clause_loc = OMP_CLAUSE_LOCATION (c);
12778 }
12779 else
12780 clause_loc = gimple_location (entry_stmt);
12781
43895be5 12782 c = find_omp_clause (clauses, OMP_CLAUSE_NOWAIT);
12783 if (c)
12784 flags_i |= GOMP_TARGET_FLAG_NOWAIT;
12785
bc7bff74 12786 /* Ensure 'device' is of the correct type. */
12787 device = fold_convert_loc (clause_loc, integer_type_node, device);
12788
12789 /* If we found the clause 'if (cond)', build
ca4c3545 12790 (cond ? device : GOMP_DEVICE_HOST_FALLBACK). */
bc7bff74 12791 if (cond)
12792 {
12793 cond = gimple_boolify (cond);
12794
12795 basic_block cond_bb, then_bb, else_bb;
12796 edge e;
12797 tree tmp_var;
12798
f9e245b2 12799 tmp_var = create_tmp_var (TREE_TYPE (device));
ca4c3545 12800 if (offloaded)
4302d619 12801 e = split_block_after_labels (new_bb);
ca4c3545 12802 else
bc7bff74 12803 {
12804 gsi = gsi_last_bb (new_bb);
12805 gsi_prev (&gsi);
12806 e = split_block (new_bb, gsi_stmt (gsi));
12807 }
bc7bff74 12808 cond_bb = e->src;
12809 new_bb = e->dest;
12810 remove_edge (e);
12811
12812 then_bb = create_empty_bb (cond_bb);
12813 else_bb = create_empty_bb (then_bb);
12814 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
12815 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
12816
12817 stmt = gimple_build_cond_empty (cond);
12818 gsi = gsi_last_bb (cond_bb);
12819 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
12820
12821 gsi = gsi_start_bb (then_bb);
12822 stmt = gimple_build_assign (tmp_var, device);
12823 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
12824
12825 gsi = gsi_start_bb (else_bb);
12826 stmt = gimple_build_assign (tmp_var,
ca4c3545 12827 build_int_cst (integer_type_node,
12828 GOMP_DEVICE_HOST_FALLBACK));
bc7bff74 12829 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
12830
12831 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
12832 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
b3083327 12833 add_bb_to_loop (then_bb, cond_bb->loop_father);
12834 add_bb_to_loop (else_bb, cond_bb->loop_father);
bc7bff74 12835 make_edge (then_bb, new_bb, EDGE_FALLTHRU);
12836 make_edge (else_bb, new_bb, EDGE_FALLTHRU);
12837
12838 device = tmp_var;
12839 }
12840
12841 gsi = gsi_last_bb (new_bb);
12842 t = gimple_omp_target_data_arg (entry_stmt);
12843 if (t == NULL)
12844 {
12845 t1 = size_zero_node;
12846 t2 = build_zero_cst (ptr_type_node);
12847 t3 = t2;
12848 t4 = t2;
12849 }
12850 else
12851 {
12852 t1 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t, 1))));
12853 t1 = size_binop (PLUS_EXPR, t1, size_int (1));
12854 t2 = build_fold_addr_expr (TREE_VEC_ELT (t, 0));
12855 t3 = build_fold_addr_expr (TREE_VEC_ELT (t, 1));
12856 t4 = build_fold_addr_expr (TREE_VEC_ELT (t, 2));
12857 }
12858
42acab1c 12859 gimple *g;
e561d5e1 12860 bool tagging = false;
ca4c3545 12861 /* The maximum number used by any start_ix, without varargs. */
02c05c9b 12862 auto_vec<tree, 11> args;
12863 args.quick_push (device);
ca4c3545 12864 if (offloaded)
02c05c9b 12865 args.quick_push (build_fold_addr_expr (child_fn));
02c05c9b 12866 args.quick_push (t1);
12867 args.quick_push (t2);
12868 args.quick_push (t3);
12869 args.quick_push (t4);
ca4c3545 12870 switch (start_ix)
12871 {
12872 case BUILT_IN_GOACC_DATA_START:
2fc5e987 12873 case BUILT_IN_GOACC_DECLARE:
ca4c3545 12874 case BUILT_IN_GOMP_TARGET_DATA:
43895be5 12875 break;
12876 case BUILT_IN_GOMP_TARGET:
ca4c3545 12877 case BUILT_IN_GOMP_TARGET_UPDATE:
43895be5 12878 case BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA:
12879 args.quick_push (build_int_cst (unsigned_type_node, flags_i));
12880 c = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
12881 if (c)
12882 depend = OMP_CLAUSE_DECL (c);
12883 else
12884 depend = build_int_cst (ptr_type_node, 0);
12885 args.quick_push (depend);
9561765e 12886 if (start_ix == BUILT_IN_GOMP_TARGET)
12887 {
12888 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_TEAMS);
12889 if (c)
12890 {
12891 t = fold_convert (integer_type_node,
12892 OMP_CLAUSE_NUM_TEAMS_EXPR (c));
12893 t = force_gimple_operand_gsi (&gsi, t, true, NULL,
12894 true, GSI_SAME_STMT);
12895 }
12896 else
12897 t = integer_minus_one_node;
12898 args.quick_push (t);
12899 c = find_omp_clause (clauses, OMP_CLAUSE_THREAD_LIMIT);
12900 if (c)
12901 {
12902 t = fold_convert (integer_type_node,
12903 OMP_CLAUSE_THREAD_LIMIT_EXPR (c));
12904 t = force_gimple_operand_gsi (&gsi, t, true, NULL,
12905 true, GSI_SAME_STMT);
12906 }
12907 else
12908 t = integer_minus_one_node;
12909 args.quick_push (t);
12910 }
ca4c3545 12911 break;
12912 case BUILT_IN_GOACC_PARALLEL:
12913 {
e561d5e1 12914 set_oacc_fn_attrib (child_fn, clauses, &args);
12915 tagging = true;
ca4c3545 12916 }
12917 /* FALLTHRU */
12918 case BUILT_IN_GOACC_ENTER_EXIT_DATA:
12919 case BUILT_IN_GOACC_UPDATE:
12920 {
e561d5e1 12921 tree t_async = NULL_TREE;
12922
12923 /* If present, use the value specified by the respective
ca4c3545 12924 clause, making sure that is of the correct type. */
12925 c = find_omp_clause (clauses, OMP_CLAUSE_ASYNC);
12926 if (c)
12927 t_async = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
12928 integer_type_node,
12929 OMP_CLAUSE_ASYNC_EXPR (c));
e561d5e1 12930 else if (!tagging)
12931 /* Default values for t_async. */
12932 t_async = fold_convert_loc (gimple_location (entry_stmt),
12933 integer_type_node,
12934 build_int_cst (integer_type_node,
12935 GOMP_ASYNC_SYNC));
12936 if (tagging && t_async)
ca4c3545 12937 {
e561d5e1 12938 unsigned HOST_WIDE_INT i_async;
ca4c3545 12939
e561d5e1 12940 if (TREE_CODE (t_async) == INTEGER_CST)
ca4c3545 12941 {
e561d5e1 12942 /* See if we can pack the async arg in to the tag's
12943 operand. */
12944 i_async = TREE_INT_CST_LOW (t_async);
12945
12946 if (i_async < GOMP_LAUNCH_OP_MAX)
12947 t_async = NULL_TREE;
ca4c3545 12948 }
e561d5e1 12949 if (t_async)
12950 i_async = GOMP_LAUNCH_OP_MAX;
12951 args.safe_push (oacc_launch_pack
12952 (GOMP_LAUNCH_ASYNC, NULL_TREE, i_async));
12953 }
12954 if (t_async)
12955 args.safe_push (t_async);
ca4c3545 12956
e561d5e1 12957 /* Save the argument index, and ... */
12958 unsigned t_wait_idx = args.length ();
12959 unsigned num_waits = 0;
12960 c = find_omp_clause (clauses, OMP_CLAUSE_WAIT);
12961 if (!tagging || c)
12962 /* ... push a placeholder. */
12963 args.safe_push (integer_zero_node);
12964
12965 for (; c; c = OMP_CLAUSE_CHAIN (c))
12966 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_WAIT)
12967 {
12968 args.safe_push (fold_convert_loc (OMP_CLAUSE_LOCATION (c),
12969 integer_type_node,
12970 OMP_CLAUSE_WAIT_EXPR (c)));
12971 num_waits++;
12972 }
12973
12974 if (!tagging || num_waits)
12975 {
12976 tree len;
12977
12978 /* Now that we know the number, update the placeholder. */
12979 if (tagging)
12980 len = oacc_launch_pack (GOMP_LAUNCH_WAIT, NULL_TREE, num_waits);
12981 else
12982 len = build_int_cst (integer_type_node, num_waits);
12983 len = fold_convert_loc (gimple_location (entry_stmt),
12984 unsigned_type_node, len);
12985 args[t_wait_idx] = len;
ca4c3545 12986 }
12987 }
12988 break;
12989 default:
12990 gcc_unreachable ();
bc7bff74 12991 }
e561d5e1 12992 if (tagging)
12993 /* Push terminal marker - zero. */
12994 args.safe_push (oacc_launch_pack (0, NULL_TREE, 0));
ca4c3545 12995
02c05c9b 12996 g = gimple_build_call_vec (builtin_decl_explicit (start_ix), args);
bc7bff74 12997 gimple_set_location (g, gimple_location (entry_stmt));
12998 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
ca4c3545 12999 if (!offloaded)
bc7bff74 13000 {
13001 g = gsi_stmt (gsi);
13002 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_TARGET);
13003 gsi_remove (&gsi, true);
13004 }
43895be5 13005 if (data_region && region->exit)
bc7bff74 13006 {
13007 gsi = gsi_last_bb (region->exit);
13008 g = gsi_stmt (gsi);
13009 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_RETURN);
13010 gsi_remove (&gsi, true);
13011 }
13012}
13013
13014
13015/* Expand the parallel region tree rooted at REGION. Expansion
13016 proceeds in depth-first order. Innermost regions are expanded
13017 first. This way, parallel regions that require a new function to
75a70cf9 13018 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
773c5ba7 13019 internal dependencies in their body. */
13020
13021static void
13022expand_omp (struct omp_region *region)
13023{
9561765e 13024 omp_any_child_fn_dumped = false;
773c5ba7 13025 while (region)
13026 {
1d22f541 13027 location_t saved_location;
42acab1c 13028 gimple *inner_stmt = NULL;
1d22f541 13029
d1d5b012 13030 /* First, determine whether this is a combined parallel+workshare
13031 region. */
75a70cf9 13032 if (region->type == GIMPLE_OMP_PARALLEL)
d1d5b012 13033 determine_parallel_type (region);
13034
bc7bff74 13035 if (region->type == GIMPLE_OMP_FOR
13036 && gimple_omp_for_combined_p (last_stmt (region->entry)))
13037 inner_stmt = last_stmt (region->inner->entry);
13038
773c5ba7 13039 if (region->inner)
13040 expand_omp (region->inner);
13041
1d22f541 13042 saved_location = input_location;
75a70cf9 13043 if (gimple_has_location (last_stmt (region->entry)))
13044 input_location = gimple_location (last_stmt (region->entry));
1d22f541 13045
61e47ac8 13046 switch (region->type)
773c5ba7 13047 {
75a70cf9 13048 case GIMPLE_OMP_PARALLEL:
13049 case GIMPLE_OMP_TASK:
fd6481cf 13050 expand_omp_taskreg (region);
13051 break;
13052
75a70cf9 13053 case GIMPLE_OMP_FOR:
bc7bff74 13054 expand_omp_for (region, inner_stmt);
61e47ac8 13055 break;
773c5ba7 13056
75a70cf9 13057 case GIMPLE_OMP_SECTIONS:
61e47ac8 13058 expand_omp_sections (region);
13059 break;
773c5ba7 13060
75a70cf9 13061 case GIMPLE_OMP_SECTION:
61e47ac8 13062 /* Individual omp sections are handled together with their
75a70cf9 13063 parent GIMPLE_OMP_SECTIONS region. */
61e47ac8 13064 break;
773c5ba7 13065
75a70cf9 13066 case GIMPLE_OMP_SINGLE:
61e47ac8 13067 expand_omp_single (region);
13068 break;
773c5ba7 13069
43895be5 13070 case GIMPLE_OMP_ORDERED:
13071 {
13072 gomp_ordered *ord_stmt
13073 = as_a <gomp_ordered *> (last_stmt (region->entry));
13074 if (find_omp_clause (gimple_omp_ordered_clauses (ord_stmt),
13075 OMP_CLAUSE_DEPEND))
13076 {
13077 /* We'll expand these when expanding corresponding
13078 worksharing region with ordered(n) clause. */
13079 gcc_assert (region->outer
13080 && region->outer->type == GIMPLE_OMP_FOR);
13081 region->ord_stmt = ord_stmt;
13082 break;
13083 }
13084 }
13085 /* FALLTHRU */
75a70cf9 13086 case GIMPLE_OMP_MASTER:
bc7bff74 13087 case GIMPLE_OMP_TASKGROUP:
75a70cf9 13088 case GIMPLE_OMP_CRITICAL:
bc7bff74 13089 case GIMPLE_OMP_TEAMS:
61e47ac8 13090 expand_omp_synch (region);
13091 break;
773c5ba7 13092
75a70cf9 13093 case GIMPLE_OMP_ATOMIC_LOAD:
cb7f680b 13094 expand_omp_atomic (region);
13095 break;
13096
bc7bff74 13097 case GIMPLE_OMP_TARGET:
13098 expand_omp_target (region);
13099 break;
13100
61e47ac8 13101 default:
13102 gcc_unreachable ();
13103 }
cc5982dc 13104
1d22f541 13105 input_location = saved_location;
773c5ba7 13106 region = region->next;
13107 }
9561765e 13108 if (omp_any_child_fn_dumped)
13109 {
13110 if (dump_file)
13111 dump_function_header (dump_file, current_function_decl, dump_flags);
13112 omp_any_child_fn_dumped = false;
13113 }
773c5ba7 13114}
13115
13116
13117/* Helper for build_omp_regions. Scan the dominator tree starting at
28c92cbb 13118 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
13119 true, the function ends once a single tree is built (otherwise, whole
13120 forest of OMP constructs may be built). */
773c5ba7 13121
13122static void
28c92cbb 13123build_omp_regions_1 (basic_block bb, struct omp_region *parent,
13124 bool single_tree)
773c5ba7 13125{
75a70cf9 13126 gimple_stmt_iterator gsi;
42acab1c 13127 gimple *stmt;
773c5ba7 13128 basic_block son;
13129
75a70cf9 13130 gsi = gsi_last_bb (bb);
13131 if (!gsi_end_p (gsi) && is_gimple_omp (gsi_stmt (gsi)))
773c5ba7 13132 {
13133 struct omp_region *region;
75a70cf9 13134 enum gimple_code code;
773c5ba7 13135
75a70cf9 13136 stmt = gsi_stmt (gsi);
13137 code = gimple_code (stmt);
13138 if (code == GIMPLE_OMP_RETURN)
773c5ba7 13139 {
13140 /* STMT is the return point out of region PARENT. Mark it
13141 as the exit point and make PARENT the immediately
13142 enclosing region. */
13143 gcc_assert (parent);
13144 region = parent;
61e47ac8 13145 region->exit = bb;
773c5ba7 13146 parent = parent->outer;
773c5ba7 13147 }
75a70cf9 13148 else if (code == GIMPLE_OMP_ATOMIC_STORE)
cb7f680b 13149 {
75a70cf9 13150 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
13151 GIMPLE_OMP_RETURN, but matches with
13152 GIMPLE_OMP_ATOMIC_LOAD. */
cb7f680b 13153 gcc_assert (parent);
75a70cf9 13154 gcc_assert (parent->type == GIMPLE_OMP_ATOMIC_LOAD);
cb7f680b 13155 region = parent;
13156 region->exit = bb;
13157 parent = parent->outer;
13158 }
75a70cf9 13159 else if (code == GIMPLE_OMP_CONTINUE)
61e47ac8 13160 {
13161 gcc_assert (parent);
13162 parent->cont = bb;
13163 }
75a70cf9 13164 else if (code == GIMPLE_OMP_SECTIONS_SWITCH)
ac6e3339 13165 {
75a70cf9 13166 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
13167 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
ac6e3339 13168 }
773c5ba7 13169 else
13170 {
61e47ac8 13171 region = new_omp_region (bb, code, parent);
ca4c3545 13172 /* Otherwise... */
13173 if (code == GIMPLE_OMP_TARGET)
13174 {
13175 switch (gimple_omp_target_kind (stmt))
13176 {
13177 case GF_OMP_TARGET_KIND_REGION:
13178 case GF_OMP_TARGET_KIND_DATA:
13179 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
13180 case GF_OMP_TARGET_KIND_OACC_KERNELS:
13181 case GF_OMP_TARGET_KIND_OACC_DATA:
13182 break;
13183 case GF_OMP_TARGET_KIND_UPDATE:
43895be5 13184 case GF_OMP_TARGET_KIND_ENTER_DATA:
13185 case GF_OMP_TARGET_KIND_EXIT_DATA:
ca4c3545 13186 case GF_OMP_TARGET_KIND_OACC_UPDATE:
13187 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
2fc5e987 13188 case GF_OMP_TARGET_KIND_OACC_DECLARE:
ca4c3545 13189 /* ..., other than for those stand-alone directives... */
13190 region = NULL;
13191 break;
13192 default:
13193 gcc_unreachable ();
13194 }
13195 }
43895be5 13196 else if (code == GIMPLE_OMP_ORDERED
13197 && find_omp_clause (gimple_omp_ordered_clauses
13198 (as_a <gomp_ordered *> (stmt)),
13199 OMP_CLAUSE_DEPEND))
13200 /* #pragma omp ordered depend is also just a stand-alone
13201 directive. */
13202 region = NULL;
ca4c3545 13203 /* ..., this directive becomes the parent for a new region. */
13204 if (region)
13205 parent = region;
773c5ba7 13206 }
773c5ba7 13207 }
13208
28c92cbb 13209 if (single_tree && !parent)
13210 return;
13211
773c5ba7 13212 for (son = first_dom_son (CDI_DOMINATORS, bb);
13213 son;
13214 son = next_dom_son (CDI_DOMINATORS, son))
28c92cbb 13215 build_omp_regions_1 (son, parent, single_tree);
13216}
13217
13218/* Builds the tree of OMP regions rooted at ROOT, storing it to
13219 root_omp_region. */
13220
13221static void
13222build_omp_regions_root (basic_block root)
13223{
13224 gcc_assert (root_omp_region == NULL);
13225 build_omp_regions_1 (root, NULL, true);
13226 gcc_assert (root_omp_region != NULL);
773c5ba7 13227}
13228
28c92cbb 13229/* Expands omp construct (and its subconstructs) starting in HEAD. */
13230
13231void
13232omp_expand_local (basic_block head)
13233{
13234 build_omp_regions_root (head);
13235 if (dump_file && (dump_flags & TDF_DETAILS))
13236 {
13237 fprintf (dump_file, "\nOMP region tree\n\n");
13238 dump_omp_region (dump_file, root_omp_region, 0);
13239 fprintf (dump_file, "\n");
13240 }
13241
13242 remove_exit_barriers (root_omp_region);
13243 expand_omp (root_omp_region);
13244
13245 free_omp_regions ();
13246}
773c5ba7 13247
13248/* Scan the CFG and build a tree of OMP regions. Return the root of
13249 the OMP region tree. */
13250
13251static void
13252build_omp_regions (void)
13253{
61e47ac8 13254 gcc_assert (root_omp_region == NULL);
773c5ba7 13255 calculate_dominance_info (CDI_DOMINATORS);
34154e27 13256 build_omp_regions_1 (ENTRY_BLOCK_PTR_FOR_FN (cfun), NULL, false);
773c5ba7 13257}
13258
773c5ba7 13259/* Main entry point for expanding OMP-GIMPLE into runtime calls. */
13260
2a1990e9 13261static unsigned int
773c5ba7 13262execute_expand_omp (void)
13263{
13264 build_omp_regions ();
13265
61e47ac8 13266 if (!root_omp_region)
13267 return 0;
773c5ba7 13268
61e47ac8 13269 if (dump_file)
13270 {
13271 fprintf (dump_file, "\nOMP region tree\n\n");
13272 dump_omp_region (dump_file, root_omp_region, 0);
13273 fprintf (dump_file, "\n");
773c5ba7 13274 }
61e47ac8 13275
13276 remove_exit_barriers (root_omp_region);
13277
13278 expand_omp (root_omp_region);
13279
382ecba7 13280 if (flag_checking && !loops_state_satisfies_p (LOOPS_NEED_FIXUP))
86a932e0 13281 verify_loop_structure ();
61e47ac8 13282 cleanup_tree_cfg ();
13283
13284 free_omp_regions ();
13285
2a1990e9 13286 return 0;
773c5ba7 13287}
13288
79acaae1 13289/* OMP expansion -- the default pass, run before creation of SSA form. */
13290
7620bc82 13291namespace {
13292
13293const pass_data pass_data_expand_omp =
cbe8bda8 13294{
13295 GIMPLE_PASS, /* type */
13296 "ompexp", /* name */
13297 OPTGROUP_NONE, /* optinfo_flags */
cbe8bda8 13298 TV_NONE, /* tv_id */
13299 PROP_gimple_any, /* properties_required */
8917c50b 13300 PROP_gimple_eomp, /* properties_provided */
cbe8bda8 13301 0, /* properties_destroyed */
13302 0, /* todo_flags_start */
13303 0, /* todo_flags_finish */
773c5ba7 13304};
cbe8bda8 13305
7620bc82 13306class pass_expand_omp : public gimple_opt_pass
cbe8bda8 13307{
13308public:
9af5ce0c 13309 pass_expand_omp (gcc::context *ctxt)
13310 : gimple_opt_pass (pass_data_expand_omp, ctxt)
cbe8bda8 13311 {}
13312
13313 /* opt_pass methods: */
8917c50b 13314 virtual unsigned int execute (function *)
31315c24 13315 {
ca4c3545 13316 bool gate = ((flag_cilkplus != 0 || flag_openacc != 0 || flag_openmp != 0
13317 || flag_openmp_simd != 0)
13318 && !seen_error ());
31315c24 13319
8917c50b 13320 /* This pass always runs, to provide PROP_gimple_eomp.
ca4c3545 13321 But often, there is nothing to do. */
8917c50b 13322 if (!gate)
13323 return 0;
13324
13325 return execute_expand_omp ();
13326 }
cbe8bda8 13327
13328}; // class pass_expand_omp
13329
7620bc82 13330} // anon namespace
13331
cbe8bda8 13332gimple_opt_pass *
13333make_pass_expand_omp (gcc::context *ctxt)
13334{
13335 return new pass_expand_omp (ctxt);
13336}
8917c50b 13337
7620bc82 13338namespace {
13339
13340const pass_data pass_data_expand_omp_ssa =
8917c50b 13341{
13342 GIMPLE_PASS, /* type */
13343 "ompexpssa", /* name */
13344 OPTGROUP_NONE, /* optinfo_flags */
13345 TV_NONE, /* tv_id */
13346 PROP_cfg | PROP_ssa, /* properties_required */
13347 PROP_gimple_eomp, /* properties_provided */
13348 0, /* properties_destroyed */
13349 0, /* todo_flags_start */
13350 TODO_cleanup_cfg | TODO_rebuild_alias, /* todo_flags_finish */
13351};
13352
7620bc82 13353class pass_expand_omp_ssa : public gimple_opt_pass
8917c50b 13354{
13355public:
13356 pass_expand_omp_ssa (gcc::context *ctxt)
13357 : gimple_opt_pass (pass_data_expand_omp_ssa, ctxt)
13358 {}
13359
13360 /* opt_pass methods: */
13361 virtual bool gate (function *fun)
13362 {
13363 return !(fun->curr_properties & PROP_gimple_eomp);
13364 }
13365 virtual unsigned int execute (function *) { return execute_expand_omp (); }
13366
13367}; // class pass_expand_omp_ssa
13368
7620bc82 13369} // anon namespace
13370
8917c50b 13371gimple_opt_pass *
13372make_pass_expand_omp_ssa (gcc::context *ctxt)
13373{
13374 return new pass_expand_omp_ssa (ctxt);
13375}
773c5ba7 13376\f
ca4c3545 13377/* Routines to lower OMP directives into OMP-GIMPLE. */
13378
bc7bff74 13379/* If ctx is a worksharing context inside of a cancellable parallel
13380 region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
13381 and conditional branch to parallel's cancel_label to handle
13382 cancellation in the implicit barrier. */
13383
13384static void
13385maybe_add_implicit_barrier_cancel (omp_context *ctx, gimple_seq *body)
13386{
42acab1c 13387 gimple *omp_return = gimple_seq_last_stmt (*body);
bc7bff74 13388 gcc_assert (gimple_code (omp_return) == GIMPLE_OMP_RETURN);
13389 if (gimple_omp_return_nowait_p (omp_return))
13390 return;
13391 if (ctx->outer
13392 && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_PARALLEL
13393 && ctx->outer->cancellable)
13394 {
15b28553 13395 tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL);
13396 tree c_bool_type = TREE_TYPE (TREE_TYPE (fndecl));
f9e245b2 13397 tree lhs = create_tmp_var (c_bool_type);
bc7bff74 13398 gimple_omp_return_set_lhs (omp_return, lhs);
13399 tree fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
42acab1c 13400 gimple *g = gimple_build_cond (NE_EXPR, lhs,
15b28553 13401 fold_convert (c_bool_type,
13402 boolean_false_node),
bc7bff74 13403 ctx->outer->cancel_label, fallthru_label);
13404 gimple_seq_add_stmt (body, g);
13405 gimple_seq_add_stmt (body, gimple_build_label (fallthru_label));
13406 }
13407}
13408
75a70cf9 13409/* Lower the OpenMP sections directive in the current statement in GSI_P.
13410 CTX is the enclosing OMP context for the current statement. */
773c5ba7 13411
13412static void
75a70cf9 13413lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
773c5ba7 13414{
75a70cf9 13415 tree block, control;
13416 gimple_stmt_iterator tgsi;
1a91d914 13417 gomp_sections *stmt;
42acab1c 13418 gimple *t;
1a91d914 13419 gbind *new_stmt, *bind;
e3a19533 13420 gimple_seq ilist, dlist, olist, new_body;
773c5ba7 13421
1a91d914 13422 stmt = as_a <gomp_sections *> (gsi_stmt (*gsi_p));
773c5ba7 13423
8a4a28a8 13424 push_gimplify_context ();
773c5ba7 13425
13426 dlist = NULL;
13427 ilist = NULL;
75a70cf9 13428 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
bc7bff74 13429 &ilist, &dlist, ctx, NULL);
773c5ba7 13430
e3a19533 13431 new_body = gimple_omp_body (stmt);
13432 gimple_omp_set_body (stmt, NULL);
13433 tgsi = gsi_start (new_body);
13434 for (; !gsi_end_p (tgsi); gsi_next (&tgsi))
773c5ba7 13435 {
13436 omp_context *sctx;
42acab1c 13437 gimple *sec_start;
773c5ba7 13438
75a70cf9 13439 sec_start = gsi_stmt (tgsi);
773c5ba7 13440 sctx = maybe_lookup_ctx (sec_start);
13441 gcc_assert (sctx);
13442
e3a19533 13443 lower_omp (gimple_omp_body_ptr (sec_start), sctx);
13444 gsi_insert_seq_after (&tgsi, gimple_omp_body (sec_start),
13445 GSI_CONTINUE_LINKING);
75a70cf9 13446 gimple_omp_set_body (sec_start, NULL);
773c5ba7 13447
e3a19533 13448 if (gsi_one_before_end_p (tgsi))
773c5ba7 13449 {
75a70cf9 13450 gimple_seq l = NULL;
13451 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
773c5ba7 13452 &l, ctx);
e3a19533 13453 gsi_insert_seq_after (&tgsi, l, GSI_CONTINUE_LINKING);
75a70cf9 13454 gimple_omp_section_set_last (sec_start);
773c5ba7 13455 }
48e1416a 13456
e3a19533 13457 gsi_insert_after (&tgsi, gimple_build_omp_return (false),
13458 GSI_CONTINUE_LINKING);
773c5ba7 13459 }
1e8e9920 13460
13461 block = make_node (BLOCK);
e3a19533 13462 bind = gimple_build_bind (NULL, new_body, block);
1e8e9920 13463
75a70cf9 13464 olist = NULL;
13465 lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist, ctx);
773c5ba7 13466
1d22f541 13467 block = make_node (BLOCK);
75a70cf9 13468 new_stmt = gimple_build_bind (NULL, NULL, block);
e3a19533 13469 gsi_replace (gsi_p, new_stmt, true);
773c5ba7 13470
1d22f541 13471 pop_gimplify_context (new_stmt);
75a70cf9 13472 gimple_bind_append_vars (new_stmt, ctx->block_vars);
13473 BLOCK_VARS (block) = gimple_bind_vars (bind);
1d22f541 13474 if (BLOCK_VARS (block))
13475 TREE_USED (block) = 1;
13476
75a70cf9 13477 new_body = NULL;
13478 gimple_seq_add_seq (&new_body, ilist);
13479 gimple_seq_add_stmt (&new_body, stmt);
13480 gimple_seq_add_stmt (&new_body, gimple_build_omp_sections_switch ());
13481 gimple_seq_add_stmt (&new_body, bind);
61e47ac8 13482
ac6e3339 13483 control = create_tmp_var (unsigned_type_node, ".section");
75a70cf9 13484 t = gimple_build_omp_continue (control, control);
13485 gimple_omp_sections_set_control (stmt, control);
13486 gimple_seq_add_stmt (&new_body, t);
61e47ac8 13487
75a70cf9 13488 gimple_seq_add_seq (&new_body, olist);
bc7bff74 13489 if (ctx->cancellable)
13490 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
75a70cf9 13491 gimple_seq_add_seq (&new_body, dlist);
773c5ba7 13492
75a70cf9 13493 new_body = maybe_catch_exception (new_body);
aade31a0 13494
75a70cf9 13495 t = gimple_build_omp_return
13496 (!!find_omp_clause (gimple_omp_sections_clauses (stmt),
13497 OMP_CLAUSE_NOWAIT));
13498 gimple_seq_add_stmt (&new_body, t);
bc7bff74 13499 maybe_add_implicit_barrier_cancel (ctx, &new_body);
61e47ac8 13500
75a70cf9 13501 gimple_bind_set_body (new_stmt, new_body);
1e8e9920 13502}
13503
13504
773c5ba7 13505/* A subroutine of lower_omp_single. Expand the simple form of
75a70cf9 13506 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
1e8e9920 13507
13508 if (GOMP_single_start ())
13509 BODY;
13510 [ GOMP_barrier (); ] -> unless 'nowait' is present.
773c5ba7 13511
13512 FIXME. It may be better to delay expanding the logic of this until
13513 pass_expand_omp. The expanded logic may make the job more difficult
13514 to a synchronization analysis pass. */
1e8e9920 13515
13516static void
1a91d914 13517lower_omp_single_simple (gomp_single *single_stmt, gimple_seq *pre_p)
1e8e9920 13518{
e60a6f7b 13519 location_t loc = gimple_location (single_stmt);
13520 tree tlabel = create_artificial_label (loc);
13521 tree flabel = create_artificial_label (loc);
42acab1c 13522 gimple *call, *cond;
75a70cf9 13523 tree lhs, decl;
13524
b9a16870 13525 decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START);
f9e245b2 13526 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)));
75a70cf9 13527 call = gimple_build_call (decl, 0);
13528 gimple_call_set_lhs (call, lhs);
13529 gimple_seq_add_stmt (pre_p, call);
13530
13531 cond = gimple_build_cond (EQ_EXPR, lhs,
389dd41b 13532 fold_convert_loc (loc, TREE_TYPE (lhs),
13533 boolean_true_node),
75a70cf9 13534 tlabel, flabel);
13535 gimple_seq_add_stmt (pre_p, cond);
13536 gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
13537 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
13538 gimple_seq_add_stmt (pre_p, gimple_build_label (flabel));
1e8e9920 13539}
13540
773c5ba7 13541
13542/* A subroutine of lower_omp_single. Expand the simple form of
75a70cf9 13543 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
1e8e9920 13544
13545 #pragma omp single copyprivate (a, b, c)
13546
13547 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
13548
13549 {
13550 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
13551 {
13552 BODY;
13553 copyout.a = a;
13554 copyout.b = b;
13555 copyout.c = c;
13556 GOMP_single_copy_end (&copyout);
13557 }
13558 else
13559 {
13560 a = copyout_p->a;
13561 b = copyout_p->b;
13562 c = copyout_p->c;
13563 }
13564 GOMP_barrier ();
13565 }
773c5ba7 13566
13567 FIXME. It may be better to delay expanding the logic of this until
13568 pass_expand_omp. The expanded logic may make the job more difficult
13569 to a synchronization analysis pass. */
1e8e9920 13570
13571static void
1a91d914 13572lower_omp_single_copy (gomp_single *single_stmt, gimple_seq *pre_p,
13573 omp_context *ctx)
1e8e9920 13574{
b9a16870 13575 tree ptr_type, t, l0, l1, l2, bfn_decl;
75a70cf9 13576 gimple_seq copyin_seq;
e60a6f7b 13577 location_t loc = gimple_location (single_stmt);
1e8e9920 13578
13579 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
13580
13581 ptr_type = build_pointer_type (ctx->record_type);
13582 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
13583
e60a6f7b 13584 l0 = create_artificial_label (loc);
13585 l1 = create_artificial_label (loc);
13586 l2 = create_artificial_label (loc);
1e8e9920 13587
b9a16870 13588 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START);
13589 t = build_call_expr_loc (loc, bfn_decl, 0);
389dd41b 13590 t = fold_convert_loc (loc, ptr_type, t);
75a70cf9 13591 gimplify_assign (ctx->receiver_decl, t, pre_p);
1e8e9920 13592
13593 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
13594 build_int_cst (ptr_type, 0));
13595 t = build3 (COND_EXPR, void_type_node, t,
13596 build_and_jump (&l0), build_and_jump (&l1));
13597 gimplify_and_add (t, pre_p);
13598
75a70cf9 13599 gimple_seq_add_stmt (pre_p, gimple_build_label (l0));
1e8e9920 13600
75a70cf9 13601 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
1e8e9920 13602
13603 copyin_seq = NULL;
75a70cf9 13604 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
1e8e9920 13605 &copyin_seq, ctx);
13606
389dd41b 13607 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
b9a16870 13608 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END);
13609 t = build_call_expr_loc (loc, bfn_decl, 1, t);
1e8e9920 13610 gimplify_and_add (t, pre_p);
13611
13612 t = build_and_jump (&l2);
13613 gimplify_and_add (t, pre_p);
13614
75a70cf9 13615 gimple_seq_add_stmt (pre_p, gimple_build_label (l1));
1e8e9920 13616
75a70cf9 13617 gimple_seq_add_seq (pre_p, copyin_seq);
1e8e9920 13618
75a70cf9 13619 gimple_seq_add_stmt (pre_p, gimple_build_label (l2));
1e8e9920 13620}
13621
773c5ba7 13622
1e8e9920 13623/* Expand code for an OpenMP single directive. */
13624
13625static void
75a70cf9 13626lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
1e8e9920 13627{
75a70cf9 13628 tree block;
42acab1c 13629 gimple *t;
1a91d914 13630 gomp_single *single_stmt = as_a <gomp_single *> (gsi_stmt (*gsi_p));
13631 gbind *bind;
bc7bff74 13632 gimple_seq bind_body, bind_body_tail = NULL, dlist;
1e8e9920 13633
8a4a28a8 13634 push_gimplify_context ();
1e8e9920 13635
e3a19533 13636 block = make_node (BLOCK);
13637 bind = gimple_build_bind (NULL, NULL, block);
13638 gsi_replace (gsi_p, bind, true);
75a70cf9 13639 bind_body = NULL;
e3a19533 13640 dlist = NULL;
75a70cf9 13641 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt),
bc7bff74 13642 &bind_body, &dlist, ctx, NULL);
e3a19533 13643 lower_omp (gimple_omp_body_ptr (single_stmt), ctx);
1e8e9920 13644
75a70cf9 13645 gimple_seq_add_stmt (&bind_body, single_stmt);
1e8e9920 13646
13647 if (ctx->record_type)
75a70cf9 13648 lower_omp_single_copy (single_stmt, &bind_body, ctx);
1e8e9920 13649 else
75a70cf9 13650 lower_omp_single_simple (single_stmt, &bind_body);
13651
13652 gimple_omp_set_body (single_stmt, NULL);
1e8e9920 13653
75a70cf9 13654 gimple_seq_add_seq (&bind_body, dlist);
61e47ac8 13655
75a70cf9 13656 bind_body = maybe_catch_exception (bind_body);
61e47ac8 13657
48e1416a 13658 t = gimple_build_omp_return
75a70cf9 13659 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt),
13660 OMP_CLAUSE_NOWAIT));
bc7bff74 13661 gimple_seq_add_stmt (&bind_body_tail, t);
13662 maybe_add_implicit_barrier_cancel (ctx, &bind_body_tail);
13663 if (ctx->record_type)
13664 {
13665 gimple_stmt_iterator gsi = gsi_start (bind_body_tail);
13666 tree clobber = build_constructor (ctx->record_type, NULL);
13667 TREE_THIS_VOLATILE (clobber) = 1;
13668 gsi_insert_after (&gsi, gimple_build_assign (ctx->sender_decl,
13669 clobber), GSI_SAME_STMT);
13670 }
13671 gimple_seq_add_seq (&bind_body, bind_body_tail);
e3a19533 13672 gimple_bind_set_body (bind, bind_body);
61e47ac8 13673
1e8e9920 13674 pop_gimplify_context (bind);
773c5ba7 13675
75a70cf9 13676 gimple_bind_append_vars (bind, ctx->block_vars);
13677 BLOCK_VARS (block) = ctx->block_vars;
1d22f541 13678 if (BLOCK_VARS (block))
13679 TREE_USED (block) = 1;
1e8e9920 13680}
13681
773c5ba7 13682
1e8e9920 13683/* Expand code for an OpenMP master directive. */
13684
13685static void
75a70cf9 13686lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
1e8e9920 13687{
b9a16870 13688 tree block, lab = NULL, x, bfn_decl;
42acab1c 13689 gimple *stmt = gsi_stmt (*gsi_p);
1a91d914 13690 gbind *bind;
389dd41b 13691 location_t loc = gimple_location (stmt);
75a70cf9 13692 gimple_seq tseq;
1e8e9920 13693
8a4a28a8 13694 push_gimplify_context ();
1e8e9920 13695
13696 block = make_node (BLOCK);
e3a19533 13697 bind = gimple_build_bind (NULL, NULL, block);
13698 gsi_replace (gsi_p, bind, true);
13699 gimple_bind_add_stmt (bind, stmt);
61e47ac8 13700
b9a16870 13701 bfn_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
13702 x = build_call_expr_loc (loc, bfn_decl, 0);
1e8e9920 13703 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
13704 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
75a70cf9 13705 tseq = NULL;
13706 gimplify_and_add (x, &tseq);
13707 gimple_bind_add_seq (bind, tseq);
1e8e9920 13708
e3a19533 13709 lower_omp (gimple_omp_body_ptr (stmt), ctx);
75a70cf9 13710 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
13711 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
13712 gimple_omp_set_body (stmt, NULL);
1e8e9920 13713
75a70cf9 13714 gimple_bind_add_stmt (bind, gimple_build_label (lab));
61e47ac8 13715
75a70cf9 13716 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
61e47ac8 13717
1e8e9920 13718 pop_gimplify_context (bind);
773c5ba7 13719
75a70cf9 13720 gimple_bind_append_vars (bind, ctx->block_vars);
13721 BLOCK_VARS (block) = ctx->block_vars;
1e8e9920 13722}
13723
773c5ba7 13724
bc7bff74 13725/* Expand code for an OpenMP taskgroup directive. */
13726
13727static void
13728lower_omp_taskgroup (gimple_stmt_iterator *gsi_p, omp_context *ctx)
13729{
42acab1c 13730 gimple *stmt = gsi_stmt (*gsi_p);
1a91d914 13731 gcall *x;
13732 gbind *bind;
bc7bff74 13733 tree block = make_node (BLOCK);
13734
13735 bind = gimple_build_bind (NULL, NULL, block);
13736 gsi_replace (gsi_p, bind, true);
13737 gimple_bind_add_stmt (bind, stmt);
13738
13739 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START),
13740 0);
13741 gimple_bind_add_stmt (bind, x);
13742
13743 lower_omp (gimple_omp_body_ptr (stmt), ctx);
13744 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
13745 gimple_omp_set_body (stmt, NULL);
13746
13747 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
13748
13749 gimple_bind_append_vars (bind, ctx->block_vars);
13750 BLOCK_VARS (block) = ctx->block_vars;
13751}
13752
13753
43895be5 13754/* Fold the OMP_ORDERED_CLAUSES for the OMP_ORDERED in STMT if possible. */
13755
13756static void
13757lower_omp_ordered_clauses (gimple_stmt_iterator *gsi_p, gomp_ordered *ord_stmt,
13758 omp_context *ctx)
13759{
13760 struct omp_for_data fd;
13761 if (!ctx->outer || gimple_code (ctx->outer->stmt) != GIMPLE_OMP_FOR)
13762 return;
13763
13764 unsigned int len = gimple_omp_for_collapse (ctx->outer->stmt);
13765 struct omp_for_data_loop *loops = XALLOCAVEC (struct omp_for_data_loop, len);
13766 extract_omp_for_data (as_a <gomp_for *> (ctx->outer->stmt), &fd, loops);
13767 if (!fd.ordered)
13768 return;
13769
13770 tree *list_p = gimple_omp_ordered_clauses_ptr (ord_stmt);
13771 tree c = gimple_omp_ordered_clauses (ord_stmt);
13772 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
13773 && OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK)
13774 {
13775 /* Merge depend clauses from multiple adjacent
13776 #pragma omp ordered depend(sink:...) constructs
13777 into one #pragma omp ordered depend(sink:...), so that
13778 we can optimize them together. */
13779 gimple_stmt_iterator gsi = *gsi_p;
13780 gsi_next (&gsi);
13781 while (!gsi_end_p (gsi))
13782 {
13783 gimple *stmt = gsi_stmt (gsi);
13784 if (is_gimple_debug (stmt)
13785 || gimple_code (stmt) == GIMPLE_NOP)
13786 {
13787 gsi_next (&gsi);
13788 continue;
13789 }
13790 if (gimple_code (stmt) != GIMPLE_OMP_ORDERED)
13791 break;
13792 gomp_ordered *ord_stmt2 = as_a <gomp_ordered *> (stmt);
13793 c = gimple_omp_ordered_clauses (ord_stmt2);
13794 if (c == NULL_TREE
13795 || OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND
13796 || OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_SINK)
13797 break;
13798 while (*list_p)
13799 list_p = &OMP_CLAUSE_CHAIN (*list_p);
13800 *list_p = c;
13801 gsi_remove (&gsi, true);
13802 }
13803 }
13804
13805 /* Canonicalize sink dependence clauses into one folded clause if
13806 possible.
13807
13808 The basic algorithm is to create a sink vector whose first
13809 element is the GCD of all the first elements, and whose remaining
13810 elements are the minimum of the subsequent columns.
13811
13812 We ignore dependence vectors whose first element is zero because
13813 such dependencies are known to be executed by the same thread.
13814
13815 We take into account the direction of the loop, so a minimum
13816 becomes a maximum if the loop is iterating forwards. We also
13817 ignore sink clauses where the loop direction is unknown, or where
13818 the offsets are clearly invalid because they are not a multiple
13819 of the loop increment.
13820
13821 For example:
13822
13823 #pragma omp for ordered(2)
13824 for (i=0; i < N; ++i)
13825 for (j=0; j < M; ++j)
13826 {
13827 #pragma omp ordered \
13828 depend(sink:i-8,j-2) \
13829 depend(sink:i,j-1) \ // Completely ignored because i+0.
13830 depend(sink:i-4,j-3) \
13831 depend(sink:i-6,j-4)
13832 #pragma omp ordered depend(source)
13833 }
13834
13835 Folded clause is:
13836
13837 depend(sink:-gcd(8,4,6),-min(2,3,4))
13838 -or-
13839 depend(sink:-2,-2)
13840 */
13841
13842 /* FIXME: Computing GCD's where the first element is zero is
13843 non-trivial in the presence of collapsed loops. Do this later. */
13844 if (fd.collapse > 1)
13845 return;
13846
13847 wide_int *folded_deps = XALLOCAVEC (wide_int, 2 * len - 1);
13848 memset (folded_deps, 0, sizeof (*folded_deps) * (2 * len - 1));
13849 tree folded_dep = NULL_TREE;
13850 /* TRUE if the first dimension's offset is negative. */
13851 bool neg_offset_p = false;
13852
13853 list_p = gimple_omp_ordered_clauses_ptr (ord_stmt);
13854 unsigned int i;
13855 while ((c = *list_p) != NULL)
13856 {
13857 bool remove = false;
13858
13859 gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND);
13860 if (OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_SINK)
13861 goto next_ordered_clause;
13862
13863 tree vec;
13864 for (vec = OMP_CLAUSE_DECL (c), i = 0;
13865 vec && TREE_CODE (vec) == TREE_LIST;
13866 vec = TREE_CHAIN (vec), ++i)
13867 {
13868 gcc_assert (i < len);
13869
13870 /* extract_omp_for_data has canonicalized the condition. */
13871 gcc_assert (fd.loops[i].cond_code == LT_EXPR
13872 || fd.loops[i].cond_code == GT_EXPR);
13873 bool forward = fd.loops[i].cond_code == LT_EXPR;
13874 bool maybe_lexically_later = true;
13875
13876 /* While the committee makes up its mind, bail if we have any
13877 non-constant steps. */
13878 if (TREE_CODE (fd.loops[i].step) != INTEGER_CST)
13879 goto lower_omp_ordered_ret;
13880
13881 tree itype = TREE_TYPE (TREE_VALUE (vec));
13882 if (POINTER_TYPE_P (itype))
13883 itype = sizetype;
13884 wide_int offset = wide_int::from (TREE_PURPOSE (vec),
13885 TYPE_PRECISION (itype),
13886 TYPE_SIGN (itype));
13887
13888 /* Ignore invalid offsets that are not multiples of the step. */
13889 if (!wi::multiple_of_p
13890 (wi::abs (offset), wi::abs ((wide_int) fd.loops[i].step),
13891 UNSIGNED))
13892 {
13893 warning_at (OMP_CLAUSE_LOCATION (c), 0,
13894 "ignoring sink clause with offset that is not "
13895 "a multiple of the loop step");
13896 remove = true;
13897 goto next_ordered_clause;
13898 }
13899
13900 /* Calculate the first dimension. The first dimension of
13901 the folded dependency vector is the GCD of the first
13902 elements, while ignoring any first elements whose offset
13903 is 0. */
13904 if (i == 0)
13905 {
13906 /* Ignore dependence vectors whose first dimension is 0. */
13907 if (offset == 0)
13908 {
13909 remove = true;
13910 goto next_ordered_clause;
13911 }
13912 else
13913 {
13914 if (!TYPE_UNSIGNED (itype) && (forward ^ wi::neg_p (offset)))
13915 {
13916 error_at (OMP_CLAUSE_LOCATION (c),
13917 "first offset must be in opposite direction "
13918 "of loop iterations");
13919 goto lower_omp_ordered_ret;
13920 }
13921 if (forward)
13922 offset = -offset;
13923 neg_offset_p = forward;
13924 /* Initialize the first time around. */
13925 if (folded_dep == NULL_TREE)
13926 {
13927 folded_dep = c;
13928 folded_deps[0] = offset;
13929 }
13930 else
13931 folded_deps[0] = wi::gcd (folded_deps[0],
13932 offset, UNSIGNED);
13933 }
13934 }
13935 /* Calculate minimum for the remaining dimensions. */
13936 else
13937 {
13938 folded_deps[len + i - 1] = offset;
13939 if (folded_dep == c)
13940 folded_deps[i] = offset;
13941 else if (maybe_lexically_later
13942 && !wi::eq_p (folded_deps[i], offset))
13943 {
13944 if (forward ^ wi::gts_p (folded_deps[i], offset))
13945 {
13946 unsigned int j;
13947 folded_dep = c;
13948 for (j = 1; j <= i; j++)
13949 folded_deps[j] = folded_deps[len + j - 1];
13950 }
13951 else
13952 maybe_lexically_later = false;
13953 }
13954 }
13955 }
13956 gcc_assert (i == len);
13957
13958 remove = true;
13959
13960 next_ordered_clause:
13961 if (remove)
13962 *list_p = OMP_CLAUSE_CHAIN (c);
13963 else
13964 list_p = &OMP_CLAUSE_CHAIN (c);
13965 }
13966
13967 if (folded_dep)
13968 {
13969 if (neg_offset_p)
13970 folded_deps[0] = -folded_deps[0];
13971
13972 tree itype = TREE_TYPE (TREE_VALUE (OMP_CLAUSE_DECL (folded_dep)));
13973 if (POINTER_TYPE_P (itype))
13974 itype = sizetype;
13975
13976 TREE_PURPOSE (OMP_CLAUSE_DECL (folded_dep))
13977 = wide_int_to_tree (itype, folded_deps[0]);
13978 OMP_CLAUSE_CHAIN (folded_dep) = gimple_omp_ordered_clauses (ord_stmt);
13979 *gimple_omp_ordered_clauses_ptr (ord_stmt) = folded_dep;
13980 }
13981
13982 lower_omp_ordered_ret:
13983
13984 /* Ordered without clauses is #pragma omp threads, while we want
13985 a nop instead if we remove all clauses. */
13986 if (gimple_omp_ordered_clauses (ord_stmt) == NULL_TREE)
13987 gsi_replace (gsi_p, gimple_build_nop (), true);
13988}
13989
13990
1e8e9920 13991/* Expand code for an OpenMP ordered directive. */
13992
13993static void
75a70cf9 13994lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
1e8e9920 13995{
75a70cf9 13996 tree block;
42acab1c 13997 gimple *stmt = gsi_stmt (*gsi_p);
43895be5 13998 gomp_ordered *ord_stmt = as_a <gomp_ordered *> (stmt);
1a91d914 13999 gcall *x;
14000 gbind *bind;
a9833286 14001 bool simd = find_omp_clause (gimple_omp_ordered_clauses (ord_stmt),
14002 OMP_CLAUSE_SIMD);
14003 bool threads = find_omp_clause (gimple_omp_ordered_clauses (ord_stmt),
14004 OMP_CLAUSE_THREADS);
43895be5 14005
14006 if (find_omp_clause (gimple_omp_ordered_clauses (ord_stmt),
14007 OMP_CLAUSE_DEPEND))
14008 {
14009 /* FIXME: This is needs to be moved to the expansion to verify various
14010 conditions only testable on cfg with dominators computed, and also
14011 all the depend clauses to be merged still might need to be available
14012 for the runtime checks. */
14013 if (0)
14014 lower_omp_ordered_clauses (gsi_p, ord_stmt, ctx);
14015 return;
14016 }
1e8e9920 14017
8a4a28a8 14018 push_gimplify_context ();
1e8e9920 14019
14020 block = make_node (BLOCK);
e3a19533 14021 bind = gimple_build_bind (NULL, NULL, block);
14022 gsi_replace (gsi_p, bind, true);
14023 gimple_bind_add_stmt (bind, stmt);
61e47ac8 14024
43895be5 14025 if (simd)
14026 {
a9833286 14027 x = gimple_build_call_internal (IFN_GOMP_SIMD_ORDERED_START, 1,
14028 build_int_cst (NULL_TREE, threads));
43895be5 14029 cfun->has_simduid_loops = true;
14030 }
14031 else
14032 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START),
14033 0);
75a70cf9 14034 gimple_bind_add_stmt (bind, x);
1e8e9920 14035
e3a19533 14036 lower_omp (gimple_omp_body_ptr (stmt), ctx);
75a70cf9 14037 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
14038 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
14039 gimple_omp_set_body (stmt, NULL);
1e8e9920 14040
43895be5 14041 if (simd)
a9833286 14042 x = gimple_build_call_internal (IFN_GOMP_SIMD_ORDERED_END, 1,
14043 build_int_cst (NULL_TREE, threads));
43895be5 14044 else
14045 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END),
14046 0);
75a70cf9 14047 gimple_bind_add_stmt (bind, x);
61e47ac8 14048
75a70cf9 14049 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
61e47ac8 14050
1e8e9920 14051 pop_gimplify_context (bind);
773c5ba7 14052
75a70cf9 14053 gimple_bind_append_vars (bind, ctx->block_vars);
14054 BLOCK_VARS (block) = gimple_bind_vars (bind);
1e8e9920 14055}
14056
1e8e9920 14057
75a70cf9 14058/* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
1e8e9920 14059 substitution of a couple of function calls. But in the NAMED case,
14060 requires that languages coordinate a symbol name. It is therefore
14061 best put here in common code. */
14062
d4786b13 14063static GTY(()) hash_map<tree, tree> *critical_name_mutexes;
1e8e9920 14064
14065static void
75a70cf9 14066lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
1e8e9920 14067{
75a70cf9 14068 tree block;
14069 tree name, lock, unlock;
1a91d914 14070 gomp_critical *stmt = as_a <gomp_critical *> (gsi_stmt (*gsi_p));
14071 gbind *bind;
389dd41b 14072 location_t loc = gimple_location (stmt);
75a70cf9 14073 gimple_seq tbody;
1e8e9920 14074
75a70cf9 14075 name = gimple_omp_critical_name (stmt);
1e8e9920 14076 if (name)
14077 {
c2f47e15 14078 tree decl;
1e8e9920 14079
14080 if (!critical_name_mutexes)
d4786b13 14081 critical_name_mutexes = hash_map<tree, tree>::create_ggc (10);
1e8e9920 14082
d4786b13 14083 tree *n = critical_name_mutexes->get (name);
1e8e9920 14084 if (n == NULL)
14085 {
14086 char *new_str;
14087
f9e245b2 14088 decl = create_tmp_var_raw (ptr_type_node);
1e8e9920 14089
14090 new_str = ACONCAT ((".gomp_critical_user_",
14091 IDENTIFIER_POINTER (name), NULL));
14092 DECL_NAME (decl) = get_identifier (new_str);
14093 TREE_PUBLIC (decl) = 1;
14094 TREE_STATIC (decl) = 1;
14095 DECL_COMMON (decl) = 1;
14096 DECL_ARTIFICIAL (decl) = 1;
14097 DECL_IGNORED_P (decl) = 1;
b0c5e347 14098
97221fd7 14099 varpool_node::finalize_decl (decl);
1e8e9920 14100
d4786b13 14101 critical_name_mutexes->put (name, decl);
1e8e9920 14102 }
14103 else
d4786b13 14104 decl = *n;
1e8e9920 14105
ca4c3545 14106 /* If '#pragma omp critical' is inside offloaded region or
351fb0ce 14107 inside function marked as offloadable, the symbol must be
14108 marked as offloadable too. */
14109 omp_context *octx;
14110 if (cgraph_node::get (current_function_decl)->offloadable)
14111 varpool_node::get_create (decl)->offloadable = 1;
14112 else
14113 for (octx = ctx->outer; octx; octx = octx->outer)
ca4c3545 14114 if (is_gimple_omp_offloaded (octx->stmt))
351fb0ce 14115 {
14116 varpool_node::get_create (decl)->offloadable = 1;
14117 break;
14118 }
14119
b9a16870 14120 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START);
389dd41b 14121 lock = build_call_expr_loc (loc, lock, 1, build_fold_addr_expr_loc (loc, decl));
1e8e9920 14122
b9a16870 14123 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END);
389dd41b 14124 unlock = build_call_expr_loc (loc, unlock, 1,
14125 build_fold_addr_expr_loc (loc, decl));
1e8e9920 14126 }
14127 else
14128 {
b9a16870 14129 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START);
389dd41b 14130 lock = build_call_expr_loc (loc, lock, 0);
1e8e9920 14131
b9a16870 14132 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END);
389dd41b 14133 unlock = build_call_expr_loc (loc, unlock, 0);
1e8e9920 14134 }
14135
8a4a28a8 14136 push_gimplify_context ();
1e8e9920 14137
14138 block = make_node (BLOCK);
e3a19533 14139 bind = gimple_build_bind (NULL, NULL, block);
14140 gsi_replace (gsi_p, bind, true);
14141 gimple_bind_add_stmt (bind, stmt);
61e47ac8 14142
75a70cf9 14143 tbody = gimple_bind_body (bind);
14144 gimplify_and_add (lock, &tbody);
14145 gimple_bind_set_body (bind, tbody);
1e8e9920 14146
e3a19533 14147 lower_omp (gimple_omp_body_ptr (stmt), ctx);
75a70cf9 14148 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
14149 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
14150 gimple_omp_set_body (stmt, NULL);
1e8e9920 14151
75a70cf9 14152 tbody = gimple_bind_body (bind);
14153 gimplify_and_add (unlock, &tbody);
14154 gimple_bind_set_body (bind, tbody);
61e47ac8 14155
75a70cf9 14156 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
1e8e9920 14157
14158 pop_gimplify_context (bind);
75a70cf9 14159 gimple_bind_append_vars (bind, ctx->block_vars);
14160 BLOCK_VARS (block) = gimple_bind_vars (bind);
773c5ba7 14161}
14162
14163
14164/* A subroutine of lower_omp_for. Generate code to emit the predicate
14165 for a lastprivate clause. Given a loop control predicate of (V
14166 cond N2), we gate the clause on (!(V cond N2)). The lowered form
1e4afe3c 14167 is appended to *DLIST, iterator initialization is appended to
14168 *BODY_P. */
773c5ba7 14169
14170static void
75a70cf9 14171lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
14172 gimple_seq *dlist, struct omp_context *ctx)
773c5ba7 14173{
75a70cf9 14174 tree clauses, cond, vinit;
773c5ba7 14175 enum tree_code cond_code;
75a70cf9 14176 gimple_seq stmts;
48e1416a 14177
fd6481cf 14178 cond_code = fd->loop.cond_code;
773c5ba7 14179 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
14180
14181 /* When possible, use a strict equality expression. This can let VRP
14182 type optimizations deduce the value and remove a copy. */
e913b5cd 14183 if (tree_fits_shwi_p (fd->loop.step))
773c5ba7 14184 {
e913b5cd 14185 HOST_WIDE_INT step = tree_to_shwi (fd->loop.step);
773c5ba7 14186 if (step == 1 || step == -1)
14187 cond_code = EQ_EXPR;
14188 }
14189
d7729e26 14190 tree n2 = fd->loop.n2;
14191 if (fd->collapse > 1
14192 && TREE_CODE (n2) != INTEGER_CST
43895be5 14193 && gimple_omp_for_combined_into_p (fd->for_stmt))
d7729e26 14194 {
9561765e 14195 struct omp_context *taskreg_ctx = NULL;
43895be5 14196 if (gimple_code (ctx->outer->stmt) == GIMPLE_OMP_FOR)
14197 {
14198 gomp_for *gfor = as_a <gomp_for *> (ctx->outer->stmt);
9561765e 14199 if (gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_FOR
14200 || gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_DISTRIBUTE)
43895be5 14201 {
9561765e 14202 if (gimple_omp_for_combined_into_p (gfor))
14203 {
14204 gcc_assert (ctx->outer->outer
14205 && is_parallel_ctx (ctx->outer->outer));
14206 taskreg_ctx = ctx->outer->outer;
14207 }
14208 else
14209 {
14210 struct omp_for_data outer_fd;
14211 extract_omp_for_data (gfor, &outer_fd, NULL);
14212 n2 = fold_convert (TREE_TYPE (n2), outer_fd.loop.n2);
14213 }
43895be5 14214 }
14215 else if (gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_TASKLOOP)
9561765e 14216 taskreg_ctx = ctx->outer->outer;
43895be5 14217 }
9561765e 14218 else if (is_taskreg_ctx (ctx->outer))
14219 taskreg_ctx = ctx->outer;
14220 if (taskreg_ctx)
d7729e26 14221 {
43895be5 14222 int i;
14223 tree innerc
9561765e 14224 = find_omp_clause (gimple_omp_taskreg_clauses (taskreg_ctx->stmt),
43895be5 14225 OMP_CLAUSE__LOOPTEMP_);
14226 gcc_assert (innerc);
14227 for (i = 0; i < fd->collapse; i++)
14228 {
14229 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
14230 OMP_CLAUSE__LOOPTEMP_);
14231 gcc_assert (innerc);
14232 }
14233 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
14234 OMP_CLAUSE__LOOPTEMP_);
14235 if (innerc)
14236 n2 = fold_convert (TREE_TYPE (n2),
14237 lookup_decl (OMP_CLAUSE_DECL (innerc),
9561765e 14238 taskreg_ctx));
d7729e26 14239 }
14240 }
14241 cond = build2 (cond_code, boolean_type_node, fd->loop.v, n2);
773c5ba7 14242
75a70cf9 14243 clauses = gimple_omp_for_clauses (fd->for_stmt);
1e4afe3c 14244 stmts = NULL;
14245 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
75a70cf9 14246 if (!gimple_seq_empty_p (stmts))
1e4afe3c 14247 {
75a70cf9 14248 gimple_seq_add_seq (&stmts, *dlist);
fd6481cf 14249 *dlist = stmts;
1e4afe3c 14250
14251 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
fd6481cf 14252 vinit = fd->loop.n1;
1e4afe3c 14253 if (cond_code == EQ_EXPR
e913b5cd 14254 && tree_fits_shwi_p (fd->loop.n2)
fd6481cf 14255 && ! integer_zerop (fd->loop.n2))
14256 vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0);
3d483a94 14257 else
14258 vinit = unshare_expr (vinit);
1e4afe3c 14259
14260 /* Initialize the iterator variable, so that threads that don't execute
14261 any iterations don't execute the lastprivate clauses by accident. */
75a70cf9 14262 gimplify_assign (fd->loop.v, vinit, body_p);
1e4afe3c 14263 }
773c5ba7 14264}
14265
14266
ca4c3545 14267/* Lower code for an OMP loop directive. */
773c5ba7 14268
14269static void
75a70cf9 14270lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
773c5ba7 14271{
75a70cf9 14272 tree *rhs_p, block;
bc7bff74 14273 struct omp_for_data fd, *fdp = NULL;
1a91d914 14274 gomp_for *stmt = as_a <gomp_for *> (gsi_stmt (*gsi_p));
14275 gbind *new_stmt;
f018d957 14276 gimple_seq omp_for_body, body, dlist;
a8e785ba 14277 gimple_seq oacc_head = NULL, oacc_tail = NULL;
75a70cf9 14278 size_t i;
773c5ba7 14279
8a4a28a8 14280 push_gimplify_context ();
773c5ba7 14281
e3a19533 14282 lower_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
773c5ba7 14283
1d22f541 14284 block = make_node (BLOCK);
75a70cf9 14285 new_stmt = gimple_build_bind (NULL, NULL, block);
e3a19533 14286 /* Replace at gsi right away, so that 'stmt' is no member
47ae02b7 14287 of a sequence anymore as we're going to add to a different
e3a19533 14288 one below. */
14289 gsi_replace (gsi_p, new_stmt, true);
1d22f541 14290
773c5ba7 14291 /* Move declaration of temporaries in the loop body before we make
14292 it go away. */
75a70cf9 14293 omp_for_body = gimple_omp_body (stmt);
14294 if (!gimple_seq_empty_p (omp_for_body)
14295 && gimple_code (gimple_seq_first_stmt (omp_for_body)) == GIMPLE_BIND)
14296 {
1a91d914 14297 gbind *inner_bind
14298 = as_a <gbind *> (gimple_seq_first_stmt (omp_for_body));
6d5a8d89 14299 tree vars = gimple_bind_vars (inner_bind);
75a70cf9 14300 gimple_bind_append_vars (new_stmt, vars);
6d5a8d89 14301 /* bind_vars/BLOCK_VARS are being moved to new_stmt/block, don't
14302 keep them on the inner_bind and it's block. */
14303 gimple_bind_set_vars (inner_bind, NULL_TREE);
14304 if (gimple_bind_block (inner_bind))
14305 BLOCK_VARS (gimple_bind_block (inner_bind)) = NULL_TREE;
75a70cf9 14306 }
773c5ba7 14307
bc7bff74 14308 if (gimple_omp_for_combined_into_p (stmt))
14309 {
14310 extract_omp_for_data (stmt, &fd, NULL);
14311 fdp = &fd;
14312
14313 /* We need two temporaries with fd.loop.v type (istart/iend)
14314 and then (fd.collapse - 1) temporaries with the same
14315 type for count2 ... countN-1 vars if not constant. */
14316 size_t count = 2;
14317 tree type = fd.iter_type;
14318 if (fd.collapse > 1
14319 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
14320 count += fd.collapse - 1;
43895be5 14321 bool taskreg_for
14322 = (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR
14323 || gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_TASKLOOP);
bc7bff74 14324 tree outerc = NULL, *pc = gimple_omp_for_clauses_ptr (stmt);
14325 tree clauses = *pc;
43895be5 14326 if (taskreg_for)
bc7bff74 14327 outerc
43895be5 14328 = find_omp_clause (gimple_omp_taskreg_clauses (ctx->outer->stmt),
bc7bff74 14329 OMP_CLAUSE__LOOPTEMP_);
14330 for (i = 0; i < count; i++)
14331 {
14332 tree temp;
43895be5 14333 if (taskreg_for)
bc7bff74 14334 {
14335 gcc_assert (outerc);
14336 temp = lookup_decl (OMP_CLAUSE_DECL (outerc), ctx->outer);
14337 outerc = find_omp_clause (OMP_CLAUSE_CHAIN (outerc),
14338 OMP_CLAUSE__LOOPTEMP_);
14339 }
14340 else
691447ab 14341 {
f9e245b2 14342 temp = create_tmp_var (type);
691447ab 14343 insert_decl_map (&ctx->outer->cb, temp, temp);
14344 }
bc7bff74 14345 *pc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
14346 OMP_CLAUSE_DECL (*pc) = temp;
14347 pc = &OMP_CLAUSE_CHAIN (*pc);
14348 }
14349 *pc = clauses;
14350 }
14351
75a70cf9 14352 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
773c5ba7 14353 dlist = NULL;
75a70cf9 14354 body = NULL;
bc7bff74 14355 lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx,
14356 fdp);
75a70cf9 14357 gimple_seq_add_seq (&body, gimple_omp_for_pre_body (stmt));
773c5ba7 14358
3d483a94 14359 lower_omp (gimple_omp_body_ptr (stmt), ctx);
14360
773c5ba7 14361 /* Lower the header expressions. At this point, we can assume that
14362 the header is of the form:
14363
14364 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
14365
14366 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
14367 using the .omp_data_s mapping, if needed. */
75a70cf9 14368 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
fd6481cf 14369 {
75a70cf9 14370 rhs_p = gimple_omp_for_initial_ptr (stmt, i);
fd6481cf 14371 if (!is_gimple_min_invariant (*rhs_p))
75a70cf9 14372 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
fd6481cf 14373
75a70cf9 14374 rhs_p = gimple_omp_for_final_ptr (stmt, i);
fd6481cf 14375 if (!is_gimple_min_invariant (*rhs_p))
75a70cf9 14376 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
fd6481cf 14377
75a70cf9 14378 rhs_p = &TREE_OPERAND (gimple_omp_for_incr (stmt, i), 1);
fd6481cf 14379 if (!is_gimple_min_invariant (*rhs_p))
75a70cf9 14380 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
fd6481cf 14381 }
773c5ba7 14382
14383 /* Once lowered, extract the bounds and clauses. */
fd6481cf 14384 extract_omp_for_data (stmt, &fd, NULL);
773c5ba7 14385
a8e785ba 14386 if (is_gimple_omp_oacc (ctx->stmt)
14387 && !ctx_in_oacc_kernels_region (ctx))
14388 lower_oacc_head_tail (gimple_location (stmt),
14389 gimple_omp_for_clauses (stmt),
14390 &oacc_head, &oacc_tail, ctx);
14391
f69b8a4c 14392 /* Add OpenACC partitioning and reduction markers just before the loop */
a8e785ba 14393 if (oacc_head)
14394 gimple_seq_add_seq (&body, oacc_head);
14395
75a70cf9 14396 lower_omp_for_lastprivate (&fd, &body, &dlist, ctx);
773c5ba7 14397
43895be5 14398 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR)
14399 for (tree c = gimple_omp_for_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
14400 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
14401 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
14402 {
14403 OMP_CLAUSE_DECL (c) = lookup_decl (OMP_CLAUSE_DECL (c), ctx);
14404 if (DECL_P (OMP_CLAUSE_LINEAR_STEP (c)))
14405 OMP_CLAUSE_LINEAR_STEP (c)
14406 = maybe_lookup_decl_in_outer_ctx (OMP_CLAUSE_LINEAR_STEP (c),
14407 ctx);
14408 }
14409
75a70cf9 14410 gimple_seq_add_stmt (&body, stmt);
14411 gimple_seq_add_seq (&body, gimple_omp_body (stmt));
61e47ac8 14412
75a70cf9 14413 gimple_seq_add_stmt (&body, gimple_build_omp_continue (fd.loop.v,
14414 fd.loop.v));
61e47ac8 14415
773c5ba7 14416 /* After the loop, add exit clauses. */
75a70cf9 14417 lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, ctx);
bc7bff74 14418
14419 if (ctx->cancellable)
14420 gimple_seq_add_stmt (&body, gimple_build_label (ctx->cancel_label));
14421
75a70cf9 14422 gimple_seq_add_seq (&body, dlist);
773c5ba7 14423
75a70cf9 14424 body = maybe_catch_exception (body);
aade31a0 14425
61e47ac8 14426 /* Region exit marker goes at the end of the loop body. */
75a70cf9 14427 gimple_seq_add_stmt (&body, gimple_build_omp_return (fd.have_nowait));
bc7bff74 14428 maybe_add_implicit_barrier_cancel (ctx, &body);
a8e785ba 14429
14430 /* Add OpenACC joining and reduction markers just after the loop. */
14431 if (oacc_tail)
14432 gimple_seq_add_seq (&body, oacc_tail);
14433
1d22f541 14434 pop_gimplify_context (new_stmt);
75a70cf9 14435
14436 gimple_bind_append_vars (new_stmt, ctx->block_vars);
14437 BLOCK_VARS (block) = gimple_bind_vars (new_stmt);
1d22f541 14438 if (BLOCK_VARS (block))
14439 TREE_USED (block) = 1;
773c5ba7 14440
75a70cf9 14441 gimple_bind_set_body (new_stmt, body);
14442 gimple_omp_set_body (stmt, NULL);
14443 gimple_omp_for_set_pre_body (stmt, NULL);
1e8e9920 14444}
14445
48e1416a 14446/* Callback for walk_stmts. Check if the current statement only contains
a7dfc4fe 14447 GIMPLE_OMP_FOR or GIMPLE_OMP_SECTIONS. */
de7ef844 14448
14449static tree
75a70cf9 14450check_combined_parallel (gimple_stmt_iterator *gsi_p,
14451 bool *handled_ops_p,
14452 struct walk_stmt_info *wi)
de7ef844 14453{
4077bf7a 14454 int *info = (int *) wi->info;
42acab1c 14455 gimple *stmt = gsi_stmt (*gsi_p);
de7ef844 14456
75a70cf9 14457 *handled_ops_p = true;
14458 switch (gimple_code (stmt))
de7ef844 14459 {
75a70cf9 14460 WALK_SUBSTMTS;
14461
14462 case GIMPLE_OMP_FOR:
14463 case GIMPLE_OMP_SECTIONS:
de7ef844 14464 *info = *info == 0 ? 1 : -1;
14465 break;
14466 default:
14467 *info = -1;
14468 break;
14469 }
14470 return NULL;
14471}
773c5ba7 14472
fd6481cf 14473struct omp_taskcopy_context
14474{
14475 /* This field must be at the beginning, as we do "inheritance": Some
14476 callback functions for tree-inline.c (e.g., omp_copy_decl)
14477 receive a copy_body_data pointer that is up-casted to an
14478 omp_context pointer. */
14479 copy_body_data cb;
14480 omp_context *ctx;
14481};
14482
14483static tree
14484task_copyfn_copy_decl (tree var, copy_body_data *cb)
14485{
14486 struct omp_taskcopy_context *tcctx = (struct omp_taskcopy_context *) cb;
14487
14488 if (splay_tree_lookup (tcctx->ctx->sfield_map, (splay_tree_key) var))
f9e245b2 14489 return create_tmp_var (TREE_TYPE (var));
fd6481cf 14490
14491 return var;
14492}
14493
14494static tree
14495task_copyfn_remap_type (struct omp_taskcopy_context *tcctx, tree orig_type)
14496{
14497 tree name, new_fields = NULL, type, f;
14498
14499 type = lang_hooks.types.make_type (RECORD_TYPE);
14500 name = DECL_NAME (TYPE_NAME (orig_type));
e60a6f7b 14501 name = build_decl (gimple_location (tcctx->ctx->stmt),
14502 TYPE_DECL, name, type);
fd6481cf 14503 TYPE_NAME (type) = name;
14504
14505 for (f = TYPE_FIELDS (orig_type); f ; f = TREE_CHAIN (f))
14506 {
14507 tree new_f = copy_node (f);
14508 DECL_CONTEXT (new_f) = type;
14509 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &tcctx->cb);
14510 TREE_CHAIN (new_f) = new_fields;
75a70cf9 14511 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &tcctx->cb, NULL);
14512 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r, &tcctx->cb, NULL);
14513 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
14514 &tcctx->cb, NULL);
fd6481cf 14515 new_fields = new_f;
06ecf488 14516 tcctx->cb.decl_map->put (f, new_f);
fd6481cf 14517 }
14518 TYPE_FIELDS (type) = nreverse (new_fields);
14519 layout_type (type);
14520 return type;
14521}
14522
14523/* Create task copyfn. */
14524
14525static void
1a91d914 14526create_task_copyfn (gomp_task *task_stmt, omp_context *ctx)
fd6481cf 14527{
14528 struct function *child_cfun;
14529 tree child_fn, t, c, src, dst, f, sf, arg, sarg, decl;
14530 tree record_type, srecord_type, bind, list;
14531 bool record_needs_remap = false, srecord_needs_remap = false;
14532 splay_tree_node n;
14533 struct omp_taskcopy_context tcctx;
389dd41b 14534 location_t loc = gimple_location (task_stmt);
fd6481cf 14535
75a70cf9 14536 child_fn = gimple_omp_task_copy_fn (task_stmt);
fd6481cf 14537 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
14538 gcc_assert (child_cfun->cfg == NULL);
fd6481cf 14539 DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
14540
14541 /* Reset DECL_CONTEXT on function arguments. */
1767a056 14542 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
fd6481cf 14543 DECL_CONTEXT (t) = child_fn;
14544
14545 /* Populate the function. */
8a4a28a8 14546 push_gimplify_context ();
9078126c 14547 push_cfun (child_cfun);
fd6481cf 14548
14549 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
14550 TREE_SIDE_EFFECTS (bind) = 1;
14551 list = NULL;
14552 DECL_SAVED_TREE (child_fn) = bind;
75a70cf9 14553 DECL_SOURCE_LOCATION (child_fn) = gimple_location (task_stmt);
fd6481cf 14554
14555 /* Remap src and dst argument types if needed. */
14556 record_type = ctx->record_type;
14557 srecord_type = ctx->srecord_type;
1767a056 14558 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
fd6481cf 14559 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
14560 {
14561 record_needs_remap = true;
14562 break;
14563 }
1767a056 14564 for (f = TYPE_FIELDS (srecord_type); f ; f = DECL_CHAIN (f))
fd6481cf 14565 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
14566 {
14567 srecord_needs_remap = true;
14568 break;
14569 }
14570
14571 if (record_needs_remap || srecord_needs_remap)
14572 {
14573 memset (&tcctx, '\0', sizeof (tcctx));
14574 tcctx.cb.src_fn = ctx->cb.src_fn;
14575 tcctx.cb.dst_fn = child_fn;
415d1b9a 14576 tcctx.cb.src_node = cgraph_node::get (tcctx.cb.src_fn);
53f79206 14577 gcc_checking_assert (tcctx.cb.src_node);
fd6481cf 14578 tcctx.cb.dst_node = tcctx.cb.src_node;
14579 tcctx.cb.src_cfun = ctx->cb.src_cfun;
14580 tcctx.cb.copy_decl = task_copyfn_copy_decl;
e38def9c 14581 tcctx.cb.eh_lp_nr = 0;
fd6481cf 14582 tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
06ecf488 14583 tcctx.cb.decl_map = new hash_map<tree, tree>;
fd6481cf 14584 tcctx.ctx = ctx;
14585
14586 if (record_needs_remap)
14587 record_type = task_copyfn_remap_type (&tcctx, record_type);
14588 if (srecord_needs_remap)
14589 srecord_type = task_copyfn_remap_type (&tcctx, srecord_type);
14590 }
14591 else
14592 tcctx.cb.decl_map = NULL;
14593
fd6481cf 14594 arg = DECL_ARGUMENTS (child_fn);
14595 TREE_TYPE (arg) = build_pointer_type (record_type);
1767a056 14596 sarg = DECL_CHAIN (arg);
fd6481cf 14597 TREE_TYPE (sarg) = build_pointer_type (srecord_type);
14598
14599 /* First pass: initialize temporaries used in record_type and srecord_type
14600 sizes and field offsets. */
14601 if (tcctx.cb.decl_map)
75a70cf9 14602 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
fd6481cf 14603 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
14604 {
14605 tree *p;
14606
14607 decl = OMP_CLAUSE_DECL (c);
06ecf488 14608 p = tcctx.cb.decl_map->get (decl);
fd6481cf 14609 if (p == NULL)
14610 continue;
14611 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
14612 sf = (tree) n->value;
06ecf488 14613 sf = *tcctx.cb.decl_map->get (sf);
182cf5a9 14614 src = build_simple_mem_ref_loc (loc, sarg);
445d06b6 14615 src = omp_build_component_ref (src, sf);
75a70cf9 14616 t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
fd6481cf 14617 append_to_statement_list (t, &list);
14618 }
14619
14620 /* Second pass: copy shared var pointers and copy construct non-VLA
14621 firstprivate vars. */
75a70cf9 14622 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
fd6481cf 14623 switch (OMP_CLAUSE_CODE (c))
14624 {
43895be5 14625 splay_tree_key key;
fd6481cf 14626 case OMP_CLAUSE_SHARED:
14627 decl = OMP_CLAUSE_DECL (c);
43895be5 14628 key = (splay_tree_key) decl;
14629 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
14630 key = (splay_tree_key) &DECL_UID (decl);
14631 n = splay_tree_lookup (ctx->field_map, key);
fd6481cf 14632 if (n == NULL)
14633 break;
14634 f = (tree) n->value;
14635 if (tcctx.cb.decl_map)
06ecf488 14636 f = *tcctx.cb.decl_map->get (f);
43895be5 14637 n = splay_tree_lookup (ctx->sfield_map, key);
fd6481cf 14638 sf = (tree) n->value;
14639 if (tcctx.cb.decl_map)
06ecf488 14640 sf = *tcctx.cb.decl_map->get (sf);
182cf5a9 14641 src = build_simple_mem_ref_loc (loc, sarg);
445d06b6 14642 src = omp_build_component_ref (src, sf);
182cf5a9 14643 dst = build_simple_mem_ref_loc (loc, arg);
445d06b6 14644 dst = omp_build_component_ref (dst, f);
75a70cf9 14645 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
fd6481cf 14646 append_to_statement_list (t, &list);
14647 break;
14648 case OMP_CLAUSE_FIRSTPRIVATE:
14649 decl = OMP_CLAUSE_DECL (c);
14650 if (is_variable_sized (decl))
14651 break;
14652 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
14653 if (n == NULL)
14654 break;
14655 f = (tree) n->value;
14656 if (tcctx.cb.decl_map)
06ecf488 14657 f = *tcctx.cb.decl_map->get (f);
fd6481cf 14658 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
14659 if (n != NULL)
14660 {
14661 sf = (tree) n->value;
14662 if (tcctx.cb.decl_map)
06ecf488 14663 sf = *tcctx.cb.decl_map->get (sf);
182cf5a9 14664 src = build_simple_mem_ref_loc (loc, sarg);
445d06b6 14665 src = omp_build_component_ref (src, sf);
fd6481cf 14666 if (use_pointer_for_field (decl, NULL) || is_reference (decl))
182cf5a9 14667 src = build_simple_mem_ref_loc (loc, src);
fd6481cf 14668 }
14669 else
14670 src = decl;
182cf5a9 14671 dst = build_simple_mem_ref_loc (loc, arg);
445d06b6 14672 dst = omp_build_component_ref (dst, f);
fd6481cf 14673 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
14674 append_to_statement_list (t, &list);
14675 break;
14676 case OMP_CLAUSE_PRIVATE:
14677 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c))
14678 break;
14679 decl = OMP_CLAUSE_DECL (c);
14680 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
14681 f = (tree) n->value;
14682 if (tcctx.cb.decl_map)
06ecf488 14683 f = *tcctx.cb.decl_map->get (f);
fd6481cf 14684 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
14685 if (n != NULL)
14686 {
14687 sf = (tree) n->value;
14688 if (tcctx.cb.decl_map)
06ecf488 14689 sf = *tcctx.cb.decl_map->get (sf);
182cf5a9 14690 src = build_simple_mem_ref_loc (loc, sarg);
445d06b6 14691 src = omp_build_component_ref (src, sf);
fd6481cf 14692 if (use_pointer_for_field (decl, NULL))
182cf5a9 14693 src = build_simple_mem_ref_loc (loc, src);
fd6481cf 14694 }
14695 else
14696 src = decl;
182cf5a9 14697 dst = build_simple_mem_ref_loc (loc, arg);
445d06b6 14698 dst = omp_build_component_ref (dst, f);
75a70cf9 14699 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
fd6481cf 14700 append_to_statement_list (t, &list);
14701 break;
14702 default:
14703 break;
14704 }
14705
14706 /* Last pass: handle VLA firstprivates. */
14707 if (tcctx.cb.decl_map)
75a70cf9 14708 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
fd6481cf 14709 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
14710 {
14711 tree ind, ptr, df;
14712
14713 decl = OMP_CLAUSE_DECL (c);
14714 if (!is_variable_sized (decl))
14715 continue;
14716 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
14717 if (n == NULL)
14718 continue;
14719 f = (tree) n->value;
06ecf488 14720 f = *tcctx.cb.decl_map->get (f);
fd6481cf 14721 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
14722 ind = DECL_VALUE_EXPR (decl);
14723 gcc_assert (TREE_CODE (ind) == INDIRECT_REF);
14724 gcc_assert (DECL_P (TREE_OPERAND (ind, 0)));
14725 n = splay_tree_lookup (ctx->sfield_map,
14726 (splay_tree_key) TREE_OPERAND (ind, 0));
14727 sf = (tree) n->value;
06ecf488 14728 sf = *tcctx.cb.decl_map->get (sf);
182cf5a9 14729 src = build_simple_mem_ref_loc (loc, sarg);
445d06b6 14730 src = omp_build_component_ref (src, sf);
182cf5a9 14731 src = build_simple_mem_ref_loc (loc, src);
14732 dst = build_simple_mem_ref_loc (loc, arg);
445d06b6 14733 dst = omp_build_component_ref (dst, f);
fd6481cf 14734 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
14735 append_to_statement_list (t, &list);
14736 n = splay_tree_lookup (ctx->field_map,
14737 (splay_tree_key) TREE_OPERAND (ind, 0));
14738 df = (tree) n->value;
06ecf488 14739 df = *tcctx.cb.decl_map->get (df);
182cf5a9 14740 ptr = build_simple_mem_ref_loc (loc, arg);
445d06b6 14741 ptr = omp_build_component_ref (ptr, df);
75a70cf9 14742 t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
389dd41b 14743 build_fold_addr_expr_loc (loc, dst));
fd6481cf 14744 append_to_statement_list (t, &list);
14745 }
14746
14747 t = build1 (RETURN_EXPR, void_type_node, NULL);
14748 append_to_statement_list (t, &list);
14749
14750 if (tcctx.cb.decl_map)
06ecf488 14751 delete tcctx.cb.decl_map;
fd6481cf 14752 pop_gimplify_context (NULL);
14753 BIND_EXPR_BODY (bind) = list;
14754 pop_cfun ();
fd6481cf 14755}
14756
bc7bff74 14757static void
43895be5 14758lower_depend_clauses (tree *pclauses, gimple_seq *iseq, gimple_seq *oseq)
bc7bff74 14759{
14760 tree c, clauses;
42acab1c 14761 gimple *g;
bc7bff74 14762 size_t n_in = 0, n_out = 0, idx = 2, i;
14763
43895be5 14764 clauses = find_omp_clause (*pclauses, OMP_CLAUSE_DEPEND);
bc7bff74 14765 gcc_assert (clauses);
14766 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
14767 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
14768 switch (OMP_CLAUSE_DEPEND_KIND (c))
14769 {
14770 case OMP_CLAUSE_DEPEND_IN:
14771 n_in++;
14772 break;
14773 case OMP_CLAUSE_DEPEND_OUT:
14774 case OMP_CLAUSE_DEPEND_INOUT:
14775 n_out++;
14776 break;
43895be5 14777 case OMP_CLAUSE_DEPEND_SOURCE:
14778 case OMP_CLAUSE_DEPEND_SINK:
14779 /* FALLTHRU */
bc7bff74 14780 default:
14781 gcc_unreachable ();
14782 }
14783 tree type = build_array_type_nelts (ptr_type_node, n_in + n_out + 2);
f9e245b2 14784 tree array = create_tmp_var (type);
43895be5 14785 TREE_ADDRESSABLE (array) = 1;
bc7bff74 14786 tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
14787 NULL_TREE);
14788 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_in + n_out));
14789 gimple_seq_add_stmt (iseq, g);
14790 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
14791 NULL_TREE);
14792 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_out));
14793 gimple_seq_add_stmt (iseq, g);
14794 for (i = 0; i < 2; i++)
14795 {
14796 if ((i ? n_in : n_out) == 0)
14797 continue;
14798 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
14799 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
14800 && ((OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_IN) ^ i))
14801 {
14802 tree t = OMP_CLAUSE_DECL (c);
14803 t = fold_convert (ptr_type_node, t);
14804 gimplify_expr (&t, iseq, NULL, is_gimple_val, fb_rvalue);
14805 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (idx++),
14806 NULL_TREE, NULL_TREE);
14807 g = gimple_build_assign (r, t);
14808 gimple_seq_add_stmt (iseq, g);
14809 }
14810 }
bc7bff74 14811 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
14812 OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
43895be5 14813 OMP_CLAUSE_CHAIN (c) = *pclauses;
14814 *pclauses = c;
bc7bff74 14815 tree clobber = build_constructor (type, NULL);
14816 TREE_THIS_VOLATILE (clobber) = 1;
14817 g = gimple_build_assign (array, clobber);
14818 gimple_seq_add_stmt (oseq, g);
14819}
14820
75a70cf9 14821/* Lower the OpenMP parallel or task directive in the current statement
14822 in GSI_P. CTX holds context information for the directive. */
773c5ba7 14823
14824static void
75a70cf9 14825lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
773c5ba7 14826{
75a70cf9 14827 tree clauses;
14828 tree child_fn, t;
42acab1c 14829 gimple *stmt = gsi_stmt (*gsi_p);
1a91d914 14830 gbind *par_bind, *bind, *dep_bind = NULL;
bc7bff74 14831 gimple_seq par_body, olist, ilist, par_olist, par_rlist, par_ilist, new_body;
389dd41b 14832 location_t loc = gimple_location (stmt);
773c5ba7 14833
75a70cf9 14834 clauses = gimple_omp_taskreg_clauses (stmt);
1a91d914 14835 par_bind
14836 = as_a <gbind *> (gimple_seq_first_stmt (gimple_omp_body (stmt)));
75a70cf9 14837 par_body = gimple_bind_body (par_bind);
773c5ba7 14838 child_fn = ctx->cb.dst_fn;
75a70cf9 14839 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
14840 && !gimple_omp_parallel_combined_p (stmt))
de7ef844 14841 {
14842 struct walk_stmt_info wi;
14843 int ws_num = 0;
14844
14845 memset (&wi, 0, sizeof (wi));
de7ef844 14846 wi.info = &ws_num;
14847 wi.val_only = true;
75a70cf9 14848 walk_gimple_seq (par_body, check_combined_parallel, NULL, &wi);
de7ef844 14849 if (ws_num == 1)
75a70cf9 14850 gimple_omp_parallel_set_combined_p (stmt, true);
de7ef844 14851 }
bc7bff74 14852 gimple_seq dep_ilist = NULL;
14853 gimple_seq dep_olist = NULL;
14854 if (gimple_code (stmt) == GIMPLE_OMP_TASK
14855 && find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
14856 {
8a4a28a8 14857 push_gimplify_context ();
bc7bff74 14858 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
43895be5 14859 lower_depend_clauses (gimple_omp_task_clauses_ptr (stmt),
14860 &dep_ilist, &dep_olist);
bc7bff74 14861 }
14862
fd6481cf 14863 if (ctx->srecord_type)
1a91d914 14864 create_task_copyfn (as_a <gomp_task *> (stmt), ctx);
773c5ba7 14865
8a4a28a8 14866 push_gimplify_context ();
773c5ba7 14867
75a70cf9 14868 par_olist = NULL;
14869 par_ilist = NULL;
bc7bff74 14870 par_rlist = NULL;
14871 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx, NULL);
e3a19533 14872 lower_omp (&par_body, ctx);
75a70cf9 14873 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL)
bc7bff74 14874 lower_reduction_clauses (clauses, &par_rlist, ctx);
773c5ba7 14875
14876 /* Declare all the variables created by mapping and the variables
14877 declared in the scope of the parallel body. */
14878 record_vars_into (ctx->block_vars, child_fn);
75a70cf9 14879 record_vars_into (gimple_bind_vars (par_bind), child_fn);
773c5ba7 14880
14881 if (ctx->record_type)
14882 {
fd6481cf 14883 ctx->sender_decl
14884 = create_tmp_var (ctx->srecord_type ? ctx->srecord_type
14885 : ctx->record_type, ".omp_data_o");
84bfaaeb 14886 DECL_NAMELESS (ctx->sender_decl) = 1;
86f2ad37 14887 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
75a70cf9 14888 gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl);
773c5ba7 14889 }
14890
75a70cf9 14891 olist = NULL;
14892 ilist = NULL;
773c5ba7 14893 lower_send_clauses (clauses, &ilist, &olist, ctx);
14894 lower_send_shared_vars (&ilist, &olist, ctx);
14895
bc7bff74 14896 if (ctx->record_type)
14897 {
14898 tree clobber = build_constructor (TREE_TYPE (ctx->sender_decl), NULL);
14899 TREE_THIS_VOLATILE (clobber) = 1;
14900 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
14901 clobber));
14902 }
14903
773c5ba7 14904 /* Once all the expansions are done, sequence all the different
75a70cf9 14905 fragments inside gimple_omp_body. */
773c5ba7 14906
75a70cf9 14907 new_body = NULL;
773c5ba7 14908
14909 if (ctx->record_type)
14910 {
389dd41b 14911 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
cc6b725b 14912 /* fixup_child_record_type might have changed receiver_decl's type. */
389dd41b 14913 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
75a70cf9 14914 gimple_seq_add_stmt (&new_body,
14915 gimple_build_assign (ctx->receiver_decl, t));
773c5ba7 14916 }
14917
75a70cf9 14918 gimple_seq_add_seq (&new_body, par_ilist);
14919 gimple_seq_add_seq (&new_body, par_body);
bc7bff74 14920 gimple_seq_add_seq (&new_body, par_rlist);
14921 if (ctx->cancellable)
14922 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
75a70cf9 14923 gimple_seq_add_seq (&new_body, par_olist);
14924 new_body = maybe_catch_exception (new_body);
b25f70fd 14925 if (gimple_code (stmt) == GIMPLE_OMP_TASK)
14926 gimple_seq_add_stmt (&new_body,
14927 gimple_build_omp_continue (integer_zero_node,
14928 integer_zero_node));
75a70cf9 14929 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
14930 gimple_omp_set_body (stmt, new_body);
773c5ba7 14931
75a70cf9 14932 bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
bc7bff74 14933 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
14934 gimple_bind_add_seq (bind, ilist);
14935 gimple_bind_add_stmt (bind, stmt);
14936 gimple_bind_add_seq (bind, olist);
14937
14938 pop_gimplify_context (NULL);
14939
14940 if (dep_bind)
14941 {
14942 gimple_bind_add_seq (dep_bind, dep_ilist);
14943 gimple_bind_add_stmt (dep_bind, bind);
14944 gimple_bind_add_seq (dep_bind, dep_olist);
14945 pop_gimplify_context (dep_bind);
14946 }
14947}
14948
ca4c3545 14949/* Lower the GIMPLE_OMP_TARGET in the current statement
bc7bff74 14950 in GSI_P. CTX holds context information for the directive. */
14951
14952static void
14953lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14954{
14955 tree clauses;
14956 tree child_fn, t, c;
1a91d914 14957 gomp_target *stmt = as_a <gomp_target *> (gsi_stmt (*gsi_p));
43895be5 14958 gbind *tgt_bind, *bind, *dep_bind = NULL;
b656be3a 14959 gimple_seq tgt_body, olist, ilist, fplist, new_body;
bc7bff74 14960 location_t loc = gimple_location (stmt);
ca4c3545 14961 bool offloaded, data_region;
bc7bff74 14962 unsigned int map_cnt = 0;
43895be5 14963 bool has_depend = false;
bc7bff74 14964
ca4c3545 14965 offloaded = is_gimple_omp_offloaded (stmt);
14966 switch (gimple_omp_target_kind (stmt))
14967 {
14968 case GF_OMP_TARGET_KIND_REGION:
14969 case GF_OMP_TARGET_KIND_UPDATE:
43895be5 14970 case GF_OMP_TARGET_KIND_ENTER_DATA:
14971 case GF_OMP_TARGET_KIND_EXIT_DATA:
ca4c3545 14972 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
14973 case GF_OMP_TARGET_KIND_OACC_KERNELS:
14974 case GF_OMP_TARGET_KIND_OACC_UPDATE:
14975 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
2fc5e987 14976 case GF_OMP_TARGET_KIND_OACC_DECLARE:
ca4c3545 14977 data_region = false;
14978 break;
14979 case GF_OMP_TARGET_KIND_DATA:
14980 case GF_OMP_TARGET_KIND_OACC_DATA:
14981 data_region = true;
14982 break;
14983 default:
14984 gcc_unreachable ();
14985 }
14986
bc7bff74 14987 clauses = gimple_omp_target_clauses (stmt);
ca4c3545 14988
43895be5 14989 gimple_seq dep_ilist = NULL;
14990 gimple_seq dep_olist = NULL;
14991 if (find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
14992 {
14993 push_gimplify_context ();
14994 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
14995 lower_depend_clauses (gimple_omp_target_clauses_ptr (stmt),
14996 &dep_ilist, &dep_olist);
14997 has_depend = true;
14998 }
14999
ca4c3545 15000 tgt_bind = NULL;
15001 tgt_body = NULL;
15002 if (offloaded)
bc7bff74 15003 {
1a91d914 15004 tgt_bind = gimple_seq_first_stmt_as_a_bind (gimple_omp_body (stmt));
bc7bff74 15005 tgt_body = gimple_bind_body (tgt_bind);
15006 }
ca4c3545 15007 else if (data_region)
bc7bff74 15008 tgt_body = gimple_omp_body (stmt);
15009 child_fn = ctx->cb.dst_fn;
15010
8a4a28a8 15011 push_gimplify_context ();
b656be3a 15012 fplist = NULL;
bc7bff74 15013
15014 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
15015 switch (OMP_CLAUSE_CODE (c))
15016 {
15017 tree var, x;
15018
15019 default:
15020 break;
15021 case OMP_CLAUSE_MAP:
382ecba7 15022#if CHECKING_P
ca4c3545 15023 /* First check what we're prepared to handle in the following. */
15024 switch (OMP_CLAUSE_MAP_KIND (c))
15025 {
15026 case GOMP_MAP_ALLOC:
15027 case GOMP_MAP_TO:
15028 case GOMP_MAP_FROM:
15029 case GOMP_MAP_TOFROM:
15030 case GOMP_MAP_POINTER:
15031 case GOMP_MAP_TO_PSET:
43895be5 15032 case GOMP_MAP_FORCE_DEALLOC:
15033 case GOMP_MAP_RELEASE:
15034 case GOMP_MAP_ALWAYS_TO:
15035 case GOMP_MAP_ALWAYS_FROM:
15036 case GOMP_MAP_ALWAYS_TOFROM:
15037 case GOMP_MAP_FIRSTPRIVATE_POINTER:
9561765e 15038 case GOMP_MAP_FIRSTPRIVATE_REFERENCE:
43895be5 15039 case GOMP_MAP_STRUCT:
9561765e 15040 case GOMP_MAP_ALWAYS_POINTER:
ca4c3545 15041 break;
15042 case GOMP_MAP_FORCE_ALLOC:
15043 case GOMP_MAP_FORCE_TO:
15044 case GOMP_MAP_FORCE_FROM:
15045 case GOMP_MAP_FORCE_TOFROM:
15046 case GOMP_MAP_FORCE_PRESENT:
ca4c3545 15047 case GOMP_MAP_FORCE_DEVICEPTR:
2fc5e987 15048 case GOMP_MAP_DEVICE_RESIDENT:
15049 case GOMP_MAP_LINK:
ca4c3545 15050 gcc_assert (is_gimple_omp_oacc (stmt));
15051 break;
15052 default:
15053 gcc_unreachable ();
15054 }
15055#endif
15056 /* FALLTHRU */
bc7bff74 15057 case OMP_CLAUSE_TO:
15058 case OMP_CLAUSE_FROM:
b656be3a 15059 oacc_firstprivate:
bc7bff74 15060 var = OMP_CLAUSE_DECL (c);
15061 if (!DECL_P (var))
15062 {
15063 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
43895be5 15064 || (!OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
15065 && (OMP_CLAUSE_MAP_KIND (c)
15066 != GOMP_MAP_FIRSTPRIVATE_POINTER)))
bc7bff74 15067 map_cnt++;
15068 continue;
15069 }
15070
15071 if (DECL_SIZE (var)
15072 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
15073 {
15074 tree var2 = DECL_VALUE_EXPR (var);
15075 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
15076 var2 = TREE_OPERAND (var2, 0);
15077 gcc_assert (DECL_P (var2));
15078 var = var2;
15079 }
15080
43895be5 15081 if (offloaded
b656be3a 15082 && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
9561765e 15083 && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
15084 || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_REFERENCE))
43895be5 15085 {
15086 if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
15087 {
15088 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx))
15089 && varpool_node::get_create (var)->offloadable)
15090 continue;
15091
15092 tree type = build_pointer_type (TREE_TYPE (var));
15093 tree new_var = lookup_decl (var, ctx);
15094 x = create_tmp_var_raw (type, get_name (new_var));
15095 gimple_add_tmp_var (x);
15096 x = build_simple_mem_ref (x);
15097 SET_DECL_VALUE_EXPR (new_var, x);
15098 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15099 }
15100 continue;
15101 }
15102
bc7bff74 15103 if (!maybe_lookup_field (var, ctx))
15104 continue;
15105
ca4c3545 15106 if (offloaded)
bc7bff74 15107 {
15108 x = build_receiver_ref (var, true, ctx);
15109 tree new_var = lookup_decl (var, ctx);
43895be5 15110
b656be3a 15111 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
15112 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
bc7bff74 15113 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
15114 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
15115 x = build_simple_mem_ref (x);
b656be3a 15116 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
15117 {
15118 gcc_assert (is_gimple_omp_oacc (ctx->stmt));
15119 if (is_reference (new_var))
15120 {
15121 /* Create a local object to hold the instance
15122 value. */
15123 tree type = TREE_TYPE (TREE_TYPE (new_var));
15124 const char *id = IDENTIFIER_POINTER (DECL_NAME (new_var));
15125 tree inst = create_tmp_var (type, id);
15126 gimplify_assign (inst, fold_indirect_ref (x), &fplist);
15127 x = build_fold_addr_expr (inst);
15128 }
15129 gimplify_assign (new_var, x, &fplist);
15130 }
15131 else if (DECL_P (new_var))
15132 {
15133 SET_DECL_VALUE_EXPR (new_var, x);
15134 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15135 }
15136 else
15137 gcc_unreachable ();
bc7bff74 15138 }
15139 map_cnt++;
43895be5 15140 break;
15141
15142 case OMP_CLAUSE_FIRSTPRIVATE:
b656be3a 15143 if (is_oacc_parallel (ctx))
15144 goto oacc_firstprivate;
43895be5 15145 map_cnt++;
15146 var = OMP_CLAUSE_DECL (c);
15147 if (!is_reference (var)
15148 && !is_gimple_reg_type (TREE_TYPE (var)))
15149 {
15150 tree new_var = lookup_decl (var, ctx);
15151 if (is_variable_sized (var))
15152 {
15153 tree pvar = DECL_VALUE_EXPR (var);
15154 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15155 pvar = TREE_OPERAND (pvar, 0);
15156 gcc_assert (DECL_P (pvar));
15157 tree new_pvar = lookup_decl (pvar, ctx);
15158 x = build_fold_indirect_ref (new_pvar);
15159 TREE_THIS_NOTRAP (x) = 1;
15160 }
15161 else
15162 x = build_receiver_ref (var, true, ctx);
15163 SET_DECL_VALUE_EXPR (new_var, x);
15164 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15165 }
15166 break;
15167
15168 case OMP_CLAUSE_PRIVATE:
b656be3a 15169 if (is_gimple_omp_oacc (ctx->stmt))
15170 break;
43895be5 15171 var = OMP_CLAUSE_DECL (c);
15172 if (is_variable_sized (var))
15173 {
15174 tree new_var = lookup_decl (var, ctx);
15175 tree pvar = DECL_VALUE_EXPR (var);
15176 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15177 pvar = TREE_OPERAND (pvar, 0);
15178 gcc_assert (DECL_P (pvar));
15179 tree new_pvar = lookup_decl (pvar, ctx);
15180 x = build_fold_indirect_ref (new_pvar);
15181 TREE_THIS_NOTRAP (x) = 1;
15182 SET_DECL_VALUE_EXPR (new_var, x);
15183 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15184 }
15185 break;
15186
15187 case OMP_CLAUSE_USE_DEVICE_PTR:
15188 case OMP_CLAUSE_IS_DEVICE_PTR:
15189 var = OMP_CLAUSE_DECL (c);
15190 map_cnt++;
15191 if (is_variable_sized (var))
15192 {
15193 tree new_var = lookup_decl (var, ctx);
15194 tree pvar = DECL_VALUE_EXPR (var);
15195 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15196 pvar = TREE_OPERAND (pvar, 0);
15197 gcc_assert (DECL_P (pvar));
15198 tree new_pvar = lookup_decl (pvar, ctx);
15199 x = build_fold_indirect_ref (new_pvar);
15200 TREE_THIS_NOTRAP (x) = 1;
15201 SET_DECL_VALUE_EXPR (new_var, x);
15202 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15203 }
15204 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
15205 {
15206 tree new_var = lookup_decl (var, ctx);
15207 tree type = build_pointer_type (TREE_TYPE (var));
15208 x = create_tmp_var_raw (type, get_name (new_var));
15209 gimple_add_tmp_var (x);
15210 x = build_simple_mem_ref (x);
15211 SET_DECL_VALUE_EXPR (new_var, x);
15212 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15213 }
15214 break;
bc7bff74 15215 }
15216
ca4c3545 15217 if (offloaded)
bc7bff74 15218 {
15219 target_nesting_level++;
15220 lower_omp (&tgt_body, ctx);
15221 target_nesting_level--;
15222 }
ca4c3545 15223 else if (data_region)
bc7bff74 15224 lower_omp (&tgt_body, ctx);
15225
ca4c3545 15226 if (offloaded)
bc7bff74 15227 {
15228 /* Declare all the variables created by mapping and the variables
15229 declared in the scope of the target body. */
15230 record_vars_into (ctx->block_vars, child_fn);
15231 record_vars_into (gimple_bind_vars (tgt_bind), child_fn);
15232 }
15233
15234 olist = NULL;
15235 ilist = NULL;
15236 if (ctx->record_type)
15237 {
15238 ctx->sender_decl
15239 = create_tmp_var (ctx->record_type, ".omp_data_arr");
15240 DECL_NAMELESS (ctx->sender_decl) = 1;
15241 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
15242 t = make_tree_vec (3);
15243 TREE_VEC_ELT (t, 0) = ctx->sender_decl;
15244 TREE_VEC_ELT (t, 1)
15245 = create_tmp_var (build_array_type_nelts (size_type_node, map_cnt),
15246 ".omp_data_sizes");
15247 DECL_NAMELESS (TREE_VEC_ELT (t, 1)) = 1;
15248 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 1)) = 1;
15249 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 1;
43895be5 15250 tree tkind_type = short_unsigned_type_node;
15251 int talign_shift = 8;
bc7bff74 15252 TREE_VEC_ELT (t, 2)
ca4c3545 15253 = create_tmp_var (build_array_type_nelts (tkind_type, map_cnt),
bc7bff74 15254 ".omp_data_kinds");
15255 DECL_NAMELESS (TREE_VEC_ELT (t, 2)) = 1;
15256 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 2)) = 1;
15257 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 1;
15258 gimple_omp_target_set_data_arg (stmt, t);
15259
15260 vec<constructor_elt, va_gc> *vsize;
15261 vec<constructor_elt, va_gc> *vkind;
15262 vec_alloc (vsize, map_cnt);
15263 vec_alloc (vkind, map_cnt);
15264 unsigned int map_idx = 0;
15265
15266 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
15267 switch (OMP_CLAUSE_CODE (c))
15268 {
43895be5 15269 tree ovar, nc, s, purpose, var, x, type;
15270 unsigned int talign;
bc7bff74 15271
15272 default:
15273 break;
b656be3a 15274
bc7bff74 15275 case OMP_CLAUSE_MAP:
15276 case OMP_CLAUSE_TO:
15277 case OMP_CLAUSE_FROM:
b656be3a 15278 oacc_firstprivate_map:
bc7bff74 15279 nc = c;
15280 ovar = OMP_CLAUSE_DECL (c);
43895be5 15281 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
9561765e 15282 && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
15283 || (OMP_CLAUSE_MAP_KIND (c)
15284 == GOMP_MAP_FIRSTPRIVATE_REFERENCE)))
43895be5 15285 break;
bc7bff74 15286 if (!DECL_P (ovar))
15287 {
15288 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
15289 && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
15290 {
15291 gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c))
15292 == get_base_address (ovar));
15293 nc = OMP_CLAUSE_CHAIN (c);
15294 ovar = OMP_CLAUSE_DECL (nc);
15295 }
15296 else
15297 {
15298 tree x = build_sender_ref (ovar, ctx);
15299 tree v
15300 = build_fold_addr_expr_with_type (ovar, ptr_type_node);
15301 gimplify_assign (x, v, &ilist);
15302 nc = NULL_TREE;
15303 }
15304 }
15305 else
15306 {
15307 if (DECL_SIZE (ovar)
15308 && TREE_CODE (DECL_SIZE (ovar)) != INTEGER_CST)
15309 {
15310 tree ovar2 = DECL_VALUE_EXPR (ovar);
15311 gcc_assert (TREE_CODE (ovar2) == INDIRECT_REF);
15312 ovar2 = TREE_OPERAND (ovar2, 0);
15313 gcc_assert (DECL_P (ovar2));
15314 ovar = ovar2;
15315 }
9561765e 15316 if (!maybe_lookup_field (ovar, ctx))
bc7bff74 15317 continue;
15318 }
15319
43895be5 15320 talign = TYPE_ALIGN_UNIT (TREE_TYPE (ovar));
4f3b8d78 15321 if (DECL_P (ovar) && DECL_ALIGN_UNIT (ovar) > talign)
15322 talign = DECL_ALIGN_UNIT (ovar);
bc7bff74 15323 if (nc)
15324 {
43895be5 15325 var = lookup_decl_in_outer_ctx (ovar, ctx);
9561765e 15326 x = build_sender_ref (ovar, ctx);
abe55632 15327
15328 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
b656be3a 15329 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
15330 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
15331 && TREE_CODE (TREE_TYPE (ovar)) == ARRAY_TYPE)
bc7bff74 15332 {
ca4c3545 15333 gcc_assert (offloaded);
bc7bff74 15334 tree avar
f9e245b2 15335 = create_tmp_var (TREE_TYPE (TREE_TYPE (x)));
bc7bff74 15336 mark_addressable (avar);
15337 gimplify_assign (avar, build_fold_addr_expr (var), &ilist);
4f3b8d78 15338 talign = DECL_ALIGN_UNIT (avar);
bc7bff74 15339 avar = build_fold_addr_expr (avar);
15340 gimplify_assign (x, avar, &ilist);
15341 }
b656be3a 15342 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
15343 {
15344 gcc_assert (is_gimple_omp_oacc (ctx->stmt));
15345 if (!is_reference (var))
15346 var = build_fold_addr_expr (var);
15347 else
15348 talign = TYPE_ALIGN_UNIT (TREE_TYPE (TREE_TYPE (ovar)));
15349 gimplify_assign (x, var, &ilist);
15350 }
bc7bff74 15351 else if (is_gimple_reg (var))
15352 {
ca4c3545 15353 gcc_assert (offloaded);
f9e245b2 15354 tree avar = create_tmp_var (TREE_TYPE (var));
bc7bff74 15355 mark_addressable (avar);
ca4c3545 15356 enum gomp_map_kind map_kind = OMP_CLAUSE_MAP_KIND (c);
15357 if (GOMP_MAP_COPY_TO_P (map_kind)
15358 || map_kind == GOMP_MAP_POINTER
15359 || map_kind == GOMP_MAP_TO_PSET
15360 || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
bc7bff74 15361 gimplify_assign (avar, var, &ilist);
15362 avar = build_fold_addr_expr (avar);
15363 gimplify_assign (x, avar, &ilist);
ca4c3545 15364 if ((GOMP_MAP_COPY_FROM_P (map_kind)
15365 || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
bc7bff74 15366 && !TYPE_READONLY (TREE_TYPE (var)))
15367 {
43895be5 15368 x = unshare_expr (x);
bc7bff74 15369 x = build_simple_mem_ref (x);
15370 gimplify_assign (var, x, &olist);
15371 }
15372 }
15373 else
15374 {
15375 var = build_fold_addr_expr (var);
15376 gimplify_assign (x, var, &ilist);
15377 }
15378 }
b656be3a 15379 s = NULL_TREE;
15380 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
15381 {
15382 gcc_checking_assert (is_gimple_omp_oacc (ctx->stmt));
15383 s = TREE_TYPE (ovar);
15384 if (TREE_CODE (s) == REFERENCE_TYPE)
15385 s = TREE_TYPE (s);
15386 s = TYPE_SIZE_UNIT (s);
15387 }
15388 else
15389 s = OMP_CLAUSE_SIZE (c);
bc7bff74 15390 if (s == NULL_TREE)
15391 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
15392 s = fold_convert (size_type_node, s);
43895be5 15393 purpose = size_int (map_idx++);
bc7bff74 15394 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
15395 if (TREE_CODE (s) != INTEGER_CST)
15396 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
15397
43895be5 15398 unsigned HOST_WIDE_INT tkind, tkind_zero;
bc7bff74 15399 switch (OMP_CLAUSE_CODE (c))
15400 {
15401 case OMP_CLAUSE_MAP:
15402 tkind = OMP_CLAUSE_MAP_KIND (c);
43895be5 15403 tkind_zero = tkind;
15404 if (OMP_CLAUSE_MAP_MAYBE_ZERO_LENGTH_ARRAY_SECTION (c))
15405 switch (tkind)
15406 {
15407 case GOMP_MAP_ALLOC:
15408 case GOMP_MAP_TO:
15409 case GOMP_MAP_FROM:
15410 case GOMP_MAP_TOFROM:
15411 case GOMP_MAP_ALWAYS_TO:
15412 case GOMP_MAP_ALWAYS_FROM:
15413 case GOMP_MAP_ALWAYS_TOFROM:
15414 case GOMP_MAP_RELEASE:
15415 tkind_zero = GOMP_MAP_ZERO_LEN_ARRAY_SECTION;
15416 break;
15417 case GOMP_MAP_DELETE:
15418 tkind_zero = GOMP_MAP_DELETE_ZERO_LEN_ARRAY_SECTION;
15419 default:
15420 break;
15421 }
15422 if (tkind_zero != tkind)
15423 {
15424 if (integer_zerop (s))
15425 tkind = tkind_zero;
15426 else if (integer_nonzerop (s))
15427 tkind_zero = tkind;
15428 }
bc7bff74 15429 break;
b656be3a 15430 case OMP_CLAUSE_FIRSTPRIVATE:
15431 gcc_checking_assert (is_gimple_omp_oacc (ctx->stmt));
15432 tkind = GOMP_MAP_TO;
15433 tkind_zero = tkind;
15434 break;
bc7bff74 15435 case OMP_CLAUSE_TO:
ca4c3545 15436 tkind = GOMP_MAP_TO;
43895be5 15437 tkind_zero = tkind;
bc7bff74 15438 break;
15439 case OMP_CLAUSE_FROM:
ca4c3545 15440 tkind = GOMP_MAP_FROM;
43895be5 15441 tkind_zero = tkind;
bc7bff74 15442 break;
15443 default:
15444 gcc_unreachable ();
15445 }
ca4c3545 15446 gcc_checking_assert (tkind
15447 < (HOST_WIDE_INT_C (1U) << talign_shift));
43895be5 15448 gcc_checking_assert (tkind_zero
15449 < (HOST_WIDE_INT_C (1U) << talign_shift));
bc7bff74 15450 talign = ceil_log2 (talign);
ca4c3545 15451 tkind |= talign << talign_shift;
43895be5 15452 tkind_zero |= talign << talign_shift;
ca4c3545 15453 gcc_checking_assert (tkind
15454 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
43895be5 15455 gcc_checking_assert (tkind_zero
15456 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
15457 if (tkind == tkind_zero)
15458 x = build_int_cstu (tkind_type, tkind);
15459 else
15460 {
15461 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 0;
15462 x = build3 (COND_EXPR, tkind_type,
15463 fold_build2 (EQ_EXPR, boolean_type_node,
15464 unshare_expr (s), size_zero_node),
15465 build_int_cstu (tkind_type, tkind_zero),
15466 build_int_cstu (tkind_type, tkind));
15467 }
15468 CONSTRUCTOR_APPEND_ELT (vkind, purpose, x);
bc7bff74 15469 if (nc && nc != c)
15470 c = nc;
43895be5 15471 break;
15472
15473 case OMP_CLAUSE_FIRSTPRIVATE:
b656be3a 15474 if (is_oacc_parallel (ctx))
15475 goto oacc_firstprivate_map;
43895be5 15476 ovar = OMP_CLAUSE_DECL (c);
15477 if (is_reference (ovar))
15478 talign = TYPE_ALIGN_UNIT (TREE_TYPE (TREE_TYPE (ovar)));
15479 else
15480 talign = DECL_ALIGN_UNIT (ovar);
15481 var = lookup_decl_in_outer_ctx (ovar, ctx);
15482 x = build_sender_ref (ovar, ctx);
15483 tkind = GOMP_MAP_FIRSTPRIVATE;
15484 type = TREE_TYPE (ovar);
15485 if (is_reference (ovar))
15486 type = TREE_TYPE (type);
15487 bool use_firstprivate_int, force_addr;
15488 use_firstprivate_int = false;
15489 force_addr = false;
15490 if ((INTEGRAL_TYPE_P (type)
15491 && TYPE_PRECISION (type) <= POINTER_SIZE)
15492 || TREE_CODE (type) == POINTER_TYPE)
15493 use_firstprivate_int = true;
15494 if (has_depend)
15495 {
15496 if (is_reference (var))
15497 use_firstprivate_int = false;
15498 else if (is_gimple_reg (var))
15499 {
15500 if (DECL_HAS_VALUE_EXPR_P (var))
15501 {
15502 tree v = get_base_address (var);
15503 if (DECL_P (v) && TREE_ADDRESSABLE (v))
15504 {
15505 use_firstprivate_int = false;
15506 force_addr = true;
15507 }
15508 else
15509 switch (TREE_CODE (v))
15510 {
15511 case INDIRECT_REF:
15512 case MEM_REF:
15513 use_firstprivate_int = false;
15514 force_addr = true;
15515 break;
15516 default:
15517 break;
15518 }
15519 }
15520 }
15521 else
15522 use_firstprivate_int = false;
15523 }
15524 if (use_firstprivate_int)
15525 {
15526 tkind = GOMP_MAP_FIRSTPRIVATE_INT;
15527 tree t = var;
15528 if (is_reference (var))
15529 t = build_simple_mem_ref (var);
15530 if (TREE_CODE (type) != POINTER_TYPE)
15531 t = fold_convert (pointer_sized_int_node, t);
15532 t = fold_convert (TREE_TYPE (x), t);
15533 gimplify_assign (x, t, &ilist);
15534 }
15535 else if (is_reference (var))
15536 gimplify_assign (x, var, &ilist);
15537 else if (!force_addr && is_gimple_reg (var))
15538 {
15539 tree avar = create_tmp_var (TREE_TYPE (var));
15540 mark_addressable (avar);
15541 gimplify_assign (avar, var, &ilist);
15542 avar = build_fold_addr_expr (avar);
15543 gimplify_assign (x, avar, &ilist);
15544 }
15545 else
15546 {
15547 var = build_fold_addr_expr (var);
15548 gimplify_assign (x, var, &ilist);
15549 }
15550 if (tkind == GOMP_MAP_FIRSTPRIVATE_INT)
15551 s = size_int (0);
15552 else if (is_reference (var))
15553 s = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (ovar)));
15554 else
15555 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
15556 s = fold_convert (size_type_node, s);
15557 purpose = size_int (map_idx++);
15558 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
15559 if (TREE_CODE (s) != INTEGER_CST)
15560 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
15561
15562 gcc_checking_assert (tkind
15563 < (HOST_WIDE_INT_C (1U) << talign_shift));
15564 talign = ceil_log2 (talign);
15565 tkind |= talign << talign_shift;
15566 gcc_checking_assert (tkind
15567 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
15568 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
15569 build_int_cstu (tkind_type, tkind));
15570 break;
15571
15572 case OMP_CLAUSE_USE_DEVICE_PTR:
15573 case OMP_CLAUSE_IS_DEVICE_PTR:
15574 ovar = OMP_CLAUSE_DECL (c);
15575 var = lookup_decl_in_outer_ctx (ovar, ctx);
15576 x = build_sender_ref (ovar, ctx);
15577 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_PTR)
15578 tkind = GOMP_MAP_USE_DEVICE_PTR;
15579 else
15580 tkind = GOMP_MAP_FIRSTPRIVATE_INT;
15581 type = TREE_TYPE (ovar);
15582 if (TREE_CODE (type) == ARRAY_TYPE)
15583 var = build_fold_addr_expr (var);
15584 else
15585 {
15586 if (is_reference (ovar))
15587 {
15588 type = TREE_TYPE (type);
15589 if (TREE_CODE (type) != ARRAY_TYPE)
15590 var = build_simple_mem_ref (var);
15591 var = fold_convert (TREE_TYPE (x), var);
15592 }
15593 }
15594 gimplify_assign (x, var, &ilist);
15595 s = size_int (0);
15596 purpose = size_int (map_idx++);
15597 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
15598 gcc_checking_assert (tkind
15599 < (HOST_WIDE_INT_C (1U) << talign_shift));
15600 gcc_checking_assert (tkind
15601 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
15602 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
15603 build_int_cstu (tkind_type, tkind));
15604 break;
bc7bff74 15605 }
15606
15607 gcc_assert (map_idx == map_cnt);
15608
15609 DECL_INITIAL (TREE_VEC_ELT (t, 1))
15610 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)), vsize);
15611 DECL_INITIAL (TREE_VEC_ELT (t, 2))
15612 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 2)), vkind);
43895be5 15613 for (int i = 1; i <= 2; i++)
15614 if (!TREE_STATIC (TREE_VEC_ELT (t, i)))
15615 {
15616 gimple_seq initlist = NULL;
15617 force_gimple_operand (build1 (DECL_EXPR, void_type_node,
15618 TREE_VEC_ELT (t, i)),
15619 &initlist, true, NULL_TREE);
15620 gimple_seq_add_seq (&ilist, initlist);
15621
15622 tree clobber = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, i)),
15623 NULL);
15624 TREE_THIS_VOLATILE (clobber) = 1;
15625 gimple_seq_add_stmt (&olist,
15626 gimple_build_assign (TREE_VEC_ELT (t, i),
15627 clobber));
15628 }
bc7bff74 15629
15630 tree clobber = build_constructor (ctx->record_type, NULL);
15631 TREE_THIS_VOLATILE (clobber) = 1;
15632 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
15633 clobber));
15634 }
15635
15636 /* Once all the expansions are done, sequence all the different
15637 fragments inside gimple_omp_body. */
15638
15639 new_body = NULL;
15640
ca4c3545 15641 if (offloaded
15642 && ctx->record_type)
bc7bff74 15643 {
15644 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
15645 /* fixup_child_record_type might have changed receiver_decl's type. */
15646 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
15647 gimple_seq_add_stmt (&new_body,
15648 gimple_build_assign (ctx->receiver_decl, t));
15649 }
b656be3a 15650 gimple_seq_add_seq (&new_body, fplist);
bc7bff74 15651
43895be5 15652 if (offloaded || data_region)
bc7bff74 15653 {
43895be5 15654 tree prev = NULL_TREE;
15655 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
15656 switch (OMP_CLAUSE_CODE (c))
15657 {
15658 tree var, x;
15659 default:
15660 break;
15661 case OMP_CLAUSE_FIRSTPRIVATE:
b656be3a 15662 if (is_gimple_omp_oacc (ctx->stmt))
15663 break;
43895be5 15664 var = OMP_CLAUSE_DECL (c);
15665 if (is_reference (var)
15666 || is_gimple_reg_type (TREE_TYPE (var)))
15667 {
15668 tree new_var = lookup_decl (var, ctx);
15669 tree type;
15670 type = TREE_TYPE (var);
15671 if (is_reference (var))
15672 type = TREE_TYPE (type);
15673 bool use_firstprivate_int;
15674 use_firstprivate_int = false;
15675 if ((INTEGRAL_TYPE_P (type)
15676 && TYPE_PRECISION (type) <= POINTER_SIZE)
15677 || TREE_CODE (type) == POINTER_TYPE)
15678 use_firstprivate_int = true;
15679 if (has_depend)
15680 {
15681 tree v = lookup_decl_in_outer_ctx (var, ctx);
15682 if (is_reference (v))
15683 use_firstprivate_int = false;
15684 else if (is_gimple_reg (v))
15685 {
15686 if (DECL_HAS_VALUE_EXPR_P (v))
15687 {
15688 v = get_base_address (v);
15689 if (DECL_P (v) && TREE_ADDRESSABLE (v))
15690 use_firstprivate_int = false;
15691 else
15692 switch (TREE_CODE (v))
15693 {
15694 case INDIRECT_REF:
15695 case MEM_REF:
15696 use_firstprivate_int = false;
15697 break;
15698 default:
15699 break;
15700 }
15701 }
15702 }
15703 else
15704 use_firstprivate_int = false;
15705 }
15706 if (use_firstprivate_int)
15707 {
15708 x = build_receiver_ref (var, false, ctx);
15709 if (TREE_CODE (type) != POINTER_TYPE)
15710 x = fold_convert (pointer_sized_int_node, x);
15711 x = fold_convert (type, x);
15712 gimplify_expr (&x, &new_body, NULL, is_gimple_val,
15713 fb_rvalue);
15714 if (is_reference (var))
15715 {
15716 tree v = create_tmp_var_raw (type, get_name (var));
15717 gimple_add_tmp_var (v);
15718 TREE_ADDRESSABLE (v) = 1;
15719 gimple_seq_add_stmt (&new_body,
15720 gimple_build_assign (v, x));
15721 x = build_fold_addr_expr (v);
15722 }
15723 gimple_seq_add_stmt (&new_body,
15724 gimple_build_assign (new_var, x));
15725 }
15726 else
15727 {
15728 x = build_receiver_ref (var, !is_reference (var), ctx);
15729 gimplify_expr (&x, &new_body, NULL, is_gimple_val,
15730 fb_rvalue);
15731 gimple_seq_add_stmt (&new_body,
15732 gimple_build_assign (new_var, x));
15733 }
15734 }
15735 else if (is_variable_sized (var))
15736 {
15737 tree pvar = DECL_VALUE_EXPR (var);
15738 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15739 pvar = TREE_OPERAND (pvar, 0);
15740 gcc_assert (DECL_P (pvar));
15741 tree new_var = lookup_decl (pvar, ctx);
15742 x = build_receiver_ref (var, false, ctx);
15743 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
15744 gimple_seq_add_stmt (&new_body,
15745 gimple_build_assign (new_var, x));
15746 }
15747 break;
15748 case OMP_CLAUSE_PRIVATE:
b656be3a 15749 if (is_gimple_omp_oacc (ctx->stmt))
15750 break;
43895be5 15751 var = OMP_CLAUSE_DECL (c);
15752 if (is_reference (var))
15753 {
15754 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
15755 tree new_var = lookup_decl (var, ctx);
15756 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
15757 if (TREE_CONSTANT (x))
15758 {
15759 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
15760 get_name (var));
15761 gimple_add_tmp_var (x);
15762 TREE_ADDRESSABLE (x) = 1;
15763 x = build_fold_addr_expr_loc (clause_loc, x);
15764 }
15765 else
15766 {
15767 tree atmp
15768 = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
15769 tree rtype = TREE_TYPE (TREE_TYPE (new_var));
15770 tree al = size_int (TYPE_ALIGN (rtype));
15771 x = build_call_expr_loc (clause_loc, atmp, 2, x, al);
15772 }
15773
15774 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
15775 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
15776 gimple_seq_add_stmt (&new_body,
15777 gimple_build_assign (new_var, x));
15778 }
15779 break;
15780 case OMP_CLAUSE_USE_DEVICE_PTR:
15781 case OMP_CLAUSE_IS_DEVICE_PTR:
15782 var = OMP_CLAUSE_DECL (c);
15783 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_PTR)
15784 x = build_sender_ref (var, ctx);
15785 else
15786 x = build_receiver_ref (var, false, ctx);
15787 if (is_variable_sized (var))
15788 {
15789 tree pvar = DECL_VALUE_EXPR (var);
15790 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15791 pvar = TREE_OPERAND (pvar, 0);
15792 gcc_assert (DECL_P (pvar));
15793 tree new_var = lookup_decl (pvar, ctx);
15794 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
15795 gimple_seq_add_stmt (&new_body,
15796 gimple_build_assign (new_var, x));
15797 }
15798 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
15799 {
15800 tree new_var = lookup_decl (var, ctx);
15801 new_var = DECL_VALUE_EXPR (new_var);
15802 gcc_assert (TREE_CODE (new_var) == MEM_REF);
15803 new_var = TREE_OPERAND (new_var, 0);
15804 gcc_assert (DECL_P (new_var));
15805 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
15806 gimple_seq_add_stmt (&new_body,
15807 gimple_build_assign (new_var, x));
15808 }
15809 else
15810 {
15811 tree type = TREE_TYPE (var);
15812 tree new_var = lookup_decl (var, ctx);
15813 if (is_reference (var))
15814 {
15815 type = TREE_TYPE (type);
15816 if (TREE_CODE (type) != ARRAY_TYPE)
15817 {
15818 tree v = create_tmp_var_raw (type, get_name (var));
15819 gimple_add_tmp_var (v);
15820 TREE_ADDRESSABLE (v) = 1;
15821 x = fold_convert (type, x);
15822 gimplify_expr (&x, &new_body, NULL, is_gimple_val,
15823 fb_rvalue);
15824 gimple_seq_add_stmt (&new_body,
15825 gimple_build_assign (v, x));
15826 x = build_fold_addr_expr (v);
15827 }
15828 }
15829 x = fold_convert (TREE_TYPE (new_var), x);
15830 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
15831 gimple_seq_add_stmt (&new_body,
15832 gimple_build_assign (new_var, x));
15833 }
15834 break;
15835 }
9561765e 15836 /* Handle GOMP_MAP_FIRSTPRIVATE_{POINTER,REFERENCE} in second pass,
43895be5 15837 so that firstprivate vars holding OMP_CLAUSE_SIZE if needed
15838 are already handled. */
b656be3a 15839 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
43895be5 15840 switch (OMP_CLAUSE_CODE (c))
15841 {
15842 tree var;
15843 default:
15844 break;
15845 case OMP_CLAUSE_MAP:
9561765e 15846 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
15847 || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_REFERENCE)
43895be5 15848 {
15849 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
15850 HOST_WIDE_INT offset = 0;
15851 gcc_assert (prev);
15852 var = OMP_CLAUSE_DECL (c);
15853 if (DECL_P (var)
15854 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
15855 && is_global_var (maybe_lookup_decl_in_outer_ctx (var,
15856 ctx))
15857 && varpool_node::get_create (var)->offloadable)
15858 break;
15859 if (TREE_CODE (var) == INDIRECT_REF
15860 && TREE_CODE (TREE_OPERAND (var, 0)) == COMPONENT_REF)
15861 var = TREE_OPERAND (var, 0);
15862 if (TREE_CODE (var) == COMPONENT_REF)
15863 {
15864 var = get_addr_base_and_unit_offset (var, &offset);
15865 gcc_assert (var != NULL_TREE && DECL_P (var));
15866 }
15867 else if (DECL_SIZE (var)
15868 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
15869 {
15870 tree var2 = DECL_VALUE_EXPR (var);
15871 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
15872 var2 = TREE_OPERAND (var2, 0);
15873 gcc_assert (DECL_P (var2));
15874 var = var2;
15875 }
15876 tree new_var = lookup_decl (var, ctx), x;
15877 tree type = TREE_TYPE (new_var);
15878 bool is_ref;
15879 if (TREE_CODE (OMP_CLAUSE_DECL (c)) == INDIRECT_REF
15880 && (TREE_CODE (TREE_OPERAND (OMP_CLAUSE_DECL (c), 0))
15881 == COMPONENT_REF))
15882 {
15883 type = TREE_TYPE (TREE_OPERAND (OMP_CLAUSE_DECL (c), 0));
15884 is_ref = true;
15885 new_var = build2 (MEM_REF, type,
15886 build_fold_addr_expr (new_var),
15887 build_int_cst (build_pointer_type (type),
15888 offset));
15889 }
15890 else if (TREE_CODE (OMP_CLAUSE_DECL (c)) == COMPONENT_REF)
15891 {
15892 type = TREE_TYPE (OMP_CLAUSE_DECL (c));
15893 is_ref = TREE_CODE (type) == REFERENCE_TYPE;
15894 new_var = build2 (MEM_REF, type,
15895 build_fold_addr_expr (new_var),
15896 build_int_cst (build_pointer_type (type),
15897 offset));
15898 }
15899 else
15900 is_ref = is_reference (var);
9561765e 15901 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_REFERENCE)
15902 is_ref = false;
43895be5 15903 bool ref_to_array = false;
15904 if (is_ref)
15905 {
15906 type = TREE_TYPE (type);
15907 if (TREE_CODE (type) == ARRAY_TYPE)
15908 {
15909 type = build_pointer_type (type);
15910 ref_to_array = true;
15911 }
15912 }
15913 else if (TREE_CODE (type) == ARRAY_TYPE)
15914 {
15915 tree decl2 = DECL_VALUE_EXPR (new_var);
15916 gcc_assert (TREE_CODE (decl2) == MEM_REF);
15917 decl2 = TREE_OPERAND (decl2, 0);
15918 gcc_assert (DECL_P (decl2));
15919 new_var = decl2;
15920 type = TREE_TYPE (new_var);
15921 }
15922 x = build_receiver_ref (OMP_CLAUSE_DECL (prev), false, ctx);
15923 x = fold_convert_loc (clause_loc, type, x);
15924 if (!integer_zerop (OMP_CLAUSE_SIZE (c)))
15925 {
15926 tree bias = OMP_CLAUSE_SIZE (c);
15927 if (DECL_P (bias))
15928 bias = lookup_decl (bias, ctx);
15929 bias = fold_convert_loc (clause_loc, sizetype, bias);
15930 bias = fold_build1_loc (clause_loc, NEGATE_EXPR, sizetype,
15931 bias);
15932 x = fold_build2_loc (clause_loc, POINTER_PLUS_EXPR,
15933 TREE_TYPE (x), x, bias);
15934 }
15935 if (ref_to_array)
15936 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
15937 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
15938 if (is_ref && !ref_to_array)
15939 {
15940 tree t = create_tmp_var_raw (type, get_name (var));
15941 gimple_add_tmp_var (t);
15942 TREE_ADDRESSABLE (t) = 1;
15943 gimple_seq_add_stmt (&new_body,
15944 gimple_build_assign (t, x));
15945 x = build_fold_addr_expr_loc (clause_loc, t);
15946 }
15947 gimple_seq_add_stmt (&new_body,
15948 gimple_build_assign (new_var, x));
15949 prev = NULL_TREE;
15950 }
15951 else if (OMP_CLAUSE_CHAIN (c)
15952 && OMP_CLAUSE_CODE (OMP_CLAUSE_CHAIN (c))
15953 == OMP_CLAUSE_MAP
9561765e 15954 && (OMP_CLAUSE_MAP_KIND (OMP_CLAUSE_CHAIN (c))
15955 == GOMP_MAP_FIRSTPRIVATE_POINTER
15956 || (OMP_CLAUSE_MAP_KIND (OMP_CLAUSE_CHAIN (c))
15957 == GOMP_MAP_FIRSTPRIVATE_REFERENCE)))
43895be5 15958 prev = c;
15959 break;
15960 case OMP_CLAUSE_PRIVATE:
15961 var = OMP_CLAUSE_DECL (c);
15962 if (is_variable_sized (var))
15963 {
15964 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
15965 tree new_var = lookup_decl (var, ctx);
15966 tree pvar = DECL_VALUE_EXPR (var);
15967 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15968 pvar = TREE_OPERAND (pvar, 0);
15969 gcc_assert (DECL_P (pvar));
15970 tree new_pvar = lookup_decl (pvar, ctx);
15971 tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
15972 tree al = size_int (DECL_ALIGN (var));
15973 tree x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
15974 x = build_call_expr_loc (clause_loc, atmp, 2, x, al);
15975 x = fold_convert_loc (clause_loc, TREE_TYPE (new_pvar), x);
15976 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
15977 gimple_seq_add_stmt (&new_body,
15978 gimple_build_assign (new_pvar, x));
15979 }
15980 break;
15981 }
2eab8648 15982
641a0fa1 15983 gimple_seq fork_seq = NULL;
15984 gimple_seq join_seq = NULL;
15985
15986 if (is_oacc_parallel (ctx))
15987 {
15988 /* If there are reductions on the offloaded region itself, treat
15989 them as a dummy GANG loop. */
15990 tree level = build_int_cst (integer_type_node, GOMP_DIM_GANG);
15991
15992 lower_oacc_reductions (gimple_location (ctx->stmt), clauses, level,
15993 false, NULL, NULL, &fork_seq, &join_seq, ctx);
15994 }
15995
15996 gimple_seq_add_seq (&new_body, fork_seq);
bc7bff74 15997 gimple_seq_add_seq (&new_body, tgt_body);
641a0fa1 15998 gimple_seq_add_seq (&new_body, join_seq);
2eab8648 15999
43895be5 16000 if (offloaded)
16001 new_body = maybe_catch_exception (new_body);
2eab8648 16002
bc7bff74 16003 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
16004 gimple_omp_set_body (stmt, new_body);
16005 }
16006
16007 bind = gimple_build_bind (NULL, NULL,
16008 tgt_bind ? gimple_bind_block (tgt_bind)
16009 : NULL_TREE);
43895be5 16010 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
e3a19533 16011 gimple_bind_add_seq (bind, ilist);
16012 gimple_bind_add_stmt (bind, stmt);
16013 gimple_bind_add_seq (bind, olist);
773c5ba7 16014
75a70cf9 16015 pop_gimplify_context (NULL);
43895be5 16016
16017 if (dep_bind)
16018 {
16019 gimple_bind_add_seq (dep_bind, dep_ilist);
16020 gimple_bind_add_stmt (dep_bind, bind);
16021 gimple_bind_add_seq (dep_bind, dep_olist);
16022 pop_gimplify_context (dep_bind);
16023 }
773c5ba7 16024}
16025
bc7bff74 16026/* Expand code for an OpenMP teams directive. */
16027
16028static void
16029lower_omp_teams (gimple_stmt_iterator *gsi_p, omp_context *ctx)
16030{
1a91d914 16031 gomp_teams *teams_stmt = as_a <gomp_teams *> (gsi_stmt (*gsi_p));
8a4a28a8 16032 push_gimplify_context ();
bc7bff74 16033
16034 tree block = make_node (BLOCK);
1a91d914 16035 gbind *bind = gimple_build_bind (NULL, NULL, block);
bc7bff74 16036 gsi_replace (gsi_p, bind, true);
16037 gimple_seq bind_body = NULL;
16038 gimple_seq dlist = NULL;
16039 gimple_seq olist = NULL;
16040
16041 tree num_teams = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
16042 OMP_CLAUSE_NUM_TEAMS);
16043 if (num_teams == NULL_TREE)
16044 num_teams = build_int_cst (unsigned_type_node, 0);
16045 else
16046 {
16047 num_teams = OMP_CLAUSE_NUM_TEAMS_EXPR (num_teams);
16048 num_teams = fold_convert (unsigned_type_node, num_teams);
16049 gimplify_expr (&num_teams, &bind_body, NULL, is_gimple_val, fb_rvalue);
16050 }
16051 tree thread_limit = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
16052 OMP_CLAUSE_THREAD_LIMIT);
16053 if (thread_limit == NULL_TREE)
16054 thread_limit = build_int_cst (unsigned_type_node, 0);
16055 else
16056 {
16057 thread_limit = OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit);
16058 thread_limit = fold_convert (unsigned_type_node, thread_limit);
16059 gimplify_expr (&thread_limit, &bind_body, NULL, is_gimple_val,
16060 fb_rvalue);
16061 }
16062
16063 lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt),
16064 &bind_body, &dlist, ctx, NULL);
16065 lower_omp (gimple_omp_body_ptr (teams_stmt), ctx);
16066 lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt), &olist, ctx);
16067 gimple_seq_add_stmt (&bind_body, teams_stmt);
16068
16069 location_t loc = gimple_location (teams_stmt);
16070 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TEAMS);
42acab1c 16071 gimple *call = gimple_build_call (decl, 2, num_teams, thread_limit);
bc7bff74 16072 gimple_set_location (call, loc);
16073 gimple_seq_add_stmt (&bind_body, call);
16074
16075 gimple_seq_add_seq (&bind_body, gimple_omp_body (teams_stmt));
16076 gimple_omp_set_body (teams_stmt, NULL);
16077 gimple_seq_add_seq (&bind_body, olist);
16078 gimple_seq_add_seq (&bind_body, dlist);
16079 gimple_seq_add_stmt (&bind_body, gimple_build_omp_return (true));
16080 gimple_bind_set_body (bind, bind_body);
16081
16082 pop_gimplify_context (bind);
16083
16084 gimple_bind_append_vars (bind, ctx->block_vars);
16085 BLOCK_VARS (block) = ctx->block_vars;
16086 if (BLOCK_VARS (block))
16087 TREE_USED (block) = 1;
16088}
16089
16090
a4890dc9 16091/* Callback for lower_omp_1. Return non-NULL if *tp needs to be
75a70cf9 16092 regimplified. If DATA is non-NULL, lower_omp_1 is outside
ca4c3545 16093 of OMP context, but with task_shared_vars set. */
46515c92 16094
16095static tree
75a70cf9 16096lower_omp_regimplify_p (tree *tp, int *walk_subtrees,
16097 void *data)
46515c92 16098{
a4890dc9 16099 tree t = *tp;
46515c92 16100
a4890dc9 16101 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
75a70cf9 16102 if (TREE_CODE (t) == VAR_DECL && data == NULL && DECL_HAS_VALUE_EXPR_P (t))
9f49e155 16103 return t;
16104
16105 if (task_shared_vars
16106 && DECL_P (t)
16107 && bitmap_bit_p (task_shared_vars, DECL_UID (t)))
a4890dc9 16108 return t;
46515c92 16109
a4890dc9 16110 /* If a global variable has been privatized, TREE_CONSTANT on
16111 ADDR_EXPR might be wrong. */
75a70cf9 16112 if (data == NULL && TREE_CODE (t) == ADDR_EXPR)
a4890dc9 16113 recompute_tree_invariant_for_addr_expr (t);
46515c92 16114
43895be5 16115 *walk_subtrees = !IS_TYPE_OR_DECL_P (t);
16116 return NULL_TREE;
16117}
16118
16119/* Data to be communicated between lower_omp_regimplify_operands and
16120 lower_omp_regimplify_operands_p. */
16121
16122struct lower_omp_regimplify_operands_data
16123{
16124 omp_context *ctx;
16125 vec<tree> *decls;
16126};
16127
16128/* Helper function for lower_omp_regimplify_operands. Find
16129 omp_member_access_dummy_var vars and adjust temporarily their
16130 DECL_VALUE_EXPRs if needed. */
16131
16132static tree
16133lower_omp_regimplify_operands_p (tree *tp, int *walk_subtrees,
16134 void *data)
16135{
16136 tree t = omp_member_access_dummy_var (*tp);
16137 if (t)
16138 {
16139 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
16140 lower_omp_regimplify_operands_data *ldata
16141 = (lower_omp_regimplify_operands_data *) wi->info;
16142 tree o = maybe_lookup_decl (t, ldata->ctx);
16143 if (o != t)
16144 {
16145 ldata->decls->safe_push (DECL_VALUE_EXPR (*tp));
16146 ldata->decls->safe_push (*tp);
16147 tree v = unshare_and_remap (DECL_VALUE_EXPR (*tp), t, o);
16148 SET_DECL_VALUE_EXPR (*tp, v);
16149 }
16150 }
16151 *walk_subtrees = !IS_TYPE_OR_DECL_P (*tp);
a4890dc9 16152 return NULL_TREE;
46515c92 16153}
773c5ba7 16154
43895be5 16155/* Wrapper around gimple_regimplify_operands that adjusts DECL_VALUE_EXPRs
16156 of omp_member_access_dummy_var vars during regimplification. */
16157
16158static void
16159lower_omp_regimplify_operands (omp_context *ctx, gimple *stmt,
16160 gimple_stmt_iterator *gsi_p)
16161{
16162 auto_vec<tree, 10> decls;
16163 if (ctx)
16164 {
16165 struct walk_stmt_info wi;
16166 memset (&wi, '\0', sizeof (wi));
16167 struct lower_omp_regimplify_operands_data data;
16168 data.ctx = ctx;
16169 data.decls = &decls;
16170 wi.info = &data;
16171 walk_gimple_op (stmt, lower_omp_regimplify_operands_p, &wi);
16172 }
16173 gimple_regimplify_operands (stmt, gsi_p);
16174 while (!decls.is_empty ())
16175 {
16176 tree t = decls.pop ();
16177 tree v = decls.pop ();
16178 SET_DECL_VALUE_EXPR (t, v);
16179 }
16180}
16181
a4890dc9 16182static void
75a70cf9 16183lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
1e8e9920 16184{
42acab1c 16185 gimple *stmt = gsi_stmt (*gsi_p);
75a70cf9 16186 struct walk_stmt_info wi;
1a91d914 16187 gcall *call_stmt;
1e8e9920 16188
75a70cf9 16189 if (gimple_has_location (stmt))
16190 input_location = gimple_location (stmt);
a4890dc9 16191
75a70cf9 16192 if (task_shared_vars)
16193 memset (&wi, '\0', sizeof (wi));
a4890dc9 16194
773c5ba7 16195 /* If we have issued syntax errors, avoid doing any heavy lifting.
ca4c3545 16196 Just replace the OMP directives with a NOP to avoid
773c5ba7 16197 confusing RTL expansion. */
852f689e 16198 if (seen_error () && is_gimple_omp (stmt))
773c5ba7 16199 {
75a70cf9 16200 gsi_replace (gsi_p, gimple_build_nop (), true);
a4890dc9 16201 return;
773c5ba7 16202 }
16203
75a70cf9 16204 switch (gimple_code (stmt))
1e8e9920 16205 {
75a70cf9 16206 case GIMPLE_COND:
1a91d914 16207 {
16208 gcond *cond_stmt = as_a <gcond *> (stmt);
16209 if ((ctx || task_shared_vars)
16210 && (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
16211 lower_omp_regimplify_p,
16212 ctx ? NULL : &wi, NULL)
16213 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
16214 lower_omp_regimplify_p,
16215 ctx ? NULL : &wi, NULL)))
43895be5 16216 lower_omp_regimplify_operands (ctx, cond_stmt, gsi_p);
1a91d914 16217 }
a4890dc9 16218 break;
75a70cf9 16219 case GIMPLE_CATCH:
1a91d914 16220 lower_omp (gimple_catch_handler_ptr (as_a <gcatch *> (stmt)), ctx);
a4890dc9 16221 break;
75a70cf9 16222 case GIMPLE_EH_FILTER:
e3a19533 16223 lower_omp (gimple_eh_filter_failure_ptr (stmt), ctx);
a4890dc9 16224 break;
75a70cf9 16225 case GIMPLE_TRY:
e3a19533 16226 lower_omp (gimple_try_eval_ptr (stmt), ctx);
16227 lower_omp (gimple_try_cleanup_ptr (stmt), ctx);
a4890dc9 16228 break;
35215227 16229 case GIMPLE_TRANSACTION:
1a91d914 16230 lower_omp (gimple_transaction_body_ptr (
16231 as_a <gtransaction *> (stmt)),
16232 ctx);
35215227 16233 break;
75a70cf9 16234 case GIMPLE_BIND:
1a91d914 16235 lower_omp (gimple_bind_body_ptr (as_a <gbind *> (stmt)), ctx);
a4890dc9 16236 break;
75a70cf9 16237 case GIMPLE_OMP_PARALLEL:
16238 case GIMPLE_OMP_TASK:
16239 ctx = maybe_lookup_ctx (stmt);
bc7bff74 16240 gcc_assert (ctx);
16241 if (ctx->cancellable)
16242 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
75a70cf9 16243 lower_omp_taskreg (gsi_p, ctx);
a4890dc9 16244 break;
75a70cf9 16245 case GIMPLE_OMP_FOR:
16246 ctx = maybe_lookup_ctx (stmt);
1e8e9920 16247 gcc_assert (ctx);
bc7bff74 16248 if (ctx->cancellable)
16249 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
75a70cf9 16250 lower_omp_for (gsi_p, ctx);
1e8e9920 16251 break;
75a70cf9 16252 case GIMPLE_OMP_SECTIONS:
16253 ctx = maybe_lookup_ctx (stmt);
1e8e9920 16254 gcc_assert (ctx);
bc7bff74 16255 if (ctx->cancellable)
16256 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
75a70cf9 16257 lower_omp_sections (gsi_p, ctx);
1e8e9920 16258 break;
75a70cf9 16259 case GIMPLE_OMP_SINGLE:
16260 ctx = maybe_lookup_ctx (stmt);
1e8e9920 16261 gcc_assert (ctx);
75a70cf9 16262 lower_omp_single (gsi_p, ctx);
1e8e9920 16263 break;
75a70cf9 16264 case GIMPLE_OMP_MASTER:
16265 ctx = maybe_lookup_ctx (stmt);
1e8e9920 16266 gcc_assert (ctx);
75a70cf9 16267 lower_omp_master (gsi_p, ctx);
1e8e9920 16268 break;
bc7bff74 16269 case GIMPLE_OMP_TASKGROUP:
16270 ctx = maybe_lookup_ctx (stmt);
16271 gcc_assert (ctx);
16272 lower_omp_taskgroup (gsi_p, ctx);
16273 break;
75a70cf9 16274 case GIMPLE_OMP_ORDERED:
16275 ctx = maybe_lookup_ctx (stmt);
1e8e9920 16276 gcc_assert (ctx);
75a70cf9 16277 lower_omp_ordered (gsi_p, ctx);
1e8e9920 16278 break;
75a70cf9 16279 case GIMPLE_OMP_CRITICAL:
16280 ctx = maybe_lookup_ctx (stmt);
1e8e9920 16281 gcc_assert (ctx);
75a70cf9 16282 lower_omp_critical (gsi_p, ctx);
16283 break;
16284 case GIMPLE_OMP_ATOMIC_LOAD:
16285 if ((ctx || task_shared_vars)
1a91d914 16286 && walk_tree (gimple_omp_atomic_load_rhs_ptr (
16287 as_a <gomp_atomic_load *> (stmt)),
75a70cf9 16288 lower_omp_regimplify_p, ctx ? NULL : &wi, NULL))
43895be5 16289 lower_omp_regimplify_operands (ctx, stmt, gsi_p);
1e8e9920 16290 break;
bc7bff74 16291 case GIMPLE_OMP_TARGET:
16292 ctx = maybe_lookup_ctx (stmt);
16293 gcc_assert (ctx);
16294 lower_omp_target (gsi_p, ctx);
16295 break;
16296 case GIMPLE_OMP_TEAMS:
16297 ctx = maybe_lookup_ctx (stmt);
16298 gcc_assert (ctx);
16299 lower_omp_teams (gsi_p, ctx);
16300 break;
16301 case GIMPLE_CALL:
16302 tree fndecl;
1a91d914 16303 call_stmt = as_a <gcall *> (stmt);
16304 fndecl = gimple_call_fndecl (call_stmt);
bc7bff74 16305 if (fndecl
16306 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
16307 switch (DECL_FUNCTION_CODE (fndecl))
16308 {
16309 case BUILT_IN_GOMP_BARRIER:
16310 if (ctx == NULL)
16311 break;
16312 /* FALLTHRU */
16313 case BUILT_IN_GOMP_CANCEL:
16314 case BUILT_IN_GOMP_CANCELLATION_POINT:
16315 omp_context *cctx;
16316 cctx = ctx;
16317 if (gimple_code (cctx->stmt) == GIMPLE_OMP_SECTION)
16318 cctx = cctx->outer;
1a91d914 16319 gcc_assert (gimple_call_lhs (call_stmt) == NULL_TREE);
bc7bff74 16320 if (!cctx->cancellable)
16321 {
16322 if (DECL_FUNCTION_CODE (fndecl)
16323 == BUILT_IN_GOMP_CANCELLATION_POINT)
16324 {
16325 stmt = gimple_build_nop ();
16326 gsi_replace (gsi_p, stmt, false);
16327 }
16328 break;
16329 }
bc7bff74 16330 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
16331 {
16332 fndecl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL);
1a91d914 16333 gimple_call_set_fndecl (call_stmt, fndecl);
16334 gimple_call_set_fntype (call_stmt, TREE_TYPE (fndecl));
bc7bff74 16335 }
15b28553 16336 tree lhs;
f9e245b2 16337 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (fndecl)));
1a91d914 16338 gimple_call_set_lhs (call_stmt, lhs);
bc7bff74 16339 tree fallthru_label;
16340 fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
42acab1c 16341 gimple *g;
bc7bff74 16342 g = gimple_build_label (fallthru_label);
16343 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
15b28553 16344 g = gimple_build_cond (NE_EXPR, lhs,
16345 fold_convert (TREE_TYPE (lhs),
16346 boolean_false_node),
bc7bff74 16347 cctx->cancel_label, fallthru_label);
16348 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
16349 break;
16350 default:
16351 break;
16352 }
16353 /* FALLTHRU */
a4890dc9 16354 default:
fd6481cf 16355 if ((ctx || task_shared_vars)
75a70cf9 16356 && walk_gimple_op (stmt, lower_omp_regimplify_p,
16357 ctx ? NULL : &wi))
ef8cfd4d 16358 {
16359 /* Just remove clobbers, this should happen only if we have
16360 "privatized" local addressable variables in SIMD regions,
16361 the clobber isn't needed in that case and gimplifying address
16362 of the ARRAY_REF into a pointer and creating MEM_REF based
16363 clobber would create worse code than we get with the clobber
16364 dropped. */
16365 if (gimple_clobber_p (stmt))
16366 {
16367 gsi_replace (gsi_p, gimple_build_nop (), true);
16368 break;
16369 }
43895be5 16370 lower_omp_regimplify_operands (ctx, stmt, gsi_p);
ef8cfd4d 16371 }
1e8e9920 16372 break;
1e8e9920 16373 }
1e8e9920 16374}
16375
16376static void
e3a19533 16377lower_omp (gimple_seq *body, omp_context *ctx)
1e8e9920 16378{
1d22f541 16379 location_t saved_location = input_location;
e3a19533 16380 gimple_stmt_iterator gsi;
16381 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
75a70cf9 16382 lower_omp_1 (&gsi, ctx);
ca4c3545 16383 /* During gimplification, we haven't folded statments inside offloading
c3a81971 16384 or taskreg regions (gimplify.c:maybe_fold_stmt); do that now. */
16385 if (target_nesting_level || taskreg_nesting_level)
bc7bff74 16386 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
16387 fold_stmt (&gsi);
1d22f541 16388 input_location = saved_location;
1e8e9920 16389}
16390\f
16391/* Main entry point. */
16392
2a1990e9 16393static unsigned int
1e8e9920 16394execute_lower_omp (void)
16395{
75a70cf9 16396 gimple_seq body;
37eaded9 16397 int i;
16398 omp_context *ctx;
75a70cf9 16399
41709826 16400 /* This pass always runs, to provide PROP_gimple_lomp.
ca4c3545 16401 But often, there is nothing to do. */
16402 if (flag_cilkplus == 0 && flag_openacc == 0 && flag_openmp == 0
16403 && flag_openmp_simd == 0)
41709826 16404 return 0;
16405
1e8e9920 16406 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
16407 delete_omp_context);
16408
75a70cf9 16409 body = gimple_body (current_function_decl);
ab129075 16410 scan_omp (&body, NULL);
fd6481cf 16411 gcc_assert (taskreg_nesting_level == 0);
37eaded9 16412 FOR_EACH_VEC_ELT (taskreg_contexts, i, ctx)
16413 finish_taskreg_scan (ctx);
16414 taskreg_contexts.release ();
1e8e9920 16415
16416 if (all_contexts->root)
fd6481cf 16417 {
16418 if (task_shared_vars)
8a4a28a8 16419 push_gimplify_context ();
e3a19533 16420 lower_omp (&body, NULL);
fd6481cf 16421 if (task_shared_vars)
16422 pop_gimplify_context (NULL);
16423 }
1e8e9920 16424
773c5ba7 16425 if (all_contexts)
16426 {
16427 splay_tree_delete (all_contexts);
16428 all_contexts = NULL;
16429 }
fd6481cf 16430 BITMAP_FREE (task_shared_vars);
2a1990e9 16431 return 0;
1e8e9920 16432}
16433
7620bc82 16434namespace {
16435
16436const pass_data pass_data_lower_omp =
cbe8bda8 16437{
16438 GIMPLE_PASS, /* type */
16439 "omplower", /* name */
16440 OPTGROUP_NONE, /* optinfo_flags */
cbe8bda8 16441 TV_NONE, /* tv_id */
16442 PROP_gimple_any, /* properties_required */
16443 PROP_gimple_lomp, /* properties_provided */
16444 0, /* properties_destroyed */
16445 0, /* todo_flags_start */
16446 0, /* todo_flags_finish */
1e8e9920 16447};
cbe8bda8 16448
7620bc82 16449class pass_lower_omp : public gimple_opt_pass
cbe8bda8 16450{
16451public:
9af5ce0c 16452 pass_lower_omp (gcc::context *ctxt)
16453 : gimple_opt_pass (pass_data_lower_omp, ctxt)
cbe8bda8 16454 {}
16455
16456 /* opt_pass methods: */
65b0537f 16457 virtual unsigned int execute (function *) { return execute_lower_omp (); }
cbe8bda8 16458
16459}; // class pass_lower_omp
16460
7620bc82 16461} // anon namespace
16462
cbe8bda8 16463gimple_opt_pass *
16464make_pass_lower_omp (gcc::context *ctxt)
16465{
16466 return new pass_lower_omp (ctxt);
16467}
1e8e9920 16468\f
ca4c3545 16469/* The following is a utility to diagnose structured block violations.
61e47ac8 16470 It is not part of the "omplower" pass, as that's invoked too late. It
16471 should be invoked by the respective front ends after gimplification. */
1e8e9920 16472
16473static splay_tree all_labels;
16474
16475/* Check for mismatched contexts and generate an error if needed. Return
16476 true if an error is detected. */
16477
16478static bool
75a70cf9 16479diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
42acab1c 16480 gimple *branch_ctx, gimple *label_ctx)
1e8e9920 16481{
ca4c3545 16482 gcc_checking_assert (!branch_ctx || is_gimple_omp (branch_ctx));
16483 gcc_checking_assert (!label_ctx || is_gimple_omp (label_ctx));
16484
75a70cf9 16485 if (label_ctx == branch_ctx)
1e8e9920 16486 return false;
16487
ca4c3545 16488 const char* kind = NULL;
16489
16490 if (flag_cilkplus)
16491 {
16492 if ((branch_ctx
16493 && gimple_code (branch_ctx) == GIMPLE_OMP_FOR
16494 && gimple_omp_for_kind (branch_ctx) == GF_OMP_FOR_KIND_CILKSIMD)
16495 || (label_ctx
16496 && gimple_code (label_ctx) == GIMPLE_OMP_FOR
16497 && gimple_omp_for_kind (label_ctx) == GF_OMP_FOR_KIND_CILKSIMD))
16498 kind = "Cilk Plus";
16499 }
16500 if (flag_openacc)
16501 {
16502 if ((branch_ctx && is_gimple_omp_oacc (branch_ctx))
16503 || (label_ctx && is_gimple_omp_oacc (label_ctx)))
16504 {
16505 gcc_checking_assert (kind == NULL);
16506 kind = "OpenACC";
16507 }
16508 }
16509 if (kind == NULL)
16510 {
16511 gcc_checking_assert (flag_openmp);
16512 kind = "OpenMP";
16513 }
48e1416a 16514
75a70cf9 16515 /*
16516 Previously we kept track of the label's entire context in diagnose_sb_[12]
16517 so we could traverse it and issue a correct "exit" or "enter" error
16518 message upon a structured block violation.
16519
16520 We built the context by building a list with tree_cons'ing, but there is
16521 no easy counterpart in gimple tuples. It seems like far too much work
16522 for issuing exit/enter error messages. If someone really misses the
16523 distinct error message... patches welcome.
16524 */
48e1416a 16525
75a70cf9 16526#if 0
1e8e9920 16527 /* Try to avoid confusing the user by producing and error message
f0b5f617 16528 with correct "exit" or "enter" verbiage. We prefer "exit"
1e8e9920 16529 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
16530 if (branch_ctx == NULL)
16531 exit_p = false;
16532 else
16533 {
16534 while (label_ctx)
16535 {
16536 if (TREE_VALUE (label_ctx) == branch_ctx)
16537 {
16538 exit_p = false;
16539 break;
16540 }
16541 label_ctx = TREE_CHAIN (label_ctx);
16542 }
16543 }
16544
16545 if (exit_p)
ca4c3545 16546 error ("invalid exit from %s structured block", kind);
1e8e9920 16547 else
ca4c3545 16548 error ("invalid entry to %s structured block", kind);
75a70cf9 16549#endif
1e8e9920 16550
75a70cf9 16551 /* If it's obvious we have an invalid entry, be specific about the error. */
16552 if (branch_ctx == NULL)
ca4c3545 16553 error ("invalid entry to %s structured block", kind);
75a70cf9 16554 else
f2697631 16555 {
16556 /* Otherwise, be vague and lazy, but efficient. */
ca4c3545 16557 error ("invalid branch to/from %s structured block", kind);
f2697631 16558 }
75a70cf9 16559
16560 gsi_replace (gsi_p, gimple_build_nop (), false);
1e8e9920 16561 return true;
16562}
16563
ca4c3545 16564/* Pass 1: Create a minimal tree of structured blocks, and record
75a70cf9 16565 where each label is found. */
1e8e9920 16566
16567static tree
75a70cf9 16568diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
16569 struct walk_stmt_info *wi)
1e8e9920 16570{
42acab1c 16571 gimple *context = (gimple *) wi->info;
16572 gimple *inner_context;
16573 gimple *stmt = gsi_stmt (*gsi_p);
1e8e9920 16574
75a70cf9 16575 *handled_ops_p = true;
16576
ca4c3545 16577 switch (gimple_code (stmt))
1e8e9920 16578 {
75a70cf9 16579 WALK_SUBSTMTS;
48e1416a 16580
75a70cf9 16581 case GIMPLE_OMP_PARALLEL:
16582 case GIMPLE_OMP_TASK:
16583 case GIMPLE_OMP_SECTIONS:
16584 case GIMPLE_OMP_SINGLE:
16585 case GIMPLE_OMP_SECTION:
16586 case GIMPLE_OMP_MASTER:
16587 case GIMPLE_OMP_ORDERED:
16588 case GIMPLE_OMP_CRITICAL:
bc7bff74 16589 case GIMPLE_OMP_TARGET:
16590 case GIMPLE_OMP_TEAMS:
16591 case GIMPLE_OMP_TASKGROUP:
75a70cf9 16592 /* The minimal context here is just the current OMP construct. */
16593 inner_context = stmt;
1e8e9920 16594 wi->info = inner_context;
75a70cf9 16595 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
1e8e9920 16596 wi->info = context;
16597 break;
16598
75a70cf9 16599 case GIMPLE_OMP_FOR:
16600 inner_context = stmt;
1e8e9920 16601 wi->info = inner_context;
75a70cf9 16602 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
16603 walk them. */
16604 walk_gimple_seq (gimple_omp_for_pre_body (stmt),
16605 diagnose_sb_1, NULL, wi);
16606 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
1e8e9920 16607 wi->info = context;
16608 break;
16609
75a70cf9 16610 case GIMPLE_LABEL:
1a91d914 16611 splay_tree_insert (all_labels,
16612 (splay_tree_key) gimple_label_label (
16613 as_a <glabel *> (stmt)),
1e8e9920 16614 (splay_tree_value) context);
16615 break;
16616
16617 default:
16618 break;
16619 }
16620
16621 return NULL_TREE;
16622}
16623
16624/* Pass 2: Check each branch and see if its context differs from that of
16625 the destination label's context. */
16626
16627static tree
75a70cf9 16628diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
16629 struct walk_stmt_info *wi)
1e8e9920 16630{
42acab1c 16631 gimple *context = (gimple *) wi->info;
1e8e9920 16632 splay_tree_node n;
42acab1c 16633 gimple *stmt = gsi_stmt (*gsi_p);
1e8e9920 16634
75a70cf9 16635 *handled_ops_p = true;
16636
16637 switch (gimple_code (stmt))
1e8e9920 16638 {
75a70cf9 16639 WALK_SUBSTMTS;
16640
16641 case GIMPLE_OMP_PARALLEL:
16642 case GIMPLE_OMP_TASK:
16643 case GIMPLE_OMP_SECTIONS:
16644 case GIMPLE_OMP_SINGLE:
16645 case GIMPLE_OMP_SECTION:
16646 case GIMPLE_OMP_MASTER:
16647 case GIMPLE_OMP_ORDERED:
16648 case GIMPLE_OMP_CRITICAL:
bc7bff74 16649 case GIMPLE_OMP_TARGET:
16650 case GIMPLE_OMP_TEAMS:
16651 case GIMPLE_OMP_TASKGROUP:
75a70cf9 16652 wi->info = stmt;
e3a19533 16653 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
1e8e9920 16654 wi->info = context;
16655 break;
16656
75a70cf9 16657 case GIMPLE_OMP_FOR:
16658 wi->info = stmt;
16659 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
16660 walk them. */
e3a19533 16661 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt),
16662 diagnose_sb_2, NULL, wi);
16663 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
1e8e9920 16664 wi->info = context;
16665 break;
16666
0e1818e7 16667 case GIMPLE_COND:
16668 {
1a91d914 16669 gcond *cond_stmt = as_a <gcond *> (stmt);
16670 tree lab = gimple_cond_true_label (cond_stmt);
0e1818e7 16671 if (lab)
16672 {
16673 n = splay_tree_lookup (all_labels,
16674 (splay_tree_key) lab);
16675 diagnose_sb_0 (gsi_p, context,
42acab1c 16676 n ? (gimple *) n->value : NULL);
0e1818e7 16677 }
1a91d914 16678 lab = gimple_cond_false_label (cond_stmt);
0e1818e7 16679 if (lab)
16680 {
16681 n = splay_tree_lookup (all_labels,
16682 (splay_tree_key) lab);
16683 diagnose_sb_0 (gsi_p, context,
42acab1c 16684 n ? (gimple *) n->value : NULL);
0e1818e7 16685 }
16686 }
16687 break;
16688
75a70cf9 16689 case GIMPLE_GOTO:
1e8e9920 16690 {
75a70cf9 16691 tree lab = gimple_goto_dest (stmt);
1e8e9920 16692 if (TREE_CODE (lab) != LABEL_DECL)
16693 break;
16694
16695 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
42acab1c 16696 diagnose_sb_0 (gsi_p, context, n ? (gimple *) n->value : NULL);
1e8e9920 16697 }
16698 break;
16699
75a70cf9 16700 case GIMPLE_SWITCH:
1e8e9920 16701 {
1a91d914 16702 gswitch *switch_stmt = as_a <gswitch *> (stmt);
75a70cf9 16703 unsigned int i;
1a91d914 16704 for (i = 0; i < gimple_switch_num_labels (switch_stmt); ++i)
1e8e9920 16705 {
1a91d914 16706 tree lab = CASE_LABEL (gimple_switch_label (switch_stmt, i));
1e8e9920 16707 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
42acab1c 16708 if (n && diagnose_sb_0 (gsi_p, context, (gimple *) n->value))
1e8e9920 16709 break;
16710 }
16711 }
16712 break;
16713
75a70cf9 16714 case GIMPLE_RETURN:
16715 diagnose_sb_0 (gsi_p, context, NULL);
1e8e9920 16716 break;
16717
16718 default:
16719 break;
16720 }
16721
16722 return NULL_TREE;
16723}
16724
ca4c3545 16725/* Called from tree-cfg.c::make_edges to create cfg edges for all relevant
16726 GIMPLE_* codes. */
7740abd8 16727bool
b2c0e0b7 16728make_gimple_omp_edges (basic_block bb, struct omp_region **region,
16729 int *region_idx)
7740abd8 16730{
42acab1c 16731 gimple *last = last_stmt (bb);
7740abd8 16732 enum gimple_code code = gimple_code (last);
16733 struct omp_region *cur_region = *region;
16734 bool fallthru = false;
16735
16736 switch (code)
16737 {
16738 case GIMPLE_OMP_PARALLEL:
16739 case GIMPLE_OMP_TASK:
16740 case GIMPLE_OMP_FOR:
16741 case GIMPLE_OMP_SINGLE:
16742 case GIMPLE_OMP_TEAMS:
16743 case GIMPLE_OMP_MASTER:
16744 case GIMPLE_OMP_TASKGROUP:
7740abd8 16745 case GIMPLE_OMP_CRITICAL:
16746 case GIMPLE_OMP_SECTION:
16747 cur_region = new_omp_region (bb, code, cur_region);
16748 fallthru = true;
16749 break;
16750
43895be5 16751 case GIMPLE_OMP_ORDERED:
16752 cur_region = new_omp_region (bb, code, cur_region);
16753 fallthru = true;
16754 if (find_omp_clause (gimple_omp_ordered_clauses
16755 (as_a <gomp_ordered *> (last)),
16756 OMP_CLAUSE_DEPEND))
16757 cur_region = cur_region->outer;
16758 break;
16759
7740abd8 16760 case GIMPLE_OMP_TARGET:
16761 cur_region = new_omp_region (bb, code, cur_region);
16762 fallthru = true;
ca4c3545 16763 switch (gimple_omp_target_kind (last))
16764 {
16765 case GF_OMP_TARGET_KIND_REGION:
16766 case GF_OMP_TARGET_KIND_DATA:
16767 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
16768 case GF_OMP_TARGET_KIND_OACC_KERNELS:
16769 case GF_OMP_TARGET_KIND_OACC_DATA:
16770 break;
16771 case GF_OMP_TARGET_KIND_UPDATE:
43895be5 16772 case GF_OMP_TARGET_KIND_ENTER_DATA:
16773 case GF_OMP_TARGET_KIND_EXIT_DATA:
ca4c3545 16774 case GF_OMP_TARGET_KIND_OACC_UPDATE:
16775 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
2fc5e987 16776 case GF_OMP_TARGET_KIND_OACC_DECLARE:
ca4c3545 16777 cur_region = cur_region->outer;
16778 break;
16779 default:
16780 gcc_unreachable ();
16781 }
7740abd8 16782 break;
16783
16784 case GIMPLE_OMP_SECTIONS:
16785 cur_region = new_omp_region (bb, code, cur_region);
16786 fallthru = true;
16787 break;
16788
16789 case GIMPLE_OMP_SECTIONS_SWITCH:
16790 fallthru = false;
16791 break;
16792
16793 case GIMPLE_OMP_ATOMIC_LOAD:
16794 case GIMPLE_OMP_ATOMIC_STORE:
16795 fallthru = true;
16796 break;
16797
16798 case GIMPLE_OMP_RETURN:
16799 /* In the case of a GIMPLE_OMP_SECTION, the edge will go
16800 somewhere other than the next block. This will be
16801 created later. */
16802 cur_region->exit = bb;
b25f70fd 16803 if (cur_region->type == GIMPLE_OMP_TASK)
16804 /* Add an edge corresponding to not scheduling the task
16805 immediately. */
16806 make_edge (cur_region->entry, bb, EDGE_ABNORMAL);
7740abd8 16807 fallthru = cur_region->type != GIMPLE_OMP_SECTION;
16808 cur_region = cur_region->outer;
16809 break;
16810
16811 case GIMPLE_OMP_CONTINUE:
16812 cur_region->cont = bb;
16813 switch (cur_region->type)
16814 {
16815 case GIMPLE_OMP_FOR:
16816 /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
16817 succs edges as abnormal to prevent splitting
16818 them. */
16819 single_succ_edge (cur_region->entry)->flags |= EDGE_ABNORMAL;
16820 /* Make the loopback edge. */
16821 make_edge (bb, single_succ (cur_region->entry),
16822 EDGE_ABNORMAL);
16823
16824 /* Create an edge from GIMPLE_OMP_FOR to exit, which
16825 corresponds to the case that the body of the loop
16826 is not executed at all. */
16827 make_edge (cur_region->entry, bb->next_bb, EDGE_ABNORMAL);
16828 make_edge (bb, bb->next_bb, EDGE_FALLTHRU | EDGE_ABNORMAL);
16829 fallthru = false;
16830 break;
16831
16832 case GIMPLE_OMP_SECTIONS:
16833 /* Wire up the edges into and out of the nested sections. */
16834 {
16835 basic_block switch_bb = single_succ (cur_region->entry);
16836
16837 struct omp_region *i;
16838 for (i = cur_region->inner; i ; i = i->next)
16839 {
16840 gcc_assert (i->type == GIMPLE_OMP_SECTION);
16841 make_edge (switch_bb, i->entry, 0);
16842 make_edge (i->exit, bb, EDGE_FALLTHRU);
16843 }
16844
16845 /* Make the loopback edge to the block with
16846 GIMPLE_OMP_SECTIONS_SWITCH. */
16847 make_edge (bb, switch_bb, 0);
16848
16849 /* Make the edge from the switch to exit. */
16850 make_edge (switch_bb, bb->next_bb, 0);
16851 fallthru = false;
16852 }
16853 break;
16854
b25f70fd 16855 case GIMPLE_OMP_TASK:
16856 fallthru = true;
16857 break;
16858
7740abd8 16859 default:
16860 gcc_unreachable ();
16861 }
16862 break;
16863
16864 default:
16865 gcc_unreachable ();
16866 }
16867
16868 if (*region != cur_region)
b2c0e0b7 16869 {
16870 *region = cur_region;
16871 if (cur_region)
16872 *region_idx = cur_region->entry->index;
16873 else
16874 *region_idx = 0;
16875 }
7740abd8 16876
16877 return fallthru;
16878}
16879
bfec3452 16880static unsigned int
16881diagnose_omp_structured_block_errors (void)
1e8e9920 16882{
1e8e9920 16883 struct walk_stmt_info wi;
bfec3452 16884 gimple_seq body = gimple_body (current_function_decl);
1e8e9920 16885
16886 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
16887
16888 memset (&wi, 0, sizeof (wi));
75a70cf9 16889 walk_gimple_seq (body, diagnose_sb_1, NULL, &wi);
1e8e9920 16890
16891 memset (&wi, 0, sizeof (wi));
1e8e9920 16892 wi.want_locations = true;
e3a19533 16893 walk_gimple_seq_mod (&body, diagnose_sb_2, NULL, &wi);
16894
16895 gimple_set_body (current_function_decl, body);
1e8e9920 16896
16897 splay_tree_delete (all_labels);
16898 all_labels = NULL;
16899
bfec3452 16900 return 0;
1e8e9920 16901}
16902
7620bc82 16903namespace {
16904
16905const pass_data pass_data_diagnose_omp_blocks =
cbe8bda8 16906{
16907 GIMPLE_PASS, /* type */
16908 "*diagnose_omp_blocks", /* name */
16909 OPTGROUP_NONE, /* optinfo_flags */
cbe8bda8 16910 TV_NONE, /* tv_id */
16911 PROP_gimple_any, /* properties_required */
16912 0, /* properties_provided */
16913 0, /* properties_destroyed */
16914 0, /* todo_flags_start */
16915 0, /* todo_flags_finish */
bfec3452 16916};
16917
7620bc82 16918class pass_diagnose_omp_blocks : public gimple_opt_pass
cbe8bda8 16919{
16920public:
9af5ce0c 16921 pass_diagnose_omp_blocks (gcc::context *ctxt)
16922 : gimple_opt_pass (pass_data_diagnose_omp_blocks, ctxt)
cbe8bda8 16923 {}
16924
16925 /* opt_pass methods: */
ca4c3545 16926 virtual bool gate (function *)
16927 {
16928 return flag_cilkplus || flag_openacc || flag_openmp;
16929 }
65b0537f 16930 virtual unsigned int execute (function *)
16931 {
16932 return diagnose_omp_structured_block_errors ();
16933 }
cbe8bda8 16934
16935}; // class pass_diagnose_omp_blocks
16936
7620bc82 16937} // anon namespace
16938
cbe8bda8 16939gimple_opt_pass *
16940make_pass_diagnose_omp_blocks (gcc::context *ctxt)
16941{
16942 return new pass_diagnose_omp_blocks (ctxt);
16943}
d09768a4 16944\f
16945/* SIMD clone supporting code. */
16946
16947/* Allocate a fresh `simd_clone' and return it. NARGS is the number
16948 of arguments to reserve space for. */
16949
16950static struct cgraph_simd_clone *
16951simd_clone_struct_alloc (int nargs)
16952{
16953 struct cgraph_simd_clone *clone_info;
16954 size_t len = (sizeof (struct cgraph_simd_clone)
16955 + nargs * sizeof (struct cgraph_simd_clone_arg));
16956 clone_info = (struct cgraph_simd_clone *)
ea7d8c7a 16957 ggc_internal_cleared_alloc (len);
d09768a4 16958 return clone_info;
16959}
16960
16961/* Make a copy of the `struct cgraph_simd_clone' in FROM to TO. */
16962
16963static inline void
16964simd_clone_struct_copy (struct cgraph_simd_clone *to,
16965 struct cgraph_simd_clone *from)
16966{
16967 memcpy (to, from, (sizeof (struct cgraph_simd_clone)
46c0fd4b 16968 + ((from->nargs - from->inbranch)
16969 * sizeof (struct cgraph_simd_clone_arg))));
d09768a4 16970}
16971
16972/* Return vector of parameter types of function FNDECL. This uses
16973 TYPE_ARG_TYPES if available, otherwise falls back to types of
16974 DECL_ARGUMENTS types. */
16975
16976vec<tree>
16977simd_clone_vector_of_formal_parm_types (tree fndecl)
16978{
16979 if (TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
16980 return ipa_get_vector_of_formal_parm_types (TREE_TYPE (fndecl));
16981 vec<tree> args = ipa_get_vector_of_formal_parms (fndecl);
16982 unsigned int i;
16983 tree arg;
16984 FOR_EACH_VEC_ELT (args, i, arg)
16985 args[i] = TREE_TYPE (args[i]);
16986 return args;
16987}
16988
16989/* Given a simd function in NODE, extract the simd specific
16990 information from the OMP clauses passed in CLAUSES, and return
16991 the struct cgraph_simd_clone * if it should be cloned. *INBRANCH_SPECIFIED
16992 is set to TRUE if the `inbranch' or `notinbranch' clause specified,
16993 otherwise set to FALSE. */
16994
16995static struct cgraph_simd_clone *
16996simd_clone_clauses_extract (struct cgraph_node *node, tree clauses,
16997 bool *inbranch_specified)
16998{
16999 vec<tree> args = simd_clone_vector_of_formal_parm_types (node->decl);
17000 tree t;
17001 int n;
17002 *inbranch_specified = false;
17003
17004 n = args.length ();
17005 if (n > 0 && args.last () == void_type_node)
17006 n--;
17007
17008 /* To distinguish from an OpenMP simd clone, Cilk Plus functions to
17009 be cloned have a distinctive artificial label in addition to "omp
17010 declare simd". */
17011 bool cilk_clone
a89e6c15 17012 = (flag_cilkplus
74acc703 17013 && lookup_attribute ("cilk simd function",
d09768a4 17014 DECL_ATTRIBUTES (node->decl)));
17015
17016 /* Allocate one more than needed just in case this is an in-branch
17017 clone which will require a mask argument. */
17018 struct cgraph_simd_clone *clone_info = simd_clone_struct_alloc (n + 1);
17019 clone_info->nargs = n;
17020 clone_info->cilk_elemental = cilk_clone;
17021
17022 if (!clauses)
17023 {
17024 args.release ();
17025 return clone_info;
17026 }
17027 clauses = TREE_VALUE (clauses);
17028 if (!clauses || TREE_CODE (clauses) != OMP_CLAUSE)
17029 return clone_info;
17030
17031 for (t = clauses; t; t = OMP_CLAUSE_CHAIN (t))
17032 {
17033 switch (OMP_CLAUSE_CODE (t))
17034 {
17035 case OMP_CLAUSE_INBRANCH:
17036 clone_info->inbranch = 1;
17037 *inbranch_specified = true;
17038 break;
17039 case OMP_CLAUSE_NOTINBRANCH:
17040 clone_info->inbranch = 0;
17041 *inbranch_specified = true;
17042 break;
17043 case OMP_CLAUSE_SIMDLEN:
17044 clone_info->simdlen
17045 = TREE_INT_CST_LOW (OMP_CLAUSE_SIMDLEN_EXPR (t));
17046 break;
17047 case OMP_CLAUSE_LINEAR:
17048 {
17049 tree decl = OMP_CLAUSE_DECL (t);
17050 tree step = OMP_CLAUSE_LINEAR_STEP (t);
17051 int argno = TREE_INT_CST_LOW (decl);
17052 if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (t))
17053 {
9561765e 17054 enum cgraph_simd_clone_arg_type arg_type;
17055 if (TREE_CODE (args[argno]) == REFERENCE_TYPE)
17056 switch (OMP_CLAUSE_LINEAR_KIND (t))
17057 {
17058 case OMP_CLAUSE_LINEAR_REF:
17059 arg_type
17060 = SIMD_CLONE_ARG_TYPE_LINEAR_REF_VARIABLE_STEP;
17061 break;
17062 case OMP_CLAUSE_LINEAR_UVAL:
17063 arg_type
17064 = SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_VARIABLE_STEP;
17065 break;
17066 case OMP_CLAUSE_LINEAR_VAL:
17067 case OMP_CLAUSE_LINEAR_DEFAULT:
17068 arg_type
17069 = SIMD_CLONE_ARG_TYPE_LINEAR_VAL_VARIABLE_STEP;
17070 break;
17071 default:
17072 gcc_unreachable ();
17073 }
17074 else
17075 arg_type = SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP;
17076 clone_info->args[argno].arg_type = arg_type;
d09768a4 17077 clone_info->args[argno].linear_step = tree_to_shwi (step);
17078 gcc_assert (clone_info->args[argno].linear_step >= 0
17079 && clone_info->args[argno].linear_step < n);
17080 }
17081 else
17082 {
17083 if (POINTER_TYPE_P (args[argno]))
17084 step = fold_convert (ssizetype, step);
17085 if (!tree_fits_shwi_p (step))
17086 {
17087 warning_at (OMP_CLAUSE_LOCATION (t), 0,
17088 "ignoring large linear step");
17089 args.release ();
17090 return NULL;
17091 }
17092 else if (integer_zerop (step))
17093 {
17094 warning_at (OMP_CLAUSE_LOCATION (t), 0,
17095 "ignoring zero linear step");
17096 args.release ();
17097 return NULL;
17098 }
17099 else
17100 {
43895be5 17101 enum cgraph_simd_clone_arg_type arg_type;
17102 if (TREE_CODE (args[argno]) == REFERENCE_TYPE)
17103 switch (OMP_CLAUSE_LINEAR_KIND (t))
17104 {
17105 case OMP_CLAUSE_LINEAR_REF:
17106 arg_type
17107 = SIMD_CLONE_ARG_TYPE_LINEAR_REF_CONSTANT_STEP;
17108 break;
17109 case OMP_CLAUSE_LINEAR_UVAL:
17110 arg_type
17111 = SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP;
17112 break;
17113 case OMP_CLAUSE_LINEAR_VAL:
17114 case OMP_CLAUSE_LINEAR_DEFAULT:
17115 arg_type
17116 = SIMD_CLONE_ARG_TYPE_LINEAR_VAL_CONSTANT_STEP;
17117 break;
17118 default:
17119 gcc_unreachable ();
17120 }
17121 else
17122 arg_type = SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP;
17123 clone_info->args[argno].arg_type = arg_type;
d09768a4 17124 clone_info->args[argno].linear_step = tree_to_shwi (step);
17125 }
17126 }
17127 break;
17128 }
17129 case OMP_CLAUSE_UNIFORM:
17130 {
17131 tree decl = OMP_CLAUSE_DECL (t);
17132 int argno = tree_to_uhwi (decl);
17133 clone_info->args[argno].arg_type
17134 = SIMD_CLONE_ARG_TYPE_UNIFORM;
17135 break;
17136 }
17137 case OMP_CLAUSE_ALIGNED:
17138 {
17139 tree decl = OMP_CLAUSE_DECL (t);
17140 int argno = tree_to_uhwi (decl);
17141 clone_info->args[argno].alignment
17142 = TREE_INT_CST_LOW (OMP_CLAUSE_ALIGNED_ALIGNMENT (t));
17143 break;
17144 }
17145 default:
17146 break;
17147 }
17148 }
17149 args.release ();
17150 return clone_info;
17151}
17152
17153/* Given a SIMD clone in NODE, calculate the characteristic data
17154 type and return the coresponding type. The characteristic data
17155 type is computed as described in the Intel Vector ABI. */
17156
17157static tree
17158simd_clone_compute_base_data_type (struct cgraph_node *node,
17159 struct cgraph_simd_clone *clone_info)
17160{
17161 tree type = integer_type_node;
17162 tree fndecl = node->decl;
17163
17164 /* a) For non-void function, the characteristic data type is the
17165 return type. */
17166 if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) != VOID_TYPE)
17167 type = TREE_TYPE (TREE_TYPE (fndecl));
17168
17169 /* b) If the function has any non-uniform, non-linear parameters,
17170 then the characteristic data type is the type of the first
17171 such parameter. */
17172 else
17173 {
17174 vec<tree> map = simd_clone_vector_of_formal_parm_types (fndecl);
17175 for (unsigned int i = 0; i < clone_info->nargs; ++i)
17176 if (clone_info->args[i].arg_type == SIMD_CLONE_ARG_TYPE_VECTOR)
17177 {
17178 type = map[i];
17179 break;
17180 }
17181 map.release ();
17182 }
17183
17184 /* c) If the characteristic data type determined by a) or b) above
17185 is struct, union, or class type which is pass-by-value (except
17186 for the type that maps to the built-in complex data type), the
17187 characteristic data type is int. */
17188 if (RECORD_OR_UNION_TYPE_P (type)
17189 && !aggregate_value_p (type, NULL)
17190 && TREE_CODE (type) != COMPLEX_TYPE)
17191 return integer_type_node;
17192
17193 /* d) If none of the above three classes is applicable, the
17194 characteristic data type is int. */
17195
17196 return type;
17197
17198 /* e) For Intel Xeon Phi native and offload compilation, if the
17199 resulting characteristic data type is 8-bit or 16-bit integer
17200 data type, the characteristic data type is int. */
17201 /* Well, we don't handle Xeon Phi yet. */
17202}
17203
17204static tree
17205simd_clone_mangle (struct cgraph_node *node,
17206 struct cgraph_simd_clone *clone_info)
17207{
17208 char vecsize_mangle = clone_info->vecsize_mangle;
17209 char mask = clone_info->inbranch ? 'M' : 'N';
17210 unsigned int simdlen = clone_info->simdlen;
17211 unsigned int n;
17212 pretty_printer pp;
17213
17214 gcc_assert (vecsize_mangle && simdlen);
17215
17216 pp_string (&pp, "_ZGV");
17217 pp_character (&pp, vecsize_mangle);
17218 pp_character (&pp, mask);
17219 pp_decimal_int (&pp, simdlen);
17220
17221 for (n = 0; n < clone_info->nargs; ++n)
17222 {
17223 struct cgraph_simd_clone_arg arg = clone_info->args[n];
17224
43895be5 17225 switch (arg.arg_type)
d09768a4 17226 {
43895be5 17227 case SIMD_CLONE_ARG_TYPE_UNIFORM:
17228 pp_character (&pp, 'u');
17229 break;
17230 case SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP:
d09768a4 17231 pp_character (&pp, 'l');
43895be5 17232 goto mangle_linear;
17233 case SIMD_CLONE_ARG_TYPE_LINEAR_REF_CONSTANT_STEP:
17234 pp_character (&pp, 'R');
17235 goto mangle_linear;
17236 case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_CONSTANT_STEP:
17237 pp_character (&pp, 'L');
17238 goto mangle_linear;
17239 case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP:
17240 pp_character (&pp, 'U');
17241 goto mangle_linear;
17242 mangle_linear:
17243 gcc_assert (arg.linear_step != 0);
d09768a4 17244 if (arg.linear_step > 1)
17245 pp_unsigned_wide_integer (&pp, arg.linear_step);
17246 else if (arg.linear_step < 0)
17247 {
17248 pp_character (&pp, 'n');
17249 pp_unsigned_wide_integer (&pp, (-(unsigned HOST_WIDE_INT)
17250 arg.linear_step));
17251 }
43895be5 17252 break;
17253 case SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP:
9561765e 17254 pp_string (&pp, "ls");
17255 pp_unsigned_wide_integer (&pp, arg.linear_step);
17256 break;
17257 case SIMD_CLONE_ARG_TYPE_LINEAR_REF_VARIABLE_STEP:
17258 pp_string (&pp, "Rs");
17259 pp_unsigned_wide_integer (&pp, arg.linear_step);
17260 break;
17261 case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_VARIABLE_STEP:
17262 pp_string (&pp, "Ls");
17263 pp_unsigned_wide_integer (&pp, arg.linear_step);
17264 break;
17265 case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_VARIABLE_STEP:
17266 pp_string (&pp, "Us");
d09768a4 17267 pp_unsigned_wide_integer (&pp, arg.linear_step);
43895be5 17268 break;
17269 default:
17270 pp_character (&pp, 'v');
d09768a4 17271 }
d09768a4 17272 if (arg.alignment)
17273 {
17274 pp_character (&pp, 'a');
17275 pp_decimal_int (&pp, arg.alignment);
17276 }
17277 }
17278
17279 pp_underscore (&pp);
4e4baaad 17280 const char *str = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl));
17281 if (*str == '*')
17282 ++str;
17283 pp_string (&pp, str);
17284 str = pp_formatted_text (&pp);
d09768a4 17285
17286 /* If there already is a SIMD clone with the same mangled name, don't
17287 add another one. This can happen e.g. for
17288 #pragma omp declare simd
17289 #pragma omp declare simd simdlen(8)
17290 int foo (int, int);
17291 if the simdlen is assumed to be 8 for the first one, etc. */
17292 for (struct cgraph_node *clone = node->simd_clones; clone;
17293 clone = clone->simdclone->next_clone)
17294 if (strcmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (clone->decl)),
17295 str) == 0)
17296 return NULL_TREE;
17297
17298 return get_identifier (str);
17299}
17300
17301/* Create a simd clone of OLD_NODE and return it. */
17302
17303static struct cgraph_node *
17304simd_clone_create (struct cgraph_node *old_node)
17305{
17306 struct cgraph_node *new_node;
17307 if (old_node->definition)
ea0695f9 17308 {
415d1b9a 17309 if (!old_node->has_gimple_body_p ())
ea0695f9 17310 return NULL;
415d1b9a 17311 old_node->get_body ();
17312 new_node = old_node->create_version_clone_with_body (vNULL, NULL, NULL,
17313 false, NULL, NULL,
17314 "simdclone");
ea0695f9 17315 }
d09768a4 17316 else
17317 {
17318 tree old_decl = old_node->decl;
17319 tree new_decl = copy_node (old_node->decl);
17320 DECL_NAME (new_decl) = clone_function_name (old_decl, "simdclone");
17321 SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl));
17322 SET_DECL_RTL (new_decl, NULL);
17323 DECL_STATIC_CONSTRUCTOR (new_decl) = 0;
17324 DECL_STATIC_DESTRUCTOR (new_decl) = 0;
415d1b9a 17325 new_node = old_node->create_version_clone (new_decl, vNULL, NULL);
64c7c74a 17326 if (old_node->in_other_partition)
17327 new_node->in_other_partition = 1;
35ee1c66 17328 symtab->call_cgraph_insertion_hooks (new_node);
d09768a4 17329 }
17330 if (new_node == NULL)
17331 return new_node;
17332
17333 TREE_PUBLIC (new_node->decl) = TREE_PUBLIC (old_node->decl);
17334
17335 /* The function cgraph_function_versioning () will force the new
17336 symbol local. Undo this, and inherit external visability from
17337 the old node. */
17338 new_node->local.local = old_node->local.local;
17339 new_node->externally_visible = old_node->externally_visible;
17340
17341 return new_node;
17342}
17343
17344/* Adjust the return type of the given function to its appropriate
17345 vector counterpart. Returns a simd array to be used throughout the
17346 function as a return value. */
17347
17348static tree
17349simd_clone_adjust_return_type (struct cgraph_node *node)
17350{
17351 tree fndecl = node->decl;
17352 tree orig_rettype = TREE_TYPE (TREE_TYPE (fndecl));
17353 unsigned int veclen;
17354 tree t;
17355
17356 /* Adjust the function return type. */
17357 if (orig_rettype == void_type_node)
17358 return NULL_TREE;
17359 TREE_TYPE (fndecl) = build_distinct_type_copy (TREE_TYPE (fndecl));
fdf7662c 17360 t = TREE_TYPE (TREE_TYPE (fndecl));
17361 if (INTEGRAL_TYPE_P (t) || POINTER_TYPE_P (t))
d09768a4 17362 veclen = node->simdclone->vecsize_int;
17363 else
17364 veclen = node->simdclone->vecsize_float;
fdf7662c 17365 veclen /= GET_MODE_BITSIZE (TYPE_MODE (t));
d09768a4 17366 if (veclen > node->simdclone->simdlen)
17367 veclen = node->simdclone->simdlen;
fdf7662c 17368 if (POINTER_TYPE_P (t))
17369 t = pointer_sized_int_node;
d09768a4 17370 if (veclen == node->simdclone->simdlen)
fdf7662c 17371 t = build_vector_type (t, node->simdclone->simdlen);
d09768a4 17372 else
17373 {
fdf7662c 17374 t = build_vector_type (t, veclen);
d09768a4 17375 t = build_array_type_nelts (t, node->simdclone->simdlen / veclen);
d09768a4 17376 }
fdf7662c 17377 TREE_TYPE (TREE_TYPE (fndecl)) = t;
d09768a4 17378 if (!node->definition)
17379 return NULL_TREE;
17380
17381 t = DECL_RESULT (fndecl);
17382 /* Adjust the DECL_RESULT. */
17383 gcc_assert (TREE_TYPE (t) != void_type_node);
17384 TREE_TYPE (t) = TREE_TYPE (TREE_TYPE (fndecl));
17385 relayout_decl (t);
17386
17387 tree atype = build_array_type_nelts (orig_rettype,
17388 node->simdclone->simdlen);
17389 if (veclen != node->simdclone->simdlen)
17390 return build1 (VIEW_CONVERT_EXPR, atype, t);
17391
17392 /* Set up a SIMD array to use as the return value. */
17393 tree retval = create_tmp_var_raw (atype, "retval");
17394 gimple_add_tmp_var (retval);
17395 return retval;
17396}
17397
17398/* Each vector argument has a corresponding array to be used locally
17399 as part of the eventual loop. Create such temporary array and
17400 return it.
17401
17402 PREFIX is the prefix to be used for the temporary.
17403
17404 TYPE is the inner element type.
17405
17406 SIMDLEN is the number of elements. */
17407
17408static tree
17409create_tmp_simd_array (const char *prefix, tree type, int simdlen)
17410{
17411 tree atype = build_array_type_nelts (type, simdlen);
17412 tree avar = create_tmp_var_raw (atype, prefix);
17413 gimple_add_tmp_var (avar);
17414 return avar;
17415}
17416
17417/* Modify the function argument types to their corresponding vector
17418 counterparts if appropriate. Also, create one array for each simd
17419 argument to be used locally when using the function arguments as
17420 part of the loop.
17421
17422 NODE is the function whose arguments are to be adjusted.
17423
17424 Returns an adjustment vector that will be filled describing how the
17425 argument types will be adjusted. */
17426
17427static ipa_parm_adjustment_vec
17428simd_clone_adjust_argument_types (struct cgraph_node *node)
17429{
17430 vec<tree> args;
17431 ipa_parm_adjustment_vec adjustments;
17432
17433 if (node->definition)
17434 args = ipa_get_vector_of_formal_parms (node->decl);
17435 else
17436 args = simd_clone_vector_of_formal_parm_types (node->decl);
17437 adjustments.create (args.length ());
17438 unsigned i, j, veclen;
17439 struct ipa_parm_adjustment adj;
17440 for (i = 0; i < node->simdclone->nargs; ++i)
17441 {
17442 memset (&adj, 0, sizeof (adj));
17443 tree parm = args[i];
17444 tree parm_type = node->definition ? TREE_TYPE (parm) : parm;
17445 adj.base_index = i;
17446 adj.base = parm;
17447
17448 node->simdclone->args[i].orig_arg = node->definition ? parm : NULL_TREE;
17449 node->simdclone->args[i].orig_type = parm_type;
17450
43895be5 17451 switch (node->simdclone->args[i].arg_type)
d09768a4 17452 {
43895be5 17453 default:
d09768a4 17454 /* No adjustment necessary for scalar arguments. */
17455 adj.op = IPA_PARM_OP_COPY;
43895be5 17456 break;
17457 case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP:
9561765e 17458 case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_VARIABLE_STEP:
43895be5 17459 if (node->definition)
17460 node->simdclone->args[i].simd_array
17461 = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm)),
17462 TREE_TYPE (parm_type),
17463 node->simdclone->simdlen);
17464 adj.op = IPA_PARM_OP_COPY;
17465 break;
17466 case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_CONSTANT_STEP:
9561765e 17467 case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_VARIABLE_STEP:
43895be5 17468 case SIMD_CLONE_ARG_TYPE_VECTOR:
d09768a4 17469 if (INTEGRAL_TYPE_P (parm_type) || POINTER_TYPE_P (parm_type))
17470 veclen = node->simdclone->vecsize_int;
17471 else
17472 veclen = node->simdclone->vecsize_float;
17473 veclen /= GET_MODE_BITSIZE (TYPE_MODE (parm_type));
17474 if (veclen > node->simdclone->simdlen)
17475 veclen = node->simdclone->simdlen;
17476 adj.arg_prefix = "simd";
fdf7662c 17477 if (POINTER_TYPE_P (parm_type))
17478 adj.type = build_vector_type (pointer_sized_int_node, veclen);
17479 else
17480 adj.type = build_vector_type (parm_type, veclen);
d09768a4 17481 node->simdclone->args[i].vector_type = adj.type;
17482 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
17483 {
17484 adjustments.safe_push (adj);
17485 if (j == veclen)
17486 {
17487 memset (&adj, 0, sizeof (adj));
17488 adj.op = IPA_PARM_OP_NEW;
17489 adj.arg_prefix = "simd";
17490 adj.base_index = i;
17491 adj.type = node->simdclone->args[i].vector_type;
17492 }
17493 }
17494
17495 if (node->definition)
17496 node->simdclone->args[i].simd_array
17497 = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm)),
17498 parm_type, node->simdclone->simdlen);
17499 }
17500 adjustments.safe_push (adj);
17501 }
17502
17503 if (node->simdclone->inbranch)
17504 {
17505 tree base_type
17506 = simd_clone_compute_base_data_type (node->simdclone->origin,
17507 node->simdclone);
17508
17509 memset (&adj, 0, sizeof (adj));
17510 adj.op = IPA_PARM_OP_NEW;
17511 adj.arg_prefix = "mask";
17512
17513 adj.base_index = i;
17514 if (INTEGRAL_TYPE_P (base_type) || POINTER_TYPE_P (base_type))
17515 veclen = node->simdclone->vecsize_int;
17516 else
17517 veclen = node->simdclone->vecsize_float;
17518 veclen /= GET_MODE_BITSIZE (TYPE_MODE (base_type));
17519 if (veclen > node->simdclone->simdlen)
17520 veclen = node->simdclone->simdlen;
fdf7662c 17521 if (POINTER_TYPE_P (base_type))
17522 adj.type = build_vector_type (pointer_sized_int_node, veclen);
17523 else
17524 adj.type = build_vector_type (base_type, veclen);
d09768a4 17525 adjustments.safe_push (adj);
17526
17527 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
17528 adjustments.safe_push (adj);
17529
17530 /* We have previously allocated one extra entry for the mask. Use
17531 it and fill it. */
17532 struct cgraph_simd_clone *sc = node->simdclone;
17533 sc->nargs++;
17534 if (node->definition)
17535 {
17536 sc->args[i].orig_arg
17537 = build_decl (UNKNOWN_LOCATION, PARM_DECL, NULL, base_type);
17538 sc->args[i].simd_array
17539 = create_tmp_simd_array ("mask", base_type, sc->simdlen);
17540 }
17541 sc->args[i].orig_type = base_type;
17542 sc->args[i].arg_type = SIMD_CLONE_ARG_TYPE_MASK;
17543 }
17544
17545 if (node->definition)
17546 ipa_modify_formal_parameters (node->decl, adjustments);
17547 else
17548 {
17549 tree new_arg_types = NULL_TREE, new_reversed;
17550 bool last_parm_void = false;
17551 if (args.length () > 0 && args.last () == void_type_node)
17552 last_parm_void = true;
17553
17554 gcc_assert (TYPE_ARG_TYPES (TREE_TYPE (node->decl)));
17555 j = adjustments.length ();
17556 for (i = 0; i < j; i++)
17557 {
17558 struct ipa_parm_adjustment *adj = &adjustments[i];
17559 tree ptype;
17560 if (adj->op == IPA_PARM_OP_COPY)
17561 ptype = args[adj->base_index];
17562 else
17563 ptype = adj->type;
17564 new_arg_types = tree_cons (NULL_TREE, ptype, new_arg_types);
17565 }
17566 new_reversed = nreverse (new_arg_types);
17567 if (last_parm_void)
17568 {
17569 if (new_reversed)
17570 TREE_CHAIN (new_arg_types) = void_list_node;
17571 else
17572 new_reversed = void_list_node;
17573 }
17574
17575 tree new_type = build_distinct_type_copy (TREE_TYPE (node->decl));
17576 TYPE_ARG_TYPES (new_type) = new_reversed;
17577 TREE_TYPE (node->decl) = new_type;
17578
17579 adjustments.release ();
17580 }
17581 args.release ();
17582 return adjustments;
17583}
17584
17585/* Initialize and copy the function arguments in NODE to their
17586 corresponding local simd arrays. Returns a fresh gimple_seq with
17587 the instruction sequence generated. */
17588
17589static gimple_seq
17590simd_clone_init_simd_arrays (struct cgraph_node *node,
17591 ipa_parm_adjustment_vec adjustments)
17592{
17593 gimple_seq seq = NULL;
17594 unsigned i = 0, j = 0, k;
17595
17596 for (tree arg = DECL_ARGUMENTS (node->decl);
17597 arg;
17598 arg = DECL_CHAIN (arg), i++, j++)
17599 {
43895be5 17600 if (adjustments[j].op == IPA_PARM_OP_COPY
17601 || POINTER_TYPE_P (TREE_TYPE (arg)))
d09768a4 17602 continue;
17603
17604 node->simdclone->args[i].vector_arg = arg;
17605
17606 tree array = node->simdclone->args[i].simd_array;
17607 if (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg)) == node->simdclone->simdlen)
17608 {
17609 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
17610 tree ptr = build_fold_addr_expr (array);
17611 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
17612 build_int_cst (ptype, 0));
17613 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
17614 gimplify_and_add (t, &seq);
17615 }
17616 else
17617 {
17618 unsigned int simdlen = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg));
17619 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
17620 for (k = 0; k < node->simdclone->simdlen; k += simdlen)
17621 {
17622 tree ptr = build_fold_addr_expr (array);
17623 int elemsize;
17624 if (k)
17625 {
17626 arg = DECL_CHAIN (arg);
17627 j++;
17628 }
17629 elemsize
17630 = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg))));
17631 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
17632 build_int_cst (ptype, k * elemsize));
17633 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
17634 gimplify_and_add (t, &seq);
17635 }
17636 }
17637 }
17638 return seq;
17639}
17640
17641/* Callback info for ipa_simd_modify_stmt_ops below. */
17642
17643struct modify_stmt_info {
17644 ipa_parm_adjustment_vec adjustments;
42acab1c 17645 gimple *stmt;
d09768a4 17646 /* True if the parent statement was modified by
17647 ipa_simd_modify_stmt_ops. */
17648 bool modified;
17649};
17650
17651/* Callback for walk_gimple_op.
17652
17653 Adjust operands from a given statement as specified in the
17654 adjustments vector in the callback data. */
17655
17656static tree
17657ipa_simd_modify_stmt_ops (tree *tp, int *walk_subtrees, void *data)
17658{
17659 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
2d78e89f 17660 struct modify_stmt_info *info = (struct modify_stmt_info *) wi->info;
17661 tree *orig_tp = tp;
17662 if (TREE_CODE (*tp) == ADDR_EXPR)
17663 tp = &TREE_OPERAND (*tp, 0);
17664 struct ipa_parm_adjustment *cand = NULL;
17665 if (TREE_CODE (*tp) == PARM_DECL)
17666 cand = ipa_get_adjustment_candidate (&tp, NULL, info->adjustments, true);
17667 else
d09768a4 17668 {
d09768a4 17669 if (TYPE_P (*tp))
17670 *walk_subtrees = 0;
d09768a4 17671 }
d09768a4 17672
2d78e89f 17673 tree repl = NULL_TREE;
17674 if (cand)
17675 repl = unshare_expr (cand->new_decl);
17676 else
d09768a4 17677 {
2d78e89f 17678 if (tp != orig_tp)
17679 {
17680 *walk_subtrees = 0;
17681 bool modified = info->modified;
17682 info->modified = false;
17683 walk_tree (tp, ipa_simd_modify_stmt_ops, wi, wi->pset);
17684 if (!info->modified)
17685 {
17686 info->modified = modified;
17687 return NULL_TREE;
17688 }
17689 info->modified = modified;
17690 repl = *tp;
17691 }
17692 else
17693 return NULL_TREE;
d09768a4 17694 }
2d78e89f 17695
17696 if (tp != orig_tp)
d09768a4 17697 {
2d78e89f 17698 repl = build_fold_addr_expr (repl);
42acab1c 17699 gimple *stmt;
9c1dd4d9 17700 if (is_gimple_debug (info->stmt))
17701 {
17702 tree vexpr = make_node (DEBUG_EXPR_DECL);
17703 stmt = gimple_build_debug_source_bind (vexpr, repl, NULL);
17704 DECL_ARTIFICIAL (vexpr) = 1;
17705 TREE_TYPE (vexpr) = TREE_TYPE (repl);
17706 DECL_MODE (vexpr) = TYPE_MODE (TREE_TYPE (repl));
17707 repl = vexpr;
17708 }
17709 else
17710 {
f9e245b2 17711 stmt = gimple_build_assign (make_ssa_name (TREE_TYPE (repl)), repl);
9c1dd4d9 17712 repl = gimple_assign_lhs (stmt);
17713 }
2d78e89f 17714 gimple_stmt_iterator gsi = gsi_for_stmt (info->stmt);
d09768a4 17715 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
2d78e89f 17716 *orig_tp = repl;
d09768a4 17717 }
2d78e89f 17718 else if (!useless_type_conversion_p (TREE_TYPE (*tp), TREE_TYPE (repl)))
d09768a4 17719 {
17720 tree vce = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (*tp), repl);
17721 *tp = vce;
17722 }
17723 else
17724 *tp = repl;
17725
17726 info->modified = true;
d09768a4 17727 return NULL_TREE;
17728}
17729
17730/* Traverse the function body and perform all modifications as
17731 described in ADJUSTMENTS. At function return, ADJUSTMENTS will be
17732 modified such that the replacement/reduction value will now be an
17733 offset into the corresponding simd_array.
17734
17735 This function will replace all function argument uses with their
17736 corresponding simd array elements, and ajust the return values
17737 accordingly. */
17738
17739static void
17740ipa_simd_modify_function_body (struct cgraph_node *node,
17741 ipa_parm_adjustment_vec adjustments,
17742 tree retval_array, tree iter)
17743{
17744 basic_block bb;
2d78e89f 17745 unsigned int i, j, l;
d09768a4 17746
17747 /* Re-use the adjustments array, but this time use it to replace
17748 every function argument use to an offset into the corresponding
17749 simd_array. */
17750 for (i = 0, j = 0; i < node->simdclone->nargs; ++i, ++j)
17751 {
17752 if (!node->simdclone->args[i].vector_arg)
17753 continue;
17754
17755 tree basetype = TREE_TYPE (node->simdclone->args[i].orig_arg);
17756 tree vectype = TREE_TYPE (node->simdclone->args[i].vector_arg);
17757 adjustments[j].new_decl
17758 = build4 (ARRAY_REF,
17759 basetype,
17760 node->simdclone->args[i].simd_array,
17761 iter,
17762 NULL_TREE, NULL_TREE);
17763 if (adjustments[j].op == IPA_PARM_OP_NONE
17764 && TYPE_VECTOR_SUBPARTS (vectype) < node->simdclone->simdlen)
17765 j += node->simdclone->simdlen / TYPE_VECTOR_SUBPARTS (vectype) - 1;
17766 }
17767
2d78e89f 17768 l = adjustments.length ();
17769 for (i = 1; i < num_ssa_names; i++)
17770 {
17771 tree name = ssa_name (i);
17772 if (name
17773 && SSA_NAME_VAR (name)
17774 && TREE_CODE (SSA_NAME_VAR (name)) == PARM_DECL)
17775 {
17776 for (j = 0; j < l; j++)
17777 if (SSA_NAME_VAR (name) == adjustments[j].base
17778 && adjustments[j].new_decl)
17779 {
17780 tree base_var;
17781 if (adjustments[j].new_ssa_base == NULL_TREE)
17782 {
17783 base_var
17784 = copy_var_decl (adjustments[j].base,
17785 DECL_NAME (adjustments[j].base),
17786 TREE_TYPE (adjustments[j].base));
17787 adjustments[j].new_ssa_base = base_var;
17788 }
17789 else
17790 base_var = adjustments[j].new_ssa_base;
17791 if (SSA_NAME_IS_DEFAULT_DEF (name))
17792 {
17793 bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
17794 gimple_stmt_iterator gsi = gsi_after_labels (bb);
17795 tree new_decl = unshare_expr (adjustments[j].new_decl);
17796 set_ssa_default_def (cfun, adjustments[j].base, NULL_TREE);
17797 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
17798 SSA_NAME_IS_DEFAULT_DEF (name) = 0;
42acab1c 17799 gimple *stmt = gimple_build_assign (name, new_decl);
2d78e89f 17800 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
17801 }
17802 else
17803 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
17804 }
17805 }
17806 }
17807
d09768a4 17808 struct modify_stmt_info info;
17809 info.adjustments = adjustments;
17810
17811 FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl))
17812 {
17813 gimple_stmt_iterator gsi;
17814
17815 gsi = gsi_start_bb (bb);
17816 while (!gsi_end_p (gsi))
17817 {
42acab1c 17818 gimple *stmt = gsi_stmt (gsi);
d09768a4 17819 info.stmt = stmt;
17820 struct walk_stmt_info wi;
17821
17822 memset (&wi, 0, sizeof (wi));
17823 info.modified = false;
17824 wi.info = &info;
17825 walk_gimple_op (stmt, ipa_simd_modify_stmt_ops, &wi);
17826
1a91d914 17827 if (greturn *return_stmt = dyn_cast <greturn *> (stmt))
d09768a4 17828 {
1a91d914 17829 tree retval = gimple_return_retval (return_stmt);
d09768a4 17830 if (!retval)
17831 {
17832 gsi_remove (&gsi, true);
17833 continue;
17834 }
17835
17836 /* Replace `return foo' with `retval_array[iter] = foo'. */
17837 tree ref = build4 (ARRAY_REF, TREE_TYPE (retval),
17838 retval_array, iter, NULL, NULL);
17839 stmt = gimple_build_assign (ref, retval);
17840 gsi_replace (&gsi, stmt, true);
17841 info.modified = true;
17842 }
17843
17844 if (info.modified)
17845 {
17846 update_stmt (stmt);
17847 if (maybe_clean_eh_stmt (stmt))
17848 gimple_purge_dead_eh_edges (gimple_bb (stmt));
17849 }
17850 gsi_next (&gsi);
17851 }
17852 }
17853}
17854
9561765e 17855/* Helper function of simd_clone_adjust, return linear step addend
17856 of Ith argument. */
17857
17858static tree
17859simd_clone_linear_addend (struct cgraph_node *node, unsigned int i,
17860 tree addtype, basic_block entry_bb)
17861{
17862 tree ptype = NULL_TREE;
17863 switch (node->simdclone->args[i].arg_type)
17864 {
17865 case SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP:
17866 case SIMD_CLONE_ARG_TYPE_LINEAR_REF_CONSTANT_STEP:
17867 case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_CONSTANT_STEP:
17868 case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP:
17869 return build_int_cst (addtype, node->simdclone->args[i].linear_step);
17870 case SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP:
17871 case SIMD_CLONE_ARG_TYPE_LINEAR_REF_VARIABLE_STEP:
17872 ptype = TREE_TYPE (node->simdclone->args[i].orig_arg);
17873 break;
17874 case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_VARIABLE_STEP:
17875 case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_VARIABLE_STEP:
17876 ptype = TREE_TYPE (TREE_TYPE (node->simdclone->args[i].orig_arg));
17877 break;
17878 default:
17879 gcc_unreachable ();
17880 }
17881
17882 unsigned int idx = node->simdclone->args[i].linear_step;
17883 tree arg = node->simdclone->args[idx].orig_arg;
17884 gcc_assert (is_gimple_reg_type (TREE_TYPE (arg)));
17885 gimple_stmt_iterator gsi = gsi_after_labels (entry_bb);
17886 gimple *g;
17887 tree ret;
17888 if (is_gimple_reg (arg))
17889 ret = get_or_create_ssa_default_def (cfun, arg);
17890 else
17891 {
17892 g = gimple_build_assign (make_ssa_name (TREE_TYPE (arg)), arg);
17893 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
17894 ret = gimple_assign_lhs (g);
17895 }
17896 if (TREE_CODE (TREE_TYPE (arg)) == REFERENCE_TYPE)
17897 {
17898 g = gimple_build_assign (make_ssa_name (TREE_TYPE (TREE_TYPE (arg))),
17899 build_simple_mem_ref (ret));
17900 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
17901 ret = gimple_assign_lhs (g);
17902 }
17903 if (!useless_type_conversion_p (addtype, TREE_TYPE (ret)))
17904 {
17905 g = gimple_build_assign (make_ssa_name (addtype), NOP_EXPR, ret);
17906 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
17907 ret = gimple_assign_lhs (g);
17908 }
17909 if (POINTER_TYPE_P (ptype))
17910 {
17911 tree size = TYPE_SIZE_UNIT (TREE_TYPE (ptype));
17912 if (size && TREE_CODE (size) == INTEGER_CST)
17913 {
17914 g = gimple_build_assign (make_ssa_name (addtype), MULT_EXPR,
17915 ret, fold_convert (addtype, size));
17916 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
17917 ret = gimple_assign_lhs (g);
17918 }
17919 }
17920 return ret;
17921}
17922
d09768a4 17923/* Adjust the argument types in NODE to their appropriate vector
17924 counterparts. */
17925
17926static void
17927simd_clone_adjust (struct cgraph_node *node)
17928{
17929 push_cfun (DECL_STRUCT_FUNCTION (node->decl));
17930
17931 targetm.simd_clone.adjust (node);
17932
17933 tree retval = simd_clone_adjust_return_type (node);
17934 ipa_parm_adjustment_vec adjustments
17935 = simd_clone_adjust_argument_types (node);
17936
17937 push_gimplify_context ();
17938
17939 gimple_seq seq = simd_clone_init_simd_arrays (node, adjustments);
17940
17941 /* Adjust all uses of vector arguments accordingly. Adjust all
17942 return values accordingly. */
17943 tree iter = create_tmp_var (unsigned_type_node, "iter");
f9e245b2 17944 tree iter1 = make_ssa_name (iter);
17945 tree iter2 = make_ssa_name (iter);
d09768a4 17946 ipa_simd_modify_function_body (node, adjustments, retval, iter1);
17947
17948 /* Initialize the iteration variable. */
17949 basic_block entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
17950 basic_block body_bb = split_block_after_labels (entry_bb)->dest;
17951 gimple_stmt_iterator gsi = gsi_after_labels (entry_bb);
17952 /* Insert the SIMD array and iv initialization at function
17953 entry. */
17954 gsi_insert_seq_before (&gsi, seq, GSI_NEW_STMT);
17955
17956 pop_gimplify_context (NULL);
17957
17958 /* Create a new BB right before the original exit BB, to hold the
17959 iteration increment and the condition/branch. */
17960 basic_block orig_exit = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), 0)->src;
17961 basic_block incr_bb = create_empty_bb (orig_exit);
343ee723 17962 add_bb_to_loop (incr_bb, body_bb->loop_father);
d09768a4 17963 /* The succ of orig_exit was EXIT_BLOCK_PTR_FOR_FN (cfun), with an empty
17964 flag. Set it now to be a FALLTHRU_EDGE. */
17965 gcc_assert (EDGE_COUNT (orig_exit->succs) == 1);
17966 EDGE_SUCC (orig_exit, 0)->flags |= EDGE_FALLTHRU;
17967 for (unsigned i = 0;
17968 i < EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds); ++i)
17969 {
17970 edge e = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), i);
17971 redirect_edge_succ (e, incr_bb);
17972 }
17973 edge e = make_edge (incr_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
17974 e->probability = REG_BR_PROB_BASE;
17975 gsi = gsi_last_bb (incr_bb);
42acab1c 17976 gimple *g = gimple_build_assign (iter2, PLUS_EXPR, iter1,
e9cf809e 17977 build_int_cst (unsigned_type_node, 1));
d09768a4 17978 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
17979
17980 /* Mostly annotate the loop for the vectorizer (the rest is done below). */
17981 struct loop *loop = alloc_loop ();
4c73695b 17982 cfun->has_force_vectorize_loops = true;
d09768a4 17983 loop->safelen = node->simdclone->simdlen;
4c73695b 17984 loop->force_vectorize = true;
d09768a4 17985 loop->header = body_bb;
d09768a4 17986
17987 /* Branch around the body if the mask applies. */
17988 if (node->simdclone->inbranch)
17989 {
17990 gimple_stmt_iterator gsi = gsi_last_bb (loop->header);
17991 tree mask_array
17992 = node->simdclone->args[node->simdclone->nargs - 1].simd_array;
f9e245b2 17993 tree mask = make_ssa_name (TREE_TYPE (TREE_TYPE (mask_array)));
d09768a4 17994 tree aref = build4 (ARRAY_REF,
17995 TREE_TYPE (TREE_TYPE (mask_array)),
17996 mask_array, iter1,
17997 NULL, NULL);
17998 g = gimple_build_assign (mask, aref);
17999 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
18000 int bitsize = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (aref)));
18001 if (!INTEGRAL_TYPE_P (TREE_TYPE (aref)))
18002 {
18003 aref = build1 (VIEW_CONVERT_EXPR,
18004 build_nonstandard_integer_type (bitsize, 0), mask);
f9e245b2 18005 mask = make_ssa_name (TREE_TYPE (aref));
d09768a4 18006 g = gimple_build_assign (mask, aref);
18007 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
18008 }
18009
18010 g = gimple_build_cond (EQ_EXPR, mask, build_zero_cst (TREE_TYPE (mask)),
18011 NULL, NULL);
18012 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
18013 make_edge (loop->header, incr_bb, EDGE_TRUE_VALUE);
18014 FALLTHRU_EDGE (loop->header)->flags = EDGE_FALSE_VALUE;
18015 }
18016
18017 /* Generate the condition. */
18018 g = gimple_build_cond (LT_EXPR,
18019 iter2,
18020 build_int_cst (unsigned_type_node,
18021 node->simdclone->simdlen),
18022 NULL, NULL);
18023 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
18024 e = split_block (incr_bb, gsi_stmt (gsi));
18025 basic_block latch_bb = e->dest;
343ee723 18026 basic_block new_exit_bb;
4302d619 18027 new_exit_bb = split_block_after_labels (latch_bb)->dest;
d09768a4 18028 loop->latch = latch_bb;
18029
18030 redirect_edge_succ (FALLTHRU_EDGE (latch_bb), body_bb);
18031
18032 make_edge (incr_bb, new_exit_bb, EDGE_FALSE_VALUE);
18033 /* The successor of incr_bb is already pointing to latch_bb; just
18034 change the flags.
18035 make_edge (incr_bb, latch_bb, EDGE_TRUE_VALUE); */
18036 FALLTHRU_EDGE (incr_bb)->flags = EDGE_TRUE_VALUE;
18037
1a91d914 18038 gphi *phi = create_phi_node (iter1, body_bb);
d09768a4 18039 edge preheader_edge = find_edge (entry_bb, body_bb);
18040 edge latch_edge = single_succ_edge (latch_bb);
18041 add_phi_arg (phi, build_zero_cst (unsigned_type_node), preheader_edge,
18042 UNKNOWN_LOCATION);
18043 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
18044
18045 /* Generate the new return. */
18046 gsi = gsi_last_bb (new_exit_bb);
18047 if (retval
18048 && TREE_CODE (retval) == VIEW_CONVERT_EXPR
18049 && TREE_CODE (TREE_OPERAND (retval, 0)) == RESULT_DECL)
18050 retval = TREE_OPERAND (retval, 0);
18051 else if (retval)
18052 {
18053 retval = build1 (VIEW_CONVERT_EXPR,
18054 TREE_TYPE (TREE_TYPE (node->decl)),
18055 retval);
18056 retval = force_gimple_operand_gsi (&gsi, retval, true, NULL,
18057 false, GSI_CONTINUE_LINKING);
18058 }
18059 g = gimple_build_return (retval);
18060 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
18061
18062 /* Handle aligned clauses by replacing default defs of the aligned
18063 uniform args with __builtin_assume_aligned (arg_N(D), alignment)
18064 lhs. Handle linear by adding PHIs. */
18065 for (unsigned i = 0; i < node->simdclone->nargs; i++)
97a82d40 18066 if (node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
18067 && (TREE_ADDRESSABLE (node->simdclone->args[i].orig_arg)
18068 || !is_gimple_reg_type
18069 (TREE_TYPE (node->simdclone->args[i].orig_arg))))
18070 {
18071 tree orig_arg = node->simdclone->args[i].orig_arg;
18072 if (is_gimple_reg_type (TREE_TYPE (orig_arg)))
18073 iter1 = make_ssa_name (TREE_TYPE (orig_arg));
18074 else
18075 {
18076 iter1 = create_tmp_var_raw (TREE_TYPE (orig_arg));
18077 gimple_add_tmp_var (iter1);
18078 }
18079 gsi = gsi_after_labels (entry_bb);
18080 g = gimple_build_assign (iter1, orig_arg);
18081 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
18082 gsi = gsi_after_labels (body_bb);
18083 g = gimple_build_assign (orig_arg, iter1);
18084 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
18085 }
18086 else if (node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
18087 && DECL_BY_REFERENCE (node->simdclone->args[i].orig_arg)
18088 && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
18089 == REFERENCE_TYPE
18090 && TREE_ADDRESSABLE
18091 (TREE_TYPE (TREE_TYPE (node->simdclone->args[i].orig_arg))))
18092 {
18093 tree orig_arg = node->simdclone->args[i].orig_arg;
18094 tree def = ssa_default_def (cfun, orig_arg);
18095 if (def && !has_zero_uses (def))
18096 {
18097 iter1 = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (orig_arg)));
18098 gimple_add_tmp_var (iter1);
18099 gsi = gsi_after_labels (entry_bb);
18100 g = gimple_build_assign (iter1, build_simple_mem_ref (def));
18101 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
18102 gsi = gsi_after_labels (body_bb);
18103 g = gimple_build_assign (build_simple_mem_ref (def), iter1);
18104 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
18105 }
18106 }
18107 else if (node->simdclone->args[i].alignment
18108 && node->simdclone->args[i].arg_type
18109 == SIMD_CLONE_ARG_TYPE_UNIFORM
18110 && (node->simdclone->args[i].alignment
18111 & (node->simdclone->args[i].alignment - 1)) == 0
18112 && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
18113 == POINTER_TYPE)
d09768a4 18114 {
18115 unsigned int alignment = node->simdclone->args[i].alignment;
18116 tree orig_arg = node->simdclone->args[i].orig_arg;
18117 tree def = ssa_default_def (cfun, orig_arg);
6db33a3d 18118 if (def && !has_zero_uses (def))
d09768a4 18119 {
18120 tree fn = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
18121 gimple_seq seq = NULL;
18122 bool need_cvt = false;
1a91d914 18123 gcall *call
d09768a4 18124 = gimple_build_call (fn, 2, def, size_int (alignment));
18125 g = call;
18126 if (!useless_type_conversion_p (TREE_TYPE (orig_arg),
18127 ptr_type_node))
18128 need_cvt = true;
f9e245b2 18129 tree t = make_ssa_name (need_cvt ? ptr_type_node : orig_arg);
d09768a4 18130 gimple_call_set_lhs (g, t);
18131 gimple_seq_add_stmt_without_update (&seq, g);
18132 if (need_cvt)
18133 {
f9e245b2 18134 t = make_ssa_name (orig_arg);
e9cf809e 18135 g = gimple_build_assign (t, NOP_EXPR, gimple_call_lhs (g));
d09768a4 18136 gimple_seq_add_stmt_without_update (&seq, g);
18137 }
18138 gsi_insert_seq_on_edge_immediate
18139 (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)), seq);
18140
18141 entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
18142 int freq = compute_call_stmt_bb_frequency (current_function_decl,
18143 entry_bb);
415d1b9a 18144 node->create_edge (cgraph_node::get_create (fn),
18145 call, entry_bb->count, freq);
d09768a4 18146
18147 imm_use_iterator iter;
18148 use_operand_p use_p;
42acab1c 18149 gimple *use_stmt;
d09768a4 18150 tree repl = gimple_get_lhs (g);
18151 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
18152 if (is_gimple_debug (use_stmt) || use_stmt == call)
18153 continue;
18154 else
18155 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
18156 SET_USE (use_p, repl);
18157 }
18158 }
43895be5 18159 else if ((node->simdclone->args[i].arg_type
18160 == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
18161 || (node->simdclone->args[i].arg_type
9561765e 18162 == SIMD_CLONE_ARG_TYPE_LINEAR_REF_CONSTANT_STEP)
18163 || (node->simdclone->args[i].arg_type
18164 == SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP)
18165 || (node->simdclone->args[i].arg_type
18166 == SIMD_CLONE_ARG_TYPE_LINEAR_REF_VARIABLE_STEP))
d09768a4 18167 {
18168 tree orig_arg = node->simdclone->args[i].orig_arg;
d09768a4 18169 gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
18170 || POINTER_TYPE_P (TREE_TYPE (orig_arg)));
97a82d40 18171 tree def = NULL_TREE;
18172 if (TREE_ADDRESSABLE (orig_arg))
18173 {
18174 def = make_ssa_name (TREE_TYPE (orig_arg));
18175 iter1 = make_ssa_name (TREE_TYPE (orig_arg));
18176 iter2 = make_ssa_name (TREE_TYPE (orig_arg));
18177 gsi = gsi_after_labels (entry_bb);
18178 g = gimple_build_assign (def, orig_arg);
18179 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
18180 }
18181 else
18182 {
18183 def = ssa_default_def (cfun, orig_arg);
18184 if (!def || has_zero_uses (def))
18185 def = NULL_TREE;
18186 else
18187 {
18188 iter1 = make_ssa_name (orig_arg);
18189 iter2 = make_ssa_name (orig_arg);
18190 }
18191 }
18192 if (def)
d09768a4 18193 {
d09768a4 18194 phi = create_phi_node (iter1, body_bb);
18195 add_phi_arg (phi, def, preheader_edge, UNKNOWN_LOCATION);
18196 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
18197 enum tree_code code = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
18198 ? PLUS_EXPR : POINTER_PLUS_EXPR;
18199 tree addtype = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
18200 ? TREE_TYPE (orig_arg) : sizetype;
9561765e 18201 tree addcst = simd_clone_linear_addend (node, i, addtype,
18202 entry_bb);
d09768a4 18203 gsi = gsi_last_bb (incr_bb);
9561765e 18204 g = gimple_build_assign (iter2, code, iter1, addcst);
d09768a4 18205 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
18206
18207 imm_use_iterator iter;
18208 use_operand_p use_p;
42acab1c 18209 gimple *use_stmt;
97a82d40 18210 if (TREE_ADDRESSABLE (orig_arg))
18211 {
18212 gsi = gsi_after_labels (body_bb);
18213 g = gimple_build_assign (orig_arg, iter1);
18214 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
18215 }
18216 else
18217 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
18218 if (use_stmt == phi)
18219 continue;
18220 else
18221 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
18222 SET_USE (use_p, iter1);
d09768a4 18223 }
18224 }
43895be5 18225 else if (node->simdclone->args[i].arg_type
9561765e 18226 == SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP
18227 || (node->simdclone->args[i].arg_type
18228 == SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_VARIABLE_STEP))
43895be5 18229 {
18230 tree orig_arg = node->simdclone->args[i].orig_arg;
18231 tree def = ssa_default_def (cfun, orig_arg);
18232 gcc_assert (!TREE_ADDRESSABLE (orig_arg)
18233 && TREE_CODE (TREE_TYPE (orig_arg)) == REFERENCE_TYPE);
18234 if (def && !has_zero_uses (def))
18235 {
18236 tree rtype = TREE_TYPE (TREE_TYPE (orig_arg));
18237 iter1 = make_ssa_name (orig_arg);
18238 iter2 = make_ssa_name (orig_arg);
18239 tree iter3 = make_ssa_name (rtype);
18240 tree iter4 = make_ssa_name (rtype);
18241 tree iter5 = make_ssa_name (rtype);
18242 gsi = gsi_after_labels (entry_bb);
18243 gimple *load
18244 = gimple_build_assign (iter3, build_simple_mem_ref (def));
18245 gsi_insert_before (&gsi, load, GSI_NEW_STMT);
18246
18247 tree array = node->simdclone->args[i].simd_array;
18248 TREE_ADDRESSABLE (array) = 1;
18249 tree ptr = build_fold_addr_expr (array);
18250 phi = create_phi_node (iter1, body_bb);
18251 add_phi_arg (phi, ptr, preheader_edge, UNKNOWN_LOCATION);
18252 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
18253 g = gimple_build_assign (iter2, POINTER_PLUS_EXPR, iter1,
18254 TYPE_SIZE_UNIT (TREE_TYPE (iter3)));
18255 gsi = gsi_last_bb (incr_bb);
18256 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
18257
18258 phi = create_phi_node (iter4, body_bb);
18259 add_phi_arg (phi, iter3, preheader_edge, UNKNOWN_LOCATION);
18260 add_phi_arg (phi, iter5, latch_edge, UNKNOWN_LOCATION);
18261 enum tree_code code = INTEGRAL_TYPE_P (TREE_TYPE (iter3))
18262 ? PLUS_EXPR : POINTER_PLUS_EXPR;
18263 tree addtype = INTEGRAL_TYPE_P (TREE_TYPE (iter3))
18264 ? TREE_TYPE (iter3) : sizetype;
9561765e 18265 tree addcst = simd_clone_linear_addend (node, i, addtype,
18266 entry_bb);
43895be5 18267 g = gimple_build_assign (iter5, code, iter4, addcst);
18268 gsi = gsi_last_bb (incr_bb);
18269 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
18270
18271 g = gimple_build_assign (build_simple_mem_ref (iter1), iter4);
18272 gsi = gsi_after_labels (body_bb);
18273 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
18274
18275 imm_use_iterator iter;
18276 use_operand_p use_p;
18277 gimple *use_stmt;
18278 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
18279 if (use_stmt == load)
18280 continue;
18281 else
18282 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
18283 SET_USE (use_p, iter1);
18284
18285 if (!TYPE_READONLY (rtype))
18286 {
18287 tree v = make_ssa_name (rtype);
18288 tree aref = build4 (ARRAY_REF, rtype, array,
18289 size_zero_node, NULL_TREE,
18290 NULL_TREE);
18291 gsi = gsi_after_labels (new_exit_bb);
18292 g = gimple_build_assign (v, aref);
18293 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
18294 g = gimple_build_assign (build_simple_mem_ref (def), v);
18295 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
18296 }
18297 }
18298 }
d09768a4 18299
18300 calculate_dominance_info (CDI_DOMINATORS);
18301 add_loop (loop, loop->header->loop_father);
18302 update_ssa (TODO_update_ssa);
18303
18304 pop_cfun ();
18305}
18306
18307/* If the function in NODE is tagged as an elemental SIMD function,
18308 create the appropriate SIMD clones. */
18309
18310static void
18311expand_simd_clones (struct cgraph_node *node)
18312{
d09768a4 18313 tree attr = lookup_attribute ("omp declare simd",
18314 DECL_ATTRIBUTES (node->decl));
ea0695f9 18315 if (attr == NULL_TREE
18316 || node->global.inlined_to
18317 || lookup_attribute ("noclone", DECL_ATTRIBUTES (node->decl)))
d09768a4 18318 return;
ea0695f9 18319
d09768a4 18320 /* Ignore
18321 #pragma omp declare simd
18322 extern int foo ();
18323 in C, there we don't know the argument types at all. */
18324 if (!node->definition
18325 && TYPE_ARG_TYPES (TREE_TYPE (node->decl)) == NULL_TREE)
18326 return;
18327
b2fbac0f 18328 /* Call this before creating clone_info, as it might ggc_collect. */
18329 if (node->definition && node->has_gimple_body_p ())
18330 node->get_body ();
18331
d09768a4 18332 do
18333 {
18334 /* Start with parsing the "omp declare simd" attribute(s). */
18335 bool inbranch_clause_specified;
18336 struct cgraph_simd_clone *clone_info
18337 = simd_clone_clauses_extract (node, TREE_VALUE (attr),
18338 &inbranch_clause_specified);
18339 if (clone_info == NULL)
18340 continue;
18341
18342 int orig_simdlen = clone_info->simdlen;
18343 tree base_type = simd_clone_compute_base_data_type (node, clone_info);
18344 /* The target can return 0 (no simd clones should be created),
18345 1 (just one ISA of simd clones should be created) or higher
18346 count of ISA variants. In that case, clone_info is initialized
18347 for the first ISA variant. */
18348 int count
18349 = targetm.simd_clone.compute_vecsize_and_simdlen (node, clone_info,
18350 base_type, 0);
18351 if (count == 0)
18352 continue;
18353
18354 /* Loop over all COUNT ISA variants, and if !INBRANCH_CLAUSE_SPECIFIED,
18355 also create one inbranch and one !inbranch clone of it. */
18356 for (int i = 0; i < count * 2; i++)
18357 {
18358 struct cgraph_simd_clone *clone = clone_info;
18359 if (inbranch_clause_specified && (i & 1) != 0)
18360 continue;
18361
18362 if (i != 0)
18363 {
18364 clone = simd_clone_struct_alloc (clone_info->nargs
d09768a4 18365 + ((i & 1) != 0));
18366 simd_clone_struct_copy (clone, clone_info);
18367 /* Undo changes targetm.simd_clone.compute_vecsize_and_simdlen
18368 and simd_clone_adjust_argument_types did to the first
18369 clone's info. */
18370 clone->nargs -= clone_info->inbranch;
18371 clone->simdlen = orig_simdlen;
18372 /* And call the target hook again to get the right ISA. */
18373 targetm.simd_clone.compute_vecsize_and_simdlen (node, clone,
18374 base_type,
18375 i / 2);
18376 if ((i & 1) != 0)
18377 clone->inbranch = 1;
18378 }
18379
18380 /* simd_clone_mangle might fail if such a clone has been created
18381 already. */
18382 tree id = simd_clone_mangle (node, clone);
18383 if (id == NULL_TREE)
18384 continue;
18385
18386 /* Only when we are sure we want to create the clone actually
18387 clone the function (or definitions) or create another
18388 extern FUNCTION_DECL (for prototypes without definitions). */
18389 struct cgraph_node *n = simd_clone_create (node);
18390 if (n == NULL)
18391 continue;
18392
18393 n->simdclone = clone;
18394 clone->origin = node;
18395 clone->next_clone = NULL;
18396 if (node->simd_clones == NULL)
18397 {
18398 clone->prev_clone = n;
18399 node->simd_clones = n;
18400 }
18401 else
18402 {
18403 clone->prev_clone = node->simd_clones->simdclone->prev_clone;
18404 clone->prev_clone->simdclone->next_clone = n;
18405 node->simd_clones->simdclone->prev_clone = n;
18406 }
35ee1c66 18407 symtab->change_decl_assembler_name (n->decl, id);
d09768a4 18408 /* And finally adjust the return type, parameters and for
18409 definitions also function body. */
18410 if (node->definition)
18411 simd_clone_adjust (n);
18412 else
18413 {
18414 simd_clone_adjust_return_type (n);
18415 simd_clone_adjust_argument_types (n);
18416 }
18417 }
18418 }
18419 while ((attr = lookup_attribute ("omp declare simd", TREE_CHAIN (attr))));
18420}
18421
18422/* Entry point for IPA simd clone creation pass. */
18423
18424static unsigned int
18425ipa_omp_simd_clone (void)
18426{
18427 struct cgraph_node *node;
18428 FOR_EACH_FUNCTION (node)
18429 expand_simd_clones (node);
18430 return 0;
18431}
18432
7620bc82 18433namespace {
18434
18435const pass_data pass_data_omp_simd_clone =
d09768a4 18436{
18437 SIMPLE_IPA_PASS, /* type */
18438 "simdclone", /* name */
18439 OPTGROUP_NONE, /* optinfo_flags */
d09768a4 18440 TV_NONE, /* tv_id */
18441 ( PROP_ssa | PROP_cfg ), /* properties_required */
18442 0, /* properties_provided */
18443 0, /* properties_destroyed */
18444 0, /* todo_flags_start */
18445 0, /* todo_flags_finish */
18446};
18447
7620bc82 18448class pass_omp_simd_clone : public simple_ipa_opt_pass
d09768a4 18449{
18450public:
18451 pass_omp_simd_clone(gcc::context *ctxt)
18452 : simple_ipa_opt_pass(pass_data_omp_simd_clone, ctxt)
18453 {}
18454
18455 /* opt_pass methods: */
31315c24 18456 virtual bool gate (function *);
65b0537f 18457 virtual unsigned int execute (function *) { return ipa_omp_simd_clone (); }
d09768a4 18458};
18459
31315c24 18460bool
18461pass_omp_simd_clone::gate (function *)
18462{
c58a4cfd 18463 return targetm.simd_clone.compute_vecsize_and_simdlen != NULL;
31315c24 18464}
18465
7620bc82 18466} // anon namespace
18467
d09768a4 18468simple_ipa_opt_pass *
18469make_pass_omp_simd_clone (gcc::context *ctxt)
18470{
18471 return new pass_omp_simd_clone (ctxt);
18472}
cbe8bda8 18473
dccabdd1 18474/* Helper function for omp_finish_file routine. Takes decls from V_DECLS and
18475 adds their addresses and sizes to constructor-vector V_CTOR. */
18476static void
18477add_decls_addresses_to_decl_constructor (vec<tree, va_gc> *v_decls,
18478 vec<constructor_elt, va_gc> *v_ctor)
18479{
18480 unsigned len = vec_safe_length (v_decls);
18481 for (unsigned i = 0; i < len; i++)
18482 {
18483 tree it = (*v_decls)[i];
18484 bool is_function = TREE_CODE (it) != VAR_DECL;
18485
18486 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE, build_fold_addr_expr (it));
18487 if (!is_function)
18488 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE,
18489 fold_convert (const_ptr_type_node,
18490 DECL_SIZE_UNIT (it)));
18491 }
18492}
18493
18494/* Create new symbols containing (address, size) pairs for global variables,
18495 marked with "omp declare target" attribute, as well as addresses for the
ca4c3545 18496 functions, which are outlined offloading regions. */
dccabdd1 18497void
18498omp_finish_file (void)
18499{
18500 unsigned num_funcs = vec_safe_length (offload_funcs);
18501 unsigned num_vars = vec_safe_length (offload_vars);
18502
18503 if (num_funcs == 0 && num_vars == 0)
18504 return;
18505
18506 if (targetm_common.have_named_sections)
18507 {
18508 vec<constructor_elt, va_gc> *v_f, *v_v;
18509 vec_alloc (v_f, num_funcs);
18510 vec_alloc (v_v, num_vars * 2);
18511
18512 add_decls_addresses_to_decl_constructor (offload_funcs, v_f);
18513 add_decls_addresses_to_decl_constructor (offload_vars, v_v);
18514
18515 tree vars_decl_type = build_array_type_nelts (pointer_sized_int_node,
18516 num_vars * 2);
18517 tree funcs_decl_type = build_array_type_nelts (pointer_sized_int_node,
18518 num_funcs);
18519 TYPE_ALIGN (vars_decl_type) = TYPE_ALIGN (pointer_sized_int_node);
18520 TYPE_ALIGN (funcs_decl_type) = TYPE_ALIGN (pointer_sized_int_node);
18521 tree ctor_v = build_constructor (vars_decl_type, v_v);
18522 tree ctor_f = build_constructor (funcs_decl_type, v_f);
18523 TREE_CONSTANT (ctor_v) = TREE_CONSTANT (ctor_f) = 1;
18524 TREE_STATIC (ctor_v) = TREE_STATIC (ctor_f) = 1;
18525 tree funcs_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
18526 get_identifier (".offload_func_table"),
18527 funcs_decl_type);
18528 tree vars_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
18529 get_identifier (".offload_var_table"),
18530 vars_decl_type);
18531 TREE_STATIC (funcs_decl) = TREE_STATIC (vars_decl) = 1;
18532 /* Do not align tables more than TYPE_ALIGN (pointer_sized_int_node),
18533 otherwise a joint table in a binary will contain padding between
18534 tables from multiple object files. */
18535 DECL_USER_ALIGN (funcs_decl) = DECL_USER_ALIGN (vars_decl) = 1;
18536 DECL_ALIGN (funcs_decl) = TYPE_ALIGN (funcs_decl_type);
18537 DECL_ALIGN (vars_decl) = TYPE_ALIGN (vars_decl_type);
18538 DECL_INITIAL (funcs_decl) = ctor_f;
18539 DECL_INITIAL (vars_decl) = ctor_v;
18540 set_decl_section_name (funcs_decl, OFFLOAD_FUNC_TABLE_SECTION_NAME);
18541 set_decl_section_name (vars_decl, OFFLOAD_VAR_TABLE_SECTION_NAME);
18542
18543 varpool_node::finalize_decl (vars_decl);
18544 varpool_node::finalize_decl (funcs_decl);
7114ebdd 18545 }
dccabdd1 18546 else
18547 {
18548 for (unsigned i = 0; i < num_funcs; i++)
18549 {
18550 tree it = (*offload_funcs)[i];
18551 targetm.record_offload_symbol (it);
18552 }
18553 for (unsigned i = 0; i < num_vars; i++)
18554 {
18555 tree it = (*offload_vars)[i];
18556 targetm.record_offload_symbol (it);
18557 }
18558 }
18559}
18560
cbba99a0 18561/* Find the number of threads (POS = false), or thread number (POS =
18562 true) for an OpenACC region partitioned as MASK. Setup code
18563 required for the calculation is added to SEQ. */
18564
18565static tree
18566oacc_thread_numbers (bool pos, int mask, gimple_seq *seq)
18567{
18568 tree res = pos ? NULL_TREE : build_int_cst (unsigned_type_node, 1);
18569 unsigned ix;
18570
18571 /* Start at gang level, and examine relevant dimension indices. */
18572 for (ix = GOMP_DIM_GANG; ix != GOMP_DIM_MAX; ix++)
18573 if (GOMP_DIM_MASK (ix) & mask)
18574 {
18575 tree arg = build_int_cst (unsigned_type_node, ix);
18576
18577 if (res)
18578 {
18579 /* We had an outer index, so scale that by the size of
18580 this dimension. */
18581 tree n = create_tmp_var (integer_type_node);
18582 gimple *call
18583 = gimple_build_call_internal (IFN_GOACC_DIM_SIZE, 1, arg);
18584
18585 gimple_call_set_lhs (call, n);
18586 gimple_seq_add_stmt (seq, call);
18587 res = fold_build2 (MULT_EXPR, integer_type_node, res, n);
18588 }
18589 if (pos)
18590 {
18591 /* Determine index in this dimension. */
18592 tree id = create_tmp_var (integer_type_node);
18593 gimple *call = gimple_build_call_internal
18594 (IFN_GOACC_DIM_POS, 1, arg);
18595
18596 gimple_call_set_lhs (call, id);
18597 gimple_seq_add_stmt (seq, call);
18598 if (res)
18599 res = fold_build2 (PLUS_EXPR, integer_type_node, res, id);
18600 else
18601 res = id;
18602 }
18603 }
18604
18605 if (res == NULL_TREE)
18606 res = integer_zero_node;
18607
18608 return res;
18609}
18610
18611/* Transform IFN_GOACC_LOOP calls to actual code. See
18612 expand_oacc_for for where these are generated. At the vector
18613 level, we stride loops, such that each member of a warp will
18614 operate on adjacent iterations. At the worker and gang level,
18615 each gang/warp executes a set of contiguous iterations. Chunking
18616 can override this such that each iteration engine executes a
18617 contiguous chunk, and then moves on to stride to the next chunk. */
18618
18619static void
18620oacc_xform_loop (gcall *call)
18621{
18622 gimple_stmt_iterator gsi = gsi_for_stmt (call);
18623 enum ifn_goacc_loop_kind code
18624 = (enum ifn_goacc_loop_kind) TREE_INT_CST_LOW (gimple_call_arg (call, 0));
18625 tree dir = gimple_call_arg (call, 1);
18626 tree range = gimple_call_arg (call, 2);
18627 tree step = gimple_call_arg (call, 3);
18628 tree chunk_size = NULL_TREE;
18629 unsigned mask = (unsigned) TREE_INT_CST_LOW (gimple_call_arg (call, 5));
18630 tree lhs = gimple_call_lhs (call);
18631 tree type = TREE_TYPE (lhs);
18632 tree diff_type = TREE_TYPE (range);
18633 tree r = NULL_TREE;
18634 gimple_seq seq = NULL;
18635 bool chunking = false, striding = true;
18636 unsigned outer_mask = mask & (~mask + 1); // Outermost partitioning
18637 unsigned inner_mask = mask & ~outer_mask; // Inner partitioning (if any)
18638
18639#ifdef ACCEL_COMPILER
18640 chunk_size = gimple_call_arg (call, 4);
18641 if (integer_minus_onep (chunk_size) /* Force static allocation. */
18642 || integer_zerop (chunk_size)) /* Default (also static). */
18643 {
18644 /* If we're at the gang level, we want each to execute a
18645 contiguous run of iterations. Otherwise we want each element
18646 to stride. */
18647 striding = !(outer_mask & GOMP_DIM_MASK (GOMP_DIM_GANG));
18648 chunking = false;
18649 }
18650 else
18651 {
18652 /* Chunk of size 1 is striding. */
18653 striding = integer_onep (chunk_size);
18654 chunking = !striding;
18655 }
18656#endif
18657
18658 /* striding=true, chunking=true
18659 -> invalid.
18660 striding=true, chunking=false
18661 -> chunks=1
18662 striding=false,chunking=true
18663 -> chunks=ceil (range/(chunksize*threads*step))
18664 striding=false,chunking=false
18665 -> chunk_size=ceil(range/(threads*step)),chunks=1 */
18666 push_gimplify_context (true);
18667
18668 switch (code)
18669 {
18670 default: gcc_unreachable ();
18671
18672 case IFN_GOACC_LOOP_CHUNKS:
18673 if (!chunking)
18674 r = build_int_cst (type, 1);
18675 else
18676 {
18677 /* chunk_max
18678 = (range - dir) / (chunks * step * num_threads) + dir */
18679 tree per = oacc_thread_numbers (false, mask, &seq);
18680 per = fold_convert (type, per);
18681 chunk_size = fold_convert (type, chunk_size);
18682 per = fold_build2 (MULT_EXPR, type, per, chunk_size);
18683 per = fold_build2 (MULT_EXPR, type, per, step);
18684 r = build2 (MINUS_EXPR, type, range, dir);
18685 r = build2 (PLUS_EXPR, type, r, per);
18686 r = build2 (TRUNC_DIV_EXPR, type, r, per);
18687 }
18688 break;
18689
18690 case IFN_GOACC_LOOP_STEP:
18691 {
18692 /* If striding, step by the entire compute volume, otherwise
18693 step by the inner volume. */
18694 unsigned volume = striding ? mask : inner_mask;
18695
18696 r = oacc_thread_numbers (false, volume, &seq);
18697 r = build2 (MULT_EXPR, type, fold_convert (type, r), step);
18698 }
18699 break;
18700
18701 case IFN_GOACC_LOOP_OFFSET:
18702 if (striding)
18703 {
18704 r = oacc_thread_numbers (true, mask, &seq);
18705 r = fold_convert (diff_type, r);
18706 }
18707 else
18708 {
18709 tree inner_size = oacc_thread_numbers (false, inner_mask, &seq);
18710 tree outer_size = oacc_thread_numbers (false, outer_mask, &seq);
18711 tree volume = fold_build2 (MULT_EXPR, TREE_TYPE (inner_size),
18712 inner_size, outer_size);
18713
18714 volume = fold_convert (diff_type, volume);
18715 if (chunking)
18716 chunk_size = fold_convert (diff_type, chunk_size);
18717 else
18718 {
18719 tree per = fold_build2 (MULT_EXPR, diff_type, volume, step);
18720
18721 chunk_size = build2 (MINUS_EXPR, diff_type, range, dir);
18722 chunk_size = build2 (PLUS_EXPR, diff_type, chunk_size, per);
18723 chunk_size = build2 (TRUNC_DIV_EXPR, diff_type, chunk_size, per);
18724 }
18725
18726 tree span = build2 (MULT_EXPR, diff_type, chunk_size,
18727 fold_convert (diff_type, inner_size));
18728 r = oacc_thread_numbers (true, outer_mask, &seq);
18729 r = fold_convert (diff_type, r);
18730 r = build2 (MULT_EXPR, diff_type, r, span);
18731
18732 tree inner = oacc_thread_numbers (true, inner_mask, &seq);
18733 inner = fold_convert (diff_type, inner);
18734 r = fold_build2 (PLUS_EXPR, diff_type, r, inner);
18735
18736 if (chunking)
18737 {
18738 tree chunk = fold_convert (diff_type, gimple_call_arg (call, 6));
18739 tree per
18740 = fold_build2 (MULT_EXPR, diff_type, volume, chunk_size);
18741 per = build2 (MULT_EXPR, diff_type, per, chunk);
18742
18743 r = build2 (PLUS_EXPR, diff_type, r, per);
18744 }
18745 }
18746 r = fold_build2 (MULT_EXPR, diff_type, r, step);
18747 if (type != diff_type)
18748 r = fold_convert (type, r);
18749 break;
18750
18751 case IFN_GOACC_LOOP_BOUND:
18752 if (striding)
18753 r = range;
18754 else
18755 {
18756 tree inner_size = oacc_thread_numbers (false, inner_mask, &seq);
18757 tree outer_size = oacc_thread_numbers (false, outer_mask, &seq);
18758 tree volume = fold_build2 (MULT_EXPR, TREE_TYPE (inner_size),
18759 inner_size, outer_size);
18760
18761 volume = fold_convert (diff_type, volume);
18762 if (chunking)
18763 chunk_size = fold_convert (diff_type, chunk_size);
18764 else
18765 {
18766 tree per = fold_build2 (MULT_EXPR, diff_type, volume, step);
18767
18768 chunk_size = build2 (MINUS_EXPR, diff_type, range, dir);
18769 chunk_size = build2 (PLUS_EXPR, diff_type, chunk_size, per);
18770 chunk_size = build2 (TRUNC_DIV_EXPR, diff_type, chunk_size, per);
18771 }
18772
18773 tree span = build2 (MULT_EXPR, diff_type, chunk_size,
18774 fold_convert (diff_type, inner_size));
18775
18776 r = fold_build2 (MULT_EXPR, diff_type, span, step);
18777
18778 tree offset = gimple_call_arg (call, 6);
18779 r = build2 (PLUS_EXPR, diff_type, r,
18780 fold_convert (diff_type, offset));
18781 r = build2 (integer_onep (dir) ? MIN_EXPR : MAX_EXPR,
18782 diff_type, r, range);
18783 }
18784 if (diff_type != type)
18785 r = fold_convert (type, r);
18786 break;
18787 }
18788
18789 gimplify_assign (lhs, r, &seq);
18790
18791 pop_gimplify_context (NULL);
18792
18793 gsi_replace_with_seq (&gsi, seq, true);
18794}
18795
0bb0f256 18796/* Validate and update the dimensions for offloaded FN. ATTRS is the
18797 raw attribute. DIMS is an array of dimensions, which is returned.
18798 Returns the function level dimensionality -- the level at which an
18799 offload routine wishes to partition a loop. */
18800
18801static int
18802oacc_validate_dims (tree fn, tree attrs, int *dims)
18803{
18804 tree purpose[GOMP_DIM_MAX];
18805 unsigned ix;
18806 tree pos = TREE_VALUE (attrs);
18807 int fn_level = -1;
18808
18809 /* Make sure the attribute creator attached the dimension
18810 information. */
18811 gcc_assert (pos);
18812
18813 for (ix = 0; ix != GOMP_DIM_MAX; ix++)
18814 {
18815 purpose[ix] = TREE_PURPOSE (pos);
18816
18817 if (purpose[ix])
18818 {
18819 if (integer_zerop (purpose[ix]))
18820 fn_level = ix + 1;
18821 else if (fn_level < 0)
18822 fn_level = ix;
18823 }
18824
18825 tree val = TREE_VALUE (pos);
18826 dims[ix] = val ? TREE_INT_CST_LOW (val) : -1;
18827 pos = TREE_CHAIN (pos);
18828 }
18829
18830 bool changed = targetm.goacc.validate_dims (fn, dims, fn_level);
18831
18832 /* Default anything left to 1. */
18833 for (ix = 0; ix != GOMP_DIM_MAX; ix++)
18834 if (dims[ix] < 0)
18835 {
18836 dims[ix] = 1;
18837 changed = true;
18838 }
18839
18840 if (changed)
18841 {
18842 /* Replace the attribute with new values. */
18843 pos = NULL_TREE;
18844 for (ix = GOMP_DIM_MAX; ix--;)
18845 pos = tree_cons (purpose[ix],
18846 build_int_cst (integer_type_node, dims[ix]),
18847 pos);
18848 replace_oacc_fn_attrib (fn, pos);
18849 }
18850
18851 return fn_level;
18852}
18853
cbba99a0 18854/* Create an empty OpenACC loop structure at LOC. */
18855
18856static oacc_loop *
18857new_oacc_loop_raw (oacc_loop *parent, location_t loc)
18858{
18859 oacc_loop *loop = XCNEW (oacc_loop);
18860
18861 loop->parent = parent;
18862 loop->child = loop->sibling = NULL;
18863
18864 if (parent)
18865 {
18866 loop->sibling = parent->child;
18867 parent->child = loop;
18868 }
18869
18870 loop->loc = loc;
18871 loop->marker = NULL;
18872 memset (loop->heads, 0, sizeof (loop->heads));
18873 memset (loop->tails, 0, sizeof (loop->tails));
18874 loop->routine = NULL_TREE;
18875
18876 loop->mask = loop->flags = 0;
18877 loop->chunk_size = 0;
18878 loop->head_end = NULL;
18879
18880 return loop;
18881}
18882
18883/* Create an outermost, dummy OpenACC loop for offloaded function
18884 DECL. */
18885
18886static oacc_loop *
18887new_oacc_loop_outer (tree decl)
18888{
18889 return new_oacc_loop_raw (NULL, DECL_SOURCE_LOCATION (decl));
18890}
18891
18892/* Start a new OpenACC loop structure beginning at head marker HEAD.
18893 Link into PARENT loop. Return the new loop. */
18894
18895static oacc_loop *
18896new_oacc_loop (oacc_loop *parent, gcall *marker)
18897{
18898 oacc_loop *loop = new_oacc_loop_raw (parent, gimple_location (marker));
18899
18900 loop->marker = marker;
18901
18902 /* TODO: This is where device_type flattening would occur for the loop
18903 flags. */
18904
18905 loop->flags = TREE_INT_CST_LOW (gimple_call_arg (marker, 3));
18906
18907 tree chunk_size = integer_zero_node;
18908 if (loop->flags & OLF_GANG_STATIC)
18909 chunk_size = gimple_call_arg (marker, 4);
18910 loop->chunk_size = chunk_size;
18911
18912 return loop;
18913}
18914
18915/* Create a dummy loop encompassing a call to a openACC routine.
18916 Extract the routine's partitioning requirements. */
18917
18918static void
18919new_oacc_loop_routine (oacc_loop *parent, gcall *call, tree decl, tree attrs)
18920{
18921 oacc_loop *loop = new_oacc_loop_raw (parent, gimple_location (call));
18922 int dims[GOMP_DIM_MAX];
18923 int level = oacc_validate_dims (decl, attrs, dims);
18924
18925 gcc_assert (level >= 0);
18926
18927 loop->marker = call;
18928 loop->routine = decl;
18929 loop->mask = ((GOMP_DIM_MASK (GOMP_DIM_MAX) - 1)
18930 ^ (GOMP_DIM_MASK (level) - 1));
18931}
18932
18933/* Finish off the current OpenACC loop ending at tail marker TAIL.
18934 Return the parent loop. */
18935
18936static oacc_loop *
18937finish_oacc_loop (oacc_loop *loop)
18938{
18939 return loop->parent;
18940}
18941
18942/* Free all OpenACC loop structures within LOOP (inclusive). */
18943
18944static void
18945free_oacc_loop (oacc_loop *loop)
18946{
18947 if (loop->sibling)
18948 free_oacc_loop (loop->sibling);
18949 if (loop->child)
18950 free_oacc_loop (loop->child);
18951
18952 free (loop);
18953}
18954
18955/* Dump out the OpenACC loop head or tail beginning at FROM. */
18956
18957static void
18958dump_oacc_loop_part (FILE *file, gcall *from, int depth,
18959 const char *title, int level)
18960{
18961 enum ifn_unique_kind kind
18962 = (enum ifn_unique_kind) TREE_INT_CST_LOW (gimple_call_arg (from, 0));
18963
18964 fprintf (file, "%*s%s-%d:\n", depth * 2, "", title, level);
18965 for (gimple_stmt_iterator gsi = gsi_for_stmt (from);;)
18966 {
18967 gimple *stmt = gsi_stmt (gsi);
18968
18969 if (is_gimple_call (stmt)
18970 && gimple_call_internal_p (stmt)
18971 && gimple_call_internal_fn (stmt) == IFN_UNIQUE)
18972 {
18973 enum ifn_unique_kind k
18974 = ((enum ifn_unique_kind) TREE_INT_CST_LOW
18975 (gimple_call_arg (stmt, 0)));
18976
18977 if (k == kind && stmt != from)
18978 break;
18979 }
18980 print_gimple_stmt (file, stmt, depth * 2 + 2, 0);
18981
18982 gsi_next (&gsi);
18983 while (gsi_end_p (gsi))
18984 gsi = gsi_start_bb (single_succ (gsi_bb (gsi)));
18985 }
18986}
18987
18988/* Dump OpenACC loops LOOP, its siblings and its children. */
18989
18990static void
18991dump_oacc_loop (FILE *file, oacc_loop *loop, int depth)
18992{
18993 int ix;
18994
18995 fprintf (file, "%*sLoop %x(%x) %s:%u\n", depth * 2, "",
18996 loop->flags, loop->mask,
18997 LOCATION_FILE (loop->loc), LOCATION_LINE (loop->loc));
18998
18999 if (loop->marker)
19000 print_gimple_stmt (file, loop->marker, depth * 2, 0);
19001
19002 if (loop->routine)
19003 fprintf (file, "%*sRoutine %s:%u:%s\n",
19004 depth * 2, "", DECL_SOURCE_FILE (loop->routine),
19005 DECL_SOURCE_LINE (loop->routine),
19006 IDENTIFIER_POINTER (DECL_NAME (loop->routine)));
19007
19008 for (ix = GOMP_DIM_GANG; ix != GOMP_DIM_MAX; ix++)
19009 if (loop->heads[ix])
19010 dump_oacc_loop_part (file, loop->heads[ix], depth, "Head", ix);
19011 for (ix = GOMP_DIM_MAX; ix--;)
19012 if (loop->tails[ix])
19013 dump_oacc_loop_part (file, loop->tails[ix], depth, "Tail", ix);
19014
19015 if (loop->child)
19016 dump_oacc_loop (file, loop->child, depth + 1);
19017 if (loop->sibling)
19018 dump_oacc_loop (file, loop->sibling, depth);
19019}
19020
19021void debug_oacc_loop (oacc_loop *);
19022
19023/* Dump loops to stderr. */
19024
19025DEBUG_FUNCTION void
19026debug_oacc_loop (oacc_loop *loop)
19027{
19028 dump_oacc_loop (stderr, loop, 0);
19029}
19030
19031/* DFS walk of basic blocks BB onwards, creating OpenACC loop
19032 structures as we go. By construction these loops are properly
19033 nested. */
19034
19035static void
19036oacc_loop_discover_walk (oacc_loop *loop, basic_block bb)
19037{
19038 int marker = 0;
19039 int remaining = 0;
19040
19041 if (bb->flags & BB_VISITED)
19042 return;
19043
19044 follow:
19045 bb->flags |= BB_VISITED;
19046
19047 /* Scan for loop markers. */
19048 for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);
19049 gsi_next (&gsi))
19050 {
19051 gimple *stmt = gsi_stmt (gsi);
19052
19053 if (!is_gimple_call (stmt))
19054 continue;
19055
19056 gcall *call = as_a <gcall *> (stmt);
19057
19058 /* If this is a routine, make a dummy loop for it. */
19059 if (tree decl = gimple_call_fndecl (call))
19060 if (tree attrs = get_oacc_fn_attrib (decl))
19061 {
19062 gcc_assert (!marker);
19063 new_oacc_loop_routine (loop, call, decl, attrs);
19064 }
19065
19066 if (!gimple_call_internal_p (call))
19067 continue;
19068
19069 if (gimple_call_internal_fn (call) != IFN_UNIQUE)
19070 continue;
19071
19072 enum ifn_unique_kind kind
19073 = (enum ifn_unique_kind) TREE_INT_CST_LOW (gimple_call_arg (call, 0));
19074 if (kind == IFN_UNIQUE_OACC_HEAD_MARK
19075 || kind == IFN_UNIQUE_OACC_TAIL_MARK)
19076 {
19077 if (gimple_call_num_args (call) == 2)
19078 {
19079 gcc_assert (marker && !remaining);
19080 marker = 0;
19081 if (kind == IFN_UNIQUE_OACC_TAIL_MARK)
19082 loop = finish_oacc_loop (loop);
19083 else
19084 loop->head_end = call;
19085 }
19086 else
19087 {
19088 int count = TREE_INT_CST_LOW (gimple_call_arg (call, 2));
19089
19090 if (!marker)
19091 {
19092 if (kind == IFN_UNIQUE_OACC_HEAD_MARK)
19093 loop = new_oacc_loop (loop, call);
19094 remaining = count;
19095 }
19096 gcc_assert (count == remaining);
19097 if (remaining)
19098 {
19099 remaining--;
19100 if (kind == IFN_UNIQUE_OACC_HEAD_MARK)
19101 loop->heads[marker] = call;
19102 else
19103 loop->tails[remaining] = call;
19104 }
19105 marker++;
19106 }
19107 }
19108 }
19109 if (remaining || marker)
19110 {
19111 bb = single_succ (bb);
19112 gcc_assert (single_pred_p (bb) && !(bb->flags & BB_VISITED));
19113 goto follow;
19114 }
19115
19116 /* Walk successor blocks. */
19117 edge e;
19118 edge_iterator ei;
19119
19120 FOR_EACH_EDGE (e, ei, bb->succs)
19121 oacc_loop_discover_walk (loop, e->dest);
19122}
19123
19124/* LOOP is the first sibling. Reverse the order in place and return
19125 the new first sibling. Recurse to child loops. */
19126
19127static oacc_loop *
19128oacc_loop_sibling_nreverse (oacc_loop *loop)
19129{
19130 oacc_loop *last = NULL;
19131 do
19132 {
19133 if (loop->child)
19134 loop->child = oacc_loop_sibling_nreverse (loop->child);
19135
19136 oacc_loop *next = loop->sibling;
19137 loop->sibling = last;
19138 last = loop;
19139 loop = next;
19140 }
19141 while (loop);
19142
19143 return last;
19144}
19145
19146/* Discover the OpenACC loops marked up by HEAD and TAIL markers for
19147 the current function. */
19148
19149static oacc_loop *
19150oacc_loop_discovery ()
19151{
19152 basic_block bb;
19153
19154 oacc_loop *top = new_oacc_loop_outer (current_function_decl);
19155 oacc_loop_discover_walk (top, ENTRY_BLOCK_PTR_FOR_FN (cfun));
19156
19157 /* The siblings were constructed in reverse order, reverse them so
19158 that diagnostics come out in an unsurprising order. */
19159 top = oacc_loop_sibling_nreverse (top);
19160
19161 /* Reset the visited flags. */
19162 FOR_ALL_BB_FN (bb, cfun)
19163 bb->flags &= ~BB_VISITED;
19164
19165 return top;
19166}
19167
19168/* Transform the abstract internal function markers starting at FROM
19169 to be for partitioning level LEVEL. Stop when we meet another HEAD
19170 or TAIL marker. */
19171
19172static void
19173oacc_loop_xform_head_tail (gcall *from, int level)
19174{
19175 enum ifn_unique_kind kind
19176 = (enum ifn_unique_kind) TREE_INT_CST_LOW (gimple_call_arg (from, 0));
19177 tree replacement = build_int_cst (unsigned_type_node, level);
19178
19179 for (gimple_stmt_iterator gsi = gsi_for_stmt (from);;)
19180 {
19181 gimple *stmt = gsi_stmt (gsi);
19182
19183 if (is_gimple_call (stmt)
19184 && gimple_call_internal_p (stmt)
19185 && gimple_call_internal_fn (stmt) == IFN_UNIQUE)
19186 {
19187 enum ifn_unique_kind k
19188 = ((enum ifn_unique_kind)
19189 TREE_INT_CST_LOW (gimple_call_arg (stmt, 0)));
19190
19191 if (k == IFN_UNIQUE_OACC_FORK || k == IFN_UNIQUE_OACC_JOIN)
19192 *gimple_call_arg_ptr (stmt, 2) = replacement;
19193 else if (k == kind && stmt != from)
19194 break;
19195 }
641a0fa1 19196 else if (is_gimple_call (stmt)
19197 && gimple_call_internal_p (stmt)
19198 && gimple_call_internal_fn (stmt) == IFN_GOACC_REDUCTION)
19199 *gimple_call_arg_ptr (stmt, 3) = replacement;
19200
cbba99a0 19201 gsi_next (&gsi);
19202 while (gsi_end_p (gsi))
19203 gsi = gsi_start_bb (single_succ (gsi_bb (gsi)));
19204 }
19205}
19206
19207/* Transform the IFN_GOACC_LOOP internal functions by providing the
19208 determined partitioning mask and chunking argument. */
19209
19210static void
19211oacc_loop_xform_loop (gcall *end_marker, tree mask_arg, tree chunk_arg)
19212{
19213 gimple_stmt_iterator gsi = gsi_for_stmt (end_marker);
19214
19215 for (;;)
19216 {
19217 for (; !gsi_end_p (gsi); gsi_next (&gsi))
19218 {
19219 gimple *stmt = gsi_stmt (gsi);
19220
19221 if (!is_gimple_call (stmt))
19222 continue;
19223
19224 gcall *call = as_a <gcall *> (stmt);
19225
19226 if (!gimple_call_internal_p (call))
19227 continue;
19228
19229 if (gimple_call_internal_fn (call) != IFN_GOACC_LOOP)
19230 continue;
19231
19232 *gimple_call_arg_ptr (call, 5) = mask_arg;
19233 *gimple_call_arg_ptr (call, 4) = chunk_arg;
19234 if (TREE_INT_CST_LOW (gimple_call_arg (call, 0))
19235 == IFN_GOACC_LOOP_BOUND)
19236 return;
19237 }
19238
19239 /* If we didn't see LOOP_BOUND, it should be in the single
19240 successor block. */
19241 basic_block bb = single_succ (gsi_bb (gsi));
19242 gsi = gsi_start_bb (bb);
19243 }
19244}
19245
19246/* Process the discovered OpenACC loops, setting the correct
19247 partitioning level etc. */
19248
19249static void
19250oacc_loop_process (oacc_loop *loop)
19251{
19252 if (loop->child)
19253 oacc_loop_process (loop->child);
19254
19255 if (loop->mask && !loop->routine)
19256 {
19257 int ix;
19258 unsigned mask = loop->mask;
19259 unsigned dim = GOMP_DIM_GANG;
19260 tree mask_arg = build_int_cst (unsigned_type_node, mask);
19261 tree chunk_arg = loop->chunk_size;
19262
19263 oacc_loop_xform_loop (loop->head_end, mask_arg, chunk_arg);
19264
19265 for (ix = 0; ix != GOMP_DIM_MAX && loop->heads[ix]; ix++)
19266 {
19267 gcc_assert (mask);
19268
19269 while (!(GOMP_DIM_MASK (dim) & mask))
19270 dim++;
19271
19272 oacc_loop_xform_head_tail (loop->heads[ix], dim);
19273 oacc_loop_xform_head_tail (loop->tails[ix], dim);
19274
19275 mask ^= GOMP_DIM_MASK (dim);
19276 }
19277 }
19278
19279 if (loop->sibling)
19280 oacc_loop_process (loop->sibling);
19281}
19282
19283/* Walk the OpenACC loop heirarchy checking and assigning the
19284 programmer-specified partitionings. OUTER_MASK is the partitioning
f4f5b4b4 19285 this loop is contained within. Return true if we contain an
19286 auto-partitionable loop. */
cbba99a0 19287
f4f5b4b4 19288static bool
cbba99a0 19289oacc_loop_fixed_partitions (oacc_loop *loop, unsigned outer_mask)
19290{
19291 unsigned this_mask = loop->mask;
19292 bool has_auto = false;
19293 bool noisy = true;
19294
19295#ifdef ACCEL_COMPILER
19296 /* When device_type is supported, we want the device compiler to be
19297 noisy, if the loop parameters are device_type-specific. */
19298 noisy = false;
19299#endif
19300
19301 if (!loop->routine)
19302 {
19303 bool auto_par = (loop->flags & OLF_AUTO) != 0;
19304 bool seq_par = (loop->flags & OLF_SEQ) != 0;
19305
19306 this_mask = ((loop->flags >> OLF_DIM_BASE)
19307 & (GOMP_DIM_MASK (GOMP_DIM_MAX) - 1));
19308
19309 if ((this_mask != 0) + auto_par + seq_par > 1)
19310 {
19311 if (noisy)
19312 error_at (loop->loc,
19313 seq_par
19314 ? "%<seq%> overrides other OpenACC loop specifiers"
19315 : "%<auto%> conflicts with other OpenACC loop specifiers");
19316 auto_par = false;
19317 loop->flags &= ~OLF_AUTO;
19318 if (seq_par)
19319 {
19320 loop->flags &=
19321 ~((GOMP_DIM_MASK (GOMP_DIM_MAX) - 1) << OLF_DIM_BASE);
19322 this_mask = 0;
19323 }
19324 }
19325 if (auto_par && (loop->flags & OLF_INDEPENDENT))
19326 has_auto = true;
19327 }
19328
19329 if (this_mask & outer_mask)
19330 {
19331 const oacc_loop *outer;
19332 for (outer = loop->parent; outer; outer = outer->parent)
19333 if (outer->mask & this_mask)
19334 break;
19335
19336 if (noisy)
19337 {
19338 if (outer)
19339 {
19340 error_at (loop->loc,
19341 "%s uses same OpenACC parallelism as containing loop",
19342 loop->routine ? "routine call" : "inner loop");
19343 inform (outer->loc, "containing loop here");
19344 }
19345 else
19346 error_at (loop->loc,
19347 "%s uses OpenACC parallelism disallowed by containing routine",
19348 loop->routine ? "routine call" : "loop");
19349
19350 if (loop->routine)
19351 inform (DECL_SOURCE_LOCATION (loop->routine),
19352 "routine %qD declared here", loop->routine);
19353 }
19354 this_mask &= ~outer_mask;
19355 }
19356 else
19357 {
19358 unsigned outermost = this_mask & -this_mask;
19359
19360 if (outermost && outermost <= outer_mask)
19361 {
19362 if (noisy)
19363 {
19364 error_at (loop->loc,
19365 "incorrectly nested OpenACC loop parallelism");
19366
19367 const oacc_loop *outer;
19368 for (outer = loop->parent;
19369 outer->flags && outer->flags < outermost;
19370 outer = outer->parent)
19371 continue;
19372 inform (outer->loc, "containing loop here");
19373 }
19374
19375 this_mask &= ~outermost;
19376 }
19377 }
19378
19379 loop->mask = this_mask;
19380
19381 if (loop->child
19382 && oacc_loop_fixed_partitions (loop->child, outer_mask | this_mask))
19383 has_auto = true;
19384
19385 if (loop->sibling
19386 && oacc_loop_fixed_partitions (loop->sibling, outer_mask))
19387 has_auto = true;
19388
19389 return has_auto;
19390}
19391
f4f5b4b4 19392/* Walk the OpenACC loop heirarchy to assign auto-partitioned loops.
19393 OUTER_MASK is the partitioning this loop is contained within.
19394 Return the cumulative partitioning used by this loop, siblings and
19395 children. */
19396
19397static unsigned
19398oacc_loop_auto_partitions (oacc_loop *loop, unsigned outer_mask)
19399{
19400 unsigned inner_mask = 0;
19401 bool noisy = true;
19402
19403#ifdef ACCEL_COMPILER
19404 /* When device_type is supported, we want the device compiler to be
19405 noisy, if the loop parameters are device_type-specific. */
19406 noisy = false;
19407#endif
19408
19409 if (loop->child)
19410 inner_mask |= oacc_loop_auto_partitions (loop->child,
19411 outer_mask | loop->mask);
19412
19413 if ((loop->flags & OLF_AUTO) && (loop->flags & OLF_INDEPENDENT))
19414 {
19415 unsigned this_mask = 0;
19416
19417 /* Determine the outermost partitioning used within this loop. */
19418 this_mask = inner_mask | GOMP_DIM_MASK (GOMP_DIM_MAX);
19419 this_mask = (this_mask & -this_mask);
19420
19421 /* Pick the partitioning just inside that one. */
19422 this_mask >>= 1;
19423
19424 /* And avoid picking one use by an outer loop. */
19425 this_mask &= ~outer_mask;
19426
19427 if (!this_mask && noisy)
19428 warning_at (loop->loc, 0,
19429 "insufficient partitioning available to parallelize loop");
19430
19431 loop->mask = this_mask;
19432 }
19433 inner_mask |= loop->mask;
19434
19435 if (loop->sibling)
19436 inner_mask |= oacc_loop_auto_partitions (loop->sibling, outer_mask);
19437
19438 return inner_mask;
19439}
19440
cbba99a0 19441/* Walk the OpenACC loop heirarchy to check and assign partitioning
19442 axes. */
19443
19444static void
f4f5b4b4 19445oacc_loop_partition (oacc_loop *loop, unsigned outer_mask)
cbba99a0 19446{
f4f5b4b4 19447 if (oacc_loop_fixed_partitions (loop, outer_mask))
19448 oacc_loop_auto_partitions (loop, outer_mask);
cbba99a0 19449}
19450
c25f1934 19451/* Default fork/join early expander. Delete the function calls if
19452 there is no RTL expander. */
19453
19454bool
19455default_goacc_fork_join (gcall *ARG_UNUSED (call),
19456 const int *ARG_UNUSED (dims), bool is_fork)
19457{
19458 if (is_fork)
19459 return targetm.have_oacc_fork ();
19460 else
19461 return targetm.have_oacc_join ();
19462}
19463
641a0fa1 19464/* Default goacc.reduction early expander.
19465
19466 LHS-opt = IFN_REDUCTION (KIND, RES_PTR, VAR, LEVEL, OP, OFFSET)
19467 If RES_PTR is not integer-zerop:
19468 SETUP - emit 'LHS = *RES_PTR', LHS = NULL
19469 TEARDOWN - emit '*RES_PTR = VAR'
19470 If LHS is not NULL
19471 emit 'LHS = VAR' */
19472
19473void
19474default_goacc_reduction (gcall *call)
19475{
19476 unsigned code = (unsigned)TREE_INT_CST_LOW (gimple_call_arg (call, 0));
19477 gimple_stmt_iterator gsi = gsi_for_stmt (call);
19478 tree lhs = gimple_call_lhs (call);
19479 tree var = gimple_call_arg (call, 2);
19480 gimple_seq seq = NULL;
19481
19482 if (code == IFN_GOACC_REDUCTION_SETUP
19483 || code == IFN_GOACC_REDUCTION_TEARDOWN)
19484 {
19485 /* Setup and Teardown need to copy from/to the receiver object,
19486 if there is one. */
19487 tree ref_to_res = gimple_call_arg (call, 1);
19488
19489 if (!integer_zerop (ref_to_res))
19490 {
19491 tree dst = build_simple_mem_ref (ref_to_res);
19492 tree src = var;
19493
19494 if (code == IFN_GOACC_REDUCTION_SETUP)
19495 {
19496 src = dst;
19497 dst = lhs;
19498 lhs = NULL;
19499 }
19500 gimple_seq_add_stmt (&seq, gimple_build_assign (dst, src));
19501 }
19502 }
19503
19504 /* Copy VAR to LHS, if there is an LHS. */
19505 if (lhs)
19506 gimple_seq_add_stmt (&seq, gimple_build_assign (lhs, var));
19507
19508 gsi_replace_with_seq (&gsi, seq, true);
19509}
19510
0bb0f256 19511/* Main entry point for oacc transformations which run on the device
19512 compiler after LTO, so we know what the target device is at this
19513 point (including the host fallback). */
19514
19515static unsigned int
19516execute_oacc_device_lower ()
19517{
19518 tree attrs = get_oacc_fn_attrib (current_function_decl);
19519 int dims[GOMP_DIM_MAX];
19520
19521 if (!attrs)
19522 /* Not an offloaded function. */
19523 return 0;
19524
cbba99a0 19525 int fn_level = oacc_validate_dims (current_function_decl, attrs, dims);
19526
19527 /* Discover, partition and process the loops. */
19528 oacc_loop *loops = oacc_loop_discovery ();
f4f5b4b4 19529 unsigned outer_mask = fn_level >= 0 ? GOMP_DIM_MASK (fn_level) - 1 : 0;
19530 oacc_loop_partition (loops, outer_mask);
cbba99a0 19531 oacc_loop_process (loops);
19532 if (dump_file)
19533 {
19534 fprintf (dump_file, "OpenACC loops\n");
19535 dump_oacc_loop (dump_file, loops, 0);
19536 fprintf (dump_file, "\n");
19537 }
19538
641a0fa1 19539 /* Offloaded targets may introduce new basic blocks, which require
19540 dominance information to update SSA. */
19541 calculate_dominance_info (CDI_DOMINATORS);
19542
cbba99a0 19543 /* Now lower internal loop functions to target-specific code
19544 sequences. */
19545 basic_block bb;
19546 FOR_ALL_BB_FN (bb, cfun)
19547 for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);)
19548 {
19549 gimple *stmt = gsi_stmt (gsi);
19550 if (!is_gimple_call (stmt))
19551 {
19552 gsi_next (&gsi);
19553 continue;
19554 }
19555
19556 gcall *call = as_a <gcall *> (stmt);
19557 if (!gimple_call_internal_p (call))
19558 {
19559 gsi_next (&gsi);
19560 continue;
19561 }
19562
19563 /* Rewind to allow rescan. */
19564 gsi_prev (&gsi);
19565 bool rescan = false, remove = false;
19566 enum internal_fn ifn_code = gimple_call_internal_fn (call);
19567
19568 switch (ifn_code)
19569 {
19570 default: break;
19571
19572 case IFN_GOACC_LOOP:
19573 oacc_xform_loop (call);
19574 rescan = true;
19575 break;
19576
641a0fa1 19577 case IFN_GOACC_REDUCTION:
19578 /* Mark the function for SSA renaming. */
19579 mark_virtual_operands_for_renaming (cfun);
19580
19581 /* If the level is -1, this ended up being an unused
19582 axis. Handle as a default. */
19583 if (integer_minus_onep (gimple_call_arg (call, 3)))
19584 default_goacc_reduction (call);
19585 else
19586 targetm.goacc.reduction (call);
19587 rescan = true;
19588 break;
19589
cbba99a0 19590 case IFN_UNIQUE:
19591 {
19592 enum ifn_unique_kind kind
19593 = ((enum ifn_unique_kind)
19594 TREE_INT_CST_LOW (gimple_call_arg (call, 0)));
19595
19596 switch (kind)
19597 {
19598 default:
19599 gcc_unreachable ();
19600
19601 case IFN_UNIQUE_OACC_FORK:
19602 case IFN_UNIQUE_OACC_JOIN:
19603 if (integer_minus_onep (gimple_call_arg (call, 2)))
19604 remove = true;
19605 else if (!targetm.goacc.fork_join
19606 (call, dims, kind == IFN_UNIQUE_OACC_FORK))
19607 remove = true;
19608 break;
19609
19610 case IFN_UNIQUE_OACC_HEAD_MARK:
19611 case IFN_UNIQUE_OACC_TAIL_MARK:
19612 remove = true;
19613 break;
19614 }
19615 break;
19616 }
19617 }
19618
19619 if (gsi_end_p (gsi))
19620 /* We rewound past the beginning of the BB. */
19621 gsi = gsi_start_bb (bb);
19622 else
19623 /* Undo the rewind. */
19624 gsi_next (&gsi);
19625
19626 if (remove)
19627 {
19628 if (gimple_vdef (call))
19629 replace_uses_by (gimple_vdef (call), gimple_vuse (call));
19630 if (gimple_call_lhs (call))
19631 {
19632 /* Propagate the data dependency var. */
19633 gimple *ass = gimple_build_assign (gimple_call_lhs (call),
19634 gimple_call_arg (call, 1));
19635 gsi_replace (&gsi, ass, false);
19636 }
19637 else
19638 gsi_remove (&gsi, true);
19639 }
19640 else if (!rescan)
19641 /* If not rescanning, advance over the call. */
19642 gsi_next (&gsi);
19643 }
19644
19645 free_oacc_loop (loops);
19646
0bb0f256 19647 return 0;
19648}
19649
19650/* Default launch dimension validator. Force everything to 1. A
19651 backend that wants to provide larger dimensions must override this
19652 hook. */
19653
19654bool
19655default_goacc_validate_dims (tree ARG_UNUSED (decl), int *dims,
19656 int ARG_UNUSED (fn_level))
19657{
19658 bool changed = false;
19659
19660 for (unsigned ix = 0; ix != GOMP_DIM_MAX; ix++)
19661 {
19662 if (dims[ix] != 1)
19663 {
19664 dims[ix] = 1;
19665 changed = true;
19666 }
19667 }
19668
19669 return changed;
19670}
19671
e1037942 19672/* Default dimension bound is unknown on accelerator and 1 on host. */
19673
19674int
19675default_goacc_dim_limit (int ARG_UNUSED (axis))
19676{
19677#ifdef ACCEL_COMPILER
19678 return 0;
19679#else
19680 return 1;
19681#endif
19682}
19683
0bb0f256 19684namespace {
19685
19686const pass_data pass_data_oacc_device_lower =
19687{
19688 GIMPLE_PASS, /* type */
19689 "oaccdevlow", /* name */
19690 OPTGROUP_NONE, /* optinfo_flags */
19691 TV_NONE, /* tv_id */
19692 PROP_cfg, /* properties_required */
19693 0 /* Possibly PROP_gimple_eomp. */, /* properties_provided */
19694 0, /* properties_destroyed */
19695 0, /* todo_flags_start */
19696 TODO_update_ssa | TODO_cleanup_cfg, /* todo_flags_finish */
19697};
19698
19699class pass_oacc_device_lower : public gimple_opt_pass
19700{
19701public:
19702 pass_oacc_device_lower (gcc::context *ctxt)
19703 : gimple_opt_pass (pass_data_oacc_device_lower, ctxt)
19704 {}
19705
19706 /* opt_pass methods: */
19707 virtual unsigned int execute (function *)
19708 {
173dfdf5 19709 bool gate = flag_openacc != 0;
0bb0f256 19710
19711 if (!gate)
19712 return 0;
19713
19714 return execute_oacc_device_lower ();
19715 }
19716
f69b8a4c 19717}; // class pass_oacc_device_lower
0bb0f256 19718
19719} // anon namespace
19720
19721gimple_opt_pass *
19722make_pass_oacc_device_lower (gcc::context *ctxt)
19723{
19724 return new pass_oacc_device_lower (ctxt);
19725}
19726
1e8e9920 19727#include "gt-omp-low.h"