]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/omp-low.c
Allow pass_parallelize_loops to be run outside the loop pipeline
[thirdparty/gcc.git] / gcc / omp-low.c
CommitLineData
ca4c3545 1/* Lowering pass for OMP directives. Converts OMP directives into explicit
2 calls to the runtime library (libgomp), data marshalling to implement data
3 sharing and copying clauses, offloading to accelerators, and more.
4
1e8e9920 5 Contributed by Diego Novillo <dnovillo@redhat.com>
6
f1717362 7 Copyright (C) 2005-2016 Free Software Foundation, Inc.
1e8e9920 8
9This file is part of GCC.
10
11GCC is free software; you can redistribute it and/or modify it under
12the terms of the GNU General Public License as published by the Free
8c4c00c1 13Software Foundation; either version 3, or (at your option) any later
1e8e9920 14version.
15
16GCC is distributed in the hope that it will be useful, but WITHOUT ANY
17WARRANTY; without even the implied warranty of MERCHANTABILITY or
18FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19for more details.
20
21You should have received a copy of the GNU General Public License
8c4c00c1 22along with GCC; see the file COPYING3. If not see
23<http://www.gnu.org/licenses/>. */
1e8e9920 24
25#include "config.h"
26#include "system.h"
27#include "coretypes.h"
9ef16211 28#include "backend.h"
7c29e30e 29#include "target.h"
30#include "rtl.h"
1e8e9920 31#include "tree.h"
9ef16211 32#include "gimple.h"
7c29e30e 33#include "cfghooks.h"
34#include "alloc-pool.h"
35#include "tree-pass.h"
9ef16211 36#include "ssa.h"
7c29e30e 37#include "expmed.h"
38#include "optabs.h"
39#include "emit-rtl.h"
40#include "cgraph.h"
41#include "pretty-print.h"
42#include "diagnostic-core.h"
9ef16211 43#include "alias.h"
b20a8bb4 44#include "fold-const.h"
9ed99284 45#include "stor-layout.h"
94ea8568 46#include "cfganal.h"
bc61cadb 47#include "internal-fn.h"
48#include "gimple-fold.h"
a8783bee 49#include "gimplify.h"
dcf1a1ec 50#include "gimple-iterator.h"
e795d6e1 51#include "gimplify-me.h"
dcf1a1ec 52#include "gimple-walk.h"
75a70cf9 53#include "tree-iterator.h"
1e8e9920 54#include "tree-inline.h"
55#include "langhooks.h"
073c1fd5 56#include "tree-cfg.h"
073c1fd5 57#include "tree-into-ssa.h"
d53441c8 58#include "flags.h"
d53441c8 59#include "dojump.h"
60#include "explow.h"
61#include "calls.h"
d53441c8 62#include "varasm.h"
63#include "stmt.h"
9ed99284 64#include "expr.h"
073c1fd5 65#include "tree-dfa.h"
69ee5dbb 66#include "tree-ssa.h"
1e8e9920 67#include "except.h"
e3022db7 68#include "splay-tree.h"
cb7f680b 69#include "cfgloop.h"
dccabdd1 70#include "common/common-target.h"
7740abd8 71#include "omp-low.h"
424a4a92 72#include "gimple-low.h"
73#include "tree-cfgcleanup.h"
2cc80ac3 74#include "symbol-summary.h"
d09768a4 75#include "ipa-prop.h"
e797f49f 76#include "tree-nested.h"
d09768a4 77#include "tree-eh.h"
40750995 78#include "cilk.h"
b0c5e347 79#include "context.h"
dccabdd1 80#include "lto-section-names.h"
ca4c3545 81#include "gomp-constants.h"
cbba99a0 82#include "gimple-pretty-print.h"
1e8e9920 83
ca4c3545 84/* Lowering of OMP parallel and workshare constructs proceeds in two
1e8e9920 85 phases. The first phase scans the function looking for OMP statements
86 and then for variables that must be replaced to satisfy data sharing
87 clauses. The second phase expands code for the constructs, as well as
334ec2d8 88 re-gimplifying things when variables have been replaced with complex
1e8e9920 89 expressions.
90
d134bccc 91 Final code generation is done by pass_expand_omp. The flowgraph is
ca4c3545 92 scanned for regions which are then moved to a new
93 function, to be invoked by the thread library, or offloaded. */
1e8e9920 94
ca4c3545 95/* OMP region information. Every parallel and workshare
7740abd8 96 directive is enclosed between two markers, the OMP_* directive
43895be5 97 and a corresponding GIMPLE_OMP_RETURN statement. */
7740abd8 98
99struct omp_region
100{
101 /* The enclosing region. */
102 struct omp_region *outer;
103
104 /* First child region. */
105 struct omp_region *inner;
106
107 /* Next peer region. */
108 struct omp_region *next;
109
110 /* Block containing the omp directive as its last stmt. */
111 basic_block entry;
112
43895be5 113 /* Block containing the GIMPLE_OMP_RETURN as its last stmt. */
7740abd8 114 basic_block exit;
115
43895be5 116 /* Block containing the GIMPLE_OMP_CONTINUE as its last stmt. */
7740abd8 117 basic_block cont;
118
119 /* If this is a combined parallel+workshare region, this is a list
120 of additional arguments needed by the combined parallel+workshare
121 library call. */
122 vec<tree, va_gc> *ws_args;
123
124 /* The code for the omp directive of this region. */
125 enum gimple_code type;
126
43895be5 127 /* Schedule kind, only used for GIMPLE_OMP_FOR type regions. */
7740abd8 128 enum omp_clause_schedule_kind sched_kind;
129
9561765e 130 /* Schedule modifiers. */
131 unsigned char sched_modifiers;
132
7740abd8 133 /* True if this is a combined parallel+workshare region. */
134 bool is_combined_parallel;
43895be5 135
136 /* The ordered stmt if type is GIMPLE_OMP_ORDERED and it has
137 a depend clause. */
138 gomp_ordered *ord_stmt;
7740abd8 139};
140
1e8e9920 141/* Context structure. Used to store information about each parallel
142 directive in the code. */
143
6dc50383 144struct omp_context
1e8e9920 145{
146 /* This field must be at the beginning, as we do "inheritance": Some
147 callback functions for tree-inline.c (e.g., omp_copy_decl)
148 receive a copy_body_data pointer that is up-casted to an
149 omp_context pointer. */
150 copy_body_data cb;
151
152 /* The tree of contexts corresponding to the encountered constructs. */
153 struct omp_context *outer;
42acab1c 154 gimple *stmt;
1e8e9920 155
48e1416a 156 /* Map variables to fields in a structure that allows communication
1e8e9920 157 between sending and receiving threads. */
158 splay_tree field_map;
159 tree record_type;
160 tree sender_decl;
161 tree receiver_decl;
162
fd6481cf 163 /* These are used just by task contexts, if task firstprivate fn is
164 needed. srecord_type is used to communicate from the thread
165 that encountered the task construct to task firstprivate fn,
166 record_type is allocated by GOMP_task, initialized by task firstprivate
167 fn and passed to the task body fn. */
168 splay_tree sfield_map;
169 tree srecord_type;
170
1e8e9920 171 /* A chain of variables to add to the top-level block surrounding the
172 construct. In the case of a parallel, this is in the child function. */
173 tree block_vars;
174
bc7bff74 175 /* Label to which GOMP_cancel{,llation_point} and explicit and implicit
176 barriers should jump to during omplower pass. */
177 tree cancel_label;
178
1e8e9920 179 /* What to do with variables with implicitly determined sharing
180 attributes. */
181 enum omp_clause_default_kind default_kind;
182
183 /* Nesting depth of this context. Used to beautify error messages re
184 invalid gotos. The outermost ctx is depth 1, with depth 0 being
185 reserved for the main body of the function. */
186 int depth;
187
1e8e9920 188 /* True if this parallel directive is nested within another. */
189 bool is_nested;
bc7bff74 190
191 /* True if this construct can be cancelled. */
192 bool cancellable;
6dc50383 193};
1e8e9920 194
ca4c3545 195/* A structure holding the elements of:
196 for (V = N1; V cond N2; V += STEP) [...] */
1e8e9920 197
fd6481cf 198struct omp_for_data_loop
199{
200 tree v, n1, n2, step;
201 enum tree_code cond_code;
202};
203
773c5ba7 204/* A structure describing the main elements of a parallel loop. */
1e8e9920 205
773c5ba7 206struct omp_for_data
1e8e9920 207{
fd6481cf 208 struct omp_for_data_loop loop;
75a70cf9 209 tree chunk_size;
1a91d914 210 gomp_for *for_stmt;
fd6481cf 211 tree pre, iter_type;
212 int collapse;
43895be5 213 int ordered;
214 bool have_nowait, have_ordered, simd_schedule;
9561765e 215 unsigned char sched_modifiers;
1e8e9920 216 enum omp_clause_schedule_kind sched_kind;
fd6481cf 217 struct omp_for_data_loop *loops;
1e8e9920 218};
219
cbba99a0 220/* Describe the OpenACC looping structure of a function. The entire
221 function is held in a 'NULL' loop. */
222
223struct oacc_loop
224{
225 oacc_loop *parent; /* Containing loop. */
226
227 oacc_loop *child; /* First inner loop. */
228
229 oacc_loop *sibling; /* Next loop within same parent. */
230
231 location_t loc; /* Location of the loop start. */
232
233 gcall *marker; /* Initial head marker. */
234
235 gcall *heads[GOMP_DIM_MAX]; /* Head marker functions. */
236 gcall *tails[GOMP_DIM_MAX]; /* Tail marker functions. */
237
238 tree routine; /* Pseudo-loop enclosing a routine. */
239
240 unsigned mask; /* Partitioning mask. */
241 unsigned flags; /* Partitioning flags. */
242 tree chunk_size; /* Chunk size. */
243 gcall *head_end; /* Final marker of head sequence. */
244};
245
246/* Flags for an OpenACC loop. */
247
248enum oacc_loop_flags {
249 OLF_SEQ = 1u << 0, /* Explicitly sequential */
250 OLF_AUTO = 1u << 1, /* Compiler chooses axes. */
251 OLF_INDEPENDENT = 1u << 2, /* Iterations are known independent. */
252 OLF_GANG_STATIC = 1u << 3, /* Gang partitioning is static (has op). */
253
254 /* Explicitly specified loop axes. */
255 OLF_DIM_BASE = 4,
256 OLF_DIM_GANG = 1u << (OLF_DIM_BASE + GOMP_DIM_GANG),
257 OLF_DIM_WORKER = 1u << (OLF_DIM_BASE + GOMP_DIM_WORKER),
258 OLF_DIM_VECTOR = 1u << (OLF_DIM_BASE + GOMP_DIM_VECTOR),
259
260 OLF_MAX = OLF_DIM_BASE + GOMP_DIM_MAX
261};
262
773c5ba7 263
1e8e9920 264static splay_tree all_contexts;
fd6481cf 265static int taskreg_nesting_level;
bc7bff74 266static int target_nesting_level;
7740abd8 267static struct omp_region *root_omp_region;
fd6481cf 268static bitmap task_shared_vars;
37eaded9 269static vec<omp_context *> taskreg_contexts;
9561765e 270static bool omp_any_child_fn_dumped;
1e8e9920 271
ab129075 272static void scan_omp (gimple_seq *, omp_context *);
75a70cf9 273static tree scan_omp_1_op (tree *, int *, void *);
2131a1a9 274static gphi *find_phi_with_arg_on_edge (tree, edge);
75a70cf9 275
276#define WALK_SUBSTMTS \
277 case GIMPLE_BIND: \
278 case GIMPLE_TRY: \
279 case GIMPLE_CATCH: \
280 case GIMPLE_EH_FILTER: \
4c0315d0 281 case GIMPLE_TRANSACTION: \
75a70cf9 282 /* The sub-statements for these should be walked. */ \
283 *handled_ops_p = false; \
284 break;
285
a8e785ba 286/* Return true if CTX corresponds to an oacc parallel region. */
287
288static bool
289is_oacc_parallel (omp_context *ctx)
290{
291 enum gimple_code outer_type = gimple_code (ctx->stmt);
292 return ((outer_type == GIMPLE_OMP_TARGET)
293 && (gimple_omp_target_kind (ctx->stmt)
294 == GF_OMP_TARGET_KIND_OACC_PARALLEL));
295}
296
297/* Return true if CTX corresponds to an oacc kernels region. */
298
299static bool
300is_oacc_kernels (omp_context *ctx)
301{
302 enum gimple_code outer_type = gimple_code (ctx->stmt);
303 return ((outer_type == GIMPLE_OMP_TARGET)
304 && (gimple_omp_target_kind (ctx->stmt)
305 == GF_OMP_TARGET_KIND_OACC_KERNELS));
306}
307
43895be5 308/* If DECL is the artificial dummy VAR_DECL created for non-static
309 data member privatization, return the underlying "this" parameter,
310 otherwise return NULL. */
311
312tree
313omp_member_access_dummy_var (tree decl)
314{
315 if (!VAR_P (decl)
316 || !DECL_ARTIFICIAL (decl)
317 || !DECL_IGNORED_P (decl)
318 || !DECL_HAS_VALUE_EXPR_P (decl)
319 || !lang_hooks.decls.omp_disregard_value_expr (decl, false))
320 return NULL_TREE;
321
322 tree v = DECL_VALUE_EXPR (decl);
323 if (TREE_CODE (v) != COMPONENT_REF)
324 return NULL_TREE;
325
326 while (1)
327 switch (TREE_CODE (v))
328 {
329 case COMPONENT_REF:
330 case MEM_REF:
331 case INDIRECT_REF:
332 CASE_CONVERT:
333 case POINTER_PLUS_EXPR:
334 v = TREE_OPERAND (v, 0);
335 continue;
336 case PARM_DECL:
337 if (DECL_CONTEXT (v) == current_function_decl
338 && DECL_ARTIFICIAL (v)
339 && TREE_CODE (TREE_TYPE (v)) == POINTER_TYPE)
340 return v;
341 return NULL_TREE;
342 default:
343 return NULL_TREE;
344 }
345}
346
347/* Helper for unshare_and_remap, called through walk_tree. */
348
349static tree
350unshare_and_remap_1 (tree *tp, int *walk_subtrees, void *data)
351{
352 tree *pair = (tree *) data;
353 if (*tp == pair[0])
354 {
355 *tp = unshare_expr (pair[1]);
356 *walk_subtrees = 0;
357 }
358 else if (IS_TYPE_OR_DECL_P (*tp))
359 *walk_subtrees = 0;
360 return NULL_TREE;
361}
362
363/* Return unshare_expr (X) with all occurrences of FROM
364 replaced with TO. */
365
366static tree
367unshare_and_remap (tree x, tree from, tree to)
368{
369 tree pair[2] = { from, to };
370 x = unshare_expr (x);
371 walk_tree (&x, unshare_and_remap_1, pair, NULL);
372 return x;
373}
374
dccabdd1 375/* Holds offload tables with decls. */
376vec<tree, va_gc> *offload_funcs, *offload_vars;
377
75a70cf9 378/* Convenience function for calling scan_omp_1_op on tree operands. */
379
380static inline tree
381scan_omp_op (tree *tp, omp_context *ctx)
382{
383 struct walk_stmt_info wi;
384
385 memset (&wi, 0, sizeof (wi));
386 wi.info = ctx;
387 wi.want_locations = true;
388
389 return walk_tree (tp, scan_omp_1_op, &wi, NULL);
390}
391
e3a19533 392static void lower_omp (gimple_seq *, omp_context *);
f49d7bb5 393static tree lookup_decl_in_outer_ctx (tree, omp_context *);
394static tree maybe_lookup_decl_in_outer_ctx (tree, omp_context *);
1e8e9920 395
ca4c3545 396/* Find an OMP clause of type KIND within CLAUSES. */
1e8e9920 397
79acaae1 398tree
590c3166 399find_omp_clause (tree clauses, enum omp_clause_code kind)
1e8e9920 400{
401 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
55d6e7cd 402 if (OMP_CLAUSE_CODE (clauses) == kind)
1e8e9920 403 return clauses;
404
405 return NULL_TREE;
406}
407
408/* Return true if CTX is for an omp parallel. */
409
410static inline bool
411is_parallel_ctx (omp_context *ctx)
412{
75a70cf9 413 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL;
1e8e9920 414}
415
773c5ba7 416
fd6481cf 417/* Return true if CTX is for an omp task. */
418
419static inline bool
420is_task_ctx (omp_context *ctx)
421{
75a70cf9 422 return gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
fd6481cf 423}
424
425
43895be5 426/* Return true if CTX is for an omp taskloop. */
427
428static inline bool
429is_taskloop_ctx (omp_context *ctx)
430{
431 return gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
432 && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_TASKLOOP;
433}
434
435
fd6481cf 436/* Return true if CTX is for an omp parallel or omp task. */
437
438static inline bool
439is_taskreg_ctx (omp_context *ctx)
440{
43895be5 441 return is_parallel_ctx (ctx) || is_task_ctx (ctx);
fd6481cf 442}
443
444
773c5ba7 445/* Return true if REGION is a combined parallel+workshare region. */
1e8e9920 446
447static inline bool
773c5ba7 448is_combined_parallel (struct omp_region *region)
449{
450 return region->is_combined_parallel;
451}
452
453
454/* Extract the header elements of parallel loop FOR_STMT and store
455 them into *FD. */
456
457static void
1a91d914 458extract_omp_for_data (gomp_for *for_stmt, struct omp_for_data *fd,
fd6481cf 459 struct omp_for_data_loop *loops)
773c5ba7 460{
fd6481cf 461 tree t, var, *collapse_iter, *collapse_count;
462 tree count = NULL_TREE, iter_type = long_integer_type_node;
463 struct omp_for_data_loop *loop;
464 int i;
465 struct omp_for_data_loop dummy_loop;
389dd41b 466 location_t loc = gimple_location (for_stmt);
10c55644 467 bool simd = gimple_omp_for_kind (for_stmt) & GF_OMP_FOR_SIMD;
bc7bff74 468 bool distribute = gimple_omp_for_kind (for_stmt)
469 == GF_OMP_FOR_KIND_DISTRIBUTE;
43895be5 470 bool taskloop = gimple_omp_for_kind (for_stmt)
471 == GF_OMP_FOR_KIND_TASKLOOP;
472 tree iterv, countv;
773c5ba7 473
474 fd->for_stmt = for_stmt;
475 fd->pre = NULL;
43895be5 476 if (gimple_omp_for_collapse (for_stmt) > 1)
fd6481cf 477 fd->loops = loops;
478 else
479 fd->loops = &fd->loop;
773c5ba7 480
bc7bff74 481 fd->have_nowait = distribute || simd;
482 fd->have_ordered = false;
43895be5 483 fd->collapse = 1;
484 fd->ordered = 0;
773c5ba7 485 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
9561765e 486 fd->sched_modifiers = 0;
773c5ba7 487 fd->chunk_size = NULL_TREE;
43895be5 488 fd->simd_schedule = false;
40750995 489 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
490 fd->sched_kind = OMP_CLAUSE_SCHEDULE_CILKFOR;
fd6481cf 491 collapse_iter = NULL;
492 collapse_count = NULL;
773c5ba7 493
75a70cf9 494 for (t = gimple_omp_for_clauses (for_stmt); t ; t = OMP_CLAUSE_CHAIN (t))
55d6e7cd 495 switch (OMP_CLAUSE_CODE (t))
773c5ba7 496 {
497 case OMP_CLAUSE_NOWAIT:
498 fd->have_nowait = true;
499 break;
500 case OMP_CLAUSE_ORDERED:
501 fd->have_ordered = true;
43895be5 502 if (OMP_CLAUSE_ORDERED_EXPR (t))
503 fd->ordered = tree_to_shwi (OMP_CLAUSE_ORDERED_EXPR (t));
773c5ba7 504 break;
505 case OMP_CLAUSE_SCHEDULE:
43895be5 506 gcc_assert (!distribute && !taskloop);
9561765e 507 fd->sched_kind
508 = (enum omp_clause_schedule_kind)
509 (OMP_CLAUSE_SCHEDULE_KIND (t) & OMP_CLAUSE_SCHEDULE_MASK);
510 fd->sched_modifiers = (OMP_CLAUSE_SCHEDULE_KIND (t)
511 & ~OMP_CLAUSE_SCHEDULE_MASK);
773c5ba7 512 fd->chunk_size = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t);
43895be5 513 fd->simd_schedule = OMP_CLAUSE_SCHEDULE_SIMD (t);
773c5ba7 514 break;
bc7bff74 515 case OMP_CLAUSE_DIST_SCHEDULE:
516 gcc_assert (distribute);
517 fd->chunk_size = OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (t);
518 break;
fd6481cf 519 case OMP_CLAUSE_COLLAPSE:
43895be5 520 fd->collapse = tree_to_shwi (OMP_CLAUSE_COLLAPSE_EXPR (t));
fd6481cf 521 if (fd->collapse > 1)
522 {
523 collapse_iter = &OMP_CLAUSE_COLLAPSE_ITERVAR (t);
524 collapse_count = &OMP_CLAUSE_COLLAPSE_COUNT (t);
525 }
757abb46 526 break;
773c5ba7 527 default:
528 break;
529 }
43895be5 530 if (fd->ordered && fd->collapse == 1 && loops != NULL)
531 {
532 fd->loops = loops;
533 iterv = NULL_TREE;
534 countv = NULL_TREE;
535 collapse_iter = &iterv;
536 collapse_count = &countv;
537 }
773c5ba7 538
fd6481cf 539 /* FIXME: for now map schedule(auto) to schedule(static).
540 There should be analysis to determine whether all iterations
541 are approximately the same amount of work (then schedule(static)
bde357c8 542 is best) or if it varies (then schedule(dynamic,N) is better). */
fd6481cf 543 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_AUTO)
544 {
545 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
546 gcc_assert (fd->chunk_size == NULL);
547 }
548 gcc_assert (fd->collapse == 1 || collapse_iter != NULL);
43895be5 549 if (taskloop)
550 fd->sched_kind = OMP_CLAUSE_SCHEDULE_RUNTIME;
773c5ba7 551 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
552 gcc_assert (fd->chunk_size == NULL);
553 else if (fd->chunk_size == NULL)
554 {
555 /* We only need to compute a default chunk size for ordered
556 static loops and dynamic loops. */
fd6481cf 557 if (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
bc7bff74 558 || fd->have_ordered)
773c5ba7 559 fd->chunk_size = (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
560 ? integer_zero_node : integer_one_node;
561 }
fd6481cf 562
43895be5 563 int cnt = fd->ordered ? fd->ordered : fd->collapse;
564 for (i = 0; i < cnt; i++)
fd6481cf 565 {
43895be5 566 if (i == 0 && fd->collapse == 1 && (fd->ordered == 0 || loops == NULL))
fd6481cf 567 loop = &fd->loop;
568 else if (loops != NULL)
569 loop = loops + i;
570 else
571 loop = &dummy_loop;
572
75a70cf9 573 loop->v = gimple_omp_for_index (for_stmt, i);
fd6481cf 574 gcc_assert (SSA_VAR_P (loop->v));
575 gcc_assert (TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
576 || TREE_CODE (TREE_TYPE (loop->v)) == POINTER_TYPE);
577 var = TREE_CODE (loop->v) == SSA_NAME ? SSA_NAME_VAR (loop->v) : loop->v;
75a70cf9 578 loop->n1 = gimple_omp_for_initial (for_stmt, i);
fd6481cf 579
75a70cf9 580 loop->cond_code = gimple_omp_for_cond (for_stmt, i);
581 loop->n2 = gimple_omp_for_final (for_stmt, i);
fd6481cf 582 switch (loop->cond_code)
583 {
584 case LT_EXPR:
585 case GT_EXPR:
586 break;
f2697631 587 case NE_EXPR:
588 gcc_assert (gimple_omp_for_kind (for_stmt)
40750995 589 == GF_OMP_FOR_KIND_CILKSIMD
590 || (gimple_omp_for_kind (for_stmt)
591 == GF_OMP_FOR_KIND_CILKFOR));
f2697631 592 break;
fd6481cf 593 case LE_EXPR:
594 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
2cc66f2a 595 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, 1);
fd6481cf 596 else
389dd41b 597 loop->n2 = fold_build2_loc (loc,
598 PLUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
fd6481cf 599 build_int_cst (TREE_TYPE (loop->n2), 1));
600 loop->cond_code = LT_EXPR;
601 break;
602 case GE_EXPR:
603 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
2cc66f2a 604 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, -1);
fd6481cf 605 else
389dd41b 606 loop->n2 = fold_build2_loc (loc,
607 MINUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
fd6481cf 608 build_int_cst (TREE_TYPE (loop->n2), 1));
609 loop->cond_code = GT_EXPR;
610 break;
611 default:
612 gcc_unreachable ();
613 }
614
75a70cf9 615 t = gimple_omp_for_incr (for_stmt, i);
fd6481cf 616 gcc_assert (TREE_OPERAND (t, 0) == var);
617 switch (TREE_CODE (t))
618 {
619 case PLUS_EXPR:
fd6481cf 620 loop->step = TREE_OPERAND (t, 1);
621 break;
85d86b55 622 case POINTER_PLUS_EXPR:
623 loop->step = fold_convert (ssizetype, TREE_OPERAND (t, 1));
624 break;
fd6481cf 625 case MINUS_EXPR:
626 loop->step = TREE_OPERAND (t, 1);
389dd41b 627 loop->step = fold_build1_loc (loc,
628 NEGATE_EXPR, TREE_TYPE (loop->step),
fd6481cf 629 loop->step);
630 break;
631 default:
632 gcc_unreachable ();
633 }
634
bc7bff74 635 if (simd
636 || (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
637 && !fd->have_ordered))
3d483a94 638 {
639 if (fd->collapse == 1)
640 iter_type = TREE_TYPE (loop->v);
641 else if (i == 0
642 || TYPE_PRECISION (iter_type)
643 < TYPE_PRECISION (TREE_TYPE (loop->v)))
644 iter_type
645 = build_nonstandard_integer_type
bc7bff74 646 (TYPE_PRECISION (TREE_TYPE (loop->v)), 1);
3d483a94 647 }
648 else if (iter_type != long_long_unsigned_type_node)
fd6481cf 649 {
650 if (POINTER_TYPE_P (TREE_TYPE (loop->v)))
651 iter_type = long_long_unsigned_type_node;
652 else if (TYPE_UNSIGNED (TREE_TYPE (loop->v))
653 && TYPE_PRECISION (TREE_TYPE (loop->v))
654 >= TYPE_PRECISION (iter_type))
655 {
656 tree n;
657
658 if (loop->cond_code == LT_EXPR)
389dd41b 659 n = fold_build2_loc (loc,
660 PLUS_EXPR, TREE_TYPE (loop->v),
fd6481cf 661 loop->n2, loop->step);
662 else
663 n = loop->n1;
664 if (TREE_CODE (n) != INTEGER_CST
665 || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type), n))
666 iter_type = long_long_unsigned_type_node;
667 }
668 else if (TYPE_PRECISION (TREE_TYPE (loop->v))
669 > TYPE_PRECISION (iter_type))
670 {
671 tree n1, n2;
672
673 if (loop->cond_code == LT_EXPR)
674 {
675 n1 = loop->n1;
389dd41b 676 n2 = fold_build2_loc (loc,
677 PLUS_EXPR, TREE_TYPE (loop->v),
fd6481cf 678 loop->n2, loop->step);
679 }
680 else
681 {
389dd41b 682 n1 = fold_build2_loc (loc,
683 MINUS_EXPR, TREE_TYPE (loop->v),
fd6481cf 684 loop->n2, loop->step);
685 n2 = loop->n1;
686 }
687 if (TREE_CODE (n1) != INTEGER_CST
688 || TREE_CODE (n2) != INTEGER_CST
689 || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type), n1)
690 || !tree_int_cst_lt (n2, TYPE_MAX_VALUE (iter_type)))
691 iter_type = long_long_unsigned_type_node;
692 }
693 }
694
43895be5 695 if (i >= fd->collapse)
696 continue;
697
fd6481cf 698 if (collapse_count && *collapse_count == NULL)
699 {
8e6b4515 700 t = fold_binary (loop->cond_code, boolean_type_node,
701 fold_convert (TREE_TYPE (loop->v), loop->n1),
702 fold_convert (TREE_TYPE (loop->v), loop->n2));
703 if (t && integer_zerop (t))
704 count = build_zero_cst (long_long_unsigned_type_node);
705 else if ((i == 0 || count != NULL_TREE)
706 && TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
707 && TREE_CONSTANT (loop->n1)
708 && TREE_CONSTANT (loop->n2)
709 && TREE_CODE (loop->step) == INTEGER_CST)
fd6481cf 710 {
711 tree itype = TREE_TYPE (loop->v);
712
713 if (POINTER_TYPE_P (itype))
3cea8318 714 itype = signed_type_for (itype);
fd6481cf 715 t = build_int_cst (itype, (loop->cond_code == LT_EXPR ? -1 : 1));
389dd41b 716 t = fold_build2_loc (loc,
717 PLUS_EXPR, itype,
718 fold_convert_loc (loc, itype, loop->step), t);
719 t = fold_build2_loc (loc, PLUS_EXPR, itype, t,
720 fold_convert_loc (loc, itype, loop->n2));
721 t = fold_build2_loc (loc, MINUS_EXPR, itype, t,
722 fold_convert_loc (loc, itype, loop->n1));
fd6481cf 723 if (TYPE_UNSIGNED (itype) && loop->cond_code == GT_EXPR)
389dd41b 724 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype,
725 fold_build1_loc (loc, NEGATE_EXPR, itype, t),
726 fold_build1_loc (loc, NEGATE_EXPR, itype,
727 fold_convert_loc (loc, itype,
728 loop->step)));
fd6481cf 729 else
389dd41b 730 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, t,
731 fold_convert_loc (loc, itype, loop->step));
732 t = fold_convert_loc (loc, long_long_unsigned_type_node, t);
fd6481cf 733 if (count != NULL_TREE)
389dd41b 734 count = fold_build2_loc (loc,
735 MULT_EXPR, long_long_unsigned_type_node,
fd6481cf 736 count, t);
737 else
738 count = t;
739 if (TREE_CODE (count) != INTEGER_CST)
740 count = NULL_TREE;
741 }
8e6b4515 742 else if (count && !integer_zerop (count))
fd6481cf 743 count = NULL_TREE;
744 }
745 }
746
3d483a94 747 if (count
bc7bff74 748 && !simd
749 && (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
750 || fd->have_ordered))
fd6481cf 751 {
752 if (!tree_int_cst_lt (count, TYPE_MAX_VALUE (long_integer_type_node)))
753 iter_type = long_long_unsigned_type_node;
754 else
755 iter_type = long_integer_type_node;
756 }
757 else if (collapse_iter && *collapse_iter != NULL)
758 iter_type = TREE_TYPE (*collapse_iter);
759 fd->iter_type = iter_type;
760 if (collapse_iter && *collapse_iter == NULL)
761 *collapse_iter = create_tmp_var (iter_type, ".iter");
762 if (collapse_count && *collapse_count == NULL)
763 {
764 if (count)
389dd41b 765 *collapse_count = fold_convert_loc (loc, iter_type, count);
fd6481cf 766 else
767 *collapse_count = create_tmp_var (iter_type, ".count");
768 }
769
43895be5 770 if (fd->collapse > 1 || (fd->ordered && loops))
fd6481cf 771 {
772 fd->loop.v = *collapse_iter;
773 fd->loop.n1 = build_int_cst (TREE_TYPE (fd->loop.v), 0);
774 fd->loop.n2 = *collapse_count;
775 fd->loop.step = build_int_cst (TREE_TYPE (fd->loop.v), 1);
776 fd->loop.cond_code = LT_EXPR;
777 }
43895be5 778 else if (loops)
779 loops[0] = fd->loop;
773c5ba7 780}
781
782
783/* Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB
784 is the immediate dominator of PAR_ENTRY_BB, return true if there
785 are no data dependencies that would prevent expanding the parallel
786 directive at PAR_ENTRY_BB as a combined parallel+workshare region.
787
788 When expanding a combined parallel+workshare region, the call to
789 the child function may need additional arguments in the case of
75a70cf9 790 GIMPLE_OMP_FOR regions. In some cases, these arguments are
791 computed out of variables passed in from the parent to the child
792 via 'struct .omp_data_s'. For instance:
773c5ba7 793
794 #pragma omp parallel for schedule (guided, i * 4)
795 for (j ...)
796
797 Is lowered into:
798
799 # BLOCK 2 (PAR_ENTRY_BB)
800 .omp_data_o.i = i;
801 #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
48e1416a 802
773c5ba7 803 # BLOCK 3 (WS_ENTRY_BB)
804 .omp_data_i = &.omp_data_o;
805 D.1667 = .omp_data_i->i;
806 D.1598 = D.1667 * 4;
807 #pragma omp for schedule (guided, D.1598)
808
809 When we outline the parallel region, the call to the child function
810 'bar.omp_fn.0' will need the value D.1598 in its argument list, but
811 that value is computed *after* the call site. So, in principle we
812 cannot do the transformation.
813
814 To see whether the code in WS_ENTRY_BB blocks the combined
815 parallel+workshare call, we collect all the variables used in the
75a70cf9 816 GIMPLE_OMP_FOR header check whether they appear on the LHS of any
773c5ba7 817 statement in WS_ENTRY_BB. If so, then we cannot emit the combined
818 call.
819
820 FIXME. If we had the SSA form built at this point, we could merely
821 hoist the code in block 3 into block 2 and be done with it. But at
822 this point we don't have dataflow information and though we could
823 hack something up here, it is really not worth the aggravation. */
824
825static bool
f018d957 826workshare_safe_to_combine_p (basic_block ws_entry_bb)
773c5ba7 827{
828 struct omp_for_data fd;
42acab1c 829 gimple *ws_stmt = last_stmt (ws_entry_bb);
773c5ba7 830
75a70cf9 831 if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
773c5ba7 832 return true;
833
75a70cf9 834 gcc_assert (gimple_code (ws_stmt) == GIMPLE_OMP_FOR);
773c5ba7 835
1a91d914 836 extract_omp_for_data (as_a <gomp_for *> (ws_stmt), &fd, NULL);
fd6481cf 837
838 if (fd.collapse > 1 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
839 return false;
840 if (fd.iter_type != long_integer_type_node)
841 return false;
773c5ba7 842
843 /* FIXME. We give up too easily here. If any of these arguments
844 are not constants, they will likely involve variables that have
845 been mapped into fields of .omp_data_s for sharing with the child
846 function. With appropriate data flow, it would be possible to
847 see through this. */
fd6481cf 848 if (!is_gimple_min_invariant (fd.loop.n1)
849 || !is_gimple_min_invariant (fd.loop.n2)
850 || !is_gimple_min_invariant (fd.loop.step)
773c5ba7 851 || (fd.chunk_size && !is_gimple_min_invariant (fd.chunk_size)))
852 return false;
853
854 return true;
855}
856
857
43895be5 858static int omp_max_vf (void);
859
860/* Adjust CHUNK_SIZE from SCHEDULE clause, depending on simd modifier
861 presence (SIMD_SCHEDULE). */
862
863static tree
864omp_adjust_chunk_size (tree chunk_size, bool simd_schedule)
865{
866 if (!simd_schedule)
867 return chunk_size;
868
869 int vf = omp_max_vf ();
870 if (vf == 1)
871 return chunk_size;
872
873 tree type = TREE_TYPE (chunk_size);
874 chunk_size = fold_build2 (PLUS_EXPR, type, chunk_size,
875 build_int_cst (type, vf - 1));
876 return fold_build2 (BIT_AND_EXPR, type, chunk_size,
877 build_int_cst (type, -vf));
878}
879
880
773c5ba7 881/* Collect additional arguments needed to emit a combined
882 parallel+workshare call. WS_STMT is the workshare directive being
883 expanded. */
884
f1f41a6c 885static vec<tree, va_gc> *
42acab1c 886get_ws_args_for (gimple *par_stmt, gimple *ws_stmt)
773c5ba7 887{
888 tree t;
389dd41b 889 location_t loc = gimple_location (ws_stmt);
f1f41a6c 890 vec<tree, va_gc> *ws_args;
773c5ba7 891
1a91d914 892 if (gomp_for *for_stmt = dyn_cast <gomp_for *> (ws_stmt))
773c5ba7 893 {
894 struct omp_for_data fd;
bc7bff74 895 tree n1, n2;
773c5ba7 896
1a91d914 897 extract_omp_for_data (for_stmt, &fd, NULL);
bc7bff74 898 n1 = fd.loop.n1;
899 n2 = fd.loop.n2;
900
1a91d914 901 if (gimple_omp_for_combined_into_p (for_stmt))
bc7bff74 902 {
903 tree innerc
904 = find_omp_clause (gimple_omp_parallel_clauses (par_stmt),
905 OMP_CLAUSE__LOOPTEMP_);
906 gcc_assert (innerc);
907 n1 = OMP_CLAUSE_DECL (innerc);
908 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
909 OMP_CLAUSE__LOOPTEMP_);
910 gcc_assert (innerc);
911 n2 = OMP_CLAUSE_DECL (innerc);
912 }
773c5ba7 913
f1f41a6c 914 vec_alloc (ws_args, 3 + (fd.chunk_size != 0));
773c5ba7 915
bc7bff74 916 t = fold_convert_loc (loc, long_integer_type_node, n1);
f1f41a6c 917 ws_args->quick_push (t);
773c5ba7 918
bc7bff74 919 t = fold_convert_loc (loc, long_integer_type_node, n2);
f1f41a6c 920 ws_args->quick_push (t);
773c5ba7 921
414c3a2c 922 t = fold_convert_loc (loc, long_integer_type_node, fd.loop.step);
f1f41a6c 923 ws_args->quick_push (t);
414c3a2c 924
925 if (fd.chunk_size)
926 {
927 t = fold_convert_loc (loc, long_integer_type_node, fd.chunk_size);
43895be5 928 t = omp_adjust_chunk_size (t, fd.simd_schedule);
f1f41a6c 929 ws_args->quick_push (t);
414c3a2c 930 }
773c5ba7 931
932 return ws_args;
933 }
75a70cf9 934 else if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
773c5ba7 935 {
ac6e3339 936 /* Number of sections is equal to the number of edges from the
75a70cf9 937 GIMPLE_OMP_SECTIONS_SWITCH statement, except for the one to
938 the exit of the sections region. */
939 basic_block bb = single_succ (gimple_bb (ws_stmt));
ac6e3339 940 t = build_int_cst (unsigned_type_node, EDGE_COUNT (bb->succs) - 1);
f1f41a6c 941 vec_alloc (ws_args, 1);
942 ws_args->quick_push (t);
414c3a2c 943 return ws_args;
773c5ba7 944 }
945
946 gcc_unreachable ();
947}
948
949
950/* Discover whether REGION is a combined parallel+workshare region. */
951
952static void
953determine_parallel_type (struct omp_region *region)
1e8e9920 954{
773c5ba7 955 basic_block par_entry_bb, par_exit_bb;
956 basic_block ws_entry_bb, ws_exit_bb;
957
03ed154b 958 if (region == NULL || region->inner == NULL
ac6e3339 959 || region->exit == NULL || region->inner->exit == NULL
960 || region->inner->cont == NULL)
773c5ba7 961 return;
962
963 /* We only support parallel+for and parallel+sections. */
75a70cf9 964 if (region->type != GIMPLE_OMP_PARALLEL
965 || (region->inner->type != GIMPLE_OMP_FOR
966 && region->inner->type != GIMPLE_OMP_SECTIONS))
773c5ba7 967 return;
968
969 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
970 WS_EXIT_BB -> PAR_EXIT_BB. */
61e47ac8 971 par_entry_bb = region->entry;
972 par_exit_bb = region->exit;
973 ws_entry_bb = region->inner->entry;
974 ws_exit_bb = region->inner->exit;
773c5ba7 975
976 if (single_succ (par_entry_bb) == ws_entry_bb
977 && single_succ (ws_exit_bb) == par_exit_bb
f018d957 978 && workshare_safe_to_combine_p (ws_entry_bb)
75a70cf9 979 && (gimple_omp_parallel_combined_p (last_stmt (par_entry_bb))
de7ef844 980 || (last_and_only_stmt (ws_entry_bb)
981 && last_and_only_stmt (par_exit_bb))))
773c5ba7 982 {
42acab1c 983 gimple *par_stmt = last_stmt (par_entry_bb);
984 gimple *ws_stmt = last_stmt (ws_entry_bb);
61e47ac8 985
75a70cf9 986 if (region->inner->type == GIMPLE_OMP_FOR)
773c5ba7 987 {
988 /* If this is a combined parallel loop, we need to determine
989 whether or not to use the combined library calls. There
990 are two cases where we do not apply the transformation:
991 static loops and any kind of ordered loop. In the first
992 case, we already open code the loop so there is no need
993 to do anything else. In the latter case, the combined
994 parallel loop call would still need extra synchronization
995 to implement ordered semantics, so there would not be any
996 gain in using the combined call. */
75a70cf9 997 tree clauses = gimple_omp_for_clauses (ws_stmt);
773c5ba7 998 tree c = find_omp_clause (clauses, OMP_CLAUSE_SCHEDULE);
999 if (c == NULL
9561765e 1000 || ((OMP_CLAUSE_SCHEDULE_KIND (c) & OMP_CLAUSE_SCHEDULE_MASK)
1001 == OMP_CLAUSE_SCHEDULE_STATIC)
773c5ba7 1002 || find_omp_clause (clauses, OMP_CLAUSE_ORDERED))
1003 {
1004 region->is_combined_parallel = false;
1005 region->inner->is_combined_parallel = false;
1006 return;
1007 }
1008 }
1009
1010 region->is_combined_parallel = true;
1011 region->inner->is_combined_parallel = true;
bc7bff74 1012 region->ws_args = get_ws_args_for (par_stmt, ws_stmt);
773c5ba7 1013 }
1e8e9920 1014}
1015
773c5ba7 1016
1e8e9920 1017/* Return true if EXPR is variable sized. */
1018
1019static inline bool
1f1872fd 1020is_variable_sized (const_tree expr)
1e8e9920 1021{
1022 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr)));
1023}
1024
1025/* Return true if DECL is a reference type. */
1026
1027static inline bool
1028is_reference (tree decl)
1029{
1030 return lang_hooks.decls.omp_privatize_by_reference (decl);
1031}
1032
ca4c3545 1033/* Return the type of a decl. If the decl is reference type,
1034 return its base type. */
1035static inline tree
1036get_base_type (tree decl)
1037{
1038 tree type = TREE_TYPE (decl);
1039 if (is_reference (decl))
1040 type = TREE_TYPE (type);
1041 return type;
1042}
1043
1044/* Lookup variables. The "maybe" form
1e8e9920 1045 allows for the variable form to not have been entered, otherwise we
1046 assert that the variable must have been entered. */
1047
1048static inline tree
1049lookup_decl (tree var, omp_context *ctx)
1050{
06ecf488 1051 tree *n = ctx->cb.decl_map->get (var);
e3022db7 1052 return *n;
1e8e9920 1053}
1054
1055static inline tree
e8a588af 1056maybe_lookup_decl (const_tree var, omp_context *ctx)
1e8e9920 1057{
06ecf488 1058 tree *n = ctx->cb.decl_map->get (const_cast<tree> (var));
e3022db7 1059 return n ? *n : NULL_TREE;
1e8e9920 1060}
1061
1062static inline tree
1063lookup_field (tree var, omp_context *ctx)
1064{
1065 splay_tree_node n;
1066 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
1067 return (tree) n->value;
1068}
1069
fd6481cf 1070static inline tree
43895be5 1071lookup_sfield (splay_tree_key key, omp_context *ctx)
fd6481cf 1072{
1073 splay_tree_node n;
1074 n = splay_tree_lookup (ctx->sfield_map
43895be5 1075 ? ctx->sfield_map : ctx->field_map, key);
fd6481cf 1076 return (tree) n->value;
1077}
1078
1e8e9920 1079static inline tree
43895be5 1080lookup_sfield (tree var, omp_context *ctx)
1081{
1082 return lookup_sfield ((splay_tree_key) var, ctx);
1083}
1084
1085static inline tree
1086maybe_lookup_field (splay_tree_key key, omp_context *ctx)
1e8e9920 1087{
1088 splay_tree_node n;
43895be5 1089 n = splay_tree_lookup (ctx->field_map, key);
1e8e9920 1090 return n ? (tree) n->value : NULL_TREE;
1091}
1092
43895be5 1093static inline tree
1094maybe_lookup_field (tree var, omp_context *ctx)
1095{
1096 return maybe_lookup_field ((splay_tree_key) var, ctx);
1097}
1098
e8a588af 1099/* Return true if DECL should be copied by pointer. SHARED_CTX is
1100 the parallel context if DECL is to be shared. */
1e8e9920 1101
1102static bool
fd6481cf 1103use_pointer_for_field (tree decl, omp_context *shared_ctx)
1e8e9920 1104{
1105 if (AGGREGATE_TYPE_P (TREE_TYPE (decl)))
1106 return true;
1107
554f2707 1108 /* We can only use copy-in/copy-out semantics for shared variables
1e8e9920 1109 when we know the value is not accessible from an outer scope. */
e8a588af 1110 if (shared_ctx)
1e8e9920 1111 {
ca4c3545 1112 gcc_assert (!is_gimple_omp_oacc (shared_ctx->stmt));
1113
1e8e9920 1114 /* ??? Trivially accessible from anywhere. But why would we even
1115 be passing an address in this case? Should we simply assert
1116 this to be false, or should we have a cleanup pass that removes
1117 these from the list of mappings? */
1118 if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
1119 return true;
1120
1121 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
1122 without analyzing the expression whether or not its location
1123 is accessible to anyone else. In the case of nested parallel
1124 regions it certainly may be. */
df2c34fc 1125 if (TREE_CODE (decl) != RESULT_DECL && DECL_HAS_VALUE_EXPR_P (decl))
1e8e9920 1126 return true;
1127
1128 /* Do not use copy-in/copy-out for variables that have their
1129 address taken. */
1130 if (TREE_ADDRESSABLE (decl))
1131 return true;
e8a588af 1132
b8214689 1133 /* lower_send_shared_vars only uses copy-in, but not copy-out
1134 for these. */
1135 if (TREE_READONLY (decl)
1136 || ((TREE_CODE (decl) == RESULT_DECL
1137 || TREE_CODE (decl) == PARM_DECL)
1138 && DECL_BY_REFERENCE (decl)))
1139 return false;
1140
e8a588af 1141 /* Disallow copy-in/out in nested parallel if
1142 decl is shared in outer parallel, otherwise
1143 each thread could store the shared variable
1144 in its own copy-in location, making the
1145 variable no longer really shared. */
b8214689 1146 if (shared_ctx->is_nested)
e8a588af 1147 {
1148 omp_context *up;
1149
1150 for (up = shared_ctx->outer; up; up = up->outer)
0cb159ec 1151 if (is_taskreg_ctx (up) && maybe_lookup_decl (decl, up))
e8a588af 1152 break;
1153
0cb159ec 1154 if (up)
e8a588af 1155 {
1156 tree c;
1157
75a70cf9 1158 for (c = gimple_omp_taskreg_clauses (up->stmt);
e8a588af 1159 c; c = OMP_CLAUSE_CHAIN (c))
1160 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
1161 && OMP_CLAUSE_DECL (c) == decl)
1162 break;
1163
1164 if (c)
784ad964 1165 goto maybe_mark_addressable_and_ret;
e8a588af 1166 }
1167 }
fd6481cf 1168
b8214689 1169 /* For tasks avoid using copy-in/out. As tasks can be
fd6481cf 1170 deferred or executed in different thread, when GOMP_task
1171 returns, the task hasn't necessarily terminated. */
b8214689 1172 if (is_task_ctx (shared_ctx))
fd6481cf 1173 {
784ad964 1174 tree outer;
1175 maybe_mark_addressable_and_ret:
1176 outer = maybe_lookup_decl_in_outer_ctx (decl, shared_ctx);
43895be5 1177 if (is_gimple_reg (outer) && !omp_member_access_dummy_var (outer))
fd6481cf 1178 {
1179 /* Taking address of OUTER in lower_send_shared_vars
1180 might need regimplification of everything that uses the
1181 variable. */
1182 if (!task_shared_vars)
1183 task_shared_vars = BITMAP_ALLOC (NULL);
1184 bitmap_set_bit (task_shared_vars, DECL_UID (outer));
1185 TREE_ADDRESSABLE (outer) = 1;
1186 }
1187 return true;
1188 }
1e8e9920 1189 }
1190
1191 return false;
1192}
1193
79acaae1 1194/* Construct a new automatic decl similar to VAR. */
1195
1196static tree
1197omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx)
1198{
1199 tree copy = copy_var_decl (var, name, type);
1200
1201 DECL_CONTEXT (copy) = current_function_decl;
1767a056 1202 DECL_CHAIN (copy) = ctx->block_vars;
43895be5 1203 /* If VAR is listed in task_shared_vars, it means it wasn't
1204 originally addressable and is just because task needs to take
1205 it's address. But we don't need to take address of privatizations
1206 from that var. */
1207 if (TREE_ADDRESSABLE (var)
1208 && task_shared_vars
1209 && bitmap_bit_p (task_shared_vars, DECL_UID (var)))
1210 TREE_ADDRESSABLE (copy) = 0;
1e8e9920 1211 ctx->block_vars = copy;
1212
1213 return copy;
1214}
1215
1216static tree
1217omp_copy_decl_1 (tree var, omp_context *ctx)
1218{
1219 return omp_copy_decl_2 (var, DECL_NAME (var), TREE_TYPE (var), ctx);
1220}
1221
445d06b6 1222/* Build COMPONENT_REF and set TREE_THIS_VOLATILE and TREE_READONLY on it
1223 as appropriate. */
1224static tree
1225omp_build_component_ref (tree obj, tree field)
1226{
1227 tree ret = build3 (COMPONENT_REF, TREE_TYPE (field), obj, field, NULL);
1228 if (TREE_THIS_VOLATILE (field))
1229 TREE_THIS_VOLATILE (ret) |= 1;
1230 if (TREE_READONLY (field))
1231 TREE_READONLY (ret) |= 1;
1232 return ret;
1233}
1234
1e8e9920 1235/* Build tree nodes to access the field for VAR on the receiver side. */
1236
1237static tree
1238build_receiver_ref (tree var, bool by_ref, omp_context *ctx)
1239{
1240 tree x, field = lookup_field (var, ctx);
1241
1242 /* If the receiver record type was remapped in the child function,
1243 remap the field into the new record type. */
1244 x = maybe_lookup_field (field, ctx);
1245 if (x != NULL)
1246 field = x;
1247
182cf5a9 1248 x = build_simple_mem_ref (ctx->receiver_decl);
75c20a2e 1249 TREE_THIS_NOTRAP (x) = 1;
445d06b6 1250 x = omp_build_component_ref (x, field);
1e8e9920 1251 if (by_ref)
b16d27b9 1252 {
1253 x = build_simple_mem_ref (x);
1254 TREE_THIS_NOTRAP (x) = 1;
1255 }
1e8e9920 1256
1257 return x;
1258}
1259
1260/* Build tree nodes to access VAR in the scope outer to CTX. In the case
1261 of a parallel, this is a component reference; for workshare constructs
1262 this is some variable. */
1263
1264static tree
43895be5 1265build_outer_var_ref (tree var, omp_context *ctx, bool lastprivate = false)
1e8e9920 1266{
1267 tree x;
1268
f49d7bb5 1269 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx)))
1e8e9920 1270 x = var;
1271 else if (is_variable_sized (var))
1272 {
1273 x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
43895be5 1274 x = build_outer_var_ref (x, ctx, lastprivate);
182cf5a9 1275 x = build_simple_mem_ref (x);
1e8e9920 1276 }
fd6481cf 1277 else if (is_taskreg_ctx (ctx))
1e8e9920 1278 {
e8a588af 1279 bool by_ref = use_pointer_for_field (var, NULL);
1e8e9920 1280 x = build_receiver_ref (var, by_ref, ctx);
1281 }
3d483a94 1282 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
10c55644 1283 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3d483a94 1284 {
1285 /* #pragma omp simd isn't a worksharing construct, and can reference even
1286 private vars in its linear etc. clauses. */
1287 x = NULL_TREE;
1288 if (ctx->outer && is_taskreg_ctx (ctx))
1289 x = lookup_decl (var, ctx->outer);
1290 else if (ctx->outer)
84cb1020 1291 x = maybe_lookup_decl_in_outer_ctx (var, ctx);
3d483a94 1292 if (x == NULL_TREE)
1293 x = var;
1294 }
43895be5 1295 else if (lastprivate && is_taskloop_ctx (ctx))
1296 {
1297 gcc_assert (ctx->outer);
1298 splay_tree_node n
1299 = splay_tree_lookup (ctx->outer->field_map,
1300 (splay_tree_key) &DECL_UID (var));
1301 if (n == NULL)
1302 {
1303 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx->outer)))
1304 x = var;
1305 else
1306 x = lookup_decl (var, ctx->outer);
1307 }
1308 else
1309 {
1310 tree field = (tree) n->value;
1311 /* If the receiver record type was remapped in the child function,
1312 remap the field into the new record type. */
1313 x = maybe_lookup_field (field, ctx->outer);
1314 if (x != NULL)
1315 field = x;
1316
1317 x = build_simple_mem_ref (ctx->outer->receiver_decl);
1318 x = omp_build_component_ref (x, field);
1319 if (use_pointer_for_field (var, ctx->outer))
1320 x = build_simple_mem_ref (x);
1321 }
1322 }
1e8e9920 1323 else if (ctx->outer)
1324 x = lookup_decl (var, ctx->outer);
9438af57 1325 else if (is_reference (var))
1326 /* This can happen with orphaned constructs. If var is reference, it is
1327 possible it is shared and as such valid. */
1328 x = var;
43895be5 1329 else if (omp_member_access_dummy_var (var))
1330 x = var;
1e8e9920 1331 else
1332 gcc_unreachable ();
1333
43895be5 1334 if (x == var)
1335 {
1336 tree t = omp_member_access_dummy_var (var);
1337 if (t)
1338 {
1339 x = DECL_VALUE_EXPR (var);
1340 tree o = maybe_lookup_decl_in_outer_ctx (t, ctx);
1341 if (o != t)
1342 x = unshare_and_remap (x, t, o);
1343 else
1344 x = unshare_expr (x);
1345 }
1346 }
1347
1e8e9920 1348 if (is_reference (var))
182cf5a9 1349 x = build_simple_mem_ref (x);
1e8e9920 1350
1351 return x;
1352}
1353
1354/* Build tree nodes to access the field for VAR on the sender side. */
1355
1356static tree
43895be5 1357build_sender_ref (splay_tree_key key, omp_context *ctx)
1e8e9920 1358{
43895be5 1359 tree field = lookup_sfield (key, ctx);
445d06b6 1360 return omp_build_component_ref (ctx->sender_decl, field);
1e8e9920 1361}
1362
43895be5 1363static tree
1364build_sender_ref (tree var, omp_context *ctx)
1365{
1366 return build_sender_ref ((splay_tree_key) var, ctx);
1367}
1368
12dc9a16 1369/* Add a new field for VAR inside the structure CTX->SENDER_DECL. If
1370 BASE_POINTERS_RESTRICT, declare the field with restrict. */
1e8e9920 1371
1372static void
12dc9a16 1373install_var_field (tree var, bool by_ref, int mask, omp_context *ctx,
1374 bool base_pointers_restrict = false)
1e8e9920 1375{
fd6481cf 1376 tree field, type, sfield = NULL_TREE;
43895be5 1377 splay_tree_key key = (splay_tree_key) var;
1e8e9920 1378
43895be5 1379 if ((mask & 8) != 0)
1380 {
1381 key = (splay_tree_key) &DECL_UID (var);
1382 gcc_checking_assert (key != (splay_tree_key) var);
1383 }
fd6481cf 1384 gcc_assert ((mask & 1) == 0
43895be5 1385 || !splay_tree_lookup (ctx->field_map, key));
fd6481cf 1386 gcc_assert ((mask & 2) == 0 || !ctx->sfield_map
43895be5 1387 || !splay_tree_lookup (ctx->sfield_map, key));
ca4c3545 1388 gcc_assert ((mask & 3) == 3
1389 || !is_gimple_omp_oacc (ctx->stmt));
1e8e9920 1390
1391 type = TREE_TYPE (var);
44c0112f 1392 /* Prevent redeclaring the var in the split-off function with a restrict
1393 pointer type. Note that we only clear type itself, restrict qualifiers in
1394 the pointed-to type will be ignored by points-to analysis. */
1395 if (POINTER_TYPE_P (type)
1396 && TYPE_RESTRICT (type))
1397 type = build_qualified_type (type, TYPE_QUALS (type) & ~TYPE_QUAL_RESTRICT);
1398
bc7bff74 1399 if (mask & 4)
1400 {
1401 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
1402 type = build_pointer_type (build_pointer_type (type));
1403 }
1404 else if (by_ref)
12dc9a16 1405 {
1406 type = build_pointer_type (type);
1407 if (base_pointers_restrict)
1408 type = build_qualified_type (type, TYPE_QUAL_RESTRICT);
1409 }
fd6481cf 1410 else if ((mask & 3) == 1 && is_reference (var))
1411 type = TREE_TYPE (type);
1e8e9920 1412
e60a6f7b 1413 field = build_decl (DECL_SOURCE_LOCATION (var),
1414 FIELD_DECL, DECL_NAME (var), type);
1e8e9920 1415
1416 /* Remember what variable this field was created for. This does have a
1417 side effect of making dwarf2out ignore this member, so for helpful
1418 debugging we clear it later in delete_omp_context. */
1419 DECL_ABSTRACT_ORIGIN (field) = var;
fd6481cf 1420 if (type == TREE_TYPE (var))
1421 {
1422 DECL_ALIGN (field) = DECL_ALIGN (var);
1423 DECL_USER_ALIGN (field) = DECL_USER_ALIGN (var);
1424 TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (var);
1425 }
1426 else
1427 DECL_ALIGN (field) = TYPE_ALIGN (type);
1e8e9920 1428
fd6481cf 1429 if ((mask & 3) == 3)
1430 {
1431 insert_field_into_struct (ctx->record_type, field);
1432 if (ctx->srecord_type)
1433 {
e60a6f7b 1434 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1435 FIELD_DECL, DECL_NAME (var), type);
fd6481cf 1436 DECL_ABSTRACT_ORIGIN (sfield) = var;
1437 DECL_ALIGN (sfield) = DECL_ALIGN (field);
1438 DECL_USER_ALIGN (sfield) = DECL_USER_ALIGN (field);
1439 TREE_THIS_VOLATILE (sfield) = TREE_THIS_VOLATILE (field);
1440 insert_field_into_struct (ctx->srecord_type, sfield);
1441 }
1442 }
1443 else
1444 {
1445 if (ctx->srecord_type == NULL_TREE)
1446 {
1447 tree t;
1448
1449 ctx->srecord_type = lang_hooks.types.make_type (RECORD_TYPE);
1450 ctx->sfield_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1451 for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
1452 {
43895be5 1453 sfield = build_decl (DECL_SOURCE_LOCATION (t),
e60a6f7b 1454 FIELD_DECL, DECL_NAME (t), TREE_TYPE (t));
fd6481cf 1455 DECL_ABSTRACT_ORIGIN (sfield) = DECL_ABSTRACT_ORIGIN (t);
1456 insert_field_into_struct (ctx->srecord_type, sfield);
1457 splay_tree_insert (ctx->sfield_map,
1458 (splay_tree_key) DECL_ABSTRACT_ORIGIN (t),
1459 (splay_tree_value) sfield);
1460 }
1461 }
1462 sfield = field;
1463 insert_field_into_struct ((mask & 1) ? ctx->record_type
1464 : ctx->srecord_type, field);
1465 }
1e8e9920 1466
fd6481cf 1467 if (mask & 1)
43895be5 1468 splay_tree_insert (ctx->field_map, key, (splay_tree_value) field);
fd6481cf 1469 if ((mask & 2) && ctx->sfield_map)
43895be5 1470 splay_tree_insert (ctx->sfield_map, key, (splay_tree_value) sfield);
1e8e9920 1471}
1472
1473static tree
1474install_var_local (tree var, omp_context *ctx)
1475{
1476 tree new_var = omp_copy_decl_1 (var, ctx);
1477 insert_decl_map (&ctx->cb, var, new_var);
1478 return new_var;
1479}
1480
1481/* Adjust the replacement for DECL in CTX for the new context. This means
1482 copying the DECL_VALUE_EXPR, and fixing up the type. */
1483
1484static void
1485fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug)
1486{
1487 tree new_decl, size;
1488
1489 new_decl = lookup_decl (decl, ctx);
1490
1491 TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb);
1492
1493 if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug)
1494 && DECL_HAS_VALUE_EXPR_P (decl))
1495 {
1496 tree ve = DECL_VALUE_EXPR (decl);
75a70cf9 1497 walk_tree (&ve, copy_tree_body_r, &ctx->cb, NULL);
1e8e9920 1498 SET_DECL_VALUE_EXPR (new_decl, ve);
1499 DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
1500 }
1501
1502 if (!TREE_CONSTANT (DECL_SIZE (new_decl)))
1503 {
1504 size = remap_decl (DECL_SIZE (decl), &ctx->cb);
1505 if (size == error_mark_node)
1506 size = TYPE_SIZE (TREE_TYPE (new_decl));
1507 DECL_SIZE (new_decl) = size;
1508
1509 size = remap_decl (DECL_SIZE_UNIT (decl), &ctx->cb);
1510 if (size == error_mark_node)
1511 size = TYPE_SIZE_UNIT (TREE_TYPE (new_decl));
1512 DECL_SIZE_UNIT (new_decl) = size;
1513 }
1514}
1515
1516/* The callback for remap_decl. Search all containing contexts for a
1517 mapping of the variable; this avoids having to duplicate the splay
1518 tree ahead of time. We know a mapping doesn't already exist in the
1519 given context. Create new mappings to implement default semantics. */
1520
1521static tree
1522omp_copy_decl (tree var, copy_body_data *cb)
1523{
1524 omp_context *ctx = (omp_context *) cb;
1525 tree new_var;
1526
1e8e9920 1527 if (TREE_CODE (var) == LABEL_DECL)
1528 {
e60a6f7b 1529 new_var = create_artificial_label (DECL_SOURCE_LOCATION (var));
773c5ba7 1530 DECL_CONTEXT (new_var) = current_function_decl;
1e8e9920 1531 insert_decl_map (&ctx->cb, var, new_var);
1532 return new_var;
1533 }
1534
fd6481cf 1535 while (!is_taskreg_ctx (ctx))
1e8e9920 1536 {
1537 ctx = ctx->outer;
1538 if (ctx == NULL)
1539 return var;
1540 new_var = maybe_lookup_decl (var, ctx);
1541 if (new_var)
1542 return new_var;
1543 }
1544
f49d7bb5 1545 if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn)
1546 return var;
1547
1e8e9920 1548 return error_mark_node;
1549}
1550
773c5ba7 1551
773c5ba7 1552/* Debugging dumps for parallel regions. */
1553void dump_omp_region (FILE *, struct omp_region *, int);
1554void debug_omp_region (struct omp_region *);
1555void debug_all_omp_regions (void);
1556
1557/* Dump the parallel region tree rooted at REGION. */
1558
1559void
1560dump_omp_region (FILE *file, struct omp_region *region, int indent)
1561{
61e47ac8 1562 fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index,
75a70cf9 1563 gimple_code_name[region->type]);
773c5ba7 1564
1565 if (region->inner)
1566 dump_omp_region (file, region->inner, indent + 4);
1567
61e47ac8 1568 if (region->cont)
1569 {
75a70cf9 1570 fprintf (file, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent, "",
61e47ac8 1571 region->cont->index);
1572 }
48e1416a 1573
773c5ba7 1574 if (region->exit)
75a70cf9 1575 fprintf (file, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent, "",
61e47ac8 1576 region->exit->index);
773c5ba7 1577 else
61e47ac8 1578 fprintf (file, "%*s[no exit marker]\n", indent, "");
773c5ba7 1579
1580 if (region->next)
61e47ac8 1581 dump_omp_region (file, region->next, indent);
773c5ba7 1582}
1583
4b987fac 1584DEBUG_FUNCTION void
773c5ba7 1585debug_omp_region (struct omp_region *region)
1586{
1587 dump_omp_region (stderr, region, 0);
1588}
1589
4b987fac 1590DEBUG_FUNCTION void
773c5ba7 1591debug_all_omp_regions (void)
1592{
1593 dump_omp_region (stderr, root_omp_region, 0);
1594}
1595
1596
1597/* Create a new parallel region starting at STMT inside region PARENT. */
1598
7740abd8 1599static struct omp_region *
75a70cf9 1600new_omp_region (basic_block bb, enum gimple_code type,
1601 struct omp_region *parent)
773c5ba7 1602{
4077bf7a 1603 struct omp_region *region = XCNEW (struct omp_region);
773c5ba7 1604
1605 region->outer = parent;
61e47ac8 1606 region->entry = bb;
1607 region->type = type;
773c5ba7 1608
1609 if (parent)
1610 {
1611 /* This is a nested region. Add it to the list of inner
1612 regions in PARENT. */
1613 region->next = parent->inner;
1614 parent->inner = region;
1615 }
61e47ac8 1616 else
773c5ba7 1617 {
1618 /* This is a toplevel region. Add it to the list of toplevel
1619 regions in ROOT_OMP_REGION. */
1620 region->next = root_omp_region;
1621 root_omp_region = region;
1622 }
61e47ac8 1623
1624 return region;
1625}
1626
1627/* Release the memory associated with the region tree rooted at REGION. */
1628
1629static void
1630free_omp_region_1 (struct omp_region *region)
1631{
1632 struct omp_region *i, *n;
1633
1634 for (i = region->inner; i ; i = n)
773c5ba7 1635 {
61e47ac8 1636 n = i->next;
1637 free_omp_region_1 (i);
773c5ba7 1638 }
1639
61e47ac8 1640 free (region);
1641}
773c5ba7 1642
61e47ac8 1643/* Release the memory for the entire omp region tree. */
1644
1645void
1646free_omp_regions (void)
1647{
1648 struct omp_region *r, *n;
1649 for (r = root_omp_region; r ; r = n)
1650 {
1651 n = r->next;
1652 free_omp_region_1 (r);
1653 }
1654 root_omp_region = NULL;
773c5ba7 1655}
1656
1657
1e8e9920 1658/* Create a new context, with OUTER_CTX being the surrounding context. */
1659
1660static omp_context *
42acab1c 1661new_omp_context (gimple *stmt, omp_context *outer_ctx)
1e8e9920 1662{
1663 omp_context *ctx = XCNEW (omp_context);
1664
1665 splay_tree_insert (all_contexts, (splay_tree_key) stmt,
1666 (splay_tree_value) ctx);
1667 ctx->stmt = stmt;
1668
1669 if (outer_ctx)
1670 {
1671 ctx->outer = outer_ctx;
1672 ctx->cb = outer_ctx->cb;
1673 ctx->cb.block = NULL;
1674 ctx->depth = outer_ctx->depth + 1;
1675 }
1676 else
1677 {
1678 ctx->cb.src_fn = current_function_decl;
1679 ctx->cb.dst_fn = current_function_decl;
415d1b9a 1680 ctx->cb.src_node = cgraph_node::get (current_function_decl);
53f79206 1681 gcc_checking_assert (ctx->cb.src_node);
1e8e9920 1682 ctx->cb.dst_node = ctx->cb.src_node;
1683 ctx->cb.src_cfun = cfun;
1684 ctx->cb.copy_decl = omp_copy_decl;
e38def9c 1685 ctx->cb.eh_lp_nr = 0;
1e8e9920 1686 ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
1687 ctx->depth = 1;
1688 }
1689
06ecf488 1690 ctx->cb.decl_map = new hash_map<tree, tree>;
1e8e9920 1691
1692 return ctx;
1693}
1694
75a70cf9 1695static gimple_seq maybe_catch_exception (gimple_seq);
f6430caa 1696
1697/* Finalize task copyfn. */
1698
1699static void
1a91d914 1700finalize_task_copyfn (gomp_task *task_stmt)
f6430caa 1701{
1702 struct function *child_cfun;
9078126c 1703 tree child_fn;
e3a19533 1704 gimple_seq seq = NULL, new_seq;
1a91d914 1705 gbind *bind;
f6430caa 1706
75a70cf9 1707 child_fn = gimple_omp_task_copy_fn (task_stmt);
f6430caa 1708 if (child_fn == NULL_TREE)
1709 return;
1710
1711 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
82b40354 1712 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
f6430caa 1713
f6430caa 1714 push_cfun (child_cfun);
7e3aae05 1715 bind = gimplify_body (child_fn, false);
75a70cf9 1716 gimple_seq_add_stmt (&seq, bind);
1717 new_seq = maybe_catch_exception (seq);
1718 if (new_seq != seq)
1719 {
1720 bind = gimple_build_bind (NULL, new_seq, NULL);
e3a19533 1721 seq = NULL;
75a70cf9 1722 gimple_seq_add_stmt (&seq, bind);
1723 }
1724 gimple_set_body (child_fn, seq);
f6430caa 1725 pop_cfun ();
f6430caa 1726
82b40354 1727 /* Inform the callgraph about the new function. */
47300487 1728 cgraph_node *node = cgraph_node::get_create (child_fn);
1729 node->parallelized_function = 1;
415d1b9a 1730 cgraph_node::add_new_function (child_fn, false);
f6430caa 1731}
1732
1e8e9920 1733/* Destroy a omp_context data structures. Called through the splay tree
1734 value delete callback. */
1735
1736static void
1737delete_omp_context (splay_tree_value value)
1738{
1739 omp_context *ctx = (omp_context *) value;
1740
06ecf488 1741 delete ctx->cb.decl_map;
1e8e9920 1742
1743 if (ctx->field_map)
1744 splay_tree_delete (ctx->field_map);
fd6481cf 1745 if (ctx->sfield_map)
1746 splay_tree_delete (ctx->sfield_map);
1e8e9920 1747
1748 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
1749 it produces corrupt debug information. */
1750 if (ctx->record_type)
1751 {
1752 tree t;
1767a056 1753 for (t = TYPE_FIELDS (ctx->record_type); t ; t = DECL_CHAIN (t))
1e8e9920 1754 DECL_ABSTRACT_ORIGIN (t) = NULL;
1755 }
fd6481cf 1756 if (ctx->srecord_type)
1757 {
1758 tree t;
1767a056 1759 for (t = TYPE_FIELDS (ctx->srecord_type); t ; t = DECL_CHAIN (t))
fd6481cf 1760 DECL_ABSTRACT_ORIGIN (t) = NULL;
1761 }
1e8e9920 1762
f6430caa 1763 if (is_task_ctx (ctx))
1a91d914 1764 finalize_task_copyfn (as_a <gomp_task *> (ctx->stmt));
f6430caa 1765
1e8e9920 1766 XDELETE (ctx);
1767}
1768
1769/* Fix up RECEIVER_DECL with a type that has been remapped to the child
1770 context. */
1771
1772static void
1773fixup_child_record_type (omp_context *ctx)
1774{
1775 tree f, type = ctx->record_type;
1776
1777 /* ??? It isn't sufficient to just call remap_type here, because
1778 variably_modified_type_p doesn't work the way we expect for
1779 record types. Testing each field for whether it needs remapping
1780 and creating a new record by hand works, however. */
1767a056 1781 for (f = TYPE_FIELDS (type); f ; f = DECL_CHAIN (f))
1e8e9920 1782 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
1783 break;
1784 if (f)
1785 {
1786 tree name, new_fields = NULL;
1787
1788 type = lang_hooks.types.make_type (RECORD_TYPE);
1789 name = DECL_NAME (TYPE_NAME (ctx->record_type));
e60a6f7b 1790 name = build_decl (DECL_SOURCE_LOCATION (ctx->receiver_decl),
1791 TYPE_DECL, name, type);
1e8e9920 1792 TYPE_NAME (type) = name;
1793
1767a056 1794 for (f = TYPE_FIELDS (ctx->record_type); f ; f = DECL_CHAIN (f))
1e8e9920 1795 {
1796 tree new_f = copy_node (f);
1797 DECL_CONTEXT (new_f) = type;
1798 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
1767a056 1799 DECL_CHAIN (new_f) = new_fields;
75a70cf9 1800 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &ctx->cb, NULL);
1801 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r,
1802 &ctx->cb, NULL);
1803 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
1804 &ctx->cb, NULL);
1e8e9920 1805 new_fields = new_f;
1806
1807 /* Arrange to be able to look up the receiver field
1808 given the sender field. */
1809 splay_tree_insert (ctx->field_map, (splay_tree_key) f,
1810 (splay_tree_value) new_f);
1811 }
1812 TYPE_FIELDS (type) = nreverse (new_fields);
1813 layout_type (type);
1814 }
1815
43895be5 1816 /* In a target region we never modify any of the pointers in *.omp_data_i,
1817 so attempt to help the optimizers. */
1818 if (is_gimple_omp_offloaded (ctx->stmt))
1819 type = build_qualified_type (type, TYPE_QUAL_CONST);
1820
5455b100 1821 TREE_TYPE (ctx->receiver_decl)
1822 = build_qualified_type (build_reference_type (type), TYPE_QUAL_RESTRICT);
1e8e9920 1823}
1824
1825/* Instantiate decls as necessary in CTX to satisfy the data sharing
12dc9a16 1826 specified by CLAUSES. If BASE_POINTERS_RESTRICT, install var field with
1827 restrict. */
1e8e9920 1828
1829static void
12dc9a16 1830scan_sharing_clauses (tree clauses, omp_context *ctx,
1831 bool base_pointers_restrict = false)
1e8e9920 1832{
1833 tree c, decl;
1834 bool scan_array_reductions = false;
1835
1836 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1837 {
1838 bool by_ref;
1839
55d6e7cd 1840 switch (OMP_CLAUSE_CODE (c))
1e8e9920 1841 {
1842 case OMP_CLAUSE_PRIVATE:
1843 decl = OMP_CLAUSE_DECL (c);
fd6481cf 1844 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
1845 goto do_private;
1846 else if (!is_variable_sized (decl))
1e8e9920 1847 install_var_local (decl, ctx);
1848 break;
1849
1850 case OMP_CLAUSE_SHARED:
5fddcf34 1851 decl = OMP_CLAUSE_DECL (c);
bc7bff74 1852 /* Ignore shared directives in teams construct. */
1853 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
5fddcf34 1854 {
1855 /* Global variables don't need to be copied,
1856 the receiver side will use them directly. */
1857 tree odecl = maybe_lookup_decl_in_outer_ctx (decl, ctx);
1858 if (is_global_var (odecl))
1859 break;
1860 insert_decl_map (&ctx->cb, decl, odecl);
1861 break;
1862 }
fd6481cf 1863 gcc_assert (is_taskreg_ctx (ctx));
e7327393 1864 gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl))
1865 || !is_variable_sized (decl));
f49d7bb5 1866 /* Global variables don't need to be copied,
1867 the receiver side will use them directly. */
1868 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1869 break;
43895be5 1870 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
98588013 1871 {
1872 use_pointer_for_field (decl, ctx);
1873 break;
1874 }
1875 by_ref = use_pointer_for_field (decl, NULL);
1876 if ((! TREE_READONLY (decl) && !OMP_CLAUSE_SHARED_READONLY (c))
1e8e9920 1877 || TREE_ADDRESSABLE (decl)
1878 || by_ref
1879 || is_reference (decl))
1880 {
98588013 1881 by_ref = use_pointer_for_field (decl, ctx);
fd6481cf 1882 install_var_field (decl, by_ref, 3, ctx);
1e8e9920 1883 install_var_local (decl, ctx);
1884 break;
1885 }
1886 /* We don't need to copy const scalar vars back. */
55d6e7cd 1887 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
1e8e9920 1888 goto do_private;
1889
43895be5 1890 case OMP_CLAUSE_REDUCTION:
1891 decl = OMP_CLAUSE_DECL (c);
1892 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1893 && TREE_CODE (decl) == MEM_REF)
1894 {
1895 tree t = TREE_OPERAND (decl, 0);
9561765e 1896 if (TREE_CODE (t) == POINTER_PLUS_EXPR)
1897 t = TREE_OPERAND (t, 0);
43895be5 1898 if (TREE_CODE (t) == INDIRECT_REF
1899 || TREE_CODE (t) == ADDR_EXPR)
1900 t = TREE_OPERAND (t, 0);
1901 install_var_local (t, ctx);
1902 if (is_taskreg_ctx (ctx)
1903 && !is_global_var (maybe_lookup_decl_in_outer_ctx (t, ctx))
1904 && !is_variable_sized (t))
1905 {
1906 by_ref = use_pointer_for_field (t, ctx);
1907 install_var_field (t, by_ref, 3, ctx);
1908 }
1909 break;
1910 }
1911 goto do_private;
1912
1e8e9920 1913 case OMP_CLAUSE_LASTPRIVATE:
1914 /* Let the corresponding firstprivate clause create
1915 the variable. */
1916 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1917 break;
1918 /* FALLTHRU */
1919
1920 case OMP_CLAUSE_FIRSTPRIVATE:
3d483a94 1921 case OMP_CLAUSE_LINEAR:
1e8e9920 1922 decl = OMP_CLAUSE_DECL (c);
1923 do_private:
43895be5 1924 if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
1925 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IS_DEVICE_PTR)
1926 && is_gimple_omp_offloaded (ctx->stmt))
1927 {
1928 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
1929 install_var_field (decl, !is_reference (decl), 3, ctx);
1930 else if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1931 install_var_field (decl, true, 3, ctx);
1932 else
1933 install_var_field (decl, false, 3, ctx);
1934 }
1e8e9920 1935 if (is_variable_sized (decl))
1e8e9920 1936 {
fd6481cf 1937 if (is_task_ctx (ctx))
1938 install_var_field (decl, false, 1, ctx);
1939 break;
1940 }
1941 else if (is_taskreg_ctx (ctx))
1942 {
1943 bool global
1944 = is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx));
e8a588af 1945 by_ref = use_pointer_for_field (decl, NULL);
fd6481cf 1946
1947 if (is_task_ctx (ctx)
1948 && (global || by_ref || is_reference (decl)))
1949 {
1950 install_var_field (decl, false, 1, ctx);
1951 if (!global)
1952 install_var_field (decl, by_ref, 2, ctx);
1953 }
1954 else if (!global)
1955 install_var_field (decl, by_ref, 3, ctx);
1e8e9920 1956 }
1957 install_var_local (decl, ctx);
1958 break;
1959
43895be5 1960 case OMP_CLAUSE_USE_DEVICE_PTR:
1961 decl = OMP_CLAUSE_DECL (c);
1962 if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1963 install_var_field (decl, true, 3, ctx);
1964 else
1965 install_var_field (decl, false, 3, ctx);
1966 if (DECL_SIZE (decl)
1967 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1968 {
1969 tree decl2 = DECL_VALUE_EXPR (decl);
1970 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1971 decl2 = TREE_OPERAND (decl2, 0);
1972 gcc_assert (DECL_P (decl2));
1973 install_var_local (decl2, ctx);
1974 }
1975 install_var_local (decl, ctx);
1976 break;
1977
1978 case OMP_CLAUSE_IS_DEVICE_PTR:
1979 decl = OMP_CLAUSE_DECL (c);
1980 goto do_private;
1981
bc7bff74 1982 case OMP_CLAUSE__LOOPTEMP_:
43895be5 1983 gcc_assert (is_taskreg_ctx (ctx));
bc7bff74 1984 decl = OMP_CLAUSE_DECL (c);
1985 install_var_field (decl, false, 3, ctx);
1986 install_var_local (decl, ctx);
1987 break;
1988
1e8e9920 1989 case OMP_CLAUSE_COPYPRIVATE:
1e8e9920 1990 case OMP_CLAUSE_COPYIN:
1991 decl = OMP_CLAUSE_DECL (c);
e8a588af 1992 by_ref = use_pointer_for_field (decl, NULL);
fd6481cf 1993 install_var_field (decl, by_ref, 3, ctx);
1e8e9920 1994 break;
1995
1996 case OMP_CLAUSE_DEFAULT:
1997 ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
1998 break;
1999
2169f33b 2000 case OMP_CLAUSE_FINAL:
1e8e9920 2001 case OMP_CLAUSE_IF:
2002 case OMP_CLAUSE_NUM_THREADS:
bc7bff74 2003 case OMP_CLAUSE_NUM_TEAMS:
2004 case OMP_CLAUSE_THREAD_LIMIT:
2005 case OMP_CLAUSE_DEVICE:
1e8e9920 2006 case OMP_CLAUSE_SCHEDULE:
bc7bff74 2007 case OMP_CLAUSE_DIST_SCHEDULE:
2008 case OMP_CLAUSE_DEPEND:
43895be5 2009 case OMP_CLAUSE_PRIORITY:
2010 case OMP_CLAUSE_GRAINSIZE:
2011 case OMP_CLAUSE_NUM_TASKS:
40750995 2012 case OMP_CLAUSE__CILK_FOR_COUNT_:
ca4c3545 2013 case OMP_CLAUSE_NUM_GANGS:
2014 case OMP_CLAUSE_NUM_WORKERS:
2015 case OMP_CLAUSE_VECTOR_LENGTH:
1e8e9920 2016 if (ctx->outer)
75a70cf9 2017 scan_omp_op (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
1e8e9920 2018 break;
2019
bc7bff74 2020 case OMP_CLAUSE_TO:
2021 case OMP_CLAUSE_FROM:
2022 case OMP_CLAUSE_MAP:
2023 if (ctx->outer)
2024 scan_omp_op (&OMP_CLAUSE_SIZE (c), ctx->outer);
2025 decl = OMP_CLAUSE_DECL (c);
2026 /* Global variables with "omp declare target" attribute
2027 don't need to be copied, the receiver side will use them
c0998828 2028 directly. However, global variables with "omp declare target link"
2029 attribute need to be copied. */
bc7bff74 2030 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
2031 && DECL_P (decl)
9561765e 2032 && ((OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_FIRSTPRIVATE_POINTER
2033 && (OMP_CLAUSE_MAP_KIND (c)
2034 != GOMP_MAP_FIRSTPRIVATE_REFERENCE))
43895be5 2035 || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
bc7bff74 2036 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
c0998828 2037 && varpool_node::get_create (decl)->offloadable
2038 && !lookup_attribute ("omp declare target link",
2039 DECL_ATTRIBUTES (decl)))
bc7bff74 2040 break;
2041 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
ca4c3545 2042 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER)
bc7bff74 2043 {
ca4c3545 2044 /* Ignore GOMP_MAP_POINTER kind for arrays in regions that are
2045 not offloaded; there is nothing to map for those. */
2046 if (!is_gimple_omp_offloaded (ctx->stmt)
c1a114c2 2047 && !POINTER_TYPE_P (TREE_TYPE (decl))
2048 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
bc7bff74 2049 break;
2050 }
43895be5 2051 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
9561765e 2052 && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
2053 || (OMP_CLAUSE_MAP_KIND (c)
2054 == GOMP_MAP_FIRSTPRIVATE_REFERENCE)))
43895be5 2055 {
2056 if (TREE_CODE (decl) == COMPONENT_REF
2057 || (TREE_CODE (decl) == INDIRECT_REF
2058 && TREE_CODE (TREE_OPERAND (decl, 0)) == COMPONENT_REF
2059 && (TREE_CODE (TREE_TYPE (TREE_OPERAND (decl, 0)))
2060 == REFERENCE_TYPE)))
2061 break;
2062 if (DECL_SIZE (decl)
2063 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
2064 {
2065 tree decl2 = DECL_VALUE_EXPR (decl);
2066 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2067 decl2 = TREE_OPERAND (decl2, 0);
2068 gcc_assert (DECL_P (decl2));
2069 install_var_local (decl2, ctx);
2070 }
2071 install_var_local (decl, ctx);
2072 break;
2073 }
bc7bff74 2074 if (DECL_P (decl))
2075 {
2076 if (DECL_SIZE (decl)
2077 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
2078 {
2079 tree decl2 = DECL_VALUE_EXPR (decl);
2080 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2081 decl2 = TREE_OPERAND (decl2, 0);
2082 gcc_assert (DECL_P (decl2));
9561765e 2083 install_var_field (decl2, true, 3, ctx);
bc7bff74 2084 install_var_local (decl2, ctx);
2085 install_var_local (decl, ctx);
2086 }
2087 else
2088 {
2089 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
ca4c3545 2090 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
bc7bff74 2091 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
2092 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
2093 install_var_field (decl, true, 7, ctx);
2094 else
12dc9a16 2095 install_var_field (decl, true, 3, ctx,
2096 base_pointers_restrict);
ca4c3545 2097 if (is_gimple_omp_offloaded (ctx->stmt))
bc7bff74 2098 install_var_local (decl, ctx);
2099 }
2100 }
2101 else
2102 {
2103 tree base = get_base_address (decl);
2104 tree nc = OMP_CLAUSE_CHAIN (c);
2105 if (DECL_P (base)
2106 && nc != NULL_TREE
2107 && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
2108 && OMP_CLAUSE_DECL (nc) == base
ca4c3545 2109 && OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_POINTER
bc7bff74 2110 && integer_zerop (OMP_CLAUSE_SIZE (nc)))
2111 {
2112 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c) = 1;
2113 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (nc) = 1;
2114 }
2115 else
2116 {
691447ab 2117 if (ctx->outer)
2118 {
2119 scan_omp_op (&OMP_CLAUSE_DECL (c), ctx->outer);
2120 decl = OMP_CLAUSE_DECL (c);
2121 }
bc7bff74 2122 gcc_assert (!splay_tree_lookup (ctx->field_map,
2123 (splay_tree_key) decl));
2124 tree field
2125 = build_decl (OMP_CLAUSE_LOCATION (c),
2126 FIELD_DECL, NULL_TREE, ptr_type_node);
2127 DECL_ALIGN (field) = TYPE_ALIGN (ptr_type_node);
2128 insert_field_into_struct (ctx->record_type, field);
2129 splay_tree_insert (ctx->field_map, (splay_tree_key) decl,
2130 (splay_tree_value) field);
2131 }
2132 }
2133 break;
2134
1e8e9920 2135 case OMP_CLAUSE_NOWAIT:
2136 case OMP_CLAUSE_ORDERED:
fd6481cf 2137 case OMP_CLAUSE_COLLAPSE:
2138 case OMP_CLAUSE_UNTIED:
2169f33b 2139 case OMP_CLAUSE_MERGEABLE:
bc7bff74 2140 case OMP_CLAUSE_PROC_BIND:
3d483a94 2141 case OMP_CLAUSE_SAFELEN:
43895be5 2142 case OMP_CLAUSE_SIMDLEN:
2143 case OMP_CLAUSE_THREADS:
2144 case OMP_CLAUSE_SIMD:
2145 case OMP_CLAUSE_NOGROUP:
2146 case OMP_CLAUSE_DEFAULTMAP:
ca4c3545 2147 case OMP_CLAUSE_ASYNC:
2148 case OMP_CLAUSE_WAIT:
2149 case OMP_CLAUSE_GANG:
2150 case OMP_CLAUSE_WORKER:
2151 case OMP_CLAUSE_VECTOR:
ef014f95 2152 case OMP_CLAUSE_TILE:
f4f5b4b4 2153 case OMP_CLAUSE_INDEPENDENT:
2154 case OMP_CLAUSE_AUTO:
2155 case OMP_CLAUSE_SEQ:
1e8e9920 2156 break;
2157
bc7bff74 2158 case OMP_CLAUSE_ALIGNED:
2159 decl = OMP_CLAUSE_DECL (c);
2160 if (is_global_var (decl)
2161 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
2162 install_var_local (decl, ctx);
2163 break;
2164
ca4c3545 2165 case OMP_CLAUSE_DEVICE_RESIDENT:
ca4c3545 2166 case OMP_CLAUSE__CACHE_:
ca4c3545 2167 sorry ("Clause not supported yet");
2168 break;
2169
1e8e9920 2170 default:
2171 gcc_unreachable ();
2172 }
2173 }
2174
2175 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2176 {
55d6e7cd 2177 switch (OMP_CLAUSE_CODE (c))
1e8e9920 2178 {
2179 case OMP_CLAUSE_LASTPRIVATE:
2180 /* Let the corresponding firstprivate clause create
2181 the variable. */
75a70cf9 2182 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
fd6481cf 2183 scan_array_reductions = true;
1e8e9920 2184 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
2185 break;
2186 /* FALLTHRU */
2187
1e8e9920 2188 case OMP_CLAUSE_FIRSTPRIVATE:
ca4c3545 2189 case OMP_CLAUSE_PRIVATE:
3d483a94 2190 case OMP_CLAUSE_LINEAR:
43895be5 2191 case OMP_CLAUSE_IS_DEVICE_PTR:
1e8e9920 2192 decl = OMP_CLAUSE_DECL (c);
2193 if (is_variable_sized (decl))
43895be5 2194 {
2195 if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
2196 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IS_DEVICE_PTR)
2197 && is_gimple_omp_offloaded (ctx->stmt))
2198 {
2199 tree decl2 = DECL_VALUE_EXPR (decl);
2200 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2201 decl2 = TREE_OPERAND (decl2, 0);
2202 gcc_assert (DECL_P (decl2));
2203 install_var_local (decl2, ctx);
2204 fixup_remapped_decl (decl2, ctx, false);
2205 }
2206 install_var_local (decl, ctx);
2207 }
1e8e9920 2208 fixup_remapped_decl (decl, ctx,
55d6e7cd 2209 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
1e8e9920 2210 && OMP_CLAUSE_PRIVATE_DEBUG (c));
43895be5 2211 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
2212 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
1e8e9920 2213 scan_array_reductions = true;
43895be5 2214 break;
2215
2216 case OMP_CLAUSE_REDUCTION:
2217 decl = OMP_CLAUSE_DECL (c);
2218 if (TREE_CODE (decl) != MEM_REF)
2219 {
2220 if (is_variable_sized (decl))
2221 install_var_local (decl, ctx);
2222 fixup_remapped_decl (decl, ctx, false);
2223 }
2224 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2b536a17 2225 scan_array_reductions = true;
1e8e9920 2226 break;
2227
2228 case OMP_CLAUSE_SHARED:
bc7bff74 2229 /* Ignore shared directives in teams construct. */
2230 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
2231 break;
1e8e9920 2232 decl = OMP_CLAUSE_DECL (c);
43895be5 2233 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
2234 break;
2235 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
2236 {
2237 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl,
2238 ctx->outer)))
2239 break;
2240 bool by_ref = use_pointer_for_field (decl, ctx);
2241 install_var_field (decl, by_ref, 11, ctx);
2242 break;
2243 }
2244 fixup_remapped_decl (decl, ctx, false);
1e8e9920 2245 break;
2246
bc7bff74 2247 case OMP_CLAUSE_MAP:
ca4c3545 2248 if (!is_gimple_omp_offloaded (ctx->stmt))
bc7bff74 2249 break;
2250 decl = OMP_CLAUSE_DECL (c);
2251 if (DECL_P (decl)
9561765e 2252 && ((OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_FIRSTPRIVATE_POINTER
2253 && (OMP_CLAUSE_MAP_KIND (c)
2254 != GOMP_MAP_FIRSTPRIVATE_REFERENCE))
43895be5 2255 || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
bc7bff74 2256 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
b0c5e347 2257 && varpool_node::get_create (decl)->offloadable)
bc7bff74 2258 break;
2259 if (DECL_P (decl))
2260 {
43895be5 2261 if ((OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
2262 || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER)
bc7bff74 2263 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
2264 && !COMPLETE_TYPE_P (TREE_TYPE (decl)))
2265 {
2266 tree new_decl = lookup_decl (decl, ctx);
2267 TREE_TYPE (new_decl)
2268 = remap_type (TREE_TYPE (decl), &ctx->cb);
2269 }
2270 else if (DECL_SIZE (decl)
2271 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
2272 {
2273 tree decl2 = DECL_VALUE_EXPR (decl);
2274 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2275 decl2 = TREE_OPERAND (decl2, 0);
2276 gcc_assert (DECL_P (decl2));
2277 fixup_remapped_decl (decl2, ctx, false);
2278 fixup_remapped_decl (decl, ctx, true);
2279 }
2280 else
2281 fixup_remapped_decl (decl, ctx, false);
2282 }
2283 break;
2284
1e8e9920 2285 case OMP_CLAUSE_COPYPRIVATE:
2286 case OMP_CLAUSE_COPYIN:
2287 case OMP_CLAUSE_DEFAULT:
2288 case OMP_CLAUSE_IF:
2289 case OMP_CLAUSE_NUM_THREADS:
bc7bff74 2290 case OMP_CLAUSE_NUM_TEAMS:
2291 case OMP_CLAUSE_THREAD_LIMIT:
2292 case OMP_CLAUSE_DEVICE:
1e8e9920 2293 case OMP_CLAUSE_SCHEDULE:
bc7bff74 2294 case OMP_CLAUSE_DIST_SCHEDULE:
1e8e9920 2295 case OMP_CLAUSE_NOWAIT:
2296 case OMP_CLAUSE_ORDERED:
fd6481cf 2297 case OMP_CLAUSE_COLLAPSE:
2298 case OMP_CLAUSE_UNTIED:
2169f33b 2299 case OMP_CLAUSE_FINAL:
2300 case OMP_CLAUSE_MERGEABLE:
bc7bff74 2301 case OMP_CLAUSE_PROC_BIND:
3d483a94 2302 case OMP_CLAUSE_SAFELEN:
43895be5 2303 case OMP_CLAUSE_SIMDLEN:
bc7bff74 2304 case OMP_CLAUSE_ALIGNED:
2305 case OMP_CLAUSE_DEPEND:
2306 case OMP_CLAUSE__LOOPTEMP_:
2307 case OMP_CLAUSE_TO:
2308 case OMP_CLAUSE_FROM:
43895be5 2309 case OMP_CLAUSE_PRIORITY:
2310 case OMP_CLAUSE_GRAINSIZE:
2311 case OMP_CLAUSE_NUM_TASKS:
2312 case OMP_CLAUSE_THREADS:
2313 case OMP_CLAUSE_SIMD:
2314 case OMP_CLAUSE_NOGROUP:
2315 case OMP_CLAUSE_DEFAULTMAP:
2316 case OMP_CLAUSE_USE_DEVICE_PTR:
40750995 2317 case OMP_CLAUSE__CILK_FOR_COUNT_:
ca4c3545 2318 case OMP_CLAUSE_ASYNC:
2319 case OMP_CLAUSE_WAIT:
2320 case OMP_CLAUSE_NUM_GANGS:
2321 case OMP_CLAUSE_NUM_WORKERS:
2322 case OMP_CLAUSE_VECTOR_LENGTH:
2323 case OMP_CLAUSE_GANG:
2324 case OMP_CLAUSE_WORKER:
2325 case OMP_CLAUSE_VECTOR:
ef014f95 2326 case OMP_CLAUSE_TILE:
f4f5b4b4 2327 case OMP_CLAUSE_INDEPENDENT:
2328 case OMP_CLAUSE_AUTO:
2329 case OMP_CLAUSE_SEQ:
ca4c3545 2330 break;
2331
2332 case OMP_CLAUSE_DEVICE_RESIDENT:
ca4c3545 2333 case OMP_CLAUSE__CACHE_:
ca4c3545 2334 sorry ("Clause not supported yet");
1e8e9920 2335 break;
2336
2337 default:
2338 gcc_unreachable ();
2339 }
2340 }
2341
ca4c3545 2342 gcc_checking_assert (!scan_array_reductions
2343 || !is_gimple_omp_oacc (ctx->stmt));
1e8e9920 2344 if (scan_array_reductions)
2345 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
55d6e7cd 2346 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1e8e9920 2347 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2348 {
ab129075 2349 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
2350 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
1e8e9920 2351 }
fd6481cf 2352 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
75a70cf9 2353 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
ab129075 2354 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
2b536a17 2355 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
2356 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
2357 scan_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
1e8e9920 2358}
2359
40750995 2360/* Create a new name for omp child function. Returns an identifier. If
2361 IS_CILK_FOR is true then the suffix for the child function is
2362 "_cilk_for_fn." */
1e8e9920 2363
1e8e9920 2364static tree
40750995 2365create_omp_child_function_name (bool task_copy, bool is_cilk_for)
1e8e9920 2366{
40750995 2367 if (is_cilk_for)
2368 return clone_function_name (current_function_decl, "_cilk_for_fn");
2369 return clone_function_name (current_function_decl,
2370 task_copy ? "_omp_cpyfn" : "_omp_fn");
2371}
2372
2373/* Returns the type of the induction variable for the child function for
2374 _Cilk_for and the types for _high and _low variables based on TYPE. */
2375
2376static tree
2377cilk_for_check_loop_diff_type (tree type)
2378{
2379 if (TYPE_PRECISION (type) <= TYPE_PRECISION (uint32_type_node))
2380 {
2381 if (TYPE_UNSIGNED (type))
2382 return uint32_type_node;
2383 else
2384 return integer_type_node;
2385 }
2386 else
2387 {
2388 if (TYPE_UNSIGNED (type))
2389 return uint64_type_node;
2390 else
2391 return long_long_integer_type_node;
2392 }
1e8e9920 2393}
2394
2395/* Build a decl for the omp child function. It'll not contain a body
2396 yet, just the bare decl. */
2397
2398static void
fd6481cf 2399create_omp_child_function (omp_context *ctx, bool task_copy)
1e8e9920 2400{
2401 tree decl, type, name, t;
2402
40750995 2403 tree cilk_for_count
2404 = (flag_cilkplus && gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2405 ? find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
2406 OMP_CLAUSE__CILK_FOR_COUNT_) : NULL_TREE;
2407 tree cilk_var_type = NULL_TREE;
2408
2409 name = create_omp_child_function_name (task_copy,
2410 cilk_for_count != NULL_TREE);
fd6481cf 2411 if (task_copy)
2412 type = build_function_type_list (void_type_node, ptr_type_node,
2413 ptr_type_node, NULL_TREE);
40750995 2414 else if (cilk_for_count)
2415 {
2416 type = TREE_TYPE (OMP_CLAUSE_OPERAND (cilk_for_count, 0));
2417 cilk_var_type = cilk_for_check_loop_diff_type (type);
2418 type = build_function_type_list (void_type_node, ptr_type_node,
2419 cilk_var_type, cilk_var_type, NULL_TREE);
2420 }
fd6481cf 2421 else
2422 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
1e8e9920 2423
40750995 2424 decl = build_decl (gimple_location (ctx->stmt), FUNCTION_DECL, name, type);
1e8e9920 2425
ca4c3545 2426 gcc_checking_assert (!is_gimple_omp_oacc (ctx->stmt)
2427 || !task_copy);
fd6481cf 2428 if (!task_copy)
2429 ctx->cb.dst_fn = decl;
2430 else
75a70cf9 2431 gimple_omp_task_set_copy_fn (ctx->stmt, decl);
1e8e9920 2432
2433 TREE_STATIC (decl) = 1;
2434 TREE_USED (decl) = 1;
2435 DECL_ARTIFICIAL (decl) = 1;
2436 DECL_IGNORED_P (decl) = 0;
2437 TREE_PUBLIC (decl) = 0;
2438 DECL_UNINLINABLE (decl) = 1;
2439 DECL_EXTERNAL (decl) = 0;
2440 DECL_CONTEXT (decl) = NULL_TREE;
773c5ba7 2441 DECL_INITIAL (decl) = make_node (BLOCK);
b0c5e347 2442 if (cgraph_node::get (current_function_decl)->offloadable)
2443 cgraph_node::get_create (decl)->offloadable = 1;
bc7bff74 2444 else
2445 {
2446 omp_context *octx;
2447 for (octx = ctx; octx; octx = octx->outer)
ca4c3545 2448 if (is_gimple_omp_offloaded (octx->stmt))
bc7bff74 2449 {
b0c5e347 2450 cgraph_node::get_create (decl)->offloadable = 1;
5f3001a9 2451 if (ENABLE_OFFLOADING)
2452 g->have_offload = true;
2453
bc7bff74 2454 break;
2455 }
2456 }
1e8e9920 2457
ec12b31a 2458 if (cgraph_node::get_create (decl)->offloadable
2459 && !lookup_attribute ("omp declare target",
2460 DECL_ATTRIBUTES (current_function_decl)))
2461 DECL_ATTRIBUTES (decl)
2462 = tree_cons (get_identifier ("omp target entrypoint"),
2463 NULL_TREE, DECL_ATTRIBUTES (decl));
2464
e60a6f7b 2465 t = build_decl (DECL_SOURCE_LOCATION (decl),
2466 RESULT_DECL, NULL_TREE, void_type_node);
1e8e9920 2467 DECL_ARTIFICIAL (t) = 1;
2468 DECL_IGNORED_P (t) = 1;
8e5b4ed6 2469 DECL_CONTEXT (t) = decl;
1e8e9920 2470 DECL_RESULT (decl) = t;
2471
40750995 2472 /* _Cilk_for's child function requires two extra parameters called
2473 __low and __high that are set the by Cilk runtime when it calls this
2474 function. */
2475 if (cilk_for_count)
2476 {
2477 t = build_decl (DECL_SOURCE_LOCATION (decl),
2478 PARM_DECL, get_identifier ("__high"), cilk_var_type);
2479 DECL_ARTIFICIAL (t) = 1;
2480 DECL_NAMELESS (t) = 1;
2481 DECL_ARG_TYPE (t) = ptr_type_node;
2482 DECL_CONTEXT (t) = current_function_decl;
2483 TREE_USED (t) = 1;
2484 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2485 DECL_ARGUMENTS (decl) = t;
2486
2487 t = build_decl (DECL_SOURCE_LOCATION (decl),
2488 PARM_DECL, get_identifier ("__low"), cilk_var_type);
2489 DECL_ARTIFICIAL (t) = 1;
2490 DECL_NAMELESS (t) = 1;
2491 DECL_ARG_TYPE (t) = ptr_type_node;
2492 DECL_CONTEXT (t) = current_function_decl;
2493 TREE_USED (t) = 1;
2494 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2495 DECL_ARGUMENTS (decl) = t;
2496 }
2497
2498 tree data_name = get_identifier (".omp_data_i");
2499 t = build_decl (DECL_SOURCE_LOCATION (decl), PARM_DECL, data_name,
2500 ptr_type_node);
1e8e9920 2501 DECL_ARTIFICIAL (t) = 1;
84bfaaeb 2502 DECL_NAMELESS (t) = 1;
1e8e9920 2503 DECL_ARG_TYPE (t) = ptr_type_node;
773c5ba7 2504 DECL_CONTEXT (t) = current_function_decl;
1e8e9920 2505 TREE_USED (t) = 1;
43895be5 2506 TREE_READONLY (t) = 1;
40750995 2507 if (cilk_for_count)
2508 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
1e8e9920 2509 DECL_ARGUMENTS (decl) = t;
fd6481cf 2510 if (!task_copy)
2511 ctx->receiver_decl = t;
2512 else
2513 {
e60a6f7b 2514 t = build_decl (DECL_SOURCE_LOCATION (decl),
2515 PARM_DECL, get_identifier (".omp_data_o"),
fd6481cf 2516 ptr_type_node);
2517 DECL_ARTIFICIAL (t) = 1;
84bfaaeb 2518 DECL_NAMELESS (t) = 1;
fd6481cf 2519 DECL_ARG_TYPE (t) = ptr_type_node;
2520 DECL_CONTEXT (t) = current_function_decl;
2521 TREE_USED (t) = 1;
86f2ad37 2522 TREE_ADDRESSABLE (t) = 1;
1767a056 2523 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
fd6481cf 2524 DECL_ARGUMENTS (decl) = t;
2525 }
1e8e9920 2526
48e1416a 2527 /* Allocate memory for the function structure. The call to
773c5ba7 2528 allocate_struct_function clobbers CFUN, so we need to restore
1e8e9920 2529 it afterward. */
87d4aa85 2530 push_struct_function (decl);
75a70cf9 2531 cfun->function_end_locus = gimple_location (ctx->stmt);
87d4aa85 2532 pop_cfun ();
1e8e9920 2533}
2534
bc7bff74 2535/* Callback for walk_gimple_seq. Check if combined parallel
2536 contains gimple_omp_for_combined_into_p OMP_FOR. */
2537
2538static tree
2539find_combined_for (gimple_stmt_iterator *gsi_p,
2540 bool *handled_ops_p,
2541 struct walk_stmt_info *wi)
2542{
42acab1c 2543 gimple *stmt = gsi_stmt (*gsi_p);
bc7bff74 2544
2545 *handled_ops_p = true;
2546 switch (gimple_code (stmt))
2547 {
2548 WALK_SUBSTMTS;
2549
2550 case GIMPLE_OMP_FOR:
2551 if (gimple_omp_for_combined_into_p (stmt)
43895be5 2552 && gimple_omp_for_kind (stmt)
2553 == *(const enum gf_mask *) (wi->info))
bc7bff74 2554 {
2555 wi->info = stmt;
2556 return integer_zero_node;
2557 }
2558 break;
2559 default:
2560 break;
2561 }
2562 return NULL;
2563}
2564
43895be5 2565/* Add _LOOPTEMP_ clauses on OpenMP parallel or task. */
2566
2567static void
2568add_taskreg_looptemp_clauses (enum gf_mask msk, gimple *stmt,
2569 omp_context *outer_ctx)
2570{
2571 struct walk_stmt_info wi;
2572
2573 memset (&wi, 0, sizeof (wi));
2574 wi.val_only = true;
2575 wi.info = (void *) &msk;
2576 walk_gimple_seq (gimple_omp_body (stmt), find_combined_for, NULL, &wi);
2577 if (wi.info != (void *) &msk)
2578 {
2579 gomp_for *for_stmt = as_a <gomp_for *> ((gimple *) wi.info);
2580 struct omp_for_data fd;
2581 extract_omp_for_data (for_stmt, &fd, NULL);
2582 /* We need two temporaries with fd.loop.v type (istart/iend)
2583 and then (fd.collapse - 1) temporaries with the same
2584 type for count2 ... countN-1 vars if not constant. */
2585 size_t count = 2, i;
2586 tree type = fd.iter_type;
2587 if (fd.collapse > 1
2588 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
2589 {
2590 count += fd.collapse - 1;
9561765e 2591 /* If there are lastprivate clauses on the inner
43895be5 2592 GIMPLE_OMP_FOR, add one more temporaries for the total number
2593 of iterations (product of count1 ... countN-1). */
9561765e 2594 if (find_omp_clause (gimple_omp_for_clauses (for_stmt),
2595 OMP_CLAUSE_LASTPRIVATE))
2596 count++;
2597 else if (msk == GF_OMP_FOR_KIND_FOR
2598 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
2599 OMP_CLAUSE_LASTPRIVATE))
43895be5 2600 count++;
2601 }
2602 for (i = 0; i < count; i++)
2603 {
2604 tree temp = create_tmp_var (type);
2605 tree c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
2606 insert_decl_map (&outer_ctx->cb, temp, temp);
2607 OMP_CLAUSE_DECL (c) = temp;
2608 OMP_CLAUSE_CHAIN (c) = gimple_omp_taskreg_clauses (stmt);
2609 gimple_omp_taskreg_set_clauses (stmt, c);
2610 }
2611 }
2612}
2613
1e8e9920 2614/* Scan an OpenMP parallel directive. */
2615
2616static void
75a70cf9 2617scan_omp_parallel (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
1e8e9920 2618{
2619 omp_context *ctx;
2620 tree name;
1a91d914 2621 gomp_parallel *stmt = as_a <gomp_parallel *> (gsi_stmt (*gsi));
1e8e9920 2622
2623 /* Ignore parallel directives with empty bodies, unless there
2624 are copyin clauses. */
2625 if (optimize > 0
75a70cf9 2626 && empty_body_p (gimple_omp_body (stmt))
2627 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
2628 OMP_CLAUSE_COPYIN) == NULL)
1e8e9920 2629 {
75a70cf9 2630 gsi_replace (gsi, gimple_build_nop (), false);
1e8e9920 2631 return;
2632 }
2633
bc7bff74 2634 if (gimple_omp_parallel_combined_p (stmt))
43895be5 2635 add_taskreg_looptemp_clauses (GF_OMP_FOR_KIND_FOR, stmt, outer_ctx);
bc7bff74 2636
75a70cf9 2637 ctx = new_omp_context (stmt, outer_ctx);
37eaded9 2638 taskreg_contexts.safe_push (ctx);
fd6481cf 2639 if (taskreg_nesting_level > 1)
773c5ba7 2640 ctx->is_nested = true;
1e8e9920 2641 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1e8e9920 2642 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2643 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
1e8e9920 2644 name = create_tmp_var_name (".omp_data_s");
e60a6f7b 2645 name = build_decl (gimple_location (stmt),
2646 TYPE_DECL, name, ctx->record_type);
84bfaaeb 2647 DECL_ARTIFICIAL (name) = 1;
2648 DECL_NAMELESS (name) = 1;
1e8e9920 2649 TYPE_NAME (ctx->record_type) = name;
240131b5 2650 TYPE_ARTIFICIAL (ctx->record_type) = 1;
fd6481cf 2651 create_omp_child_function (ctx, false);
75a70cf9 2652 gimple_omp_parallel_set_child_fn (stmt, ctx->cb.dst_fn);
1e8e9920 2653
75a70cf9 2654 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt), ctx);
ab129075 2655 scan_omp (gimple_omp_body_ptr (stmt), ctx);
1e8e9920 2656
2657 if (TYPE_FIELDS (ctx->record_type) == NULL)
2658 ctx->record_type = ctx->receiver_decl = NULL;
1e8e9920 2659}
2660
fd6481cf 2661/* Scan an OpenMP task directive. */
2662
2663static void
75a70cf9 2664scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
fd6481cf 2665{
2666 omp_context *ctx;
75a70cf9 2667 tree name, t;
1a91d914 2668 gomp_task *stmt = as_a <gomp_task *> (gsi_stmt (*gsi));
fd6481cf 2669
2670 /* Ignore task directives with empty bodies. */
2671 if (optimize > 0
75a70cf9 2672 && empty_body_p (gimple_omp_body (stmt)))
fd6481cf 2673 {
75a70cf9 2674 gsi_replace (gsi, gimple_build_nop (), false);
fd6481cf 2675 return;
2676 }
2677
43895be5 2678 if (gimple_omp_task_taskloop_p (stmt))
2679 add_taskreg_looptemp_clauses (GF_OMP_FOR_KIND_TASKLOOP, stmt, outer_ctx);
2680
75a70cf9 2681 ctx = new_omp_context (stmt, outer_ctx);
37eaded9 2682 taskreg_contexts.safe_push (ctx);
fd6481cf 2683 if (taskreg_nesting_level > 1)
2684 ctx->is_nested = true;
2685 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2686 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2687 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2688 name = create_tmp_var_name (".omp_data_s");
e60a6f7b 2689 name = build_decl (gimple_location (stmt),
2690 TYPE_DECL, name, ctx->record_type);
84bfaaeb 2691 DECL_ARTIFICIAL (name) = 1;
2692 DECL_NAMELESS (name) = 1;
fd6481cf 2693 TYPE_NAME (ctx->record_type) = name;
240131b5 2694 TYPE_ARTIFICIAL (ctx->record_type) = 1;
fd6481cf 2695 create_omp_child_function (ctx, false);
75a70cf9 2696 gimple_omp_task_set_child_fn (stmt, ctx->cb.dst_fn);
fd6481cf 2697
75a70cf9 2698 scan_sharing_clauses (gimple_omp_task_clauses (stmt), ctx);
fd6481cf 2699
2700 if (ctx->srecord_type)
2701 {
2702 name = create_tmp_var_name (".omp_data_a");
e60a6f7b 2703 name = build_decl (gimple_location (stmt),
2704 TYPE_DECL, name, ctx->srecord_type);
84bfaaeb 2705 DECL_ARTIFICIAL (name) = 1;
2706 DECL_NAMELESS (name) = 1;
fd6481cf 2707 TYPE_NAME (ctx->srecord_type) = name;
240131b5 2708 TYPE_ARTIFICIAL (ctx->srecord_type) = 1;
fd6481cf 2709 create_omp_child_function (ctx, true);
2710 }
2711
ab129075 2712 scan_omp (gimple_omp_body_ptr (stmt), ctx);
fd6481cf 2713
2714 if (TYPE_FIELDS (ctx->record_type) == NULL)
2715 {
2716 ctx->record_type = ctx->receiver_decl = NULL;
75a70cf9 2717 t = build_int_cst (long_integer_type_node, 0);
2718 gimple_omp_task_set_arg_size (stmt, t);
2719 t = build_int_cst (long_integer_type_node, 1);
2720 gimple_omp_task_set_arg_align (stmt, t);
fd6481cf 2721 }
37eaded9 2722}
2723
2724
2725/* If any decls have been made addressable during scan_omp,
2726 adjust their fields if needed, and layout record types
2727 of parallel/task constructs. */
2728
2729static void
2730finish_taskreg_scan (omp_context *ctx)
2731{
2732 if (ctx->record_type == NULL_TREE)
2733 return;
2734
2735 /* If any task_shared_vars were needed, verify all
2736 OMP_CLAUSE_SHARED clauses on GIMPLE_OMP_{PARALLEL,TASK}
2737 statements if use_pointer_for_field hasn't changed
2738 because of that. If it did, update field types now. */
2739 if (task_shared_vars)
2740 {
2741 tree c;
2742
2743 for (c = gimple_omp_taskreg_clauses (ctx->stmt);
2744 c; c = OMP_CLAUSE_CHAIN (c))
43895be5 2745 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
2746 && !OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
37eaded9 2747 {
2748 tree decl = OMP_CLAUSE_DECL (c);
2749
2750 /* Global variables don't need to be copied,
2751 the receiver side will use them directly. */
2752 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
2753 continue;
2754 if (!bitmap_bit_p (task_shared_vars, DECL_UID (decl))
2755 || !use_pointer_for_field (decl, ctx))
2756 continue;
2757 tree field = lookup_field (decl, ctx);
2758 if (TREE_CODE (TREE_TYPE (field)) == POINTER_TYPE
2759 && TREE_TYPE (TREE_TYPE (field)) == TREE_TYPE (decl))
2760 continue;
2761 TREE_TYPE (field) = build_pointer_type (TREE_TYPE (decl));
2762 TREE_THIS_VOLATILE (field) = 0;
2763 DECL_USER_ALIGN (field) = 0;
2764 DECL_ALIGN (field) = TYPE_ALIGN (TREE_TYPE (field));
2765 if (TYPE_ALIGN (ctx->record_type) < DECL_ALIGN (field))
2766 TYPE_ALIGN (ctx->record_type) = DECL_ALIGN (field);
2767 if (ctx->srecord_type)
2768 {
2769 tree sfield = lookup_sfield (decl, ctx);
2770 TREE_TYPE (sfield) = TREE_TYPE (field);
2771 TREE_THIS_VOLATILE (sfield) = 0;
2772 DECL_USER_ALIGN (sfield) = 0;
2773 DECL_ALIGN (sfield) = DECL_ALIGN (field);
2774 if (TYPE_ALIGN (ctx->srecord_type) < DECL_ALIGN (sfield))
2775 TYPE_ALIGN (ctx->srecord_type) = DECL_ALIGN (sfield);
2776 }
2777 }
2778 }
2779
2780 if (gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2781 {
2782 layout_type (ctx->record_type);
2783 fixup_child_record_type (ctx);
2784 }
fd6481cf 2785 else
2786 {
37eaded9 2787 location_t loc = gimple_location (ctx->stmt);
fd6481cf 2788 tree *p, vla_fields = NULL_TREE, *q = &vla_fields;
2789 /* Move VLA fields to the end. */
2790 p = &TYPE_FIELDS (ctx->record_type);
2791 while (*p)
2792 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p))
2793 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p))))
2794 {
2795 *q = *p;
2796 *p = TREE_CHAIN (*p);
2797 TREE_CHAIN (*q) = NULL_TREE;
2798 q = &TREE_CHAIN (*q);
2799 }
2800 else
1767a056 2801 p = &DECL_CHAIN (*p);
fd6481cf 2802 *p = vla_fields;
43895be5 2803 if (gimple_omp_task_taskloop_p (ctx->stmt))
2804 {
2805 /* Move fields corresponding to first and second _looptemp_
2806 clause first. There are filled by GOMP_taskloop
2807 and thus need to be in specific positions. */
2808 tree c1 = gimple_omp_task_clauses (ctx->stmt);
2809 c1 = find_omp_clause (c1, OMP_CLAUSE__LOOPTEMP_);
2810 tree c2 = find_omp_clause (OMP_CLAUSE_CHAIN (c1),
2811 OMP_CLAUSE__LOOPTEMP_);
2812 tree f1 = lookup_field (OMP_CLAUSE_DECL (c1), ctx);
2813 tree f2 = lookup_field (OMP_CLAUSE_DECL (c2), ctx);
2814 p = &TYPE_FIELDS (ctx->record_type);
2815 while (*p)
2816 if (*p == f1 || *p == f2)
2817 *p = DECL_CHAIN (*p);
2818 else
2819 p = &DECL_CHAIN (*p);
2820 DECL_CHAIN (f1) = f2;
2821 DECL_CHAIN (f2) = TYPE_FIELDS (ctx->record_type);
2822 TYPE_FIELDS (ctx->record_type) = f1;
2823 if (ctx->srecord_type)
2824 {
2825 f1 = lookup_sfield (OMP_CLAUSE_DECL (c1), ctx);
2826 f2 = lookup_sfield (OMP_CLAUSE_DECL (c2), ctx);
2827 p = &TYPE_FIELDS (ctx->srecord_type);
2828 while (*p)
2829 if (*p == f1 || *p == f2)
2830 *p = DECL_CHAIN (*p);
2831 else
2832 p = &DECL_CHAIN (*p);
2833 DECL_CHAIN (f1) = f2;
2834 DECL_CHAIN (f2) = TYPE_FIELDS (ctx->srecord_type);
2835 TYPE_FIELDS (ctx->srecord_type) = f1;
2836 }
2837 }
fd6481cf 2838 layout_type (ctx->record_type);
2839 fixup_child_record_type (ctx);
2840 if (ctx->srecord_type)
2841 layout_type (ctx->srecord_type);
37eaded9 2842 tree t = fold_convert_loc (loc, long_integer_type_node,
2843 TYPE_SIZE_UNIT (ctx->record_type));
2844 gimple_omp_task_set_arg_size (ctx->stmt, t);
75a70cf9 2845 t = build_int_cst (long_integer_type_node,
fd6481cf 2846 TYPE_ALIGN_UNIT (ctx->record_type));
37eaded9 2847 gimple_omp_task_set_arg_align (ctx->stmt, t);
fd6481cf 2848 }
2849}
2850
a8e785ba 2851/* Find the enclosing offload context. */
1e8e9920 2852
ca4c3545 2853static omp_context *
2854enclosing_target_ctx (omp_context *ctx)
2855{
a8e785ba 2856 for (; ctx; ctx = ctx->outer)
2857 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET)
2858 break;
2859
ca4c3545 2860 return ctx;
2861}
2862
a8e785ba 2863/* Return true if ctx is part of an oacc kernels region. */
2864
ca4c3545 2865static bool
a8e785ba 2866ctx_in_oacc_kernels_region (omp_context *ctx)
ca4c3545 2867{
a8e785ba 2868 for (;ctx != NULL; ctx = ctx->outer)
2869 {
2870 gimple *stmt = ctx->stmt;
2871 if (gimple_code (stmt) == GIMPLE_OMP_TARGET
2872 && gimple_omp_target_kind (stmt) == GF_OMP_TARGET_KIND_OACC_KERNELS)
2873 return true;
2874 }
2875
2876 return false;
2877}
2878
2879/* Check the parallelism clauses inside a kernels regions.
2880 Until kernels handling moves to use the same loop indirection
2881 scheme as parallel, we need to do this checking early. */
2882
2883static unsigned
2884check_oacc_kernel_gwv (gomp_for *stmt, omp_context *ctx)
2885{
2886 bool checking = true;
2887 unsigned outer_mask = 0;
2888 unsigned this_mask = 0;
2889 bool has_seq = false, has_auto = false;
2890
2891 if (ctx->outer)
2892 outer_mask = check_oacc_kernel_gwv (NULL, ctx->outer);
2893 if (!stmt)
2894 {
2895 checking = false;
2896 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR)
2897 return outer_mask;
2898 stmt = as_a <gomp_for *> (ctx->stmt);
2899 }
2900
2901 for (tree c = gimple_omp_for_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
2902 {
2903 switch (OMP_CLAUSE_CODE (c))
2904 {
2905 case OMP_CLAUSE_GANG:
2906 this_mask |= GOMP_DIM_MASK (GOMP_DIM_GANG);
2907 break;
2908 case OMP_CLAUSE_WORKER:
2909 this_mask |= GOMP_DIM_MASK (GOMP_DIM_WORKER);
2910 break;
2911 case OMP_CLAUSE_VECTOR:
2912 this_mask |= GOMP_DIM_MASK (GOMP_DIM_VECTOR);
2913 break;
2914 case OMP_CLAUSE_SEQ:
2915 has_seq = true;
2916 break;
2917 case OMP_CLAUSE_AUTO:
2918 has_auto = true;
2919 break;
2920 default:
2921 break;
2922 }
2923 }
2924
2925 if (checking)
2926 {
2927 if (has_seq && (this_mask || has_auto))
2928 error_at (gimple_location (stmt), "%<seq%> overrides other"
2929 " OpenACC loop specifiers");
2930 else if (has_auto && this_mask)
2931 error_at (gimple_location (stmt), "%<auto%> conflicts with other"
2932 " OpenACC loop specifiers");
2933
2934 if (this_mask & outer_mask)
2935 error_at (gimple_location (stmt), "inner loop uses same"
2936 " OpenACC parallelism as containing loop");
2937 }
2938
2939 return outer_mask | this_mask;
ca4c3545 2940}
2941
2942/* Scan a GIMPLE_OMP_FOR. */
1e8e9920 2943
2944static void
1a91d914 2945scan_omp_for (gomp_for *stmt, omp_context *outer_ctx)
1e8e9920 2946{
773c5ba7 2947 omp_context *ctx;
75a70cf9 2948 size_t i;
ca4c3545 2949 tree clauses = gimple_omp_for_clauses (stmt);
2950
773c5ba7 2951 ctx = new_omp_context (stmt, outer_ctx);
1e8e9920 2952
ca4c3545 2953 if (is_gimple_omp_oacc (stmt))
2954 {
a8e785ba 2955 omp_context *tgt = enclosing_target_ctx (outer_ctx);
2956
2957 if (!tgt || is_oacc_parallel (tgt))
2958 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2959 {
2960 char const *check = NULL;
2961
2962 switch (OMP_CLAUSE_CODE (c))
2963 {
2964 case OMP_CLAUSE_GANG:
2965 check = "gang";
2966 break;
2967
2968 case OMP_CLAUSE_WORKER:
2969 check = "worker";
2970 break;
2971
2972 case OMP_CLAUSE_VECTOR:
2973 check = "vector";
2974 break;
2975
2976 default:
2977 break;
2978 }
2979
2980 if (check && OMP_CLAUSE_OPERAND (c, 0))
2981 error_at (gimple_location (stmt),
2982 "argument not permitted on %qs clause in"
2983 " OpenACC %<parallel%>", check);
2984 }
2985
2986 if (tgt && is_oacc_kernels (tgt))
2987 {
2988 /* Strip out reductions, as they are not handled yet. */
2989 tree *prev_ptr = &clauses;
2990
2991 while (tree probe = *prev_ptr)
ca4c3545 2992 {
a8e785ba 2993 tree *next_ptr = &OMP_CLAUSE_CHAIN (probe);
2994
2995 if (OMP_CLAUSE_CODE (probe) == OMP_CLAUSE_REDUCTION)
2996 *prev_ptr = *next_ptr;
2997 else
2998 prev_ptr = next_ptr;
ca4c3545 2999 }
a8e785ba 3000
3001 gimple_omp_for_set_clauses (stmt, clauses);
3002 check_oacc_kernel_gwv (stmt, ctx);
ca4c3545 3003 }
3004 }
3005
3006 scan_sharing_clauses (clauses, ctx);
1e8e9920 3007
ab129075 3008 scan_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
75a70cf9 3009 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
fd6481cf 3010 {
75a70cf9 3011 scan_omp_op (gimple_omp_for_index_ptr (stmt, i), ctx);
3012 scan_omp_op (gimple_omp_for_initial_ptr (stmt, i), ctx);
3013 scan_omp_op (gimple_omp_for_final_ptr (stmt, i), ctx);
3014 scan_omp_op (gimple_omp_for_incr_ptr (stmt, i), ctx);
fd6481cf 3015 }
ab129075 3016 scan_omp (gimple_omp_body_ptr (stmt), ctx);
1e8e9920 3017}
3018
3019/* Scan an OpenMP sections directive. */
3020
3021static void
1a91d914 3022scan_omp_sections (gomp_sections *stmt, omp_context *outer_ctx)
1e8e9920 3023{
1e8e9920 3024 omp_context *ctx;
3025
3026 ctx = new_omp_context (stmt, outer_ctx);
75a70cf9 3027 scan_sharing_clauses (gimple_omp_sections_clauses (stmt), ctx);
ab129075 3028 scan_omp (gimple_omp_body_ptr (stmt), ctx);
1e8e9920 3029}
3030
3031/* Scan an OpenMP single directive. */
3032
3033static void
1a91d914 3034scan_omp_single (gomp_single *stmt, omp_context *outer_ctx)
1e8e9920 3035{
1e8e9920 3036 omp_context *ctx;
3037 tree name;
3038
3039 ctx = new_omp_context (stmt, outer_ctx);
3040 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
3041 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
3042 name = create_tmp_var_name (".omp_copy_s");
e60a6f7b 3043 name = build_decl (gimple_location (stmt),
3044 TYPE_DECL, name, ctx->record_type);
1e8e9920 3045 TYPE_NAME (ctx->record_type) = name;
3046
75a70cf9 3047 scan_sharing_clauses (gimple_omp_single_clauses (stmt), ctx);
ab129075 3048 scan_omp (gimple_omp_body_ptr (stmt), ctx);
1e8e9920 3049
3050 if (TYPE_FIELDS (ctx->record_type) == NULL)
3051 ctx->record_type = NULL;
3052 else
3053 layout_type (ctx->record_type);
3054}
3055
12dc9a16 3056/* Return true if the CLAUSES of an omp target guarantee that the base pointers
3057 used in the corresponding offloaded function are restrict. */
3058
3059static bool
3060omp_target_base_pointers_restrict_p (tree clauses)
3061{
3062 /* The analysis relies on the GOMP_MAP_FORCE_* mapping kinds, which are only
3063 used by OpenACC. */
3064 if (flag_openacc == 0)
3065 return false;
3066
3067 /* I. Basic example:
3068
3069 void foo (void)
3070 {
3071 unsigned int a[2], b[2];
3072
3073 #pragma acc kernels \
3074 copyout (a) \
3075 copyout (b)
3076 {
3077 a[0] = 0;
3078 b[0] = 1;
3079 }
3080 }
3081
3082 After gimplification, we have:
3083
3084 #pragma omp target oacc_kernels \
3085 map(force_from:a [len: 8]) \
3086 map(force_from:b [len: 8])
3087 {
3088 a[0] = 0;
3089 b[0] = 1;
3090 }
3091
3092 Because both mappings have the force prefix, we know that they will be
3093 allocated when calling the corresponding offloaded function, which means we
3094 can mark the base pointers for a and b in the offloaded function as
3095 restrict. */
3096
3097 tree c;
3098 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
3099 {
3100 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP)
3101 return false;
3102
3103 switch (OMP_CLAUSE_MAP_KIND (c))
3104 {
3105 case GOMP_MAP_FORCE_ALLOC:
3106 case GOMP_MAP_FORCE_TO:
3107 case GOMP_MAP_FORCE_FROM:
3108 case GOMP_MAP_FORCE_TOFROM:
3109 break;
3110 default:
3111 return false;
3112 }
3113 }
3114
3115 return true;
3116}
3117
ca4c3545 3118/* Scan a GIMPLE_OMP_TARGET. */
bc7bff74 3119
3120static void
1a91d914 3121scan_omp_target (gomp_target *stmt, omp_context *outer_ctx)
bc7bff74 3122{
3123 omp_context *ctx;
3124 tree name;
ca4c3545 3125 bool offloaded = is_gimple_omp_offloaded (stmt);
3126 tree clauses = gimple_omp_target_clauses (stmt);
bc7bff74 3127
3128 ctx = new_omp_context (stmt, outer_ctx);
3129 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
3130 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
3131 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
3132 name = create_tmp_var_name (".omp_data_t");
3133 name = build_decl (gimple_location (stmt),
3134 TYPE_DECL, name, ctx->record_type);
3135 DECL_ARTIFICIAL (name) = 1;
3136 DECL_NAMELESS (name) = 1;
3137 TYPE_NAME (ctx->record_type) = name;
240131b5 3138 TYPE_ARTIFICIAL (ctx->record_type) = 1;
12dc9a16 3139
3140 bool base_pointers_restrict = false;
ca4c3545 3141 if (offloaded)
bc7bff74 3142 {
3143 create_omp_child_function (ctx, false);
3144 gimple_omp_target_set_child_fn (stmt, ctx->cb.dst_fn);
12dc9a16 3145
3146 base_pointers_restrict = omp_target_base_pointers_restrict_p (clauses);
3147 if (base_pointers_restrict
3148 && dump_file && (dump_flags & TDF_DETAILS))
3149 fprintf (dump_file,
3150 "Base pointers in offloaded function are restrict\n");
bc7bff74 3151 }
3152
12dc9a16 3153 scan_sharing_clauses (clauses, ctx, base_pointers_restrict);
bc7bff74 3154 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3155
3156 if (TYPE_FIELDS (ctx->record_type) == NULL)
3157 ctx->record_type = ctx->receiver_decl = NULL;
3158 else
3159 {
3160 TYPE_FIELDS (ctx->record_type)
3161 = nreverse (TYPE_FIELDS (ctx->record_type));
382ecba7 3162 if (flag_checking)
3163 {
3164 unsigned int align = DECL_ALIGN (TYPE_FIELDS (ctx->record_type));
3165 for (tree field = TYPE_FIELDS (ctx->record_type);
3166 field;
3167 field = DECL_CHAIN (field))
3168 gcc_assert (DECL_ALIGN (field) == align);
3169 }
bc7bff74 3170 layout_type (ctx->record_type);
ca4c3545 3171 if (offloaded)
bc7bff74 3172 fixup_child_record_type (ctx);
3173 }
3174}
3175
3176/* Scan an OpenMP teams directive. */
3177
3178static void
1a91d914 3179scan_omp_teams (gomp_teams *stmt, omp_context *outer_ctx)
bc7bff74 3180{
3181 omp_context *ctx = new_omp_context (stmt, outer_ctx);
3182 scan_sharing_clauses (gimple_omp_teams_clauses (stmt), ctx);
3183 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3184}
1e8e9920 3185
ca4c3545 3186/* Check nesting restrictions. */
ab129075 3187static bool
42acab1c 3188check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx)
c1d127dd 3189{
43895be5 3190 tree c;
3191
ca4c3545 3192 /* No nesting of non-OpenACC STMT (that is, an OpenMP one, or a GOMP builtin)
3193 inside an OpenACC CTX. */
3194 if (!(is_gimple_omp (stmt)
3195 && is_gimple_omp_oacc (stmt)))
3196 {
7821c1b5 3197 for (omp_context *octx = ctx; octx != NULL; octx = octx->outer)
3198 if (is_gimple_omp (octx->stmt)
3199 && is_gimple_omp_oacc (octx->stmt)
9e10bfb7 3200 /* Except for atomic codes that we share with OpenMP. */
3201 && ! (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD
3202 || gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE))
ca4c3545 3203 {
3204 error_at (gimple_location (stmt),
3205 "non-OpenACC construct inside of OpenACC region");
3206 return false;
3207 }
3208 }
3209
3d483a94 3210 if (ctx != NULL)
3211 {
3212 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
10c55644 3213 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3d483a94 3214 {
43895be5 3215 c = NULL_TREE;
3216 if (gimple_code (stmt) == GIMPLE_OMP_ORDERED)
3217 {
3218 c = gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt));
7821c1b5 3219 if (find_omp_clause (c, OMP_CLAUSE_SIMD))
3220 {
3221 if (find_omp_clause (c, OMP_CLAUSE_THREADS)
3222 && (ctx->outer == NULL
3223 || !gimple_omp_for_combined_into_p (ctx->stmt)
3224 || gimple_code (ctx->outer->stmt) != GIMPLE_OMP_FOR
3225 || (gimple_omp_for_kind (ctx->outer->stmt)
3226 != GF_OMP_FOR_KIND_FOR)
3227 || !gimple_omp_for_combined_p (ctx->outer->stmt)))
3228 {
3229 error_at (gimple_location (stmt),
3230 "%<ordered simd threads%> must be closely "
3231 "nested inside of %<for simd%> region");
3232 return false;
3233 }
3234 return true;
3235 }
43895be5 3236 }
3d483a94 3237 error_at (gimple_location (stmt),
43895be5 3238 "OpenMP constructs other than %<#pragma omp ordered simd%>"
7821c1b5 3239 " may not be nested inside %<simd%> region");
3d483a94 3240 return false;
3241 }
bc7bff74 3242 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3243 {
3244 if ((gimple_code (stmt) != GIMPLE_OMP_FOR
3245 || (gimple_omp_for_kind (stmt)
3246 != GF_OMP_FOR_KIND_DISTRIBUTE))
3247 && gimple_code (stmt) != GIMPLE_OMP_PARALLEL)
3248 {
3249 error_at (gimple_location (stmt),
7821c1b5 3250 "only %<distribute%> or %<parallel%> regions are "
3251 "allowed to be strictly nested inside %<teams%> "
3252 "region");
bc7bff74 3253 return false;
3254 }
3255 }
3d483a94 3256 }
75a70cf9 3257 switch (gimple_code (stmt))
c1d127dd 3258 {
75a70cf9 3259 case GIMPLE_OMP_FOR:
10c55644 3260 if (gimple_omp_for_kind (stmt) & GF_OMP_FOR_SIMD)
3d483a94 3261 return true;
bc7bff74 3262 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
3263 {
3264 if (ctx != NULL && gimple_code (ctx->stmt) != GIMPLE_OMP_TEAMS)
3265 {
3266 error_at (gimple_location (stmt),
7821c1b5 3267 "%<distribute%> region must be strictly nested "
3268 "inside %<teams%> construct");
bc7bff74 3269 return false;
3270 }
3271 return true;
3272 }
43895be5 3273 /* We split taskloop into task and nested taskloop in it. */
3274 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_TASKLOOP)
3275 return true;
7a1ed40d 3276 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
3277 {
3278 bool ok = false;
3279
3280 if (ctx)
3281 switch (gimple_code (ctx->stmt))
3282 {
3283 case GIMPLE_OMP_FOR:
3284 ok = (gimple_omp_for_kind (ctx->stmt)
3285 == GF_OMP_FOR_KIND_OACC_LOOP);
3286 break;
3287
3288 case GIMPLE_OMP_TARGET:
3289 switch (gimple_omp_target_kind (ctx->stmt))
3290 {
3291 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
3292 case GF_OMP_TARGET_KIND_OACC_KERNELS:
3293 ok = true;
3294 break;
3295
3296 default:
3297 break;
3298 }
3299
3300 default:
3301 break;
3302 }
3303 else if (get_oacc_fn_attrib (current_function_decl))
3304 ok = true;
3305 if (!ok)
3306 {
3307 error_at (gimple_location (stmt),
3308 "OpenACC loop directive must be associated with"
3309 " an OpenACC compute region");
3310 return false;
3311 }
3312 }
bc7bff74 3313 /* FALLTHRU */
3314 case GIMPLE_CALL:
3315 if (is_gimple_call (stmt)
3316 && (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3317 == BUILT_IN_GOMP_CANCEL
3318 || DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3319 == BUILT_IN_GOMP_CANCELLATION_POINT))
3320 {
3321 const char *bad = NULL;
3322 const char *kind = NULL;
7821c1b5 3323 const char *construct
3324 = (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3325 == BUILT_IN_GOMP_CANCEL)
3326 ? "#pragma omp cancel"
3327 : "#pragma omp cancellation point";
bc7bff74 3328 if (ctx == NULL)
3329 {
3330 error_at (gimple_location (stmt), "orphaned %qs construct",
7821c1b5 3331 construct);
bc7bff74 3332 return false;
3333 }
6b409616 3334 switch (tree_fits_shwi_p (gimple_call_arg (stmt, 0))
3335 ? tree_to_shwi (gimple_call_arg (stmt, 0))
bc7bff74 3336 : 0)
3337 {
3338 case 1:
3339 if (gimple_code (ctx->stmt) != GIMPLE_OMP_PARALLEL)
3340 bad = "#pragma omp parallel";
3341 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3342 == BUILT_IN_GOMP_CANCEL
3343 && !integer_zerop (gimple_call_arg (stmt, 1)))
3344 ctx->cancellable = true;
3345 kind = "parallel";
3346 break;
3347 case 2:
3348 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
3349 || gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR)
3350 bad = "#pragma omp for";
3351 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3352 == BUILT_IN_GOMP_CANCEL
3353 && !integer_zerop (gimple_call_arg (stmt, 1)))
3354 {
3355 ctx->cancellable = true;
3356 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3357 OMP_CLAUSE_NOWAIT))
3358 warning_at (gimple_location (stmt), 0,
3359 "%<#pragma omp cancel for%> inside "
3360 "%<nowait%> for construct");
3361 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3362 OMP_CLAUSE_ORDERED))
3363 warning_at (gimple_location (stmt), 0,
3364 "%<#pragma omp cancel for%> inside "
3365 "%<ordered%> for construct");
3366 }
3367 kind = "for";
3368 break;
3369 case 4:
3370 if (gimple_code (ctx->stmt) != GIMPLE_OMP_SECTIONS
3371 && gimple_code (ctx->stmt) != GIMPLE_OMP_SECTION)
3372 bad = "#pragma omp sections";
3373 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3374 == BUILT_IN_GOMP_CANCEL
3375 && !integer_zerop (gimple_call_arg (stmt, 1)))
3376 {
3377 if (gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS)
3378 {
3379 ctx->cancellable = true;
3380 if (find_omp_clause (gimple_omp_sections_clauses
3381 (ctx->stmt),
3382 OMP_CLAUSE_NOWAIT))
3383 warning_at (gimple_location (stmt), 0,
3384 "%<#pragma omp cancel sections%> inside "
3385 "%<nowait%> sections construct");
3386 }
3387 else
3388 {
3389 gcc_assert (ctx->outer
3390 && gimple_code (ctx->outer->stmt)
3391 == GIMPLE_OMP_SECTIONS);
3392 ctx->outer->cancellable = true;
3393 if (find_omp_clause (gimple_omp_sections_clauses
3394 (ctx->outer->stmt),
3395 OMP_CLAUSE_NOWAIT))
3396 warning_at (gimple_location (stmt), 0,
3397 "%<#pragma omp cancel sections%> inside "
3398 "%<nowait%> sections construct");
3399 }
3400 }
3401 kind = "sections";
3402 break;
3403 case 8:
3404 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TASK)
3405 bad = "#pragma omp task";
3406 else
7821c1b5 3407 {
3408 for (omp_context *octx = ctx->outer;
3409 octx; octx = octx->outer)
3410 {
3411 switch (gimple_code (octx->stmt))
3412 {
3413 case GIMPLE_OMP_TASKGROUP:
3414 break;
3415 case GIMPLE_OMP_TARGET:
3416 if (gimple_omp_target_kind (octx->stmt)
3417 != GF_OMP_TARGET_KIND_REGION)
3418 continue;
3419 /* FALLTHRU */
3420 case GIMPLE_OMP_PARALLEL:
3421 case GIMPLE_OMP_TEAMS:
3422 error_at (gimple_location (stmt),
3423 "%<%s taskgroup%> construct not closely "
3424 "nested inside of %<taskgroup%> region",
3425 construct);
3426 return false;
3427 default:
3428 continue;
3429 }
3430 break;
3431 }
3432 ctx->cancellable = true;
3433 }
bc7bff74 3434 kind = "taskgroup";
3435 break;
3436 default:
3437 error_at (gimple_location (stmt), "invalid arguments");
3438 return false;
3439 }
3440 if (bad)
3441 {
3442 error_at (gimple_location (stmt),
3443 "%<%s %s%> construct not closely nested inside of %qs",
7821c1b5 3444 construct, kind, bad);
bc7bff74 3445 return false;
3446 }
3447 }
3d483a94 3448 /* FALLTHRU */
75a70cf9 3449 case GIMPLE_OMP_SECTIONS:
3450 case GIMPLE_OMP_SINGLE:
c1d127dd 3451 for (; ctx != NULL; ctx = ctx->outer)
75a70cf9 3452 switch (gimple_code (ctx->stmt))
c1d127dd 3453 {
75a70cf9 3454 case GIMPLE_OMP_FOR:
7821c1b5 3455 if (gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR
3456 && gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_TASKLOOP)
3457 break;
3458 /* FALLTHRU */
75a70cf9 3459 case GIMPLE_OMP_SECTIONS:
3460 case GIMPLE_OMP_SINGLE:
3461 case GIMPLE_OMP_ORDERED:
3462 case GIMPLE_OMP_MASTER:
3463 case GIMPLE_OMP_TASK:
bc7bff74 3464 case GIMPLE_OMP_CRITICAL:
75a70cf9 3465 if (is_gimple_call (stmt))
fd6481cf 3466 {
bc7bff74 3467 if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3468 != BUILT_IN_GOMP_BARRIER)
3469 return true;
ab129075 3470 error_at (gimple_location (stmt),
3471 "barrier region may not be closely nested inside "
7821c1b5 3472 "of work-sharing, %<critical%>, %<ordered%>, "
3473 "%<master%>, explicit %<task%> or %<taskloop%> "
3474 "region");
ab129075 3475 return false;
fd6481cf 3476 }
ab129075 3477 error_at (gimple_location (stmt),
3478 "work-sharing region may not be closely nested inside "
7821c1b5 3479 "of work-sharing, %<critical%>, %<ordered%>, "
3480 "%<master%>, explicit %<task%> or %<taskloop%> region");
ab129075 3481 return false;
75a70cf9 3482 case GIMPLE_OMP_PARALLEL:
7821c1b5 3483 case GIMPLE_OMP_TEAMS:
ab129075 3484 return true;
7821c1b5 3485 case GIMPLE_OMP_TARGET:
3486 if (gimple_omp_target_kind (ctx->stmt)
3487 == GF_OMP_TARGET_KIND_REGION)
3488 return true;
3489 break;
c1d127dd 3490 default:
3491 break;
3492 }
3493 break;
75a70cf9 3494 case GIMPLE_OMP_MASTER:
c1d127dd 3495 for (; ctx != NULL; ctx = ctx->outer)
75a70cf9 3496 switch (gimple_code (ctx->stmt))
c1d127dd 3497 {
75a70cf9 3498 case GIMPLE_OMP_FOR:
7821c1b5 3499 if (gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR
3500 && gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_TASKLOOP)
3501 break;
3502 /* FALLTHRU */
75a70cf9 3503 case GIMPLE_OMP_SECTIONS:
3504 case GIMPLE_OMP_SINGLE:
3505 case GIMPLE_OMP_TASK:
ab129075 3506 error_at (gimple_location (stmt),
7821c1b5 3507 "%<master%> region may not be closely nested inside "
3508 "of work-sharing, explicit %<task%> or %<taskloop%> "
3509 "region");
ab129075 3510 return false;
75a70cf9 3511 case GIMPLE_OMP_PARALLEL:
7821c1b5 3512 case GIMPLE_OMP_TEAMS:
ab129075 3513 return true;
7821c1b5 3514 case GIMPLE_OMP_TARGET:
3515 if (gimple_omp_target_kind (ctx->stmt)
3516 == GF_OMP_TARGET_KIND_REGION)
3517 return true;
3518 break;
c1d127dd 3519 default:
3520 break;
3521 }
3522 break;
43895be5 3523 case GIMPLE_OMP_TASK:
3524 for (c = gimple_omp_task_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
3525 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
3526 && (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE
3527 || OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK))
3528 {
3529 enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c);
3530 error_at (OMP_CLAUSE_LOCATION (c),
3531 "%<depend(%s)%> is only allowed in %<omp ordered%>",
3532 kind == OMP_CLAUSE_DEPEND_SOURCE ? "source" : "sink");
3533 return false;
3534 }
3535 break;
75a70cf9 3536 case GIMPLE_OMP_ORDERED:
43895be5 3537 for (c = gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt));
3538 c; c = OMP_CLAUSE_CHAIN (c))
3539 {
3540 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND)
3541 {
3542 gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_THREADS
7821c1b5 3543 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SIMD);
43895be5 3544 continue;
3545 }
3546 enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c);
3547 if (kind == OMP_CLAUSE_DEPEND_SOURCE
3548 || kind == OMP_CLAUSE_DEPEND_SINK)
3549 {
3550 tree oclause;
3551 /* Look for containing ordered(N) loop. */
3552 if (ctx == NULL
3553 || gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
3554 || (oclause
3555 = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3556 OMP_CLAUSE_ORDERED)) == NULL_TREE)
3557 {
3558 error_at (OMP_CLAUSE_LOCATION (c),
7821c1b5 3559 "%<ordered%> construct with %<depend%> clause "
3560 "must be closely nested inside an %<ordered%> "
3561 "loop");
43895be5 3562 return false;
3563 }
3564 else if (OMP_CLAUSE_ORDERED_EXPR (oclause) == NULL_TREE)
3565 {
3566 error_at (OMP_CLAUSE_LOCATION (c),
7821c1b5 3567 "%<ordered%> construct with %<depend%> clause "
3568 "must be closely nested inside a loop with "
3569 "%<ordered%> clause with a parameter");
43895be5 3570 return false;
3571 }
3572 }
3573 else
3574 {
3575 error_at (OMP_CLAUSE_LOCATION (c),
7821c1b5 3576 "invalid depend kind in omp %<ordered%> %<depend%>");
3577 return false;
3578 }
3579 }
3580 c = gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt));
3581 if (find_omp_clause (c, OMP_CLAUSE_SIMD))
3582 {
3583 /* ordered simd must be closely nested inside of simd region,
3584 and simd region must not encounter constructs other than
3585 ordered simd, therefore ordered simd may be either orphaned,
3586 or ctx->stmt must be simd. The latter case is handled already
3587 earlier. */
3588 if (ctx != NULL)
3589 {
3590 error_at (gimple_location (stmt),
3591 "%<ordered%> %<simd%> must be closely nested inside "
3592 "%<simd%> region");
43895be5 3593 return false;
3594 }
3595 }
c1d127dd 3596 for (; ctx != NULL; ctx = ctx->outer)
75a70cf9 3597 switch (gimple_code (ctx->stmt))
c1d127dd 3598 {
75a70cf9 3599 case GIMPLE_OMP_CRITICAL:
3600 case GIMPLE_OMP_TASK:
7821c1b5 3601 case GIMPLE_OMP_ORDERED:
3602 ordered_in_taskloop:
ab129075 3603 error_at (gimple_location (stmt),
7821c1b5 3604 "%<ordered%> region may not be closely nested inside "
3605 "of %<critical%>, %<ordered%>, explicit %<task%> or "
3606 "%<taskloop%> region");
ab129075 3607 return false;
75a70cf9 3608 case GIMPLE_OMP_FOR:
7821c1b5 3609 if (gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_TASKLOOP)
3610 goto ordered_in_taskloop;
75a70cf9 3611 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
c1d127dd 3612 OMP_CLAUSE_ORDERED) == NULL)
ab129075 3613 {
3614 error_at (gimple_location (stmt),
7821c1b5 3615 "%<ordered%> region must be closely nested inside "
3616 "a loop region with an %<ordered%> clause");
ab129075 3617 return false;
3618 }
3619 return true;
7821c1b5 3620 case GIMPLE_OMP_TARGET:
3621 if (gimple_omp_target_kind (ctx->stmt)
3622 != GF_OMP_TARGET_KIND_REGION)
3623 break;
3624 /* FALLTHRU */
75a70cf9 3625 case GIMPLE_OMP_PARALLEL:
7821c1b5 3626 case GIMPLE_OMP_TEAMS:
bc7bff74 3627 error_at (gimple_location (stmt),
7821c1b5 3628 "%<ordered%> region must be closely nested inside "
3629 "a loop region with an %<ordered%> clause");
bc7bff74 3630 return false;
c1d127dd 3631 default:
3632 break;
3633 }
3634 break;
75a70cf9 3635 case GIMPLE_OMP_CRITICAL:
1a91d914 3636 {
3637 tree this_stmt_name
3638 = gimple_omp_critical_name (as_a <gomp_critical *> (stmt));
3639 for (; ctx != NULL; ctx = ctx->outer)
3640 if (gomp_critical *other_crit
3641 = dyn_cast <gomp_critical *> (ctx->stmt))
3642 if (this_stmt_name == gimple_omp_critical_name (other_crit))
3643 {
3644 error_at (gimple_location (stmt),
7821c1b5 3645 "%<critical%> region may not be nested inside "
3646 "a %<critical%> region with the same name");
1a91d914 3647 return false;
3648 }
3649 }
c1d127dd 3650 break;
bc7bff74 3651 case GIMPLE_OMP_TEAMS:
3652 if (ctx == NULL
3653 || gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET
3654 || gimple_omp_target_kind (ctx->stmt) != GF_OMP_TARGET_KIND_REGION)
3655 {
3656 error_at (gimple_location (stmt),
7821c1b5 3657 "%<teams%> construct not closely nested inside of "
3658 "%<target%> construct");
bc7bff74 3659 return false;
3660 }
3661 break;
691447ab 3662 case GIMPLE_OMP_TARGET:
43895be5 3663 for (c = gimple_omp_target_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
3664 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
3665 && (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE
3666 || OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK))
3667 {
3668 enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c);
3669 error_at (OMP_CLAUSE_LOCATION (c),
3670 "%<depend(%s)%> is only allowed in %<omp ordered%>",
3671 kind == OMP_CLAUSE_DEPEND_SOURCE ? "source" : "sink");
3672 return false;
3673 }
691447ab 3674 for (; ctx != NULL; ctx = ctx->outer)
ca4c3545 3675 {
3676 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET)
3677 {
3678 if (is_gimple_omp (stmt)
3679 && is_gimple_omp_oacc (stmt)
3680 && is_gimple_omp (ctx->stmt))
3681 {
3682 error_at (gimple_location (stmt),
3683 "OpenACC construct inside of non-OpenACC region");
3684 return false;
3685 }
3686 continue;
3687 }
3688
3689 const char *stmt_name, *ctx_stmt_name;
3690 switch (gimple_omp_target_kind (stmt))
3691 {
3692 case GF_OMP_TARGET_KIND_REGION: stmt_name = "target"; break;
3693 case GF_OMP_TARGET_KIND_DATA: stmt_name = "target data"; break;
3694 case GF_OMP_TARGET_KIND_UPDATE: stmt_name = "target update"; break;
43895be5 3695 case GF_OMP_TARGET_KIND_ENTER_DATA:
3696 stmt_name = "target enter data"; break;
3697 case GF_OMP_TARGET_KIND_EXIT_DATA:
3698 stmt_name = "target exit data"; break;
ca4c3545 3699 case GF_OMP_TARGET_KIND_OACC_PARALLEL: stmt_name = "parallel"; break;
3700 case GF_OMP_TARGET_KIND_OACC_KERNELS: stmt_name = "kernels"; break;
3701 case GF_OMP_TARGET_KIND_OACC_DATA: stmt_name = "data"; break;
3702 case GF_OMP_TARGET_KIND_OACC_UPDATE: stmt_name = "update"; break;
43895be5 3703 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
3704 stmt_name = "enter/exit data"; break;
571b3486 3705 case GF_OMP_TARGET_KIND_OACC_HOST_DATA: stmt_name = "host_data";
3706 break;
ca4c3545 3707 default: gcc_unreachable ();
3708 }
3709 switch (gimple_omp_target_kind (ctx->stmt))
3710 {
3711 case GF_OMP_TARGET_KIND_REGION: ctx_stmt_name = "target"; break;
3712 case GF_OMP_TARGET_KIND_DATA: ctx_stmt_name = "target data"; break;
43895be5 3713 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
3714 ctx_stmt_name = "parallel"; break;
3715 case GF_OMP_TARGET_KIND_OACC_KERNELS:
3716 ctx_stmt_name = "kernels"; break;
ca4c3545 3717 case GF_OMP_TARGET_KIND_OACC_DATA: ctx_stmt_name = "data"; break;
571b3486 3718 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
3719 ctx_stmt_name = "host_data"; break;
ca4c3545 3720 default: gcc_unreachable ();
3721 }
3722
3723 /* OpenACC/OpenMP mismatch? */
3724 if (is_gimple_omp_oacc (stmt)
3725 != is_gimple_omp_oacc (ctx->stmt))
3726 {
3727 error_at (gimple_location (stmt),
7821c1b5 3728 "%s %qs construct inside of %s %qs region",
ca4c3545 3729 (is_gimple_omp_oacc (stmt)
3730 ? "OpenACC" : "OpenMP"), stmt_name,
3731 (is_gimple_omp_oacc (ctx->stmt)
3732 ? "OpenACC" : "OpenMP"), ctx_stmt_name);
3733 return false;
3734 }
3735 if (is_gimple_omp_offloaded (ctx->stmt))
3736 {
3737 /* No GIMPLE_OMP_TARGET inside offloaded OpenACC CTX. */
3738 if (is_gimple_omp_oacc (ctx->stmt))
3739 {
3740 error_at (gimple_location (stmt),
7821c1b5 3741 "%qs construct inside of %qs region",
ca4c3545 3742 stmt_name, ctx_stmt_name);
3743 return false;
3744 }
3745 else
3746 {
ca4c3545 3747 warning_at (gimple_location (stmt), 0,
7821c1b5 3748 "%qs construct inside of %qs region",
ca4c3545 3749 stmt_name, ctx_stmt_name);
3750 }
3751 }
3752 }
691447ab 3753 break;
c1d127dd 3754 default:
3755 break;
3756 }
ab129075 3757 return true;
c1d127dd 3758}
3759
3760
75a70cf9 3761/* Helper function scan_omp.
3762
3763 Callback for walk_tree or operators in walk_gimple_stmt used to
ca4c3545 3764 scan for OMP directives in TP. */
1e8e9920 3765
3766static tree
75a70cf9 3767scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
1e8e9920 3768{
4077bf7a 3769 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
3770 omp_context *ctx = (omp_context *) wi->info;
1e8e9920 3771 tree t = *tp;
3772
75a70cf9 3773 switch (TREE_CODE (t))
3774 {
3775 case VAR_DECL:
3776 case PARM_DECL:
3777 case LABEL_DECL:
3778 case RESULT_DECL:
3779 if (ctx)
3780 *tp = remap_decl (t, &ctx->cb);
3781 break;
3782
3783 default:
3784 if (ctx && TYPE_P (t))
3785 *tp = remap_type (t, &ctx->cb);
3786 else if (!DECL_P (t))
7cf869dd 3787 {
3788 *walk_subtrees = 1;
3789 if (ctx)
182cf5a9 3790 {
3791 tree tem = remap_type (TREE_TYPE (t), &ctx->cb);
3792 if (tem != TREE_TYPE (t))
3793 {
3794 if (TREE_CODE (t) == INTEGER_CST)
e913b5cd 3795 *tp = wide_int_to_tree (tem, t);
182cf5a9 3796 else
3797 TREE_TYPE (t) = tem;
3798 }
3799 }
7cf869dd 3800 }
75a70cf9 3801 break;
3802 }
3803
3804 return NULL_TREE;
3805}
3806
f2697631 3807/* Return true if FNDECL is a setjmp or a longjmp. */
3808
3809static bool
3810setjmp_or_longjmp_p (const_tree fndecl)
3811{
3812 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
3813 && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_SETJMP
3814 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LONGJMP))
3815 return true;
3816
3817 tree declname = DECL_NAME (fndecl);
3818 if (!declname)
3819 return false;
3820 const char *name = IDENTIFIER_POINTER (declname);
3821 return !strcmp (name, "setjmp") || !strcmp (name, "longjmp");
3822}
3823
75a70cf9 3824
3825/* Helper function for scan_omp.
3826
ca4c3545 3827 Callback for walk_gimple_stmt used to scan for OMP directives in
75a70cf9 3828 the current statement in GSI. */
3829
3830static tree
3831scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
3832 struct walk_stmt_info *wi)
3833{
42acab1c 3834 gimple *stmt = gsi_stmt (*gsi);
75a70cf9 3835 omp_context *ctx = (omp_context *) wi->info;
3836
3837 if (gimple_has_location (stmt))
3838 input_location = gimple_location (stmt);
1e8e9920 3839
ca4c3545 3840 /* Check the nesting restrictions. */
bc7bff74 3841 bool remove = false;
3842 if (is_gimple_omp (stmt))
3843 remove = !check_omp_nesting_restrictions (stmt, ctx);
3844 else if (is_gimple_call (stmt))
3845 {
3846 tree fndecl = gimple_call_fndecl (stmt);
f2697631 3847 if (fndecl)
3848 {
3849 if (setjmp_or_longjmp_p (fndecl)
3850 && ctx
3851 && gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
10c55644 3852 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
f2697631 3853 {
3854 remove = true;
3855 error_at (gimple_location (stmt),
3856 "setjmp/longjmp inside simd construct");
3857 }
3858 else if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
3859 switch (DECL_FUNCTION_CODE (fndecl))
3860 {
3861 case BUILT_IN_GOMP_BARRIER:
3862 case BUILT_IN_GOMP_CANCEL:
3863 case BUILT_IN_GOMP_CANCELLATION_POINT:
3864 case BUILT_IN_GOMP_TASKYIELD:
3865 case BUILT_IN_GOMP_TASKWAIT:
3866 case BUILT_IN_GOMP_TASKGROUP_START:
3867 case BUILT_IN_GOMP_TASKGROUP_END:
3868 remove = !check_omp_nesting_restrictions (stmt, ctx);
3869 break;
3870 default:
3871 break;
3872 }
3873 }
bc7bff74 3874 }
3875 if (remove)
3876 {
3877 stmt = gimple_build_nop ();
3878 gsi_replace (gsi, stmt, false);
fd6481cf 3879 }
c1d127dd 3880
75a70cf9 3881 *handled_ops_p = true;
3882
3883 switch (gimple_code (stmt))
1e8e9920 3884 {
75a70cf9 3885 case GIMPLE_OMP_PARALLEL:
fd6481cf 3886 taskreg_nesting_level++;
75a70cf9 3887 scan_omp_parallel (gsi, ctx);
fd6481cf 3888 taskreg_nesting_level--;
3889 break;
3890
75a70cf9 3891 case GIMPLE_OMP_TASK:
fd6481cf 3892 taskreg_nesting_level++;
75a70cf9 3893 scan_omp_task (gsi, ctx);
fd6481cf 3894 taskreg_nesting_level--;
1e8e9920 3895 break;
3896
75a70cf9 3897 case GIMPLE_OMP_FOR:
1a91d914 3898 scan_omp_for (as_a <gomp_for *> (stmt), ctx);
1e8e9920 3899 break;
3900
75a70cf9 3901 case GIMPLE_OMP_SECTIONS:
1a91d914 3902 scan_omp_sections (as_a <gomp_sections *> (stmt), ctx);
1e8e9920 3903 break;
3904
75a70cf9 3905 case GIMPLE_OMP_SINGLE:
1a91d914 3906 scan_omp_single (as_a <gomp_single *> (stmt), ctx);
1e8e9920 3907 break;
3908
75a70cf9 3909 case GIMPLE_OMP_SECTION:
3910 case GIMPLE_OMP_MASTER:
bc7bff74 3911 case GIMPLE_OMP_TASKGROUP:
75a70cf9 3912 case GIMPLE_OMP_ORDERED:
3913 case GIMPLE_OMP_CRITICAL:
3914 ctx = new_omp_context (stmt, ctx);
ab129075 3915 scan_omp (gimple_omp_body_ptr (stmt), ctx);
1e8e9920 3916 break;
3917
bc7bff74 3918 case GIMPLE_OMP_TARGET:
1a91d914 3919 scan_omp_target (as_a <gomp_target *> (stmt), ctx);
bc7bff74 3920 break;
3921
3922 case GIMPLE_OMP_TEAMS:
1a91d914 3923 scan_omp_teams (as_a <gomp_teams *> (stmt), ctx);
bc7bff74 3924 break;
3925
75a70cf9 3926 case GIMPLE_BIND:
1e8e9920 3927 {
3928 tree var;
1e8e9920 3929
75a70cf9 3930 *handled_ops_p = false;
3931 if (ctx)
1a91d914 3932 for (var = gimple_bind_vars (as_a <gbind *> (stmt));
3933 var ;
3934 var = DECL_CHAIN (var))
75a70cf9 3935 insert_decl_map (&ctx->cb, var, var);
1e8e9920 3936 }
3937 break;
1e8e9920 3938 default:
75a70cf9 3939 *handled_ops_p = false;
1e8e9920 3940 break;
3941 }
3942
3943 return NULL_TREE;
3944}
3945
3946
75a70cf9 3947/* Scan all the statements starting at the current statement. CTX
ca4c3545 3948 contains context information about the OMP directives and
75a70cf9 3949 clauses found during the scan. */
1e8e9920 3950
3951static void
ab129075 3952scan_omp (gimple_seq *body_p, omp_context *ctx)
1e8e9920 3953{
3954 location_t saved_location;
3955 struct walk_stmt_info wi;
3956
3957 memset (&wi, 0, sizeof (wi));
1e8e9920 3958 wi.info = ctx;
1e8e9920 3959 wi.want_locations = true;
3960
3961 saved_location = input_location;
ab129075 3962 walk_gimple_seq_mod (body_p, scan_omp_1_stmt, scan_omp_1_op, &wi);
1e8e9920 3963 input_location = saved_location;
3964}
3965\f
3966/* Re-gimplification and code generation routines. */
3967
3968/* Build a call to GOMP_barrier. */
3969
42acab1c 3970static gimple *
bc7bff74 3971build_omp_barrier (tree lhs)
3972{
3973 tree fndecl = builtin_decl_explicit (lhs ? BUILT_IN_GOMP_BARRIER_CANCEL
3974 : BUILT_IN_GOMP_BARRIER);
1a91d914 3975 gcall *g = gimple_build_call (fndecl, 0);
bc7bff74 3976 if (lhs)
3977 gimple_call_set_lhs (g, lhs);
3978 return g;
1e8e9920 3979}
3980
3981/* If a context was created for STMT when it was scanned, return it. */
3982
3983static omp_context *
42acab1c 3984maybe_lookup_ctx (gimple *stmt)
1e8e9920 3985{
3986 splay_tree_node n;
3987 n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
3988 return n ? (omp_context *) n->value : NULL;
3989}
3990
773c5ba7 3991
3992/* Find the mapping for DECL in CTX or the immediately enclosing
3993 context that has a mapping for DECL.
3994
3995 If CTX is a nested parallel directive, we may have to use the decl
3996 mappings created in CTX's parent context. Suppose that we have the
3997 following parallel nesting (variable UIDs showed for clarity):
3998
3999 iD.1562 = 0;
4000 #omp parallel shared(iD.1562) -> outer parallel
4001 iD.1562 = iD.1562 + 1;
4002
4003 #omp parallel shared (iD.1562) -> inner parallel
4004 iD.1562 = iD.1562 - 1;
4005
4006 Each parallel structure will create a distinct .omp_data_s structure
4007 for copying iD.1562 in/out of the directive:
4008
4009 outer parallel .omp_data_s.1.i -> iD.1562
4010 inner parallel .omp_data_s.2.i -> iD.1562
4011
4012 A shared variable mapping will produce a copy-out operation before
4013 the parallel directive and a copy-in operation after it. So, in
4014 this case we would have:
4015
4016 iD.1562 = 0;
4017 .omp_data_o.1.i = iD.1562;
4018 #omp parallel shared(iD.1562) -> outer parallel
4019 .omp_data_i.1 = &.omp_data_o.1
4020 .omp_data_i.1->i = .omp_data_i.1->i + 1;
4021
4022 .omp_data_o.2.i = iD.1562; -> **
4023 #omp parallel shared(iD.1562) -> inner parallel
4024 .omp_data_i.2 = &.omp_data_o.2
4025 .omp_data_i.2->i = .omp_data_i.2->i - 1;
4026
4027
4028 ** This is a problem. The symbol iD.1562 cannot be referenced
4029 inside the body of the outer parallel region. But since we are
4030 emitting this copy operation while expanding the inner parallel
4031 directive, we need to access the CTX structure of the outer
4032 parallel directive to get the correct mapping:
4033
4034 .omp_data_o.2.i = .omp_data_i.1->i
4035
4036 Since there may be other workshare or parallel directives enclosing
4037 the parallel directive, it may be necessary to walk up the context
4038 parent chain. This is not a problem in general because nested
4039 parallelism happens only rarely. */
4040
4041static tree
4042lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
4043{
4044 tree t;
4045 omp_context *up;
4046
773c5ba7 4047 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
4048 t = maybe_lookup_decl (decl, up);
4049
87b31375 4050 gcc_assert (!ctx->is_nested || t || is_global_var (decl));
773c5ba7 4051
c37594c7 4052 return t ? t : decl;
773c5ba7 4053}
4054
4055
f49d7bb5 4056/* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
4057 in outer contexts. */
4058
4059static tree
4060maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
4061{
4062 tree t = NULL;
4063 omp_context *up;
4064
87b31375 4065 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
4066 t = maybe_lookup_decl (decl, up);
f49d7bb5 4067
4068 return t ? t : decl;
4069}
4070
4071
df67b98c 4072/* Construct the initialization value for reduction operation OP. */
1e8e9920 4073
4074tree
df67b98c 4075omp_reduction_init_op (location_t loc, enum tree_code op, tree type)
1e8e9920 4076{
df67b98c 4077 switch (op)
1e8e9920 4078 {
4079 case PLUS_EXPR:
4080 case MINUS_EXPR:
4081 case BIT_IOR_EXPR:
4082 case BIT_XOR_EXPR:
4083 case TRUTH_OR_EXPR:
4084 case TRUTH_ORIF_EXPR:
4085 case TRUTH_XOR_EXPR:
4086 case NE_EXPR:
385f3f36 4087 return build_zero_cst (type);
1e8e9920 4088
4089 case MULT_EXPR:
4090 case TRUTH_AND_EXPR:
4091 case TRUTH_ANDIF_EXPR:
4092 case EQ_EXPR:
389dd41b 4093 return fold_convert_loc (loc, type, integer_one_node);
1e8e9920 4094
4095 case BIT_AND_EXPR:
389dd41b 4096 return fold_convert_loc (loc, type, integer_minus_one_node);
1e8e9920 4097
4098 case MAX_EXPR:
4099 if (SCALAR_FLOAT_TYPE_P (type))
4100 {
4101 REAL_VALUE_TYPE max, min;
fe994837 4102 if (HONOR_INFINITIES (type))
1e8e9920 4103 {
4104 real_inf (&max);
4105 real_arithmetic (&min, NEGATE_EXPR, &max, NULL);
4106 }
4107 else
4108 real_maxval (&min, 1, TYPE_MODE (type));
4109 return build_real (type, min);
4110 }
5902cce5 4111 else if (POINTER_TYPE_P (type))
4112 {
4113 wide_int min
4114 = wi::min_value (TYPE_PRECISION (type), TYPE_SIGN (type));
4115 return wide_int_to_tree (type, min);
4116 }
1e8e9920 4117 else
4118 {
4119 gcc_assert (INTEGRAL_TYPE_P (type));
4120 return TYPE_MIN_VALUE (type);
4121 }
4122
4123 case MIN_EXPR:
4124 if (SCALAR_FLOAT_TYPE_P (type))
4125 {
4126 REAL_VALUE_TYPE max;
fe994837 4127 if (HONOR_INFINITIES (type))
1e8e9920 4128 real_inf (&max);
4129 else
4130 real_maxval (&max, 0, TYPE_MODE (type));
4131 return build_real (type, max);
4132 }
5902cce5 4133 else if (POINTER_TYPE_P (type))
4134 {
4135 wide_int max
4136 = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type));
4137 return wide_int_to_tree (type, max);
4138 }
1e8e9920 4139 else
4140 {
4141 gcc_assert (INTEGRAL_TYPE_P (type));
4142 return TYPE_MAX_VALUE (type);
4143 }
4144
4145 default:
4146 gcc_unreachable ();
4147 }
4148}
4149
df67b98c 4150/* Construct the initialization value for reduction CLAUSE. */
4151
4152tree
4153omp_reduction_init (tree clause, tree type)
4154{
4155 return omp_reduction_init_op (OMP_CLAUSE_LOCATION (clause),
4156 OMP_CLAUSE_REDUCTION_CODE (clause), type);
4157}
4158
bc7bff74 4159/* Return alignment to be assumed for var in CLAUSE, which should be
4160 OMP_CLAUSE_ALIGNED. */
4161
4162static tree
4163omp_clause_aligned_alignment (tree clause)
4164{
4165 if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause))
4166 return OMP_CLAUSE_ALIGNED_ALIGNMENT (clause);
4167
4168 /* Otherwise return implementation defined alignment. */
4169 unsigned int al = 1;
3754d046 4170 machine_mode mode, vmode;
bc7bff74 4171 int vs = targetm.vectorize.autovectorize_vector_sizes ();
4172 if (vs)
4173 vs = 1 << floor_log2 (vs);
4174 static enum mode_class classes[]
4175 = { MODE_INT, MODE_VECTOR_INT, MODE_FLOAT, MODE_VECTOR_FLOAT };
4176 for (int i = 0; i < 4; i += 2)
4177 for (mode = GET_CLASS_NARROWEST_MODE (classes[i]);
4178 mode != VOIDmode;
4179 mode = GET_MODE_WIDER_MODE (mode))
4180 {
4181 vmode = targetm.vectorize.preferred_simd_mode (mode);
4182 if (GET_MODE_CLASS (vmode) != classes[i + 1])
4183 continue;
4184 while (vs
4185 && GET_MODE_SIZE (vmode) < vs
4186 && GET_MODE_2XWIDER_MODE (vmode) != VOIDmode)
4187 vmode = GET_MODE_2XWIDER_MODE (vmode);
4188
4189 tree type = lang_hooks.types.type_for_mode (mode, 1);
4190 if (type == NULL_TREE || TYPE_MODE (type) != mode)
4191 continue;
4192 type = build_vector_type (type, GET_MODE_SIZE (vmode)
4193 / GET_MODE_SIZE (mode));
4194 if (TYPE_MODE (type) != vmode)
4195 continue;
4196 if (TYPE_ALIGN_UNIT (type) > al)
4197 al = TYPE_ALIGN_UNIT (type);
4198 }
4199 return build_int_cst (integer_type_node, al);
4200}
4201
3d483a94 4202/* Return maximum possible vectorization factor for the target. */
4203
4204static int
4205omp_max_vf (void)
4206{
4207 if (!optimize
4208 || optimize_debug
ad45e43e 4209 || !flag_tree_loop_optimize
043115ec 4210 || (!flag_tree_loop_vectorize
4211 && (global_options_set.x_flag_tree_loop_vectorize
4212 || global_options_set.x_flag_tree_vectorize)))
3d483a94 4213 return 1;
4214
4215 int vs = targetm.vectorize.autovectorize_vector_sizes ();
4216 if (vs)
4217 {
4218 vs = 1 << floor_log2 (vs);
4219 return vs;
4220 }
3754d046 4221 machine_mode vqimode = targetm.vectorize.preferred_simd_mode (QImode);
3d483a94 4222 if (GET_MODE_CLASS (vqimode) == MODE_VECTOR_INT)
4223 return GET_MODE_NUNITS (vqimode);
4224 return 1;
4225}
4226
4227/* Helper function of lower_rec_input_clauses, used for #pragma omp simd
4228 privatization. */
4229
4230static bool
4231lower_rec_simd_input_clauses (tree new_var, omp_context *ctx, int &max_vf,
4232 tree &idx, tree &lane, tree &ivar, tree &lvar)
4233{
4234 if (max_vf == 0)
4235 {
4236 max_vf = omp_max_vf ();
4237 if (max_vf > 1)
4238 {
4239 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
4240 OMP_CLAUSE_SAFELEN);
c3f3b68d 4241 if (c && TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) != INTEGER_CST)
4242 max_vf = 1;
4243 else if (c && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
4244 max_vf) == -1)
d85a2013 4245 max_vf = tree_to_shwi (OMP_CLAUSE_SAFELEN_EXPR (c));
3d483a94 4246 }
4247 if (max_vf > 1)
4248 {
f9e245b2 4249 idx = create_tmp_var (unsigned_type_node);
4250 lane = create_tmp_var (unsigned_type_node);
3d483a94 4251 }
4252 }
4253 if (max_vf == 1)
4254 return false;
4255
4256 tree atype = build_array_type_nelts (TREE_TYPE (new_var), max_vf);
f9e245b2 4257 tree avar = create_tmp_var_raw (atype);
3d483a94 4258 if (TREE_ADDRESSABLE (new_var))
4259 TREE_ADDRESSABLE (avar) = 1;
4260 DECL_ATTRIBUTES (avar)
4261 = tree_cons (get_identifier ("omp simd array"), NULL,
4262 DECL_ATTRIBUTES (avar));
4263 gimple_add_tmp_var (avar);
4264 ivar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, idx,
4265 NULL_TREE, NULL_TREE);
4266 lvar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, lane,
4267 NULL_TREE, NULL_TREE);
bc7bff74 4268 if (DECL_P (new_var))
4269 {
4270 SET_DECL_VALUE_EXPR (new_var, lvar);
4271 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4272 }
3d483a94 4273 return true;
4274}
4275
2712b6de 4276/* Helper function of lower_rec_input_clauses. For a reference
4277 in simd reduction, add an underlying variable it will reference. */
4278
4279static void
4280handle_simd_reference (location_t loc, tree new_vard, gimple_seq *ilist)
4281{
4282 tree z = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard)));
4283 if (TREE_CONSTANT (z))
4284 {
43895be5 4285 z = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_vard)),
4286 get_name (new_vard));
2712b6de 4287 gimple_add_tmp_var (z);
4288 TREE_ADDRESSABLE (z) = 1;
4289 z = build_fold_addr_expr_loc (loc, z);
4290 gimplify_assign (new_vard, z, ilist);
4291 }
4292}
4293
1e8e9920 4294/* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
4295 from the receiver (aka child) side and initializers for REFERENCE_TYPE
4296 private variables. Initialization statements go in ILIST, while calls
4297 to destructors go in DLIST. */
4298
4299static void
75a70cf9 4300lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
bc7bff74 4301 omp_context *ctx, struct omp_for_data *fd)
1e8e9920 4302{
c2f47e15 4303 tree c, dtor, copyin_seq, x, ptr;
1e8e9920 4304 bool copyin_by_ref = false;
f49d7bb5 4305 bool lastprivate_firstprivate = false;
bc7bff74 4306 bool reduction_omp_orig_ref = false;
1e8e9920 4307 int pass;
3d483a94 4308 bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
10c55644 4309 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD);
3d483a94 4310 int max_vf = 0;
4311 tree lane = NULL_TREE, idx = NULL_TREE;
4312 tree ivar = NULL_TREE, lvar = NULL_TREE;
4313 gimple_seq llist[2] = { NULL, NULL };
1e8e9920 4314
1e8e9920 4315 copyin_seq = NULL;
4316
3d483a94 4317 /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
4318 with data sharing clauses referencing variable sized vars. That
4319 is unnecessarily hard to support and very unlikely to result in
4320 vectorized code anyway. */
4321 if (is_simd)
4322 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4323 switch (OMP_CLAUSE_CODE (c))
4324 {
9580cb79 4325 case OMP_CLAUSE_LINEAR:
4326 if (OMP_CLAUSE_LINEAR_ARRAY (c))
4327 max_vf = 1;
4328 /* FALLTHRU */
3d483a94 4329 case OMP_CLAUSE_PRIVATE:
4330 case OMP_CLAUSE_FIRSTPRIVATE:
4331 case OMP_CLAUSE_LASTPRIVATE:
3d483a94 4332 if (is_variable_sized (OMP_CLAUSE_DECL (c)))
4333 max_vf = 1;
4334 break;
43895be5 4335 case OMP_CLAUSE_REDUCTION:
4336 if (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF
4337 || is_variable_sized (OMP_CLAUSE_DECL (c)))
4338 max_vf = 1;
4339 break;
3d483a94 4340 default:
4341 continue;
4342 }
4343
1e8e9920 4344 /* Do all the fixed sized types in the first pass, and the variable sized
4345 types in the second pass. This makes sure that the scalar arguments to
48e1416a 4346 the variable sized types are processed before we use them in the
1e8e9920 4347 variable sized operations. */
4348 for (pass = 0; pass < 2; ++pass)
4349 {
4350 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4351 {
55d6e7cd 4352 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
1e8e9920 4353 tree var, new_var;
4354 bool by_ref;
389dd41b 4355 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
1e8e9920 4356
4357 switch (c_kind)
4358 {
4359 case OMP_CLAUSE_PRIVATE:
4360 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
4361 continue;
4362 break;
4363 case OMP_CLAUSE_SHARED:
bc7bff74 4364 /* Ignore shared directives in teams construct. */
4365 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
4366 continue;
f49d7bb5 4367 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
4368 {
43895be5 4369 gcc_assert (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c)
4370 || is_global_var (OMP_CLAUSE_DECL (c)));
f49d7bb5 4371 continue;
4372 }
1e8e9920 4373 case OMP_CLAUSE_FIRSTPRIVATE:
1e8e9920 4374 case OMP_CLAUSE_COPYIN:
43895be5 4375 break;
bc7bff74 4376 case OMP_CLAUSE_LINEAR:
43895be5 4377 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c)
4378 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
4379 lastprivate_firstprivate = true;
bc7bff74 4380 break;
1e8e9920 4381 case OMP_CLAUSE_REDUCTION:
bc7bff74 4382 if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
4383 reduction_omp_orig_ref = true;
1e8e9920 4384 break;
bc7bff74 4385 case OMP_CLAUSE__LOOPTEMP_:
43895be5 4386 /* Handle _looptemp_ clauses only on parallel/task. */
bc7bff74 4387 if (fd)
4388 continue;
3d483a94 4389 break;
df2c34fc 4390 case OMP_CLAUSE_LASTPRIVATE:
f49d7bb5 4391 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4392 {
4393 lastprivate_firstprivate = true;
43895be5 4394 if (pass != 0 || is_taskloop_ctx (ctx))
f49d7bb5 4395 continue;
4396 }
cf5f881f 4397 /* Even without corresponding firstprivate, if
4398 decl is Fortran allocatable, it needs outer var
4399 reference. */
4400 else if (pass == 0
4401 && lang_hooks.decls.omp_private_outer_ref
4402 (OMP_CLAUSE_DECL (c)))
4403 lastprivate_firstprivate = true;
df2c34fc 4404 break;
bc7bff74 4405 case OMP_CLAUSE_ALIGNED:
4406 if (pass == 0)
4407 continue;
4408 var = OMP_CLAUSE_DECL (c);
4409 if (TREE_CODE (TREE_TYPE (var)) == POINTER_TYPE
4410 && !is_global_var (var))
4411 {
4412 new_var = maybe_lookup_decl (var, ctx);
4413 if (new_var == NULL_TREE)
4414 new_var = maybe_lookup_decl_in_outer_ctx (var, ctx);
4415 x = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
4416 x = build_call_expr_loc (clause_loc, x, 2, new_var,
4417 omp_clause_aligned_alignment (c));
4418 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
4419 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
4420 gimplify_and_add (x, ilist);
4421 }
4422 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
4423 && is_global_var (var))
4424 {
4425 tree ptype = build_pointer_type (TREE_TYPE (var)), t, t2;
4426 new_var = lookup_decl (var, ctx);
4427 t = maybe_lookup_decl_in_outer_ctx (var, ctx);
4428 t = build_fold_addr_expr_loc (clause_loc, t);
4429 t2 = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
4430 t = build_call_expr_loc (clause_loc, t2, 2, t,
4431 omp_clause_aligned_alignment (c));
4432 t = fold_convert_loc (clause_loc, ptype, t);
f9e245b2 4433 x = create_tmp_var (ptype);
bc7bff74 4434 t = build2 (MODIFY_EXPR, ptype, x, t);
4435 gimplify_and_add (t, ilist);
4436 t = build_simple_mem_ref_loc (clause_loc, x);
4437 SET_DECL_VALUE_EXPR (new_var, t);
4438 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4439 }
4440 continue;
1e8e9920 4441 default:
4442 continue;
4443 }
4444
4445 new_var = var = OMP_CLAUSE_DECL (c);
43895be5 4446 if (c_kind == OMP_CLAUSE_REDUCTION && TREE_CODE (var) == MEM_REF)
4447 {
4448 var = TREE_OPERAND (var, 0);
9561765e 4449 if (TREE_CODE (var) == POINTER_PLUS_EXPR)
4450 var = TREE_OPERAND (var, 0);
43895be5 4451 if (TREE_CODE (var) == INDIRECT_REF
4452 || TREE_CODE (var) == ADDR_EXPR)
4453 var = TREE_OPERAND (var, 0);
4454 if (is_variable_sized (var))
4455 {
4456 gcc_assert (DECL_HAS_VALUE_EXPR_P (var));
4457 var = DECL_VALUE_EXPR (var);
4458 gcc_assert (TREE_CODE (var) == INDIRECT_REF);
4459 var = TREE_OPERAND (var, 0);
4460 gcc_assert (DECL_P (var));
4461 }
4462 new_var = var;
4463 }
1e8e9920 4464 if (c_kind != OMP_CLAUSE_COPYIN)
4465 new_var = lookup_decl (var, ctx);
4466
4467 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
4468 {
4469 if (pass != 0)
4470 continue;
4471 }
43895be5 4472 /* C/C++ array section reductions. */
4473 else if (c_kind == OMP_CLAUSE_REDUCTION
4474 && var != OMP_CLAUSE_DECL (c))
1e8e9920 4475 {
4476 if (pass == 0)
4477 continue;
4478
9561765e 4479 tree bias = TREE_OPERAND (OMP_CLAUSE_DECL (c), 1);
43895be5 4480 tree orig_var = TREE_OPERAND (OMP_CLAUSE_DECL (c), 0);
9561765e 4481 if (TREE_CODE (orig_var) == POINTER_PLUS_EXPR)
4482 {
4483 tree b = TREE_OPERAND (orig_var, 1);
4484 b = maybe_lookup_decl (b, ctx);
4485 if (b == NULL)
4486 {
4487 b = TREE_OPERAND (orig_var, 1);
4488 b = maybe_lookup_decl_in_outer_ctx (b, ctx);
4489 }
4490 if (integer_zerop (bias))
4491 bias = b;
4492 else
4493 {
4494 bias = fold_convert_loc (clause_loc,
4495 TREE_TYPE (b), bias);
4496 bias = fold_build2_loc (clause_loc, PLUS_EXPR,
4497 TREE_TYPE (b), b, bias);
4498 }
4499 orig_var = TREE_OPERAND (orig_var, 0);
4500 }
43895be5 4501 if (TREE_CODE (orig_var) == INDIRECT_REF
4502 || TREE_CODE (orig_var) == ADDR_EXPR)
4503 orig_var = TREE_OPERAND (orig_var, 0);
4504 tree d = OMP_CLAUSE_DECL (c);
4505 tree type = TREE_TYPE (d);
4506 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
4507 tree v = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
4508 const char *name = get_name (orig_var);
4509 if (TREE_CONSTANT (v))
fd6481cf 4510 {
43895be5 4511 x = create_tmp_var_raw (type, name);
4512 gimple_add_tmp_var (x);
4513 TREE_ADDRESSABLE (x) = 1;
4514 x = build_fold_addr_expr_loc (clause_loc, x);
4515 }
4516 else
4517 {
4518 tree atmp
4519 = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
4520 tree t = maybe_lookup_decl (v, ctx);
4521 if (t)
4522 v = t;
4523 else
4524 v = maybe_lookup_decl_in_outer_ctx (v, ctx);
4525 gimplify_expr (&v, ilist, NULL, is_gimple_val, fb_rvalue);
4526 t = fold_build2_loc (clause_loc, PLUS_EXPR,
4527 TREE_TYPE (v), v,
4528 build_int_cst (TREE_TYPE (v), 1));
4529 t = fold_build2_loc (clause_loc, MULT_EXPR,
4530 TREE_TYPE (v), t,
4531 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4532 tree al = size_int (TYPE_ALIGN (TREE_TYPE (type)));
4533 x = build_call_expr_loc (clause_loc, atmp, 2, t, al);
4534 }
4535
4536 tree ptype = build_pointer_type (TREE_TYPE (type));
4537 x = fold_convert_loc (clause_loc, ptype, x);
4538 tree y = create_tmp_var (ptype, name);
4539 gimplify_assign (y, x, ilist);
4540 x = y;
9561765e 4541 tree yb = y;
4542
4543 if (!integer_zerop (bias))
4544 {
219e09fc 4545 bias = fold_convert_loc (clause_loc, pointer_sized_int_node,
4546 bias);
4547 yb = fold_convert_loc (clause_loc, pointer_sized_int_node,
4548 x);
4549 yb = fold_build2_loc (clause_loc, MINUS_EXPR,
4550 pointer_sized_int_node, yb, bias);
4551 x = fold_convert_loc (clause_loc, TREE_TYPE (x), yb);
9561765e 4552 yb = create_tmp_var (ptype, name);
4553 gimplify_assign (yb, x, ilist);
4554 x = yb;
4555 }
4556
4557 d = TREE_OPERAND (d, 0);
4558 if (TREE_CODE (d) == POINTER_PLUS_EXPR)
4559 d = TREE_OPERAND (d, 0);
4560 if (TREE_CODE (d) == ADDR_EXPR)
43895be5 4561 {
4562 if (orig_var != var)
4563 {
4564 gcc_assert (is_variable_sized (orig_var));
4565 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var),
4566 x);
4567 gimplify_assign (new_var, x, ilist);
4568 tree new_orig_var = lookup_decl (orig_var, ctx);
4569 tree t = build_fold_indirect_ref (new_var);
4570 DECL_IGNORED_P (new_var) = 0;
4571 TREE_THIS_NOTRAP (t);
4572 SET_DECL_VALUE_EXPR (new_orig_var, t);
4573 DECL_HAS_VALUE_EXPR_P (new_orig_var) = 1;
4574 }
4575 else
4576 {
4577 x = build2 (MEM_REF, TREE_TYPE (new_var), x,
4578 build_int_cst (ptype, 0));
4579 SET_DECL_VALUE_EXPR (new_var, x);
4580 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4581 }
4582 }
4583 else
4584 {
4585 gcc_assert (orig_var == var);
9561765e 4586 if (TREE_CODE (d) == INDIRECT_REF)
43895be5 4587 {
4588 x = create_tmp_var (ptype, name);
4589 TREE_ADDRESSABLE (x) = 1;
9561765e 4590 gimplify_assign (x, yb, ilist);
43895be5 4591 x = build_fold_addr_expr_loc (clause_loc, x);
4592 }
4593 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
4594 gimplify_assign (new_var, x, ilist);
4595 }
4596 tree y1 = create_tmp_var (ptype, NULL);
4597 gimplify_assign (y1, y, ilist);
4598 tree i2 = NULL_TREE, y2 = NULL_TREE;
4599 tree body2 = NULL_TREE, end2 = NULL_TREE;
4600 tree y3 = NULL_TREE, y4 = NULL_TREE;
4601 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) || is_simd)
4602 {
4603 y2 = create_tmp_var (ptype, NULL);
4604 gimplify_assign (y2, y, ilist);
4605 tree ref = build_outer_var_ref (var, ctx);
4606 /* For ref build_outer_var_ref already performs this. */
9561765e 4607 if (TREE_CODE (d) == INDIRECT_REF)
43895be5 4608 gcc_assert (is_reference (var));
9561765e 4609 else if (TREE_CODE (d) == ADDR_EXPR)
43895be5 4610 ref = build_fold_addr_expr (ref);
4611 else if (is_reference (var))
4612 ref = build_fold_addr_expr (ref);
4613 ref = fold_convert_loc (clause_loc, ptype, ref);
4614 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
4615 && OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
4616 {
4617 y3 = create_tmp_var (ptype, NULL);
4618 gimplify_assign (y3, unshare_expr (ref), ilist);
4619 }
4620 if (is_simd)
4621 {
4622 y4 = create_tmp_var (ptype, NULL);
4623 gimplify_assign (y4, ref, dlist);
4624 }
4625 }
4626 tree i = create_tmp_var (TREE_TYPE (v), NULL);
4627 gimplify_assign (i, build_int_cst (TREE_TYPE (v), 0), ilist);
4628 tree body = create_artificial_label (UNKNOWN_LOCATION);
4629 tree end = create_artificial_label (UNKNOWN_LOCATION);
4630 gimple_seq_add_stmt (ilist, gimple_build_label (body));
4631 if (y2)
4632 {
4633 i2 = create_tmp_var (TREE_TYPE (v), NULL);
4634 gimplify_assign (i2, build_int_cst (TREE_TYPE (v), 0), dlist);
4635 body2 = create_artificial_label (UNKNOWN_LOCATION);
4636 end2 = create_artificial_label (UNKNOWN_LOCATION);
4637 gimple_seq_add_stmt (dlist, gimple_build_label (body2));
4638 }
4639 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4640 {
4641 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
4642 tree decl_placeholder
4643 = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c);
4644 SET_DECL_VALUE_EXPR (decl_placeholder,
4645 build_simple_mem_ref (y1));
4646 DECL_HAS_VALUE_EXPR_P (decl_placeholder) = 1;
4647 SET_DECL_VALUE_EXPR (placeholder,
4648 y3 ? build_simple_mem_ref (y3)
4649 : error_mark_node);
4650 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
4651 x = lang_hooks.decls.omp_clause_default_ctor
4652 (c, build_simple_mem_ref (y1),
4653 y3 ? build_simple_mem_ref (y3) : NULL_TREE);
4654 if (x)
4655 gimplify_and_add (x, ilist);
4656 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
4657 {
4658 gimple_seq tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
4659 lower_omp (&tseq, ctx);
4660 gimple_seq_add_seq (ilist, tseq);
4661 }
4662 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
4663 if (is_simd)
4664 {
4665 SET_DECL_VALUE_EXPR (decl_placeholder,
4666 build_simple_mem_ref (y2));
4667 SET_DECL_VALUE_EXPR (placeholder,
4668 build_simple_mem_ref (y4));
4669 gimple_seq tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
4670 lower_omp (&tseq, ctx);
4671 gimple_seq_add_seq (dlist, tseq);
4672 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4673 }
4674 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
4675 DECL_HAS_VALUE_EXPR_P (decl_placeholder) = 0;
4676 x = lang_hooks.decls.omp_clause_dtor
4677 (c, build_simple_mem_ref (y2));
4678 if (x)
4679 {
4680 gimple_seq tseq = NULL;
4681 dtor = x;
4682 gimplify_stmt (&dtor, &tseq);
4683 gimple_seq_add_seq (dlist, tseq);
4684 }
4685 }
4686 else
4687 {
4688 x = omp_reduction_init (c, TREE_TYPE (type));
4689 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
4690
4691 /* reduction(-:var) sums up the partial results, so it
4692 acts identically to reduction(+:var). */
4693 if (code == MINUS_EXPR)
4694 code = PLUS_EXPR;
4695
4696 gimplify_assign (build_simple_mem_ref (y1), x, ilist);
4697 if (is_simd)
4698 {
4699 x = build2 (code, TREE_TYPE (type),
4700 build_simple_mem_ref (y4),
4701 build_simple_mem_ref (y2));
4702 gimplify_assign (build_simple_mem_ref (y4), x, dlist);
4703 }
4704 }
4705 gimple *g
4706 = gimple_build_assign (y1, POINTER_PLUS_EXPR, y1,
4707 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4708 gimple_seq_add_stmt (ilist, g);
4709 if (y3)
4710 {
4711 g = gimple_build_assign (y3, POINTER_PLUS_EXPR, y3,
4712 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4713 gimple_seq_add_stmt (ilist, g);
4714 }
4715 g = gimple_build_assign (i, PLUS_EXPR, i,
4716 build_int_cst (TREE_TYPE (i), 1));
4717 gimple_seq_add_stmt (ilist, g);
4718 g = gimple_build_cond (LE_EXPR, i, v, body, end);
4719 gimple_seq_add_stmt (ilist, g);
4720 gimple_seq_add_stmt (ilist, gimple_build_label (end));
4721 if (y2)
4722 {
4723 g = gimple_build_assign (y2, POINTER_PLUS_EXPR, y2,
4724 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4725 gimple_seq_add_stmt (dlist, g);
4726 if (y4)
4727 {
4728 g = gimple_build_assign
4729 (y4, POINTER_PLUS_EXPR, y4,
4730 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4731 gimple_seq_add_stmt (dlist, g);
4732 }
4733 g = gimple_build_assign (i2, PLUS_EXPR, i2,
4734 build_int_cst (TREE_TYPE (i2), 1));
4735 gimple_seq_add_stmt (dlist, g);
4736 g = gimple_build_cond (LE_EXPR, i2, v, body2, end2);
4737 gimple_seq_add_stmt (dlist, g);
4738 gimple_seq_add_stmt (dlist, gimple_build_label (end2));
4739 }
4740 continue;
4741 }
4742 else if (is_variable_sized (var))
4743 {
4744 /* For variable sized types, we need to allocate the
4745 actual storage here. Call alloca and store the
4746 result in the pointer decl that we created elsewhere. */
4747 if (pass == 0)
4748 continue;
4749
4750 if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
4751 {
4752 gcall *stmt;
4753 tree tmp, atmp;
4754
4755 ptr = DECL_VALUE_EXPR (new_var);
4756 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
4757 ptr = TREE_OPERAND (ptr, 0);
fd6481cf 4758 gcc_assert (DECL_P (ptr));
4759 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
75a70cf9 4760
4761 /* void *tmp = __builtin_alloca */
43895be5 4762 atmp = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
4763 stmt = gimple_build_call (atmp, 2, x,
4764 size_int (DECL_ALIGN (var)));
f9e245b2 4765 tmp = create_tmp_var_raw (ptr_type_node);
75a70cf9 4766 gimple_add_tmp_var (tmp);
4767 gimple_call_set_lhs (stmt, tmp);
4768
4769 gimple_seq_add_stmt (ilist, stmt);
4770
389dd41b 4771 x = fold_convert_loc (clause_loc, TREE_TYPE (ptr), tmp);
75a70cf9 4772 gimplify_assign (ptr, x, ilist);
fd6481cf 4773 }
1e8e9920 4774 }
b656be3a 4775 else if (is_reference (var) && !is_oacc_parallel (ctx))
1e8e9920 4776 {
773c5ba7 4777 /* For references that are being privatized for Fortran,
4778 allocate new backing storage for the new pointer
4779 variable. This allows us to avoid changing all the
4780 code that expects a pointer to something that expects
bc7bff74 4781 a direct variable. */
1e8e9920 4782 if (pass == 0)
4783 continue;
4784
4785 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
fd6481cf 4786 if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx))
4787 {
4788 x = build_receiver_ref (var, false, ctx);
389dd41b 4789 x = build_fold_addr_expr_loc (clause_loc, x);
fd6481cf 4790 }
4791 else if (TREE_CONSTANT (x))
1e8e9920 4792 {
2712b6de 4793 /* For reduction in SIMD loop, defer adding the
4794 initialization of the reference, because if we decide
4795 to use SIMD array for it, the initilization could cause
4796 expansion ICE. */
4797 if (c_kind == OMP_CLAUSE_REDUCTION && is_simd)
09d1c205 4798 x = NULL_TREE;
4799 else
4800 {
09d1c205 4801 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
43895be5 4802 get_name (var));
09d1c205 4803 gimple_add_tmp_var (x);
4804 TREE_ADDRESSABLE (x) = 1;
4805 x = build_fold_addr_expr_loc (clause_loc, x);
4806 }
1e8e9920 4807 }
4808 else
4809 {
43895be5 4810 tree atmp
4811 = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
4812 tree rtype = TREE_TYPE (TREE_TYPE (new_var));
4813 tree al = size_int (TYPE_ALIGN (rtype));
4814 x = build_call_expr_loc (clause_loc, atmp, 2, x, al);
1e8e9920 4815 }
4816
09d1c205 4817 if (x)
4818 {
4819 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
4820 gimplify_assign (new_var, x, ilist);
4821 }
1e8e9920 4822
182cf5a9 4823 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
1e8e9920 4824 }
4825 else if (c_kind == OMP_CLAUSE_REDUCTION
4826 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4827 {
4828 if (pass == 0)
4829 continue;
4830 }
4831 else if (pass != 0)
4832 continue;
4833
55d6e7cd 4834 switch (OMP_CLAUSE_CODE (c))
1e8e9920 4835 {
4836 case OMP_CLAUSE_SHARED:
bc7bff74 4837 /* Ignore shared directives in teams construct. */
4838 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
4839 continue;
f49d7bb5 4840 /* Shared global vars are just accessed directly. */
4841 if (is_global_var (new_var))
4842 break;
43895be5 4843 /* For taskloop firstprivate/lastprivate, represented
4844 as firstprivate and shared clause on the task, new_var
4845 is the firstprivate var. */
4846 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
4847 break;
1e8e9920 4848 /* Set up the DECL_VALUE_EXPR for shared variables now. This
4849 needs to be delayed until after fixup_child_record_type so
4850 that we get the correct type during the dereference. */
e8a588af 4851 by_ref = use_pointer_for_field (var, ctx);
1e8e9920 4852 x = build_receiver_ref (var, by_ref, ctx);
4853 SET_DECL_VALUE_EXPR (new_var, x);
4854 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4855
4856 /* ??? If VAR is not passed by reference, and the variable
4857 hasn't been initialized yet, then we'll get a warning for
4858 the store into the omp_data_s structure. Ideally, we'd be
48e1416a 4859 able to notice this and not store anything at all, but
1e8e9920 4860 we're generating code too early. Suppress the warning. */
4861 if (!by_ref)
4862 TREE_NO_WARNING (var) = 1;
4863 break;
4864
4865 case OMP_CLAUSE_LASTPRIVATE:
4866 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4867 break;
4868 /* FALLTHRU */
4869
4870 case OMP_CLAUSE_PRIVATE:
fd6481cf 4871 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE)
4872 x = build_outer_var_ref (var, ctx);
4873 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
4874 {
4875 if (is_task_ctx (ctx))
4876 x = build_receiver_ref (var, false, ctx);
4877 else
4878 x = build_outer_var_ref (var, ctx);
4879 }
4880 else
4881 x = NULL;
3d483a94 4882 do_private:
bc7bff74 4883 tree nx;
43895be5 4884 nx = lang_hooks.decls.omp_clause_default_ctor
4885 (c, unshare_expr (new_var), x);
3d483a94 4886 if (is_simd)
4887 {
4888 tree y = lang_hooks.decls.omp_clause_dtor (c, new_var);
bc7bff74 4889 if ((TREE_ADDRESSABLE (new_var) || nx || y
3d483a94 4890 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
4891 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4892 idx, lane, ivar, lvar))
4893 {
bc7bff74 4894 if (nx)
3d483a94 4895 x = lang_hooks.decls.omp_clause_default_ctor
4896 (c, unshare_expr (ivar), x);
bc7bff74 4897 if (nx && x)
3d483a94 4898 gimplify_and_add (x, &llist[0]);
4899 if (y)
4900 {
4901 y = lang_hooks.decls.omp_clause_dtor (c, ivar);
4902 if (y)
4903 {
4904 gimple_seq tseq = NULL;
4905
4906 dtor = y;
4907 gimplify_stmt (&dtor, &tseq);
4908 gimple_seq_add_seq (&llist[1], tseq);
4909 }
4910 }
4911 break;
4912 }
4913 }
bc7bff74 4914 if (nx)
4915 gimplify_and_add (nx, ilist);
1e8e9920 4916 /* FALLTHRU */
4917
4918 do_dtor:
4919 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
4920 if (x)
4921 {
75a70cf9 4922 gimple_seq tseq = NULL;
4923
1e8e9920 4924 dtor = x;
75a70cf9 4925 gimplify_stmt (&dtor, &tseq);
e3a19533 4926 gimple_seq_add_seq (dlist, tseq);
1e8e9920 4927 }
4928 break;
4929
3d483a94 4930 case OMP_CLAUSE_LINEAR:
4931 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c))
4932 goto do_firstprivate;
4933 if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
4934 x = NULL;
4935 else
4936 x = build_outer_var_ref (var, ctx);
4937 goto do_private;
4938
1e8e9920 4939 case OMP_CLAUSE_FIRSTPRIVATE:
fd6481cf 4940 if (is_task_ctx (ctx))
4941 {
4942 if (is_reference (var) || is_variable_sized (var))
4943 goto do_dtor;
4944 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var,
4945 ctx))
4946 || use_pointer_for_field (var, NULL))
4947 {
4948 x = build_receiver_ref (var, false, ctx);
4949 SET_DECL_VALUE_EXPR (new_var, x);
4950 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4951 goto do_dtor;
4952 }
4953 }
3d483a94 4954 do_firstprivate:
1e8e9920 4955 x = build_outer_var_ref (var, ctx);
3d483a94 4956 if (is_simd)
4957 {
bc7bff74 4958 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
4959 && gimple_omp_for_combined_into_p (ctx->stmt))
4960 {
9580cb79 4961 tree t = OMP_CLAUSE_LINEAR_STEP (c);
4962 tree stept = TREE_TYPE (t);
4963 tree ct = find_omp_clause (clauses,
4964 OMP_CLAUSE__LOOPTEMP_);
4965 gcc_assert (ct);
4966 tree l = OMP_CLAUSE_DECL (ct);
e471cc6f 4967 tree n1 = fd->loop.n1;
4968 tree step = fd->loop.step;
4969 tree itype = TREE_TYPE (l);
4970 if (POINTER_TYPE_P (itype))
4971 itype = signed_type_for (itype);
4972 l = fold_build2 (MINUS_EXPR, itype, l, n1);
4973 if (TYPE_UNSIGNED (itype)
4974 && fd->loop.cond_code == GT_EXPR)
4975 l = fold_build2 (TRUNC_DIV_EXPR, itype,
4976 fold_build1 (NEGATE_EXPR, itype, l),
4977 fold_build1 (NEGATE_EXPR,
4978 itype, step));
4979 else
4980 l = fold_build2 (TRUNC_DIV_EXPR, itype, l, step);
bc7bff74 4981 t = fold_build2 (MULT_EXPR, stept,
4982 fold_convert (stept, l), t);
9580cb79 4983
4984 if (OMP_CLAUSE_LINEAR_ARRAY (c))
4985 {
4986 x = lang_hooks.decls.omp_clause_linear_ctor
4987 (c, new_var, x, t);
4988 gimplify_and_add (x, ilist);
4989 goto do_dtor;
4990 }
4991
bc7bff74 4992 if (POINTER_TYPE_P (TREE_TYPE (x)))
4993 x = fold_build2 (POINTER_PLUS_EXPR,
4994 TREE_TYPE (x), x, t);
4995 else
4996 x = fold_build2 (PLUS_EXPR, TREE_TYPE (x), x, t);
4997 }
4998
3d483a94 4999 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
5000 || TREE_ADDRESSABLE (new_var))
5001 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
5002 idx, lane, ivar, lvar))
5003 {
5004 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR)
5005 {
f9e245b2 5006 tree iv = create_tmp_var (TREE_TYPE (new_var));
3d483a94 5007 x = lang_hooks.decls.omp_clause_copy_ctor (c, iv, x);
5008 gimplify_and_add (x, ilist);
5009 gimple_stmt_iterator gsi
5010 = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
1a91d914 5011 gassign *g
3d483a94 5012 = gimple_build_assign (unshare_expr (lvar), iv);
5013 gsi_insert_before_without_update (&gsi, g,
5014 GSI_SAME_STMT);
9580cb79 5015 tree t = OMP_CLAUSE_LINEAR_STEP (c);
3d483a94 5016 enum tree_code code = PLUS_EXPR;
5017 if (POINTER_TYPE_P (TREE_TYPE (new_var)))
5018 code = POINTER_PLUS_EXPR;
e9cf809e 5019 g = gimple_build_assign (iv, code, iv, t);
3d483a94 5020 gsi_insert_before_without_update (&gsi, g,
5021 GSI_SAME_STMT);
5022 break;
5023 }
5024 x = lang_hooks.decls.omp_clause_copy_ctor
5025 (c, unshare_expr (ivar), x);
5026 gimplify_and_add (x, &llist[0]);
5027 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
5028 if (x)
5029 {
5030 gimple_seq tseq = NULL;
5031
5032 dtor = x;
5033 gimplify_stmt (&dtor, &tseq);
5034 gimple_seq_add_seq (&llist[1], tseq);
5035 }
5036 break;
5037 }
5038 }
43895be5 5039 x = lang_hooks.decls.omp_clause_copy_ctor
5040 (c, unshare_expr (new_var), x);
1e8e9920 5041 gimplify_and_add (x, ilist);
5042 goto do_dtor;
1e8e9920 5043
bc7bff74 5044 case OMP_CLAUSE__LOOPTEMP_:
43895be5 5045 gcc_assert (is_taskreg_ctx (ctx));
bc7bff74 5046 x = build_outer_var_ref (var, ctx);
5047 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
5048 gimplify_and_add (x, ilist);
5049 break;
5050
1e8e9920 5051 case OMP_CLAUSE_COPYIN:
e8a588af 5052 by_ref = use_pointer_for_field (var, NULL);
1e8e9920 5053 x = build_receiver_ref (var, by_ref, ctx);
5054 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
5055 append_to_statement_list (x, &copyin_seq);
5056 copyin_by_ref |= by_ref;
5057 break;
5058
5059 case OMP_CLAUSE_REDUCTION:
641a0fa1 5060 /* OpenACC reductions are initialized using the
5061 GOACC_REDUCTION internal function. */
5062 if (is_gimple_omp_oacc (ctx->stmt))
5063 break;
1e8e9920 5064 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
5065 {
fd6481cf 5066 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
42acab1c 5067 gimple *tseq;
fd6481cf 5068 x = build_outer_var_ref (var, ctx);
5069
bc7bff74 5070 if (is_reference (var)
5071 && !useless_type_conversion_p (TREE_TYPE (placeholder),
5072 TREE_TYPE (x)))
389dd41b 5073 x = build_fold_addr_expr_loc (clause_loc, x);
fd6481cf 5074 SET_DECL_VALUE_EXPR (placeholder, x);
5075 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
bc7bff74 5076 tree new_vard = new_var;
5077 if (is_reference (var))
5078 {
5079 gcc_assert (TREE_CODE (new_var) == MEM_REF);
5080 new_vard = TREE_OPERAND (new_var, 0);
5081 gcc_assert (DECL_P (new_vard));
5082 }
3d483a94 5083 if (is_simd
5084 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
5085 idx, lane, ivar, lvar))
5086 {
bc7bff74 5087 if (new_vard == new_var)
5088 {
5089 gcc_assert (DECL_VALUE_EXPR (new_var) == lvar);
5090 SET_DECL_VALUE_EXPR (new_var, ivar);
5091 }
5092 else
5093 {
5094 SET_DECL_VALUE_EXPR (new_vard,
5095 build_fold_addr_expr (ivar));
5096 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
5097 }
5098 x = lang_hooks.decls.omp_clause_default_ctor
5099 (c, unshare_expr (ivar),
5100 build_outer_var_ref (var, ctx));
5101 if (x)
5102 gimplify_and_add (x, &llist[0]);
5103 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
5104 {
5105 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
5106 lower_omp (&tseq, ctx);
5107 gimple_seq_add_seq (&llist[0], tseq);
5108 }
5109 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
5110 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
5111 lower_omp (&tseq, ctx);
5112 gimple_seq_add_seq (&llist[1], tseq);
5113 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
5114 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
5115 if (new_vard == new_var)
5116 SET_DECL_VALUE_EXPR (new_var, lvar);
5117 else
5118 SET_DECL_VALUE_EXPR (new_vard,
5119 build_fold_addr_expr (lvar));
5120 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
5121 if (x)
5122 {
5123 tseq = NULL;
5124 dtor = x;
5125 gimplify_stmt (&dtor, &tseq);
5126 gimple_seq_add_seq (&llist[1], tseq);
5127 }
5128 break;
5129 }
09d1c205 5130 /* If this is a reference to constant size reduction var
5131 with placeholder, we haven't emitted the initializer
5132 for it because it is undesirable if SIMD arrays are used.
5133 But if they aren't used, we need to emit the deferred
5134 initialization now. */
5135 else if (is_reference (var) && is_simd)
2712b6de 5136 handle_simd_reference (clause_loc, new_vard, ilist);
bc7bff74 5137 x = lang_hooks.decls.omp_clause_default_ctor
cf5f881f 5138 (c, unshare_expr (new_var),
5139 build_outer_var_ref (var, ctx));
bc7bff74 5140 if (x)
5141 gimplify_and_add (x, ilist);
5142 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
5143 {
5144 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
5145 lower_omp (&tseq, ctx);
5146 gimple_seq_add_seq (ilist, tseq);
5147 }
75a70cf9 5148 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
bc7bff74 5149 if (is_simd)
5150 {
5151 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
5152 lower_omp (&tseq, ctx);
5153 gimple_seq_add_seq (dlist, tseq);
5154 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
5155 }
fd6481cf 5156 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
bc7bff74 5157 goto do_dtor;
1e8e9920 5158 }
5159 else
5160 {
5161 x = omp_reduction_init (c, TREE_TYPE (new_var));
5162 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
c22ad515 5163 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
5164
5165 /* reduction(-:var) sums up the partial results, so it
5166 acts identically to reduction(+:var). */
5167 if (code == MINUS_EXPR)
5168 code = PLUS_EXPR;
5169
2712b6de 5170 tree new_vard = new_var;
5171 if (is_simd && is_reference (var))
5172 {
5173 gcc_assert (TREE_CODE (new_var) == MEM_REF);
5174 new_vard = TREE_OPERAND (new_var, 0);
5175 gcc_assert (DECL_P (new_vard));
5176 }
3d483a94 5177 if (is_simd
5178 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
5179 idx, lane, ivar, lvar))
5180 {
3d483a94 5181 tree ref = build_outer_var_ref (var, ctx);
5182
5183 gimplify_assign (unshare_expr (ivar), x, &llist[0]);
5184
3d483a94 5185 x = build2 (code, TREE_TYPE (ref), ref, ivar);
5186 ref = build_outer_var_ref (var, ctx);
5187 gimplify_assign (ref, x, &llist[1]);
2712b6de 5188
5189 if (new_vard != new_var)
5190 {
5191 SET_DECL_VALUE_EXPR (new_vard,
5192 build_fold_addr_expr (lvar));
5193 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
5194 }
3d483a94 5195 }
5196 else
5197 {
2712b6de 5198 if (is_reference (var) && is_simd)
5199 handle_simd_reference (clause_loc, new_vard, ilist);
3d483a94 5200 gimplify_assign (new_var, x, ilist);
5201 if (is_simd)
c22ad515 5202 {
5203 tree ref = build_outer_var_ref (var, ctx);
5204
5205 x = build2 (code, TREE_TYPE (ref), ref, new_var);
5206 ref = build_outer_var_ref (var, ctx);
5207 gimplify_assign (ref, x, dlist);
5208 }
3d483a94 5209 }
1e8e9920 5210 }
5211 break;
5212
5213 default:
5214 gcc_unreachable ();
5215 }
5216 }
5217 }
5218
3d483a94 5219 if (lane)
5220 {
5221 tree uid = create_tmp_var (ptr_type_node, "simduid");
8e1a382d 5222 /* Don't want uninit warnings on simduid, it is always uninitialized,
5223 but we use it not for the value, but for the DECL_UID only. */
5224 TREE_NO_WARNING (uid) = 1;
42acab1c 5225 gimple *g
3d483a94 5226 = gimple_build_call_internal (IFN_GOMP_SIMD_LANE, 1, uid);
5227 gimple_call_set_lhs (g, lane);
5228 gimple_stmt_iterator gsi = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
5229 gsi_insert_before_without_update (&gsi, g, GSI_SAME_STMT);
5230 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SIMDUID_);
5231 OMP_CLAUSE__SIMDUID__DECL (c) = uid;
5232 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
5233 gimple_omp_for_set_clauses (ctx->stmt, c);
e9cf809e 5234 g = gimple_build_assign (lane, INTEGER_CST,
5235 build_int_cst (unsigned_type_node, 0));
3d483a94 5236 gimple_seq_add_stmt (ilist, g);
5237 for (int i = 0; i < 2; i++)
5238 if (llist[i])
5239 {
f9e245b2 5240 tree vf = create_tmp_var (unsigned_type_node);
3d483a94 5241 g = gimple_build_call_internal (IFN_GOMP_SIMD_VF, 1, uid);
5242 gimple_call_set_lhs (g, vf);
5243 gimple_seq *seq = i == 0 ? ilist : dlist;
5244 gimple_seq_add_stmt (seq, g);
5245 tree t = build_int_cst (unsigned_type_node, 0);
e9cf809e 5246 g = gimple_build_assign (idx, INTEGER_CST, t);
3d483a94 5247 gimple_seq_add_stmt (seq, g);
5248 tree body = create_artificial_label (UNKNOWN_LOCATION);
5249 tree header = create_artificial_label (UNKNOWN_LOCATION);
5250 tree end = create_artificial_label (UNKNOWN_LOCATION);
5251 gimple_seq_add_stmt (seq, gimple_build_goto (header));
5252 gimple_seq_add_stmt (seq, gimple_build_label (body));
5253 gimple_seq_add_seq (seq, llist[i]);
5254 t = build_int_cst (unsigned_type_node, 1);
e9cf809e 5255 g = gimple_build_assign (idx, PLUS_EXPR, idx, t);
3d483a94 5256 gimple_seq_add_stmt (seq, g);
5257 gimple_seq_add_stmt (seq, gimple_build_label (header));
5258 g = gimple_build_cond (LT_EXPR, idx, vf, body, end);
5259 gimple_seq_add_stmt (seq, g);
5260 gimple_seq_add_stmt (seq, gimple_build_label (end));
5261 }
5262 }
5263
1e8e9920 5264 /* The copyin sequence is not to be executed by the main thread, since
5265 that would result in self-copies. Perhaps not visible to scalars,
5266 but it certainly is to C++ operator=. */
5267 if (copyin_seq)
5268 {
b9a16870 5269 x = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM),
5270 0);
1e8e9920 5271 x = build2 (NE_EXPR, boolean_type_node, x,
5272 build_int_cst (TREE_TYPE (x), 0));
5273 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
5274 gimplify_and_add (x, ilist);
5275 }
5276
5277 /* If any copyin variable is passed by reference, we must ensure the
5278 master thread doesn't modify it before it is copied over in all
f49d7bb5 5279 threads. Similarly for variables in both firstprivate and
5280 lastprivate clauses we need to ensure the lastprivate copying
bc7bff74 5281 happens after firstprivate copying in all threads. And similarly
5282 for UDRs if initializer expression refers to omp_orig. */
5283 if (copyin_by_ref || lastprivate_firstprivate || reduction_omp_orig_ref)
3d483a94 5284 {
5285 /* Don't add any barrier for #pragma omp simd or
5286 #pragma omp distribute. */
5287 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
7c01fa6c 5288 || gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_FOR)
bc7bff74 5289 gimple_seq_add_stmt (ilist, build_omp_barrier (NULL_TREE));
3d483a94 5290 }
5291
5292 /* If max_vf is non-zero, then we can use only a vectorization factor
5293 up to the max_vf we chose. So stick it into the safelen clause. */
5294 if (max_vf)
5295 {
5296 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
5297 OMP_CLAUSE_SAFELEN);
5298 if (c == NULL_TREE
c3f3b68d 5299 || (TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) == INTEGER_CST
5300 && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
5301 max_vf) == 1))
3d483a94 5302 {
5303 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_SAFELEN);
5304 OMP_CLAUSE_SAFELEN_EXPR (c) = build_int_cst (integer_type_node,
5305 max_vf);
5306 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
5307 gimple_omp_for_set_clauses (ctx->stmt, c);
5308 }
5309 }
1e8e9920 5310}
5311
773c5ba7 5312
1e8e9920 5313/* Generate code to implement the LASTPRIVATE clauses. This is used for
5314 both parallel and workshare constructs. PREDICATE may be NULL if it's
5315 always true. */
5316
5317static void
75a70cf9 5318lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
bc7bff74 5319 omp_context *ctx)
1e8e9920 5320{
3d483a94 5321 tree x, c, label = NULL, orig_clauses = clauses;
fd6481cf 5322 bool par_clauses = false;
3d483a94 5323 tree simduid = NULL, lastlane = NULL;
1e8e9920 5324
3d483a94 5325 /* Early exit if there are no lastprivate or linear clauses. */
5326 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
5327 if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LASTPRIVATE
5328 || (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LINEAR
5329 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses)))
5330 break;
1e8e9920 5331 if (clauses == NULL)
5332 {
5333 /* If this was a workshare clause, see if it had been combined
5334 with its parallel. In that case, look for the clauses on the
5335 parallel statement itself. */
5336 if (is_parallel_ctx (ctx))
5337 return;
5338
5339 ctx = ctx->outer;
5340 if (ctx == NULL || !is_parallel_ctx (ctx))
5341 return;
5342
75a70cf9 5343 clauses = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
1e8e9920 5344 OMP_CLAUSE_LASTPRIVATE);
5345 if (clauses == NULL)
5346 return;
fd6481cf 5347 par_clauses = true;
1e8e9920 5348 }
5349
75a70cf9 5350 if (predicate)
5351 {
1a91d914 5352 gcond *stmt;
75a70cf9 5353 tree label_true, arm1, arm2;
5354
e60a6f7b 5355 label = create_artificial_label (UNKNOWN_LOCATION);
5356 label_true = create_artificial_label (UNKNOWN_LOCATION);
75a70cf9 5357 arm1 = TREE_OPERAND (predicate, 0);
5358 arm2 = TREE_OPERAND (predicate, 1);
5359 gimplify_expr (&arm1, stmt_list, NULL, is_gimple_val, fb_rvalue);
5360 gimplify_expr (&arm2, stmt_list, NULL, is_gimple_val, fb_rvalue);
5361 stmt = gimple_build_cond (TREE_CODE (predicate), arm1, arm2,
5362 label_true, label);
5363 gimple_seq_add_stmt (stmt_list, stmt);
5364 gimple_seq_add_stmt (stmt_list, gimple_build_label (label_true));
5365 }
1e8e9920 5366
3d483a94 5367 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
10c55644 5368 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3d483a94 5369 {
5370 simduid = find_omp_clause (orig_clauses, OMP_CLAUSE__SIMDUID_);
5371 if (simduid)
5372 simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
5373 }
5374
fd6481cf 5375 for (c = clauses; c ;)
1e8e9920 5376 {
5377 tree var, new_var;
389dd41b 5378 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
1e8e9920 5379
3d483a94 5380 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5381 || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
5382 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
fd6481cf 5383 {
5384 var = OMP_CLAUSE_DECL (c);
43895be5 5385 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5386 && OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c)
5387 && is_taskloop_ctx (ctx))
5388 {
5389 gcc_checking_assert (ctx->outer && is_task_ctx (ctx->outer));
5390 new_var = lookup_decl (var, ctx->outer);
5391 }
5392 else
5393 new_var = lookup_decl (var, ctx);
1e8e9920 5394
3d483a94 5395 if (simduid && DECL_HAS_VALUE_EXPR_P (new_var))
5396 {
5397 tree val = DECL_VALUE_EXPR (new_var);
5398 if (TREE_CODE (val) == ARRAY_REF
5399 && VAR_P (TREE_OPERAND (val, 0))
5400 && lookup_attribute ("omp simd array",
5401 DECL_ATTRIBUTES (TREE_OPERAND (val,
5402 0))))
5403 {
5404 if (lastlane == NULL)
5405 {
f9e245b2 5406 lastlane = create_tmp_var (unsigned_type_node);
1a91d914 5407 gcall *g
3d483a94 5408 = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE,
5409 2, simduid,
5410 TREE_OPERAND (val, 1));
5411 gimple_call_set_lhs (g, lastlane);
5412 gimple_seq_add_stmt (stmt_list, g);
5413 }
5414 new_var = build4 (ARRAY_REF, TREE_TYPE (val),
5415 TREE_OPERAND (val, 0), lastlane,
5416 NULL_TREE, NULL_TREE);
5417 }
5418 }
5419
5420 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5421 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
75a70cf9 5422 {
e3a19533 5423 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
75a70cf9 5424 gimple_seq_add_seq (stmt_list,
5425 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
3d483a94 5426 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) = NULL;
75a70cf9 5427 }
2b536a17 5428 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
5429 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
5430 {
5431 lower_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
5432 gimple_seq_add_seq (stmt_list,
5433 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c));
5434 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c) = NULL;
5435 }
1e8e9920 5436
43895be5 5437 x = NULL_TREE;
5438 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5439 && OMP_CLAUSE_LASTPRIVATE_TASKLOOP_IV (c))
5440 {
5441 gcc_checking_assert (is_taskloop_ctx (ctx));
5442 tree ovar = maybe_lookup_decl_in_outer_ctx (var,
5443 ctx->outer->outer);
5444 if (is_global_var (ovar))
5445 x = ovar;
5446 }
5447 if (!x)
5448 x = build_outer_var_ref (var, ctx, true);
fd6481cf 5449 if (is_reference (var))
182cf5a9 5450 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
fd6481cf 5451 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
75a70cf9 5452 gimplify_and_add (x, stmt_list);
fd6481cf 5453 }
5454 c = OMP_CLAUSE_CHAIN (c);
5455 if (c == NULL && !par_clauses)
5456 {
5457 /* If this was a workshare clause, see if it had been combined
5458 with its parallel. In that case, continue looking for the
5459 clauses also on the parallel statement itself. */
5460 if (is_parallel_ctx (ctx))
5461 break;
5462
5463 ctx = ctx->outer;
5464 if (ctx == NULL || !is_parallel_ctx (ctx))
5465 break;
5466
75a70cf9 5467 c = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
fd6481cf 5468 OMP_CLAUSE_LASTPRIVATE);
5469 par_clauses = true;
5470 }
1e8e9920 5471 }
5472
75a70cf9 5473 if (label)
5474 gimple_seq_add_stmt (stmt_list, gimple_build_label (label));
1e8e9920 5475}
5476
641a0fa1 5477/* Lower the OpenACC reductions of CLAUSES for compute axis LEVEL
5478 (which might be a placeholder). INNER is true if this is an inner
5479 axis of a multi-axis loop. FORK and JOIN are (optional) fork and
5480 join markers. Generate the before-loop forking sequence in
5481 FORK_SEQ and the after-loop joining sequence to JOIN_SEQ. The
5482 general form of these sequences is
5483
5484 GOACC_REDUCTION_SETUP
5485 GOACC_FORK
5486 GOACC_REDUCTION_INIT
5487 ...
5488 GOACC_REDUCTION_FINI
5489 GOACC_JOIN
5490 GOACC_REDUCTION_TEARDOWN. */
5491
ca4c3545 5492static void
641a0fa1 5493lower_oacc_reductions (location_t loc, tree clauses, tree level, bool inner,
5494 gcall *fork, gcall *join, gimple_seq *fork_seq,
5495 gimple_seq *join_seq, omp_context *ctx)
ca4c3545 5496{
641a0fa1 5497 gimple_seq before_fork = NULL;
5498 gimple_seq after_fork = NULL;
5499 gimple_seq before_join = NULL;
5500 gimple_seq after_join = NULL;
5501 tree init_code = NULL_TREE, fini_code = NULL_TREE,
5502 setup_code = NULL_TREE, teardown_code = NULL_TREE;
5503 unsigned offset = 0;
5504
5505 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
5506 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
5507 {
5508 tree orig = OMP_CLAUSE_DECL (c);
5509 tree var = maybe_lookup_decl (orig, ctx);
5510 tree ref_to_res = NULL_TREE;
5511 tree incoming, outgoing;
5512
5513 enum tree_code rcode = OMP_CLAUSE_REDUCTION_CODE (c);
5514 if (rcode == MINUS_EXPR)
5515 rcode = PLUS_EXPR;
5516 else if (rcode == TRUTH_ANDIF_EXPR)
5517 rcode = BIT_AND_EXPR;
5518 else if (rcode == TRUTH_ORIF_EXPR)
5519 rcode = BIT_IOR_EXPR;
5520 tree op = build_int_cst (unsigned_type_node, rcode);
5521
5522 if (!var)
5523 var = orig;
5524 gcc_assert (!is_reference (var));
5525
5526 incoming = outgoing = var;
5527
5528 if (!inner)
5529 {
5530 /* See if an outer construct also reduces this variable. */
5531 omp_context *outer = ctx;
ca4c3545 5532
641a0fa1 5533 while (omp_context *probe = outer->outer)
5534 {
5535 enum gimple_code type = gimple_code (probe->stmt);
5536 tree cls;
ca4c3545 5537
641a0fa1 5538 switch (type)
5539 {
5540 case GIMPLE_OMP_FOR:
5541 cls = gimple_omp_for_clauses (probe->stmt);
5542 break;
ca4c3545 5543
641a0fa1 5544 case GIMPLE_OMP_TARGET:
5545 if (gimple_omp_target_kind (probe->stmt)
5546 != GF_OMP_TARGET_KIND_OACC_PARALLEL)
5547 goto do_lookup;
ca4c3545 5548
641a0fa1 5549 cls = gimple_omp_target_clauses (probe->stmt);
5550 break;
ca4c3545 5551
641a0fa1 5552 default:
5553 goto do_lookup;
5554 }
5555
5556 outer = probe;
5557 for (; cls; cls = OMP_CLAUSE_CHAIN (cls))
5558 if (OMP_CLAUSE_CODE (cls) == OMP_CLAUSE_REDUCTION
5559 && orig == OMP_CLAUSE_DECL (cls))
5560 goto has_outer_reduction;
5561 }
ca4c3545 5562
641a0fa1 5563 do_lookup:
5564 /* This is the outermost construct with this reduction,
5565 see if there's a mapping for it. */
5566 if (gimple_code (outer->stmt) == GIMPLE_OMP_TARGET
5567 && maybe_lookup_field (orig, outer))
5568 {
5569 ref_to_res = build_receiver_ref (orig, false, outer);
5570 if (is_reference (orig))
5571 ref_to_res = build_simple_mem_ref (ref_to_res);
ca4c3545 5572
641a0fa1 5573 outgoing = var;
5574 incoming = omp_reduction_init_op (loc, rcode, TREE_TYPE (var));
5575 }
5576 else
5577 incoming = outgoing = orig;
5578
5579 has_outer_reduction:;
5580 }
ca4c3545 5581
641a0fa1 5582 if (!ref_to_res)
5583 ref_to_res = integer_zero_node;
ca4c3545 5584
641a0fa1 5585 /* Determine position in reduction buffer, which may be used
5586 by target. */
5587 enum machine_mode mode = TYPE_MODE (TREE_TYPE (var));
5588 unsigned align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
5589 offset = (offset + align - 1) & ~(align - 1);
5590 tree off = build_int_cst (sizetype, offset);
5591 offset += GET_MODE_SIZE (mode);
ca4c3545 5592
641a0fa1 5593 if (!init_code)
5594 {
5595 init_code = build_int_cst (integer_type_node,
5596 IFN_GOACC_REDUCTION_INIT);
5597 fini_code = build_int_cst (integer_type_node,
5598 IFN_GOACC_REDUCTION_FINI);
5599 setup_code = build_int_cst (integer_type_node,
5600 IFN_GOACC_REDUCTION_SETUP);
5601 teardown_code = build_int_cst (integer_type_node,
5602 IFN_GOACC_REDUCTION_TEARDOWN);
5603 }
5604
5605 tree setup_call
5606 = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
5607 TREE_TYPE (var), 6, setup_code,
5608 unshare_expr (ref_to_res),
5609 incoming, level, op, off);
5610 tree init_call
5611 = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
5612 TREE_TYPE (var), 6, init_code,
5613 unshare_expr (ref_to_res),
5614 var, level, op, off);
5615 tree fini_call
5616 = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
5617 TREE_TYPE (var), 6, fini_code,
5618 unshare_expr (ref_to_res),
5619 var, level, op, off);
5620 tree teardown_call
5621 = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
5622 TREE_TYPE (var), 6, teardown_code,
5623 ref_to_res, var, level, op, off);
5624
5625 gimplify_assign (var, setup_call, &before_fork);
5626 gimplify_assign (var, init_call, &after_fork);
5627 gimplify_assign (var, fini_call, &before_join);
5628 gimplify_assign (outgoing, teardown_call, &after_join);
5629 }
5630
5631 /* Now stitch things together. */
5632 gimple_seq_add_seq (fork_seq, before_fork);
5633 if (fork)
5634 gimple_seq_add_stmt (fork_seq, fork);
5635 gimple_seq_add_seq (fork_seq, after_fork);
5636
5637 gimple_seq_add_seq (join_seq, before_join);
5638 if (join)
5639 gimple_seq_add_stmt (join_seq, join);
5640 gimple_seq_add_seq (join_seq, after_join);
ca4c3545 5641}
773c5ba7 5642
1e8e9920 5643/* Generate code to implement the REDUCTION clauses. */
5644
5645static void
75a70cf9 5646lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
1e8e9920 5647{
75a70cf9 5648 gimple_seq sub_seq = NULL;
42acab1c 5649 gimple *stmt;
f69b8a4c 5650 tree x, c;
1e8e9920 5651 int count = 0;
5652
641a0fa1 5653 /* OpenACC loop reductions are handled elsewhere. */
5654 if (is_gimple_omp_oacc (ctx->stmt))
5655 return;
5656
3d483a94 5657 /* SIMD reductions are handled in lower_rec_input_clauses. */
5658 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
10c55644 5659 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3d483a94 5660 return;
5661
1e8e9920 5662 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
5663 update in that case, otherwise use a lock. */
5664 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
55d6e7cd 5665 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
1e8e9920 5666 {
43895be5 5667 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
5668 || TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF)
1e8e9920 5669 {
bc7bff74 5670 /* Never use OMP_ATOMIC for array reductions or UDRs. */
1e8e9920 5671 count = -1;
5672 break;
5673 }
5674 count++;
5675 }
5676
5677 if (count == 0)
5678 return;
5679
5680 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
5681 {
43895be5 5682 tree var, ref, new_var, orig_var;
1e8e9920 5683 enum tree_code code;
389dd41b 5684 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
1e8e9920 5685
55d6e7cd 5686 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
1e8e9920 5687 continue;
5688
43895be5 5689 orig_var = var = OMP_CLAUSE_DECL (c);
5690 if (TREE_CODE (var) == MEM_REF)
5691 {
5692 var = TREE_OPERAND (var, 0);
9561765e 5693 if (TREE_CODE (var) == POINTER_PLUS_EXPR)
5694 var = TREE_OPERAND (var, 0);
43895be5 5695 if (TREE_CODE (var) == INDIRECT_REF
5696 || TREE_CODE (var) == ADDR_EXPR)
5697 var = TREE_OPERAND (var, 0);
5698 orig_var = var;
5699 if (is_variable_sized (var))
5700 {
5701 gcc_assert (DECL_HAS_VALUE_EXPR_P (var));
5702 var = DECL_VALUE_EXPR (var);
5703 gcc_assert (TREE_CODE (var) == INDIRECT_REF);
5704 var = TREE_OPERAND (var, 0);
5705 gcc_assert (DECL_P (var));
5706 }
5707 }
1e8e9920 5708 new_var = lookup_decl (var, ctx);
43895be5 5709 if (var == OMP_CLAUSE_DECL (c) && is_reference (var))
182cf5a9 5710 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
1e8e9920 5711 ref = build_outer_var_ref (var, ctx);
5712 code = OMP_CLAUSE_REDUCTION_CODE (c);
773c5ba7 5713
5714 /* reduction(-:var) sums up the partial results, so it acts
5715 identically to reduction(+:var). */
1e8e9920 5716 if (code == MINUS_EXPR)
5717 code = PLUS_EXPR;
5718
641a0fa1 5719 if (count == 1)
1e8e9920 5720 {
389dd41b 5721 tree addr = build_fold_addr_expr_loc (clause_loc, ref);
1e8e9920 5722
5723 addr = save_expr (addr);
5724 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
389dd41b 5725 x = fold_build2_loc (clause_loc, code, TREE_TYPE (ref), ref, new_var);
1e8e9920 5726 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
75a70cf9 5727 gimplify_and_add (x, stmt_seqp);
1e8e9920 5728 return;
5729 }
43895be5 5730 else if (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF)
5731 {
5732 tree d = OMP_CLAUSE_DECL (c);
5733 tree type = TREE_TYPE (d);
5734 tree v = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
5735 tree i = create_tmp_var (TREE_TYPE (v), NULL);
5736 tree ptype = build_pointer_type (TREE_TYPE (type));
9561765e 5737 tree bias = TREE_OPERAND (d, 1);
5738 d = TREE_OPERAND (d, 0);
5739 if (TREE_CODE (d) == POINTER_PLUS_EXPR)
5740 {
5741 tree b = TREE_OPERAND (d, 1);
5742 b = maybe_lookup_decl (b, ctx);
5743 if (b == NULL)
5744 {
5745 b = TREE_OPERAND (d, 1);
5746 b = maybe_lookup_decl_in_outer_ctx (b, ctx);
5747 }
5748 if (integer_zerop (bias))
5749 bias = b;
5750 else
5751 {
5752 bias = fold_convert_loc (clause_loc, TREE_TYPE (b), bias);
5753 bias = fold_build2_loc (clause_loc, PLUS_EXPR,
5754 TREE_TYPE (b), b, bias);
5755 }
5756 d = TREE_OPERAND (d, 0);
5757 }
43895be5 5758 /* For ref build_outer_var_ref already performs this, so
5759 only new_var needs a dereference. */
9561765e 5760 if (TREE_CODE (d) == INDIRECT_REF)
43895be5 5761 {
5762 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
5763 gcc_assert (is_reference (var) && var == orig_var);
5764 }
9561765e 5765 else if (TREE_CODE (d) == ADDR_EXPR)
43895be5 5766 {
5767 if (orig_var == var)
5768 {
5769 new_var = build_fold_addr_expr (new_var);
5770 ref = build_fold_addr_expr (ref);
5771 }
5772 }
5773 else
5774 {
5775 gcc_assert (orig_var == var);
5776 if (is_reference (var))
5777 ref = build_fold_addr_expr (ref);
5778 }
5779 if (DECL_P (v))
5780 {
5781 tree t = maybe_lookup_decl (v, ctx);
5782 if (t)
5783 v = t;
5784 else
5785 v = maybe_lookup_decl_in_outer_ctx (v, ctx);
5786 gimplify_expr (&v, stmt_seqp, NULL, is_gimple_val, fb_rvalue);
5787 }
9561765e 5788 if (!integer_zerop (bias))
5789 {
5790 bias = fold_convert_loc (clause_loc, sizetype, bias);
5791 new_var = fold_build2_loc (clause_loc, POINTER_PLUS_EXPR,
5792 TREE_TYPE (new_var), new_var,
5793 unshare_expr (bias));
5794 ref = fold_build2_loc (clause_loc, POINTER_PLUS_EXPR,
5795 TREE_TYPE (ref), ref, bias);
5796 }
43895be5 5797 new_var = fold_convert_loc (clause_loc, ptype, new_var);
5798 ref = fold_convert_loc (clause_loc, ptype, ref);
5799 tree m = create_tmp_var (ptype, NULL);
5800 gimplify_assign (m, new_var, stmt_seqp);
5801 new_var = m;
5802 m = create_tmp_var (ptype, NULL);
5803 gimplify_assign (m, ref, stmt_seqp);
5804 ref = m;
5805 gimplify_assign (i, build_int_cst (TREE_TYPE (v), 0), stmt_seqp);
5806 tree body = create_artificial_label (UNKNOWN_LOCATION);
5807 tree end = create_artificial_label (UNKNOWN_LOCATION);
5808 gimple_seq_add_stmt (&sub_seq, gimple_build_label (body));
5809 tree priv = build_simple_mem_ref_loc (clause_loc, new_var);
5810 tree out = build_simple_mem_ref_loc (clause_loc, ref);
5811 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
5812 {
5813 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
5814 tree decl_placeholder
5815 = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c);
5816 SET_DECL_VALUE_EXPR (placeholder, out);
5817 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
5818 SET_DECL_VALUE_EXPR (decl_placeholder, priv);
5819 DECL_HAS_VALUE_EXPR_P (decl_placeholder) = 1;
5820 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
5821 gimple_seq_add_seq (&sub_seq,
5822 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
5823 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
5824 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
5825 OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c) = NULL;
5826 }
5827 else
5828 {
5829 x = build2 (code, TREE_TYPE (out), out, priv);
5830 out = unshare_expr (out);
5831 gimplify_assign (out, x, &sub_seq);
5832 }
5833 gimple *g = gimple_build_assign (new_var, POINTER_PLUS_EXPR, new_var,
5834 TYPE_SIZE_UNIT (TREE_TYPE (type)));
5835 gimple_seq_add_stmt (&sub_seq, g);
5836 g = gimple_build_assign (ref, POINTER_PLUS_EXPR, ref,
5837 TYPE_SIZE_UNIT (TREE_TYPE (type)));
5838 gimple_seq_add_stmt (&sub_seq, g);
5839 g = gimple_build_assign (i, PLUS_EXPR, i,
5840 build_int_cst (TREE_TYPE (i), 1));
5841 gimple_seq_add_stmt (&sub_seq, g);
5842 g = gimple_build_cond (LE_EXPR, i, v, body, end);
5843 gimple_seq_add_stmt (&sub_seq, g);
5844 gimple_seq_add_stmt (&sub_seq, gimple_build_label (end));
5845 }
ca4c3545 5846 else if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1e8e9920 5847 {
5848 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
5849
bc7bff74 5850 if (is_reference (var)
5851 && !useless_type_conversion_p (TREE_TYPE (placeholder),
5852 TREE_TYPE (ref)))
389dd41b 5853 ref = build_fold_addr_expr_loc (clause_loc, ref);
1e8e9920 5854 SET_DECL_VALUE_EXPR (placeholder, ref);
5855 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
e3a19533 5856 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
75a70cf9 5857 gimple_seq_add_seq (&sub_seq, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
5858 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
1e8e9920 5859 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
5860 }
5861 else
5862 {
5863 x = build2 (code, TREE_TYPE (ref), ref, new_var);
5864 ref = build_outer_var_ref (var, ctx);
75a70cf9 5865 gimplify_assign (ref, x, &sub_seq);
1e8e9920 5866 }
5867 }
5868
ca4c3545 5869 if (is_gimple_omp_oacc (ctx->stmt))
5870 return;
5871
b9a16870 5872 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START),
5873 0);
75a70cf9 5874 gimple_seq_add_stmt (stmt_seqp, stmt);
1e8e9920 5875
75a70cf9 5876 gimple_seq_add_seq (stmt_seqp, sub_seq);
1e8e9920 5877
b9a16870 5878 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END),
5879 0);
75a70cf9 5880 gimple_seq_add_stmt (stmt_seqp, stmt);
1e8e9920 5881}
5882
773c5ba7 5883
1e8e9920 5884/* Generate code to implement the COPYPRIVATE clauses. */
5885
5886static void
75a70cf9 5887lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist,
1e8e9920 5888 omp_context *ctx)
5889{
5890 tree c;
5891
5892 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
5893 {
cb561506 5894 tree var, new_var, ref, x;
1e8e9920 5895 bool by_ref;
389dd41b 5896 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
1e8e9920 5897
55d6e7cd 5898 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
1e8e9920 5899 continue;
5900
5901 var = OMP_CLAUSE_DECL (c);
e8a588af 5902 by_ref = use_pointer_for_field (var, NULL);
1e8e9920 5903
5904 ref = build_sender_ref (var, ctx);
cb561506 5905 x = new_var = lookup_decl_in_outer_ctx (var, ctx);
5906 if (by_ref)
5907 {
5908 x = build_fold_addr_expr_loc (clause_loc, new_var);
5909 x = fold_convert_loc (clause_loc, TREE_TYPE (ref), x);
5910 }
75a70cf9 5911 gimplify_assign (ref, x, slist);
1e8e9920 5912
cb561506 5913 ref = build_receiver_ref (var, false, ctx);
5914 if (by_ref)
5915 {
5916 ref = fold_convert_loc (clause_loc,
5917 build_pointer_type (TREE_TYPE (new_var)),
5918 ref);
5919 ref = build_fold_indirect_ref_loc (clause_loc, ref);
5920 }
1e8e9920 5921 if (is_reference (var))
5922 {
cb561506 5923 ref = fold_convert_loc (clause_loc, TREE_TYPE (new_var), ref);
182cf5a9 5924 ref = build_simple_mem_ref_loc (clause_loc, ref);
5925 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
1e8e9920 5926 }
cb561506 5927 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, ref);
1e8e9920 5928 gimplify_and_add (x, rlist);
5929 }
5930}
5931
773c5ba7 5932
1e8e9920 5933/* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
5934 and REDUCTION from the sender (aka parent) side. */
5935
5936static void
75a70cf9 5937lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
5938 omp_context *ctx)
1e8e9920 5939{
43895be5 5940 tree c, t;
5941 int ignored_looptemp = 0;
5942 bool is_taskloop = false;
5943
5944 /* For taskloop, ignore first two _looptemp_ clauses, those are initialized
5945 by GOMP_taskloop. */
5946 if (is_task_ctx (ctx) && gimple_omp_task_taskloop_p (ctx->stmt))
5947 {
5948 ignored_looptemp = 2;
5949 is_taskloop = true;
5950 }
1e8e9920 5951
5952 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
5953 {
773c5ba7 5954 tree val, ref, x, var;
1e8e9920 5955 bool by_ref, do_in = false, do_out = false;
389dd41b 5956 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
1e8e9920 5957
55d6e7cd 5958 switch (OMP_CLAUSE_CODE (c))
1e8e9920 5959 {
fd6481cf 5960 case OMP_CLAUSE_PRIVATE:
5961 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
5962 break;
5963 continue;
1e8e9920 5964 case OMP_CLAUSE_FIRSTPRIVATE:
5965 case OMP_CLAUSE_COPYIN:
5966 case OMP_CLAUSE_LASTPRIVATE:
5967 case OMP_CLAUSE_REDUCTION:
43895be5 5968 break;
5969 case OMP_CLAUSE_SHARED:
5970 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
5971 break;
5972 continue;
bc7bff74 5973 case OMP_CLAUSE__LOOPTEMP_:
43895be5 5974 if (ignored_looptemp)
5975 {
5976 ignored_looptemp--;
5977 continue;
5978 }
1e8e9920 5979 break;
5980 default:
5981 continue;
5982 }
5983
87b31375 5984 val = OMP_CLAUSE_DECL (c);
43895be5 5985 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
5986 && TREE_CODE (val) == MEM_REF)
5987 {
5988 val = TREE_OPERAND (val, 0);
9561765e 5989 if (TREE_CODE (val) == POINTER_PLUS_EXPR)
5990 val = TREE_OPERAND (val, 0);
43895be5 5991 if (TREE_CODE (val) == INDIRECT_REF
5992 || TREE_CODE (val) == ADDR_EXPR)
5993 val = TREE_OPERAND (val, 0);
5994 if (is_variable_sized (val))
5995 continue;
5996 }
5997
5998 /* For OMP_CLAUSE_SHARED_FIRSTPRIVATE, look beyond the
5999 outer taskloop region. */
6000 omp_context *ctx_for_o = ctx;
6001 if (is_taskloop
6002 && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
6003 && OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
6004 ctx_for_o = ctx->outer;
6005
6006 var = lookup_decl_in_outer_ctx (val, ctx_for_o);
773c5ba7 6007
f49d7bb5 6008 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
6009 && is_global_var (var))
6010 continue;
43895be5 6011
6012 t = omp_member_access_dummy_var (var);
6013 if (t)
6014 {
6015 var = DECL_VALUE_EXPR (var);
6016 tree o = maybe_lookup_decl_in_outer_ctx (t, ctx_for_o);
6017 if (o != t)
6018 var = unshare_and_remap (var, t, o);
6019 else
6020 var = unshare_expr (var);
6021 }
6022
6023 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED)
6024 {
6025 /* Handle taskloop firstprivate/lastprivate, where the
6026 lastprivate on GIMPLE_OMP_TASK is represented as
6027 OMP_CLAUSE_SHARED_FIRSTPRIVATE. */
6028 tree f = lookup_sfield ((splay_tree_key) &DECL_UID (val), ctx);
6029 x = omp_build_component_ref (ctx->sender_decl, f);
6030 if (use_pointer_for_field (val, ctx))
6031 var = build_fold_addr_expr (var);
6032 gimplify_assign (x, var, ilist);
6033 DECL_ABSTRACT_ORIGIN (f) = NULL;
6034 continue;
6035 }
6036
6037 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION
6038 || val == OMP_CLAUSE_DECL (c))
6039 && is_variable_sized (val))
1e8e9920 6040 continue;
e8a588af 6041 by_ref = use_pointer_for_field (val, NULL);
1e8e9920 6042
55d6e7cd 6043 switch (OMP_CLAUSE_CODE (c))
1e8e9920 6044 {
fd6481cf 6045 case OMP_CLAUSE_PRIVATE:
1e8e9920 6046 case OMP_CLAUSE_FIRSTPRIVATE:
6047 case OMP_CLAUSE_COPYIN:
bc7bff74 6048 case OMP_CLAUSE__LOOPTEMP_:
1e8e9920 6049 do_in = true;
6050 break;
6051
6052 case OMP_CLAUSE_LASTPRIVATE:
6053 if (by_ref || is_reference (val))
6054 {
6055 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
6056 continue;
6057 do_in = true;
6058 }
6059 else
fd6481cf 6060 {
6061 do_out = true;
6062 if (lang_hooks.decls.omp_private_outer_ref (val))
6063 do_in = true;
6064 }
1e8e9920 6065 break;
6066
6067 case OMP_CLAUSE_REDUCTION:
6068 do_in = true;
43895be5 6069 if (val == OMP_CLAUSE_DECL (c))
6070 do_out = !(by_ref || is_reference (val));
6071 else
6072 by_ref = TREE_CODE (TREE_TYPE (val)) == ARRAY_TYPE;
1e8e9920 6073 break;
6074
6075 default:
6076 gcc_unreachable ();
6077 }
6078
6079 if (do_in)
6080 {
6081 ref = build_sender_ref (val, ctx);
389dd41b 6082 x = by_ref ? build_fold_addr_expr_loc (clause_loc, var) : var;
75a70cf9 6083 gimplify_assign (ref, x, ilist);
fd6481cf 6084 if (is_task_ctx (ctx))
6085 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref, 1)) = NULL;
1e8e9920 6086 }
773c5ba7 6087
1e8e9920 6088 if (do_out)
6089 {
6090 ref = build_sender_ref (val, ctx);
75a70cf9 6091 gimplify_assign (var, ref, olist);
1e8e9920 6092 }
6093 }
6094}
6095
75a70cf9 6096/* Generate code to implement SHARED from the sender (aka parent)
6097 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
6098 list things that got automatically shared. */
1e8e9920 6099
6100static void
75a70cf9 6101lower_send_shared_vars (gimple_seq *ilist, gimple_seq *olist, omp_context *ctx)
1e8e9920 6102{
43895be5 6103 tree var, ovar, nvar, t, f, x, record_type;
1e8e9920 6104
6105 if (ctx->record_type == NULL)
6106 return;
773c5ba7 6107
fd6481cf 6108 record_type = ctx->srecord_type ? ctx->srecord_type : ctx->record_type;
1767a056 6109 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
1e8e9920 6110 {
6111 ovar = DECL_ABSTRACT_ORIGIN (f);
43895be5 6112 if (!ovar || TREE_CODE (ovar) == FIELD_DECL)
6113 continue;
6114
1e8e9920 6115 nvar = maybe_lookup_decl (ovar, ctx);
6116 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
6117 continue;
6118
773c5ba7 6119 /* If CTX is a nested parallel directive. Find the immediately
6120 enclosing parallel or workshare construct that contains a
6121 mapping for OVAR. */
87b31375 6122 var = lookup_decl_in_outer_ctx (ovar, ctx);
773c5ba7 6123
43895be5 6124 t = omp_member_access_dummy_var (var);
6125 if (t)
6126 {
6127 var = DECL_VALUE_EXPR (var);
6128 tree o = maybe_lookup_decl_in_outer_ctx (t, ctx);
6129 if (o != t)
6130 var = unshare_and_remap (var, t, o);
6131 else
6132 var = unshare_expr (var);
6133 }
6134
e8a588af 6135 if (use_pointer_for_field (ovar, ctx))
1e8e9920 6136 {
6137 x = build_sender_ref (ovar, ctx);
773c5ba7 6138 var = build_fold_addr_expr (var);
75a70cf9 6139 gimplify_assign (x, var, ilist);
1e8e9920 6140 }
6141 else
6142 {
6143 x = build_sender_ref (ovar, ctx);
75a70cf9 6144 gimplify_assign (x, var, ilist);
1e8e9920 6145
d2263ebb 6146 if (!TREE_READONLY (var)
6147 /* We don't need to receive a new reference to a result
6148 or parm decl. In fact we may not store to it as we will
6149 invalidate any pending RSO and generate wrong gimple
6150 during inlining. */
6151 && !((TREE_CODE (var) == RESULT_DECL
6152 || TREE_CODE (var) == PARM_DECL)
6153 && DECL_BY_REFERENCE (var)))
fd6481cf 6154 {
6155 x = build_sender_ref (ovar, ctx);
75a70cf9 6156 gimplify_assign (var, x, olist);
fd6481cf 6157 }
1e8e9920 6158 }
6159 }
6160}
6161
a8e785ba 6162/* Emit an OpenACC head marker call, encapulating the partitioning and
6163 other information that must be processed by the target compiler.
6164 Return the maximum number of dimensions the associated loop might
6165 be partitioned over. */
6166
6167static unsigned
6168lower_oacc_head_mark (location_t loc, tree ddvar, tree clauses,
6169 gimple_seq *seq, omp_context *ctx)
6170{
6171 unsigned levels = 0;
6172 unsigned tag = 0;
6173 tree gang_static = NULL_TREE;
6174 auto_vec<tree, 5> args;
6175
6176 args.quick_push (build_int_cst
6177 (integer_type_node, IFN_UNIQUE_OACC_HEAD_MARK));
6178 args.quick_push (ddvar);
6179 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
6180 {
6181 switch (OMP_CLAUSE_CODE (c))
6182 {
6183 case OMP_CLAUSE_GANG:
6184 tag |= OLF_DIM_GANG;
6185 gang_static = OMP_CLAUSE_GANG_STATIC_EXPR (c);
6186 /* static:* is represented by -1, and we can ignore it, as
6187 scheduling is always static. */
6188 if (gang_static && integer_minus_onep (gang_static))
6189 gang_static = NULL_TREE;
6190 levels++;
6191 break;
6192
6193 case OMP_CLAUSE_WORKER:
6194 tag |= OLF_DIM_WORKER;
6195 levels++;
6196 break;
6197
6198 case OMP_CLAUSE_VECTOR:
6199 tag |= OLF_DIM_VECTOR;
6200 levels++;
6201 break;
6202
6203 case OMP_CLAUSE_SEQ:
6204 tag |= OLF_SEQ;
6205 break;
6206
6207 case OMP_CLAUSE_AUTO:
6208 tag |= OLF_AUTO;
6209 break;
6210
6211 case OMP_CLAUSE_INDEPENDENT:
6212 tag |= OLF_INDEPENDENT;
6213 break;
6214
6215 default:
6216 continue;
6217 }
6218 }
6219
6220 if (gang_static)
6221 {
6222 if (DECL_P (gang_static))
6223 gang_static = build_outer_var_ref (gang_static, ctx);
6224 tag |= OLF_GANG_STATIC;
6225 }
6226
6227 /* In a parallel region, loops are implicitly INDEPENDENT. */
6228 omp_context *tgt = enclosing_target_ctx (ctx);
6229 if (!tgt || is_oacc_parallel (tgt))
6230 tag |= OLF_INDEPENDENT;
6231
6232 /* A loop lacking SEQ, GANG, WORKER and/or VECTOR is implicitly AUTO. */
6233 if (!(tag & (((GOMP_DIM_MASK (GOMP_DIM_MAX) - 1) << OLF_DIM_BASE)
6234 | OLF_SEQ)))
6235 tag |= OLF_AUTO;
6236
6237 /* Ensure at least one level. */
6238 if (!levels)
6239 levels++;
6240
6241 args.quick_push (build_int_cst (integer_type_node, levels));
6242 args.quick_push (build_int_cst (integer_type_node, tag));
6243 if (gang_static)
6244 args.quick_push (gang_static);
6245
6246 gcall *call = gimple_build_call_internal_vec (IFN_UNIQUE, args);
6247 gimple_set_location (call, loc);
6248 gimple_set_lhs (call, ddvar);
6249 gimple_seq_add_stmt (seq, call);
6250
6251 return levels;
6252}
6253
6254/* Emit an OpenACC lopp head or tail marker to SEQ. LEVEL is the
6255 partitioning level of the enclosed region. */
6256
6257static void
6258lower_oacc_loop_marker (location_t loc, tree ddvar, bool head,
6259 tree tofollow, gimple_seq *seq)
6260{
6261 int marker_kind = (head ? IFN_UNIQUE_OACC_HEAD_MARK
6262 : IFN_UNIQUE_OACC_TAIL_MARK);
6263 tree marker = build_int_cst (integer_type_node, marker_kind);
6264 int nargs = 2 + (tofollow != NULL_TREE);
6265 gcall *call = gimple_build_call_internal (IFN_UNIQUE, nargs,
6266 marker, ddvar, tofollow);
6267 gimple_set_location (call, loc);
6268 gimple_set_lhs (call, ddvar);
6269 gimple_seq_add_stmt (seq, call);
6270}
6271
6272/* Generate the before and after OpenACC loop sequences. CLAUSES are
6273 the loop clauses, from which we extract reductions. Initialize
6274 HEAD and TAIL. */
6275
6276static void
6277lower_oacc_head_tail (location_t loc, tree clauses,
6278 gimple_seq *head, gimple_seq *tail, omp_context *ctx)
6279{
6280 bool inner = false;
6281 tree ddvar = create_tmp_var (integer_type_node, ".data_dep");
6282 gimple_seq_add_stmt (head, gimple_build_assign (ddvar, integer_zero_node));
6283
6284 unsigned count = lower_oacc_head_mark (loc, ddvar, clauses, head, ctx);
6285 if (!count)
6286 lower_oacc_loop_marker (loc, ddvar, false, integer_zero_node, tail);
6287
6288 tree fork_kind = build_int_cst (unsigned_type_node, IFN_UNIQUE_OACC_FORK);
6289 tree join_kind = build_int_cst (unsigned_type_node, IFN_UNIQUE_OACC_JOIN);
6290
6291 for (unsigned done = 1; count; count--, done++)
6292 {
6293 gimple_seq fork_seq = NULL;
6294 gimple_seq join_seq = NULL;
6295
6296 tree place = build_int_cst (integer_type_node, -1);
6297 gcall *fork = gimple_build_call_internal (IFN_UNIQUE, 3,
6298 fork_kind, ddvar, place);
6299 gimple_set_location (fork, loc);
6300 gimple_set_lhs (fork, ddvar);
6301
6302 gcall *join = gimple_build_call_internal (IFN_UNIQUE, 3,
6303 join_kind, ddvar, place);
6304 gimple_set_location (join, loc);
6305 gimple_set_lhs (join, ddvar);
6306
6307 /* Mark the beginning of this level sequence. */
6308 if (inner)
6309 lower_oacc_loop_marker (loc, ddvar, true,
6310 build_int_cst (integer_type_node, count),
6311 &fork_seq);
6312 lower_oacc_loop_marker (loc, ddvar, false,
6313 build_int_cst (integer_type_node, done),
6314 &join_seq);
6315
641a0fa1 6316 lower_oacc_reductions (loc, clauses, place, inner,
6317 fork, join, &fork_seq, &join_seq, ctx);
a8e785ba 6318
6319 /* Append this level to head. */
6320 gimple_seq_add_seq (head, fork_seq);
6321 /* Prepend it to tail. */
6322 gimple_seq_add_seq (&join_seq, *tail);
6323 *tail = join_seq;
6324
6325 inner = true;
6326 }
6327
6328 /* Mark the end of the sequence. */
6329 lower_oacc_loop_marker (loc, ddvar, true, NULL_TREE, head);
6330 lower_oacc_loop_marker (loc, ddvar, false, NULL_TREE, tail);
6331}
75a70cf9 6332
6333/* A convenience function to build an empty GIMPLE_COND with just the
6334 condition. */
6335
1a91d914 6336static gcond *
75a70cf9 6337gimple_build_cond_empty (tree cond)
6338{
6339 enum tree_code pred_code;
6340 tree lhs, rhs;
6341
6342 gimple_cond_get_ops_from_tree (cond, &pred_code, &lhs, &rhs);
6343 return gimple_build_cond (pred_code, lhs, rhs, NULL_TREE, NULL_TREE);
6344}
6345
43895be5 6346static void expand_omp_build_assign (gimple_stmt_iterator *, tree, tree,
6347 bool = false);
75a70cf9 6348
48e1416a 6349/* Build the function calls to GOMP_parallel_start etc to actually
773c5ba7 6350 generate the parallel operation. REGION is the parallel region
6351 being expanded. BB is the block where to insert the code. WS_ARGS
6352 will be set if this is a call to a combined parallel+workshare
6353 construct, it contains the list of additional arguments needed by
6354 the workshare construct. */
1e8e9920 6355
6356static void
61e47ac8 6357expand_parallel_call (struct omp_region *region, basic_block bb,
1a91d914 6358 gomp_parallel *entry_stmt,
6359 vec<tree, va_gc> *ws_args)
1e8e9920 6360{
bc7bff74 6361 tree t, t1, t2, val, cond, c, clauses, flags;
75a70cf9 6362 gimple_stmt_iterator gsi;
42acab1c 6363 gimple *stmt;
b9a16870 6364 enum built_in_function start_ix;
6365 int start_ix2;
389dd41b 6366 location_t clause_loc;
f1f41a6c 6367 vec<tree, va_gc> *args;
773c5ba7 6368
75a70cf9 6369 clauses = gimple_omp_parallel_clauses (entry_stmt);
773c5ba7 6370
bc7bff74 6371 /* Determine what flavor of GOMP_parallel we will be
773c5ba7 6372 emitting. */
bc7bff74 6373 start_ix = BUILT_IN_GOMP_PARALLEL;
773c5ba7 6374 if (is_combined_parallel (region))
6375 {
61e47ac8 6376 switch (region->inner->type)
773c5ba7 6377 {
75a70cf9 6378 case GIMPLE_OMP_FOR:
fd6481cf 6379 gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
9561765e 6380 switch (region->inner->sched_kind)
6381 {
6382 case OMP_CLAUSE_SCHEDULE_RUNTIME:
6383 start_ix2 = 3;
6384 break;
6385 case OMP_CLAUSE_SCHEDULE_DYNAMIC:
6386 case OMP_CLAUSE_SCHEDULE_GUIDED:
6387 if (region->inner->sched_modifiers
6388 & OMP_CLAUSE_SCHEDULE_NONMONOTONIC)
6389 {
6390 start_ix2 = 3 + region->inner->sched_kind;
6391 break;
6392 }
6393 /* FALLTHRU */
6394 default:
6395 start_ix2 = region->inner->sched_kind;
6396 break;
6397 }
6398 start_ix2 += (int) BUILT_IN_GOMP_PARALLEL_LOOP_STATIC;
6399 start_ix = (enum built_in_function) start_ix2;
61e47ac8 6400 break;
75a70cf9 6401 case GIMPLE_OMP_SECTIONS:
bc7bff74 6402 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS;
61e47ac8 6403 break;
6404 default:
6405 gcc_unreachable ();
773c5ba7 6406 }
773c5ba7 6407 }
1e8e9920 6408
6409 /* By default, the value of NUM_THREADS is zero (selected at run time)
6410 and there is no conditional. */
6411 cond = NULL_TREE;
6412 val = build_int_cst (unsigned_type_node, 0);
bc7bff74 6413 flags = build_int_cst (unsigned_type_node, 0);
1e8e9920 6414
6415 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
6416 if (c)
6417 cond = OMP_CLAUSE_IF_EXPR (c);
6418
6419 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
6420 if (c)
389dd41b 6421 {
6422 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
6423 clause_loc = OMP_CLAUSE_LOCATION (c);
6424 }
6425 else
6426 clause_loc = gimple_location (entry_stmt);
1e8e9920 6427
bc7bff74 6428 c = find_omp_clause (clauses, OMP_CLAUSE_PROC_BIND);
6429 if (c)
6430 flags = build_int_cst (unsigned_type_node, OMP_CLAUSE_PROC_BIND_KIND (c));
6431
1e8e9920 6432 /* Ensure 'val' is of the correct type. */
389dd41b 6433 val = fold_convert_loc (clause_loc, unsigned_type_node, val);
1e8e9920 6434
6435 /* If we found the clause 'if (cond)', build either
6436 (cond != 0) or (cond ? val : 1u). */
6437 if (cond)
6438 {
773c5ba7 6439 cond = gimple_boolify (cond);
6440
1e8e9920 6441 if (integer_zerop (val))
389dd41b 6442 val = fold_build2_loc (clause_loc,
6443 EQ_EXPR, unsigned_type_node, cond,
79acaae1 6444 build_int_cst (TREE_TYPE (cond), 0));
1e8e9920 6445 else
773c5ba7 6446 {
6447 basic_block cond_bb, then_bb, else_bb;
79acaae1 6448 edge e, e_then, e_else;
75a70cf9 6449 tree tmp_then, tmp_else, tmp_join, tmp_var;
79acaae1 6450
f9e245b2 6451 tmp_var = create_tmp_var (TREE_TYPE (val));
79acaae1 6452 if (gimple_in_ssa_p (cfun))
6453 {
f9e245b2 6454 tmp_then = make_ssa_name (tmp_var);
6455 tmp_else = make_ssa_name (tmp_var);
6456 tmp_join = make_ssa_name (tmp_var);
79acaae1 6457 }
6458 else
6459 {
6460 tmp_then = tmp_var;
6461 tmp_else = tmp_var;
6462 tmp_join = tmp_var;
6463 }
773c5ba7 6464
4302d619 6465 e = split_block_after_labels (bb);
773c5ba7 6466 cond_bb = e->src;
6467 bb = e->dest;
6468 remove_edge (e);
6469
6470 then_bb = create_empty_bb (cond_bb);
6471 else_bb = create_empty_bb (then_bb);
79acaae1 6472 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
6473 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
773c5ba7 6474
75a70cf9 6475 stmt = gimple_build_cond_empty (cond);
6476 gsi = gsi_start_bb (cond_bb);
6477 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
773c5ba7 6478
75a70cf9 6479 gsi = gsi_start_bb (then_bb);
43895be5 6480 expand_omp_build_assign (&gsi, tmp_then, val, true);
773c5ba7 6481
75a70cf9 6482 gsi = gsi_start_bb (else_bb);
43895be5 6483 expand_omp_build_assign (&gsi, tmp_else,
6484 build_int_cst (unsigned_type_node, 1),
6485 true);
773c5ba7 6486
6487 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
6488 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
b3083327 6489 add_bb_to_loop (then_bb, cond_bb->loop_father);
6490 add_bb_to_loop (else_bb, cond_bb->loop_father);
79acaae1 6491 e_then = make_edge (then_bb, bb, EDGE_FALLTHRU);
6492 e_else = make_edge (else_bb, bb, EDGE_FALLTHRU);
773c5ba7 6493
79acaae1 6494 if (gimple_in_ssa_p (cfun))
6495 {
1a91d914 6496 gphi *phi = create_phi_node (tmp_join, bb);
60d535d2 6497 add_phi_arg (phi, tmp_then, e_then, UNKNOWN_LOCATION);
6498 add_phi_arg (phi, tmp_else, e_else, UNKNOWN_LOCATION);
79acaae1 6499 }
6500
6501 val = tmp_join;
773c5ba7 6502 }
6503
75a70cf9 6504 gsi = gsi_start_bb (bb);
6505 val = force_gimple_operand_gsi (&gsi, val, true, NULL_TREE,
6506 false, GSI_CONTINUE_LINKING);
1e8e9920 6507 }
6508
75a70cf9 6509 gsi = gsi_last_bb (bb);
6510 t = gimple_omp_parallel_data_arg (entry_stmt);
1e8e9920 6511 if (t == NULL)
c2f47e15 6512 t1 = null_pointer_node;
1e8e9920 6513 else
c2f47e15 6514 t1 = build_fold_addr_expr (t);
75a70cf9 6515 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
773c5ba7 6516
bc7bff74 6517 vec_alloc (args, 4 + vec_safe_length (ws_args));
f1f41a6c 6518 args->quick_push (t2);
6519 args->quick_push (t1);
6520 args->quick_push (val);
6521 if (ws_args)
6522 args->splice (*ws_args);
bc7bff74 6523 args->quick_push (flags);
414c3a2c 6524
6525 t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
b9a16870 6526 builtin_decl_explicit (start_ix), args);
773c5ba7 6527
75a70cf9 6528 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6529 false, GSI_CONTINUE_LINKING);
1e8e9920 6530}
6531
40750995 6532/* Insert a function call whose name is FUNC_NAME with the information from
6533 ENTRY_STMT into the basic_block BB. */
6534
6535static void
1a91d914 6536expand_cilk_for_call (basic_block bb, gomp_parallel *entry_stmt,
40750995 6537 vec <tree, va_gc> *ws_args)
6538{
6539 tree t, t1, t2;
6540 gimple_stmt_iterator gsi;
6541 vec <tree, va_gc> *args;
6542
6543 gcc_assert (vec_safe_length (ws_args) == 2);
6544 tree func_name = (*ws_args)[0];
6545 tree grain = (*ws_args)[1];
6546
6547 tree clauses = gimple_omp_parallel_clauses (entry_stmt);
6548 tree count = find_omp_clause (clauses, OMP_CLAUSE__CILK_FOR_COUNT_);
6549 gcc_assert (count != NULL_TREE);
6550 count = OMP_CLAUSE_OPERAND (count, 0);
6551
6552 gsi = gsi_last_bb (bb);
6553 t = gimple_omp_parallel_data_arg (entry_stmt);
6554 if (t == NULL)
6555 t1 = null_pointer_node;
6556 else
6557 t1 = build_fold_addr_expr (t);
6558 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
6559
6560 vec_alloc (args, 4);
6561 args->quick_push (t2);
6562 args->quick_push (t1);
6563 args->quick_push (count);
6564 args->quick_push (grain);
6565 t = build_call_expr_loc_vec (UNKNOWN_LOCATION, func_name, args);
6566
6567 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, false,
6568 GSI_CONTINUE_LINKING);
6569}
773c5ba7 6570
fd6481cf 6571/* Build the function call to GOMP_task to actually
6572 generate the task operation. BB is the block where to insert the code. */
6573
6574static void
43895be5 6575expand_task_call (struct omp_region *region, basic_block bb,
6576 gomp_task *entry_stmt)
fd6481cf 6577{
43895be5 6578 tree t1, t2, t3;
75a70cf9 6579 gimple_stmt_iterator gsi;
389dd41b 6580 location_t loc = gimple_location (entry_stmt);
fd6481cf 6581
43895be5 6582 tree clauses = gimple_omp_task_clauses (entry_stmt);
6583
6584 tree ifc = find_omp_clause (clauses, OMP_CLAUSE_IF);
6585 tree untied = find_omp_clause (clauses, OMP_CLAUSE_UNTIED);
6586 tree mergeable = find_omp_clause (clauses, OMP_CLAUSE_MERGEABLE);
6587 tree depend = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
6588 tree finalc = find_omp_clause (clauses, OMP_CLAUSE_FINAL);
6589 tree priority = find_omp_clause (clauses, OMP_CLAUSE_PRIORITY);
6590
6591 unsigned int iflags
6592 = (untied ? GOMP_TASK_FLAG_UNTIED : 0)
6593 | (mergeable ? GOMP_TASK_FLAG_MERGEABLE : 0)
6594 | (depend ? GOMP_TASK_FLAG_DEPEND : 0);
6595
6596 bool taskloop_p = gimple_omp_task_taskloop_p (entry_stmt);
6597 tree startvar = NULL_TREE, endvar = NULL_TREE, step = NULL_TREE;
6598 tree num_tasks = NULL_TREE;
6599 bool ull = false;
6600 if (taskloop_p)
6601 {
6602 gimple *g = last_stmt (region->outer->entry);
6603 gcc_assert (gimple_code (g) == GIMPLE_OMP_FOR
6604 && gimple_omp_for_kind (g) == GF_OMP_FOR_KIND_TASKLOOP);
6605 struct omp_for_data fd;
6606 extract_omp_for_data (as_a <gomp_for *> (g), &fd, NULL);
6607 startvar = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
6608 endvar = find_omp_clause (OMP_CLAUSE_CHAIN (startvar),
6609 OMP_CLAUSE__LOOPTEMP_);
6610 startvar = OMP_CLAUSE_DECL (startvar);
6611 endvar = OMP_CLAUSE_DECL (endvar);
6612 step = fold_convert_loc (loc, fd.iter_type, fd.loop.step);
6613 if (fd.loop.cond_code == LT_EXPR)
6614 iflags |= GOMP_TASK_FLAG_UP;
6615 tree tclauses = gimple_omp_for_clauses (g);
6616 num_tasks = find_omp_clause (tclauses, OMP_CLAUSE_NUM_TASKS);
6617 if (num_tasks)
6618 num_tasks = OMP_CLAUSE_NUM_TASKS_EXPR (num_tasks);
6619 else
6620 {
6621 num_tasks = find_omp_clause (tclauses, OMP_CLAUSE_GRAINSIZE);
6622 if (num_tasks)
6623 {
6624 iflags |= GOMP_TASK_FLAG_GRAINSIZE;
6625 num_tasks = OMP_CLAUSE_GRAINSIZE_EXPR (num_tasks);
6626 }
6627 else
6628 num_tasks = integer_zero_node;
6629 }
6630 num_tasks = fold_convert_loc (loc, long_integer_type_node, num_tasks);
6631 if (ifc == NULL_TREE)
6632 iflags |= GOMP_TASK_FLAG_IF;
6633 if (find_omp_clause (tclauses, OMP_CLAUSE_NOGROUP))
6634 iflags |= GOMP_TASK_FLAG_NOGROUP;
6635 ull = fd.iter_type == long_long_unsigned_type_node;
6636 }
6637 else if (priority)
6638 iflags |= GOMP_TASK_FLAG_PRIORITY;
fd6481cf 6639
43895be5 6640 tree flags = build_int_cst (unsigned_type_node, iflags);
fd6481cf 6641
43895be5 6642 tree cond = boolean_true_node;
6643 if (ifc)
6644 {
6645 if (taskloop_p)
6646 {
6647 tree t = gimple_boolify (OMP_CLAUSE_IF_EXPR (ifc));
6648 t = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, t,
6649 build_int_cst (unsigned_type_node,
6650 GOMP_TASK_FLAG_IF),
6651 build_int_cst (unsigned_type_node, 0));
6652 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node,
6653 flags, t);
6654 }
6655 else
6656 cond = gimple_boolify (OMP_CLAUSE_IF_EXPR (ifc));
6657 }
2169f33b 6658
43895be5 6659 if (finalc)
2169f33b 6660 {
43895be5 6661 tree t = gimple_boolify (OMP_CLAUSE_FINAL_EXPR (finalc));
6662 t = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, t,
6663 build_int_cst (unsigned_type_node,
6664 GOMP_TASK_FLAG_FINAL),
2169f33b 6665 build_int_cst (unsigned_type_node, 0));
43895be5 6666 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node, flags, t);
2169f33b 6667 }
bc7bff74 6668 if (depend)
6669 depend = OMP_CLAUSE_DECL (depend);
6670 else
6671 depend = build_int_cst (ptr_type_node, 0);
43895be5 6672 if (priority)
6673 priority = fold_convert (integer_type_node,
6674 OMP_CLAUSE_PRIORITY_EXPR (priority));
6675 else
6676 priority = integer_zero_node;
fd6481cf 6677
75a70cf9 6678 gsi = gsi_last_bb (bb);
43895be5 6679 tree t = gimple_omp_task_data_arg (entry_stmt);
fd6481cf 6680 if (t == NULL)
6681 t2 = null_pointer_node;
6682 else
389dd41b 6683 t2 = build_fold_addr_expr_loc (loc, t);
6684 t1 = build_fold_addr_expr_loc (loc, gimple_omp_task_child_fn (entry_stmt));
75a70cf9 6685 t = gimple_omp_task_copy_fn (entry_stmt);
fd6481cf 6686 if (t == NULL)
6687 t3 = null_pointer_node;
6688 else
389dd41b 6689 t3 = build_fold_addr_expr_loc (loc, t);
fd6481cf 6690
43895be5 6691 if (taskloop_p)
6692 t = build_call_expr (ull
6693 ? builtin_decl_explicit (BUILT_IN_GOMP_TASKLOOP_ULL)
6694 : builtin_decl_explicit (BUILT_IN_GOMP_TASKLOOP),
6695 11, t1, t2, t3,
6696 gimple_omp_task_arg_size (entry_stmt),
6697 gimple_omp_task_arg_align (entry_stmt), flags,
6698 num_tasks, priority, startvar, endvar, step);
6699 else
6700 t = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK),
6701 9, t1, t2, t3,
6702 gimple_omp_task_arg_size (entry_stmt),
6703 gimple_omp_task_arg_align (entry_stmt), cond, flags,
6704 depend, priority);
fd6481cf 6705
75a70cf9 6706 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6707 false, GSI_CONTINUE_LINKING);
fd6481cf 6708}
6709
6710
75a70cf9 6711/* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
6712 catch handler and return it. This prevents programs from violating the
6713 structured block semantics with throws. */
1e8e9920 6714
75a70cf9 6715static gimple_seq
6716maybe_catch_exception (gimple_seq body)
1e8e9920 6717{
42acab1c 6718 gimple *g;
e38def9c 6719 tree decl;
1e8e9920 6720
6721 if (!flag_exceptions)
75a70cf9 6722 return body;
1e8e9920 6723
596981c8 6724 if (lang_hooks.eh_protect_cleanup_actions != NULL)
6725 decl = lang_hooks.eh_protect_cleanup_actions ();
1e8e9920 6726 else
b9a16870 6727 decl = builtin_decl_explicit (BUILT_IN_TRAP);
75a70cf9 6728
e38def9c 6729 g = gimple_build_eh_must_not_throw (decl);
6730 g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g),
75a70cf9 6731 GIMPLE_TRY_CATCH);
1e8e9920 6732
e38def9c 6733 return gimple_seq_alloc_with_stmt (g);
1e8e9920 6734}
6735
773c5ba7 6736/* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
1e8e9920 6737
773c5ba7 6738static tree
f1f41a6c 6739vec2chain (vec<tree, va_gc> *v)
1e8e9920 6740{
2ab2ce89 6741 tree chain = NULL_TREE, t;
6742 unsigned ix;
1e8e9920 6743
f1f41a6c 6744 FOR_EACH_VEC_SAFE_ELT_REVERSE (v, ix, t)
773c5ba7 6745 {
1767a056 6746 DECL_CHAIN (t) = chain;
2ab2ce89 6747 chain = t;
773c5ba7 6748 }
1e8e9920 6749
2ab2ce89 6750 return chain;
773c5ba7 6751}
1e8e9920 6752
1e8e9920 6753
773c5ba7 6754/* Remove barriers in REGION->EXIT's block. Note that this is only
75a70cf9 6755 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
6756 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
6757 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
773c5ba7 6758 removed. */
1e8e9920 6759
773c5ba7 6760static void
6761remove_exit_barrier (struct omp_region *region)
6762{
75a70cf9 6763 gimple_stmt_iterator gsi;
773c5ba7 6764 basic_block exit_bb;
61e47ac8 6765 edge_iterator ei;
6766 edge e;
42acab1c 6767 gimple *stmt;
4a04f4b4 6768 int any_addressable_vars = -1;
1e8e9920 6769
61e47ac8 6770 exit_bb = region->exit;
1e8e9920 6771
5056ba1a 6772 /* If the parallel region doesn't return, we don't have REGION->EXIT
6773 block at all. */
6774 if (! exit_bb)
6775 return;
6776
75a70cf9 6777 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
6778 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
61e47ac8 6779 statements that can appear in between are extremely limited -- no
6780 memory operations at all. Here, we allow nothing at all, so the
75a70cf9 6781 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
6782 gsi = gsi_last_bb (exit_bb);
6783 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
6784 gsi_prev (&gsi);
6785 if (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
773c5ba7 6786 return;
1e8e9920 6787
61e47ac8 6788 FOR_EACH_EDGE (e, ei, exit_bb->preds)
6789 {
75a70cf9 6790 gsi = gsi_last_bb (e->src);
6791 if (gsi_end_p (gsi))
61e47ac8 6792 continue;
75a70cf9 6793 stmt = gsi_stmt (gsi);
4a04f4b4 6794 if (gimple_code (stmt) == GIMPLE_OMP_RETURN
6795 && !gimple_omp_return_nowait_p (stmt))
6796 {
6797 /* OpenMP 3.0 tasks unfortunately prevent this optimization
6798 in many cases. If there could be tasks queued, the barrier
6799 might be needed to let the tasks run before some local
6800 variable of the parallel that the task uses as shared
6801 runs out of scope. The task can be spawned either
6802 from within current function (this would be easy to check)
6803 or from some function it calls and gets passed an address
6804 of such a variable. */
6805 if (any_addressable_vars < 0)
6806 {
1a91d914 6807 gomp_parallel *parallel_stmt
6808 = as_a <gomp_parallel *> (last_stmt (region->entry));
4a04f4b4 6809 tree child_fun = gimple_omp_parallel_child_fn (parallel_stmt);
2ab2ce89 6810 tree local_decls, block, decl;
6811 unsigned ix;
4a04f4b4 6812
6813 any_addressable_vars = 0;
2ab2ce89 6814 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun), ix, decl)
6815 if (TREE_ADDRESSABLE (decl))
4a04f4b4 6816 {
6817 any_addressable_vars = 1;
6818 break;
6819 }
6820 for (block = gimple_block (stmt);
6821 !any_addressable_vars
6822 && block
6823 && TREE_CODE (block) == BLOCK;
6824 block = BLOCK_SUPERCONTEXT (block))
6825 {
6826 for (local_decls = BLOCK_VARS (block);
6827 local_decls;
1767a056 6828 local_decls = DECL_CHAIN (local_decls))
4a04f4b4 6829 if (TREE_ADDRESSABLE (local_decls))
6830 {
6831 any_addressable_vars = 1;
6832 break;
6833 }
6834 if (block == gimple_block (parallel_stmt))
6835 break;
6836 }
6837 }
6838 if (!any_addressable_vars)
6839 gimple_omp_return_set_nowait (stmt);
6840 }
61e47ac8 6841 }
1e8e9920 6842}
6843
61e47ac8 6844static void
6845remove_exit_barriers (struct omp_region *region)
6846{
75a70cf9 6847 if (region->type == GIMPLE_OMP_PARALLEL)
61e47ac8 6848 remove_exit_barrier (region);
6849
6850 if (region->inner)
6851 {
6852 region = region->inner;
6853 remove_exit_barriers (region);
6854 while (region->next)
6855 {
6856 region = region->next;
6857 remove_exit_barriers (region);
6858 }
6859 }
6860}
773c5ba7 6861
658b4427 6862/* Optimize omp_get_thread_num () and omp_get_num_threads ()
6863 calls. These can't be declared as const functions, but
6864 within one parallel body they are constant, so they can be
6865 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
fd6481cf 6866 which are declared const. Similarly for task body, except
6867 that in untied task omp_get_thread_num () can change at any task
6868 scheduling point. */
658b4427 6869
6870static void
42acab1c 6871optimize_omp_library_calls (gimple *entry_stmt)
658b4427 6872{
6873 basic_block bb;
75a70cf9 6874 gimple_stmt_iterator gsi;
b9a16870 6875 tree thr_num_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
6876 tree thr_num_id = DECL_ASSEMBLER_NAME (thr_num_tree);
6877 tree num_thr_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
6878 tree num_thr_id = DECL_ASSEMBLER_NAME (num_thr_tree);
75a70cf9 6879 bool untied_task = (gimple_code (entry_stmt) == GIMPLE_OMP_TASK
6880 && find_omp_clause (gimple_omp_task_clauses (entry_stmt),
fd6481cf 6881 OMP_CLAUSE_UNTIED) != NULL);
658b4427 6882
fc00614f 6883 FOR_EACH_BB_FN (bb, cfun)
75a70cf9 6884 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
658b4427 6885 {
42acab1c 6886 gimple *call = gsi_stmt (gsi);
658b4427 6887 tree decl;
6888
75a70cf9 6889 if (is_gimple_call (call)
6890 && (decl = gimple_call_fndecl (call))
658b4427 6891 && DECL_EXTERNAL (decl)
6892 && TREE_PUBLIC (decl)
6893 && DECL_INITIAL (decl) == NULL)
6894 {
6895 tree built_in;
6896
6897 if (DECL_NAME (decl) == thr_num_id)
fd6481cf 6898 {
6899 /* In #pragma omp task untied omp_get_thread_num () can change
6900 during the execution of the task region. */
6901 if (untied_task)
6902 continue;
b9a16870 6903 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
fd6481cf 6904 }
658b4427 6905 else if (DECL_NAME (decl) == num_thr_id)
b9a16870 6906 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
658b4427 6907 else
6908 continue;
6909
6910 if (DECL_ASSEMBLER_NAME (decl) != DECL_ASSEMBLER_NAME (built_in)
75a70cf9 6911 || gimple_call_num_args (call) != 0)
658b4427 6912 continue;
6913
6914 if (flag_exceptions && !TREE_NOTHROW (decl))
6915 continue;
6916
6917 if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
1ea6a73c 6918 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl)),
6919 TREE_TYPE (TREE_TYPE (built_in))))
658b4427 6920 continue;
6921
0acacf9e 6922 gimple_call_set_fndecl (call, built_in);
658b4427 6923 }
6924 }
6925}
6926
8e6b4515 6927/* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
6928 regimplified. */
6929
6930static tree
6931expand_omp_regimplify_p (tree *tp, int *walk_subtrees, void *)
6932{
6933 tree t = *tp;
6934
6935 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
6936 if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t))
6937 return t;
6938
6939 if (TREE_CODE (t) == ADDR_EXPR)
6940 recompute_tree_invariant_for_addr_expr (t);
6941
6942 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
6943 return NULL_TREE;
6944}
6945
43895be5 6946/* Prepend or append TO = FROM assignment before or after *GSI_P. */
3d483a94 6947
6948static void
43895be5 6949expand_omp_build_assign (gimple_stmt_iterator *gsi_p, tree to, tree from,
6950 bool after)
3d483a94 6951{
6952 bool simple_p = DECL_P (to) && TREE_ADDRESSABLE (to);
6953 from = force_gimple_operand_gsi (gsi_p, from, simple_p, NULL_TREE,
43895be5 6954 !after, after ? GSI_CONTINUE_LINKING
6955 : GSI_SAME_STMT);
42acab1c 6956 gimple *stmt = gimple_build_assign (to, from);
43895be5 6957 if (after)
6958 gsi_insert_after (gsi_p, stmt, GSI_CONTINUE_LINKING);
6959 else
6960 gsi_insert_before (gsi_p, stmt, GSI_SAME_STMT);
3d483a94 6961 if (walk_tree (&from, expand_omp_regimplify_p, NULL, NULL)
6962 || walk_tree (&to, expand_omp_regimplify_p, NULL, NULL))
6963 {
6964 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
6965 gimple_regimplify_operands (stmt, &gsi);
6966 }
6967}
6968
fd6481cf 6969/* Expand the OpenMP parallel or task directive starting at REGION. */
1e8e9920 6970
6971static void
fd6481cf 6972expand_omp_taskreg (struct omp_region *region)
1e8e9920 6973{
773c5ba7 6974 basic_block entry_bb, exit_bb, new_bb;
87d4aa85 6975 struct function *child_cfun;
414c3a2c 6976 tree child_fn, block, t;
75a70cf9 6977 gimple_stmt_iterator gsi;
42acab1c 6978 gimple *entry_stmt, *stmt;
773c5ba7 6979 edge e;
f1f41a6c 6980 vec<tree, va_gc> *ws_args;
773c5ba7 6981
61e47ac8 6982 entry_stmt = last_stmt (region->entry);
75a70cf9 6983 child_fn = gimple_omp_taskreg_child_fn (entry_stmt);
773c5ba7 6984 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
773c5ba7 6985
61e47ac8 6986 entry_bb = region->entry;
b25f70fd 6987 if (gimple_code (entry_stmt) == GIMPLE_OMP_TASK)
6988 exit_bb = region->cont;
6989 else
6990 exit_bb = region->exit;
773c5ba7 6991
40750995 6992 bool is_cilk_for
6993 = (flag_cilkplus
6994 && gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL
6995 && find_omp_clause (gimple_omp_parallel_clauses (entry_stmt),
6996 OMP_CLAUSE__CILK_FOR_COUNT_) != NULL_TREE);
6997
6998 if (is_cilk_for)
6999 /* If it is a _Cilk_for statement, it is modelled *like* a parallel for,
7000 and the inner statement contains the name of the built-in function
7001 and grain. */
7002 ws_args = region->inner->ws_args;
7003 else if (is_combined_parallel (region))
61e47ac8 7004 ws_args = region->ws_args;
773c5ba7 7005 else
414c3a2c 7006 ws_args = NULL;
1e8e9920 7007
61e47ac8 7008 if (child_cfun->cfg)
1e8e9920 7009 {
773c5ba7 7010 /* Due to inlining, it may happen that we have already outlined
7011 the region, in which case all we need to do is make the
7012 sub-graph unreachable and emit the parallel call. */
7013 edge entry_succ_e, exit_succ_e;
773c5ba7 7014
7015 entry_succ_e = single_succ_edge (entry_bb);
773c5ba7 7016
75a70cf9 7017 gsi = gsi_last_bb (entry_bb);
7018 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_PARALLEL
7019 || gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_TASK);
7020 gsi_remove (&gsi, true);
773c5ba7 7021
7022 new_bb = entry_bb;
03ed154b 7023 if (exit_bb)
7024 {
7025 exit_succ_e = single_succ_edge (exit_bb);
7026 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
7027 }
79acaae1 7028 remove_edge_and_dominated_blocks (entry_succ_e);
1e8e9920 7029 }
773c5ba7 7030 else
7031 {
501bdd19 7032 unsigned srcidx, dstidx, num;
2ab2ce89 7033
773c5ba7 7034 /* If the parallel region needs data sent from the parent
3480139d 7035 function, then the very first statement (except possible
7036 tree profile counter updates) of the parallel body
773c5ba7 7037 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
7038 &.OMP_DATA_O is passed as an argument to the child function,
7039 we need to replace it with the argument as seen by the child
7040 function.
7041
7042 In most cases, this will end up being the identity assignment
7043 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
7044 a function call that has been inlined, the original PARM_DECL
7045 .OMP_DATA_I may have been converted into a different local
7046 variable. In which case, we need to keep the assignment. */
75a70cf9 7047 if (gimple_omp_taskreg_data_arg (entry_stmt))
773c5ba7 7048 {
b25f70fd 7049 basic_block entry_succ_bb
7050 = single_succ_p (entry_bb) ? single_succ (entry_bb)
7051 : FALLTHRU_EDGE (entry_bb)->dest;
883f001d 7052 tree arg;
42acab1c 7053 gimple *parcopy_stmt = NULL;
1e8e9920 7054
75a70cf9 7055 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
3480139d 7056 {
42acab1c 7057 gimple *stmt;
3480139d 7058
75a70cf9 7059 gcc_assert (!gsi_end_p (gsi));
7060 stmt = gsi_stmt (gsi);
7061 if (gimple_code (stmt) != GIMPLE_ASSIGN)
cc6b725b 7062 continue;
7063
75a70cf9 7064 if (gimple_num_ops (stmt) == 2)
3480139d 7065 {
75a70cf9 7066 tree arg = gimple_assign_rhs1 (stmt);
7067
7068 /* We're ignore the subcode because we're
7069 effectively doing a STRIP_NOPS. */
7070
7071 if (TREE_CODE (arg) == ADDR_EXPR
7072 && TREE_OPERAND (arg, 0)
7073 == gimple_omp_taskreg_data_arg (entry_stmt))
7074 {
7075 parcopy_stmt = stmt;
7076 break;
7077 }
3480139d 7078 }
7079 }
79acaae1 7080
75a70cf9 7081 gcc_assert (parcopy_stmt != NULL);
79acaae1 7082 arg = DECL_ARGUMENTS (child_fn);
7083
7084 if (!gimple_in_ssa_p (cfun))
7085 {
75a70cf9 7086 if (gimple_assign_lhs (parcopy_stmt) == arg)
7087 gsi_remove (&gsi, true);
79acaae1 7088 else
75a70cf9 7089 {
7090 /* ?? Is setting the subcode really necessary ?? */
7091 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (arg));
7092 gimple_assign_set_rhs1 (parcopy_stmt, arg);
7093 }
79acaae1 7094 }
7095 else
7096 {
883f001d 7097 tree lhs = gimple_assign_lhs (parcopy_stmt);
7098 gcc_assert (SSA_NAME_VAR (lhs) == arg);
7099 /* We'd like to set the rhs to the default def in the child_fn,
7100 but it's too early to create ssa names in the child_fn.
7101 Instead, we set the rhs to the parm. In
7102 move_sese_region_to_fn, we introduce a default def for the
7103 parm, map the parm to it's default def, and once we encounter
7104 this stmt, replace the parm with the default def. */
7105 gimple_assign_set_rhs1 (parcopy_stmt, arg);
79acaae1 7106 update_stmt (parcopy_stmt);
7107 }
773c5ba7 7108 }
7109
7110 /* Declare local variables needed in CHILD_CFUN. */
7111 block = DECL_INITIAL (child_fn);
2ab2ce89 7112 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
e1a7ccb9 7113 /* The gimplifier could record temporaries in parallel/task block
7114 rather than in containing function's local_decls chain,
7115 which would mean cgraph missed finalizing them. Do it now. */
1767a056 7116 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
e1a7ccb9 7117 if (TREE_CODE (t) == VAR_DECL
7118 && TREE_STATIC (t)
7119 && !DECL_EXTERNAL (t))
97221fd7 7120 varpool_node::finalize_decl (t);
75a70cf9 7121 DECL_SAVED_TREE (child_fn) = NULL;
e3a19533 7122 /* We'll create a CFG for child_fn, so no gimple body is needed. */
7123 gimple_set_body (child_fn, NULL);
1d22f541 7124 TREE_USED (block) = 1;
773c5ba7 7125
79acaae1 7126 /* Reset DECL_CONTEXT on function arguments. */
1767a056 7127 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
773c5ba7 7128 DECL_CONTEXT (t) = child_fn;
7129
75a70cf9 7130 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
7131 so that it can be moved to the child function. */
7132 gsi = gsi_last_bb (entry_bb);
7133 stmt = gsi_stmt (gsi);
7134 gcc_assert (stmt && (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
7135 || gimple_code (stmt) == GIMPLE_OMP_TASK));
75a70cf9 7136 e = split_block (entry_bb, stmt);
923635e7 7137 gsi_remove (&gsi, true);
773c5ba7 7138 entry_bb = e->dest;
b25f70fd 7139 edge e2 = NULL;
7140 if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
7141 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7142 else
7143 {
7144 e2 = make_edge (e->src, BRANCH_EDGE (entry_bb)->dest, EDGE_ABNORMAL);
7145 gcc_assert (e2->dest == region->exit);
7146 remove_edge (BRANCH_EDGE (entry_bb));
7147 set_immediate_dominator (CDI_DOMINATORS, e2->dest, e->src);
7148 gsi = gsi_last_bb (region->exit);
7149 gcc_assert (!gsi_end_p (gsi)
7150 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
7151 gsi_remove (&gsi, true);
7152 }
773c5ba7 7153
b25f70fd 7154 /* Convert GIMPLE_OMP_{RETURN,CONTINUE} into a RETURN_EXPR. */
5056ba1a 7155 if (exit_bb)
7156 {
75a70cf9 7157 gsi = gsi_last_bb (exit_bb);
7158 gcc_assert (!gsi_end_p (gsi)
b25f70fd 7159 && (gimple_code (gsi_stmt (gsi))
7160 == (e2 ? GIMPLE_OMP_CONTINUE : GIMPLE_OMP_RETURN)));
75a70cf9 7161 stmt = gimple_build_return (NULL);
7162 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
7163 gsi_remove (&gsi, true);
5056ba1a 7164 }
79acaae1 7165
7166 /* Move the parallel region into CHILD_CFUN. */
48e1416a 7167
79acaae1 7168 if (gimple_in_ssa_p (cfun))
7169 {
bcaa2770 7170 init_tree_ssa (child_cfun);
5084b2e4 7171 init_ssa_operands (child_cfun);
7172 child_cfun->gimple_df->in_ssa_p = true;
1d22f541 7173 block = NULL_TREE;
79acaae1 7174 }
1d22f541 7175 else
75a70cf9 7176 block = gimple_block (entry_stmt);
1d22f541 7177
7178 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
79acaae1 7179 if (exit_bb)
7180 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
b25f70fd 7181 if (e2)
7182 {
7183 basic_block dest_bb = e2->dest;
7184 if (!exit_bb)
7185 make_edge (new_bb, dest_bb, EDGE_FALLTHRU);
7186 remove_edge (e2);
7187 set_immediate_dominator (CDI_DOMINATORS, dest_bb, new_bb);
7188 }
04c2922b 7189 /* When the OMP expansion process cannot guarantee an up-to-date
7190 loop tree arrange for the child function to fixup loops. */
7191 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
7192 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
79acaae1 7193
1d22f541 7194 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
f1f41a6c 7195 num = vec_safe_length (child_cfun->local_decls);
501bdd19 7196 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
7197 {
f1f41a6c 7198 t = (*child_cfun->local_decls)[srcidx];
501bdd19 7199 if (DECL_CONTEXT (t) == cfun->decl)
7200 continue;
7201 if (srcidx != dstidx)
f1f41a6c 7202 (*child_cfun->local_decls)[dstidx] = t;
501bdd19 7203 dstidx++;
7204 }
7205 if (dstidx != num)
f1f41a6c 7206 vec_safe_truncate (child_cfun->local_decls, dstidx);
1d22f541 7207
79acaae1 7208 /* Inform the callgraph about the new function. */
9918db44 7209 child_cfun->curr_properties = cfun->curr_properties;
7210 child_cfun->has_simduid_loops |= cfun->has_simduid_loops;
7211 child_cfun->has_force_vectorize_loops |= cfun->has_force_vectorize_loops;
47300487 7212 cgraph_node *node = cgraph_node::get_create (child_fn);
7213 node->parallelized_function = 1;
415d1b9a 7214 cgraph_node::add_new_function (child_fn, true);
79acaae1 7215
9561765e 7216 bool need_asm = DECL_ASSEMBLER_NAME_SET_P (current_function_decl)
7217 && !DECL_ASSEMBLER_NAME_SET_P (child_fn);
7218
79acaae1 7219 /* Fix the callgraph edges for child_cfun. Those for cfun will be
7220 fixed in a following pass. */
7221 push_cfun (child_cfun);
9561765e 7222 if (need_asm)
7223 assign_assembler_name_if_neeeded (child_fn);
7224
658b4427 7225 if (optimize)
fd6481cf 7226 optimize_omp_library_calls (entry_stmt);
35ee1c66 7227 cgraph_edge::rebuild_edges ();
fbe86b1b 7228
7229 /* Some EH regions might become dead, see PR34608. If
7230 pass_cleanup_cfg isn't the first pass to happen with the
7231 new child, these dead EH edges might cause problems.
7232 Clean them up now. */
7233 if (flag_exceptions)
7234 {
7235 basic_block bb;
fbe86b1b 7236 bool changed = false;
7237
fc00614f 7238 FOR_EACH_BB_FN (bb, cfun)
75a70cf9 7239 changed |= gimple_purge_dead_eh_edges (bb);
fbe86b1b 7240 if (changed)
7241 cleanup_tree_cfg ();
fbe86b1b 7242 }
dd277d48 7243 if (gimple_in_ssa_p (cfun))
7244 update_ssa (TODO_update_ssa);
382ecba7 7245 if (flag_checking && !loops_state_satisfies_p (LOOPS_NEED_FIXUP))
86a932e0 7246 verify_loop_structure ();
79acaae1 7247 pop_cfun ();
9561765e 7248
7249 if (dump_file && !gimple_in_ssa_p (cfun))
7250 {
7251 omp_any_child_fn_dumped = true;
7252 dump_function_header (dump_file, child_fn, dump_flags);
7253 dump_function_to_file (child_fn, dump_file, dump_flags);
7254 }
773c5ba7 7255 }
48e1416a 7256
773c5ba7 7257 /* Emit a library call to launch the children threads. */
40750995 7258 if (is_cilk_for)
1a91d914 7259 expand_cilk_for_call (new_bb,
7260 as_a <gomp_parallel *> (entry_stmt), ws_args);
40750995 7261 else if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
1a91d914 7262 expand_parallel_call (region, new_bb,
7263 as_a <gomp_parallel *> (entry_stmt), ws_args);
fd6481cf 7264 else
43895be5 7265 expand_task_call (region, new_bb, as_a <gomp_task *> (entry_stmt));
083152fb 7266 if (gimple_in_ssa_p (cfun))
7267 update_ssa (TODO_update_ssa_only_virtuals);
1e8e9920 7268}
7269
a8e785ba 7270/* Information about members of an OpenACC collapsed loop nest. */
7271
7272struct oacc_collapse
7273{
7274 tree base; /* Base value. */
7275 tree iters; /* Number of steps. */
7276 tree step; /* step size. */
7277};
7278
7279/* Helper for expand_oacc_for. Determine collapsed loop information.
7280 Fill in COUNTS array. Emit any initialization code before GSI.
7281 Return the calculated outer loop bound of BOUND_TYPE. */
7282
7283static tree
7284expand_oacc_collapse_init (const struct omp_for_data *fd,
7285 gimple_stmt_iterator *gsi,
7286 oacc_collapse *counts, tree bound_type)
7287{
7288 tree total = build_int_cst (bound_type, 1);
7289 int ix;
7290
7291 gcc_assert (integer_onep (fd->loop.step));
7292 gcc_assert (integer_zerop (fd->loop.n1));
7293
7294 for (ix = 0; ix != fd->collapse; ix++)
7295 {
7296 const omp_for_data_loop *loop = &fd->loops[ix];
7297
7298 tree iter_type = TREE_TYPE (loop->v);
7299 tree diff_type = iter_type;
7300 tree plus_type = iter_type;
7301
7302 gcc_assert (loop->cond_code == fd->loop.cond_code);
7303
7304 if (POINTER_TYPE_P (iter_type))
7305 plus_type = sizetype;
7306 if (POINTER_TYPE_P (diff_type) || TYPE_UNSIGNED (diff_type))
7307 diff_type = signed_type_for (diff_type);
7308
7309 tree b = loop->n1;
7310 tree e = loop->n2;
7311 tree s = loop->step;
7312 bool up = loop->cond_code == LT_EXPR;
7313 tree dir = build_int_cst (diff_type, up ? +1 : -1);
7314 bool negating;
7315 tree expr;
7316
7317 b = force_gimple_operand_gsi (gsi, b, true, NULL_TREE,
7318 true, GSI_SAME_STMT);
7319 e = force_gimple_operand_gsi (gsi, e, true, NULL_TREE,
7320 true, GSI_SAME_STMT);
7321
7322 /* Convert the step, avoiding possible unsigned->signed overflow. */
7323 negating = !up && TYPE_UNSIGNED (TREE_TYPE (s));
7324 if (negating)
7325 s = fold_build1 (NEGATE_EXPR, TREE_TYPE (s), s);
7326 s = fold_convert (diff_type, s);
7327 if (negating)
7328 s = fold_build1 (NEGATE_EXPR, diff_type, s);
7329 s = force_gimple_operand_gsi (gsi, s, true, NULL_TREE,
7330 true, GSI_SAME_STMT);
7331
7332 /* Determine the range, avoiding possible unsigned->signed overflow. */
7333 negating = !up && TYPE_UNSIGNED (iter_type);
7334 expr = fold_build2 (MINUS_EXPR, plus_type,
7335 fold_convert (plus_type, negating ? b : e),
7336 fold_convert (plus_type, negating ? e : b));
7337 expr = fold_convert (diff_type, expr);
7338 if (negating)
7339 expr = fold_build1 (NEGATE_EXPR, diff_type, expr);
7340 tree range = force_gimple_operand_gsi
7341 (gsi, expr, true, NULL_TREE, true, GSI_SAME_STMT);
7342
7343 /* Determine number of iterations. */
7344 expr = fold_build2 (MINUS_EXPR, diff_type, range, dir);
7345 expr = fold_build2 (PLUS_EXPR, diff_type, expr, s);
7346 expr = fold_build2 (TRUNC_DIV_EXPR, diff_type, expr, s);
7347
7348 tree iters = force_gimple_operand_gsi (gsi, expr, true, NULL_TREE,
7349 true, GSI_SAME_STMT);
7350
7351 counts[ix].base = b;
7352 counts[ix].iters = iters;
7353 counts[ix].step = s;
7354
7355 total = fold_build2 (MULT_EXPR, bound_type, total,
7356 fold_convert (bound_type, iters));
7357 }
7358
7359 return total;
7360}
7361
7362/* Emit initializers for collapsed loop members. IVAR is the outer
7363 loop iteration variable, from which collapsed loop iteration values
7364 are calculated. COUNTS array has been initialized by
7365 expand_oacc_collapse_inits. */
7366
7367static void
7368expand_oacc_collapse_vars (const struct omp_for_data *fd,
7369 gimple_stmt_iterator *gsi,
7370 const oacc_collapse *counts, tree ivar)
7371{
7372 tree ivar_type = TREE_TYPE (ivar);
7373
7374 /* The most rapidly changing iteration variable is the innermost
7375 one. */
7376 for (int ix = fd->collapse; ix--;)
7377 {
7378 const omp_for_data_loop *loop = &fd->loops[ix];
7379 const oacc_collapse *collapse = &counts[ix];
7380 tree iter_type = TREE_TYPE (loop->v);
7381 tree diff_type = TREE_TYPE (collapse->step);
7382 tree plus_type = iter_type;
7383 enum tree_code plus_code = PLUS_EXPR;
7384 tree expr;
7385
7386 if (POINTER_TYPE_P (iter_type))
7387 {
7388 plus_code = POINTER_PLUS_EXPR;
7389 plus_type = sizetype;
7390 }
7391
7392 expr = fold_build2 (TRUNC_MOD_EXPR, ivar_type, ivar,
7393 fold_convert (ivar_type, collapse->iters));
7394 expr = fold_build2 (MULT_EXPR, diff_type, fold_convert (diff_type, expr),
7395 collapse->step);
7396 expr = fold_build2 (plus_code, iter_type, collapse->base,
7397 fold_convert (plus_type, expr));
7398 expr = force_gimple_operand_gsi (gsi, expr, false, NULL_TREE,
7399 true, GSI_SAME_STMT);
7400 gassign *ass = gimple_build_assign (loop->v, expr);
7401 gsi_insert_before (gsi, ass, GSI_SAME_STMT);
7402
7403 if (ix)
7404 {
7405 expr = fold_build2 (TRUNC_DIV_EXPR, ivar_type, ivar,
7406 fold_convert (ivar_type, collapse->iters));
7407 ivar = force_gimple_operand_gsi (gsi, expr, true, NULL_TREE,
7408 true, GSI_SAME_STMT);
7409 }
7410 }
7411}
7412
773c5ba7 7413
3d483a94 7414/* Helper function for expand_omp_{for_*,simd}. If this is the outermost
7415 of the combined collapse > 1 loop constructs, generate code like:
7416 if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
7417 if (cond3 is <)
7418 adj = STEP3 - 1;
7419 else
7420 adj = STEP3 + 1;
7421 count3 = (adj + N32 - N31) / STEP3;
7422 if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
7423 if (cond2 is <)
7424 adj = STEP2 - 1;
7425 else
7426 adj = STEP2 + 1;
7427 count2 = (adj + N22 - N21) / STEP2;
7428 if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
7429 if (cond1 is <)
7430 adj = STEP1 - 1;
7431 else
7432 adj = STEP1 + 1;
7433 count1 = (adj + N12 - N11) / STEP1;
7434 count = count1 * count2 * count3;
7435 Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
7436 count = 0;
bc7bff74 7437 and set ZERO_ITER_BB to that bb. If this isn't the outermost
7438 of the combined loop constructs, just initialize COUNTS array
7439 from the _looptemp_ clauses. */
3d483a94 7440
7441/* NOTE: It *could* be better to moosh all of the BBs together,
7442 creating one larger BB with all the computation and the unexpected
7443 jump at the end. I.e.
7444
7445 bool zero3, zero2, zero1, zero;
7446
7447 zero3 = N32 c3 N31;
7448 count3 = (N32 - N31) /[cl] STEP3;
7449 zero2 = N22 c2 N21;
7450 count2 = (N22 - N21) /[cl] STEP2;
7451 zero1 = N12 c1 N11;
7452 count1 = (N12 - N11) /[cl] STEP1;
7453 zero = zero3 || zero2 || zero1;
7454 count = count1 * count2 * count3;
7455 if (__builtin_expect(zero, false)) goto zero_iter_bb;
7456
7457 After all, we expect the zero=false, and thus we expect to have to
7458 evaluate all of the comparison expressions, so short-circuiting
7459 oughtn't be a win. Since the condition isn't protecting a
7460 denominator, we're not concerned about divide-by-zero, so we can
7461 fully evaluate count even if a numerator turned out to be wrong.
7462
7463 It seems like putting this all together would create much better
7464 scheduling opportunities, and less pressure on the chip's branch
7465 predictor. */
7466
7467static void
7468expand_omp_for_init_counts (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
7469 basic_block &entry_bb, tree *counts,
43895be5 7470 basic_block &zero_iter1_bb, int &first_zero_iter1,
7471 basic_block &zero_iter2_bb, int &first_zero_iter2,
3d483a94 7472 basic_block &l2_dom_bb)
7473{
7474 tree t, type = TREE_TYPE (fd->loop.v);
3d483a94 7475 edge e, ne;
7476 int i;
7477
7478 /* Collapsed loops need work for expansion into SSA form. */
7479 gcc_assert (!gimple_in_ssa_p (cfun));
7480
bc7bff74 7481 if (gimple_omp_for_combined_into_p (fd->for_stmt)
7482 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
7483 {
43895be5 7484 gcc_assert (fd->ordered == 0);
bc7bff74 7485 /* First two _looptemp_ clauses are for istart/iend, counts[0]
7486 isn't supposed to be handled, as the inner loop doesn't
7487 use it. */
7488 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7489 OMP_CLAUSE__LOOPTEMP_);
7490 gcc_assert (innerc);
7491 for (i = 0; i < fd->collapse; i++)
7492 {
7493 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7494 OMP_CLAUSE__LOOPTEMP_);
7495 gcc_assert (innerc);
7496 if (i)
7497 counts[i] = OMP_CLAUSE_DECL (innerc);
7498 else
7499 counts[0] = NULL_TREE;
7500 }
7501 return;
7502 }
7503
43895be5 7504 for (i = fd->collapse; i < fd->ordered; i++)
7505 {
7506 tree itype = TREE_TYPE (fd->loops[i].v);
7507 counts[i] = NULL_TREE;
7508 t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
7509 fold_convert (itype, fd->loops[i].n1),
7510 fold_convert (itype, fd->loops[i].n2));
7511 if (t && integer_zerop (t))
7512 {
7513 for (i = fd->collapse; i < fd->ordered; i++)
7514 counts[i] = build_int_cst (type, 0);
7515 break;
7516 }
7517 }
7518 for (i = 0; i < (fd->ordered ? fd->ordered : fd->collapse); i++)
3d483a94 7519 {
7520 tree itype = TREE_TYPE (fd->loops[i].v);
7521
43895be5 7522 if (i >= fd->collapse && counts[i])
7523 continue;
7524 if ((SSA_VAR_P (fd->loop.n2) || i >= fd->collapse)
3d483a94 7525 && ((t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
7526 fold_convert (itype, fd->loops[i].n1),
7527 fold_convert (itype, fd->loops[i].n2)))
7528 == NULL_TREE || !integer_onep (t)))
7529 {
1a91d914 7530 gcond *cond_stmt;
3d483a94 7531 tree n1, n2;
7532 n1 = fold_convert (itype, unshare_expr (fd->loops[i].n1));
7533 n1 = force_gimple_operand_gsi (gsi, n1, true, NULL_TREE,
7534 true, GSI_SAME_STMT);
7535 n2 = fold_convert (itype, unshare_expr (fd->loops[i].n2));
7536 n2 = force_gimple_operand_gsi (gsi, n2, true, NULL_TREE,
7537 true, GSI_SAME_STMT);
1a91d914 7538 cond_stmt = gimple_build_cond (fd->loops[i].cond_code, n1, n2,
7539 NULL_TREE, NULL_TREE);
7540 gsi_insert_before (gsi, cond_stmt, GSI_SAME_STMT);
7541 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
3d483a94 7542 expand_omp_regimplify_p, NULL, NULL)
1a91d914 7543 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
3d483a94 7544 expand_omp_regimplify_p, NULL, NULL))
7545 {
1a91d914 7546 *gsi = gsi_for_stmt (cond_stmt);
7547 gimple_regimplify_operands (cond_stmt, gsi);
3d483a94 7548 }
1a91d914 7549 e = split_block (entry_bb, cond_stmt);
43895be5 7550 basic_block &zero_iter_bb
7551 = i < fd->collapse ? zero_iter1_bb : zero_iter2_bb;
7552 int &first_zero_iter
7553 = i < fd->collapse ? first_zero_iter1 : first_zero_iter2;
3d483a94 7554 if (zero_iter_bb == NULL)
7555 {
1a91d914 7556 gassign *assign_stmt;
3d483a94 7557 first_zero_iter = i;
7558 zero_iter_bb = create_empty_bb (entry_bb);
b3083327 7559 add_bb_to_loop (zero_iter_bb, entry_bb->loop_father);
3d483a94 7560 *gsi = gsi_after_labels (zero_iter_bb);
43895be5 7561 if (i < fd->collapse)
7562 assign_stmt = gimple_build_assign (fd->loop.n2,
7563 build_zero_cst (type));
7564 else
7565 {
7566 counts[i] = create_tmp_reg (type, ".count");
7567 assign_stmt
7568 = gimple_build_assign (counts[i], build_zero_cst (type));
7569 }
1a91d914 7570 gsi_insert_before (gsi, assign_stmt, GSI_SAME_STMT);
3d483a94 7571 set_immediate_dominator (CDI_DOMINATORS, zero_iter_bb,
7572 entry_bb);
7573 }
7574 ne = make_edge (entry_bb, zero_iter_bb, EDGE_FALSE_VALUE);
7575 ne->probability = REG_BR_PROB_BASE / 2000 - 1;
7576 e->flags = EDGE_TRUE_VALUE;
7577 e->probability = REG_BR_PROB_BASE - ne->probability;
7578 if (l2_dom_bb == NULL)
7579 l2_dom_bb = entry_bb;
7580 entry_bb = e->dest;
7581 *gsi = gsi_last_bb (entry_bb);
7582 }
7583
7584 if (POINTER_TYPE_P (itype))
7585 itype = signed_type_for (itype);
7586 t = build_int_cst (itype, (fd->loops[i].cond_code == LT_EXPR
7587 ? -1 : 1));
7588 t = fold_build2 (PLUS_EXPR, itype,
7589 fold_convert (itype, fd->loops[i].step), t);
7590 t = fold_build2 (PLUS_EXPR, itype, t,
7591 fold_convert (itype, fd->loops[i].n2));
7592 t = fold_build2 (MINUS_EXPR, itype, t,
7593 fold_convert (itype, fd->loops[i].n1));
7594 /* ?? We could probably use CEIL_DIV_EXPR instead of
7595 TRUNC_DIV_EXPR and adjusting by hand. Unless we can't
7596 generate the same code in the end because generically we
7597 don't know that the values involved must be negative for
7598 GT?? */
7599 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
7600 t = fold_build2 (TRUNC_DIV_EXPR, itype,
7601 fold_build1 (NEGATE_EXPR, itype, t),
7602 fold_build1 (NEGATE_EXPR, itype,
7603 fold_convert (itype,
7604 fd->loops[i].step)));
7605 else
7606 t = fold_build2 (TRUNC_DIV_EXPR, itype, t,
7607 fold_convert (itype, fd->loops[i].step));
7608 t = fold_convert (type, t);
7609 if (TREE_CODE (t) == INTEGER_CST)
7610 counts[i] = t;
7611 else
7612 {
43895be5 7613 if (i < fd->collapse || i != first_zero_iter2)
7614 counts[i] = create_tmp_reg (type, ".count");
3d483a94 7615 expand_omp_build_assign (gsi, counts[i], t);
7616 }
43895be5 7617 if (SSA_VAR_P (fd->loop.n2) && i < fd->collapse)
3d483a94 7618 {
7619 if (i == 0)
7620 t = counts[0];
7621 else
7622 t = fold_build2 (MULT_EXPR, type, fd->loop.n2, counts[i]);
7623 expand_omp_build_assign (gsi, fd->loop.n2, t);
7624 }
7625 }
7626}
7627
7628
7629/* Helper function for expand_omp_{for_*,simd}. Generate code like:
7630 T = V;
7631 V3 = N31 + (T % count3) * STEP3;
7632 T = T / count3;
7633 V2 = N21 + (T % count2) * STEP2;
7634 T = T / count2;
7635 V1 = N11 + T * STEP1;
bc7bff74 7636 if this loop doesn't have an inner loop construct combined with it.
7637 If it does have an inner loop construct combined with it and the
7638 iteration count isn't known constant, store values from counts array
7639 into its _looptemp_ temporaries instead. */
3d483a94 7640
7641static void
7642expand_omp_for_init_vars (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
42acab1c 7643 tree *counts, gimple *inner_stmt, tree startvar)
3d483a94 7644{
7645 int i;
bc7bff74 7646 if (gimple_omp_for_combined_p (fd->for_stmt))
7647 {
7648 /* If fd->loop.n2 is constant, then no propagation of the counts
7649 is needed, they are constant. */
7650 if (TREE_CODE (fd->loop.n2) == INTEGER_CST)
7651 return;
7652
43895be5 7653 tree clauses = gimple_code (inner_stmt) != GIMPLE_OMP_FOR
7654 ? gimple_omp_taskreg_clauses (inner_stmt)
bc7bff74 7655 : gimple_omp_for_clauses (inner_stmt);
7656 /* First two _looptemp_ clauses are for istart/iend, counts[0]
7657 isn't supposed to be handled, as the inner loop doesn't
7658 use it. */
7659 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
7660 gcc_assert (innerc);
7661 for (i = 0; i < fd->collapse; i++)
7662 {
7663 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7664 OMP_CLAUSE__LOOPTEMP_);
7665 gcc_assert (innerc);
7666 if (i)
7667 {
7668 tree tem = OMP_CLAUSE_DECL (innerc);
7669 tree t = fold_convert (TREE_TYPE (tem), counts[i]);
7670 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
7671 false, GSI_CONTINUE_LINKING);
1a91d914 7672 gassign *stmt = gimple_build_assign (tem, t);
bc7bff74 7673 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7674 }
7675 }
7676 return;
7677 }
7678
3d483a94 7679 tree type = TREE_TYPE (fd->loop.v);
7680 tree tem = create_tmp_reg (type, ".tem");
1a91d914 7681 gassign *stmt = gimple_build_assign (tem, startvar);
3d483a94 7682 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7683
7684 for (i = fd->collapse - 1; i >= 0; i--)
7685 {
7686 tree vtype = TREE_TYPE (fd->loops[i].v), itype, t;
7687 itype = vtype;
7688 if (POINTER_TYPE_P (vtype))
7689 itype = signed_type_for (vtype);
7690 if (i != 0)
7691 t = fold_build2 (TRUNC_MOD_EXPR, type, tem, counts[i]);
7692 else
7693 t = tem;
7694 t = fold_convert (itype, t);
7695 t = fold_build2 (MULT_EXPR, itype, t,
7696 fold_convert (itype, fd->loops[i].step));
7697 if (POINTER_TYPE_P (vtype))
7698 t = fold_build_pointer_plus (fd->loops[i].n1, t);
7699 else
7700 t = fold_build2 (PLUS_EXPR, itype, fd->loops[i].n1, t);
7701 t = force_gimple_operand_gsi (gsi, t,
7702 DECL_P (fd->loops[i].v)
7703 && TREE_ADDRESSABLE (fd->loops[i].v),
7704 NULL_TREE, false,
7705 GSI_CONTINUE_LINKING);
7706 stmt = gimple_build_assign (fd->loops[i].v, t);
7707 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7708 if (i != 0)
7709 {
7710 t = fold_build2 (TRUNC_DIV_EXPR, type, tem, counts[i]);
7711 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
7712 false, GSI_CONTINUE_LINKING);
7713 stmt = gimple_build_assign (tem, t);
7714 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7715 }
7716 }
7717}
7718
7719
7720/* Helper function for expand_omp_for_*. Generate code like:
7721 L10:
7722 V3 += STEP3;
7723 if (V3 cond3 N32) goto BODY_BB; else goto L11;
7724 L11:
7725 V3 = N31;
7726 V2 += STEP2;
7727 if (V2 cond2 N22) goto BODY_BB; else goto L12;
7728 L12:
7729 V2 = N21;
7730 V1 += STEP1;
7731 goto BODY_BB; */
7732
7733static basic_block
7734extract_omp_for_update_vars (struct omp_for_data *fd, basic_block cont_bb,
7735 basic_block body_bb)
7736{
7737 basic_block last_bb, bb, collapse_bb = NULL;
7738 int i;
7739 gimple_stmt_iterator gsi;
7740 edge e;
7741 tree t;
42acab1c 7742 gimple *stmt;
3d483a94 7743
7744 last_bb = cont_bb;
7745 for (i = fd->collapse - 1; i >= 0; i--)
7746 {
7747 tree vtype = TREE_TYPE (fd->loops[i].v);
7748
7749 bb = create_empty_bb (last_bb);
b3083327 7750 add_bb_to_loop (bb, last_bb->loop_father);
3d483a94 7751 gsi = gsi_start_bb (bb);
7752
7753 if (i < fd->collapse - 1)
7754 {
7755 e = make_edge (last_bb, bb, EDGE_FALSE_VALUE);
7756 e->probability = REG_BR_PROB_BASE / 8;
7757
7758 t = fd->loops[i + 1].n1;
7759 t = force_gimple_operand_gsi (&gsi, t,
7760 DECL_P (fd->loops[i + 1].v)
7761 && TREE_ADDRESSABLE (fd->loops[i
7762 + 1].v),
7763 NULL_TREE, false,
7764 GSI_CONTINUE_LINKING);
7765 stmt = gimple_build_assign (fd->loops[i + 1].v, t);
7766 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7767 }
7768 else
7769 collapse_bb = bb;
7770
7771 set_immediate_dominator (CDI_DOMINATORS, bb, last_bb);
7772
7773 if (POINTER_TYPE_P (vtype))
7774 t = fold_build_pointer_plus (fd->loops[i].v, fd->loops[i].step);
7775 else
7776 t = fold_build2 (PLUS_EXPR, vtype, fd->loops[i].v, fd->loops[i].step);
7777 t = force_gimple_operand_gsi (&gsi, t,
7778 DECL_P (fd->loops[i].v)
7779 && TREE_ADDRESSABLE (fd->loops[i].v),
7780 NULL_TREE, false, GSI_CONTINUE_LINKING);
7781 stmt = gimple_build_assign (fd->loops[i].v, t);
7782 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7783
7784 if (i > 0)
7785 {
7786 t = fd->loops[i].n2;
7787 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7788 false, GSI_CONTINUE_LINKING);
7789 tree v = fd->loops[i].v;
7790 if (DECL_P (v) && TREE_ADDRESSABLE (v))
7791 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
7792 false, GSI_CONTINUE_LINKING);
7793 t = fold_build2 (fd->loops[i].cond_code, boolean_type_node, v, t);
7794 stmt = gimple_build_cond_empty (t);
7795 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7796 e = make_edge (bb, body_bb, EDGE_TRUE_VALUE);
7797 e->probability = REG_BR_PROB_BASE * 7 / 8;
7798 }
7799 else
7800 make_edge (bb, body_bb, EDGE_FALLTHRU);
7801 last_bb = bb;
7802 }
7803
7804 return collapse_bb;
7805}
7806
7807
43895be5 7808/* Expand #pragma omp ordered depend(source). */
1e8e9920 7809
43895be5 7810static void
7811expand_omp_ordered_source (gimple_stmt_iterator *gsi, struct omp_for_data *fd,
7812 tree *counts, location_t loc)
7813{
7814 enum built_in_function source_ix
7815 = fd->iter_type == long_integer_type_node
7816 ? BUILT_IN_GOMP_DOACROSS_POST : BUILT_IN_GOMP_DOACROSS_ULL_POST;
7817 gimple *g
7818 = gimple_build_call (builtin_decl_explicit (source_ix), 1,
7819 build_fold_addr_expr (counts[fd->ordered]));
7820 gimple_set_location (g, loc);
7821 gsi_insert_before (gsi, g, GSI_SAME_STMT);
7822}
1e8e9920 7823
43895be5 7824/* Expand a single depend from #pragma omp ordered depend(sink:...). */
1e8e9920 7825
43895be5 7826static void
7827expand_omp_ordered_sink (gimple_stmt_iterator *gsi, struct omp_for_data *fd,
7828 tree *counts, tree c, location_t loc)
7829{
7830 auto_vec<tree, 10> args;
7831 enum built_in_function sink_ix
7832 = fd->iter_type == long_integer_type_node
7833 ? BUILT_IN_GOMP_DOACROSS_WAIT : BUILT_IN_GOMP_DOACROSS_ULL_WAIT;
7834 tree t, off, coff = NULL_TREE, deps = OMP_CLAUSE_DECL (c), cond = NULL_TREE;
7835 int i;
7836 gimple_stmt_iterator gsi2 = *gsi;
7837 bool warned_step = false;
fd6481cf 7838
43895be5 7839 for (i = 0; i < fd->ordered; i++)
7840 {
7841 off = TREE_PURPOSE (deps);
7842 if (!integer_zerop (off))
7843 {
7844 gcc_assert (fd->loops[i].cond_code == LT_EXPR
7845 || fd->loops[i].cond_code == GT_EXPR);
7846 bool forward = fd->loops[i].cond_code == LT_EXPR;
7847 if (forward ^ OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
7848 warning_at (loc, 0, "%<depend(sink)%> clause waiting for "
7849 "lexically later iteration");
7850 break;
7851 }
7852 deps = TREE_CHAIN (deps);
7853 }
7854 /* If all offsets corresponding to the collapsed loops are zero,
7855 this depend clause can be ignored. FIXME: but there is still a
7856 flush needed. We need to emit one __sync_synchronize () for it
7857 though (perhaps conditionally)? Solve this together with the
7858 conservative dependence folding optimization.
7859 if (i >= fd->collapse)
7860 return; */
fd6481cf 7861
43895be5 7862 deps = OMP_CLAUSE_DECL (c);
7863 gsi_prev (&gsi2);
7864 edge e1 = split_block (gsi_bb (gsi2), gsi_stmt (gsi2));
7865 edge e2 = split_block_after_labels (e1->dest);
fd6481cf 7866
43895be5 7867 *gsi = gsi_after_labels (e1->dest);
7868 for (i = 0; i < fd->ordered; i++)
7869 {
7870 tree itype = TREE_TYPE (fd->loops[i].v);
7871 if (POINTER_TYPE_P (itype))
7872 itype = sizetype;
7873 if (i)
7874 deps = TREE_CHAIN (deps);
7875 off = TREE_PURPOSE (deps);
7876 tree s = fold_convert_loc (loc, itype, fd->loops[i].step);
7877
7878 if (integer_zerop (off))
7879 t = boolean_true_node;
7880 else
7881 {
7882 tree a;
7883 tree co = fold_convert_loc (loc, itype, off);
7884 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
7885 {
7886 if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
7887 co = fold_build1_loc (loc, NEGATE_EXPR, itype, co);
7888 a = fold_build2_loc (loc, POINTER_PLUS_EXPR,
7889 TREE_TYPE (fd->loops[i].v), fd->loops[i].v,
7890 co);
7891 }
7892 else if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
7893 a = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (fd->loops[i].v),
7894 fd->loops[i].v, co);
7895 else
7896 a = fold_build2_loc (loc, PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
7897 fd->loops[i].v, co);
7898 if (fd->loops[i].cond_code == LT_EXPR)
7899 {
7900 if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
7901 t = fold_build2_loc (loc, GE_EXPR, boolean_type_node, a,
7902 fd->loops[i].n1);
7903 else
7904 t = fold_build2_loc (loc, LT_EXPR, boolean_type_node, a,
7905 fd->loops[i].n2);
7906 }
7907 else if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
7908 t = fold_build2_loc (loc, GT_EXPR, boolean_type_node, a,
7909 fd->loops[i].n2);
7910 else
7911 t = fold_build2_loc (loc, LE_EXPR, boolean_type_node, a,
7912 fd->loops[i].n1);
7913 }
7914 if (cond)
7915 cond = fold_build2_loc (loc, BIT_AND_EXPR, boolean_type_node, cond, t);
7916 else
7917 cond = t;
7918
7919 off = fold_convert_loc (loc, itype, off);
7920
7921 if (fd->loops[i].cond_code == LT_EXPR
7922 ? !integer_onep (fd->loops[i].step)
7923 : !integer_minus_onep (fd->loops[i].step))
7924 {
7925 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
7926 t = fold_build2_loc (loc, TRUNC_MOD_EXPR, itype, off,
7927 fold_build1_loc (loc, NEGATE_EXPR, itype,
7928 s));
7929 else
7930 t = fold_build2_loc (loc, TRUNC_MOD_EXPR, itype, off, s);
7931 t = fold_build2_loc (loc, EQ_EXPR, boolean_type_node, t,
7932 build_int_cst (itype, 0));
7933 if (integer_zerop (t) && !warned_step)
7934 {
7935 warning_at (loc, 0, "%<depend(sink)%> refers to iteration never "
7936 "in the iteration space");
7937 warned_step = true;
7938 }
7939 cond = fold_build2_loc (loc, BIT_AND_EXPR, boolean_type_node,
7940 cond, t);
7941 }
7942
7943 if (i <= fd->collapse - 1 && fd->collapse > 1)
7944 t = fd->loop.v;
7945 else if (counts[i])
7946 t = counts[i];
7947 else
7948 {
7949 t = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (fd->loops[i].v),
7950 fd->loops[i].v, fd->loops[i].n1);
7951 t = fold_convert_loc (loc, fd->iter_type, t);
7952 }
7953 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
7954 off = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, off,
7955 fold_build1_loc (loc, NEGATE_EXPR, itype,
7956 s));
7957 else
7958 off = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, off, s);
7959 if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
7960 off = fold_build1_loc (loc, NEGATE_EXPR, itype, off);
7961 off = fold_convert_loc (loc, fd->iter_type, off);
7962 if (i <= fd->collapse - 1 && fd->collapse > 1)
7963 {
7964 if (i)
7965 off = fold_build2_loc (loc, PLUS_EXPR, fd->iter_type, coff,
7966 off);
7967 if (i < fd->collapse - 1)
7968 {
7969 coff = fold_build2_loc (loc, MULT_EXPR, fd->iter_type, off,
7970 counts[i]);
7971 continue;
7972 }
7973 }
7974 off = unshare_expr (off);
7975 t = fold_build2_loc (loc, PLUS_EXPR, fd->iter_type, t, off);
7976 t = force_gimple_operand_gsi (gsi, t, true, NULL_TREE,
7977 true, GSI_SAME_STMT);
7978 args.safe_push (t);
7979 }
7980 gimple *g = gimple_build_call_vec (builtin_decl_explicit (sink_ix), args);
7981 gimple_set_location (g, loc);
7982 gsi_insert_before (gsi, g, GSI_SAME_STMT);
7983
7984 *gsi = gsi_last_bb (e1->src);
7985 cond = unshare_expr (cond);
7986 cond = force_gimple_operand_gsi (gsi, cond, true, NULL_TREE, false,
7987 GSI_CONTINUE_LINKING);
7988 gsi_insert_after (gsi, gimple_build_cond_empty (cond), GSI_NEW_STMT);
7989 edge e3 = make_edge (e1->src, e2->dest, EDGE_FALSE_VALUE);
7990 e3->probability = REG_BR_PROB_BASE / 8;
7991 e1->probability = REG_BR_PROB_BASE - e3->probability;
7992 e1->flags = EDGE_TRUE_VALUE;
7993 set_immediate_dominator (CDI_DOMINATORS, e2->dest, e1->src);
7994
7995 *gsi = gsi_after_labels (e2->dest);
7996}
7997
7998/* Expand all #pragma omp ordered depend(source) and
7999 #pragma omp ordered depend(sink:...) constructs in the current
8000 #pragma omp for ordered(n) region. */
8001
8002static void
8003expand_omp_ordered_source_sink (struct omp_region *region,
8004 struct omp_for_data *fd, tree *counts,
8005 basic_block cont_bb)
8006{
8007 struct omp_region *inner;
8008 int i;
8009 for (i = fd->collapse - 1; i < fd->ordered; i++)
8010 if (i == fd->collapse - 1 && fd->collapse > 1)
8011 counts[i] = NULL_TREE;
8012 else if (i >= fd->collapse && !cont_bb)
8013 counts[i] = build_zero_cst (fd->iter_type);
8014 else if (!POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v))
8015 && integer_onep (fd->loops[i].step))
8016 counts[i] = NULL_TREE;
8017 else
8018 counts[i] = create_tmp_var (fd->iter_type, ".orditer");
8019 tree atype
8020 = build_array_type_nelts (fd->iter_type, fd->ordered - fd->collapse + 1);
8021 counts[fd->ordered] = create_tmp_var (atype, ".orditera");
8022 TREE_ADDRESSABLE (counts[fd->ordered]) = 1;
8023
8024 for (inner = region->inner; inner; inner = inner->next)
8025 if (inner->type == GIMPLE_OMP_ORDERED)
8026 {
8027 gomp_ordered *ord_stmt = inner->ord_stmt;
8028 gimple_stmt_iterator gsi = gsi_for_stmt (ord_stmt);
8029 location_t loc = gimple_location (ord_stmt);
8030 tree c;
8031 for (c = gimple_omp_ordered_clauses (ord_stmt);
8032 c; c = OMP_CLAUSE_CHAIN (c))
8033 if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE)
8034 break;
8035 if (c)
8036 expand_omp_ordered_source (&gsi, fd, counts, loc);
8037 for (c = gimple_omp_ordered_clauses (ord_stmt);
8038 c; c = OMP_CLAUSE_CHAIN (c))
8039 if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK)
8040 expand_omp_ordered_sink (&gsi, fd, counts, c, loc);
8041 gsi_remove (&gsi, true);
8042 }
8043}
8044
8045/* Wrap the body into fd->ordered - fd->collapse loops that aren't
8046 collapsed. */
8047
8048static basic_block
8049expand_omp_for_ordered_loops (struct omp_for_data *fd, tree *counts,
8050 basic_block cont_bb, basic_block body_bb,
8051 bool ordered_lastprivate)
8052{
8053 if (fd->ordered == fd->collapse)
8054 return cont_bb;
8055
8056 if (!cont_bb)
8057 {
8058 gimple_stmt_iterator gsi = gsi_after_labels (body_bb);
8059 for (int i = fd->collapse; i < fd->ordered; i++)
8060 {
8061 tree type = TREE_TYPE (fd->loops[i].v);
8062 tree n1 = fold_convert (type, fd->loops[i].n1);
8063 expand_omp_build_assign (&gsi, fd->loops[i].v, n1);
8064 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8065 size_int (i - fd->collapse + 1),
8066 NULL_TREE, NULL_TREE);
8067 expand_omp_build_assign (&gsi, aref, build_zero_cst (fd->iter_type));
8068 }
8069 return NULL;
8070 }
8071
8072 for (int i = fd->ordered - 1; i >= fd->collapse; i--)
8073 {
8074 tree t, type = TREE_TYPE (fd->loops[i].v);
8075 gimple_stmt_iterator gsi = gsi_after_labels (body_bb);
8076 expand_omp_build_assign (&gsi, fd->loops[i].v,
8077 fold_convert (type, fd->loops[i].n1));
8078 if (counts[i])
8079 expand_omp_build_assign (&gsi, counts[i],
8080 build_zero_cst (fd->iter_type));
8081 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8082 size_int (i - fd->collapse + 1),
8083 NULL_TREE, NULL_TREE);
8084 expand_omp_build_assign (&gsi, aref, build_zero_cst (fd->iter_type));
8085 if (!gsi_end_p (gsi))
8086 gsi_prev (&gsi);
8087 else
8088 gsi = gsi_last_bb (body_bb);
8089 edge e1 = split_block (body_bb, gsi_stmt (gsi));
8090 basic_block new_body = e1->dest;
8091 if (body_bb == cont_bb)
8092 cont_bb = new_body;
8093 edge e2 = NULL;
8094 basic_block new_header;
8095 if (EDGE_COUNT (cont_bb->preds) > 0)
8096 {
8097 gsi = gsi_last_bb (cont_bb);
8098 if (POINTER_TYPE_P (type))
8099 t = fold_build_pointer_plus (fd->loops[i].v,
8100 fold_convert (sizetype,
8101 fd->loops[i].step));
8102 else
8103 t = fold_build2 (PLUS_EXPR, type, fd->loops[i].v,
8104 fold_convert (type, fd->loops[i].step));
8105 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
8106 if (counts[i])
8107 {
8108 t = fold_build2 (PLUS_EXPR, fd->iter_type, counts[i],
8109 build_int_cst (fd->iter_type, 1));
8110 expand_omp_build_assign (&gsi, counts[i], t);
8111 t = counts[i];
8112 }
8113 else
8114 {
8115 t = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->loops[i].v),
8116 fd->loops[i].v, fd->loops[i].n1);
8117 t = fold_convert (fd->iter_type, t);
8118 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8119 true, GSI_SAME_STMT);
8120 }
8121 aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8122 size_int (i - fd->collapse + 1),
8123 NULL_TREE, NULL_TREE);
8124 expand_omp_build_assign (&gsi, aref, t);
8125 gsi_prev (&gsi);
8126 e2 = split_block (cont_bb, gsi_stmt (gsi));
8127 new_header = e2->dest;
8128 }
8129 else
8130 new_header = cont_bb;
8131 gsi = gsi_after_labels (new_header);
8132 tree v = force_gimple_operand_gsi (&gsi, fd->loops[i].v, true, NULL_TREE,
8133 true, GSI_SAME_STMT);
8134 tree n2
8135 = force_gimple_operand_gsi (&gsi, fold_convert (type, fd->loops[i].n2),
8136 true, NULL_TREE, true, GSI_SAME_STMT);
8137 t = build2 (fd->loops[i].cond_code, boolean_type_node, v, n2);
8138 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_NEW_STMT);
8139 edge e3 = split_block (new_header, gsi_stmt (gsi));
8140 cont_bb = e3->dest;
8141 remove_edge (e1);
8142 make_edge (body_bb, new_header, EDGE_FALLTHRU);
8143 e3->flags = EDGE_FALSE_VALUE;
8144 e3->probability = REG_BR_PROB_BASE / 8;
8145 e1 = make_edge (new_header, new_body, EDGE_TRUE_VALUE);
8146 e1->probability = REG_BR_PROB_BASE - e3->probability;
8147
8148 set_immediate_dominator (CDI_DOMINATORS, new_header, body_bb);
8149 set_immediate_dominator (CDI_DOMINATORS, new_body, new_header);
8150
8151 if (e2)
8152 {
8153 struct loop *loop = alloc_loop ();
8154 loop->header = new_header;
8155 loop->latch = e2->src;
8156 add_loop (loop, body_bb->loop_father);
8157 }
8158 }
8159
8160 /* If there are any lastprivate clauses and it is possible some loops
8161 might have zero iterations, ensure all the decls are initialized,
8162 otherwise we could crash evaluating C++ class iterators with lastprivate
8163 clauses. */
8164 bool need_inits = false;
8165 for (int i = fd->collapse; ordered_lastprivate && i < fd->ordered; i++)
8166 if (need_inits)
8167 {
8168 tree type = TREE_TYPE (fd->loops[i].v);
8169 gimple_stmt_iterator gsi = gsi_after_labels (body_bb);
8170 expand_omp_build_assign (&gsi, fd->loops[i].v,
8171 fold_convert (type, fd->loops[i].n1));
8172 }
8173 else
8174 {
8175 tree type = TREE_TYPE (fd->loops[i].v);
8176 tree this_cond = fold_build2 (fd->loops[i].cond_code,
8177 boolean_type_node,
8178 fold_convert (type, fd->loops[i].n1),
8179 fold_convert (type, fd->loops[i].n2));
8180 if (!integer_onep (this_cond))
8181 need_inits = true;
8182 }
8183
8184 return cont_bb;
8185}
8186
8187
8188/* A subroutine of expand_omp_for. Generate code for a parallel
8189 loop with any schedule. Given parameters:
8190
8191 for (V = N1; V cond N2; V += STEP) BODY;
8192
8193 where COND is "<" or ">", we generate pseudocode
8194
8195 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
8196 if (more) goto L0; else goto L3;
8197 L0:
8198 V = istart0;
8199 iend = iend0;
8200 L1:
8201 BODY;
8202 V += STEP;
8203 if (V cond iend) goto L1; else goto L2;
8204 L2:
8205 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
8206 L3:
8207
8208 If this is a combined omp parallel loop, instead of the call to
8209 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
8210 If this is gimple_omp_for_combined_p loop, then instead of assigning
8211 V and iend in L0 we assign the first two _looptemp_ clause decls of the
8212 inner GIMPLE_OMP_FOR and V += STEP; and
8213 if (V cond iend) goto L1; else goto L2; are removed.
8214
8215 For collapsed loops, given parameters:
8216 collapse(3)
8217 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
8218 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
8219 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
8220 BODY;
8221
8222 we generate pseudocode
8223
8224 if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
8225 if (cond3 is <)
8226 adj = STEP3 - 1;
8227 else
8228 adj = STEP3 + 1;
8229 count3 = (adj + N32 - N31) / STEP3;
8230 if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
8231 if (cond2 is <)
8232 adj = STEP2 - 1;
8233 else
8234 adj = STEP2 + 1;
fd6481cf 8235 count2 = (adj + N22 - N21) / STEP2;
8e6b4515 8236 if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
fd6481cf 8237 if (cond1 is <)
8238 adj = STEP1 - 1;
8239 else
8240 adj = STEP1 + 1;
8241 count1 = (adj + N12 - N11) / STEP1;
8242 count = count1 * count2 * count3;
8e6b4515 8243 goto Z1;
8244 Z0:
8245 count = 0;
8246 Z1:
fd6481cf 8247 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
8248 if (more) goto L0; else goto L3;
8249 L0:
8250 V = istart0;
8251 T = V;
8252 V3 = N31 + (T % count3) * STEP3;
8253 T = T / count3;
8254 V2 = N21 + (T % count2) * STEP2;
8255 T = T / count2;
8256 V1 = N11 + T * STEP1;
8257 iend = iend0;
8258 L1:
8259 BODY;
8260 V += 1;
8261 if (V < iend) goto L10; else goto L2;
8262 L10:
8263 V3 += STEP3;
8264 if (V3 cond3 N32) goto L1; else goto L11;
8265 L11:
8266 V3 = N31;
8267 V2 += STEP2;
8268 if (V2 cond2 N22) goto L1; else goto L12;
8269 L12:
8270 V2 = N21;
8271 V1 += STEP1;
8272 goto L1;
8273 L2:
8274 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
8275 L3:
8276
8277 */
1e8e9920 8278
61e47ac8 8279static void
773c5ba7 8280expand_omp_for_generic (struct omp_region *region,
8281 struct omp_for_data *fd,
1e8e9920 8282 enum built_in_function start_fn,
bc7bff74 8283 enum built_in_function next_fn,
42acab1c 8284 gimple *inner_stmt)
1e8e9920 8285{
75a70cf9 8286 tree type, istart0, iend0, iend;
fd6481cf 8287 tree t, vmain, vback, bias = NULL_TREE;
8288 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, collapse_bb;
03ed154b 8289 basic_block l2_bb = NULL, l3_bb = NULL;
75a70cf9 8290 gimple_stmt_iterator gsi;
1a91d914 8291 gassign *assign_stmt;
773c5ba7 8292 bool in_combined_parallel = is_combined_parallel (region);
ac6e3339 8293 bool broken_loop = region->cont == NULL;
79acaae1 8294 edge e, ne;
fd6481cf 8295 tree *counts = NULL;
8296 int i;
43895be5 8297 bool ordered_lastprivate = false;
ac6e3339 8298
8299 gcc_assert (!broken_loop || !in_combined_parallel);
fd6481cf 8300 gcc_assert (fd->iter_type == long_integer_type_node
8301 || !in_combined_parallel);
1e8e9920 8302
61e47ac8 8303 entry_bb = region->entry;
03ed154b 8304 cont_bb = region->cont;
fd6481cf 8305 collapse_bb = NULL;
ac6e3339 8306 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
8307 gcc_assert (broken_loop
8308 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
8309 l0_bb = split_edge (FALLTHRU_EDGE (entry_bb));
8310 l1_bb = single_succ (l0_bb);
8311 if (!broken_loop)
03ed154b 8312 {
8313 l2_bb = create_empty_bb (cont_bb);
95cd5725 8314 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb
8315 || (single_succ_edge (BRANCH_EDGE (cont_bb)->dest)->dest
8316 == l1_bb));
ac6e3339 8317 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
03ed154b 8318 }
ac6e3339 8319 else
8320 l2_bb = NULL;
8321 l3_bb = BRANCH_EDGE (entry_bb)->dest;
8322 exit_bb = region->exit;
773c5ba7 8323
75a70cf9 8324 gsi = gsi_last_bb (entry_bb);
fd6481cf 8325
75a70cf9 8326 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
43895be5 8327 if (fd->ordered
8328 && find_omp_clause (gimple_omp_for_clauses (gsi_stmt (gsi)),
8329 OMP_CLAUSE_LASTPRIVATE))
8330 ordered_lastprivate = false;
8331 if (fd->collapse > 1 || fd->ordered)
fd6481cf 8332 {
43895be5 8333 int first_zero_iter1 = -1, first_zero_iter2 = -1;
8334 basic_block zero_iter1_bb = NULL, zero_iter2_bb = NULL, l2_dom_bb = NULL;
8e6b4515 8335
43895be5 8336 counts = XALLOCAVEC (tree, fd->ordered ? fd->ordered + 1 : fd->collapse);
3d483a94 8337 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
43895be5 8338 zero_iter1_bb, first_zero_iter1,
8339 zero_iter2_bb, first_zero_iter2, l2_dom_bb);
fd6481cf 8340
43895be5 8341 if (zero_iter1_bb)
8e6b4515 8342 {
8343 /* Some counts[i] vars might be uninitialized if
8344 some loop has zero iterations. But the body shouldn't
8345 be executed in that case, so just avoid uninit warnings. */
43895be5 8346 for (i = first_zero_iter1;
8347 i < (fd->ordered ? fd->ordered : fd->collapse); i++)
8e6b4515 8348 if (SSA_VAR_P (counts[i]))
8349 TREE_NO_WARNING (counts[i]) = 1;
8350 gsi_prev (&gsi);
8351 e = split_block (entry_bb, gsi_stmt (gsi));
8352 entry_bb = e->dest;
43895be5 8353 make_edge (zero_iter1_bb, entry_bb, EDGE_FALLTHRU);
8e6b4515 8354 gsi = gsi_last_bb (entry_bb);
8355 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
8356 get_immediate_dominator (CDI_DOMINATORS,
43895be5 8357 zero_iter1_bb));
8358 }
8359 if (zero_iter2_bb)
8360 {
8361 /* Some counts[i] vars might be uninitialized if
8362 some loop has zero iterations. But the body shouldn't
8363 be executed in that case, so just avoid uninit warnings. */
8364 for (i = first_zero_iter2; i < fd->ordered; i++)
8365 if (SSA_VAR_P (counts[i]))
8366 TREE_NO_WARNING (counts[i]) = 1;
8367 if (zero_iter1_bb)
8368 make_edge (zero_iter2_bb, entry_bb, EDGE_FALLTHRU);
8369 else
8370 {
8371 gsi_prev (&gsi);
8372 e = split_block (entry_bb, gsi_stmt (gsi));
8373 entry_bb = e->dest;
8374 make_edge (zero_iter2_bb, entry_bb, EDGE_FALLTHRU);
8375 gsi = gsi_last_bb (entry_bb);
8376 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
8377 get_immediate_dominator
8378 (CDI_DOMINATORS, zero_iter2_bb));
8379 }
8380 }
8381 if (fd->collapse == 1)
8382 {
8383 counts[0] = fd->loop.n2;
8384 fd->loop = fd->loops[0];
8385 }
8386 }
8387
8388 type = TREE_TYPE (fd->loop.v);
8389 istart0 = create_tmp_var (fd->iter_type, ".istart0");
8390 iend0 = create_tmp_var (fd->iter_type, ".iend0");
8391 TREE_ADDRESSABLE (istart0) = 1;
8392 TREE_ADDRESSABLE (iend0) = 1;
8393
8394 /* See if we need to bias by LLONG_MIN. */
8395 if (fd->iter_type == long_long_unsigned_type_node
8396 && TREE_CODE (type) == INTEGER_TYPE
8397 && !TYPE_UNSIGNED (type)
8398 && fd->ordered == 0)
8399 {
8400 tree n1, n2;
8401
8402 if (fd->loop.cond_code == LT_EXPR)
8403 {
8404 n1 = fd->loop.n1;
8405 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
8e6b4515 8406 }
43895be5 8407 else
8408 {
8409 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
8410 n2 = fd->loop.n1;
8411 }
8412 if (TREE_CODE (n1) != INTEGER_CST
8413 || TREE_CODE (n2) != INTEGER_CST
8414 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
8415 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
fd6481cf 8416 }
43895be5 8417
8418 gimple_stmt_iterator gsif = gsi;
8419 gsi_prev (&gsif);
8420
8421 tree arr = NULL_TREE;
79acaae1 8422 if (in_combined_parallel)
8423 {
43895be5 8424 gcc_assert (fd->ordered == 0);
79acaae1 8425 /* In a combined parallel loop, emit a call to
8426 GOMP_loop_foo_next. */
b9a16870 8427 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
79acaae1 8428 build_fold_addr_expr (istart0),
8429 build_fold_addr_expr (iend0));
8430 }
8431 else
1e8e9920 8432 {
c2f47e15 8433 tree t0, t1, t2, t3, t4;
773c5ba7 8434 /* If this is not a combined parallel loop, emit a call to
8435 GOMP_loop_foo_start in ENTRY_BB. */
c2f47e15 8436 t4 = build_fold_addr_expr (iend0);
8437 t3 = build_fold_addr_expr (istart0);
43895be5 8438 if (fd->ordered)
c799f233 8439 {
43895be5 8440 t0 = build_int_cst (unsigned_type_node,
8441 fd->ordered - fd->collapse + 1);
8442 arr = create_tmp_var (build_array_type_nelts (fd->iter_type,
8443 fd->ordered
8444 - fd->collapse + 1),
8445 ".omp_counts");
8446 DECL_NAMELESS (arr) = 1;
8447 TREE_ADDRESSABLE (arr) = 1;
8448 TREE_STATIC (arr) = 1;
8449 vec<constructor_elt, va_gc> *v;
8450 vec_alloc (v, fd->ordered - fd->collapse + 1);
8451 int idx;
8452
8453 for (idx = 0; idx < fd->ordered - fd->collapse + 1; idx++)
8454 {
8455 tree c;
8456 if (idx == 0 && fd->collapse > 1)
8457 c = fd->loop.n2;
8458 else
8459 c = counts[idx + fd->collapse - 1];
8460 tree purpose = size_int (idx);
8461 CONSTRUCTOR_APPEND_ELT (v, purpose, c);
8462 if (TREE_CODE (c) != INTEGER_CST)
8463 TREE_STATIC (arr) = 0;
8464 }
8465
8466 DECL_INITIAL (arr) = build_constructor (TREE_TYPE (arr), v);
8467 if (!TREE_STATIC (arr))
8468 force_gimple_operand_gsi (&gsi, build1 (DECL_EXPR,
8469 void_type_node, arr),
8470 true, NULL_TREE, true, GSI_SAME_STMT);
8471 t1 = build_fold_addr_expr (arr);
8472 t2 = NULL_TREE;
c799f233 8473 }
8474 else
8475 {
43895be5 8476 t2 = fold_convert (fd->iter_type, fd->loop.step);
8477 t1 = fd->loop.n2;
8478 t0 = fd->loop.n1;
8479 if (gimple_omp_for_combined_into_p (fd->for_stmt))
8480 {
8481 tree innerc
8482 = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
8483 OMP_CLAUSE__LOOPTEMP_);
8484 gcc_assert (innerc);
8485 t0 = OMP_CLAUSE_DECL (innerc);
8486 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
8487 OMP_CLAUSE__LOOPTEMP_);
8488 gcc_assert (innerc);
8489 t1 = OMP_CLAUSE_DECL (innerc);
8490 }
8491 if (POINTER_TYPE_P (TREE_TYPE (t0))
8492 && TYPE_PRECISION (TREE_TYPE (t0))
8493 != TYPE_PRECISION (fd->iter_type))
8494 {
8495 /* Avoid casting pointers to integer of a different size. */
8496 tree itype = signed_type_for (type);
8497 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
8498 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
8499 }
8500 else
8501 {
8502 t1 = fold_convert (fd->iter_type, t1);
8503 t0 = fold_convert (fd->iter_type, t0);
8504 }
8505 if (bias)
8506 {
8507 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
8508 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
8509 }
fd6481cf 8510 }
43895be5 8511 if (fd->iter_type == long_integer_type_node || fd->ordered)
fd6481cf 8512 {
8513 if (fd->chunk_size)
8514 {
8515 t = fold_convert (fd->iter_type, fd->chunk_size);
43895be5 8516 t = omp_adjust_chunk_size (t, fd->simd_schedule);
8517 if (fd->ordered)
8518 t = build_call_expr (builtin_decl_explicit (start_fn),
8519 5, t0, t1, t, t3, t4);
8520 else
8521 t = build_call_expr (builtin_decl_explicit (start_fn),
8522 6, t0, t1, t2, t, t3, t4);
fd6481cf 8523 }
43895be5 8524 else if (fd->ordered)
8525 t = build_call_expr (builtin_decl_explicit (start_fn),
8526 4, t0, t1, t3, t4);
fd6481cf 8527 else
b9a16870 8528 t = build_call_expr (builtin_decl_explicit (start_fn),
8529 5, t0, t1, t2, t3, t4);
1e8e9920 8530 }
c2f47e15 8531 else
fd6481cf 8532 {
8533 tree t5;
8534 tree c_bool_type;
b9a16870 8535 tree bfn_decl;
fd6481cf 8536
8537 /* The GOMP_loop_ull_*start functions have additional boolean
8538 argument, true for < loops and false for > loops.
8539 In Fortran, the C bool type can be different from
8540 boolean_type_node. */
b9a16870 8541 bfn_decl = builtin_decl_explicit (start_fn);
8542 c_bool_type = TREE_TYPE (TREE_TYPE (bfn_decl));
fd6481cf 8543 t5 = build_int_cst (c_bool_type,
8544 fd->loop.cond_code == LT_EXPR ? 1 : 0);
8545 if (fd->chunk_size)
8546 {
b9a16870 8547 tree bfn_decl = builtin_decl_explicit (start_fn);
fd6481cf 8548 t = fold_convert (fd->iter_type, fd->chunk_size);
43895be5 8549 t = omp_adjust_chunk_size (t, fd->simd_schedule);
b9a16870 8550 t = build_call_expr (bfn_decl, 7, t5, t0, t1, t2, t, t3, t4);
fd6481cf 8551 }
8552 else
b9a16870 8553 t = build_call_expr (builtin_decl_explicit (start_fn),
8554 6, t5, t0, t1, t2, t3, t4);
fd6481cf 8555 }
1e8e9920 8556 }
fd6481cf 8557 if (TREE_TYPE (t) != boolean_type_node)
8558 t = fold_build2 (NE_EXPR, boolean_type_node,
8559 t, build_int_cst (TREE_TYPE (t), 0));
75a70cf9 8560 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8561 true, GSI_SAME_STMT);
43895be5 8562 if (arr && !TREE_STATIC (arr))
8563 {
8564 tree clobber = build_constructor (TREE_TYPE (arr), NULL);
8565 TREE_THIS_VOLATILE (clobber) = 1;
8566 gsi_insert_before (&gsi, gimple_build_assign (arr, clobber),
8567 GSI_SAME_STMT);
8568 }
75a70cf9 8569 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
79acaae1 8570
75a70cf9 8571 /* Remove the GIMPLE_OMP_FOR statement. */
8572 gsi_remove (&gsi, true);
1e8e9920 8573
43895be5 8574 if (gsi_end_p (gsif))
8575 gsif = gsi_after_labels (gsi_bb (gsif));
8576 gsi_next (&gsif);
8577
773c5ba7 8578 /* Iteration setup for sequential loop goes in L0_BB. */
3d483a94 8579 tree startvar = fd->loop.v;
8580 tree endvar = NULL_TREE;
8581
bc7bff74 8582 if (gimple_omp_for_combined_p (fd->for_stmt))
8583 {
8584 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_FOR
8585 && gimple_omp_for_kind (inner_stmt)
8586 == GF_OMP_FOR_KIND_SIMD);
8587 tree innerc = find_omp_clause (gimple_omp_for_clauses (inner_stmt),
8588 OMP_CLAUSE__LOOPTEMP_);
8589 gcc_assert (innerc);
8590 startvar = OMP_CLAUSE_DECL (innerc);
8591 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
8592 OMP_CLAUSE__LOOPTEMP_);
8593 gcc_assert (innerc);
8594 endvar = OMP_CLAUSE_DECL (innerc);
8595 }
8596
75a70cf9 8597 gsi = gsi_start_bb (l0_bb);
1efcacec 8598 t = istart0;
43895be5 8599 if (fd->ordered && fd->collapse == 1)
8600 t = fold_build2 (MULT_EXPR, fd->iter_type, t,
8601 fold_convert (fd->iter_type, fd->loop.step));
8602 else if (bias)
1efcacec 8603 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
43895be5 8604 if (fd->ordered && fd->collapse == 1)
8605 {
8606 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8607 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (startvar),
8608 fd->loop.n1, fold_convert (sizetype, t));
8609 else
8610 {
8611 t = fold_convert (TREE_TYPE (startvar), t);
8612 t = fold_build2 (PLUS_EXPR, TREE_TYPE (startvar),
8613 fd->loop.n1, t);
8614 }
8615 }
8616 else
8617 {
8618 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8619 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
8620 t = fold_convert (TREE_TYPE (startvar), t);
8621 }
4abecb72 8622 t = force_gimple_operand_gsi (&gsi, t,
3d483a94 8623 DECL_P (startvar)
8624 && TREE_ADDRESSABLE (startvar),
4abecb72 8625 NULL_TREE, false, GSI_CONTINUE_LINKING);
1a91d914 8626 assign_stmt = gimple_build_assign (startvar, t);
8627 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
1e8e9920 8628
1efcacec 8629 t = iend0;
43895be5 8630 if (fd->ordered && fd->collapse == 1)
8631 t = fold_build2 (MULT_EXPR, fd->iter_type, t,
8632 fold_convert (fd->iter_type, fd->loop.step));
8633 else if (bias)
1efcacec 8634 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
43895be5 8635 if (fd->ordered && fd->collapse == 1)
fd6481cf 8636 {
43895be5 8637 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8638 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (startvar),
8639 fd->loop.n1, fold_convert (sizetype, t));
8640 else
8641 {
8642 t = fold_convert (TREE_TYPE (startvar), t);
8643 t = fold_build2 (PLUS_EXPR, TREE_TYPE (startvar),
8644 fd->loop.n1, t);
8645 }
8646 }
8647 else
8648 {
8649 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8650 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
8651 t = fold_convert (TREE_TYPE (startvar), t);
8652 }
8653 iend = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8654 false, GSI_CONTINUE_LINKING);
8655 if (endvar)
8656 {
8657 assign_stmt = gimple_build_assign (endvar, iend);
1a91d914 8658 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
d44f2f7c 8659 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (iend)))
1a91d914 8660 assign_stmt = gimple_build_assign (fd->loop.v, iend);
d44f2f7c 8661 else
e9cf809e 8662 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, iend);
1a91d914 8663 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
fd6481cf 8664 }
43895be5 8665 /* Handle linear clause adjustments. */
8666 tree itercnt = NULL_TREE;
8667 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_FOR)
8668 for (tree c = gimple_omp_for_clauses (fd->for_stmt);
8669 c; c = OMP_CLAUSE_CHAIN (c))
8670 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
8671 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
8672 {
8673 tree d = OMP_CLAUSE_DECL (c);
8674 bool is_ref = is_reference (d);
8675 tree t = d, a, dest;
8676 if (is_ref)
8677 t = build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c), t);
8678 tree type = TREE_TYPE (t);
8679 if (POINTER_TYPE_P (type))
8680 type = sizetype;
8681 dest = unshare_expr (t);
8682 tree v = create_tmp_var (TREE_TYPE (t), NULL);
8683 expand_omp_build_assign (&gsif, v, t);
8684 if (itercnt == NULL_TREE)
8685 {
8686 itercnt = startvar;
8687 tree n1 = fd->loop.n1;
8688 if (POINTER_TYPE_P (TREE_TYPE (itercnt)))
8689 {
8690 itercnt
8691 = fold_convert (signed_type_for (TREE_TYPE (itercnt)),
8692 itercnt);
8693 n1 = fold_convert (TREE_TYPE (itercnt), n1);
8694 }
8695 itercnt = fold_build2 (MINUS_EXPR, TREE_TYPE (itercnt),
8696 itercnt, n1);
8697 itercnt = fold_build2 (EXACT_DIV_EXPR, TREE_TYPE (itercnt),
8698 itercnt, fd->loop.step);
8699 itercnt = force_gimple_operand_gsi (&gsi, itercnt, true,
8700 NULL_TREE, false,
8701 GSI_CONTINUE_LINKING);
8702 }
8703 a = fold_build2 (MULT_EXPR, type,
8704 fold_convert (type, itercnt),
8705 fold_convert (type, OMP_CLAUSE_LINEAR_STEP (c)));
8706 t = fold_build2 (type == TREE_TYPE (t) ? PLUS_EXPR
8707 : POINTER_PLUS_EXPR, TREE_TYPE (t), v, a);
8708 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8709 false, GSI_CONTINUE_LINKING);
8710 assign_stmt = gimple_build_assign (dest, t);
8711 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
8712 }
3d483a94 8713 if (fd->collapse > 1)
bc7bff74 8714 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
773c5ba7 8715
43895be5 8716 if (fd->ordered)
8717 {
8718 /* Until now, counts array contained number of iterations or
8719 variable containing it for ith loop. From now on, we need
8720 those counts only for collapsed loops, and only for the 2nd
8721 till the last collapsed one. Move those one element earlier,
8722 we'll use counts[fd->collapse - 1] for the first source/sink
8723 iteration counter and so on and counts[fd->ordered]
8724 as the array holding the current counter values for
8725 depend(source). */
8726 if (fd->collapse > 1)
8727 memmove (counts, counts + 1, (fd->collapse - 1) * sizeof (counts[0]));
8728 if (broken_loop)
8729 {
8730 int i;
8731 for (i = fd->collapse; i < fd->ordered; i++)
8732 {
8733 tree type = TREE_TYPE (fd->loops[i].v);
8734 tree this_cond
8735 = fold_build2 (fd->loops[i].cond_code, boolean_type_node,
8736 fold_convert (type, fd->loops[i].n1),
8737 fold_convert (type, fd->loops[i].n2));
8738 if (!integer_onep (this_cond))
8739 break;
8740 }
8741 if (i < fd->ordered)
8742 {
8743 cont_bb
8744 = create_empty_bb (EXIT_BLOCK_PTR_FOR_FN (cfun)->prev_bb);
8745 add_bb_to_loop (cont_bb, l1_bb->loop_father);
8746 gimple_stmt_iterator gsi = gsi_after_labels (cont_bb);
8747 gimple *g = gimple_build_omp_continue (fd->loop.v, fd->loop.v);
8748 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
8749 make_edge (cont_bb, l3_bb, EDGE_FALLTHRU);
8750 make_edge (cont_bb, l1_bb, 0);
8751 l2_bb = create_empty_bb (cont_bb);
8752 broken_loop = false;
8753 }
8754 }
8755 expand_omp_ordered_source_sink (region, fd, counts, cont_bb);
8756 cont_bb = expand_omp_for_ordered_loops (fd, counts, cont_bb, l1_bb,
8757 ordered_lastprivate);
8758 if (counts[fd->collapse - 1])
8759 {
8760 gcc_assert (fd->collapse == 1);
8761 gsi = gsi_last_bb (l0_bb);
8762 expand_omp_build_assign (&gsi, counts[fd->collapse - 1],
8763 istart0, true);
8764 gsi = gsi_last_bb (cont_bb);
8765 t = fold_build2 (PLUS_EXPR, fd->iter_type, counts[fd->collapse - 1],
8766 build_int_cst (fd->iter_type, 1));
8767 expand_omp_build_assign (&gsi, counts[fd->collapse - 1], t);
8768 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8769 size_zero_node, NULL_TREE, NULL_TREE);
8770 expand_omp_build_assign (&gsi, aref, counts[fd->collapse - 1]);
8771 t = counts[fd->collapse - 1];
8772 }
8773 else if (fd->collapse > 1)
8774 t = fd->loop.v;
8775 else
8776 {
8777 t = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->loops[0].v),
8778 fd->loops[0].v, fd->loops[0].n1);
8779 t = fold_convert (fd->iter_type, t);
8780 }
8781 gsi = gsi_last_bb (l0_bb);
8782 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8783 size_zero_node, NULL_TREE, NULL_TREE);
8784 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8785 false, GSI_CONTINUE_LINKING);
8786 expand_omp_build_assign (&gsi, aref, t, true);
8787 }
8788
ac6e3339 8789 if (!broken_loop)
03ed154b 8790 {
ac6e3339 8791 /* Code to control the increment and predicate for the sequential
8792 loop goes in the CONT_BB. */
75a70cf9 8793 gsi = gsi_last_bb (cont_bb);
1a91d914 8794 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
8795 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
8796 vmain = gimple_omp_continue_control_use (cont_stmt);
8797 vback = gimple_omp_continue_control_def (cont_stmt);
79acaae1 8798
bc7bff74 8799 if (!gimple_omp_for_combined_p (fd->for_stmt))
3d483a94 8800 {
8801 if (POINTER_TYPE_P (type))
8802 t = fold_build_pointer_plus (vmain, fd->loop.step);
8803 else
8804 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
8805 t = force_gimple_operand_gsi (&gsi, t,
8806 DECL_P (vback)
8807 && TREE_ADDRESSABLE (vback),
8808 NULL_TREE, true, GSI_SAME_STMT);
1a91d914 8809 assign_stmt = gimple_build_assign (vback, t);
8810 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
3d483a94 8811
43895be5 8812 if (fd->ordered && counts[fd->collapse - 1] == NULL_TREE)
8813 {
8814 if (fd->collapse > 1)
8815 t = fd->loop.v;
8816 else
8817 {
8818 t = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->loops[0].v),
8819 fd->loops[0].v, fd->loops[0].n1);
8820 t = fold_convert (fd->iter_type, t);
8821 }
8822 tree aref = build4 (ARRAY_REF, fd->iter_type,
8823 counts[fd->ordered], size_zero_node,
8824 NULL_TREE, NULL_TREE);
8825 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8826 true, GSI_SAME_STMT);
8827 expand_omp_build_assign (&gsi, aref, t);
8828 }
8829
3d483a94 8830 t = build2 (fd->loop.cond_code, boolean_type_node,
8831 DECL_P (vback) && TREE_ADDRESSABLE (vback) ? t : vback,
8832 iend);
1a91d914 8833 gcond *cond_stmt = gimple_build_cond_empty (t);
8834 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
3d483a94 8835 }
773c5ba7 8836
75a70cf9 8837 /* Remove GIMPLE_OMP_CONTINUE. */
8838 gsi_remove (&gsi, true);
773c5ba7 8839
bc7bff74 8840 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
3d483a94 8841 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, l1_bb);
fd6481cf 8842
ac6e3339 8843 /* Emit code to get the next parallel iteration in L2_BB. */
75a70cf9 8844 gsi = gsi_start_bb (l2_bb);
773c5ba7 8845
b9a16870 8846 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
ac6e3339 8847 build_fold_addr_expr (istart0),
8848 build_fold_addr_expr (iend0));
75a70cf9 8849 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8850 false, GSI_CONTINUE_LINKING);
fd6481cf 8851 if (TREE_TYPE (t) != boolean_type_node)
8852 t = fold_build2 (NE_EXPR, boolean_type_node,
8853 t, build_int_cst (TREE_TYPE (t), 0));
1a91d914 8854 gcond *cond_stmt = gimple_build_cond_empty (t);
8855 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
ac6e3339 8856 }
1e8e9920 8857
61e47ac8 8858 /* Add the loop cleanup function. */
75a70cf9 8859 gsi = gsi_last_bb (exit_bb);
8860 if (gimple_omp_return_nowait_p (gsi_stmt (gsi)))
b9a16870 8861 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
bc7bff74 8862 else if (gimple_omp_return_lhs (gsi_stmt (gsi)))
8863 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL);
61e47ac8 8864 else
b9a16870 8865 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END);
1a91d914 8866 gcall *call_stmt = gimple_build_call (t, 0);
bc7bff74 8867 if (gimple_omp_return_lhs (gsi_stmt (gsi)))
1a91d914 8868 gimple_call_set_lhs (call_stmt, gimple_omp_return_lhs (gsi_stmt (gsi)));
8869 gsi_insert_after (&gsi, call_stmt, GSI_SAME_STMT);
43895be5 8870 if (fd->ordered)
8871 {
8872 tree arr = counts[fd->ordered];
8873 tree clobber = build_constructor (TREE_TYPE (arr), NULL);
8874 TREE_THIS_VOLATILE (clobber) = 1;
8875 gsi_insert_after (&gsi, gimple_build_assign (arr, clobber),
8876 GSI_SAME_STMT);
8877 }
75a70cf9 8878 gsi_remove (&gsi, true);
773c5ba7 8879
8880 /* Connect the new blocks. */
79acaae1 8881 find_edge (entry_bb, l0_bb)->flags = EDGE_TRUE_VALUE;
8882 find_edge (entry_bb, l3_bb)->flags = EDGE_FALSE_VALUE;
1e8e9920 8883
ac6e3339 8884 if (!broken_loop)
8885 {
75a70cf9 8886 gimple_seq phis;
8887
79acaae1 8888 e = find_edge (cont_bb, l3_bb);
8889 ne = make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
8890
75a70cf9 8891 phis = phi_nodes (l3_bb);
8892 for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi))
8893 {
42acab1c 8894 gimple *phi = gsi_stmt (gsi);
75a70cf9 8895 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, ne),
8896 PHI_ARG_DEF_FROM_EDGE (phi, e));
8897 }
79acaae1 8898 remove_edge (e);
8899
ac6e3339 8900 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
3d483a94 8901 e = find_edge (cont_bb, l1_bb);
95cd5725 8902 if (e == NULL)
8903 {
8904 e = BRANCH_EDGE (cont_bb);
8905 gcc_assert (single_succ (e->dest) == l1_bb);
8906 }
bc7bff74 8907 if (gimple_omp_for_combined_p (fd->for_stmt))
8908 {
8909 remove_edge (e);
8910 e = NULL;
8911 }
3d483a94 8912 else if (fd->collapse > 1)
fd6481cf 8913 {
fd6481cf 8914 remove_edge (e);
8915 e = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
8916 }
8917 else
3d483a94 8918 e->flags = EDGE_TRUE_VALUE;
8919 if (e)
fd6481cf 8920 {
3d483a94 8921 e->probability = REG_BR_PROB_BASE * 7 / 8;
8922 find_edge (cont_bb, l2_bb)->probability = REG_BR_PROB_BASE / 8;
8923 }
8924 else
8925 {
8926 e = find_edge (cont_bb, l2_bb);
8927 e->flags = EDGE_FALLTHRU;
fd6481cf 8928 }
ac6e3339 8929 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
79acaae1 8930
2131a1a9 8931 if (gimple_in_ssa_p (cfun))
8932 {
8933 /* Add phis to the outer loop that connect to the phis in the inner,
8934 original loop, and move the loop entry value of the inner phi to
8935 the loop entry value of the outer phi. */
8936 gphi_iterator psi;
8937 for (psi = gsi_start_phis (l3_bb); !gsi_end_p (psi); gsi_next (&psi))
8938 {
8939 source_location locus;
8940 gphi *nphi;
8941 gphi *exit_phi = psi.phi ();
8942
8943 edge l2_to_l3 = find_edge (l2_bb, l3_bb);
8944 tree exit_res = PHI_ARG_DEF_FROM_EDGE (exit_phi, l2_to_l3);
8945
8946 basic_block latch = BRANCH_EDGE (cont_bb)->dest;
8947 edge latch_to_l1 = find_edge (latch, l1_bb);
8948 gphi *inner_phi
8949 = find_phi_with_arg_on_edge (exit_res, latch_to_l1);
8950
8951 tree t = gimple_phi_result (exit_phi);
8952 tree new_res = copy_ssa_name (t, NULL);
8953 nphi = create_phi_node (new_res, l0_bb);
8954
8955 edge l0_to_l1 = find_edge (l0_bb, l1_bb);
8956 t = PHI_ARG_DEF_FROM_EDGE (inner_phi, l0_to_l1);
8957 locus = gimple_phi_arg_location_from_edge (inner_phi, l0_to_l1);
8958 edge entry_to_l0 = find_edge (entry_bb, l0_bb);
8959 add_phi_arg (nphi, t, entry_to_l0, locus);
8960
8961 edge l2_to_l0 = find_edge (l2_bb, l0_bb);
8962 add_phi_arg (nphi, exit_res, l2_to_l0, UNKNOWN_LOCATION);
8963
8964 add_phi_arg (inner_phi, new_res, l0_to_l1, UNKNOWN_LOCATION);
8965 };
8966 }
8967
79acaae1 8968 set_immediate_dominator (CDI_DOMINATORS, l2_bb,
8969 recompute_dominator (CDI_DOMINATORS, l2_bb));
8970 set_immediate_dominator (CDI_DOMINATORS, l3_bb,
8971 recompute_dominator (CDI_DOMINATORS, l3_bb));
8972 set_immediate_dominator (CDI_DOMINATORS, l0_bb,
8973 recompute_dominator (CDI_DOMINATORS, l0_bb));
8974 set_immediate_dominator (CDI_DOMINATORS, l1_bb,
8975 recompute_dominator (CDI_DOMINATORS, l1_bb));
04c2922b 8976
1c6a437b 8977 /* We enter expand_omp_for_generic with a loop. This original loop may
8978 have its own loop struct, or it may be part of an outer loop struct
8979 (which may be the fake loop). */
8980 struct loop *outer_loop = entry_bb->loop_father;
8981 bool orig_loop_has_loop_struct = l1_bb->loop_father != outer_loop;
8982
8983 add_bb_to_loop (l2_bb, outer_loop);
8984
8985 /* We've added a new loop around the original loop. Allocate the
8986 corresponding loop struct. */
8987 struct loop *new_loop = alloc_loop ();
8988 new_loop->header = l0_bb;
8989 new_loop->latch = l2_bb;
8990 add_loop (new_loop, outer_loop);
8991
8992 /* Allocate a loop structure for the original loop unless we already
8993 had one. */
8994 if (!orig_loop_has_loop_struct
8995 && !gimple_omp_for_combined_p (fd->for_stmt))
3d483a94 8996 {
1c6a437b 8997 struct loop *orig_loop = alloc_loop ();
8998 orig_loop->header = l1_bb;
3d483a94 8999 /* The loop may have multiple latches. */
1c6a437b 9000 add_loop (orig_loop, new_loop);
3d483a94 9001 }
ac6e3339 9002 }
1e8e9920 9003}
9004
9005
773c5ba7 9006/* A subroutine of expand_omp_for. Generate code for a parallel
9007 loop with static schedule and no specified chunk size. Given
9008 parameters:
1e8e9920 9009
9010 for (V = N1; V cond N2; V += STEP) BODY;
9011
9012 where COND is "<" or ">", we generate pseudocode
9013
8e6b4515 9014 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
1e8e9920 9015 if (cond is <)
9016 adj = STEP - 1;
9017 else
9018 adj = STEP + 1;
fd6481cf 9019 if ((__typeof (V)) -1 > 0 && cond is >)
9020 n = -(adj + N2 - N1) / -STEP;
9021 else
9022 n = (adj + N2 - N1) / STEP;
1e8e9920 9023 q = n / nthreads;
31712e83 9024 tt = n % nthreads;
9025 if (threadid < tt) goto L3; else goto L4;
9026 L3:
9027 tt = 0;
9028 q = q + 1;
9029 L4:
9030 s0 = q * threadid + tt;
9031 e0 = s0 + q;
79acaae1 9032 V = s0 * STEP + N1;
1e8e9920 9033 if (s0 >= e0) goto L2; else goto L0;
9034 L0:
1e8e9920 9035 e = e0 * STEP + N1;
9036 L1:
9037 BODY;
9038 V += STEP;
9039 if (V cond e) goto L1;
1e8e9920 9040 L2:
9041*/
9042
61e47ac8 9043static void
773c5ba7 9044expand_omp_for_static_nochunk (struct omp_region *region,
bc7bff74 9045 struct omp_for_data *fd,
42acab1c 9046 gimple *inner_stmt)
1e8e9920 9047{
31712e83 9048 tree n, q, s0, e0, e, t, tt, nthreads, threadid;
fd6481cf 9049 tree type, itype, vmain, vback;
31712e83 9050 basic_block entry_bb, second_bb, third_bb, exit_bb, seq_start_bb;
bc7bff74 9051 basic_block body_bb, cont_bb, collapse_bb = NULL;
61e47ac8 9052 basic_block fin_bb;
75a70cf9 9053 gimple_stmt_iterator gsi;
31712e83 9054 edge ep;
bc7bff74 9055 bool broken_loop = region->cont == NULL;
9056 tree *counts = NULL;
9057 tree n1, n2, step;
1e8e9920 9058
fd6481cf 9059 itype = type = TREE_TYPE (fd->loop.v);
9060 if (POINTER_TYPE_P (type))
3cea8318 9061 itype = signed_type_for (type);
1e8e9920 9062
61e47ac8 9063 entry_bb = region->entry;
61e47ac8 9064 cont_bb = region->cont;
ac6e3339 9065 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
bc7bff74 9066 fin_bb = BRANCH_EDGE (entry_bb)->dest;
9067 gcc_assert (broken_loop
9068 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
ac6e3339 9069 seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb));
9070 body_bb = single_succ (seq_start_bb);
bc7bff74 9071 if (!broken_loop)
9072 {
86a932e0 9073 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb
9074 || single_succ (BRANCH_EDGE (cont_bb)->dest) == body_bb);
bc7bff74 9075 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
9076 }
61e47ac8 9077 exit_bb = region->exit;
9078
773c5ba7 9079 /* Iteration space partitioning goes in ENTRY_BB. */
75a70cf9 9080 gsi = gsi_last_bb (entry_bb);
9081 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
61e47ac8 9082
bc7bff74 9083 if (fd->collapse > 1)
9084 {
43895be5 9085 int first_zero_iter = -1, dummy = -1;
9086 basic_block l2_dom_bb = NULL, dummy_bb = NULL;
bc7bff74 9087
9088 counts = XALLOCAVEC (tree, fd->collapse);
9089 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
9090 fin_bb, first_zero_iter,
43895be5 9091 dummy_bb, dummy, l2_dom_bb);
bc7bff74 9092 t = NULL_TREE;
9093 }
9094 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
9095 t = integer_one_node;
9096 else
9097 t = fold_binary (fd->loop.cond_code, boolean_type_node,
9098 fold_convert (type, fd->loop.n1),
9099 fold_convert (type, fd->loop.n2));
9100 if (fd->collapse == 1
9101 && TYPE_UNSIGNED (type)
8e6b4515 9102 && (t == NULL_TREE || !integer_onep (t)))
9103 {
8e6b4515 9104 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
9105 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
9106 true, GSI_SAME_STMT);
9107 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
9108 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
9109 true, GSI_SAME_STMT);
1a91d914 9110 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
9111 NULL_TREE, NULL_TREE);
9112 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
9113 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
8e6b4515 9114 expand_omp_regimplify_p, NULL, NULL)
1a91d914 9115 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
8e6b4515 9116 expand_omp_regimplify_p, NULL, NULL))
9117 {
1a91d914 9118 gsi = gsi_for_stmt (cond_stmt);
9119 gimple_regimplify_operands (cond_stmt, &gsi);
8e6b4515 9120 }
1a91d914 9121 ep = split_block (entry_bb, cond_stmt);
8e6b4515 9122 ep->flags = EDGE_TRUE_VALUE;
9123 entry_bb = ep->dest;
9124 ep->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
9125 ep = make_edge (ep->src, fin_bb, EDGE_FALSE_VALUE);
9126 ep->probability = REG_BR_PROB_BASE / 2000 - 1;
9127 if (gimple_in_ssa_p (cfun))
9128 {
9129 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
1a91d914 9130 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
9131 !gsi_end_p (gpi); gsi_next (&gpi))
8e6b4515 9132 {
1a91d914 9133 gphi *phi = gpi.phi ();
8e6b4515 9134 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
9135 ep, UNKNOWN_LOCATION);
9136 }
9137 }
9138 gsi = gsi_last_bb (entry_bb);
9139 }
9140
ca4c3545 9141 switch (gimple_omp_for_kind (fd->for_stmt))
9142 {
9143 case GF_OMP_FOR_KIND_FOR:
9144 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
9145 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
9146 break;
9147 case GF_OMP_FOR_KIND_DISTRIBUTE:
9148 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
9149 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
9150 break;
ca4c3545 9151 default:
9152 gcc_unreachable ();
9153 }
9154 nthreads = build_call_expr (nthreads, 0);
9155 nthreads = fold_convert (itype, nthreads);
9156 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
75a70cf9 9157 true, GSI_SAME_STMT);
ca4c3545 9158 threadid = build_call_expr (threadid, 0);
9159 threadid = fold_convert (itype, threadid);
9160 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
75a70cf9 9161 true, GSI_SAME_STMT);
1e8e9920 9162
bc7bff74 9163 n1 = fd->loop.n1;
9164 n2 = fd->loop.n2;
9165 step = fd->loop.step;
9166 if (gimple_omp_for_combined_into_p (fd->for_stmt))
9167 {
9168 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
9169 OMP_CLAUSE__LOOPTEMP_);
9170 gcc_assert (innerc);
9171 n1 = OMP_CLAUSE_DECL (innerc);
9172 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9173 OMP_CLAUSE__LOOPTEMP_);
9174 gcc_assert (innerc);
9175 n2 = OMP_CLAUSE_DECL (innerc);
9176 }
9177 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
9178 true, NULL_TREE, true, GSI_SAME_STMT);
9179 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
9180 true, NULL_TREE, true, GSI_SAME_STMT);
9181 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
9182 true, NULL_TREE, true, GSI_SAME_STMT);
fd6481cf 9183
9184 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
bc7bff74 9185 t = fold_build2 (PLUS_EXPR, itype, step, t);
9186 t = fold_build2 (PLUS_EXPR, itype, t, n2);
9187 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
fd6481cf 9188 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
9189 t = fold_build2 (TRUNC_DIV_EXPR, itype,
9190 fold_build1 (NEGATE_EXPR, itype, t),
bc7bff74 9191 fold_build1 (NEGATE_EXPR, itype, step));
fd6481cf 9192 else
bc7bff74 9193 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
fd6481cf 9194 t = fold_convert (itype, t);
75a70cf9 9195 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
1e8e9920 9196
072f7ab1 9197 q = create_tmp_reg (itype, "q");
fd6481cf 9198 t = fold_build2 (TRUNC_DIV_EXPR, itype, n, nthreads);
31712e83 9199 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
9200 gsi_insert_before (&gsi, gimple_build_assign (q, t), GSI_SAME_STMT);
9201
072f7ab1 9202 tt = create_tmp_reg (itype, "tt");
31712e83 9203 t = fold_build2 (TRUNC_MOD_EXPR, itype, n, nthreads);
9204 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
9205 gsi_insert_before (&gsi, gimple_build_assign (tt, t), GSI_SAME_STMT);
1e8e9920 9206
31712e83 9207 t = build2 (LT_EXPR, boolean_type_node, threadid, tt);
1a91d914 9208 gcond *cond_stmt = gimple_build_cond_empty (t);
9209 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
31712e83 9210
1a91d914 9211 second_bb = split_block (entry_bb, cond_stmt)->dest;
31712e83 9212 gsi = gsi_last_bb (second_bb);
9213 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
9214
9215 gsi_insert_before (&gsi, gimple_build_assign (tt, build_int_cst (itype, 0)),
9216 GSI_SAME_STMT);
1a91d914 9217 gassign *assign_stmt
e9cf809e 9218 = gimple_build_assign (q, PLUS_EXPR, q, build_int_cst (itype, 1));
1a91d914 9219 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
31712e83 9220
1a91d914 9221 third_bb = split_block (second_bb, assign_stmt)->dest;
31712e83 9222 gsi = gsi_last_bb (third_bb);
9223 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
1e8e9920 9224
fd6481cf 9225 t = build2 (MULT_EXPR, itype, q, threadid);
31712e83 9226 t = build2 (PLUS_EXPR, itype, t, tt);
75a70cf9 9227 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
1e8e9920 9228
fd6481cf 9229 t = fold_build2 (PLUS_EXPR, itype, s0, q);
75a70cf9 9230 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
79acaae1 9231
1e8e9920 9232 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
75a70cf9 9233 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
773c5ba7 9234
75a70cf9 9235 /* Remove the GIMPLE_OMP_FOR statement. */
9236 gsi_remove (&gsi, true);
773c5ba7 9237
9238 /* Setup code for sequential iteration goes in SEQ_START_BB. */
75a70cf9 9239 gsi = gsi_start_bb (seq_start_bb);
1e8e9920 9240
bc7bff74 9241 tree startvar = fd->loop.v;
9242 tree endvar = NULL_TREE;
9243
9244 if (gimple_omp_for_combined_p (fd->for_stmt))
9245 {
9246 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
9247 ? gimple_omp_parallel_clauses (inner_stmt)
9248 : gimple_omp_for_clauses (inner_stmt);
9249 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
9250 gcc_assert (innerc);
9251 startvar = OMP_CLAUSE_DECL (innerc);
9252 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9253 OMP_CLAUSE__LOOPTEMP_);
9254 gcc_assert (innerc);
9255 endvar = OMP_CLAUSE_DECL (innerc);
9561765e 9256 if (fd->collapse > 1 && TREE_CODE (fd->loop.n2) != INTEGER_CST
9257 && gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
9258 {
9259 int i;
9260 for (i = 1; i < fd->collapse; i++)
9261 {
9262 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9263 OMP_CLAUSE__LOOPTEMP_);
9264 gcc_assert (innerc);
9265 }
9266 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9267 OMP_CLAUSE__LOOPTEMP_);
9268 if (innerc)
9269 {
9270 /* If needed (distribute parallel for with lastprivate),
9271 propagate down the total number of iterations. */
9272 tree t = fold_convert (TREE_TYPE (OMP_CLAUSE_DECL (innerc)),
9273 fd->loop.n2);
9274 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, false,
9275 GSI_CONTINUE_LINKING);
9276 assign_stmt = gimple_build_assign (OMP_CLAUSE_DECL (innerc), t);
9277 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9278 }
9279 }
bc7bff74 9280 }
fd6481cf 9281 t = fold_convert (itype, s0);
bc7bff74 9282 t = fold_build2 (MULT_EXPR, itype, t, step);
fd6481cf 9283 if (POINTER_TYPE_P (type))
bc7bff74 9284 t = fold_build_pointer_plus (n1, t);
fd6481cf 9285 else
bc7bff74 9286 t = fold_build2 (PLUS_EXPR, type, t, n1);
9287 t = fold_convert (TREE_TYPE (startvar), t);
4abecb72 9288 t = force_gimple_operand_gsi (&gsi, t,
bc7bff74 9289 DECL_P (startvar)
9290 && TREE_ADDRESSABLE (startvar),
4abecb72 9291 NULL_TREE, false, GSI_CONTINUE_LINKING);
1a91d914 9292 assign_stmt = gimple_build_assign (startvar, t);
9293 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
48e1416a 9294
fd6481cf 9295 t = fold_convert (itype, e0);
bc7bff74 9296 t = fold_build2 (MULT_EXPR, itype, t, step);
fd6481cf 9297 if (POINTER_TYPE_P (type))
bc7bff74 9298 t = fold_build_pointer_plus (n1, t);
fd6481cf 9299 else
bc7bff74 9300 t = fold_build2 (PLUS_EXPR, type, t, n1);
9301 t = fold_convert (TREE_TYPE (startvar), t);
75a70cf9 9302 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9303 false, GSI_CONTINUE_LINKING);
bc7bff74 9304 if (endvar)
9305 {
1a91d914 9306 assign_stmt = gimple_build_assign (endvar, e);
9307 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
d44f2f7c 9308 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
1a91d914 9309 assign_stmt = gimple_build_assign (fd->loop.v, e);
d44f2f7c 9310 else
e9cf809e 9311 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
1a91d914 9312 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
bc7bff74 9313 }
43895be5 9314 /* Handle linear clause adjustments. */
9315 tree itercnt = NULL_TREE;
9316 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_FOR)
9317 for (tree c = gimple_omp_for_clauses (fd->for_stmt);
9318 c; c = OMP_CLAUSE_CHAIN (c))
9319 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
9320 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
9321 {
9322 tree d = OMP_CLAUSE_DECL (c);
9323 bool is_ref = is_reference (d);
9324 tree t = d, a, dest;
9325 if (is_ref)
9326 t = build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c), t);
9327 if (itercnt == NULL_TREE)
9328 {
9329 if (gimple_omp_for_combined_into_p (fd->for_stmt))
9330 {
9331 itercnt = fold_build2 (MINUS_EXPR, itype,
9332 fold_convert (itype, n1),
9333 fold_convert (itype, fd->loop.n1));
9334 itercnt = fold_build2 (EXACT_DIV_EXPR, itype, itercnt, step);
9335 itercnt = fold_build2 (PLUS_EXPR, itype, itercnt, s0);
9336 itercnt = force_gimple_operand_gsi (&gsi, itercnt, true,
9337 NULL_TREE, false,
9338 GSI_CONTINUE_LINKING);
9339 }
9340 else
9341 itercnt = s0;
9342 }
9343 tree type = TREE_TYPE (t);
9344 if (POINTER_TYPE_P (type))
9345 type = sizetype;
9346 a = fold_build2 (MULT_EXPR, type,
9347 fold_convert (type, itercnt),
9348 fold_convert (type, OMP_CLAUSE_LINEAR_STEP (c)));
9349 dest = unshare_expr (t);
9350 t = fold_build2 (type == TREE_TYPE (t) ? PLUS_EXPR
9351 : POINTER_PLUS_EXPR, TREE_TYPE (t), t, a);
9352 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9353 false, GSI_CONTINUE_LINKING);
9354 assign_stmt = gimple_build_assign (dest, t);
9355 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9356 }
bc7bff74 9357 if (fd->collapse > 1)
9358 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
1e8e9920 9359
bc7bff74 9360 if (!broken_loop)
9361 {
9362 /* The code controlling the sequential loop replaces the
9363 GIMPLE_OMP_CONTINUE. */
9364 gsi = gsi_last_bb (cont_bb);
1a91d914 9365 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
9366 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
9367 vmain = gimple_omp_continue_control_use (cont_stmt);
9368 vback = gimple_omp_continue_control_def (cont_stmt);
79acaae1 9369
bc7bff74 9370 if (!gimple_omp_for_combined_p (fd->for_stmt))
9371 {
9372 if (POINTER_TYPE_P (type))
9373 t = fold_build_pointer_plus (vmain, step);
9374 else
9375 t = fold_build2 (PLUS_EXPR, type, vmain, step);
9376 t = force_gimple_operand_gsi (&gsi, t,
9377 DECL_P (vback)
9378 && TREE_ADDRESSABLE (vback),
9379 NULL_TREE, true, GSI_SAME_STMT);
1a91d914 9380 assign_stmt = gimple_build_assign (vback, t);
9381 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
79acaae1 9382
bc7bff74 9383 t = build2 (fd->loop.cond_code, boolean_type_node,
9384 DECL_P (vback) && TREE_ADDRESSABLE (vback)
9385 ? t : vback, e);
9386 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
9387 }
1e8e9920 9388
bc7bff74 9389 /* Remove the GIMPLE_OMP_CONTINUE statement. */
9390 gsi_remove (&gsi, true);
9391
9392 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
9393 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
9394 }
773c5ba7 9395
75a70cf9 9396 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
9397 gsi = gsi_last_bb (exit_bb);
9398 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
bc7bff74 9399 {
9400 t = gimple_omp_return_lhs (gsi_stmt (gsi));
a8e785ba 9401 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
bc7bff74 9402 }
75a70cf9 9403 gsi_remove (&gsi, true);
773c5ba7 9404
9405 /* Connect all the blocks. */
31712e83 9406 ep = make_edge (entry_bb, third_bb, EDGE_FALSE_VALUE);
9407 ep->probability = REG_BR_PROB_BASE / 4 * 3;
9408 ep = find_edge (entry_bb, second_bb);
9409 ep->flags = EDGE_TRUE_VALUE;
9410 ep->probability = REG_BR_PROB_BASE / 4;
9411 find_edge (third_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
9412 find_edge (third_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
79acaae1 9413
bc7bff74 9414 if (!broken_loop)
9415 {
9416 ep = find_edge (cont_bb, body_bb);
86a932e0 9417 if (ep == NULL)
9418 {
9419 ep = BRANCH_EDGE (cont_bb);
9420 gcc_assert (single_succ (ep->dest) == body_bb);
9421 }
bc7bff74 9422 if (gimple_omp_for_combined_p (fd->for_stmt))
9423 {
9424 remove_edge (ep);
9425 ep = NULL;
9426 }
9427 else if (fd->collapse > 1)
9428 {
9429 remove_edge (ep);
9430 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
9431 }
9432 else
9433 ep->flags = EDGE_TRUE_VALUE;
9434 find_edge (cont_bb, fin_bb)->flags
9435 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
9436 }
48e1416a 9437
31712e83 9438 set_immediate_dominator (CDI_DOMINATORS, second_bb, entry_bb);
9439 set_immediate_dominator (CDI_DOMINATORS, third_bb, entry_bb);
9440 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, third_bb);
bc7bff74 9441
79acaae1 9442 set_immediate_dominator (CDI_DOMINATORS, body_bb,
9443 recompute_dominator (CDI_DOMINATORS, body_bb));
9444 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
9445 recompute_dominator (CDI_DOMINATORS, fin_bb));
04c2922b 9446
86a932e0 9447 struct loop *loop = body_bb->loop_father;
9448 if (loop != entry_bb->loop_father)
9449 {
9450 gcc_assert (loop->header == body_bb);
9451 gcc_assert (broken_loop
9452 || loop->latch == region->cont
9453 || single_pred (loop->latch) == region->cont);
9454 return;
9455 }
9456
bc7bff74 9457 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
9458 {
86a932e0 9459 loop = alloc_loop ();
bc7bff74 9460 loop->header = body_bb;
9461 if (collapse_bb == NULL)
9462 loop->latch = cont_bb;
9463 add_loop (loop, body_bb->loop_father);
9464 }
1e8e9920 9465}
9466
281001a9 9467/* Return phi in E->DEST with ARG on edge E. */
9468
9469static gphi *
9470find_phi_with_arg_on_edge (tree arg, edge e)
9471{
9472 basic_block bb = e->dest;
9473
9474 for (gphi_iterator gpi = gsi_start_phis (bb);
9475 !gsi_end_p (gpi);
9476 gsi_next (&gpi))
9477 {
9478 gphi *phi = gpi.phi ();
9479 if (PHI_ARG_DEF_FROM_EDGE (phi, e) == arg)
9480 return phi;
9481 }
9482
9483 return NULL;
9484}
773c5ba7 9485
9486/* A subroutine of expand_omp_for. Generate code for a parallel
9487 loop with static schedule and a specified chunk size. Given
9488 parameters:
1e8e9920 9489
9490 for (V = N1; V cond N2; V += STEP) BODY;
9491
9492 where COND is "<" or ">", we generate pseudocode
9493
8e6b4515 9494 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
1e8e9920 9495 if (cond is <)
9496 adj = STEP - 1;
9497 else
9498 adj = STEP + 1;
fd6481cf 9499 if ((__typeof (V)) -1 > 0 && cond is >)
9500 n = -(adj + N2 - N1) / -STEP;
9501 else
9502 n = (adj + N2 - N1) / STEP;
1e8e9920 9503 trip = 0;
79acaae1 9504 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
9505 here so that V is defined
9506 if the loop is not entered
1e8e9920 9507 L0:
9508 s0 = (trip * nthreads + threadid) * CHUNK;
9509 e0 = min(s0 + CHUNK, n);
9510 if (s0 < n) goto L1; else goto L4;
9511 L1:
9512 V = s0 * STEP + N1;
9513 e = e0 * STEP + N1;
9514 L2:
9515 BODY;
9516 V += STEP;
9517 if (V cond e) goto L2; else goto L3;
9518 L3:
9519 trip += 1;
9520 goto L0;
9521 L4:
1e8e9920 9522*/
9523
61e47ac8 9524static void
bc7bff74 9525expand_omp_for_static_chunk (struct omp_region *region,
42acab1c 9526 struct omp_for_data *fd, gimple *inner_stmt)
1e8e9920 9527{
75a70cf9 9528 tree n, s0, e0, e, t;
79acaae1 9529 tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
93481288 9530 tree type, itype, vmain, vback, vextra;
773c5ba7 9531 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
bc7bff74 9532 basic_block trip_update_bb = NULL, cont_bb, collapse_bb = NULL, fin_bb;
93481288 9533 gimple_stmt_iterator gsi;
75a70cf9 9534 edge se;
bc7bff74 9535 bool broken_loop = region->cont == NULL;
9536 tree *counts = NULL;
9537 tree n1, n2, step;
1e8e9920 9538
fd6481cf 9539 itype = type = TREE_TYPE (fd->loop.v);
9540 if (POINTER_TYPE_P (type))
3cea8318 9541 itype = signed_type_for (type);
1e8e9920 9542
61e47ac8 9543 entry_bb = region->entry;
ac6e3339 9544 se = split_block (entry_bb, last_stmt (entry_bb));
9545 entry_bb = se->src;
9546 iter_part_bb = se->dest;
61e47ac8 9547 cont_bb = region->cont;
ac6e3339 9548 gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
bc7bff74 9549 fin_bb = BRANCH_EDGE (iter_part_bb)->dest;
9550 gcc_assert (broken_loop
9551 || fin_bb == FALLTHRU_EDGE (cont_bb)->dest);
ac6e3339 9552 seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
9553 body_bb = single_succ (seq_start_bb);
bc7bff74 9554 if (!broken_loop)
9555 {
fc1d58e3 9556 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb
9557 || single_succ (BRANCH_EDGE (cont_bb)->dest) == body_bb);
bc7bff74 9558 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
9559 trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
9560 }
61e47ac8 9561 exit_bb = region->exit;
773c5ba7 9562
773c5ba7 9563 /* Trip and adjustment setup goes in ENTRY_BB. */
93481288 9564 gsi = gsi_last_bb (entry_bb);
9565 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
773c5ba7 9566
bc7bff74 9567 if (fd->collapse > 1)
9568 {
43895be5 9569 int first_zero_iter = -1, dummy = -1;
9570 basic_block l2_dom_bb = NULL, dummy_bb = NULL;
bc7bff74 9571
9572 counts = XALLOCAVEC (tree, fd->collapse);
93481288 9573 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
bc7bff74 9574 fin_bb, first_zero_iter,
43895be5 9575 dummy_bb, dummy, l2_dom_bb);
bc7bff74 9576 t = NULL_TREE;
9577 }
9578 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
9579 t = integer_one_node;
9580 else
9581 t = fold_binary (fd->loop.cond_code, boolean_type_node,
9582 fold_convert (type, fd->loop.n1),
9583 fold_convert (type, fd->loop.n2));
9584 if (fd->collapse == 1
9585 && TYPE_UNSIGNED (type)
8e6b4515 9586 && (t == NULL_TREE || !integer_onep (t)))
9587 {
8e6b4515 9588 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
93481288 9589 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
8e6b4515 9590 true, GSI_SAME_STMT);
9591 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
93481288 9592 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
8e6b4515 9593 true, GSI_SAME_STMT);
1a91d914 9594 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
9595 NULL_TREE, NULL_TREE);
9596 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
9597 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
8e6b4515 9598 expand_omp_regimplify_p, NULL, NULL)
1a91d914 9599 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
8e6b4515 9600 expand_omp_regimplify_p, NULL, NULL))
9601 {
1a91d914 9602 gsi = gsi_for_stmt (cond_stmt);
9603 gimple_regimplify_operands (cond_stmt, &gsi);
8e6b4515 9604 }
1a91d914 9605 se = split_block (entry_bb, cond_stmt);
8e6b4515 9606 se->flags = EDGE_TRUE_VALUE;
9607 entry_bb = se->dest;
9608 se->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
9609 se = make_edge (se->src, fin_bb, EDGE_FALSE_VALUE);
9610 se->probability = REG_BR_PROB_BASE / 2000 - 1;
9611 if (gimple_in_ssa_p (cfun))
9612 {
264aa959 9613 int dest_idx = find_edge (iter_part_bb, fin_bb)->dest_idx;
1a91d914 9614 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
9615 !gsi_end_p (gpi); gsi_next (&gpi))
8e6b4515 9616 {
1a91d914 9617 gphi *phi = gpi.phi ();
8e6b4515 9618 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
9619 se, UNKNOWN_LOCATION);
9620 }
9621 }
93481288 9622 gsi = gsi_last_bb (entry_bb);
8e6b4515 9623 }
9624
ca4c3545 9625 switch (gimple_omp_for_kind (fd->for_stmt))
9626 {
9627 case GF_OMP_FOR_KIND_FOR:
9628 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
9629 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
9630 break;
9631 case GF_OMP_FOR_KIND_DISTRIBUTE:
9632 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
9633 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
9634 break;
ca4c3545 9635 default:
9636 gcc_unreachable ();
9637 }
9638 nthreads = build_call_expr (nthreads, 0);
9639 nthreads = fold_convert (itype, nthreads);
9640 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
75a70cf9 9641 true, GSI_SAME_STMT);
ca4c3545 9642 threadid = build_call_expr (threadid, 0);
9643 threadid = fold_convert (itype, threadid);
9644 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
75a70cf9 9645 true, GSI_SAME_STMT);
79acaae1 9646
bc7bff74 9647 n1 = fd->loop.n1;
9648 n2 = fd->loop.n2;
9649 step = fd->loop.step;
9650 if (gimple_omp_for_combined_into_p (fd->for_stmt))
9651 {
9652 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
9653 OMP_CLAUSE__LOOPTEMP_);
9654 gcc_assert (innerc);
9655 n1 = OMP_CLAUSE_DECL (innerc);
9656 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9657 OMP_CLAUSE__LOOPTEMP_);
9658 gcc_assert (innerc);
9659 n2 = OMP_CLAUSE_DECL (innerc);
9660 }
93481288 9661 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
bc7bff74 9662 true, NULL_TREE, true, GSI_SAME_STMT);
93481288 9663 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
bc7bff74 9664 true, NULL_TREE, true, GSI_SAME_STMT);
93481288 9665 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
bc7bff74 9666 true, NULL_TREE, true, GSI_SAME_STMT);
43895be5 9667 tree chunk_size = fold_convert (itype, fd->chunk_size);
9668 chunk_size = omp_adjust_chunk_size (chunk_size, fd->simd_schedule);
9669 chunk_size
9670 = force_gimple_operand_gsi (&gsi, chunk_size, true, NULL_TREE, true,
9671 GSI_SAME_STMT);
fd6481cf 9672
9673 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
bc7bff74 9674 t = fold_build2 (PLUS_EXPR, itype, step, t);
9675 t = fold_build2 (PLUS_EXPR, itype, t, n2);
9676 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
fd6481cf 9677 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
9678 t = fold_build2 (TRUNC_DIV_EXPR, itype,
9679 fold_build1 (NEGATE_EXPR, itype, t),
bc7bff74 9680 fold_build1 (NEGATE_EXPR, itype, step));
fd6481cf 9681 else
bc7bff74 9682 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
fd6481cf 9683 t = fold_convert (itype, t);
93481288 9684 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
75a70cf9 9685 true, GSI_SAME_STMT);
79acaae1 9686
083152fb 9687 trip_var = create_tmp_reg (itype, ".trip");
79acaae1 9688 if (gimple_in_ssa_p (cfun))
9689 {
f9e245b2 9690 trip_init = make_ssa_name (trip_var);
9691 trip_main = make_ssa_name (trip_var);
9692 trip_back = make_ssa_name (trip_var);
79acaae1 9693 }
1e8e9920 9694 else
79acaae1 9695 {
9696 trip_init = trip_var;
9697 trip_main = trip_var;
9698 trip_back = trip_var;
9699 }
1e8e9920 9700
1a91d914 9701 gassign *assign_stmt
9702 = gimple_build_assign (trip_init, build_int_cst (itype, 0));
9703 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
773c5ba7 9704
43895be5 9705 t = fold_build2 (MULT_EXPR, itype, threadid, chunk_size);
bc7bff74 9706 t = fold_build2 (MULT_EXPR, itype, t, step);
fd6481cf 9707 if (POINTER_TYPE_P (type))
bc7bff74 9708 t = fold_build_pointer_plus (n1, t);
fd6481cf 9709 else
bc7bff74 9710 t = fold_build2 (PLUS_EXPR, type, t, n1);
93481288 9711 vextra = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9712 true, GSI_SAME_STMT);
79acaae1 9713
75a70cf9 9714 /* Remove the GIMPLE_OMP_FOR. */
93481288 9715 gsi_remove (&gsi, true);
773c5ba7 9716
43895be5 9717 gimple_stmt_iterator gsif = gsi;
9718
773c5ba7 9719 /* Iteration space partitioning goes in ITER_PART_BB. */
93481288 9720 gsi = gsi_last_bb (iter_part_bb);
1e8e9920 9721
fd6481cf 9722 t = fold_build2 (MULT_EXPR, itype, trip_main, nthreads);
9723 t = fold_build2 (PLUS_EXPR, itype, t, threadid);
43895be5 9724 t = fold_build2 (MULT_EXPR, itype, t, chunk_size);
93481288 9725 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
75a70cf9 9726 false, GSI_CONTINUE_LINKING);
1e8e9920 9727
43895be5 9728 t = fold_build2 (PLUS_EXPR, itype, s0, chunk_size);
fd6481cf 9729 t = fold_build2 (MIN_EXPR, itype, t, n);
93481288 9730 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
75a70cf9 9731 false, GSI_CONTINUE_LINKING);
1e8e9920 9732
9733 t = build2 (LT_EXPR, boolean_type_node, s0, n);
93481288 9734 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_CONTINUE_LINKING);
773c5ba7 9735
9736 /* Setup code for sequential iteration goes in SEQ_START_BB. */
93481288 9737 gsi = gsi_start_bb (seq_start_bb);
1e8e9920 9738
bc7bff74 9739 tree startvar = fd->loop.v;
9740 tree endvar = NULL_TREE;
9741
9742 if (gimple_omp_for_combined_p (fd->for_stmt))
9743 {
9744 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
9745 ? gimple_omp_parallel_clauses (inner_stmt)
9746 : gimple_omp_for_clauses (inner_stmt);
9747 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
9748 gcc_assert (innerc);
9749 startvar = OMP_CLAUSE_DECL (innerc);
9750 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9751 OMP_CLAUSE__LOOPTEMP_);
9752 gcc_assert (innerc);
9753 endvar = OMP_CLAUSE_DECL (innerc);
9561765e 9754 if (fd->collapse > 1 && TREE_CODE (fd->loop.n2) != INTEGER_CST
9755 && gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
9756 {
9757 int i;
9758 for (i = 1; i < fd->collapse; i++)
9759 {
9760 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9761 OMP_CLAUSE__LOOPTEMP_);
9762 gcc_assert (innerc);
9763 }
9764 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9765 OMP_CLAUSE__LOOPTEMP_);
9766 if (innerc)
9767 {
9768 /* If needed (distribute parallel for with lastprivate),
9769 propagate down the total number of iterations. */
9770 tree t = fold_convert (TREE_TYPE (OMP_CLAUSE_DECL (innerc)),
9771 fd->loop.n2);
9772 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, false,
9773 GSI_CONTINUE_LINKING);
9774 assign_stmt = gimple_build_assign (OMP_CLAUSE_DECL (innerc), t);
9775 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9776 }
9777 }
bc7bff74 9778 }
9779
fd6481cf 9780 t = fold_convert (itype, s0);
bc7bff74 9781 t = fold_build2 (MULT_EXPR, itype, t, step);
fd6481cf 9782 if (POINTER_TYPE_P (type))
bc7bff74 9783 t = fold_build_pointer_plus (n1, t);
fd6481cf 9784 else
bc7bff74 9785 t = fold_build2 (PLUS_EXPR, type, t, n1);
9786 t = fold_convert (TREE_TYPE (startvar), t);
93481288 9787 t = force_gimple_operand_gsi (&gsi, t,
bc7bff74 9788 DECL_P (startvar)
9789 && TREE_ADDRESSABLE (startvar),
4abecb72 9790 NULL_TREE, false, GSI_CONTINUE_LINKING);
1a91d914 9791 assign_stmt = gimple_build_assign (startvar, t);
9792 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
1e8e9920 9793
fd6481cf 9794 t = fold_convert (itype, e0);
bc7bff74 9795 t = fold_build2 (MULT_EXPR, itype, t, step);
fd6481cf 9796 if (POINTER_TYPE_P (type))
bc7bff74 9797 t = fold_build_pointer_plus (n1, t);
fd6481cf 9798 else
bc7bff74 9799 t = fold_build2 (PLUS_EXPR, type, t, n1);
9800 t = fold_convert (TREE_TYPE (startvar), t);
93481288 9801 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
75a70cf9 9802 false, GSI_CONTINUE_LINKING);
bc7bff74 9803 if (endvar)
9804 {
1a91d914 9805 assign_stmt = gimple_build_assign (endvar, e);
9806 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
d44f2f7c 9807 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
1a91d914 9808 assign_stmt = gimple_build_assign (fd->loop.v, e);
d44f2f7c 9809 else
e9cf809e 9810 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
1a91d914 9811 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
bc7bff74 9812 }
43895be5 9813 /* Handle linear clause adjustments. */
9814 tree itercnt = NULL_TREE, itercntbias = NULL_TREE;
9815 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_FOR)
9816 for (tree c = gimple_omp_for_clauses (fd->for_stmt);
9817 c; c = OMP_CLAUSE_CHAIN (c))
9818 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
9819 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
9820 {
9821 tree d = OMP_CLAUSE_DECL (c);
9822 bool is_ref = is_reference (d);
9823 tree t = d, a, dest;
9824 if (is_ref)
9825 t = build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c), t);
9826 tree type = TREE_TYPE (t);
9827 if (POINTER_TYPE_P (type))
9828 type = sizetype;
9829 dest = unshare_expr (t);
9830 tree v = create_tmp_var (TREE_TYPE (t), NULL);
9831 expand_omp_build_assign (&gsif, v, t);
9832 if (itercnt == NULL_TREE)
9833 {
9834 if (gimple_omp_for_combined_into_p (fd->for_stmt))
9835 {
9836 itercntbias
9837 = fold_build2 (MINUS_EXPR, itype, fold_convert (itype, n1),
9838 fold_convert (itype, fd->loop.n1));
9839 itercntbias = fold_build2 (EXACT_DIV_EXPR, itype,
9840 itercntbias, step);
9841 itercntbias
9842 = force_gimple_operand_gsi (&gsif, itercntbias, true,
9843 NULL_TREE, true,
9844 GSI_SAME_STMT);
9845 itercnt = fold_build2 (PLUS_EXPR, itype, itercntbias, s0);
9846 itercnt = force_gimple_operand_gsi (&gsi, itercnt, true,
9847 NULL_TREE, false,
9848 GSI_CONTINUE_LINKING);
9849 }
9850 else
9851 itercnt = s0;
9852 }
9853 a = fold_build2 (MULT_EXPR, type,
9854 fold_convert (type, itercnt),
9855 fold_convert (type, OMP_CLAUSE_LINEAR_STEP (c)));
9856 t = fold_build2 (type == TREE_TYPE (t) ? PLUS_EXPR
9857 : POINTER_PLUS_EXPR, TREE_TYPE (t), v, a);
9858 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9859 false, GSI_CONTINUE_LINKING);
9860 assign_stmt = gimple_build_assign (dest, t);
9861 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9862 }
bc7bff74 9863 if (fd->collapse > 1)
93481288 9864 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
bc7bff74 9865
9866 if (!broken_loop)
9867 {
9868 /* The code controlling the sequential loop goes in CONT_BB,
9869 replacing the GIMPLE_OMP_CONTINUE. */
93481288 9870 gsi = gsi_last_bb (cont_bb);
1a91d914 9871 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
9872 vmain = gimple_omp_continue_control_use (cont_stmt);
9873 vback = gimple_omp_continue_control_def (cont_stmt);
1e8e9920 9874
bc7bff74 9875 if (!gimple_omp_for_combined_p (fd->for_stmt))
9876 {
9877 if (POINTER_TYPE_P (type))
93481288 9878 t = fold_build_pointer_plus (vmain, step);
bc7bff74 9879 else
93481288 9880 t = fold_build2 (PLUS_EXPR, type, vmain, step);
9881 if (DECL_P (vback) && TREE_ADDRESSABLE (vback))
9882 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
bc7bff74 9883 true, GSI_SAME_STMT);
1a91d914 9884 assign_stmt = gimple_build_assign (vback, t);
9885 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
79acaae1 9886
345f9789 9887 if (tree_int_cst_equal (fd->chunk_size, integer_one_node))
9888 t = build2 (EQ_EXPR, boolean_type_node,
9889 build_int_cst (itype, 0),
9890 build_int_cst (itype, 1));
9891 else
9892 t = build2 (fd->loop.cond_code, boolean_type_node,
9893 DECL_P (vback) && TREE_ADDRESSABLE (vback)
9894 ? t : vback, e);
93481288 9895 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
bc7bff74 9896 }
79acaae1 9897
bc7bff74 9898 /* Remove GIMPLE_OMP_CONTINUE. */
93481288 9899 gsi_remove (&gsi, true);
48e1416a 9900
bc7bff74 9901 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
9902 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
773c5ba7 9903
bc7bff74 9904 /* Trip update code goes into TRIP_UPDATE_BB. */
93481288 9905 gsi = gsi_start_bb (trip_update_bb);
1e8e9920 9906
bc7bff74 9907 t = build_int_cst (itype, 1);
9908 t = build2 (PLUS_EXPR, itype, trip_main, t);
1a91d914 9909 assign_stmt = gimple_build_assign (trip_back, t);
9910 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
bc7bff74 9911 }
1e8e9920 9912
75a70cf9 9913 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
93481288 9914 gsi = gsi_last_bb (exit_bb);
9915 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
bc7bff74 9916 {
93481288 9917 t = gimple_omp_return_lhs (gsi_stmt (gsi));
a8e785ba 9918 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
bc7bff74 9919 }
93481288 9920 gsi_remove (&gsi, true);
1e8e9920 9921
773c5ba7 9922 /* Connect the new blocks. */
ac6e3339 9923 find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
9924 find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
79acaae1 9925
bc7bff74 9926 if (!broken_loop)
9927 {
9928 se = find_edge (cont_bb, body_bb);
fc1d58e3 9929 if (se == NULL)
9930 {
9931 se = BRANCH_EDGE (cont_bb);
9932 gcc_assert (single_succ (se->dest) == body_bb);
9933 }
bc7bff74 9934 if (gimple_omp_for_combined_p (fd->for_stmt))
9935 {
9936 remove_edge (se);
9937 se = NULL;
9938 }
9939 else if (fd->collapse > 1)
9940 {
9941 remove_edge (se);
9942 se = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
9943 }
9944 else
9945 se->flags = EDGE_TRUE_VALUE;
9946 find_edge (cont_bb, trip_update_bb)->flags
9947 = se ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
79acaae1 9948
bc7bff74 9949 redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb);
9950 }
79acaae1 9951
9952 if (gimple_in_ssa_p (cfun))
9953 {
1a91d914 9954 gphi_iterator psi;
9955 gphi *phi;
75a70cf9 9956 edge re, ene;
75a70cf9 9957 edge_var_map *vm;
9958 size_t i;
9959
bc7bff74 9960 gcc_assert (fd->collapse == 1 && !broken_loop);
9961
79acaae1 9962 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
9963 remove arguments of the phi nodes in fin_bb. We need to create
9964 appropriate phi nodes in iter_part_bb instead. */
264aa959 9965 se = find_edge (iter_part_bb, fin_bb);
79acaae1 9966 re = single_succ_edge (trip_update_bb);
06ecf488 9967 vec<edge_var_map> *head = redirect_edge_var_map_vector (re);
79acaae1 9968 ene = single_succ_edge (entry_bb);
9969
75a70cf9 9970 psi = gsi_start_phis (fin_bb);
f1f41a6c 9971 for (i = 0; !gsi_end_p (psi) && head->iterate (i, &vm);
75a70cf9 9972 gsi_next (&psi), ++i)
79acaae1 9973 {
1a91d914 9974 gphi *nphi;
efbcb6de 9975 source_location locus;
75a70cf9 9976
1a91d914 9977 phi = psi.phi ();
75a70cf9 9978 t = gimple_phi_result (phi);
9979 gcc_assert (t == redirect_edge_var_map_result (vm));
264aa959 9980
9981 if (!single_pred_p (fin_bb))
9982 t = copy_ssa_name (t, phi);
9983
79acaae1 9984 nphi = create_phi_node (t, iter_part_bb);
79acaae1 9985
9986 t = PHI_ARG_DEF_FROM_EDGE (phi, se);
efbcb6de 9987 locus = gimple_phi_arg_location_from_edge (phi, se);
9988
fd6481cf 9989 /* A special case -- fd->loop.v is not yet computed in
93481288 9990 iter_part_bb, we need to use vextra instead. */
fd6481cf 9991 if (t == fd->loop.v)
93481288 9992 t = vextra;
60d535d2 9993 add_phi_arg (nphi, t, ene, locus);
efbcb6de 9994 locus = redirect_edge_var_map_location (vm);
281001a9 9995 tree back_arg = redirect_edge_var_map_def (vm);
9996 add_phi_arg (nphi, back_arg, re, locus);
9997 edge ce = find_edge (cont_bb, body_bb);
9998 if (ce == NULL)
9999 {
10000 ce = BRANCH_EDGE (cont_bb);
10001 gcc_assert (single_succ (ce->dest) == body_bb);
10002 ce = single_succ_edge (ce->dest);
10003 }
10004 gphi *inner_loop_phi = find_phi_with_arg_on_edge (back_arg, ce);
10005 gcc_assert (inner_loop_phi != NULL);
10006 add_phi_arg (inner_loop_phi, gimple_phi_result (nphi),
10007 find_edge (seq_start_bb, body_bb), locus);
264aa959 10008
10009 if (!single_pred_p (fin_bb))
10010 add_phi_arg (phi, gimple_phi_result (nphi), se, locus);
75a70cf9 10011 }
4d556e29 10012 gcc_assert (gsi_end_p (psi) && (head == NULL || i == head->length ()));
75a70cf9 10013 redirect_edge_var_map_clear (re);
264aa959 10014 if (single_pred_p (fin_bb))
10015 while (1)
10016 {
10017 psi = gsi_start_phis (fin_bb);
10018 if (gsi_end_p (psi))
10019 break;
10020 remove_phi_node (&psi, false);
10021 }
79acaae1 10022
10023 /* Make phi node for trip. */
10024 phi = create_phi_node (trip_main, iter_part_bb);
efbcb6de 10025 add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb),
60d535d2 10026 UNKNOWN_LOCATION);
efbcb6de 10027 add_phi_arg (phi, trip_init, single_succ_edge (entry_bb),
60d535d2 10028 UNKNOWN_LOCATION);
79acaae1 10029 }
10030
bc7bff74 10031 if (!broken_loop)
10032 set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
79acaae1 10033 set_immediate_dominator (CDI_DOMINATORS, iter_part_bb,
10034 recompute_dominator (CDI_DOMINATORS, iter_part_bb));
10035 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
10036 recompute_dominator (CDI_DOMINATORS, fin_bb));
10037 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb,
10038 recompute_dominator (CDI_DOMINATORS, seq_start_bb));
10039 set_immediate_dominator (CDI_DOMINATORS, body_bb,
10040 recompute_dominator (CDI_DOMINATORS, body_bb));
04c2922b 10041
bc7bff74 10042 if (!broken_loop)
10043 {
fc1d58e3 10044 struct loop *loop = body_bb->loop_father;
bc7bff74 10045 struct loop *trip_loop = alloc_loop ();
10046 trip_loop->header = iter_part_bb;
10047 trip_loop->latch = trip_update_bb;
10048 add_loop (trip_loop, iter_part_bb->loop_father);
04c2922b 10049
fc1d58e3 10050 if (loop != entry_bb->loop_father)
10051 {
10052 gcc_assert (loop->header == body_bb);
10053 gcc_assert (loop->latch == region->cont
10054 || single_pred (loop->latch) == region->cont);
10055 trip_loop->inner = loop;
10056 return;
10057 }
10058
bc7bff74 10059 if (!gimple_omp_for_combined_p (fd->for_stmt))
10060 {
fc1d58e3 10061 loop = alloc_loop ();
bc7bff74 10062 loop->header = body_bb;
33ee4d72 10063 if (collapse_bb == NULL)
10064 loop->latch = cont_bb;
bc7bff74 10065 add_loop (loop, trip_loop);
10066 }
10067 }
1e8e9920 10068}
10069
40750995 10070/* A subroutine of expand_omp_for. Generate code for _Cilk_for loop.
10071 Given parameters:
10072 for (V = N1; V cond N2; V += STEP) BODY;
10073
10074 where COND is "<" or ">" or "!=", we generate pseudocode
10075
10076 for (ind_var = low; ind_var < high; ind_var++)
10077 {
10078 V = n1 + (ind_var * STEP)
10079
10080 <BODY>
10081 }
10082
10083 In the above pseudocode, low and high are function parameters of the
10084 child function. In the function below, we are inserting a temp.
10085 variable that will be making a call to two OMP functions that will not be
10086 found in the body of _Cilk_for (since OMP_FOR cannot be mixed
10087 with _Cilk_for). These functions are replaced with low and high
10088 by the function that handles taskreg. */
10089
10090
10091static void
10092expand_cilk_for (struct omp_region *region, struct omp_for_data *fd)
10093{
10094 bool broken_loop = region->cont == NULL;
10095 basic_block entry_bb = region->entry;
10096 basic_block cont_bb = region->cont;
10097
10098 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
10099 gcc_assert (broken_loop
10100 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
10101 basic_block l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
10102 basic_block l1_bb, l2_bb;
10103
10104 if (!broken_loop)
10105 {
10106 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
10107 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
10108 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
10109 l2_bb = BRANCH_EDGE (entry_bb)->dest;
10110 }
10111 else
10112 {
10113 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
10114 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
10115 l2_bb = single_succ (l1_bb);
10116 }
10117 basic_block exit_bb = region->exit;
10118 basic_block l2_dom_bb = NULL;
10119
10120 gimple_stmt_iterator gsi = gsi_last_bb (entry_bb);
10121
10122 /* Below statements until the "tree high_val = ..." are pseudo statements
10123 used to pass information to be used by expand_omp_taskreg.
10124 low_val and high_val will be replaced by the __low and __high
10125 parameter from the child function.
10126
10127 The call_exprs part is a place-holder, it is mainly used
10128 to distinctly identify to the top-level part that this is
10129 where we should put low and high (reasoning given in header
10130 comment). */
10131
10132 tree child_fndecl
1a91d914 10133 = gimple_omp_parallel_child_fn (
10134 as_a <gomp_parallel *> (last_stmt (region->outer->entry)));
40750995 10135 tree t, low_val = NULL_TREE, high_val = NULL_TREE;
10136 for (t = DECL_ARGUMENTS (child_fndecl); t; t = TREE_CHAIN (t))
10137 {
10138 if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__high"))
10139 high_val = t;
10140 else if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__low"))
10141 low_val = t;
10142 }
10143 gcc_assert (low_val && high_val);
10144
10145 tree type = TREE_TYPE (low_val);
10146 tree ind_var = create_tmp_reg (type, "__cilk_ind_var");
10147 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
10148
10149 /* Not needed in SSA form right now. */
10150 gcc_assert (!gimple_in_ssa_p (cfun));
10151 if (l2_dom_bb == NULL)
10152 l2_dom_bb = l1_bb;
10153
10154 tree n1 = low_val;
10155 tree n2 = high_val;
10156
42acab1c 10157 gimple *stmt = gimple_build_assign (ind_var, n1);
40750995 10158
10159 /* Replace the GIMPLE_OMP_FOR statement. */
10160 gsi_replace (&gsi, stmt, true);
10161
10162 if (!broken_loop)
10163 {
10164 /* Code to control the increment goes in the CONT_BB. */
10165 gsi = gsi_last_bb (cont_bb);
10166 stmt = gsi_stmt (gsi);
10167 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
e9cf809e 10168 stmt = gimple_build_assign (ind_var, PLUS_EXPR, ind_var,
10169 build_one_cst (type));
40750995 10170
10171 /* Replace GIMPLE_OMP_CONTINUE. */
10172 gsi_replace (&gsi, stmt, true);
10173 }
10174
10175 /* Emit the condition in L1_BB. */
10176 gsi = gsi_after_labels (l1_bb);
10177 t = fold_build2 (MULT_EXPR, TREE_TYPE (fd->loop.step),
10178 fold_convert (TREE_TYPE (fd->loop.step), ind_var),
10179 fd->loop.step);
10180 if (POINTER_TYPE_P (TREE_TYPE (fd->loop.n1)))
10181 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (fd->loop.n1),
10182 fd->loop.n1, fold_convert (sizetype, t));
10183 else
10184 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loop.n1),
10185 fd->loop.n1, fold_convert (TREE_TYPE (fd->loop.n1), t));
10186 t = fold_convert (TREE_TYPE (fd->loop.v), t);
10187 expand_omp_build_assign (&gsi, fd->loop.v, t);
10188
10189 /* The condition is always '<' since the runtime will fill in the low
10190 and high values. */
10191 stmt = gimple_build_cond (LT_EXPR, ind_var, n2, NULL_TREE, NULL_TREE);
10192 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
10193
10194 /* Remove GIMPLE_OMP_RETURN. */
10195 gsi = gsi_last_bb (exit_bb);
10196 gsi_remove (&gsi, true);
10197
10198 /* Connect the new blocks. */
10199 remove_edge (FALLTHRU_EDGE (entry_bb));
10200
10201 edge e, ne;
10202 if (!broken_loop)
10203 {
10204 remove_edge (BRANCH_EDGE (entry_bb));
10205 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
10206
10207 e = BRANCH_EDGE (l1_bb);
10208 ne = FALLTHRU_EDGE (l1_bb);
10209 e->flags = EDGE_TRUE_VALUE;
10210 }
10211 else
10212 {
10213 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
10214
10215 ne = single_succ_edge (l1_bb);
10216 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
10217
10218 }
10219 ne->flags = EDGE_FALSE_VALUE;
10220 e->probability = REG_BR_PROB_BASE * 7 / 8;
10221 ne->probability = REG_BR_PROB_BASE / 8;
10222
10223 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
10224 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
10225 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
10226
10227 if (!broken_loop)
10228 {
10229 struct loop *loop = alloc_loop ();
10230 loop->header = l1_bb;
10231 loop->latch = cont_bb;
10232 add_loop (loop, l1_bb->loop_father);
10233 loop->safelen = INT_MAX;
10234 }
10235
10236 /* Pick the correct library function based on the precision of the
10237 induction variable type. */
10238 tree lib_fun = NULL_TREE;
10239 if (TYPE_PRECISION (type) == 32)
10240 lib_fun = cilk_for_32_fndecl;
10241 else if (TYPE_PRECISION (type) == 64)
10242 lib_fun = cilk_for_64_fndecl;
10243 else
10244 gcc_unreachable ();
10245
10246 gcc_assert (fd->sched_kind == OMP_CLAUSE_SCHEDULE_CILKFOR);
10247
10248 /* WS_ARGS contains the library function flavor to call:
10249 __libcilkrts_cilk_for_64 or __libcilkrts_cilk_for_32), and the
10250 user-defined grain value. If the user does not define one, then zero
10251 is passed in by the parser. */
10252 vec_alloc (region->ws_args, 2);
10253 region->ws_args->quick_push (lib_fun);
10254 region->ws_args->quick_push (fd->chunk_size);
10255}
bc7bff74 10256
3d483a94 10257/* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
10258 loop. Given parameters:
10259
10260 for (V = N1; V cond N2; V += STEP) BODY;
10261
10262 where COND is "<" or ">", we generate pseudocode
10263
10264 V = N1;
10265 goto L1;
10266 L0:
10267 BODY;
10268 V += STEP;
10269 L1:
10270 if (V cond N2) goto L0; else goto L2;
10271 L2:
10272
10273 For collapsed loops, given parameters:
10274 collapse(3)
10275 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
10276 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
10277 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
10278 BODY;
10279
10280 we generate pseudocode
10281
10282 if (cond3 is <)
10283 adj = STEP3 - 1;
10284 else
10285 adj = STEP3 + 1;
10286 count3 = (adj + N32 - N31) / STEP3;
10287 if (cond2 is <)
10288 adj = STEP2 - 1;
10289 else
10290 adj = STEP2 + 1;
10291 count2 = (adj + N22 - N21) / STEP2;
10292 if (cond1 is <)
10293 adj = STEP1 - 1;
10294 else
10295 adj = STEP1 + 1;
10296 count1 = (adj + N12 - N11) / STEP1;
10297 count = count1 * count2 * count3;
10298 V = 0;
10299 V1 = N11;
10300 V2 = N21;
10301 V3 = N31;
10302 goto L1;
10303 L0:
10304 BODY;
10305 V += 1;
10306 V3 += STEP3;
10307 V2 += (V3 cond3 N32) ? 0 : STEP2;
10308 V3 = (V3 cond3 N32) ? V3 : N31;
10309 V1 += (V2 cond2 N22) ? 0 : STEP1;
10310 V2 = (V2 cond2 N22) ? V2 : N21;
10311 L1:
10312 if (V < count) goto L0; else goto L2;
10313 L2:
10314
10315 */
10316
10317static void
10318expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
10319{
10320 tree type, t;
10321 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, l2_bb, l2_dom_bb;
10322 gimple_stmt_iterator gsi;
42acab1c 10323 gimple *stmt;
1a91d914 10324 gcond *cond_stmt;
3d483a94 10325 bool broken_loop = region->cont == NULL;
10326 edge e, ne;
10327 tree *counts = NULL;
10328 int i;
10329 tree safelen = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
10330 OMP_CLAUSE_SAFELEN);
10331 tree simduid = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
10332 OMP_CLAUSE__SIMDUID_);
bc7bff74 10333 tree n1, n2;
3d483a94 10334
10335 type = TREE_TYPE (fd->loop.v);
10336 entry_bb = region->entry;
10337 cont_bb = region->cont;
10338 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
10339 gcc_assert (broken_loop
10340 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
10341 l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
10342 if (!broken_loop)
10343 {
10344 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
10345 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
10346 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
10347 l2_bb = BRANCH_EDGE (entry_bb)->dest;
10348 }
10349 else
10350 {
10351 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
10352 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
10353 l2_bb = single_succ (l1_bb);
10354 }
10355 exit_bb = region->exit;
10356 l2_dom_bb = NULL;
10357
10358 gsi = gsi_last_bb (entry_bb);
10359
10360 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
10361 /* Not needed in SSA form right now. */
10362 gcc_assert (!gimple_in_ssa_p (cfun));
10363 if (fd->collapse > 1)
10364 {
43895be5 10365 int first_zero_iter = -1, dummy = -1;
10366 basic_block zero_iter_bb = l2_bb, dummy_bb = NULL;
3d483a94 10367
10368 counts = XALLOCAVEC (tree, fd->collapse);
10369 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
10370 zero_iter_bb, first_zero_iter,
43895be5 10371 dummy_bb, dummy, l2_dom_bb);
3d483a94 10372 }
10373 if (l2_dom_bb == NULL)
10374 l2_dom_bb = l1_bb;
10375
bc7bff74 10376 n1 = fd->loop.n1;
3d483a94 10377 n2 = fd->loop.n2;
bc7bff74 10378 if (gimple_omp_for_combined_into_p (fd->for_stmt))
10379 {
10380 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
10381 OMP_CLAUSE__LOOPTEMP_);
10382 gcc_assert (innerc);
10383 n1 = OMP_CLAUSE_DECL (innerc);
10384 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
10385 OMP_CLAUSE__LOOPTEMP_);
10386 gcc_assert (innerc);
10387 n2 = OMP_CLAUSE_DECL (innerc);
10388 expand_omp_build_assign (&gsi, fd->loop.v,
10389 fold_convert (type, n1));
10390 if (fd->collapse > 1)
10391 {
10392 gsi_prev (&gsi);
10393 expand_omp_for_init_vars (fd, &gsi, counts, NULL, n1);
10394 gsi_next (&gsi);
10395 }
10396 }
3d483a94 10397 else
10398 {
10399 expand_omp_build_assign (&gsi, fd->loop.v,
10400 fold_convert (type, fd->loop.n1));
10401 if (fd->collapse > 1)
10402 for (i = 0; i < fd->collapse; i++)
10403 {
10404 tree itype = TREE_TYPE (fd->loops[i].v);
10405 if (POINTER_TYPE_P (itype))
10406 itype = signed_type_for (itype);
10407 t = fold_convert (TREE_TYPE (fd->loops[i].v), fd->loops[i].n1);
10408 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
10409 }
10410 }
10411
10412 /* Remove the GIMPLE_OMP_FOR statement. */
10413 gsi_remove (&gsi, true);
10414
10415 if (!broken_loop)
10416 {
10417 /* Code to control the increment goes in the CONT_BB. */
10418 gsi = gsi_last_bb (cont_bb);
10419 stmt = gsi_stmt (gsi);
10420 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
10421
10422 if (POINTER_TYPE_P (type))
10423 t = fold_build_pointer_plus (fd->loop.v, fd->loop.step);
10424 else
10425 t = fold_build2 (PLUS_EXPR, type, fd->loop.v, fd->loop.step);
10426 expand_omp_build_assign (&gsi, fd->loop.v, t);
10427
10428 if (fd->collapse > 1)
10429 {
10430 i = fd->collapse - 1;
10431 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
10432 {
10433 t = fold_convert (sizetype, fd->loops[i].step);
10434 t = fold_build_pointer_plus (fd->loops[i].v, t);
10435 }
10436 else
10437 {
10438 t = fold_convert (TREE_TYPE (fd->loops[i].v),
10439 fd->loops[i].step);
10440 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
10441 fd->loops[i].v, t);
10442 }
10443 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
10444
10445 for (i = fd->collapse - 1; i > 0; i--)
10446 {
10447 tree itype = TREE_TYPE (fd->loops[i].v);
10448 tree itype2 = TREE_TYPE (fd->loops[i - 1].v);
10449 if (POINTER_TYPE_P (itype2))
10450 itype2 = signed_type_for (itype2);
10451 t = build3 (COND_EXPR, itype2,
10452 build2 (fd->loops[i].cond_code, boolean_type_node,
10453 fd->loops[i].v,
10454 fold_convert (itype, fd->loops[i].n2)),
10455 build_int_cst (itype2, 0),
10456 fold_convert (itype2, fd->loops[i - 1].step));
10457 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i - 1].v)))
10458 t = fold_build_pointer_plus (fd->loops[i - 1].v, t);
10459 else
10460 t = fold_build2 (PLUS_EXPR, itype2, fd->loops[i - 1].v, t);
10461 expand_omp_build_assign (&gsi, fd->loops[i - 1].v, t);
10462
10463 t = build3 (COND_EXPR, itype,
10464 build2 (fd->loops[i].cond_code, boolean_type_node,
10465 fd->loops[i].v,
10466 fold_convert (itype, fd->loops[i].n2)),
10467 fd->loops[i].v,
10468 fold_convert (itype, fd->loops[i].n1));
10469 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
10470 }
10471 }
10472
10473 /* Remove GIMPLE_OMP_CONTINUE. */
10474 gsi_remove (&gsi, true);
10475 }
10476
10477 /* Emit the condition in L1_BB. */
10478 gsi = gsi_start_bb (l1_bb);
10479
10480 t = fold_convert (type, n2);
10481 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
10482 false, GSI_CONTINUE_LINKING);
43895be5 10483 tree v = fd->loop.v;
10484 if (DECL_P (v) && TREE_ADDRESSABLE (v))
10485 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
10486 false, GSI_CONTINUE_LINKING);
10487 t = build2 (fd->loop.cond_code, boolean_type_node, v, t);
1a91d914 10488 cond_stmt = gimple_build_cond_empty (t);
10489 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
10490 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt), expand_omp_regimplify_p,
3d483a94 10491 NULL, NULL)
1a91d914 10492 || walk_tree (gimple_cond_rhs_ptr (cond_stmt), expand_omp_regimplify_p,
3d483a94 10493 NULL, NULL))
10494 {
1a91d914 10495 gsi = gsi_for_stmt (cond_stmt);
10496 gimple_regimplify_operands (cond_stmt, &gsi);
3d483a94 10497 }
10498
10499 /* Remove GIMPLE_OMP_RETURN. */
10500 gsi = gsi_last_bb (exit_bb);
10501 gsi_remove (&gsi, true);
10502
10503 /* Connect the new blocks. */
10504 remove_edge (FALLTHRU_EDGE (entry_bb));
10505
10506 if (!broken_loop)
10507 {
10508 remove_edge (BRANCH_EDGE (entry_bb));
10509 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
10510
10511 e = BRANCH_EDGE (l1_bb);
10512 ne = FALLTHRU_EDGE (l1_bb);
10513 e->flags = EDGE_TRUE_VALUE;
10514 }
10515 else
10516 {
10517 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
10518
10519 ne = single_succ_edge (l1_bb);
10520 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
10521
10522 }
10523 ne->flags = EDGE_FALSE_VALUE;
10524 e->probability = REG_BR_PROB_BASE * 7 / 8;
10525 ne->probability = REG_BR_PROB_BASE / 8;
10526
10527 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
10528 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
10529 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
10530
10531 if (!broken_loop)
10532 {
10533 struct loop *loop = alloc_loop ();
10534 loop->header = l1_bb;
33ee4d72 10535 loop->latch = cont_bb;
3d483a94 10536 add_loop (loop, l1_bb->loop_father);
10537 if (safelen == NULL_TREE)
10538 loop->safelen = INT_MAX;
10539 else
10540 {
10541 safelen = OMP_CLAUSE_SAFELEN_EXPR (safelen);
c3f3b68d 10542 if (TREE_CODE (safelen) != INTEGER_CST)
10543 loop->safelen = 0;
10544 else if (!tree_fits_uhwi_p (safelen)
10545 || tree_to_uhwi (safelen) > INT_MAX)
3d483a94 10546 loop->safelen = INT_MAX;
10547 else
d85a2013 10548 loop->safelen = tree_to_uhwi (safelen);
3d483a94 10549 if (loop->safelen == 1)
10550 loop->safelen = 0;
10551 }
10552 if (simduid)
10553 {
43895be5 10554 loop->simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
10555 cfun->has_simduid_loops = true;
10556 }
10557 /* If not -fno-tree-loop-vectorize, hint that we want to vectorize
10558 the loop. */
10559 if ((flag_tree_loop_vectorize
10560 || (!global_options_set.x_flag_tree_loop_vectorize
10561 && !global_options_set.x_flag_tree_vectorize))
10562 && flag_tree_loop_optimize
10563 && loop->safelen > 1)
10564 {
10565 loop->force_vectorize = true;
10566 cfun->has_force_vectorize_loops = true;
10567 }
10568 }
10569 else if (simduid)
10570 cfun->has_simduid_loops = true;
10571}
10572
10573/* Taskloop construct is represented after gimplification with
10574 two GIMPLE_OMP_FOR constructs with GIMPLE_OMP_TASK sandwiched
10575 in between them. This routine expands the outer GIMPLE_OMP_FOR,
10576 which should just compute all the needed loop temporaries
10577 for GIMPLE_OMP_TASK. */
10578
10579static void
10580expand_omp_taskloop_for_outer (struct omp_region *region,
10581 struct omp_for_data *fd,
10582 gimple *inner_stmt)
10583{
10584 tree type, bias = NULL_TREE;
10585 basic_block entry_bb, cont_bb, exit_bb;
10586 gimple_stmt_iterator gsi;
10587 gassign *assign_stmt;
10588 tree *counts = NULL;
10589 int i;
10590
10591 gcc_assert (inner_stmt);
10592 gcc_assert (region->cont);
10593 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_TASK
10594 && gimple_omp_task_taskloop_p (inner_stmt));
10595 type = TREE_TYPE (fd->loop.v);
10596
10597 /* See if we need to bias by LLONG_MIN. */
10598 if (fd->iter_type == long_long_unsigned_type_node
10599 && TREE_CODE (type) == INTEGER_TYPE
10600 && !TYPE_UNSIGNED (type))
10601 {
10602 tree n1, n2;
10603
10604 if (fd->loop.cond_code == LT_EXPR)
10605 {
10606 n1 = fd->loop.n1;
10607 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
10608 }
10609 else
10610 {
10611 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
10612 n2 = fd->loop.n1;
10613 }
10614 if (TREE_CODE (n1) != INTEGER_CST
10615 || TREE_CODE (n2) != INTEGER_CST
10616 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
10617 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
10618 }
10619
10620 entry_bb = region->entry;
10621 cont_bb = region->cont;
10622 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
10623 gcc_assert (BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
10624 exit_bb = region->exit;
10625
10626 gsi = gsi_last_bb (entry_bb);
10627 gimple *for_stmt = gsi_stmt (gsi);
10628 gcc_assert (gimple_code (for_stmt) == GIMPLE_OMP_FOR);
10629 if (fd->collapse > 1)
10630 {
10631 int first_zero_iter = -1, dummy = -1;
10632 basic_block zero_iter_bb = NULL, dummy_bb = NULL, l2_dom_bb = NULL;
10633
10634 counts = XALLOCAVEC (tree, fd->collapse);
10635 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
10636 zero_iter_bb, first_zero_iter,
10637 dummy_bb, dummy, l2_dom_bb);
10638
10639 if (zero_iter_bb)
10640 {
10641 /* Some counts[i] vars might be uninitialized if
10642 some loop has zero iterations. But the body shouldn't
10643 be executed in that case, so just avoid uninit warnings. */
10644 for (i = first_zero_iter; i < fd->collapse; i++)
10645 if (SSA_VAR_P (counts[i]))
10646 TREE_NO_WARNING (counts[i]) = 1;
10647 gsi_prev (&gsi);
10648 edge e = split_block (entry_bb, gsi_stmt (gsi));
10649 entry_bb = e->dest;
10650 make_edge (zero_iter_bb, entry_bb, EDGE_FALLTHRU);
10651 gsi = gsi_last_bb (entry_bb);
10652 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
10653 get_immediate_dominator (CDI_DOMINATORS,
10654 zero_iter_bb));
10655 }
10656 }
10657
10658 tree t0, t1;
10659 t1 = fd->loop.n2;
10660 t0 = fd->loop.n1;
10661 if (POINTER_TYPE_P (TREE_TYPE (t0))
10662 && TYPE_PRECISION (TREE_TYPE (t0))
10663 != TYPE_PRECISION (fd->iter_type))
10664 {
10665 /* Avoid casting pointers to integer of a different size. */
10666 tree itype = signed_type_for (type);
10667 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
10668 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
10669 }
10670 else
10671 {
10672 t1 = fold_convert (fd->iter_type, t1);
10673 t0 = fold_convert (fd->iter_type, t0);
10674 }
10675 if (bias)
10676 {
10677 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
10678 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
10679 }
10680
10681 tree innerc = find_omp_clause (gimple_omp_task_clauses (inner_stmt),
10682 OMP_CLAUSE__LOOPTEMP_);
10683 gcc_assert (innerc);
10684 tree startvar = OMP_CLAUSE_DECL (innerc);
10685 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc), OMP_CLAUSE__LOOPTEMP_);
10686 gcc_assert (innerc);
10687 tree endvar = OMP_CLAUSE_DECL (innerc);
10688 if (fd->collapse > 1 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
10689 {
10690 gcc_assert (innerc);
10691 for (i = 1; i < fd->collapse; i++)
10692 {
10693 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
10694 OMP_CLAUSE__LOOPTEMP_);
10695 gcc_assert (innerc);
10696 }
10697 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
10698 OMP_CLAUSE__LOOPTEMP_);
10699 if (innerc)
10700 {
10701 /* If needed (inner taskloop has lastprivate clause), propagate
10702 down the total number of iterations. */
10703 tree t = force_gimple_operand_gsi (&gsi, fd->loop.n2, false,
10704 NULL_TREE, false,
10705 GSI_CONTINUE_LINKING);
10706 assign_stmt = gimple_build_assign (OMP_CLAUSE_DECL (innerc), t);
10707 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10708 }
10709 }
10710
10711 t0 = force_gimple_operand_gsi (&gsi, t0, false, NULL_TREE, false,
10712 GSI_CONTINUE_LINKING);
10713 assign_stmt = gimple_build_assign (startvar, t0);
10714 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10715
10716 t1 = force_gimple_operand_gsi (&gsi, t1, false, NULL_TREE, false,
10717 GSI_CONTINUE_LINKING);
10718 assign_stmt = gimple_build_assign (endvar, t1);
10719 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10720 if (fd->collapse > 1)
10721 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
10722
10723 /* Remove the GIMPLE_OMP_FOR statement. */
10724 gsi = gsi_for_stmt (for_stmt);
10725 gsi_remove (&gsi, true);
10726
10727 gsi = gsi_last_bb (cont_bb);
10728 gsi_remove (&gsi, true);
10729
10730 gsi = gsi_last_bb (exit_bb);
10731 gsi_remove (&gsi, true);
10732
10733 FALLTHRU_EDGE (entry_bb)->probability = REG_BR_PROB_BASE;
10734 remove_edge (BRANCH_EDGE (entry_bb));
10735 FALLTHRU_EDGE (cont_bb)->probability = REG_BR_PROB_BASE;
10736 remove_edge (BRANCH_EDGE (cont_bb));
10737 set_immediate_dominator (CDI_DOMINATORS, exit_bb, cont_bb);
10738 set_immediate_dominator (CDI_DOMINATORS, region->entry,
10739 recompute_dominator (CDI_DOMINATORS, region->entry));
10740}
10741
10742/* Taskloop construct is represented after gimplification with
10743 two GIMPLE_OMP_FOR constructs with GIMPLE_OMP_TASK sandwiched
10744 in between them. This routine expands the inner GIMPLE_OMP_FOR.
10745 GOMP_taskloop{,_ull} function arranges for each task to be given just
10746 a single range of iterations. */
10747
10748static void
10749expand_omp_taskloop_for_inner (struct omp_region *region,
10750 struct omp_for_data *fd,
10751 gimple *inner_stmt)
10752{
10753 tree e, t, type, itype, vmain, vback, bias = NULL_TREE;
10754 basic_block entry_bb, exit_bb, body_bb, cont_bb, collapse_bb = NULL;
10755 basic_block fin_bb;
10756 gimple_stmt_iterator gsi;
10757 edge ep;
10758 bool broken_loop = region->cont == NULL;
10759 tree *counts = NULL;
10760 tree n1, n2, step;
10761
10762 itype = type = TREE_TYPE (fd->loop.v);
10763 if (POINTER_TYPE_P (type))
10764 itype = signed_type_for (type);
10765
10766 /* See if we need to bias by LLONG_MIN. */
10767 if (fd->iter_type == long_long_unsigned_type_node
10768 && TREE_CODE (type) == INTEGER_TYPE
10769 && !TYPE_UNSIGNED (type))
10770 {
10771 tree n1, n2;
10772
10773 if (fd->loop.cond_code == LT_EXPR)
10774 {
10775 n1 = fd->loop.n1;
10776 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
10777 }
10778 else
10779 {
10780 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
10781 n2 = fd->loop.n1;
10782 }
10783 if (TREE_CODE (n1) != INTEGER_CST
10784 || TREE_CODE (n2) != INTEGER_CST
10785 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
10786 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
10787 }
10788
10789 entry_bb = region->entry;
10790 cont_bb = region->cont;
10791 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
10792 fin_bb = BRANCH_EDGE (entry_bb)->dest;
10793 gcc_assert (broken_loop
10794 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
10795 body_bb = FALLTHRU_EDGE (entry_bb)->dest;
10796 if (!broken_loop)
10797 {
10798 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
10799 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
10800 }
10801 exit_bb = region->exit;
10802
10803 /* Iteration space partitioning goes in ENTRY_BB. */
10804 gsi = gsi_last_bb (entry_bb);
10805 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
10806
10807 if (fd->collapse > 1)
10808 {
10809 int first_zero_iter = -1, dummy = -1;
10810 basic_block l2_dom_bb = NULL, dummy_bb = NULL;
10811
10812 counts = XALLOCAVEC (tree, fd->collapse);
10813 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
10814 fin_bb, first_zero_iter,
10815 dummy_bb, dummy, l2_dom_bb);
10816 t = NULL_TREE;
10817 }
10818 else
10819 t = integer_one_node;
10820
10821 step = fd->loop.step;
10822 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
10823 OMP_CLAUSE__LOOPTEMP_);
10824 gcc_assert (innerc);
10825 n1 = OMP_CLAUSE_DECL (innerc);
10826 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc), OMP_CLAUSE__LOOPTEMP_);
10827 gcc_assert (innerc);
10828 n2 = OMP_CLAUSE_DECL (innerc);
10829 if (bias)
10830 {
10831 n1 = fold_build2 (PLUS_EXPR, fd->iter_type, n1, bias);
10832 n2 = fold_build2 (PLUS_EXPR, fd->iter_type, n2, bias);
10833 }
10834 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
10835 true, NULL_TREE, true, GSI_SAME_STMT);
10836 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
10837 true, NULL_TREE, true, GSI_SAME_STMT);
10838 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
10839 true, NULL_TREE, true, GSI_SAME_STMT);
10840
10841 tree startvar = fd->loop.v;
10842 tree endvar = NULL_TREE;
10843
10844 if (gimple_omp_for_combined_p (fd->for_stmt))
10845 {
10846 tree clauses = gimple_omp_for_clauses (inner_stmt);
10847 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
10848 gcc_assert (innerc);
10849 startvar = OMP_CLAUSE_DECL (innerc);
10850 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
10851 OMP_CLAUSE__LOOPTEMP_);
10852 gcc_assert (innerc);
10853 endvar = OMP_CLAUSE_DECL (innerc);
10854 }
10855 t = fold_convert (TREE_TYPE (startvar), n1);
10856 t = force_gimple_operand_gsi (&gsi, t,
10857 DECL_P (startvar)
10858 && TREE_ADDRESSABLE (startvar),
10859 NULL_TREE, false, GSI_CONTINUE_LINKING);
10860 gimple *assign_stmt = gimple_build_assign (startvar, t);
10861 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10862
10863 t = fold_convert (TREE_TYPE (startvar), n2);
10864 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
10865 false, GSI_CONTINUE_LINKING);
10866 if (endvar)
10867 {
10868 assign_stmt = gimple_build_assign (endvar, e);
10869 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10870 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
10871 assign_stmt = gimple_build_assign (fd->loop.v, e);
10872 else
10873 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
10874 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10875 }
10876 if (fd->collapse > 1)
10877 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
10878
10879 if (!broken_loop)
10880 {
10881 /* The code controlling the sequential loop replaces the
10882 GIMPLE_OMP_CONTINUE. */
10883 gsi = gsi_last_bb (cont_bb);
10884 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
10885 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
10886 vmain = gimple_omp_continue_control_use (cont_stmt);
10887 vback = gimple_omp_continue_control_def (cont_stmt);
10888
10889 if (!gimple_omp_for_combined_p (fd->for_stmt))
10890 {
10891 if (POINTER_TYPE_P (type))
10892 t = fold_build_pointer_plus (vmain, step);
10893 else
10894 t = fold_build2 (PLUS_EXPR, type, vmain, step);
10895 t = force_gimple_operand_gsi (&gsi, t,
10896 DECL_P (vback)
10897 && TREE_ADDRESSABLE (vback),
10898 NULL_TREE, true, GSI_SAME_STMT);
10899 assign_stmt = gimple_build_assign (vback, t);
10900 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
10901
10902 t = build2 (fd->loop.cond_code, boolean_type_node,
10903 DECL_P (vback) && TREE_ADDRESSABLE (vback)
10904 ? t : vback, e);
10905 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
10906 }
10907
10908 /* Remove the GIMPLE_OMP_CONTINUE statement. */
10909 gsi_remove (&gsi, true);
10910
10911 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
10912 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
10913 }
10914
10915 /* Remove the GIMPLE_OMP_FOR statement. */
10916 gsi = gsi_for_stmt (fd->for_stmt);
10917 gsi_remove (&gsi, true);
10918
10919 /* Remove the GIMPLE_OMP_RETURN statement. */
10920 gsi = gsi_last_bb (exit_bb);
10921 gsi_remove (&gsi, true);
10922
10923 FALLTHRU_EDGE (entry_bb)->probability = REG_BR_PROB_BASE;
10924 if (!broken_loop)
10925 remove_edge (BRANCH_EDGE (entry_bb));
10926 else
10927 {
10928 remove_edge_and_dominated_blocks (BRANCH_EDGE (entry_bb));
10929 region->outer->cont = NULL;
10930 }
10931
10932 /* Connect all the blocks. */
10933 if (!broken_loop)
10934 {
10935 ep = find_edge (cont_bb, body_bb);
10936 if (gimple_omp_for_combined_p (fd->for_stmt))
10937 {
10938 remove_edge (ep);
10939 ep = NULL;
3d483a94 10940 }
43895be5 10941 else if (fd->collapse > 1)
3d483a94 10942 {
43895be5 10943 remove_edge (ep);
10944 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
3d483a94 10945 }
43895be5 10946 else
10947 ep->flags = EDGE_TRUE_VALUE;
10948 find_edge (cont_bb, fin_bb)->flags
10949 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
3d483a94 10950 }
3d483a94 10951
43895be5 10952 set_immediate_dominator (CDI_DOMINATORS, body_bb,
10953 recompute_dominator (CDI_DOMINATORS, body_bb));
10954 if (!broken_loop)
10955 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
10956 recompute_dominator (CDI_DOMINATORS, fin_bb));
10957
10958 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
10959 {
10960 struct loop *loop = alloc_loop ();
10961 loop->header = body_bb;
10962 if (collapse_bb == NULL)
10963 loop->latch = cont_bb;
10964 add_loop (loop, body_bb->loop_father);
10965 }
10966}
1e8e9920 10967
a8e785ba 10968/* A subroutine of expand_omp_for. Generate code for an OpenACC
10969 partitioned loop. The lowering here is abstracted, in that the
10970 loop parameters are passed through internal functions, which are
10971 further lowered by oacc_device_lower, once we get to the target
10972 compiler. The loop is of the form:
10973
10974 for (V = B; V LTGT E; V += S) {BODY}
10975
10976 where LTGT is < or >. We may have a specified chunking size, CHUNKING
10977 (constant 0 for no chunking) and we will have a GWV partitioning
10978 mask, specifying dimensions over which the loop is to be
10979 partitioned (see note below). We generate code that looks like:
10980
10981 <entry_bb> [incoming FALL->body, BRANCH->exit]
10982 typedef signedintify (typeof (V)) T; // underlying signed integral type
10983 T range = E - B;
10984 T chunk_no = 0;
10985 T DIR = LTGT == '<' ? +1 : -1;
10986 T chunk_max = GOACC_LOOP_CHUNK (dir, range, S, CHUNK_SIZE, GWV);
10987 T step = GOACC_LOOP_STEP (dir, range, S, CHUNK_SIZE, GWV);
10988
10989 <head_bb> [created by splitting end of entry_bb]
10990 T offset = GOACC_LOOP_OFFSET (dir, range, S, CHUNK_SIZE, GWV, chunk_no);
10991 T bound = GOACC_LOOP_BOUND (dir, range, S, CHUNK_SIZE, GWV, offset);
10992 if (!(offset LTGT bound)) goto bottom_bb;
10993
10994 <body_bb> [incoming]
10995 V = B + offset;
10996 {BODY}
10997
10998 <cont_bb> [incoming, may == body_bb FALL->exit_bb, BRANCH->body_bb]
10999 offset += step;
11000 if (offset LTGT bound) goto body_bb; [*]
11001
11002 <bottom_bb> [created by splitting start of exit_bb] insert BRANCH->head_bb
11003 chunk_no++;
11004 if (chunk < chunk_max) goto head_bb;
11005
11006 <exit_bb> [incoming]
11007 V = B + ((range -/+ 1) / S +/- 1) * S [*]
11008
11009 [*] Needed if V live at end of loop
11010
11011 Note: CHUNKING & GWV mask are specified explicitly here. This is a
11012 transition, and will be specified by a more general mechanism shortly.
11013 */
11014
11015static void
11016expand_oacc_for (struct omp_region *region, struct omp_for_data *fd)
11017{
11018 tree v = fd->loop.v;
11019 enum tree_code cond_code = fd->loop.cond_code;
11020 enum tree_code plus_code = PLUS_EXPR;
11021
11022 tree chunk_size = integer_minus_one_node;
11023 tree gwv = integer_zero_node;
11024 tree iter_type = TREE_TYPE (v);
11025 tree diff_type = iter_type;
11026 tree plus_type = iter_type;
11027 struct oacc_collapse *counts = NULL;
11028
11029 gcc_checking_assert (gimple_omp_for_kind (fd->for_stmt)
11030 == GF_OMP_FOR_KIND_OACC_LOOP);
11031 gcc_assert (!gimple_omp_for_combined_into_p (fd->for_stmt));
11032 gcc_assert (cond_code == LT_EXPR || cond_code == GT_EXPR);
11033
11034 if (POINTER_TYPE_P (iter_type))
11035 {
11036 plus_code = POINTER_PLUS_EXPR;
11037 plus_type = sizetype;
11038 }
11039 if (POINTER_TYPE_P (diff_type) || TYPE_UNSIGNED (diff_type))
11040 diff_type = signed_type_for (diff_type);
11041
11042 basic_block entry_bb = region->entry; /* BB ending in OMP_FOR */
11043 basic_block exit_bb = region->exit; /* BB ending in OMP_RETURN */
11044 basic_block cont_bb = region->cont; /* BB ending in OMP_CONTINUE */
11045 basic_block bottom_bb = NULL;
11046
11047 /* entry_bb has two sucessors; the branch edge is to the exit
11048 block, fallthrough edge to body. */
11049 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2
11050 && BRANCH_EDGE (entry_bb)->dest == exit_bb);
11051
11052 /* If cont_bb non-NULL, it has 2 successors. The branch successor is
11053 body_bb, or to a block whose only successor is the body_bb. Its
11054 fallthrough successor is the final block (same as the branch
11055 successor of the entry_bb). */
11056 if (cont_bb)
11057 {
11058 basic_block body_bb = FALLTHRU_EDGE (entry_bb)->dest;
11059 basic_block bed = BRANCH_EDGE (cont_bb)->dest;
11060
11061 gcc_assert (FALLTHRU_EDGE (cont_bb)->dest == exit_bb);
11062 gcc_assert (bed == body_bb || single_succ_edge (bed)->dest == body_bb);
11063 }
11064 else
11065 gcc_assert (!gimple_in_ssa_p (cfun));
11066
11067 /* The exit block only has entry_bb and cont_bb as predecessors. */
11068 gcc_assert (EDGE_COUNT (exit_bb->preds) == 1 + (cont_bb != NULL));
11069
11070 tree chunk_no;
11071 tree chunk_max = NULL_TREE;
11072 tree bound, offset;
11073 tree step = create_tmp_var (diff_type, ".step");
11074 bool up = cond_code == LT_EXPR;
11075 tree dir = build_int_cst (diff_type, up ? +1 : -1);
11076 bool chunking = !gimple_in_ssa_p (cfun);;
11077 bool negating;
11078
11079 /* SSA instances. */
11080 tree offset_incr = NULL_TREE;
11081 tree offset_init = NULL_TREE;
11082
11083 gimple_stmt_iterator gsi;
11084 gassign *ass;
11085 gcall *call;
11086 gimple *stmt;
11087 tree expr;
11088 location_t loc;
11089 edge split, be, fte;
11090
11091 /* Split the end of entry_bb to create head_bb. */
11092 split = split_block (entry_bb, last_stmt (entry_bb));
11093 basic_block head_bb = split->dest;
11094 entry_bb = split->src;
11095
11096 /* Chunk setup goes at end of entry_bb, replacing the omp_for. */
11097 gsi = gsi_last_bb (entry_bb);
11098 gomp_for *for_stmt = as_a <gomp_for *> (gsi_stmt (gsi));
11099 loc = gimple_location (for_stmt);
11100
11101 if (gimple_in_ssa_p (cfun))
11102 {
11103 offset_init = gimple_omp_for_index (for_stmt, 0);
11104 gcc_assert (integer_zerop (fd->loop.n1));
11105 /* The SSA parallelizer does gang parallelism. */
11106 gwv = build_int_cst (integer_type_node, GOMP_DIM_MASK (GOMP_DIM_GANG));
11107 }
11108
11109 if (fd->collapse > 1)
11110 {
11111 counts = XALLOCAVEC (struct oacc_collapse, fd->collapse);
11112 tree total = expand_oacc_collapse_init (fd, &gsi, counts,
11113 TREE_TYPE (fd->loop.n2));
11114
11115 if (SSA_VAR_P (fd->loop.n2))
11116 {
11117 total = force_gimple_operand_gsi (&gsi, total, false, NULL_TREE,
11118 true, GSI_SAME_STMT);
11119 ass = gimple_build_assign (fd->loop.n2, total);
11120 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11121 }
11122
11123 }
11124
11125 tree b = fd->loop.n1;
11126 tree e = fd->loop.n2;
11127 tree s = fd->loop.step;
11128
11129 b = force_gimple_operand_gsi (&gsi, b, true, NULL_TREE, true, GSI_SAME_STMT);
11130 e = force_gimple_operand_gsi (&gsi, e, true, NULL_TREE, true, GSI_SAME_STMT);
11131
11132 /* Convert the step, avoiding possible unsigned->signed overflow. */
11133 negating = !up && TYPE_UNSIGNED (TREE_TYPE (s));
11134 if (negating)
11135 s = fold_build1 (NEGATE_EXPR, TREE_TYPE (s), s);
11136 s = fold_convert (diff_type, s);
11137 if (negating)
11138 s = fold_build1 (NEGATE_EXPR, diff_type, s);
11139 s = force_gimple_operand_gsi (&gsi, s, true, NULL_TREE, true, GSI_SAME_STMT);
11140
11141 if (!chunking)
11142 chunk_size = integer_zero_node;
11143 expr = fold_convert (diff_type, chunk_size);
11144 chunk_size = force_gimple_operand_gsi (&gsi, expr, true,
11145 NULL_TREE, true, GSI_SAME_STMT);
11146 /* Determine the range, avoiding possible unsigned->signed overflow. */
11147 negating = !up && TYPE_UNSIGNED (iter_type);
11148 expr = fold_build2 (MINUS_EXPR, plus_type,
11149 fold_convert (plus_type, negating ? b : e),
11150 fold_convert (plus_type, negating ? e : b));
11151 expr = fold_convert (diff_type, expr);
11152 if (negating)
11153 expr = fold_build1 (NEGATE_EXPR, diff_type, expr);
11154 tree range = force_gimple_operand_gsi (&gsi, expr, true,
11155 NULL_TREE, true, GSI_SAME_STMT);
11156
11157 chunk_no = build_int_cst (diff_type, 0);
11158 if (chunking)
11159 {
11160 gcc_assert (!gimple_in_ssa_p (cfun));
11161
11162 expr = chunk_no;
11163 chunk_max = create_tmp_var (diff_type, ".chunk_max");
11164 chunk_no = create_tmp_var (diff_type, ".chunk_no");
11165
11166 ass = gimple_build_assign (chunk_no, expr);
11167 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11168
11169 call = gimple_build_call_internal (IFN_GOACC_LOOP, 6,
11170 build_int_cst (integer_type_node,
11171 IFN_GOACC_LOOP_CHUNKS),
11172 dir, range, s, chunk_size, gwv);
11173 gimple_call_set_lhs (call, chunk_max);
11174 gimple_set_location (call, loc);
11175 gsi_insert_before (&gsi, call, GSI_SAME_STMT);
11176 }
11177 else
11178 chunk_size = chunk_no;
11179
11180 call = gimple_build_call_internal (IFN_GOACC_LOOP, 6,
11181 build_int_cst (integer_type_node,
11182 IFN_GOACC_LOOP_STEP),
11183 dir, range, s, chunk_size, gwv);
11184 gimple_call_set_lhs (call, step);
11185 gimple_set_location (call, loc);
11186 gsi_insert_before (&gsi, call, GSI_SAME_STMT);
11187
11188 /* Remove the GIMPLE_OMP_FOR. */
11189 gsi_remove (&gsi, true);
11190
11191 /* Fixup edges from head_bb */
11192 be = BRANCH_EDGE (head_bb);
11193 fte = FALLTHRU_EDGE (head_bb);
11194 be->flags |= EDGE_FALSE_VALUE;
11195 fte->flags ^= EDGE_FALLTHRU | EDGE_TRUE_VALUE;
11196
11197 basic_block body_bb = fte->dest;
11198
11199 if (gimple_in_ssa_p (cfun))
11200 {
11201 gsi = gsi_last_bb (cont_bb);
11202 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
11203
11204 offset = gimple_omp_continue_control_use (cont_stmt);
11205 offset_incr = gimple_omp_continue_control_def (cont_stmt);
11206 }
11207 else
11208 {
11209 offset = create_tmp_var (diff_type, ".offset");
11210 offset_init = offset_incr = offset;
11211 }
11212 bound = create_tmp_var (TREE_TYPE (offset), ".bound");
11213
11214 /* Loop offset & bound go into head_bb. */
11215 gsi = gsi_start_bb (head_bb);
11216
11217 call = gimple_build_call_internal (IFN_GOACC_LOOP, 7,
11218 build_int_cst (integer_type_node,
11219 IFN_GOACC_LOOP_OFFSET),
11220 dir, range, s,
11221 chunk_size, gwv, chunk_no);
11222 gimple_call_set_lhs (call, offset_init);
11223 gimple_set_location (call, loc);
11224 gsi_insert_after (&gsi, call, GSI_CONTINUE_LINKING);
11225
11226 call = gimple_build_call_internal (IFN_GOACC_LOOP, 7,
11227 build_int_cst (integer_type_node,
11228 IFN_GOACC_LOOP_BOUND),
11229 dir, range, s,
11230 chunk_size, gwv, offset_init);
11231 gimple_call_set_lhs (call, bound);
11232 gimple_set_location (call, loc);
11233 gsi_insert_after (&gsi, call, GSI_CONTINUE_LINKING);
11234
11235 expr = build2 (cond_code, boolean_type_node, offset_init, bound);
11236 gsi_insert_after (&gsi, gimple_build_cond_empty (expr),
11237 GSI_CONTINUE_LINKING);
11238
11239 /* V assignment goes into body_bb. */
11240 if (!gimple_in_ssa_p (cfun))
11241 {
11242 gsi = gsi_start_bb (body_bb);
11243
11244 expr = build2 (plus_code, iter_type, b,
11245 fold_convert (plus_type, offset));
11246 expr = force_gimple_operand_gsi (&gsi, expr, false, NULL_TREE,
11247 true, GSI_SAME_STMT);
11248 ass = gimple_build_assign (v, expr);
11249 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11250 if (fd->collapse > 1)
11251 expand_oacc_collapse_vars (fd, &gsi, counts, v);
11252 }
11253
11254 /* Loop increment goes into cont_bb. If this is not a loop, we
11255 will have spawned threads as if it was, and each one will
11256 execute one iteration. The specification is not explicit about
11257 whether such constructs are ill-formed or not, and they can
11258 occur, especially when noreturn routines are involved. */
11259 if (cont_bb)
11260 {
11261 gsi = gsi_last_bb (cont_bb);
11262 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
11263 loc = gimple_location (cont_stmt);
11264
11265 /* Increment offset. */
11266 if (gimple_in_ssa_p (cfun))
11267 expr= build2 (plus_code, iter_type, offset,
11268 fold_convert (plus_type, step));
11269 else
11270 expr = build2 (PLUS_EXPR, diff_type, offset, step);
11271 expr = force_gimple_operand_gsi (&gsi, expr, false, NULL_TREE,
11272 true, GSI_SAME_STMT);
11273 ass = gimple_build_assign (offset_incr, expr);
11274 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11275 expr = build2 (cond_code, boolean_type_node, offset_incr, bound);
11276 gsi_insert_before (&gsi, gimple_build_cond_empty (expr), GSI_SAME_STMT);
11277
11278 /* Remove the GIMPLE_OMP_CONTINUE. */
11279 gsi_remove (&gsi, true);
11280
11281 /* Fixup edges from cont_bb */
11282 be = BRANCH_EDGE (cont_bb);
11283 fte = FALLTHRU_EDGE (cont_bb);
11284 be->flags |= EDGE_TRUE_VALUE;
11285 fte->flags ^= EDGE_FALLTHRU | EDGE_FALSE_VALUE;
11286
11287 if (chunking)
11288 {
11289 /* Split the beginning of exit_bb to make bottom_bb. We
11290 need to insert a nop at the start, because splitting is
11291 after a stmt, not before. */
11292 gsi = gsi_start_bb (exit_bb);
11293 stmt = gimple_build_nop ();
11294 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
11295 split = split_block (exit_bb, stmt);
11296 bottom_bb = split->src;
11297 exit_bb = split->dest;
11298 gsi = gsi_last_bb (bottom_bb);
11299
11300 /* Chunk increment and test goes into bottom_bb. */
11301 expr = build2 (PLUS_EXPR, diff_type, chunk_no,
11302 build_int_cst (diff_type, 1));
11303 ass = gimple_build_assign (chunk_no, expr);
11304 gsi_insert_after (&gsi, ass, GSI_CONTINUE_LINKING);
11305
11306 /* Chunk test at end of bottom_bb. */
11307 expr = build2 (LT_EXPR, boolean_type_node, chunk_no, chunk_max);
11308 gsi_insert_after (&gsi, gimple_build_cond_empty (expr),
11309 GSI_CONTINUE_LINKING);
11310
11311 /* Fixup edges from bottom_bb. */
11312 split->flags ^= EDGE_FALLTHRU | EDGE_FALSE_VALUE;
11313 make_edge (bottom_bb, head_bb, EDGE_TRUE_VALUE);
11314 }
11315 }
11316
11317 gsi = gsi_last_bb (exit_bb);
11318 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
11319 loc = gimple_location (gsi_stmt (gsi));
11320
11321 if (!gimple_in_ssa_p (cfun))
11322 {
11323 /* Insert the final value of V, in case it is live. This is the
11324 value for the only thread that survives past the join. */
11325 expr = fold_build2 (MINUS_EXPR, diff_type, range, dir);
11326 expr = fold_build2 (PLUS_EXPR, diff_type, expr, s);
11327 expr = fold_build2 (TRUNC_DIV_EXPR, diff_type, expr, s);
11328 expr = fold_build2 (MULT_EXPR, diff_type, expr, s);
11329 expr = build2 (plus_code, iter_type, b, fold_convert (plus_type, expr));
11330 expr = force_gimple_operand_gsi (&gsi, expr, false, NULL_TREE,
11331 true, GSI_SAME_STMT);
11332 ass = gimple_build_assign (v, expr);
11333 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11334 }
11335
11336 /* Remove the OMP_RETURN. */
11337 gsi_remove (&gsi, true);
11338
11339 if (cont_bb)
11340 {
11341 /* We now have one or two nested loops. Update the loop
11342 structures. */
11343 struct loop *parent = entry_bb->loop_father;
11344 struct loop *body = body_bb->loop_father;
11345
11346 if (chunking)
11347 {
11348 struct loop *chunk_loop = alloc_loop ();
11349 chunk_loop->header = head_bb;
11350 chunk_loop->latch = bottom_bb;
11351 add_loop (chunk_loop, parent);
11352 parent = chunk_loop;
11353 }
11354 else if (parent != body)
11355 {
11356 gcc_assert (body->header == body_bb);
11357 gcc_assert (body->latch == cont_bb
11358 || single_pred (body->latch) == cont_bb);
11359 parent = NULL;
11360 }
11361
11362 if (parent)
11363 {
11364 struct loop *body_loop = alloc_loop ();
11365 body_loop->header = body_bb;
11366 body_loop->latch = cont_bb;
11367 add_loop (body_loop, parent);
11368 }
11369 }
11370}
11371
ca4c3545 11372/* Expand the OMP loop defined by REGION. */
1e8e9920 11373
773c5ba7 11374static void
42acab1c 11375expand_omp_for (struct omp_region *region, gimple *inner_stmt)
773c5ba7 11376{
11377 struct omp_for_data fd;
fd6481cf 11378 struct omp_for_data_loop *loops;
1e8e9920 11379
fd6481cf 11380 loops
11381 = (struct omp_for_data_loop *)
75a70cf9 11382 alloca (gimple_omp_for_collapse (last_stmt (region->entry))
fd6481cf 11383 * sizeof (struct omp_for_data_loop));
1a91d914 11384 extract_omp_for_data (as_a <gomp_for *> (last_stmt (region->entry)),
11385 &fd, loops);
f77459c5 11386 region->sched_kind = fd.sched_kind;
9561765e 11387 region->sched_modifiers = fd.sched_modifiers;
1e8e9920 11388
b3a3ddec 11389 gcc_assert (EDGE_COUNT (region->entry->succs) == 2);
11390 BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
11391 FALLTHRU_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
11392 if (region->cont)
11393 {
11394 gcc_assert (EDGE_COUNT (region->cont->succs) == 2);
11395 BRANCH_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
11396 FALLTHRU_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
11397 }
04c2922b 11398 else
75de4aa2 11399 /* If there isn't a continue then this is a degerate case where
04c2922b 11400 the introduction of abnormal edges during lowering will prevent
11401 original loops from being detected. Fix that up. */
11402 loops_state_set (LOOPS_NEED_FIXUP);
b3a3ddec 11403
10c55644 11404 if (gimple_omp_for_kind (fd.for_stmt) & GF_OMP_FOR_SIMD)
3d483a94 11405 expand_omp_simd (region, &fd);
40750995 11406 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
11407 expand_cilk_for (region, &fd);
a8e785ba 11408 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
11409 {
11410 gcc_assert (!inner_stmt);
11411 expand_oacc_for (region, &fd);
11412 }
43895be5 11413 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_TASKLOOP)
11414 {
11415 if (gimple_omp_for_combined_into_p (fd.for_stmt))
11416 expand_omp_taskloop_for_inner (region, &fd, inner_stmt);
11417 else
11418 expand_omp_taskloop_for_outer (region, &fd, inner_stmt);
11419 }
3d483a94 11420 else if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
bc7bff74 11421 && !fd.have_ordered)
1e8e9920 11422 {
11423 if (fd.chunk_size == NULL)
bc7bff74 11424 expand_omp_for_static_nochunk (region, &fd, inner_stmt);
1e8e9920 11425 else
bc7bff74 11426 expand_omp_for_static_chunk (region, &fd, inner_stmt);
1e8e9920 11427 }
11428 else
11429 {
fd6481cf 11430 int fn_index, start_ix, next_ix;
11431
3d483a94 11432 gcc_assert (gimple_omp_for_kind (fd.for_stmt)
11433 == GF_OMP_FOR_KIND_FOR);
0416ca72 11434 if (fd.chunk_size == NULL
11435 && fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
11436 fd.chunk_size = integer_zero_node;
fd6481cf 11437 gcc_assert (fd.sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
9561765e 11438 switch (fd.sched_kind)
11439 {
11440 case OMP_CLAUSE_SCHEDULE_RUNTIME:
11441 fn_index = 3;
11442 break;
11443 case OMP_CLAUSE_SCHEDULE_DYNAMIC:
11444 case OMP_CLAUSE_SCHEDULE_GUIDED:
11445 if ((fd.sched_modifiers & OMP_CLAUSE_SCHEDULE_NONMONOTONIC)
11446 && !fd.ordered
11447 && !fd.have_ordered)
11448 {
11449 fn_index = 3 + fd.sched_kind;
11450 break;
11451 }
11452 /* FALLTHRU */
11453 default:
11454 fn_index = fd.sched_kind;
11455 break;
11456 }
43895be5 11457 if (!fd.ordered)
9561765e 11458 fn_index += fd.have_ordered * 6;
43895be5 11459 if (fd.ordered)
11460 start_ix = ((int)BUILT_IN_GOMP_LOOP_DOACROSS_STATIC_START) + fn_index;
11461 else
11462 start_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_START) + fn_index;
b9a16870 11463 next_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT) + fn_index;
fd6481cf 11464 if (fd.iter_type == long_long_unsigned_type_node)
11465 {
b9a16870 11466 start_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
11467 - (int)BUILT_IN_GOMP_LOOP_STATIC_START);
11468 next_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
11469 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT);
fd6481cf 11470 }
b9c74b4d 11471 expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
bc7bff74 11472 (enum built_in_function) next_ix, inner_stmt);
1e8e9920 11473 }
28c92cbb 11474
083152fb 11475 if (gimple_in_ssa_p (cfun))
11476 update_ssa (TODO_update_ssa_only_virtuals);
1e8e9920 11477}
11478
1e8e9920 11479
11480/* Expand code for an OpenMP sections directive. In pseudo code, we generate
11481
1e8e9920 11482 v = GOMP_sections_start (n);
11483 L0:
11484 switch (v)
11485 {
11486 case 0:
11487 goto L2;
11488 case 1:
11489 section 1;
11490 goto L1;
11491 case 2:
11492 ...
11493 case n:
11494 ...
1e8e9920 11495 default:
11496 abort ();
11497 }
11498 L1:
11499 v = GOMP_sections_next ();
11500 goto L0;
11501 L2:
11502 reduction;
11503
773c5ba7 11504 If this is a combined parallel sections, replace the call to
79acaae1 11505 GOMP_sections_start with call to GOMP_sections_next. */
1e8e9920 11506
11507static void
773c5ba7 11508expand_omp_sections (struct omp_region *region)
1e8e9920 11509{
f018d957 11510 tree t, u, vin = NULL, vmain, vnext, l2;
75a70cf9 11511 unsigned len;
ac6e3339 11512 basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
75a70cf9 11513 gimple_stmt_iterator si, switch_si;
1a91d914 11514 gomp_sections *sections_stmt;
42acab1c 11515 gimple *stmt;
1a91d914 11516 gomp_continue *cont;
9884aaf8 11517 edge_iterator ei;
11518 edge e;
61e47ac8 11519 struct omp_region *inner;
75a70cf9 11520 unsigned i, casei;
ac6e3339 11521 bool exit_reachable = region->cont != NULL;
1e8e9920 11522
d244d9de 11523 gcc_assert (region->exit != NULL);
61e47ac8 11524 entry_bb = region->entry;
ac6e3339 11525 l0_bb = single_succ (entry_bb);
61e47ac8 11526 l1_bb = region->cont;
ac6e3339 11527 l2_bb = region->exit;
d244d9de 11528 if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
11529 l2 = gimple_block_label (l2_bb);
11530 else
03ed154b 11531 {
d244d9de 11532 /* This can happen if there are reductions. */
11533 len = EDGE_COUNT (l0_bb->succs);
11534 gcc_assert (len > 0);
11535 e = EDGE_SUCC (l0_bb, len - 1);
11536 si = gsi_last_bb (e->dest);
11537 l2 = NULL_TREE;
11538 if (gsi_end_p (si)
11539 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
11540 l2 = gimple_block_label (e->dest);
9884aaf8 11541 else
d244d9de 11542 FOR_EACH_EDGE (e, ei, l0_bb->succs)
11543 {
11544 si = gsi_last_bb (e->dest);
11545 if (gsi_end_p (si)
11546 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
9884aaf8 11547 {
d244d9de 11548 l2 = gimple_block_label (e->dest);
11549 break;
9884aaf8 11550 }
d244d9de 11551 }
03ed154b 11552 }
d244d9de 11553 if (exit_reachable)
11554 default_bb = create_empty_bb (l1_bb->prev_bb);
03ed154b 11555 else
d244d9de 11556 default_bb = create_empty_bb (l0_bb);
773c5ba7 11557
11558 /* We will build a switch() with enough cases for all the
75a70cf9 11559 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
773c5ba7 11560 and a default case to abort if something goes wrong. */
ac6e3339 11561 len = EDGE_COUNT (l0_bb->succs);
75a70cf9 11562
f1f41a6c 11563 /* Use vec::quick_push on label_vec throughout, since we know the size
75a70cf9 11564 in advance. */
c2078b80 11565 auto_vec<tree> label_vec (len);
1e8e9920 11566
61e47ac8 11567 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
75a70cf9 11568 GIMPLE_OMP_SECTIONS statement. */
11569 si = gsi_last_bb (entry_bb);
1a91d914 11570 sections_stmt = as_a <gomp_sections *> (gsi_stmt (si));
75a70cf9 11571 gcc_assert (gimple_code (sections_stmt) == GIMPLE_OMP_SECTIONS);
11572 vin = gimple_omp_sections_control (sections_stmt);
773c5ba7 11573 if (!is_combined_parallel (region))
1e8e9920 11574 {
773c5ba7 11575 /* If we are not inside a combined parallel+sections region,
11576 call GOMP_sections_start. */
39cb6d68 11577 t = build_int_cst (unsigned_type_node, len - 1);
b9a16870 11578 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START);
75a70cf9 11579 stmt = gimple_build_call (u, 1, t);
1e8e9920 11580 }
79acaae1 11581 else
11582 {
11583 /* Otherwise, call GOMP_sections_next. */
b9a16870 11584 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
75a70cf9 11585 stmt = gimple_build_call (u, 0);
79acaae1 11586 }
75a70cf9 11587 gimple_call_set_lhs (stmt, vin);
11588 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
11589 gsi_remove (&si, true);
11590
11591 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
11592 L0_BB. */
11593 switch_si = gsi_last_bb (l0_bb);
11594 gcc_assert (gimple_code (gsi_stmt (switch_si)) == GIMPLE_OMP_SECTIONS_SWITCH);
79acaae1 11595 if (exit_reachable)
11596 {
1a91d914 11597 cont = as_a <gomp_continue *> (last_stmt (l1_bb));
75a70cf9 11598 gcc_assert (gimple_code (cont) == GIMPLE_OMP_CONTINUE);
11599 vmain = gimple_omp_continue_control_use (cont);
11600 vnext = gimple_omp_continue_control_def (cont);
79acaae1 11601 }
11602 else
11603 {
11604 vmain = vin;
11605 vnext = NULL_TREE;
11606 }
1e8e9920 11607
d244d9de 11608 t = build_case_label (build_int_cst (unsigned_type_node, 0), NULL, l2);
f1f41a6c 11609 label_vec.quick_push (t);
d244d9de 11610 i = 1;
03ed154b 11611
75a70cf9 11612 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
ac6e3339 11613 for (inner = region->inner, casei = 1;
11614 inner;
11615 inner = inner->next, i++, casei++)
1e8e9920 11616 {
773c5ba7 11617 basic_block s_entry_bb, s_exit_bb;
11618
9884aaf8 11619 /* Skip optional reduction region. */
75a70cf9 11620 if (inner->type == GIMPLE_OMP_ATOMIC_LOAD)
9884aaf8 11621 {
11622 --i;
11623 --casei;
11624 continue;
11625 }
11626
61e47ac8 11627 s_entry_bb = inner->entry;
11628 s_exit_bb = inner->exit;
1e8e9920 11629
75a70cf9 11630 t = gimple_block_label (s_entry_bb);
ac6e3339 11631 u = build_int_cst (unsigned_type_node, casei);
b6e3dd65 11632 u = build_case_label (u, NULL, t);
f1f41a6c 11633 label_vec.quick_push (u);
61e47ac8 11634
75a70cf9 11635 si = gsi_last_bb (s_entry_bb);
11636 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SECTION);
11637 gcc_assert (i < len || gimple_omp_section_last_p (gsi_stmt (si)));
11638 gsi_remove (&si, true);
61e47ac8 11639 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
03ed154b 11640
11641 if (s_exit_bb == NULL)
11642 continue;
11643
75a70cf9 11644 si = gsi_last_bb (s_exit_bb);
11645 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
11646 gsi_remove (&si, true);
03ed154b 11647
773c5ba7 11648 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
1e8e9920 11649 }
11650
773c5ba7 11651 /* Error handling code goes in DEFAULT_BB. */
75a70cf9 11652 t = gimple_block_label (default_bb);
b6e3dd65 11653 u = build_case_label (NULL, NULL, t);
61e47ac8 11654 make_edge (l0_bb, default_bb, 0);
b3083327 11655 add_bb_to_loop (default_bb, current_loops->tree_root);
1e8e9920 11656
49a70175 11657 stmt = gimple_build_switch (vmain, u, label_vec);
75a70cf9 11658 gsi_insert_after (&switch_si, stmt, GSI_SAME_STMT);
11659 gsi_remove (&switch_si, true);
75a70cf9 11660
11661 si = gsi_start_bb (default_bb);
b9a16870 11662 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
75a70cf9 11663 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
773c5ba7 11664
ac6e3339 11665 if (exit_reachable)
03ed154b 11666 {
b9a16870 11667 tree bfn_decl;
11668
ac6e3339 11669 /* Code to get the next section goes in L1_BB. */
75a70cf9 11670 si = gsi_last_bb (l1_bb);
11671 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
1e8e9920 11672
b9a16870 11673 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
11674 stmt = gimple_build_call (bfn_decl, 0);
75a70cf9 11675 gimple_call_set_lhs (stmt, vnext);
11676 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
11677 gsi_remove (&si, true);
773c5ba7 11678
ac6e3339 11679 single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
03ed154b 11680 }
773c5ba7 11681
d244d9de 11682 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
11683 si = gsi_last_bb (l2_bb);
11684 if (gimple_omp_return_nowait_p (gsi_stmt (si)))
11685 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
bc7bff74 11686 else if (gimple_omp_return_lhs (gsi_stmt (si)))
11687 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL);
d244d9de 11688 else
11689 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
11690 stmt = gimple_build_call (t, 0);
bc7bff74 11691 if (gimple_omp_return_lhs (gsi_stmt (si)))
11692 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (si)));
d244d9de 11693 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
11694 gsi_remove (&si, true);
11695
79acaae1 11696 set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
773c5ba7 11697}
1e8e9920 11698
1e8e9920 11699
61e47ac8 11700/* Expand code for an OpenMP single directive. We've already expanded
11701 much of the code, here we simply place the GOMP_barrier call. */
11702
11703static void
11704expand_omp_single (struct omp_region *region)
11705{
11706 basic_block entry_bb, exit_bb;
75a70cf9 11707 gimple_stmt_iterator si;
61e47ac8 11708
11709 entry_bb = region->entry;
11710 exit_bb = region->exit;
11711
75a70cf9 11712 si = gsi_last_bb (entry_bb);
75a70cf9 11713 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE);
11714 gsi_remove (&si, true);
61e47ac8 11715 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
11716
75a70cf9 11717 si = gsi_last_bb (exit_bb);
bc7bff74 11718 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
11719 {
11720 tree t = gimple_omp_return_lhs (gsi_stmt (si));
11721 gsi_insert_after (&si, build_omp_barrier (t), GSI_SAME_STMT);
11722 }
75a70cf9 11723 gsi_remove (&si, true);
61e47ac8 11724 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
11725}
11726
11727
11728/* Generic expansion for OpenMP synchronization directives: master,
11729 ordered and critical. All we need to do here is remove the entry
11730 and exit markers for REGION. */
773c5ba7 11731
11732static void
11733expand_omp_synch (struct omp_region *region)
11734{
11735 basic_block entry_bb, exit_bb;
75a70cf9 11736 gimple_stmt_iterator si;
773c5ba7 11737
61e47ac8 11738 entry_bb = region->entry;
11739 exit_bb = region->exit;
773c5ba7 11740
75a70cf9 11741 si = gsi_last_bb (entry_bb);
11742 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE
11743 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASTER
bc7bff74 11744 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TASKGROUP
75a70cf9 11745 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ORDERED
bc7bff74 11746 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CRITICAL
11747 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TEAMS);
75a70cf9 11748 gsi_remove (&si, true);
773c5ba7 11749 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
11750
03ed154b 11751 if (exit_bb)
11752 {
75a70cf9 11753 si = gsi_last_bb (exit_bb);
11754 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
11755 gsi_remove (&si, true);
03ed154b 11756 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
11757 }
773c5ba7 11758}
1e8e9920 11759
2169f33b 11760/* A subroutine of expand_omp_atomic. Attempt to implement the atomic
11761 operation as a normal volatile load. */
11762
11763static bool
3ec11c49 11764expand_omp_atomic_load (basic_block load_bb, tree addr,
11765 tree loaded_val, int index)
2169f33b 11766{
3ec11c49 11767 enum built_in_function tmpbase;
11768 gimple_stmt_iterator gsi;
11769 basic_block store_bb;
11770 location_t loc;
42acab1c 11771 gimple *stmt;
3ec11c49 11772 tree decl, call, type, itype;
11773
11774 gsi = gsi_last_bb (load_bb);
11775 stmt = gsi_stmt (gsi);
11776 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
11777 loc = gimple_location (stmt);
11778
11779 /* ??? If the target does not implement atomic_load_optab[mode], and mode
11780 is smaller than word size, then expand_atomic_load assumes that the load
11781 is atomic. We could avoid the builtin entirely in this case. */
11782
11783 tmpbase = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
11784 decl = builtin_decl_explicit (tmpbase);
11785 if (decl == NULL_TREE)
11786 return false;
11787
11788 type = TREE_TYPE (loaded_val);
11789 itype = TREE_TYPE (TREE_TYPE (decl));
11790
11791 call = build_call_expr_loc (loc, decl, 2, addr,
bc7bff74 11792 build_int_cst (NULL,
11793 gimple_omp_atomic_seq_cst_p (stmt)
11794 ? MEMMODEL_SEQ_CST
11795 : MEMMODEL_RELAXED));
3ec11c49 11796 if (!useless_type_conversion_p (type, itype))
11797 call = fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
11798 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
11799
11800 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
11801 gsi_remove (&gsi, true);
11802
11803 store_bb = single_succ (load_bb);
11804 gsi = gsi_last_bb (store_bb);
11805 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
11806 gsi_remove (&gsi, true);
11807
11808 if (gimple_in_ssa_p (cfun))
11809 update_ssa (TODO_update_ssa_no_phi);
11810
11811 return true;
2169f33b 11812}
11813
11814/* A subroutine of expand_omp_atomic. Attempt to implement the atomic
11815 operation as a normal volatile store. */
11816
11817static bool
3ec11c49 11818expand_omp_atomic_store (basic_block load_bb, tree addr,
11819 tree loaded_val, tree stored_val, int index)
2169f33b 11820{
3ec11c49 11821 enum built_in_function tmpbase;
11822 gimple_stmt_iterator gsi;
11823 basic_block store_bb = single_succ (load_bb);
11824 location_t loc;
42acab1c 11825 gimple *stmt;
3ec11c49 11826 tree decl, call, type, itype;
3754d046 11827 machine_mode imode;
3ec11c49 11828 bool exchange;
11829
11830 gsi = gsi_last_bb (load_bb);
11831 stmt = gsi_stmt (gsi);
11832 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
11833
11834 /* If the load value is needed, then this isn't a store but an exchange. */
11835 exchange = gimple_omp_atomic_need_value_p (stmt);
11836
11837 gsi = gsi_last_bb (store_bb);
11838 stmt = gsi_stmt (gsi);
11839 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE);
11840 loc = gimple_location (stmt);
11841
11842 /* ??? If the target does not implement atomic_store_optab[mode], and mode
11843 is smaller than word size, then expand_atomic_store assumes that the store
11844 is atomic. We could avoid the builtin entirely in this case. */
11845
11846 tmpbase = (exchange ? BUILT_IN_ATOMIC_EXCHANGE_N : BUILT_IN_ATOMIC_STORE_N);
11847 tmpbase = (enum built_in_function) ((int) tmpbase + index + 1);
11848 decl = builtin_decl_explicit (tmpbase);
11849 if (decl == NULL_TREE)
11850 return false;
11851
11852 type = TREE_TYPE (stored_val);
11853
11854 /* Dig out the type of the function's second argument. */
11855 itype = TREE_TYPE (decl);
11856 itype = TYPE_ARG_TYPES (itype);
11857 itype = TREE_CHAIN (itype);
11858 itype = TREE_VALUE (itype);
11859 imode = TYPE_MODE (itype);
11860
11861 if (exchange && !can_atomic_exchange_p (imode, true))
11862 return false;
11863
11864 if (!useless_type_conversion_p (itype, type))
11865 stored_val = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, stored_val);
11866 call = build_call_expr_loc (loc, decl, 3, addr, stored_val,
bc7bff74 11867 build_int_cst (NULL,
11868 gimple_omp_atomic_seq_cst_p (stmt)
11869 ? MEMMODEL_SEQ_CST
11870 : MEMMODEL_RELAXED));
3ec11c49 11871 if (exchange)
11872 {
11873 if (!useless_type_conversion_p (type, itype))
11874 call = build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
11875 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
11876 }
11877
11878 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
11879 gsi_remove (&gsi, true);
11880
11881 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
11882 gsi = gsi_last_bb (load_bb);
11883 gsi_remove (&gsi, true);
11884
11885 if (gimple_in_ssa_p (cfun))
11886 update_ssa (TODO_update_ssa_no_phi);
11887
11888 return true;
2169f33b 11889}
11890
cb7f680b 11891/* A subroutine of expand_omp_atomic. Attempt to implement the atomic
1cd6e20d 11892 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
cb7f680b 11893 size of the data type, and thus usable to find the index of the builtin
11894 decl. Returns false if the expression is not of the proper form. */
11895
11896static bool
11897expand_omp_atomic_fetch_op (basic_block load_bb,
11898 tree addr, tree loaded_val,
11899 tree stored_val, int index)
11900{
b9a16870 11901 enum built_in_function oldbase, newbase, tmpbase;
cb7f680b 11902 tree decl, itype, call;
2169f33b 11903 tree lhs, rhs;
cb7f680b 11904 basic_block store_bb = single_succ (load_bb);
75a70cf9 11905 gimple_stmt_iterator gsi;
42acab1c 11906 gimple *stmt;
389dd41b 11907 location_t loc;
1cd6e20d 11908 enum tree_code code;
2169f33b 11909 bool need_old, need_new;
3754d046 11910 machine_mode imode;
bc7bff74 11911 bool seq_cst;
cb7f680b 11912
11913 /* We expect to find the following sequences:
48e1416a 11914
cb7f680b 11915 load_bb:
75a70cf9 11916 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
cb7f680b 11917
11918 store_bb:
11919 val = tmp OP something; (or: something OP tmp)
48e1416a 11920 GIMPLE_OMP_STORE (val)
cb7f680b 11921
48e1416a 11922 ???FIXME: Allow a more flexible sequence.
cb7f680b 11923 Perhaps use data flow to pick the statements.
48e1416a 11924
cb7f680b 11925 */
11926
75a70cf9 11927 gsi = gsi_after_labels (store_bb);
11928 stmt = gsi_stmt (gsi);
389dd41b 11929 loc = gimple_location (stmt);
75a70cf9 11930 if (!is_gimple_assign (stmt))
cb7f680b 11931 return false;
75a70cf9 11932 gsi_next (&gsi);
11933 if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE)
cb7f680b 11934 return false;
2169f33b 11935 need_new = gimple_omp_atomic_need_value_p (gsi_stmt (gsi));
11936 need_old = gimple_omp_atomic_need_value_p (last_stmt (load_bb));
bc7bff74 11937 seq_cst = gimple_omp_atomic_seq_cst_p (last_stmt (load_bb));
2169f33b 11938 gcc_checking_assert (!need_old || !need_new);
cb7f680b 11939
75a70cf9 11940 if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
cb7f680b 11941 return false;
11942
cb7f680b 11943 /* Check for one of the supported fetch-op operations. */
1cd6e20d 11944 code = gimple_assign_rhs_code (stmt);
11945 switch (code)
cb7f680b 11946 {
11947 case PLUS_EXPR:
11948 case POINTER_PLUS_EXPR:
1cd6e20d 11949 oldbase = BUILT_IN_ATOMIC_FETCH_ADD_N;
11950 newbase = BUILT_IN_ATOMIC_ADD_FETCH_N;
cb7f680b 11951 break;
11952 case MINUS_EXPR:
1cd6e20d 11953 oldbase = BUILT_IN_ATOMIC_FETCH_SUB_N;
11954 newbase = BUILT_IN_ATOMIC_SUB_FETCH_N;
cb7f680b 11955 break;
11956 case BIT_AND_EXPR:
1cd6e20d 11957 oldbase = BUILT_IN_ATOMIC_FETCH_AND_N;
11958 newbase = BUILT_IN_ATOMIC_AND_FETCH_N;
cb7f680b 11959 break;
11960 case BIT_IOR_EXPR:
1cd6e20d 11961 oldbase = BUILT_IN_ATOMIC_FETCH_OR_N;
11962 newbase = BUILT_IN_ATOMIC_OR_FETCH_N;
cb7f680b 11963 break;
11964 case BIT_XOR_EXPR:
1cd6e20d 11965 oldbase = BUILT_IN_ATOMIC_FETCH_XOR_N;
11966 newbase = BUILT_IN_ATOMIC_XOR_FETCH_N;
cb7f680b 11967 break;
11968 default:
11969 return false;
11970 }
1cd6e20d 11971
cb7f680b 11972 /* Make sure the expression is of the proper form. */
75a70cf9 11973 if (operand_equal_p (gimple_assign_rhs1 (stmt), loaded_val, 0))
11974 rhs = gimple_assign_rhs2 (stmt);
11975 else if (commutative_tree_code (gimple_assign_rhs_code (stmt))
11976 && operand_equal_p (gimple_assign_rhs2 (stmt), loaded_val, 0))
11977 rhs = gimple_assign_rhs1 (stmt);
cb7f680b 11978 else
11979 return false;
11980
b9a16870 11981 tmpbase = ((enum built_in_function)
11982 ((need_new ? newbase : oldbase) + index + 1));
11983 decl = builtin_decl_explicit (tmpbase);
0f94f46b 11984 if (decl == NULL_TREE)
11985 return false;
cb7f680b 11986 itype = TREE_TYPE (TREE_TYPE (decl));
1cd6e20d 11987 imode = TYPE_MODE (itype);
cb7f680b 11988
1cd6e20d 11989 /* We could test all of the various optabs involved, but the fact of the
11990 matter is that (with the exception of i486 vs i586 and xadd) all targets
11991 that support any atomic operaton optab also implements compare-and-swap.
11992 Let optabs.c take care of expanding any compare-and-swap loop. */
29139cdc 11993 if (!can_compare_and_swap_p (imode, true))
cb7f680b 11994 return false;
11995
75a70cf9 11996 gsi = gsi_last_bb (load_bb);
11997 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
1cd6e20d 11998
11999 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
12000 It only requires that the operation happen atomically. Thus we can
12001 use the RELAXED memory model. */
12002 call = build_call_expr_loc (loc, decl, 3, addr,
12003 fold_convert_loc (loc, itype, rhs),
bc7bff74 12004 build_int_cst (NULL,
12005 seq_cst ? MEMMODEL_SEQ_CST
12006 : MEMMODEL_RELAXED));
1cd6e20d 12007
2169f33b 12008 if (need_old || need_new)
12009 {
12010 lhs = need_old ? loaded_val : stored_val;
12011 call = fold_convert_loc (loc, TREE_TYPE (lhs), call);
12012 call = build2_loc (loc, MODIFY_EXPR, void_type_node, lhs, call);
12013 }
12014 else
12015 call = fold_convert_loc (loc, void_type_node, call);
75a70cf9 12016 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
12017 gsi_remove (&gsi, true);
cb7f680b 12018
75a70cf9 12019 gsi = gsi_last_bb (store_bb);
12020 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
12021 gsi_remove (&gsi, true);
12022 gsi = gsi_last_bb (store_bb);
97d59451 12023 stmt = gsi_stmt (gsi);
75a70cf9 12024 gsi_remove (&gsi, true);
cb7f680b 12025
12026 if (gimple_in_ssa_p (cfun))
97d59451 12027 {
12028 release_defs (stmt);
12029 update_ssa (TODO_update_ssa_no_phi);
12030 }
cb7f680b 12031
12032 return true;
12033}
12034
12035/* A subroutine of expand_omp_atomic. Implement the atomic operation as:
12036
12037 oldval = *addr;
12038 repeat:
12039 newval = rhs; // with oldval replacing *addr in rhs
12040 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
12041 if (oldval != newval)
12042 goto repeat;
12043
12044 INDEX is log2 of the size of the data type, and thus usable to find the
12045 index of the builtin decl. */
12046
12047static bool
12048expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
12049 tree addr, tree loaded_val, tree stored_val,
12050 int index)
12051{
790368c5 12052 tree loadedi, storedi, initial, new_storedi, old_vali;
cb7f680b 12053 tree type, itype, cmpxchg, iaddr;
75a70cf9 12054 gimple_stmt_iterator si;
cb7f680b 12055 basic_block loop_header = single_succ (load_bb);
42acab1c 12056 gimple *phi, *stmt;
cb7f680b 12057 edge e;
b9a16870 12058 enum built_in_function fncode;
cb7f680b 12059
1cd6e20d 12060 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
12061 order to use the RELAXED memory model effectively. */
b9a16870 12062 fncode = (enum built_in_function)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
12063 + index + 1);
12064 cmpxchg = builtin_decl_explicit (fncode);
0f94f46b 12065 if (cmpxchg == NULL_TREE)
12066 return false;
cb7f680b 12067 type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
12068 itype = TREE_TYPE (TREE_TYPE (cmpxchg));
12069
29139cdc 12070 if (!can_compare_and_swap_p (TYPE_MODE (itype), true))
cb7f680b 12071 return false;
12072
75a70cf9 12073 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
12074 si = gsi_last_bb (load_bb);
12075 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
12076
790368c5 12077 /* For floating-point values, we'll need to view-convert them to integers
12078 so that we can perform the atomic compare and swap. Simplify the
12079 following code by always setting up the "i"ntegral variables. */
12080 if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
12081 {
75a70cf9 12082 tree iaddr_val;
12083
072f7ab1 12084 iaddr = create_tmp_reg (build_pointer_type_for_mode (itype, ptr_mode,
f9e245b2 12085 true));
75a70cf9 12086 iaddr_val
12087 = force_gimple_operand_gsi (&si,
12088 fold_convert (TREE_TYPE (iaddr), addr),
12089 false, NULL_TREE, true, GSI_SAME_STMT);
12090 stmt = gimple_build_assign (iaddr, iaddr_val);
12091 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
f9e245b2 12092 loadedi = create_tmp_var (itype);
790368c5 12093 if (gimple_in_ssa_p (cfun))
f9e245b2 12094 loadedi = make_ssa_name (loadedi);
790368c5 12095 }
12096 else
12097 {
12098 iaddr = addr;
12099 loadedi = loaded_val;
12100 }
75a70cf9 12101
2ed72821 12102 fncode = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
12103 tree loaddecl = builtin_decl_explicit (fncode);
12104 if (loaddecl)
12105 initial
12106 = fold_convert (TREE_TYPE (TREE_TYPE (iaddr)),
12107 build_call_expr (loaddecl, 2, iaddr,
12108 build_int_cst (NULL_TREE,
12109 MEMMODEL_RELAXED)));
12110 else
12111 initial = build2 (MEM_REF, TREE_TYPE (TREE_TYPE (iaddr)), iaddr,
12112 build_int_cst (TREE_TYPE (iaddr), 0));
12113
182cf5a9 12114 initial
2ed72821 12115 = force_gimple_operand_gsi (&si, initial, true, NULL_TREE, true,
12116 GSI_SAME_STMT);
790368c5 12117
12118 /* Move the value to the LOADEDI temporary. */
cb7f680b 12119 if (gimple_in_ssa_p (cfun))
12120 {
75a70cf9 12121 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header)));
790368c5 12122 phi = create_phi_node (loadedi, loop_header);
cb7f680b 12123 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)),
12124 initial);
12125 }
12126 else
75a70cf9 12127 gsi_insert_before (&si,
12128 gimple_build_assign (loadedi, initial),
12129 GSI_SAME_STMT);
790368c5 12130 if (loadedi != loaded_val)
12131 {
75a70cf9 12132 gimple_stmt_iterator gsi2;
12133 tree x;
790368c5 12134
12135 x = build1 (VIEW_CONVERT_EXPR, type, loadedi);
75a70cf9 12136 gsi2 = gsi_start_bb (loop_header);
790368c5 12137 if (gimple_in_ssa_p (cfun))
12138 {
1a91d914 12139 gassign *stmt;
75a70cf9 12140 x = force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
12141 true, GSI_SAME_STMT);
12142 stmt = gimple_build_assign (loaded_val, x);
12143 gsi_insert_before (&gsi2, stmt, GSI_SAME_STMT);
790368c5 12144 }
12145 else
12146 {
75a70cf9 12147 x = build2 (MODIFY_EXPR, TREE_TYPE (loaded_val), loaded_val, x);
12148 force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
12149 true, GSI_SAME_STMT);
790368c5 12150 }
12151 }
75a70cf9 12152 gsi_remove (&si, true);
cb7f680b 12153
75a70cf9 12154 si = gsi_last_bb (store_bb);
12155 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
cb7f680b 12156
790368c5 12157 if (iaddr == addr)
12158 storedi = stored_val;
cb7f680b 12159 else
790368c5 12160 storedi =
75a70cf9 12161 force_gimple_operand_gsi (&si,
790368c5 12162 build1 (VIEW_CONVERT_EXPR, itype,
12163 stored_val), true, NULL_TREE, true,
75a70cf9 12164 GSI_SAME_STMT);
cb7f680b 12165
12166 /* Build the compare&swap statement. */
12167 new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi);
75a70cf9 12168 new_storedi = force_gimple_operand_gsi (&si,
87f9ffa4 12169 fold_convert (TREE_TYPE (loadedi),
12170 new_storedi),
cb7f680b 12171 true, NULL_TREE,
75a70cf9 12172 true, GSI_SAME_STMT);
cb7f680b 12173
12174 if (gimple_in_ssa_p (cfun))
12175 old_vali = loadedi;
12176 else
12177 {
f9e245b2 12178 old_vali = create_tmp_var (TREE_TYPE (loadedi));
75a70cf9 12179 stmt = gimple_build_assign (old_vali, loadedi);
12180 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
cb7f680b 12181
75a70cf9 12182 stmt = gimple_build_assign (loadedi, new_storedi);
12183 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
cb7f680b 12184 }
12185
12186 /* Note that we always perform the comparison as an integer, even for
48e1416a 12187 floating point. This allows the atomic operation to properly
cb7f680b 12188 succeed even with NaNs and -0.0. */
75a70cf9 12189 stmt = gimple_build_cond_empty
12190 (build2 (NE_EXPR, boolean_type_node,
12191 new_storedi, old_vali));
12192 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
cb7f680b 12193
12194 /* Update cfg. */
12195 e = single_succ_edge (store_bb);
12196 e->flags &= ~EDGE_FALLTHRU;
12197 e->flags |= EDGE_FALSE_VALUE;
12198
12199 e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE);
12200
790368c5 12201 /* Copy the new value to loadedi (we already did that before the condition
cb7f680b 12202 if we are not in SSA). */
12203 if (gimple_in_ssa_p (cfun))
12204 {
75a70cf9 12205 phi = gimple_seq_first_stmt (phi_nodes (loop_header));
790368c5 12206 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), new_storedi);
cb7f680b 12207 }
12208
75a70cf9 12209 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
12210 gsi_remove (&si, true);
cb7f680b 12211
04c2922b 12212 struct loop *loop = alloc_loop ();
12213 loop->header = loop_header;
5f037457 12214 loop->latch = store_bb;
04c2922b 12215 add_loop (loop, loop_header->loop_father);
12216
cb7f680b 12217 if (gimple_in_ssa_p (cfun))
12218 update_ssa (TODO_update_ssa_no_phi);
12219
12220 return true;
12221}
12222
12223/* A subroutine of expand_omp_atomic. Implement the atomic operation as:
12224
12225 GOMP_atomic_start ();
12226 *addr = rhs;
12227 GOMP_atomic_end ();
12228
12229 The result is not globally atomic, but works so long as all parallel
12230 references are within #pragma omp atomic directives. According to
12231 responses received from omp@openmp.org, appears to be within spec.
12232 Which makes sense, since that's how several other compilers handle
48e1416a 12233 this situation as well.
75a70cf9 12234 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
12235 expanding. STORED_VAL is the operand of the matching
12236 GIMPLE_OMP_ATOMIC_STORE.
cb7f680b 12237
48e1416a 12238 We replace
12239 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
cb7f680b 12240 loaded_val = *addr;
12241
12242 and replace
3ec11c49 12243 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
48e1416a 12244 *addr = stored_val;
cb7f680b 12245*/
12246
12247static bool
12248expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
12249 tree addr, tree loaded_val, tree stored_val)
12250{
75a70cf9 12251 gimple_stmt_iterator si;
1a91d914 12252 gassign *stmt;
cb7f680b 12253 tree t;
12254
75a70cf9 12255 si = gsi_last_bb (load_bb);
12256 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
cb7f680b 12257
b9a16870 12258 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
414c3a2c 12259 t = build_call_expr (t, 0);
75a70cf9 12260 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
cb7f680b 12261
182cf5a9 12262 stmt = gimple_build_assign (loaded_val, build_simple_mem_ref (addr));
75a70cf9 12263 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
12264 gsi_remove (&si, true);
cb7f680b 12265
75a70cf9 12266 si = gsi_last_bb (store_bb);
12267 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
cb7f680b 12268
182cf5a9 12269 stmt = gimple_build_assign (build_simple_mem_ref (unshare_expr (addr)),
12270 stored_val);
75a70cf9 12271 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
cb7f680b 12272
b9a16870 12273 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
414c3a2c 12274 t = build_call_expr (t, 0);
75a70cf9 12275 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
12276 gsi_remove (&si, true);
cb7f680b 12277
12278 if (gimple_in_ssa_p (cfun))
12279 update_ssa (TODO_update_ssa_no_phi);
12280 return true;
12281}
12282
48e1416a 12283/* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
12284 using expand_omp_atomic_fetch_op. If it failed, we try to
cb7f680b 12285 call expand_omp_atomic_pipeline, and if it fails too, the
12286 ultimate fallback is wrapping the operation in a mutex
48e1416a 12287 (expand_omp_atomic_mutex). REGION is the atomic region built
12288 by build_omp_regions_1(). */
cb7f680b 12289
12290static void
12291expand_omp_atomic (struct omp_region *region)
12292{
12293 basic_block load_bb = region->entry, store_bb = region->exit;
1a91d914 12294 gomp_atomic_load *load = as_a <gomp_atomic_load *> (last_stmt (load_bb));
12295 gomp_atomic_store *store = as_a <gomp_atomic_store *> (last_stmt (store_bb));
75a70cf9 12296 tree loaded_val = gimple_omp_atomic_load_lhs (load);
12297 tree addr = gimple_omp_atomic_load_rhs (load);
12298 tree stored_val = gimple_omp_atomic_store_val (store);
cb7f680b 12299 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
12300 HOST_WIDE_INT index;
12301
12302 /* Make sure the type is one of the supported sizes. */
e913b5cd 12303 index = tree_to_uhwi (TYPE_SIZE_UNIT (type));
cb7f680b 12304 index = exact_log2 (index);
12305 if (index >= 0 && index <= 4)
12306 {
12307 unsigned int align = TYPE_ALIGN_UNIT (type);
12308
12309 /* __sync builtins require strict data alignment. */
dcf7024c 12310 if (exact_log2 (align) >= index)
cb7f680b 12311 {
3ec11c49 12312 /* Atomic load. */
2169f33b 12313 if (loaded_val == stored_val
12314 && (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
12315 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
12316 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
3ec11c49 12317 && expand_omp_atomic_load (load_bb, addr, loaded_val, index))
2169f33b 12318 return;
12319
3ec11c49 12320 /* Atomic store. */
2169f33b 12321 if ((GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
12322 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
12323 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
12324 && store_bb == single_succ (load_bb)
12325 && first_stmt (store_bb) == store
3ec11c49 12326 && expand_omp_atomic_store (load_bb, addr, loaded_val,
12327 stored_val, index))
2169f33b 12328 return;
12329
cb7f680b 12330 /* When possible, use specialized atomic update functions. */
12331 if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
3ec11c49 12332 && store_bb == single_succ (load_bb)
12333 && expand_omp_atomic_fetch_op (load_bb, addr,
12334 loaded_val, stored_val, index))
12335 return;
cb7f680b 12336
12337 /* If we don't have specialized __sync builtins, try and implement
12338 as a compare and swap loop. */
12339 if (expand_omp_atomic_pipeline (load_bb, store_bb, addr,
12340 loaded_val, stored_val, index))
12341 return;
12342 }
12343 }
12344
12345 /* The ultimate fallback is wrapping the operation in a mutex. */
12346 expand_omp_atomic_mutex (load_bb, store_bb, addr, loaded_val, stored_val);
12347}
12348
1e8e9920 12349
f69b8a4c 12350/* Encode an oacc launch argument. This matches the GOMP_LAUNCH_PACK
e561d5e1 12351 macro on gomp-constants.h. We do not check for overflow. */
12352
12353static tree
12354oacc_launch_pack (unsigned code, tree device, unsigned op)
12355{
12356 tree res;
12357
12358 res = build_int_cst (unsigned_type_node, GOMP_LAUNCH_PACK (code, 0, op));
12359 if (device)
12360 {
12361 device = fold_build2 (LSHIFT_EXPR, unsigned_type_node,
12362 device, build_int_cst (unsigned_type_node,
12363 GOMP_LAUNCH_DEVICE_SHIFT));
12364 res = fold_build2 (BIT_IOR_EXPR, unsigned_type_node, res, device);
12365 }
12366 return res;
12367}
12368
12369/* Look for compute grid dimension clauses and convert to an attribute
12370 attached to FN. This permits the target-side code to (a) massage
12371 the dimensions, (b) emit that data and (c) optimize. Non-constant
12372 dimensions are pushed onto ARGS.
12373
12374 The attribute value is a TREE_LIST. A set of dimensions is
12375 represented as a list of INTEGER_CST. Those that are runtime
f69b8a4c 12376 exprs are represented as an INTEGER_CST of zero.
e561d5e1 12377
12378 TOOO. Normally the attribute will just contain a single such list. If
12379 however it contains a list of lists, this will represent the use of
12380 device_type. Each member of the outer list is an assoc list of
12381 dimensions, keyed by the device type. The first entry will be the
12382 default. Well, that's the plan. */
12383
12384#define OACC_FN_ATTRIB "oacc function"
12385
12386/* Replace any existing oacc fn attribute with updated dimensions. */
12387
12388void
12389replace_oacc_fn_attrib (tree fn, tree dims)
12390{
12391 tree ident = get_identifier (OACC_FN_ATTRIB);
12392 tree attribs = DECL_ATTRIBUTES (fn);
12393
12394 /* If we happen to be present as the first attrib, drop it. */
12395 if (attribs && TREE_PURPOSE (attribs) == ident)
12396 attribs = TREE_CHAIN (attribs);
12397 DECL_ATTRIBUTES (fn) = tree_cons (ident, dims, attribs);
12398}
12399
12400/* Scan CLAUSES for launch dimensions and attach them to the oacc
12401 function attribute. Push any that are non-constant onto the ARGS
12402 list, along with an appropriate GOMP_LAUNCH_DIM tag. */
12403
12404static void
12405set_oacc_fn_attrib (tree fn, tree clauses, vec<tree> *args)
12406{
12407 /* Must match GOMP_DIM ordering. */
12408 static const omp_clause_code ids[]
12409 = { OMP_CLAUSE_NUM_GANGS, OMP_CLAUSE_NUM_WORKERS,
12410 OMP_CLAUSE_VECTOR_LENGTH };
12411 unsigned ix;
12412 tree dims[GOMP_DIM_MAX];
12413 tree attr = NULL_TREE;
12414 unsigned non_const = 0;
12415
12416 for (ix = GOMP_DIM_MAX; ix--;)
12417 {
12418 tree clause = find_omp_clause (clauses, ids[ix]);
12419 tree dim = NULL_TREE;
12420
12421 if (clause)
12422 dim = OMP_CLAUSE_EXPR (clause, ids[ix]);
12423 dims[ix] = dim;
12424 if (dim && TREE_CODE (dim) != INTEGER_CST)
12425 {
12426 dim = integer_zero_node;
12427 non_const |= GOMP_DIM_MASK (ix);
12428 }
12429 attr = tree_cons (NULL_TREE, dim, attr);
12430 }
12431
12432 replace_oacc_fn_attrib (fn, attr);
12433
12434 if (non_const)
12435 {
12436 /* Push a dynamic argument set. */
12437 args->safe_push (oacc_launch_pack (GOMP_LAUNCH_DIM,
12438 NULL_TREE, non_const));
12439 for (unsigned ix = 0; ix != GOMP_DIM_MAX; ix++)
12440 if (non_const & GOMP_DIM_MASK (ix))
12441 args->safe_push (dims[ix]);
12442 }
12443}
12444
a1b7fe4b 12445/* Process the routine's dimension clauess to generate an attribute
12446 value. Issue diagnostics as appropriate. We default to SEQ
12447 (OpenACC 2.5 clarifies this). All dimensions have a size of zero
12448 (dynamic). TREE_PURPOSE is set to indicate whether that dimension
12449 can have a loop partitioned on it. non-zero indicates
12450 yes, zero indicates no. By construction once a non-zero has been
12451 reached, further inner dimensions must also be non-zero. We set
12452 TREE_VALUE to zero for the dimensions that may be partitioned and
12453 1 for the other ones -- if a loop is (erroneously) spawned at
12454 an outer level, we don't want to try and partition it. */
12455
12456tree
12457build_oacc_routine_dims (tree clauses)
12458{
12459 /* Must match GOMP_DIM ordering. */
12460 static const omp_clause_code ids[] =
12461 {OMP_CLAUSE_GANG, OMP_CLAUSE_WORKER, OMP_CLAUSE_VECTOR, OMP_CLAUSE_SEQ};
12462 int ix;
12463 int level = -1;
12464
12465 for (; clauses; clauses = OMP_CLAUSE_CHAIN (clauses))
12466 for (ix = GOMP_DIM_MAX + 1; ix--;)
12467 if (OMP_CLAUSE_CODE (clauses) == ids[ix])
12468 {
12469 if (level >= 0)
12470 error_at (OMP_CLAUSE_LOCATION (clauses),
12471 "multiple loop axes specified for routine");
12472 level = ix;
12473 break;
12474 }
12475
12476 /* Default to SEQ. */
12477 if (level < 0)
12478 level = GOMP_DIM_MAX;
12479
12480 tree dims = NULL_TREE;
12481
12482 for (ix = GOMP_DIM_MAX; ix--;)
12483 dims = tree_cons (build_int_cst (boolean_type_node, ix >= level),
12484 build_int_cst (integer_type_node, ix < level), dims);
12485
12486 return dims;
12487}
12488
e561d5e1 12489/* Retrieve the oacc function attrib and return it. Non-oacc
12490 functions will return NULL. */
12491
12492tree
12493get_oacc_fn_attrib (tree fn)
12494{
12495 return lookup_attribute (OACC_FN_ATTRIB, DECL_ATTRIBUTES (fn));
12496}
12497
e1037942 12498/* Extract an oacc execution dimension from FN. FN must be an
12499 offloaded function or routine that has already had its execution
12500 dimensions lowered to the target-specific values. */
12501
12502int
12503get_oacc_fn_dim_size (tree fn, int axis)
12504{
12505 tree attrs = get_oacc_fn_attrib (fn);
12506
12507 gcc_assert (axis < GOMP_DIM_MAX);
12508
12509 tree dims = TREE_VALUE (attrs);
12510 while (axis--)
12511 dims = TREE_CHAIN (dims);
12512
12513 int size = TREE_INT_CST_LOW (TREE_VALUE (dims));
12514
12515 return size;
12516}
12517
12518/* Extract the dimension axis from an IFN_GOACC_DIM_POS or
12519 IFN_GOACC_DIM_SIZE call. */
12520
12521int
12522get_oacc_ifn_dim_arg (const gimple *stmt)
12523{
12524 gcc_checking_assert (gimple_call_internal_fn (stmt) == IFN_GOACC_DIM_SIZE
12525 || gimple_call_internal_fn (stmt) == IFN_GOACC_DIM_POS);
12526 tree arg = gimple_call_arg (stmt, 0);
12527 HOST_WIDE_INT axis = TREE_INT_CST_LOW (arg);
12528
12529 gcc_checking_assert (axis >= 0 && axis < GOMP_DIM_MAX);
12530 return (int) axis;
12531}
12532
1a40f20b 12533/* Mark the loops inside the kernels region starting at REGION_ENTRY and ending
12534 at REGION_EXIT. */
12535
12536static void
12537mark_loops_in_oacc_kernels_region (basic_block region_entry,
12538 basic_block region_exit)
12539{
12540 struct loop *outer = region_entry->loop_father;
12541 gcc_assert (region_exit == NULL || outer == region_exit->loop_father);
12542
12543 /* Don't parallelize the kernels region if it contains more than one outer
12544 loop. */
12545 unsigned int nr_outer_loops = 0;
4dae4a1a 12546 struct loop *single_outer = NULL;
1a40f20b 12547 for (struct loop *loop = outer->inner; loop != NULL; loop = loop->next)
12548 {
12549 gcc_assert (loop_outer (loop) == outer);
12550
12551 if (!dominated_by_p (CDI_DOMINATORS, loop->header, region_entry))
12552 continue;
12553
12554 if (region_exit != NULL
12555 && dominated_by_p (CDI_DOMINATORS, loop->header, region_exit))
12556 continue;
12557
12558 nr_outer_loops++;
12559 single_outer = loop;
12560 }
12561 if (nr_outer_loops != 1)
12562 return;
12563
12564 for (struct loop *loop = single_outer->inner; loop != NULL; loop = loop->inner)
12565 if (loop->next)
12566 return;
12567
12568 /* Mark the loops in the region. */
12569 for (struct loop *loop = single_outer; loop != NULL; loop = loop->inner)
12570 loop->in_oacc_kernels_region = true;
12571}
12572
ca4c3545 12573/* Expand the GIMPLE_OMP_TARGET starting at REGION. */
773c5ba7 12574
12575static void
bc7bff74 12576expand_omp_target (struct omp_region *region)
773c5ba7 12577{
bc7bff74 12578 basic_block entry_bb, exit_bb, new_bb;
ca4c3545 12579 struct function *child_cfun;
12580 tree child_fn, block, t;
bc7bff74 12581 gimple_stmt_iterator gsi;
1a91d914 12582 gomp_target *entry_stmt;
42acab1c 12583 gimple *stmt;
bc7bff74 12584 edge e;
ca4c3545 12585 bool offloaded, data_region;
bc7bff74 12586
1a91d914 12587 entry_stmt = as_a <gomp_target *> (last_stmt (region->entry));
bc7bff74 12588 new_bb = region->entry;
ca4c3545 12589
12590 offloaded = is_gimple_omp_offloaded (entry_stmt);
12591 switch (gimple_omp_target_kind (entry_stmt))
12592 {
e561d5e1 12593 case GF_OMP_TARGET_KIND_REGION:
12594 case GF_OMP_TARGET_KIND_UPDATE:
43895be5 12595 case GF_OMP_TARGET_KIND_ENTER_DATA:
12596 case GF_OMP_TARGET_KIND_EXIT_DATA:
12597 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
12598 case GF_OMP_TARGET_KIND_OACC_KERNELS:
ca4c3545 12599 case GF_OMP_TARGET_KIND_OACC_UPDATE:
12600 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
2fc5e987 12601 case GF_OMP_TARGET_KIND_OACC_DECLARE:
ca4c3545 12602 data_region = false;
12603 break;
12604 case GF_OMP_TARGET_KIND_DATA:
12605 case GF_OMP_TARGET_KIND_OACC_DATA:
571b3486 12606 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
ca4c3545 12607 data_region = true;
12608 break;
12609 default:
12610 gcc_unreachable ();
12611 }
12612
12613 child_fn = NULL_TREE;
12614 child_cfun = NULL;
12615 if (offloaded)
bc7bff74 12616 {
12617 child_fn = gimple_omp_target_child_fn (entry_stmt);
12618 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
12619 }
12620
ca4c3545 12621 /* Supported by expand_omp_taskreg, but not here. */
12622 if (child_cfun != NULL)
12623 gcc_checking_assert (!child_cfun->cfg);
12624 gcc_checking_assert (!gimple_in_ssa_p (cfun));
12625
bc7bff74 12626 entry_bb = region->entry;
12627 exit_bb = region->exit;
12628
1a40f20b 12629 if (gimple_omp_target_kind (entry_stmt) == GF_OMP_TARGET_KIND_OACC_KERNELS)
12630 mark_loops_in_oacc_kernels_region (region->entry, region->exit);
12631
ca4c3545 12632 if (offloaded)
bc7bff74 12633 {
12634 unsigned srcidx, dstidx, num;
12635
ca4c3545 12636 /* If the offloading region needs data sent from the parent
bc7bff74 12637 function, then the very first statement (except possible
ca4c3545 12638 tree profile counter updates) of the offloading body
bc7bff74 12639 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
12640 &.OMP_DATA_O is passed as an argument to the child function,
12641 we need to replace it with the argument as seen by the child
12642 function.
12643
12644 In most cases, this will end up being the identity assignment
ca4c3545 12645 .OMP_DATA_I = .OMP_DATA_I. However, if the offloading body had
bc7bff74 12646 a function call that has been inlined, the original PARM_DECL
12647 .OMP_DATA_I may have been converted into a different local
12648 variable. In which case, we need to keep the assignment. */
ca4c3545 12649 tree data_arg = gimple_omp_target_data_arg (entry_stmt);
12650 if (data_arg)
bc7bff74 12651 {
12652 basic_block entry_succ_bb = single_succ (entry_bb);
12653 gimple_stmt_iterator gsi;
12654 tree arg;
42acab1c 12655 gimple *tgtcopy_stmt = NULL;
ca4c3545 12656 tree sender = TREE_VEC_ELT (data_arg, 0);
bc7bff74 12657
12658 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
12659 {
12660 gcc_assert (!gsi_end_p (gsi));
12661 stmt = gsi_stmt (gsi);
12662 if (gimple_code (stmt) != GIMPLE_ASSIGN)
12663 continue;
12664
12665 if (gimple_num_ops (stmt) == 2)
12666 {
12667 tree arg = gimple_assign_rhs1 (stmt);
12668
12669 /* We're ignoring the subcode because we're
12670 effectively doing a STRIP_NOPS. */
12671
12672 if (TREE_CODE (arg) == ADDR_EXPR
12673 && TREE_OPERAND (arg, 0) == sender)
12674 {
12675 tgtcopy_stmt = stmt;
12676 break;
12677 }
12678 }
12679 }
12680
12681 gcc_assert (tgtcopy_stmt != NULL);
12682 arg = DECL_ARGUMENTS (child_fn);
12683
12684 gcc_assert (gimple_assign_lhs (tgtcopy_stmt) == arg);
12685 gsi_remove (&gsi, true);
12686 }
12687
12688 /* Declare local variables needed in CHILD_CFUN. */
12689 block = DECL_INITIAL (child_fn);
12690 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
ca4c3545 12691 /* The gimplifier could record temporaries in the offloading block
bc7bff74 12692 rather than in containing function's local_decls chain,
12693 which would mean cgraph missed finalizing them. Do it now. */
12694 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
12695 if (TREE_CODE (t) == VAR_DECL
12696 && TREE_STATIC (t)
12697 && !DECL_EXTERNAL (t))
97221fd7 12698 varpool_node::finalize_decl (t);
bc7bff74 12699 DECL_SAVED_TREE (child_fn) = NULL;
12700 /* We'll create a CFG for child_fn, so no gimple body is needed. */
12701 gimple_set_body (child_fn, NULL);
12702 TREE_USED (block) = 1;
12703
12704 /* Reset DECL_CONTEXT on function arguments. */
12705 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
12706 DECL_CONTEXT (t) = child_fn;
12707
ca4c3545 12708 /* Split ENTRY_BB at GIMPLE_*,
bc7bff74 12709 so that it can be moved to the child function. */
12710 gsi = gsi_last_bb (entry_bb);
12711 stmt = gsi_stmt (gsi);
ca4c3545 12712 gcc_assert (stmt
12713 && gimple_code (stmt) == gimple_code (entry_stmt));
bc7bff74 12714 e = split_block (entry_bb, stmt);
923635e7 12715 gsi_remove (&gsi, true);
bc7bff74 12716 entry_bb = e->dest;
12717 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
12718
12719 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
12720 if (exit_bb)
12721 {
12722 gsi = gsi_last_bb (exit_bb);
12723 gcc_assert (!gsi_end_p (gsi)
12724 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
12725 stmt = gimple_build_return (NULL);
12726 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
12727 gsi_remove (&gsi, true);
12728 }
12729
ca4c3545 12730 /* Move the offloading region into CHILD_CFUN. */
bc7bff74 12731
12732 block = gimple_block (entry_stmt);
12733
12734 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
12735 if (exit_bb)
12736 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
12737 /* When the OMP expansion process cannot guarantee an up-to-date
12738 loop tree arrange for the child function to fixup loops. */
12739 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
12740 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
12741
12742 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
12743 num = vec_safe_length (child_cfun->local_decls);
12744 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
12745 {
12746 t = (*child_cfun->local_decls)[srcidx];
12747 if (DECL_CONTEXT (t) == cfun->decl)
12748 continue;
12749 if (srcidx != dstidx)
12750 (*child_cfun->local_decls)[dstidx] = t;
12751 dstidx++;
12752 }
12753 if (dstidx != num)
12754 vec_safe_truncate (child_cfun->local_decls, dstidx);
12755
12756 /* Inform the callgraph about the new function. */
613f2c38 12757 child_cfun->curr_properties = cfun->curr_properties;
12758 child_cfun->has_simduid_loops |= cfun->has_simduid_loops;
12759 child_cfun->has_force_vectorize_loops |= cfun->has_force_vectorize_loops;
6a77ed3d 12760 cgraph_node *node = cgraph_node::get_create (child_fn);
12761 node->parallelized_function = 1;
415d1b9a 12762 cgraph_node::add_new_function (child_fn, true);
bc7bff74 12763
dccabdd1 12764 /* Add the new function to the offload table. */
5f3001a9 12765 if (ENABLE_OFFLOADING)
12766 vec_safe_push (offload_funcs, child_fn);
dccabdd1 12767
9561765e 12768 bool need_asm = DECL_ASSEMBLER_NAME_SET_P (current_function_decl)
12769 && !DECL_ASSEMBLER_NAME_SET_P (child_fn);
12770
bc7bff74 12771 /* Fix the callgraph edges for child_cfun. Those for cfun will be
12772 fixed in a following pass. */
12773 push_cfun (child_cfun);
9561765e 12774 if (need_asm)
12775 assign_assembler_name_if_neeeded (child_fn);
35ee1c66 12776 cgraph_edge::rebuild_edges ();
bc7bff74 12777
12778 /* Some EH regions might become dead, see PR34608. If
12779 pass_cleanup_cfg isn't the first pass to happen with the
12780 new child, these dead EH edges might cause problems.
12781 Clean them up now. */
12782 if (flag_exceptions)
12783 {
12784 basic_block bb;
12785 bool changed = false;
12786
fc00614f 12787 FOR_EACH_BB_FN (bb, cfun)
bc7bff74 12788 changed |= gimple_purge_dead_eh_edges (bb);
12789 if (changed)
12790 cleanup_tree_cfg ();
12791 }
382ecba7 12792 if (flag_checking && !loops_state_satisfies_p (LOOPS_NEED_FIXUP))
86a932e0 12793 verify_loop_structure ();
bc7bff74 12794 pop_cfun ();
9561765e 12795
12796 if (dump_file && !gimple_in_ssa_p (cfun))
12797 {
12798 omp_any_child_fn_dumped = true;
12799 dump_function_header (dump_file, child_fn, dump_flags);
12800 dump_function_to_file (child_fn, dump_file, dump_flags);
12801 }
bc7bff74 12802 }
12803
ca4c3545 12804 /* Emit a library call to launch the offloading region, or do data
bc7bff74 12805 transfers. */
43895be5 12806 tree t1, t2, t3, t4, device, cond, depend, c, clauses;
bc7bff74 12807 enum built_in_function start_ix;
12808 location_t clause_loc;
43895be5 12809 unsigned int flags_i = 0;
bc7bff74 12810
ca4c3545 12811 switch (gimple_omp_target_kind (entry_stmt))
12812 {
12813 case GF_OMP_TARGET_KIND_REGION:
12814 start_ix = BUILT_IN_GOMP_TARGET;
12815 break;
12816 case GF_OMP_TARGET_KIND_DATA:
12817 start_ix = BUILT_IN_GOMP_TARGET_DATA;
12818 break;
12819 case GF_OMP_TARGET_KIND_UPDATE:
12820 start_ix = BUILT_IN_GOMP_TARGET_UPDATE;
12821 break;
43895be5 12822 case GF_OMP_TARGET_KIND_ENTER_DATA:
12823 start_ix = BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA;
12824 break;
12825 case GF_OMP_TARGET_KIND_EXIT_DATA:
12826 start_ix = BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA;
12827 flags_i |= GOMP_TARGET_FLAG_EXIT_DATA;
12828 break;
ca4c3545 12829 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
12830 case GF_OMP_TARGET_KIND_OACC_KERNELS:
12831 start_ix = BUILT_IN_GOACC_PARALLEL;
12832 break;
12833 case GF_OMP_TARGET_KIND_OACC_DATA:
12834 start_ix = BUILT_IN_GOACC_DATA_START;
12835 break;
12836 case GF_OMP_TARGET_KIND_OACC_UPDATE:
12837 start_ix = BUILT_IN_GOACC_UPDATE;
12838 break;
12839 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
12840 start_ix = BUILT_IN_GOACC_ENTER_EXIT_DATA;
12841 break;
2fc5e987 12842 case GF_OMP_TARGET_KIND_OACC_DECLARE:
12843 start_ix = BUILT_IN_GOACC_DECLARE;
12844 break;
571b3486 12845 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
12846 start_ix = BUILT_IN_GOACC_HOST_DATA;
12847 break;
ca4c3545 12848 default:
12849 gcc_unreachable ();
12850 }
bc7bff74 12851
ca4c3545 12852 clauses = gimple_omp_target_clauses (entry_stmt);
bc7bff74 12853
ca4c3545 12854 /* By default, the value of DEVICE is GOMP_DEVICE_ICV (let runtime
12855 library choose) and there is no conditional. */
bc7bff74 12856 cond = NULL_TREE;
ca4c3545 12857 device = build_int_cst (integer_type_node, GOMP_DEVICE_ICV);
bc7bff74 12858
12859 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
12860 if (c)
12861 cond = OMP_CLAUSE_IF_EXPR (c);
12862
12863 c = find_omp_clause (clauses, OMP_CLAUSE_DEVICE);
12864 if (c)
12865 {
ca4c3545 12866 /* Even if we pass it to all library function calls, it is currently only
12867 defined/used for the OpenMP target ones. */
12868 gcc_checking_assert (start_ix == BUILT_IN_GOMP_TARGET
12869 || start_ix == BUILT_IN_GOMP_TARGET_DATA
43895be5 12870 || start_ix == BUILT_IN_GOMP_TARGET_UPDATE
12871 || start_ix == BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA);
ca4c3545 12872
bc7bff74 12873 device = OMP_CLAUSE_DEVICE_ID (c);
12874 clause_loc = OMP_CLAUSE_LOCATION (c);
12875 }
12876 else
12877 clause_loc = gimple_location (entry_stmt);
12878
43895be5 12879 c = find_omp_clause (clauses, OMP_CLAUSE_NOWAIT);
12880 if (c)
12881 flags_i |= GOMP_TARGET_FLAG_NOWAIT;
12882
bc7bff74 12883 /* Ensure 'device' is of the correct type. */
12884 device = fold_convert_loc (clause_loc, integer_type_node, device);
12885
12886 /* If we found the clause 'if (cond)', build
ca4c3545 12887 (cond ? device : GOMP_DEVICE_HOST_FALLBACK). */
bc7bff74 12888 if (cond)
12889 {
12890 cond = gimple_boolify (cond);
12891
12892 basic_block cond_bb, then_bb, else_bb;
12893 edge e;
12894 tree tmp_var;
12895
f9e245b2 12896 tmp_var = create_tmp_var (TREE_TYPE (device));
ca4c3545 12897 if (offloaded)
4302d619 12898 e = split_block_after_labels (new_bb);
ca4c3545 12899 else
bc7bff74 12900 {
12901 gsi = gsi_last_bb (new_bb);
12902 gsi_prev (&gsi);
12903 e = split_block (new_bb, gsi_stmt (gsi));
12904 }
bc7bff74 12905 cond_bb = e->src;
12906 new_bb = e->dest;
12907 remove_edge (e);
12908
12909 then_bb = create_empty_bb (cond_bb);
12910 else_bb = create_empty_bb (then_bb);
12911 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
12912 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
12913
12914 stmt = gimple_build_cond_empty (cond);
12915 gsi = gsi_last_bb (cond_bb);
12916 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
12917
12918 gsi = gsi_start_bb (then_bb);
12919 stmt = gimple_build_assign (tmp_var, device);
12920 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
12921
12922 gsi = gsi_start_bb (else_bb);
12923 stmt = gimple_build_assign (tmp_var,
ca4c3545 12924 build_int_cst (integer_type_node,
12925 GOMP_DEVICE_HOST_FALLBACK));
bc7bff74 12926 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
12927
12928 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
12929 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
b3083327 12930 add_bb_to_loop (then_bb, cond_bb->loop_father);
12931 add_bb_to_loop (else_bb, cond_bb->loop_father);
bc7bff74 12932 make_edge (then_bb, new_bb, EDGE_FALLTHRU);
12933 make_edge (else_bb, new_bb, EDGE_FALLTHRU);
12934
12935 device = tmp_var;
12936 }
12937
12938 gsi = gsi_last_bb (new_bb);
12939 t = gimple_omp_target_data_arg (entry_stmt);
12940 if (t == NULL)
12941 {
12942 t1 = size_zero_node;
12943 t2 = build_zero_cst (ptr_type_node);
12944 t3 = t2;
12945 t4 = t2;
12946 }
12947 else
12948 {
12949 t1 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t, 1))));
12950 t1 = size_binop (PLUS_EXPR, t1, size_int (1));
12951 t2 = build_fold_addr_expr (TREE_VEC_ELT (t, 0));
12952 t3 = build_fold_addr_expr (TREE_VEC_ELT (t, 1));
12953 t4 = build_fold_addr_expr (TREE_VEC_ELT (t, 2));
12954 }
12955
42acab1c 12956 gimple *g;
e561d5e1 12957 bool tagging = false;
ca4c3545 12958 /* The maximum number used by any start_ix, without varargs. */
02c05c9b 12959 auto_vec<tree, 11> args;
12960 args.quick_push (device);
ca4c3545 12961 if (offloaded)
02c05c9b 12962 args.quick_push (build_fold_addr_expr (child_fn));
02c05c9b 12963 args.quick_push (t1);
12964 args.quick_push (t2);
12965 args.quick_push (t3);
12966 args.quick_push (t4);
ca4c3545 12967 switch (start_ix)
12968 {
12969 case BUILT_IN_GOACC_DATA_START:
2fc5e987 12970 case BUILT_IN_GOACC_DECLARE:
ca4c3545 12971 case BUILT_IN_GOMP_TARGET_DATA:
571b3486 12972 case BUILT_IN_GOACC_HOST_DATA:
43895be5 12973 break;
12974 case BUILT_IN_GOMP_TARGET:
ca4c3545 12975 case BUILT_IN_GOMP_TARGET_UPDATE:
43895be5 12976 case BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA:
12977 args.quick_push (build_int_cst (unsigned_type_node, flags_i));
12978 c = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
12979 if (c)
12980 depend = OMP_CLAUSE_DECL (c);
12981 else
12982 depend = build_int_cst (ptr_type_node, 0);
12983 args.quick_push (depend);
9561765e 12984 if (start_ix == BUILT_IN_GOMP_TARGET)
12985 {
12986 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_TEAMS);
12987 if (c)
12988 {
12989 t = fold_convert (integer_type_node,
12990 OMP_CLAUSE_NUM_TEAMS_EXPR (c));
12991 t = force_gimple_operand_gsi (&gsi, t, true, NULL,
12992 true, GSI_SAME_STMT);
12993 }
12994 else
12995 t = integer_minus_one_node;
12996 args.quick_push (t);
12997 c = find_omp_clause (clauses, OMP_CLAUSE_THREAD_LIMIT);
12998 if (c)
12999 {
13000 t = fold_convert (integer_type_node,
13001 OMP_CLAUSE_THREAD_LIMIT_EXPR (c));
13002 t = force_gimple_operand_gsi (&gsi, t, true, NULL,
13003 true, GSI_SAME_STMT);
13004 }
13005 else
13006 t = integer_minus_one_node;
13007 args.quick_push (t);
13008 }
ca4c3545 13009 break;
13010 case BUILT_IN_GOACC_PARALLEL:
13011 {
e561d5e1 13012 set_oacc_fn_attrib (child_fn, clauses, &args);
13013 tagging = true;
ca4c3545 13014 }
13015 /* FALLTHRU */
13016 case BUILT_IN_GOACC_ENTER_EXIT_DATA:
13017 case BUILT_IN_GOACC_UPDATE:
13018 {
e561d5e1 13019 tree t_async = NULL_TREE;
13020
13021 /* If present, use the value specified by the respective
ca4c3545 13022 clause, making sure that is of the correct type. */
13023 c = find_omp_clause (clauses, OMP_CLAUSE_ASYNC);
13024 if (c)
13025 t_async = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
13026 integer_type_node,
13027 OMP_CLAUSE_ASYNC_EXPR (c));
e561d5e1 13028 else if (!tagging)
13029 /* Default values for t_async. */
13030 t_async = fold_convert_loc (gimple_location (entry_stmt),
13031 integer_type_node,
13032 build_int_cst (integer_type_node,
13033 GOMP_ASYNC_SYNC));
13034 if (tagging && t_async)
ca4c3545 13035 {
e561d5e1 13036 unsigned HOST_WIDE_INT i_async;
ca4c3545 13037
e561d5e1 13038 if (TREE_CODE (t_async) == INTEGER_CST)
ca4c3545 13039 {
e561d5e1 13040 /* See if we can pack the async arg in to the tag's
13041 operand. */
13042 i_async = TREE_INT_CST_LOW (t_async);
13043
13044 if (i_async < GOMP_LAUNCH_OP_MAX)
13045 t_async = NULL_TREE;
ca4c3545 13046 }
e561d5e1 13047 if (t_async)
13048 i_async = GOMP_LAUNCH_OP_MAX;
13049 args.safe_push (oacc_launch_pack
13050 (GOMP_LAUNCH_ASYNC, NULL_TREE, i_async));
13051 }
13052 if (t_async)
13053 args.safe_push (t_async);
ca4c3545 13054
e561d5e1 13055 /* Save the argument index, and ... */
13056 unsigned t_wait_idx = args.length ();
13057 unsigned num_waits = 0;
13058 c = find_omp_clause (clauses, OMP_CLAUSE_WAIT);
13059 if (!tagging || c)
13060 /* ... push a placeholder. */
13061 args.safe_push (integer_zero_node);
13062
13063 for (; c; c = OMP_CLAUSE_CHAIN (c))
13064 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_WAIT)
13065 {
13066 args.safe_push (fold_convert_loc (OMP_CLAUSE_LOCATION (c),
13067 integer_type_node,
13068 OMP_CLAUSE_WAIT_EXPR (c)));
13069 num_waits++;
13070 }
13071
13072 if (!tagging || num_waits)
13073 {
13074 tree len;
13075
13076 /* Now that we know the number, update the placeholder. */
13077 if (tagging)
13078 len = oacc_launch_pack (GOMP_LAUNCH_WAIT, NULL_TREE, num_waits);
13079 else
13080 len = build_int_cst (integer_type_node, num_waits);
13081 len = fold_convert_loc (gimple_location (entry_stmt),
13082 unsigned_type_node, len);
13083 args[t_wait_idx] = len;
ca4c3545 13084 }
13085 }
13086 break;
13087 default:
13088 gcc_unreachable ();
bc7bff74 13089 }
e561d5e1 13090 if (tagging)
13091 /* Push terminal marker - zero. */
13092 args.safe_push (oacc_launch_pack (0, NULL_TREE, 0));
ca4c3545 13093
02c05c9b 13094 g = gimple_build_call_vec (builtin_decl_explicit (start_ix), args);
bc7bff74 13095 gimple_set_location (g, gimple_location (entry_stmt));
13096 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
ca4c3545 13097 if (!offloaded)
bc7bff74 13098 {
13099 g = gsi_stmt (gsi);
13100 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_TARGET);
13101 gsi_remove (&gsi, true);
13102 }
43895be5 13103 if (data_region && region->exit)
bc7bff74 13104 {
13105 gsi = gsi_last_bb (region->exit);
13106 g = gsi_stmt (gsi);
13107 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_RETURN);
13108 gsi_remove (&gsi, true);
13109 }
13110}
13111
13112
13113/* Expand the parallel region tree rooted at REGION. Expansion
13114 proceeds in depth-first order. Innermost regions are expanded
13115 first. This way, parallel regions that require a new function to
75a70cf9 13116 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
773c5ba7 13117 internal dependencies in their body. */
13118
13119static void
13120expand_omp (struct omp_region *region)
13121{
9561765e 13122 omp_any_child_fn_dumped = false;
773c5ba7 13123 while (region)
13124 {
1d22f541 13125 location_t saved_location;
42acab1c 13126 gimple *inner_stmt = NULL;
1d22f541 13127
d1d5b012 13128 /* First, determine whether this is a combined parallel+workshare
13129 region. */
75a70cf9 13130 if (region->type == GIMPLE_OMP_PARALLEL)
d1d5b012 13131 determine_parallel_type (region);
13132
bc7bff74 13133 if (region->type == GIMPLE_OMP_FOR
13134 && gimple_omp_for_combined_p (last_stmt (region->entry)))
13135 inner_stmt = last_stmt (region->inner->entry);
13136
773c5ba7 13137 if (region->inner)
13138 expand_omp (region->inner);
13139
1d22f541 13140 saved_location = input_location;
75a70cf9 13141 if (gimple_has_location (last_stmt (region->entry)))
13142 input_location = gimple_location (last_stmt (region->entry));
1d22f541 13143
61e47ac8 13144 switch (region->type)
773c5ba7 13145 {
75a70cf9 13146 case GIMPLE_OMP_PARALLEL:
13147 case GIMPLE_OMP_TASK:
fd6481cf 13148 expand_omp_taskreg (region);
13149 break;
13150
75a70cf9 13151 case GIMPLE_OMP_FOR:
bc7bff74 13152 expand_omp_for (region, inner_stmt);
61e47ac8 13153 break;
773c5ba7 13154
75a70cf9 13155 case GIMPLE_OMP_SECTIONS:
61e47ac8 13156 expand_omp_sections (region);
13157 break;
773c5ba7 13158
75a70cf9 13159 case GIMPLE_OMP_SECTION:
61e47ac8 13160 /* Individual omp sections are handled together with their
75a70cf9 13161 parent GIMPLE_OMP_SECTIONS region. */
61e47ac8 13162 break;
773c5ba7 13163
75a70cf9 13164 case GIMPLE_OMP_SINGLE:
61e47ac8 13165 expand_omp_single (region);
13166 break;
773c5ba7 13167
43895be5 13168 case GIMPLE_OMP_ORDERED:
13169 {
13170 gomp_ordered *ord_stmt
13171 = as_a <gomp_ordered *> (last_stmt (region->entry));
13172 if (find_omp_clause (gimple_omp_ordered_clauses (ord_stmt),
13173 OMP_CLAUSE_DEPEND))
13174 {
13175 /* We'll expand these when expanding corresponding
13176 worksharing region with ordered(n) clause. */
13177 gcc_assert (region->outer
13178 && region->outer->type == GIMPLE_OMP_FOR);
13179 region->ord_stmt = ord_stmt;
13180 break;
13181 }
13182 }
13183 /* FALLTHRU */
75a70cf9 13184 case GIMPLE_OMP_MASTER:
bc7bff74 13185 case GIMPLE_OMP_TASKGROUP:
75a70cf9 13186 case GIMPLE_OMP_CRITICAL:
bc7bff74 13187 case GIMPLE_OMP_TEAMS:
61e47ac8 13188 expand_omp_synch (region);
13189 break;
773c5ba7 13190
75a70cf9 13191 case GIMPLE_OMP_ATOMIC_LOAD:
cb7f680b 13192 expand_omp_atomic (region);
13193 break;
13194
bc7bff74 13195 case GIMPLE_OMP_TARGET:
13196 expand_omp_target (region);
13197 break;
13198
61e47ac8 13199 default:
13200 gcc_unreachable ();
13201 }
cc5982dc 13202
1d22f541 13203 input_location = saved_location;
773c5ba7 13204 region = region->next;
13205 }
9561765e 13206 if (omp_any_child_fn_dumped)
13207 {
13208 if (dump_file)
13209 dump_function_header (dump_file, current_function_decl, dump_flags);
13210 omp_any_child_fn_dumped = false;
13211 }
773c5ba7 13212}
13213
13214
13215/* Helper for build_omp_regions. Scan the dominator tree starting at
28c92cbb 13216 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
13217 true, the function ends once a single tree is built (otherwise, whole
13218 forest of OMP constructs may be built). */
773c5ba7 13219
13220static void
28c92cbb 13221build_omp_regions_1 (basic_block bb, struct omp_region *parent,
13222 bool single_tree)
773c5ba7 13223{
75a70cf9 13224 gimple_stmt_iterator gsi;
42acab1c 13225 gimple *stmt;
773c5ba7 13226 basic_block son;
13227
75a70cf9 13228 gsi = gsi_last_bb (bb);
13229 if (!gsi_end_p (gsi) && is_gimple_omp (gsi_stmt (gsi)))
773c5ba7 13230 {
13231 struct omp_region *region;
75a70cf9 13232 enum gimple_code code;
773c5ba7 13233
75a70cf9 13234 stmt = gsi_stmt (gsi);
13235 code = gimple_code (stmt);
13236 if (code == GIMPLE_OMP_RETURN)
773c5ba7 13237 {
13238 /* STMT is the return point out of region PARENT. Mark it
13239 as the exit point and make PARENT the immediately
13240 enclosing region. */
13241 gcc_assert (parent);
13242 region = parent;
61e47ac8 13243 region->exit = bb;
773c5ba7 13244 parent = parent->outer;
773c5ba7 13245 }
75a70cf9 13246 else if (code == GIMPLE_OMP_ATOMIC_STORE)
cb7f680b 13247 {
75a70cf9 13248 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
13249 GIMPLE_OMP_RETURN, but matches with
13250 GIMPLE_OMP_ATOMIC_LOAD. */
cb7f680b 13251 gcc_assert (parent);
75a70cf9 13252 gcc_assert (parent->type == GIMPLE_OMP_ATOMIC_LOAD);
cb7f680b 13253 region = parent;
13254 region->exit = bb;
13255 parent = parent->outer;
13256 }
75a70cf9 13257 else if (code == GIMPLE_OMP_CONTINUE)
61e47ac8 13258 {
13259 gcc_assert (parent);
13260 parent->cont = bb;
13261 }
75a70cf9 13262 else if (code == GIMPLE_OMP_SECTIONS_SWITCH)
ac6e3339 13263 {
75a70cf9 13264 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
13265 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
ac6e3339 13266 }
773c5ba7 13267 else
13268 {
61e47ac8 13269 region = new_omp_region (bb, code, parent);
ca4c3545 13270 /* Otherwise... */
13271 if (code == GIMPLE_OMP_TARGET)
13272 {
13273 switch (gimple_omp_target_kind (stmt))
13274 {
13275 case GF_OMP_TARGET_KIND_REGION:
13276 case GF_OMP_TARGET_KIND_DATA:
13277 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
13278 case GF_OMP_TARGET_KIND_OACC_KERNELS:
13279 case GF_OMP_TARGET_KIND_OACC_DATA:
571b3486 13280 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
ca4c3545 13281 break;
13282 case GF_OMP_TARGET_KIND_UPDATE:
43895be5 13283 case GF_OMP_TARGET_KIND_ENTER_DATA:
13284 case GF_OMP_TARGET_KIND_EXIT_DATA:
ca4c3545 13285 case GF_OMP_TARGET_KIND_OACC_UPDATE:
13286 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
2fc5e987 13287 case GF_OMP_TARGET_KIND_OACC_DECLARE:
ca4c3545 13288 /* ..., other than for those stand-alone directives... */
13289 region = NULL;
13290 break;
13291 default:
13292 gcc_unreachable ();
13293 }
13294 }
43895be5 13295 else if (code == GIMPLE_OMP_ORDERED
13296 && find_omp_clause (gimple_omp_ordered_clauses
13297 (as_a <gomp_ordered *> (stmt)),
13298 OMP_CLAUSE_DEPEND))
13299 /* #pragma omp ordered depend is also just a stand-alone
13300 directive. */
13301 region = NULL;
ca4c3545 13302 /* ..., this directive becomes the parent for a new region. */
13303 if (region)
13304 parent = region;
773c5ba7 13305 }
773c5ba7 13306 }
13307
28c92cbb 13308 if (single_tree && !parent)
13309 return;
13310
773c5ba7 13311 for (son = first_dom_son (CDI_DOMINATORS, bb);
13312 son;
13313 son = next_dom_son (CDI_DOMINATORS, son))
28c92cbb 13314 build_omp_regions_1 (son, parent, single_tree);
13315}
13316
13317/* Builds the tree of OMP regions rooted at ROOT, storing it to
13318 root_omp_region. */
13319
13320static void
13321build_omp_regions_root (basic_block root)
13322{
13323 gcc_assert (root_omp_region == NULL);
13324 build_omp_regions_1 (root, NULL, true);
13325 gcc_assert (root_omp_region != NULL);
773c5ba7 13326}
13327
28c92cbb 13328/* Expands omp construct (and its subconstructs) starting in HEAD. */
13329
13330void
13331omp_expand_local (basic_block head)
13332{
13333 build_omp_regions_root (head);
13334 if (dump_file && (dump_flags & TDF_DETAILS))
13335 {
13336 fprintf (dump_file, "\nOMP region tree\n\n");
13337 dump_omp_region (dump_file, root_omp_region, 0);
13338 fprintf (dump_file, "\n");
13339 }
13340
13341 remove_exit_barriers (root_omp_region);
13342 expand_omp (root_omp_region);
13343
13344 free_omp_regions ();
13345}
773c5ba7 13346
13347/* Scan the CFG and build a tree of OMP regions. Return the root of
13348 the OMP region tree. */
13349
13350static void
13351build_omp_regions (void)
13352{
61e47ac8 13353 gcc_assert (root_omp_region == NULL);
773c5ba7 13354 calculate_dominance_info (CDI_DOMINATORS);
34154e27 13355 build_omp_regions_1 (ENTRY_BLOCK_PTR_FOR_FN (cfun), NULL, false);
773c5ba7 13356}
13357
773c5ba7 13358/* Main entry point for expanding OMP-GIMPLE into runtime calls. */
13359
2a1990e9 13360static unsigned int
773c5ba7 13361execute_expand_omp (void)
13362{
13363 build_omp_regions ();
13364
61e47ac8 13365 if (!root_omp_region)
13366 return 0;
773c5ba7 13367
61e47ac8 13368 if (dump_file)
13369 {
13370 fprintf (dump_file, "\nOMP region tree\n\n");
13371 dump_omp_region (dump_file, root_omp_region, 0);
13372 fprintf (dump_file, "\n");
773c5ba7 13373 }
61e47ac8 13374
13375 remove_exit_barriers (root_omp_region);
13376
13377 expand_omp (root_omp_region);
13378
382ecba7 13379 if (flag_checking && !loops_state_satisfies_p (LOOPS_NEED_FIXUP))
86a932e0 13380 verify_loop_structure ();
61e47ac8 13381 cleanup_tree_cfg ();
13382
13383 free_omp_regions ();
13384
2a1990e9 13385 return 0;
773c5ba7 13386}
13387
79acaae1 13388/* OMP expansion -- the default pass, run before creation of SSA form. */
13389
7620bc82 13390namespace {
13391
13392const pass_data pass_data_expand_omp =
cbe8bda8 13393{
13394 GIMPLE_PASS, /* type */
13395 "ompexp", /* name */
13396 OPTGROUP_NONE, /* optinfo_flags */
cbe8bda8 13397 TV_NONE, /* tv_id */
13398 PROP_gimple_any, /* properties_required */
8917c50b 13399 PROP_gimple_eomp, /* properties_provided */
cbe8bda8 13400 0, /* properties_destroyed */
13401 0, /* todo_flags_start */
13402 0, /* todo_flags_finish */
773c5ba7 13403};
cbe8bda8 13404
7620bc82 13405class pass_expand_omp : public gimple_opt_pass
cbe8bda8 13406{
13407public:
9af5ce0c 13408 pass_expand_omp (gcc::context *ctxt)
13409 : gimple_opt_pass (pass_data_expand_omp, ctxt)
cbe8bda8 13410 {}
13411
13412 /* opt_pass methods: */
8917c50b 13413 virtual unsigned int execute (function *)
31315c24 13414 {
ca4c3545 13415 bool gate = ((flag_cilkplus != 0 || flag_openacc != 0 || flag_openmp != 0
13416 || flag_openmp_simd != 0)
13417 && !seen_error ());
31315c24 13418
8917c50b 13419 /* This pass always runs, to provide PROP_gimple_eomp.
ca4c3545 13420 But often, there is nothing to do. */
8917c50b 13421 if (!gate)
13422 return 0;
13423
13424 return execute_expand_omp ();
13425 }
cbe8bda8 13426
13427}; // class pass_expand_omp
13428
7620bc82 13429} // anon namespace
13430
cbe8bda8 13431gimple_opt_pass *
13432make_pass_expand_omp (gcc::context *ctxt)
13433{
13434 return new pass_expand_omp (ctxt);
13435}
8917c50b 13436
7620bc82 13437namespace {
13438
13439const pass_data pass_data_expand_omp_ssa =
8917c50b 13440{
13441 GIMPLE_PASS, /* type */
13442 "ompexpssa", /* name */
13443 OPTGROUP_NONE, /* optinfo_flags */
13444 TV_NONE, /* tv_id */
13445 PROP_cfg | PROP_ssa, /* properties_required */
13446 PROP_gimple_eomp, /* properties_provided */
13447 0, /* properties_destroyed */
13448 0, /* todo_flags_start */
13449 TODO_cleanup_cfg | TODO_rebuild_alias, /* todo_flags_finish */
13450};
13451
7620bc82 13452class pass_expand_omp_ssa : public gimple_opt_pass
8917c50b 13453{
13454public:
13455 pass_expand_omp_ssa (gcc::context *ctxt)
13456 : gimple_opt_pass (pass_data_expand_omp_ssa, ctxt)
13457 {}
13458
13459 /* opt_pass methods: */
13460 virtual bool gate (function *fun)
13461 {
13462 return !(fun->curr_properties & PROP_gimple_eomp);
13463 }
13464 virtual unsigned int execute (function *) { return execute_expand_omp (); }
e1e1688c 13465 opt_pass * clone () { return new pass_expand_omp_ssa (m_ctxt); }
8917c50b 13466
13467}; // class pass_expand_omp_ssa
13468
7620bc82 13469} // anon namespace
13470
8917c50b 13471gimple_opt_pass *
13472make_pass_expand_omp_ssa (gcc::context *ctxt)
13473{
13474 return new pass_expand_omp_ssa (ctxt);
13475}
773c5ba7 13476\f
ca4c3545 13477/* Routines to lower OMP directives into OMP-GIMPLE. */
13478
bc7bff74 13479/* If ctx is a worksharing context inside of a cancellable parallel
13480 region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
13481 and conditional branch to parallel's cancel_label to handle
13482 cancellation in the implicit barrier. */
13483
13484static void
13485maybe_add_implicit_barrier_cancel (omp_context *ctx, gimple_seq *body)
13486{
42acab1c 13487 gimple *omp_return = gimple_seq_last_stmt (*body);
bc7bff74 13488 gcc_assert (gimple_code (omp_return) == GIMPLE_OMP_RETURN);
13489 if (gimple_omp_return_nowait_p (omp_return))
13490 return;
13491 if (ctx->outer
13492 && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_PARALLEL
13493 && ctx->outer->cancellable)
13494 {
15b28553 13495 tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL);
13496 tree c_bool_type = TREE_TYPE (TREE_TYPE (fndecl));
f9e245b2 13497 tree lhs = create_tmp_var (c_bool_type);
bc7bff74 13498 gimple_omp_return_set_lhs (omp_return, lhs);
13499 tree fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
42acab1c 13500 gimple *g = gimple_build_cond (NE_EXPR, lhs,
15b28553 13501 fold_convert (c_bool_type,
13502 boolean_false_node),
bc7bff74 13503 ctx->outer->cancel_label, fallthru_label);
13504 gimple_seq_add_stmt (body, g);
13505 gimple_seq_add_stmt (body, gimple_build_label (fallthru_label));
13506 }
13507}
13508
75a70cf9 13509/* Lower the OpenMP sections directive in the current statement in GSI_P.
13510 CTX is the enclosing OMP context for the current statement. */
773c5ba7 13511
13512static void
75a70cf9 13513lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
773c5ba7 13514{
75a70cf9 13515 tree block, control;
13516 gimple_stmt_iterator tgsi;
1a91d914 13517 gomp_sections *stmt;
42acab1c 13518 gimple *t;
1a91d914 13519 gbind *new_stmt, *bind;
e3a19533 13520 gimple_seq ilist, dlist, olist, new_body;
773c5ba7 13521
1a91d914 13522 stmt = as_a <gomp_sections *> (gsi_stmt (*gsi_p));
773c5ba7 13523
8a4a28a8 13524 push_gimplify_context ();
773c5ba7 13525
13526 dlist = NULL;
13527 ilist = NULL;
75a70cf9 13528 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
bc7bff74 13529 &ilist, &dlist, ctx, NULL);
773c5ba7 13530
e3a19533 13531 new_body = gimple_omp_body (stmt);
13532 gimple_omp_set_body (stmt, NULL);
13533 tgsi = gsi_start (new_body);
13534 for (; !gsi_end_p (tgsi); gsi_next (&tgsi))
773c5ba7 13535 {
13536 omp_context *sctx;
42acab1c 13537 gimple *sec_start;
773c5ba7 13538
75a70cf9 13539 sec_start = gsi_stmt (tgsi);
773c5ba7 13540 sctx = maybe_lookup_ctx (sec_start);
13541 gcc_assert (sctx);
13542
e3a19533 13543 lower_omp (gimple_omp_body_ptr (sec_start), sctx);
13544 gsi_insert_seq_after (&tgsi, gimple_omp_body (sec_start),
13545 GSI_CONTINUE_LINKING);
75a70cf9 13546 gimple_omp_set_body (sec_start, NULL);
773c5ba7 13547
e3a19533 13548 if (gsi_one_before_end_p (tgsi))
773c5ba7 13549 {
75a70cf9 13550 gimple_seq l = NULL;
13551 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
773c5ba7 13552 &l, ctx);
e3a19533 13553 gsi_insert_seq_after (&tgsi, l, GSI_CONTINUE_LINKING);
75a70cf9 13554 gimple_omp_section_set_last (sec_start);
773c5ba7 13555 }
48e1416a 13556
e3a19533 13557 gsi_insert_after (&tgsi, gimple_build_omp_return (false),
13558 GSI_CONTINUE_LINKING);
773c5ba7 13559 }
1e8e9920 13560
13561 block = make_node (BLOCK);
e3a19533 13562 bind = gimple_build_bind (NULL, new_body, block);
1e8e9920 13563
75a70cf9 13564 olist = NULL;
13565 lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist, ctx);
773c5ba7 13566
1d22f541 13567 block = make_node (BLOCK);
75a70cf9 13568 new_stmt = gimple_build_bind (NULL, NULL, block);
e3a19533 13569 gsi_replace (gsi_p, new_stmt, true);
773c5ba7 13570
1d22f541 13571 pop_gimplify_context (new_stmt);
75a70cf9 13572 gimple_bind_append_vars (new_stmt, ctx->block_vars);
13573 BLOCK_VARS (block) = gimple_bind_vars (bind);
1d22f541 13574 if (BLOCK_VARS (block))
13575 TREE_USED (block) = 1;
13576
75a70cf9 13577 new_body = NULL;
13578 gimple_seq_add_seq (&new_body, ilist);
13579 gimple_seq_add_stmt (&new_body, stmt);
13580 gimple_seq_add_stmt (&new_body, gimple_build_omp_sections_switch ());
13581 gimple_seq_add_stmt (&new_body, bind);
61e47ac8 13582
ac6e3339 13583 control = create_tmp_var (unsigned_type_node, ".section");
75a70cf9 13584 t = gimple_build_omp_continue (control, control);
13585 gimple_omp_sections_set_control (stmt, control);
13586 gimple_seq_add_stmt (&new_body, t);
61e47ac8 13587
75a70cf9 13588 gimple_seq_add_seq (&new_body, olist);
bc7bff74 13589 if (ctx->cancellable)
13590 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
75a70cf9 13591 gimple_seq_add_seq (&new_body, dlist);
773c5ba7 13592
75a70cf9 13593 new_body = maybe_catch_exception (new_body);
aade31a0 13594
75a70cf9 13595 t = gimple_build_omp_return
13596 (!!find_omp_clause (gimple_omp_sections_clauses (stmt),
13597 OMP_CLAUSE_NOWAIT));
13598 gimple_seq_add_stmt (&new_body, t);
bc7bff74 13599 maybe_add_implicit_barrier_cancel (ctx, &new_body);
61e47ac8 13600
75a70cf9 13601 gimple_bind_set_body (new_stmt, new_body);
1e8e9920 13602}
13603
13604
773c5ba7 13605/* A subroutine of lower_omp_single. Expand the simple form of
75a70cf9 13606 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
1e8e9920 13607
13608 if (GOMP_single_start ())
13609 BODY;
13610 [ GOMP_barrier (); ] -> unless 'nowait' is present.
773c5ba7 13611
13612 FIXME. It may be better to delay expanding the logic of this until
13613 pass_expand_omp. The expanded logic may make the job more difficult
13614 to a synchronization analysis pass. */
1e8e9920 13615
13616static void
1a91d914 13617lower_omp_single_simple (gomp_single *single_stmt, gimple_seq *pre_p)
1e8e9920 13618{
e60a6f7b 13619 location_t loc = gimple_location (single_stmt);
13620 tree tlabel = create_artificial_label (loc);
13621 tree flabel = create_artificial_label (loc);
42acab1c 13622 gimple *call, *cond;
75a70cf9 13623 tree lhs, decl;
13624
b9a16870 13625 decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START);
f9e245b2 13626 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)));
75a70cf9 13627 call = gimple_build_call (decl, 0);
13628 gimple_call_set_lhs (call, lhs);
13629 gimple_seq_add_stmt (pre_p, call);
13630
13631 cond = gimple_build_cond (EQ_EXPR, lhs,
389dd41b 13632 fold_convert_loc (loc, TREE_TYPE (lhs),
13633 boolean_true_node),
75a70cf9 13634 tlabel, flabel);
13635 gimple_seq_add_stmt (pre_p, cond);
13636 gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
13637 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
13638 gimple_seq_add_stmt (pre_p, gimple_build_label (flabel));
1e8e9920 13639}
13640
773c5ba7 13641
13642/* A subroutine of lower_omp_single. Expand the simple form of
75a70cf9 13643 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
1e8e9920 13644
13645 #pragma omp single copyprivate (a, b, c)
13646
13647 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
13648
13649 {
13650 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
13651 {
13652 BODY;
13653 copyout.a = a;
13654 copyout.b = b;
13655 copyout.c = c;
13656 GOMP_single_copy_end (&copyout);
13657 }
13658 else
13659 {
13660 a = copyout_p->a;
13661 b = copyout_p->b;
13662 c = copyout_p->c;
13663 }
13664 GOMP_barrier ();
13665 }
773c5ba7 13666
13667 FIXME. It may be better to delay expanding the logic of this until
13668 pass_expand_omp. The expanded logic may make the job more difficult
13669 to a synchronization analysis pass. */
1e8e9920 13670
13671static void
1a91d914 13672lower_omp_single_copy (gomp_single *single_stmt, gimple_seq *pre_p,
13673 omp_context *ctx)
1e8e9920 13674{
b9a16870 13675 tree ptr_type, t, l0, l1, l2, bfn_decl;
75a70cf9 13676 gimple_seq copyin_seq;
e60a6f7b 13677 location_t loc = gimple_location (single_stmt);
1e8e9920 13678
13679 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
13680
13681 ptr_type = build_pointer_type (ctx->record_type);
13682 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
13683
e60a6f7b 13684 l0 = create_artificial_label (loc);
13685 l1 = create_artificial_label (loc);
13686 l2 = create_artificial_label (loc);
1e8e9920 13687
b9a16870 13688 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START);
13689 t = build_call_expr_loc (loc, bfn_decl, 0);
389dd41b 13690 t = fold_convert_loc (loc, ptr_type, t);
75a70cf9 13691 gimplify_assign (ctx->receiver_decl, t, pre_p);
1e8e9920 13692
13693 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
13694 build_int_cst (ptr_type, 0));
13695 t = build3 (COND_EXPR, void_type_node, t,
13696 build_and_jump (&l0), build_and_jump (&l1));
13697 gimplify_and_add (t, pre_p);
13698
75a70cf9 13699 gimple_seq_add_stmt (pre_p, gimple_build_label (l0));
1e8e9920 13700
75a70cf9 13701 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
1e8e9920 13702
13703 copyin_seq = NULL;
75a70cf9 13704 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
1e8e9920 13705 &copyin_seq, ctx);
13706
389dd41b 13707 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
b9a16870 13708 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END);
13709 t = build_call_expr_loc (loc, bfn_decl, 1, t);
1e8e9920 13710 gimplify_and_add (t, pre_p);
13711
13712 t = build_and_jump (&l2);
13713 gimplify_and_add (t, pre_p);
13714
75a70cf9 13715 gimple_seq_add_stmt (pre_p, gimple_build_label (l1));
1e8e9920 13716
75a70cf9 13717 gimple_seq_add_seq (pre_p, copyin_seq);
1e8e9920 13718
75a70cf9 13719 gimple_seq_add_stmt (pre_p, gimple_build_label (l2));
1e8e9920 13720}
13721
773c5ba7 13722
1e8e9920 13723/* Expand code for an OpenMP single directive. */
13724
13725static void
75a70cf9 13726lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
1e8e9920 13727{
75a70cf9 13728 tree block;
42acab1c 13729 gimple *t;
1a91d914 13730 gomp_single *single_stmt = as_a <gomp_single *> (gsi_stmt (*gsi_p));
13731 gbind *bind;
bc7bff74 13732 gimple_seq bind_body, bind_body_tail = NULL, dlist;
1e8e9920 13733
8a4a28a8 13734 push_gimplify_context ();
1e8e9920 13735
e3a19533 13736 block = make_node (BLOCK);
13737 bind = gimple_build_bind (NULL, NULL, block);
13738 gsi_replace (gsi_p, bind, true);
75a70cf9 13739 bind_body = NULL;
e3a19533 13740 dlist = NULL;
75a70cf9 13741 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt),
bc7bff74 13742 &bind_body, &dlist, ctx, NULL);
e3a19533 13743 lower_omp (gimple_omp_body_ptr (single_stmt), ctx);
1e8e9920 13744
75a70cf9 13745 gimple_seq_add_stmt (&bind_body, single_stmt);
1e8e9920 13746
13747 if (ctx->record_type)
75a70cf9 13748 lower_omp_single_copy (single_stmt, &bind_body, ctx);
1e8e9920 13749 else
75a70cf9 13750 lower_omp_single_simple (single_stmt, &bind_body);
13751
13752 gimple_omp_set_body (single_stmt, NULL);
1e8e9920 13753
75a70cf9 13754 gimple_seq_add_seq (&bind_body, dlist);
61e47ac8 13755
75a70cf9 13756 bind_body = maybe_catch_exception (bind_body);
61e47ac8 13757
48e1416a 13758 t = gimple_build_omp_return
75a70cf9 13759 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt),
13760 OMP_CLAUSE_NOWAIT));
bc7bff74 13761 gimple_seq_add_stmt (&bind_body_tail, t);
13762 maybe_add_implicit_barrier_cancel (ctx, &bind_body_tail);
13763 if (ctx->record_type)
13764 {
13765 gimple_stmt_iterator gsi = gsi_start (bind_body_tail);
13766 tree clobber = build_constructor (ctx->record_type, NULL);
13767 TREE_THIS_VOLATILE (clobber) = 1;
13768 gsi_insert_after (&gsi, gimple_build_assign (ctx->sender_decl,
13769 clobber), GSI_SAME_STMT);
13770 }
13771 gimple_seq_add_seq (&bind_body, bind_body_tail);
e3a19533 13772 gimple_bind_set_body (bind, bind_body);
61e47ac8 13773
1e8e9920 13774 pop_gimplify_context (bind);
773c5ba7 13775
75a70cf9 13776 gimple_bind_append_vars (bind, ctx->block_vars);
13777 BLOCK_VARS (block) = ctx->block_vars;
1d22f541 13778 if (BLOCK_VARS (block))
13779 TREE_USED (block) = 1;
1e8e9920 13780}
13781
773c5ba7 13782
1e8e9920 13783/* Expand code for an OpenMP master directive. */
13784
13785static void
75a70cf9 13786lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
1e8e9920 13787{
b9a16870 13788 tree block, lab = NULL, x, bfn_decl;
42acab1c 13789 gimple *stmt = gsi_stmt (*gsi_p);
1a91d914 13790 gbind *bind;
389dd41b 13791 location_t loc = gimple_location (stmt);
75a70cf9 13792 gimple_seq tseq;
1e8e9920 13793
8a4a28a8 13794 push_gimplify_context ();
1e8e9920 13795
13796 block = make_node (BLOCK);
e3a19533 13797 bind = gimple_build_bind (NULL, NULL, block);
13798 gsi_replace (gsi_p, bind, true);
13799 gimple_bind_add_stmt (bind, stmt);
61e47ac8 13800
b9a16870 13801 bfn_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
13802 x = build_call_expr_loc (loc, bfn_decl, 0);
1e8e9920 13803 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
13804 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
75a70cf9 13805 tseq = NULL;
13806 gimplify_and_add (x, &tseq);
13807 gimple_bind_add_seq (bind, tseq);
1e8e9920 13808
e3a19533 13809 lower_omp (gimple_omp_body_ptr (stmt), ctx);
75a70cf9 13810 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
13811 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
13812 gimple_omp_set_body (stmt, NULL);
1e8e9920 13813
75a70cf9 13814 gimple_bind_add_stmt (bind, gimple_build_label (lab));
61e47ac8 13815
75a70cf9 13816 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
61e47ac8 13817
1e8e9920 13818 pop_gimplify_context (bind);
773c5ba7 13819
75a70cf9 13820 gimple_bind_append_vars (bind, ctx->block_vars);
13821 BLOCK_VARS (block) = ctx->block_vars;
1e8e9920 13822}
13823
773c5ba7 13824
bc7bff74 13825/* Expand code for an OpenMP taskgroup directive. */
13826
13827static void
13828lower_omp_taskgroup (gimple_stmt_iterator *gsi_p, omp_context *ctx)
13829{
42acab1c 13830 gimple *stmt = gsi_stmt (*gsi_p);
1a91d914 13831 gcall *x;
13832 gbind *bind;
bc7bff74 13833 tree block = make_node (BLOCK);
13834
13835 bind = gimple_build_bind (NULL, NULL, block);
13836 gsi_replace (gsi_p, bind, true);
13837 gimple_bind_add_stmt (bind, stmt);
13838
13839 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START),
13840 0);
13841 gimple_bind_add_stmt (bind, x);
13842
13843 lower_omp (gimple_omp_body_ptr (stmt), ctx);
13844 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
13845 gimple_omp_set_body (stmt, NULL);
13846
13847 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
13848
13849 gimple_bind_append_vars (bind, ctx->block_vars);
13850 BLOCK_VARS (block) = ctx->block_vars;
13851}
13852
13853
43895be5 13854/* Fold the OMP_ORDERED_CLAUSES for the OMP_ORDERED in STMT if possible. */
13855
13856static void
13857lower_omp_ordered_clauses (gimple_stmt_iterator *gsi_p, gomp_ordered *ord_stmt,
13858 omp_context *ctx)
13859{
13860 struct omp_for_data fd;
13861 if (!ctx->outer || gimple_code (ctx->outer->stmt) != GIMPLE_OMP_FOR)
13862 return;
13863
13864 unsigned int len = gimple_omp_for_collapse (ctx->outer->stmt);
13865 struct omp_for_data_loop *loops = XALLOCAVEC (struct omp_for_data_loop, len);
13866 extract_omp_for_data (as_a <gomp_for *> (ctx->outer->stmt), &fd, loops);
13867 if (!fd.ordered)
13868 return;
13869
13870 tree *list_p = gimple_omp_ordered_clauses_ptr (ord_stmt);
13871 tree c = gimple_omp_ordered_clauses (ord_stmt);
13872 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
13873 && OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK)
13874 {
13875 /* Merge depend clauses from multiple adjacent
13876 #pragma omp ordered depend(sink:...) constructs
13877 into one #pragma omp ordered depend(sink:...), so that
13878 we can optimize them together. */
13879 gimple_stmt_iterator gsi = *gsi_p;
13880 gsi_next (&gsi);
13881 while (!gsi_end_p (gsi))
13882 {
13883 gimple *stmt = gsi_stmt (gsi);
13884 if (is_gimple_debug (stmt)
13885 || gimple_code (stmt) == GIMPLE_NOP)
13886 {
13887 gsi_next (&gsi);
13888 continue;
13889 }
13890 if (gimple_code (stmt) != GIMPLE_OMP_ORDERED)
13891 break;
13892 gomp_ordered *ord_stmt2 = as_a <gomp_ordered *> (stmt);
13893 c = gimple_omp_ordered_clauses (ord_stmt2);
13894 if (c == NULL_TREE
13895 || OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND
13896 || OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_SINK)
13897 break;
13898 while (*list_p)
13899 list_p = &OMP_CLAUSE_CHAIN (*list_p);
13900 *list_p = c;
13901 gsi_remove (&gsi, true);
13902 }
13903 }
13904
13905 /* Canonicalize sink dependence clauses into one folded clause if
13906 possible.
13907
13908 The basic algorithm is to create a sink vector whose first
13909 element is the GCD of all the first elements, and whose remaining
13910 elements are the minimum of the subsequent columns.
13911
13912 We ignore dependence vectors whose first element is zero because
13913 such dependencies are known to be executed by the same thread.
13914
13915 We take into account the direction of the loop, so a minimum
13916 becomes a maximum if the loop is iterating forwards. We also
13917 ignore sink clauses where the loop direction is unknown, or where
13918 the offsets are clearly invalid because they are not a multiple
13919 of the loop increment.
13920
13921 For example:
13922
13923 #pragma omp for ordered(2)
13924 for (i=0; i < N; ++i)
13925 for (j=0; j < M; ++j)
13926 {
13927 #pragma omp ordered \
13928 depend(sink:i-8,j-2) \
13929 depend(sink:i,j-1) \ // Completely ignored because i+0.
13930 depend(sink:i-4,j-3) \
13931 depend(sink:i-6,j-4)
13932 #pragma omp ordered depend(source)
13933 }
13934
13935 Folded clause is:
13936
13937 depend(sink:-gcd(8,4,6),-min(2,3,4))
13938 -or-
13939 depend(sink:-2,-2)
13940 */
13941
13942 /* FIXME: Computing GCD's where the first element is zero is
13943 non-trivial in the presence of collapsed loops. Do this later. */
13944 if (fd.collapse > 1)
13945 return;
13946
13947 wide_int *folded_deps = XALLOCAVEC (wide_int, 2 * len - 1);
13948 memset (folded_deps, 0, sizeof (*folded_deps) * (2 * len - 1));
13949 tree folded_dep = NULL_TREE;
13950 /* TRUE if the first dimension's offset is negative. */
13951 bool neg_offset_p = false;
13952
13953 list_p = gimple_omp_ordered_clauses_ptr (ord_stmt);
13954 unsigned int i;
13955 while ((c = *list_p) != NULL)
13956 {
13957 bool remove = false;
13958
13959 gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND);
13960 if (OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_SINK)
13961 goto next_ordered_clause;
13962
13963 tree vec;
13964 for (vec = OMP_CLAUSE_DECL (c), i = 0;
13965 vec && TREE_CODE (vec) == TREE_LIST;
13966 vec = TREE_CHAIN (vec), ++i)
13967 {
13968 gcc_assert (i < len);
13969
13970 /* extract_omp_for_data has canonicalized the condition. */
13971 gcc_assert (fd.loops[i].cond_code == LT_EXPR
13972 || fd.loops[i].cond_code == GT_EXPR);
13973 bool forward = fd.loops[i].cond_code == LT_EXPR;
13974 bool maybe_lexically_later = true;
13975
13976 /* While the committee makes up its mind, bail if we have any
13977 non-constant steps. */
13978 if (TREE_CODE (fd.loops[i].step) != INTEGER_CST)
13979 goto lower_omp_ordered_ret;
13980
13981 tree itype = TREE_TYPE (TREE_VALUE (vec));
13982 if (POINTER_TYPE_P (itype))
13983 itype = sizetype;
13984 wide_int offset = wide_int::from (TREE_PURPOSE (vec),
13985 TYPE_PRECISION (itype),
13986 TYPE_SIGN (itype));
13987
13988 /* Ignore invalid offsets that are not multiples of the step. */
13989 if (!wi::multiple_of_p
13990 (wi::abs (offset), wi::abs ((wide_int) fd.loops[i].step),
13991 UNSIGNED))
13992 {
13993 warning_at (OMP_CLAUSE_LOCATION (c), 0,
13994 "ignoring sink clause with offset that is not "
13995 "a multiple of the loop step");
13996 remove = true;
13997 goto next_ordered_clause;
13998 }
13999
14000 /* Calculate the first dimension. The first dimension of
14001 the folded dependency vector is the GCD of the first
14002 elements, while ignoring any first elements whose offset
14003 is 0. */
14004 if (i == 0)
14005 {
14006 /* Ignore dependence vectors whose first dimension is 0. */
14007 if (offset == 0)
14008 {
14009 remove = true;
14010 goto next_ordered_clause;
14011 }
14012 else
14013 {
14014 if (!TYPE_UNSIGNED (itype) && (forward ^ wi::neg_p (offset)))
14015 {
14016 error_at (OMP_CLAUSE_LOCATION (c),
14017 "first offset must be in opposite direction "
14018 "of loop iterations");
14019 goto lower_omp_ordered_ret;
14020 }
14021 if (forward)
14022 offset = -offset;
14023 neg_offset_p = forward;
14024 /* Initialize the first time around. */
14025 if (folded_dep == NULL_TREE)
14026 {
14027 folded_dep = c;
14028 folded_deps[0] = offset;
14029 }
14030 else
14031 folded_deps[0] = wi::gcd (folded_deps[0],
14032 offset, UNSIGNED);
14033 }
14034 }
14035 /* Calculate minimum for the remaining dimensions. */
14036 else
14037 {
14038 folded_deps[len + i - 1] = offset;
14039 if (folded_dep == c)
14040 folded_deps[i] = offset;
14041 else if (maybe_lexically_later
14042 && !wi::eq_p (folded_deps[i], offset))
14043 {
14044 if (forward ^ wi::gts_p (folded_deps[i], offset))
14045 {
14046 unsigned int j;
14047 folded_dep = c;
14048 for (j = 1; j <= i; j++)
14049 folded_deps[j] = folded_deps[len + j - 1];
14050 }
14051 else
14052 maybe_lexically_later = false;
14053 }
14054 }
14055 }
14056 gcc_assert (i == len);
14057
14058 remove = true;
14059
14060 next_ordered_clause:
14061 if (remove)
14062 *list_p = OMP_CLAUSE_CHAIN (c);
14063 else
14064 list_p = &OMP_CLAUSE_CHAIN (c);
14065 }
14066
14067 if (folded_dep)
14068 {
14069 if (neg_offset_p)
14070 folded_deps[0] = -folded_deps[0];
14071
14072 tree itype = TREE_TYPE (TREE_VALUE (OMP_CLAUSE_DECL (folded_dep)));
14073 if (POINTER_TYPE_P (itype))
14074 itype = sizetype;
14075
14076 TREE_PURPOSE (OMP_CLAUSE_DECL (folded_dep))
14077 = wide_int_to_tree (itype, folded_deps[0]);
14078 OMP_CLAUSE_CHAIN (folded_dep) = gimple_omp_ordered_clauses (ord_stmt);
14079 *gimple_omp_ordered_clauses_ptr (ord_stmt) = folded_dep;
14080 }
14081
14082 lower_omp_ordered_ret:
14083
14084 /* Ordered without clauses is #pragma omp threads, while we want
14085 a nop instead if we remove all clauses. */
14086 if (gimple_omp_ordered_clauses (ord_stmt) == NULL_TREE)
14087 gsi_replace (gsi_p, gimple_build_nop (), true);
14088}
14089
14090
1e8e9920 14091/* Expand code for an OpenMP ordered directive. */
14092
14093static void
75a70cf9 14094lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
1e8e9920 14095{
75a70cf9 14096 tree block;
42acab1c 14097 gimple *stmt = gsi_stmt (*gsi_p);
43895be5 14098 gomp_ordered *ord_stmt = as_a <gomp_ordered *> (stmt);
1a91d914 14099 gcall *x;
14100 gbind *bind;
a9833286 14101 bool simd = find_omp_clause (gimple_omp_ordered_clauses (ord_stmt),
14102 OMP_CLAUSE_SIMD);
14103 bool threads = find_omp_clause (gimple_omp_ordered_clauses (ord_stmt),
14104 OMP_CLAUSE_THREADS);
43895be5 14105
14106 if (find_omp_clause (gimple_omp_ordered_clauses (ord_stmt),
14107 OMP_CLAUSE_DEPEND))
14108 {
14109 /* FIXME: This is needs to be moved to the expansion to verify various
14110 conditions only testable on cfg with dominators computed, and also
14111 all the depend clauses to be merged still might need to be available
14112 for the runtime checks. */
14113 if (0)
14114 lower_omp_ordered_clauses (gsi_p, ord_stmt, ctx);
14115 return;
14116 }
1e8e9920 14117
8a4a28a8 14118 push_gimplify_context ();
1e8e9920 14119
14120 block = make_node (BLOCK);
e3a19533 14121 bind = gimple_build_bind (NULL, NULL, block);
14122 gsi_replace (gsi_p, bind, true);
14123 gimple_bind_add_stmt (bind, stmt);
61e47ac8 14124
43895be5 14125 if (simd)
14126 {
a9833286 14127 x = gimple_build_call_internal (IFN_GOMP_SIMD_ORDERED_START, 1,
14128 build_int_cst (NULL_TREE, threads));
43895be5 14129 cfun->has_simduid_loops = true;
14130 }
14131 else
14132 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START),
14133 0);
75a70cf9 14134 gimple_bind_add_stmt (bind, x);
1e8e9920 14135
e3a19533 14136 lower_omp (gimple_omp_body_ptr (stmt), ctx);
75a70cf9 14137 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
14138 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
14139 gimple_omp_set_body (stmt, NULL);
1e8e9920 14140
43895be5 14141 if (simd)
a9833286 14142 x = gimple_build_call_internal (IFN_GOMP_SIMD_ORDERED_END, 1,
14143 build_int_cst (NULL_TREE, threads));
43895be5 14144 else
14145 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END),
14146 0);
75a70cf9 14147 gimple_bind_add_stmt (bind, x);
61e47ac8 14148
75a70cf9 14149 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
61e47ac8 14150
1e8e9920 14151 pop_gimplify_context (bind);
773c5ba7 14152
75a70cf9 14153 gimple_bind_append_vars (bind, ctx->block_vars);
14154 BLOCK_VARS (block) = gimple_bind_vars (bind);
1e8e9920 14155}
14156
1e8e9920 14157
75a70cf9 14158/* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
1e8e9920 14159 substitution of a couple of function calls. But in the NAMED case,
14160 requires that languages coordinate a symbol name. It is therefore
14161 best put here in common code. */
14162
d4786b13 14163static GTY(()) hash_map<tree, tree> *critical_name_mutexes;
1e8e9920 14164
14165static void
75a70cf9 14166lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
1e8e9920 14167{
75a70cf9 14168 tree block;
14169 tree name, lock, unlock;
1a91d914 14170 gomp_critical *stmt = as_a <gomp_critical *> (gsi_stmt (*gsi_p));
14171 gbind *bind;
389dd41b 14172 location_t loc = gimple_location (stmt);
75a70cf9 14173 gimple_seq tbody;
1e8e9920 14174
75a70cf9 14175 name = gimple_omp_critical_name (stmt);
1e8e9920 14176 if (name)
14177 {
c2f47e15 14178 tree decl;
1e8e9920 14179
14180 if (!critical_name_mutexes)
d4786b13 14181 critical_name_mutexes = hash_map<tree, tree>::create_ggc (10);
1e8e9920 14182
d4786b13 14183 tree *n = critical_name_mutexes->get (name);
1e8e9920 14184 if (n == NULL)
14185 {
14186 char *new_str;
14187
f9e245b2 14188 decl = create_tmp_var_raw (ptr_type_node);
1e8e9920 14189
14190 new_str = ACONCAT ((".gomp_critical_user_",
14191 IDENTIFIER_POINTER (name), NULL));
14192 DECL_NAME (decl) = get_identifier (new_str);
14193 TREE_PUBLIC (decl) = 1;
14194 TREE_STATIC (decl) = 1;
14195 DECL_COMMON (decl) = 1;
14196 DECL_ARTIFICIAL (decl) = 1;
14197 DECL_IGNORED_P (decl) = 1;
b0c5e347 14198
97221fd7 14199 varpool_node::finalize_decl (decl);
1e8e9920 14200
d4786b13 14201 critical_name_mutexes->put (name, decl);
1e8e9920 14202 }
14203 else
d4786b13 14204 decl = *n;
1e8e9920 14205
ca4c3545 14206 /* If '#pragma omp critical' is inside offloaded region or
351fb0ce 14207 inside function marked as offloadable, the symbol must be
14208 marked as offloadable too. */
14209 omp_context *octx;
14210 if (cgraph_node::get (current_function_decl)->offloadable)
14211 varpool_node::get_create (decl)->offloadable = 1;
14212 else
14213 for (octx = ctx->outer; octx; octx = octx->outer)
ca4c3545 14214 if (is_gimple_omp_offloaded (octx->stmt))
351fb0ce 14215 {
14216 varpool_node::get_create (decl)->offloadable = 1;
14217 break;
14218 }
14219
b9a16870 14220 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START);
389dd41b 14221 lock = build_call_expr_loc (loc, lock, 1, build_fold_addr_expr_loc (loc, decl));
1e8e9920 14222
b9a16870 14223 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END);
389dd41b 14224 unlock = build_call_expr_loc (loc, unlock, 1,
14225 build_fold_addr_expr_loc (loc, decl));
1e8e9920 14226 }
14227 else
14228 {
b9a16870 14229 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START);
389dd41b 14230 lock = build_call_expr_loc (loc, lock, 0);
1e8e9920 14231
b9a16870 14232 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END);
389dd41b 14233 unlock = build_call_expr_loc (loc, unlock, 0);
1e8e9920 14234 }
14235
8a4a28a8 14236 push_gimplify_context ();
1e8e9920 14237
14238 block = make_node (BLOCK);
e3a19533 14239 bind = gimple_build_bind (NULL, NULL, block);
14240 gsi_replace (gsi_p, bind, true);
14241 gimple_bind_add_stmt (bind, stmt);
61e47ac8 14242
75a70cf9 14243 tbody = gimple_bind_body (bind);
14244 gimplify_and_add (lock, &tbody);
14245 gimple_bind_set_body (bind, tbody);
1e8e9920 14246
e3a19533 14247 lower_omp (gimple_omp_body_ptr (stmt), ctx);
75a70cf9 14248 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
14249 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
14250 gimple_omp_set_body (stmt, NULL);
1e8e9920 14251
75a70cf9 14252 tbody = gimple_bind_body (bind);
14253 gimplify_and_add (unlock, &tbody);
14254 gimple_bind_set_body (bind, tbody);
61e47ac8 14255
75a70cf9 14256 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
1e8e9920 14257
14258 pop_gimplify_context (bind);
75a70cf9 14259 gimple_bind_append_vars (bind, ctx->block_vars);
14260 BLOCK_VARS (block) = gimple_bind_vars (bind);
773c5ba7 14261}
14262
14263
14264/* A subroutine of lower_omp_for. Generate code to emit the predicate
14265 for a lastprivate clause. Given a loop control predicate of (V
14266 cond N2), we gate the clause on (!(V cond N2)). The lowered form
1e4afe3c 14267 is appended to *DLIST, iterator initialization is appended to
14268 *BODY_P. */
773c5ba7 14269
14270static void
75a70cf9 14271lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
14272 gimple_seq *dlist, struct omp_context *ctx)
773c5ba7 14273{
75a70cf9 14274 tree clauses, cond, vinit;
773c5ba7 14275 enum tree_code cond_code;
75a70cf9 14276 gimple_seq stmts;
48e1416a 14277
fd6481cf 14278 cond_code = fd->loop.cond_code;
773c5ba7 14279 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
14280
14281 /* When possible, use a strict equality expression. This can let VRP
14282 type optimizations deduce the value and remove a copy. */
e913b5cd 14283 if (tree_fits_shwi_p (fd->loop.step))
773c5ba7 14284 {
e913b5cd 14285 HOST_WIDE_INT step = tree_to_shwi (fd->loop.step);
773c5ba7 14286 if (step == 1 || step == -1)
14287 cond_code = EQ_EXPR;
14288 }
14289
d7729e26 14290 tree n2 = fd->loop.n2;
14291 if (fd->collapse > 1
14292 && TREE_CODE (n2) != INTEGER_CST
43895be5 14293 && gimple_omp_for_combined_into_p (fd->for_stmt))
d7729e26 14294 {
9561765e 14295 struct omp_context *taskreg_ctx = NULL;
43895be5 14296 if (gimple_code (ctx->outer->stmt) == GIMPLE_OMP_FOR)
14297 {
14298 gomp_for *gfor = as_a <gomp_for *> (ctx->outer->stmt);
9561765e 14299 if (gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_FOR
14300 || gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_DISTRIBUTE)
43895be5 14301 {
9561765e 14302 if (gimple_omp_for_combined_into_p (gfor))
14303 {
14304 gcc_assert (ctx->outer->outer
14305 && is_parallel_ctx (ctx->outer->outer));
14306 taskreg_ctx = ctx->outer->outer;
14307 }
14308 else
14309 {
14310 struct omp_for_data outer_fd;
14311 extract_omp_for_data (gfor, &outer_fd, NULL);
14312 n2 = fold_convert (TREE_TYPE (n2), outer_fd.loop.n2);
14313 }
43895be5 14314 }
14315 else if (gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_TASKLOOP)
9561765e 14316 taskreg_ctx = ctx->outer->outer;
43895be5 14317 }
9561765e 14318 else if (is_taskreg_ctx (ctx->outer))
14319 taskreg_ctx = ctx->outer;
14320 if (taskreg_ctx)
d7729e26 14321 {
43895be5 14322 int i;
14323 tree innerc
9561765e 14324 = find_omp_clause (gimple_omp_taskreg_clauses (taskreg_ctx->stmt),
43895be5 14325 OMP_CLAUSE__LOOPTEMP_);
14326 gcc_assert (innerc);
14327 for (i = 0; i < fd->collapse; i++)
14328 {
14329 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
14330 OMP_CLAUSE__LOOPTEMP_);
14331 gcc_assert (innerc);
14332 }
14333 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
14334 OMP_CLAUSE__LOOPTEMP_);
14335 if (innerc)
14336 n2 = fold_convert (TREE_TYPE (n2),
14337 lookup_decl (OMP_CLAUSE_DECL (innerc),
9561765e 14338 taskreg_ctx));
d7729e26 14339 }
14340 }
14341 cond = build2 (cond_code, boolean_type_node, fd->loop.v, n2);
773c5ba7 14342
75a70cf9 14343 clauses = gimple_omp_for_clauses (fd->for_stmt);
1e4afe3c 14344 stmts = NULL;
14345 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
75a70cf9 14346 if (!gimple_seq_empty_p (stmts))
1e4afe3c 14347 {
75a70cf9 14348 gimple_seq_add_seq (&stmts, *dlist);
fd6481cf 14349 *dlist = stmts;
1e4afe3c 14350
14351 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
fd6481cf 14352 vinit = fd->loop.n1;
1e4afe3c 14353 if (cond_code == EQ_EXPR
e913b5cd 14354 && tree_fits_shwi_p (fd->loop.n2)
fd6481cf 14355 && ! integer_zerop (fd->loop.n2))
14356 vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0);
3d483a94 14357 else
14358 vinit = unshare_expr (vinit);
1e4afe3c 14359
14360 /* Initialize the iterator variable, so that threads that don't execute
14361 any iterations don't execute the lastprivate clauses by accident. */
75a70cf9 14362 gimplify_assign (fd->loop.v, vinit, body_p);
1e4afe3c 14363 }
773c5ba7 14364}
14365
14366
ca4c3545 14367/* Lower code for an OMP loop directive. */
773c5ba7 14368
14369static void
75a70cf9 14370lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
773c5ba7 14371{
75a70cf9 14372 tree *rhs_p, block;
bc7bff74 14373 struct omp_for_data fd, *fdp = NULL;
1a91d914 14374 gomp_for *stmt = as_a <gomp_for *> (gsi_stmt (*gsi_p));
14375 gbind *new_stmt;
f018d957 14376 gimple_seq omp_for_body, body, dlist;
a8e785ba 14377 gimple_seq oacc_head = NULL, oacc_tail = NULL;
75a70cf9 14378 size_t i;
773c5ba7 14379
8a4a28a8 14380 push_gimplify_context ();
773c5ba7 14381
e3a19533 14382 lower_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
773c5ba7 14383
1d22f541 14384 block = make_node (BLOCK);
75a70cf9 14385 new_stmt = gimple_build_bind (NULL, NULL, block);
e3a19533 14386 /* Replace at gsi right away, so that 'stmt' is no member
47ae02b7 14387 of a sequence anymore as we're going to add to a different
e3a19533 14388 one below. */
14389 gsi_replace (gsi_p, new_stmt, true);
1d22f541 14390
773c5ba7 14391 /* Move declaration of temporaries in the loop body before we make
14392 it go away. */
75a70cf9 14393 omp_for_body = gimple_omp_body (stmt);
14394 if (!gimple_seq_empty_p (omp_for_body)
14395 && gimple_code (gimple_seq_first_stmt (omp_for_body)) == GIMPLE_BIND)
14396 {
1a91d914 14397 gbind *inner_bind
14398 = as_a <gbind *> (gimple_seq_first_stmt (omp_for_body));
6d5a8d89 14399 tree vars = gimple_bind_vars (inner_bind);
75a70cf9 14400 gimple_bind_append_vars (new_stmt, vars);
6d5a8d89 14401 /* bind_vars/BLOCK_VARS are being moved to new_stmt/block, don't
14402 keep them on the inner_bind and it's block. */
14403 gimple_bind_set_vars (inner_bind, NULL_TREE);
14404 if (gimple_bind_block (inner_bind))
14405 BLOCK_VARS (gimple_bind_block (inner_bind)) = NULL_TREE;
75a70cf9 14406 }
773c5ba7 14407
bc7bff74 14408 if (gimple_omp_for_combined_into_p (stmt))
14409 {
14410 extract_omp_for_data (stmt, &fd, NULL);
14411 fdp = &fd;
14412
14413 /* We need two temporaries with fd.loop.v type (istart/iend)
14414 and then (fd.collapse - 1) temporaries with the same
14415 type for count2 ... countN-1 vars if not constant. */
14416 size_t count = 2;
14417 tree type = fd.iter_type;
14418 if (fd.collapse > 1
14419 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
14420 count += fd.collapse - 1;
43895be5 14421 bool taskreg_for
14422 = (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR
14423 || gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_TASKLOOP);
bc7bff74 14424 tree outerc = NULL, *pc = gimple_omp_for_clauses_ptr (stmt);
14425 tree clauses = *pc;
43895be5 14426 if (taskreg_for)
bc7bff74 14427 outerc
43895be5 14428 = find_omp_clause (gimple_omp_taskreg_clauses (ctx->outer->stmt),
bc7bff74 14429 OMP_CLAUSE__LOOPTEMP_);
14430 for (i = 0; i < count; i++)
14431 {
14432 tree temp;
43895be5 14433 if (taskreg_for)
bc7bff74 14434 {
14435 gcc_assert (outerc);
14436 temp = lookup_decl (OMP_CLAUSE_DECL (outerc), ctx->outer);
14437 outerc = find_omp_clause (OMP_CLAUSE_CHAIN (outerc),
14438 OMP_CLAUSE__LOOPTEMP_);
14439 }
14440 else
691447ab 14441 {
f9e245b2 14442 temp = create_tmp_var (type);
691447ab 14443 insert_decl_map (&ctx->outer->cb, temp, temp);
14444 }
bc7bff74 14445 *pc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
14446 OMP_CLAUSE_DECL (*pc) = temp;
14447 pc = &OMP_CLAUSE_CHAIN (*pc);
14448 }
14449 *pc = clauses;
14450 }
14451
75a70cf9 14452 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
773c5ba7 14453 dlist = NULL;
75a70cf9 14454 body = NULL;
bc7bff74 14455 lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx,
14456 fdp);
75a70cf9 14457 gimple_seq_add_seq (&body, gimple_omp_for_pre_body (stmt));
773c5ba7 14458
3d483a94 14459 lower_omp (gimple_omp_body_ptr (stmt), ctx);
14460
773c5ba7 14461 /* Lower the header expressions. At this point, we can assume that
14462 the header is of the form:
14463
14464 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
14465
14466 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
14467 using the .omp_data_s mapping, if needed. */
75a70cf9 14468 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
fd6481cf 14469 {
75a70cf9 14470 rhs_p = gimple_omp_for_initial_ptr (stmt, i);
fd6481cf 14471 if (!is_gimple_min_invariant (*rhs_p))
75a70cf9 14472 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
fd6481cf 14473
75a70cf9 14474 rhs_p = gimple_omp_for_final_ptr (stmt, i);
fd6481cf 14475 if (!is_gimple_min_invariant (*rhs_p))
75a70cf9 14476 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
fd6481cf 14477
75a70cf9 14478 rhs_p = &TREE_OPERAND (gimple_omp_for_incr (stmt, i), 1);
fd6481cf 14479 if (!is_gimple_min_invariant (*rhs_p))
75a70cf9 14480 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
fd6481cf 14481 }
773c5ba7 14482
14483 /* Once lowered, extract the bounds and clauses. */
fd6481cf 14484 extract_omp_for_data (stmt, &fd, NULL);
773c5ba7 14485
a8e785ba 14486 if (is_gimple_omp_oacc (ctx->stmt)
14487 && !ctx_in_oacc_kernels_region (ctx))
14488 lower_oacc_head_tail (gimple_location (stmt),
14489 gimple_omp_for_clauses (stmt),
14490 &oacc_head, &oacc_tail, ctx);
14491
f69b8a4c 14492 /* Add OpenACC partitioning and reduction markers just before the loop */
a8e785ba 14493 if (oacc_head)
14494 gimple_seq_add_seq (&body, oacc_head);
14495
75a70cf9 14496 lower_omp_for_lastprivate (&fd, &body, &dlist, ctx);
773c5ba7 14497
43895be5 14498 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR)
14499 for (tree c = gimple_omp_for_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
14500 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
14501 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
14502 {
14503 OMP_CLAUSE_DECL (c) = lookup_decl (OMP_CLAUSE_DECL (c), ctx);
14504 if (DECL_P (OMP_CLAUSE_LINEAR_STEP (c)))
14505 OMP_CLAUSE_LINEAR_STEP (c)
14506 = maybe_lookup_decl_in_outer_ctx (OMP_CLAUSE_LINEAR_STEP (c),
14507 ctx);
14508 }
14509
75a70cf9 14510 gimple_seq_add_stmt (&body, stmt);
14511 gimple_seq_add_seq (&body, gimple_omp_body (stmt));
61e47ac8 14512
75a70cf9 14513 gimple_seq_add_stmt (&body, gimple_build_omp_continue (fd.loop.v,
14514 fd.loop.v));
61e47ac8 14515
773c5ba7 14516 /* After the loop, add exit clauses. */
75a70cf9 14517 lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, ctx);
bc7bff74 14518
14519 if (ctx->cancellable)
14520 gimple_seq_add_stmt (&body, gimple_build_label (ctx->cancel_label));
14521
75a70cf9 14522 gimple_seq_add_seq (&body, dlist);
773c5ba7 14523
75a70cf9 14524 body = maybe_catch_exception (body);
aade31a0 14525
61e47ac8 14526 /* Region exit marker goes at the end of the loop body. */
75a70cf9 14527 gimple_seq_add_stmt (&body, gimple_build_omp_return (fd.have_nowait));
bc7bff74 14528 maybe_add_implicit_barrier_cancel (ctx, &body);
a8e785ba 14529
14530 /* Add OpenACC joining and reduction markers just after the loop. */
14531 if (oacc_tail)
14532 gimple_seq_add_seq (&body, oacc_tail);
14533
1d22f541 14534 pop_gimplify_context (new_stmt);
75a70cf9 14535
14536 gimple_bind_append_vars (new_stmt, ctx->block_vars);
14537 BLOCK_VARS (block) = gimple_bind_vars (new_stmt);
1d22f541 14538 if (BLOCK_VARS (block))
14539 TREE_USED (block) = 1;
773c5ba7 14540
75a70cf9 14541 gimple_bind_set_body (new_stmt, body);
14542 gimple_omp_set_body (stmt, NULL);
14543 gimple_omp_for_set_pre_body (stmt, NULL);
1e8e9920 14544}
14545
48e1416a 14546/* Callback for walk_stmts. Check if the current statement only contains
a7dfc4fe 14547 GIMPLE_OMP_FOR or GIMPLE_OMP_SECTIONS. */
de7ef844 14548
14549static tree
75a70cf9 14550check_combined_parallel (gimple_stmt_iterator *gsi_p,
14551 bool *handled_ops_p,
14552 struct walk_stmt_info *wi)
de7ef844 14553{
4077bf7a 14554 int *info = (int *) wi->info;
42acab1c 14555 gimple *stmt = gsi_stmt (*gsi_p);
de7ef844 14556
75a70cf9 14557 *handled_ops_p = true;
14558 switch (gimple_code (stmt))
de7ef844 14559 {
75a70cf9 14560 WALK_SUBSTMTS;
14561
14562 case GIMPLE_OMP_FOR:
14563 case GIMPLE_OMP_SECTIONS:
de7ef844 14564 *info = *info == 0 ? 1 : -1;
14565 break;
14566 default:
14567 *info = -1;
14568 break;
14569 }
14570 return NULL;
14571}
773c5ba7 14572
fd6481cf 14573struct omp_taskcopy_context
14574{
14575 /* This field must be at the beginning, as we do "inheritance": Some
14576 callback functions for tree-inline.c (e.g., omp_copy_decl)
14577 receive a copy_body_data pointer that is up-casted to an
14578 omp_context pointer. */
14579 copy_body_data cb;
14580 omp_context *ctx;
14581};
14582
14583static tree
14584task_copyfn_copy_decl (tree var, copy_body_data *cb)
14585{
14586 struct omp_taskcopy_context *tcctx = (struct omp_taskcopy_context *) cb;
14587
14588 if (splay_tree_lookup (tcctx->ctx->sfield_map, (splay_tree_key) var))
f9e245b2 14589 return create_tmp_var (TREE_TYPE (var));
fd6481cf 14590
14591 return var;
14592}
14593
14594static tree
14595task_copyfn_remap_type (struct omp_taskcopy_context *tcctx, tree orig_type)
14596{
14597 tree name, new_fields = NULL, type, f;
14598
14599 type = lang_hooks.types.make_type (RECORD_TYPE);
14600 name = DECL_NAME (TYPE_NAME (orig_type));
e60a6f7b 14601 name = build_decl (gimple_location (tcctx->ctx->stmt),
14602 TYPE_DECL, name, type);
fd6481cf 14603 TYPE_NAME (type) = name;
14604
14605 for (f = TYPE_FIELDS (orig_type); f ; f = TREE_CHAIN (f))
14606 {
14607 tree new_f = copy_node (f);
14608 DECL_CONTEXT (new_f) = type;
14609 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &tcctx->cb);
14610 TREE_CHAIN (new_f) = new_fields;
75a70cf9 14611 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &tcctx->cb, NULL);
14612 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r, &tcctx->cb, NULL);
14613 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
14614 &tcctx->cb, NULL);
fd6481cf 14615 new_fields = new_f;
06ecf488 14616 tcctx->cb.decl_map->put (f, new_f);
fd6481cf 14617 }
14618 TYPE_FIELDS (type) = nreverse (new_fields);
14619 layout_type (type);
14620 return type;
14621}
14622
14623/* Create task copyfn. */
14624
14625static void
1a91d914 14626create_task_copyfn (gomp_task *task_stmt, omp_context *ctx)
fd6481cf 14627{
14628 struct function *child_cfun;
14629 tree child_fn, t, c, src, dst, f, sf, arg, sarg, decl;
14630 tree record_type, srecord_type, bind, list;
14631 bool record_needs_remap = false, srecord_needs_remap = false;
14632 splay_tree_node n;
14633 struct omp_taskcopy_context tcctx;
389dd41b 14634 location_t loc = gimple_location (task_stmt);
fd6481cf 14635
75a70cf9 14636 child_fn = gimple_omp_task_copy_fn (task_stmt);
fd6481cf 14637 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
14638 gcc_assert (child_cfun->cfg == NULL);
fd6481cf 14639 DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
14640
14641 /* Reset DECL_CONTEXT on function arguments. */
1767a056 14642 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
fd6481cf 14643 DECL_CONTEXT (t) = child_fn;
14644
14645 /* Populate the function. */
8a4a28a8 14646 push_gimplify_context ();
9078126c 14647 push_cfun (child_cfun);
fd6481cf 14648
14649 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
14650 TREE_SIDE_EFFECTS (bind) = 1;
14651 list = NULL;
14652 DECL_SAVED_TREE (child_fn) = bind;
75a70cf9 14653 DECL_SOURCE_LOCATION (child_fn) = gimple_location (task_stmt);
fd6481cf 14654
14655 /* Remap src and dst argument types if needed. */
14656 record_type = ctx->record_type;
14657 srecord_type = ctx->srecord_type;
1767a056 14658 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
fd6481cf 14659 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
14660 {
14661 record_needs_remap = true;
14662 break;
14663 }
1767a056 14664 for (f = TYPE_FIELDS (srecord_type); f ; f = DECL_CHAIN (f))
fd6481cf 14665 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
14666 {
14667 srecord_needs_remap = true;
14668 break;
14669 }
14670
14671 if (record_needs_remap || srecord_needs_remap)
14672 {
14673 memset (&tcctx, '\0', sizeof (tcctx));
14674 tcctx.cb.src_fn = ctx->cb.src_fn;
14675 tcctx.cb.dst_fn = child_fn;
415d1b9a 14676 tcctx.cb.src_node = cgraph_node::get (tcctx.cb.src_fn);
53f79206 14677 gcc_checking_assert (tcctx.cb.src_node);
fd6481cf 14678 tcctx.cb.dst_node = tcctx.cb.src_node;
14679 tcctx.cb.src_cfun = ctx->cb.src_cfun;
14680 tcctx.cb.copy_decl = task_copyfn_copy_decl;
e38def9c 14681 tcctx.cb.eh_lp_nr = 0;
fd6481cf 14682 tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
06ecf488 14683 tcctx.cb.decl_map = new hash_map<tree, tree>;
fd6481cf 14684 tcctx.ctx = ctx;
14685
14686 if (record_needs_remap)
14687 record_type = task_copyfn_remap_type (&tcctx, record_type);
14688 if (srecord_needs_remap)
14689 srecord_type = task_copyfn_remap_type (&tcctx, srecord_type);
14690 }
14691 else
14692 tcctx.cb.decl_map = NULL;
14693
fd6481cf 14694 arg = DECL_ARGUMENTS (child_fn);
14695 TREE_TYPE (arg) = build_pointer_type (record_type);
1767a056 14696 sarg = DECL_CHAIN (arg);
fd6481cf 14697 TREE_TYPE (sarg) = build_pointer_type (srecord_type);
14698
14699 /* First pass: initialize temporaries used in record_type and srecord_type
14700 sizes and field offsets. */
14701 if (tcctx.cb.decl_map)
75a70cf9 14702 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
fd6481cf 14703 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
14704 {
14705 tree *p;
14706
14707 decl = OMP_CLAUSE_DECL (c);
06ecf488 14708 p = tcctx.cb.decl_map->get (decl);
fd6481cf 14709 if (p == NULL)
14710 continue;
14711 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
14712 sf = (tree) n->value;
06ecf488 14713 sf = *tcctx.cb.decl_map->get (sf);
182cf5a9 14714 src = build_simple_mem_ref_loc (loc, sarg);
445d06b6 14715 src = omp_build_component_ref (src, sf);
75a70cf9 14716 t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
fd6481cf 14717 append_to_statement_list (t, &list);
14718 }
14719
14720 /* Second pass: copy shared var pointers and copy construct non-VLA
14721 firstprivate vars. */
75a70cf9 14722 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
fd6481cf 14723 switch (OMP_CLAUSE_CODE (c))
14724 {
43895be5 14725 splay_tree_key key;
fd6481cf 14726 case OMP_CLAUSE_SHARED:
14727 decl = OMP_CLAUSE_DECL (c);
43895be5 14728 key = (splay_tree_key) decl;
14729 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
14730 key = (splay_tree_key) &DECL_UID (decl);
14731 n = splay_tree_lookup (ctx->field_map, key);
fd6481cf 14732 if (n == NULL)
14733 break;
14734 f = (tree) n->value;
14735 if (tcctx.cb.decl_map)
06ecf488 14736 f = *tcctx.cb.decl_map->get (f);
43895be5 14737 n = splay_tree_lookup (ctx->sfield_map, key);
fd6481cf 14738 sf = (tree) n->value;
14739 if (tcctx.cb.decl_map)
06ecf488 14740 sf = *tcctx.cb.decl_map->get (sf);
182cf5a9 14741 src = build_simple_mem_ref_loc (loc, sarg);
445d06b6 14742 src = omp_build_component_ref (src, sf);
182cf5a9 14743 dst = build_simple_mem_ref_loc (loc, arg);
445d06b6 14744 dst = omp_build_component_ref (dst, f);
75a70cf9 14745 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
fd6481cf 14746 append_to_statement_list (t, &list);
14747 break;
14748 case OMP_CLAUSE_FIRSTPRIVATE:
14749 decl = OMP_CLAUSE_DECL (c);
14750 if (is_variable_sized (decl))
14751 break;
14752 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
14753 if (n == NULL)
14754 break;
14755 f = (tree) n->value;
14756 if (tcctx.cb.decl_map)
06ecf488 14757 f = *tcctx.cb.decl_map->get (f);
fd6481cf 14758 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
14759 if (n != NULL)
14760 {
14761 sf = (tree) n->value;
14762 if (tcctx.cb.decl_map)
06ecf488 14763 sf = *tcctx.cb.decl_map->get (sf);
182cf5a9 14764 src = build_simple_mem_ref_loc (loc, sarg);
445d06b6 14765 src = omp_build_component_ref (src, sf);
fd6481cf 14766 if (use_pointer_for_field (decl, NULL) || is_reference (decl))
182cf5a9 14767 src = build_simple_mem_ref_loc (loc, src);
fd6481cf 14768 }
14769 else
14770 src = decl;
182cf5a9 14771 dst = build_simple_mem_ref_loc (loc, arg);
445d06b6 14772 dst = omp_build_component_ref (dst, f);
fd6481cf 14773 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
14774 append_to_statement_list (t, &list);
14775 break;
14776 case OMP_CLAUSE_PRIVATE:
14777 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c))
14778 break;
14779 decl = OMP_CLAUSE_DECL (c);
14780 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
14781 f = (tree) n->value;
14782 if (tcctx.cb.decl_map)
06ecf488 14783 f = *tcctx.cb.decl_map->get (f);
fd6481cf 14784 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
14785 if (n != NULL)
14786 {
14787 sf = (tree) n->value;
14788 if (tcctx.cb.decl_map)
06ecf488 14789 sf = *tcctx.cb.decl_map->get (sf);
182cf5a9 14790 src = build_simple_mem_ref_loc (loc, sarg);
445d06b6 14791 src = omp_build_component_ref (src, sf);
fd6481cf 14792 if (use_pointer_for_field (decl, NULL))
182cf5a9 14793 src = build_simple_mem_ref_loc (loc, src);
fd6481cf 14794 }
14795 else
14796 src = decl;
182cf5a9 14797 dst = build_simple_mem_ref_loc (loc, arg);
445d06b6 14798 dst = omp_build_component_ref (dst, f);
75a70cf9 14799 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
fd6481cf 14800 append_to_statement_list (t, &list);
14801 break;
14802 default:
14803 break;
14804 }
14805
14806 /* Last pass: handle VLA firstprivates. */
14807 if (tcctx.cb.decl_map)
75a70cf9 14808 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
fd6481cf 14809 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
14810 {
14811 tree ind, ptr, df;
14812
14813 decl = OMP_CLAUSE_DECL (c);
14814 if (!is_variable_sized (decl))
14815 continue;
14816 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
14817 if (n == NULL)
14818 continue;
14819 f = (tree) n->value;
06ecf488 14820 f = *tcctx.cb.decl_map->get (f);
fd6481cf 14821 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
14822 ind = DECL_VALUE_EXPR (decl);
14823 gcc_assert (TREE_CODE (ind) == INDIRECT_REF);
14824 gcc_assert (DECL_P (TREE_OPERAND (ind, 0)));
14825 n = splay_tree_lookup (ctx->sfield_map,
14826 (splay_tree_key) TREE_OPERAND (ind, 0));
14827 sf = (tree) n->value;
06ecf488 14828 sf = *tcctx.cb.decl_map->get (sf);
182cf5a9 14829 src = build_simple_mem_ref_loc (loc, sarg);
445d06b6 14830 src = omp_build_component_ref (src, sf);
182cf5a9 14831 src = build_simple_mem_ref_loc (loc, src);
14832 dst = build_simple_mem_ref_loc (loc, arg);
445d06b6 14833 dst = omp_build_component_ref (dst, f);
fd6481cf 14834 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
14835 append_to_statement_list (t, &list);
14836 n = splay_tree_lookup (ctx->field_map,
14837 (splay_tree_key) TREE_OPERAND (ind, 0));
14838 df = (tree) n->value;
06ecf488 14839 df = *tcctx.cb.decl_map->get (df);
182cf5a9 14840 ptr = build_simple_mem_ref_loc (loc, arg);
445d06b6 14841 ptr = omp_build_component_ref (ptr, df);
75a70cf9 14842 t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
389dd41b 14843 build_fold_addr_expr_loc (loc, dst));
fd6481cf 14844 append_to_statement_list (t, &list);
14845 }
14846
14847 t = build1 (RETURN_EXPR, void_type_node, NULL);
14848 append_to_statement_list (t, &list);
14849
14850 if (tcctx.cb.decl_map)
06ecf488 14851 delete tcctx.cb.decl_map;
fd6481cf 14852 pop_gimplify_context (NULL);
14853 BIND_EXPR_BODY (bind) = list;
14854 pop_cfun ();
fd6481cf 14855}
14856
bc7bff74 14857static void
43895be5 14858lower_depend_clauses (tree *pclauses, gimple_seq *iseq, gimple_seq *oseq)
bc7bff74 14859{
14860 tree c, clauses;
42acab1c 14861 gimple *g;
bc7bff74 14862 size_t n_in = 0, n_out = 0, idx = 2, i;
14863
43895be5 14864 clauses = find_omp_clause (*pclauses, OMP_CLAUSE_DEPEND);
bc7bff74 14865 gcc_assert (clauses);
14866 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
14867 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
14868 switch (OMP_CLAUSE_DEPEND_KIND (c))
14869 {
14870 case OMP_CLAUSE_DEPEND_IN:
14871 n_in++;
14872 break;
14873 case OMP_CLAUSE_DEPEND_OUT:
14874 case OMP_CLAUSE_DEPEND_INOUT:
14875 n_out++;
14876 break;
43895be5 14877 case OMP_CLAUSE_DEPEND_SOURCE:
14878 case OMP_CLAUSE_DEPEND_SINK:
14879 /* FALLTHRU */
bc7bff74 14880 default:
14881 gcc_unreachable ();
14882 }
14883 tree type = build_array_type_nelts (ptr_type_node, n_in + n_out + 2);
f9e245b2 14884 tree array = create_tmp_var (type);
43895be5 14885 TREE_ADDRESSABLE (array) = 1;
bc7bff74 14886 tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
14887 NULL_TREE);
14888 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_in + n_out));
14889 gimple_seq_add_stmt (iseq, g);
14890 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
14891 NULL_TREE);
14892 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_out));
14893 gimple_seq_add_stmt (iseq, g);
14894 for (i = 0; i < 2; i++)
14895 {
14896 if ((i ? n_in : n_out) == 0)
14897 continue;
14898 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
14899 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
14900 && ((OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_IN) ^ i))
14901 {
14902 tree t = OMP_CLAUSE_DECL (c);
14903 t = fold_convert (ptr_type_node, t);
14904 gimplify_expr (&t, iseq, NULL, is_gimple_val, fb_rvalue);
14905 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (idx++),
14906 NULL_TREE, NULL_TREE);
14907 g = gimple_build_assign (r, t);
14908 gimple_seq_add_stmt (iseq, g);
14909 }
14910 }
bc7bff74 14911 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
14912 OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
43895be5 14913 OMP_CLAUSE_CHAIN (c) = *pclauses;
14914 *pclauses = c;
bc7bff74 14915 tree clobber = build_constructor (type, NULL);
14916 TREE_THIS_VOLATILE (clobber) = 1;
14917 g = gimple_build_assign (array, clobber);
14918 gimple_seq_add_stmt (oseq, g);
14919}
14920
75a70cf9 14921/* Lower the OpenMP parallel or task directive in the current statement
14922 in GSI_P. CTX holds context information for the directive. */
773c5ba7 14923
14924static void
75a70cf9 14925lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
773c5ba7 14926{
75a70cf9 14927 tree clauses;
14928 tree child_fn, t;
42acab1c 14929 gimple *stmt = gsi_stmt (*gsi_p);
1a91d914 14930 gbind *par_bind, *bind, *dep_bind = NULL;
bc7bff74 14931 gimple_seq par_body, olist, ilist, par_olist, par_rlist, par_ilist, new_body;
389dd41b 14932 location_t loc = gimple_location (stmt);
773c5ba7 14933
75a70cf9 14934 clauses = gimple_omp_taskreg_clauses (stmt);
1a91d914 14935 par_bind
14936 = as_a <gbind *> (gimple_seq_first_stmt (gimple_omp_body (stmt)));
75a70cf9 14937 par_body = gimple_bind_body (par_bind);
773c5ba7 14938 child_fn = ctx->cb.dst_fn;
75a70cf9 14939 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
14940 && !gimple_omp_parallel_combined_p (stmt))
de7ef844 14941 {
14942 struct walk_stmt_info wi;
14943 int ws_num = 0;
14944
14945 memset (&wi, 0, sizeof (wi));
de7ef844 14946 wi.info = &ws_num;
14947 wi.val_only = true;
75a70cf9 14948 walk_gimple_seq (par_body, check_combined_parallel, NULL, &wi);
de7ef844 14949 if (ws_num == 1)
75a70cf9 14950 gimple_omp_parallel_set_combined_p (stmt, true);
de7ef844 14951 }
bc7bff74 14952 gimple_seq dep_ilist = NULL;
14953 gimple_seq dep_olist = NULL;
14954 if (gimple_code (stmt) == GIMPLE_OMP_TASK
14955 && find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
14956 {
8a4a28a8 14957 push_gimplify_context ();
bc7bff74 14958 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
43895be5 14959 lower_depend_clauses (gimple_omp_task_clauses_ptr (stmt),
14960 &dep_ilist, &dep_olist);
bc7bff74 14961 }
14962
fd6481cf 14963 if (ctx->srecord_type)
1a91d914 14964 create_task_copyfn (as_a <gomp_task *> (stmt), ctx);
773c5ba7 14965
8a4a28a8 14966 push_gimplify_context ();
773c5ba7 14967
75a70cf9 14968 par_olist = NULL;
14969 par_ilist = NULL;
bc7bff74 14970 par_rlist = NULL;
14971 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx, NULL);
e3a19533 14972 lower_omp (&par_body, ctx);
75a70cf9 14973 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL)
bc7bff74 14974 lower_reduction_clauses (clauses, &par_rlist, ctx);
773c5ba7 14975
14976 /* Declare all the variables created by mapping and the variables
14977 declared in the scope of the parallel body. */
14978 record_vars_into (ctx->block_vars, child_fn);
75a70cf9 14979 record_vars_into (gimple_bind_vars (par_bind), child_fn);
773c5ba7 14980
14981 if (ctx->record_type)
14982 {
fd6481cf 14983 ctx->sender_decl
14984 = create_tmp_var (ctx->srecord_type ? ctx->srecord_type
14985 : ctx->record_type, ".omp_data_o");
84bfaaeb 14986 DECL_NAMELESS (ctx->sender_decl) = 1;
86f2ad37 14987 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
75a70cf9 14988 gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl);
773c5ba7 14989 }
14990
75a70cf9 14991 olist = NULL;
14992 ilist = NULL;
773c5ba7 14993 lower_send_clauses (clauses, &ilist, &olist, ctx);
14994 lower_send_shared_vars (&ilist, &olist, ctx);
14995
bc7bff74 14996 if (ctx->record_type)
14997 {
14998 tree clobber = build_constructor (TREE_TYPE (ctx->sender_decl), NULL);
14999 TREE_THIS_VOLATILE (clobber) = 1;
15000 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
15001 clobber));
15002 }
15003
773c5ba7 15004 /* Once all the expansions are done, sequence all the different
75a70cf9 15005 fragments inside gimple_omp_body. */
773c5ba7 15006
75a70cf9 15007 new_body = NULL;
773c5ba7 15008
15009 if (ctx->record_type)
15010 {
389dd41b 15011 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
cc6b725b 15012 /* fixup_child_record_type might have changed receiver_decl's type. */
389dd41b 15013 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
75a70cf9 15014 gimple_seq_add_stmt (&new_body,
15015 gimple_build_assign (ctx->receiver_decl, t));
773c5ba7 15016 }
15017
75a70cf9 15018 gimple_seq_add_seq (&new_body, par_ilist);
15019 gimple_seq_add_seq (&new_body, par_body);
bc7bff74 15020 gimple_seq_add_seq (&new_body, par_rlist);
15021 if (ctx->cancellable)
15022 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
75a70cf9 15023 gimple_seq_add_seq (&new_body, par_olist);
15024 new_body = maybe_catch_exception (new_body);
b25f70fd 15025 if (gimple_code (stmt) == GIMPLE_OMP_TASK)
15026 gimple_seq_add_stmt (&new_body,
15027 gimple_build_omp_continue (integer_zero_node,
15028 integer_zero_node));
75a70cf9 15029 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
15030 gimple_omp_set_body (stmt, new_body);
773c5ba7 15031
75a70cf9 15032 bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
bc7bff74 15033 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
15034 gimple_bind_add_seq (bind, ilist);
15035 gimple_bind_add_stmt (bind, stmt);
15036 gimple_bind_add_seq (bind, olist);
15037
15038 pop_gimplify_context (NULL);
15039
15040 if (dep_bind)
15041 {
15042 gimple_bind_add_seq (dep_bind, dep_ilist);
15043 gimple_bind_add_stmt (dep_bind, bind);
15044 gimple_bind_add_seq (dep_bind, dep_olist);
15045 pop_gimplify_context (dep_bind);
15046 }
15047}
15048
ca4c3545 15049/* Lower the GIMPLE_OMP_TARGET in the current statement
bc7bff74 15050 in GSI_P. CTX holds context information for the directive. */
15051
15052static void
15053lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
15054{
15055 tree clauses;
15056 tree child_fn, t, c;
1a91d914 15057 gomp_target *stmt = as_a <gomp_target *> (gsi_stmt (*gsi_p));
43895be5 15058 gbind *tgt_bind, *bind, *dep_bind = NULL;
b656be3a 15059 gimple_seq tgt_body, olist, ilist, fplist, new_body;
bc7bff74 15060 location_t loc = gimple_location (stmt);
ca4c3545 15061 bool offloaded, data_region;
bc7bff74 15062 unsigned int map_cnt = 0;
43895be5 15063 bool has_depend = false;
bc7bff74 15064
ca4c3545 15065 offloaded = is_gimple_omp_offloaded (stmt);
15066 switch (gimple_omp_target_kind (stmt))
15067 {
15068 case GF_OMP_TARGET_KIND_REGION:
15069 case GF_OMP_TARGET_KIND_UPDATE:
43895be5 15070 case GF_OMP_TARGET_KIND_ENTER_DATA:
15071 case GF_OMP_TARGET_KIND_EXIT_DATA:
ca4c3545 15072 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
15073 case GF_OMP_TARGET_KIND_OACC_KERNELS:
15074 case GF_OMP_TARGET_KIND_OACC_UPDATE:
15075 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
2fc5e987 15076 case GF_OMP_TARGET_KIND_OACC_DECLARE:
ca4c3545 15077 data_region = false;
15078 break;
15079 case GF_OMP_TARGET_KIND_DATA:
15080 case GF_OMP_TARGET_KIND_OACC_DATA:
571b3486 15081 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
ca4c3545 15082 data_region = true;
15083 break;
15084 default:
15085 gcc_unreachable ();
15086 }
15087
bc7bff74 15088 clauses = gimple_omp_target_clauses (stmt);
ca4c3545 15089
43895be5 15090 gimple_seq dep_ilist = NULL;
15091 gimple_seq dep_olist = NULL;
15092 if (find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
15093 {
15094 push_gimplify_context ();
15095 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
15096 lower_depend_clauses (gimple_omp_target_clauses_ptr (stmt),
15097 &dep_ilist, &dep_olist);
15098 has_depend = true;
15099 }
15100
ca4c3545 15101 tgt_bind = NULL;
15102 tgt_body = NULL;
15103 if (offloaded)
bc7bff74 15104 {
1a91d914 15105 tgt_bind = gimple_seq_first_stmt_as_a_bind (gimple_omp_body (stmt));
bc7bff74 15106 tgt_body = gimple_bind_body (tgt_bind);
15107 }
ca4c3545 15108 else if (data_region)
bc7bff74 15109 tgt_body = gimple_omp_body (stmt);
15110 child_fn = ctx->cb.dst_fn;
15111
8a4a28a8 15112 push_gimplify_context ();
b656be3a 15113 fplist = NULL;
bc7bff74 15114
15115 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
15116 switch (OMP_CLAUSE_CODE (c))
15117 {
15118 tree var, x;
15119
15120 default:
15121 break;
15122 case OMP_CLAUSE_MAP:
382ecba7 15123#if CHECKING_P
ca4c3545 15124 /* First check what we're prepared to handle in the following. */
15125 switch (OMP_CLAUSE_MAP_KIND (c))
15126 {
15127 case GOMP_MAP_ALLOC:
15128 case GOMP_MAP_TO:
15129 case GOMP_MAP_FROM:
15130 case GOMP_MAP_TOFROM:
15131 case GOMP_MAP_POINTER:
15132 case GOMP_MAP_TO_PSET:
43895be5 15133 case GOMP_MAP_FORCE_DEALLOC:
15134 case GOMP_MAP_RELEASE:
15135 case GOMP_MAP_ALWAYS_TO:
15136 case GOMP_MAP_ALWAYS_FROM:
15137 case GOMP_MAP_ALWAYS_TOFROM:
15138 case GOMP_MAP_FIRSTPRIVATE_POINTER:
9561765e 15139 case GOMP_MAP_FIRSTPRIVATE_REFERENCE:
43895be5 15140 case GOMP_MAP_STRUCT:
9561765e 15141 case GOMP_MAP_ALWAYS_POINTER:
ca4c3545 15142 break;
15143 case GOMP_MAP_FORCE_ALLOC:
15144 case GOMP_MAP_FORCE_TO:
15145 case GOMP_MAP_FORCE_FROM:
15146 case GOMP_MAP_FORCE_TOFROM:
15147 case GOMP_MAP_FORCE_PRESENT:
ca4c3545 15148 case GOMP_MAP_FORCE_DEVICEPTR:
2fc5e987 15149 case GOMP_MAP_DEVICE_RESIDENT:
15150 case GOMP_MAP_LINK:
ca4c3545 15151 gcc_assert (is_gimple_omp_oacc (stmt));
15152 break;
15153 default:
15154 gcc_unreachable ();
15155 }
15156#endif
15157 /* FALLTHRU */
bc7bff74 15158 case OMP_CLAUSE_TO:
15159 case OMP_CLAUSE_FROM:
b656be3a 15160 oacc_firstprivate:
bc7bff74 15161 var = OMP_CLAUSE_DECL (c);
15162 if (!DECL_P (var))
15163 {
15164 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
43895be5 15165 || (!OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
15166 && (OMP_CLAUSE_MAP_KIND (c)
15167 != GOMP_MAP_FIRSTPRIVATE_POINTER)))
bc7bff74 15168 map_cnt++;
15169 continue;
15170 }
15171
15172 if (DECL_SIZE (var)
15173 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
15174 {
15175 tree var2 = DECL_VALUE_EXPR (var);
15176 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
15177 var2 = TREE_OPERAND (var2, 0);
15178 gcc_assert (DECL_P (var2));
15179 var = var2;
15180 }
15181
43895be5 15182 if (offloaded
b656be3a 15183 && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
9561765e 15184 && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
15185 || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_REFERENCE))
43895be5 15186 {
15187 if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
15188 {
15189 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx))
15190 && varpool_node::get_create (var)->offloadable)
15191 continue;
15192
15193 tree type = build_pointer_type (TREE_TYPE (var));
15194 tree new_var = lookup_decl (var, ctx);
15195 x = create_tmp_var_raw (type, get_name (new_var));
15196 gimple_add_tmp_var (x);
15197 x = build_simple_mem_ref (x);
15198 SET_DECL_VALUE_EXPR (new_var, x);
15199 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15200 }
15201 continue;
15202 }
15203
bc7bff74 15204 if (!maybe_lookup_field (var, ctx))
15205 continue;
15206
ca4c3545 15207 if (offloaded)
bc7bff74 15208 {
15209 x = build_receiver_ref (var, true, ctx);
15210 tree new_var = lookup_decl (var, ctx);
43895be5 15211
b656be3a 15212 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
15213 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
bc7bff74 15214 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
15215 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
15216 x = build_simple_mem_ref (x);
b656be3a 15217 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
15218 {
15219 gcc_assert (is_gimple_omp_oacc (ctx->stmt));
15220 if (is_reference (new_var))
15221 {
15222 /* Create a local object to hold the instance
15223 value. */
15224 tree type = TREE_TYPE (TREE_TYPE (new_var));
15225 const char *id = IDENTIFIER_POINTER (DECL_NAME (new_var));
15226 tree inst = create_tmp_var (type, id);
15227 gimplify_assign (inst, fold_indirect_ref (x), &fplist);
15228 x = build_fold_addr_expr (inst);
15229 }
15230 gimplify_assign (new_var, x, &fplist);
15231 }
15232 else if (DECL_P (new_var))
15233 {
15234 SET_DECL_VALUE_EXPR (new_var, x);
15235 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15236 }
15237 else
15238 gcc_unreachable ();
bc7bff74 15239 }
15240 map_cnt++;
43895be5 15241 break;
15242
15243 case OMP_CLAUSE_FIRSTPRIVATE:
b656be3a 15244 if (is_oacc_parallel (ctx))
15245 goto oacc_firstprivate;
43895be5 15246 map_cnt++;
15247 var = OMP_CLAUSE_DECL (c);
15248 if (!is_reference (var)
15249 && !is_gimple_reg_type (TREE_TYPE (var)))
15250 {
15251 tree new_var = lookup_decl (var, ctx);
15252 if (is_variable_sized (var))
15253 {
15254 tree pvar = DECL_VALUE_EXPR (var);
15255 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15256 pvar = TREE_OPERAND (pvar, 0);
15257 gcc_assert (DECL_P (pvar));
15258 tree new_pvar = lookup_decl (pvar, ctx);
15259 x = build_fold_indirect_ref (new_pvar);
15260 TREE_THIS_NOTRAP (x) = 1;
15261 }
15262 else
15263 x = build_receiver_ref (var, true, ctx);
15264 SET_DECL_VALUE_EXPR (new_var, x);
15265 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15266 }
15267 break;
15268
15269 case OMP_CLAUSE_PRIVATE:
b656be3a 15270 if (is_gimple_omp_oacc (ctx->stmt))
15271 break;
43895be5 15272 var = OMP_CLAUSE_DECL (c);
15273 if (is_variable_sized (var))
15274 {
15275 tree new_var = lookup_decl (var, ctx);
15276 tree pvar = DECL_VALUE_EXPR (var);
15277 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15278 pvar = TREE_OPERAND (pvar, 0);
15279 gcc_assert (DECL_P (pvar));
15280 tree new_pvar = lookup_decl (pvar, ctx);
15281 x = build_fold_indirect_ref (new_pvar);
15282 TREE_THIS_NOTRAP (x) = 1;
15283 SET_DECL_VALUE_EXPR (new_var, x);
15284 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15285 }
15286 break;
15287
15288 case OMP_CLAUSE_USE_DEVICE_PTR:
15289 case OMP_CLAUSE_IS_DEVICE_PTR:
15290 var = OMP_CLAUSE_DECL (c);
15291 map_cnt++;
15292 if (is_variable_sized (var))
15293 {
15294 tree new_var = lookup_decl (var, ctx);
15295 tree pvar = DECL_VALUE_EXPR (var);
15296 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15297 pvar = TREE_OPERAND (pvar, 0);
15298 gcc_assert (DECL_P (pvar));
15299 tree new_pvar = lookup_decl (pvar, ctx);
15300 x = build_fold_indirect_ref (new_pvar);
15301 TREE_THIS_NOTRAP (x) = 1;
15302 SET_DECL_VALUE_EXPR (new_var, x);
15303 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15304 }
15305 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
15306 {
15307 tree new_var = lookup_decl (var, ctx);
15308 tree type = build_pointer_type (TREE_TYPE (var));
15309 x = create_tmp_var_raw (type, get_name (new_var));
15310 gimple_add_tmp_var (x);
15311 x = build_simple_mem_ref (x);
15312 SET_DECL_VALUE_EXPR (new_var, x);
15313 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15314 }
15315 break;
bc7bff74 15316 }
15317
ca4c3545 15318 if (offloaded)
bc7bff74 15319 {
15320 target_nesting_level++;
15321 lower_omp (&tgt_body, ctx);
15322 target_nesting_level--;
15323 }
ca4c3545 15324 else if (data_region)
bc7bff74 15325 lower_omp (&tgt_body, ctx);
15326
ca4c3545 15327 if (offloaded)
bc7bff74 15328 {
15329 /* Declare all the variables created by mapping and the variables
15330 declared in the scope of the target body. */
15331 record_vars_into (ctx->block_vars, child_fn);
15332 record_vars_into (gimple_bind_vars (tgt_bind), child_fn);
15333 }
15334
15335 olist = NULL;
15336 ilist = NULL;
15337 if (ctx->record_type)
15338 {
15339 ctx->sender_decl
15340 = create_tmp_var (ctx->record_type, ".omp_data_arr");
15341 DECL_NAMELESS (ctx->sender_decl) = 1;
15342 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
15343 t = make_tree_vec (3);
15344 TREE_VEC_ELT (t, 0) = ctx->sender_decl;
15345 TREE_VEC_ELT (t, 1)
15346 = create_tmp_var (build_array_type_nelts (size_type_node, map_cnt),
15347 ".omp_data_sizes");
15348 DECL_NAMELESS (TREE_VEC_ELT (t, 1)) = 1;
15349 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 1)) = 1;
15350 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 1;
43895be5 15351 tree tkind_type = short_unsigned_type_node;
15352 int talign_shift = 8;
bc7bff74 15353 TREE_VEC_ELT (t, 2)
ca4c3545 15354 = create_tmp_var (build_array_type_nelts (tkind_type, map_cnt),
bc7bff74 15355 ".omp_data_kinds");
15356 DECL_NAMELESS (TREE_VEC_ELT (t, 2)) = 1;
15357 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 2)) = 1;
15358 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 1;
15359 gimple_omp_target_set_data_arg (stmt, t);
15360
15361 vec<constructor_elt, va_gc> *vsize;
15362 vec<constructor_elt, va_gc> *vkind;
15363 vec_alloc (vsize, map_cnt);
15364 vec_alloc (vkind, map_cnt);
15365 unsigned int map_idx = 0;
15366
15367 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
15368 switch (OMP_CLAUSE_CODE (c))
15369 {
43895be5 15370 tree ovar, nc, s, purpose, var, x, type;
15371 unsigned int talign;
bc7bff74 15372
15373 default:
15374 break;
b656be3a 15375
bc7bff74 15376 case OMP_CLAUSE_MAP:
15377 case OMP_CLAUSE_TO:
15378 case OMP_CLAUSE_FROM:
b656be3a 15379 oacc_firstprivate_map:
bc7bff74 15380 nc = c;
15381 ovar = OMP_CLAUSE_DECL (c);
43895be5 15382 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
9561765e 15383 && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
15384 || (OMP_CLAUSE_MAP_KIND (c)
15385 == GOMP_MAP_FIRSTPRIVATE_REFERENCE)))
43895be5 15386 break;
bc7bff74 15387 if (!DECL_P (ovar))
15388 {
15389 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
15390 && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
15391 {
15392 gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c))
15393 == get_base_address (ovar));
15394 nc = OMP_CLAUSE_CHAIN (c);
15395 ovar = OMP_CLAUSE_DECL (nc);
15396 }
15397 else
15398 {
15399 tree x = build_sender_ref (ovar, ctx);
15400 tree v
15401 = build_fold_addr_expr_with_type (ovar, ptr_type_node);
15402 gimplify_assign (x, v, &ilist);
15403 nc = NULL_TREE;
15404 }
15405 }
15406 else
15407 {
15408 if (DECL_SIZE (ovar)
15409 && TREE_CODE (DECL_SIZE (ovar)) != INTEGER_CST)
15410 {
15411 tree ovar2 = DECL_VALUE_EXPR (ovar);
15412 gcc_assert (TREE_CODE (ovar2) == INDIRECT_REF);
15413 ovar2 = TREE_OPERAND (ovar2, 0);
15414 gcc_assert (DECL_P (ovar2));
15415 ovar = ovar2;
15416 }
9561765e 15417 if (!maybe_lookup_field (ovar, ctx))
bc7bff74 15418 continue;
15419 }
15420
43895be5 15421 talign = TYPE_ALIGN_UNIT (TREE_TYPE (ovar));
4f3b8d78 15422 if (DECL_P (ovar) && DECL_ALIGN_UNIT (ovar) > talign)
15423 talign = DECL_ALIGN_UNIT (ovar);
bc7bff74 15424 if (nc)
15425 {
43895be5 15426 var = lookup_decl_in_outer_ctx (ovar, ctx);
9561765e 15427 x = build_sender_ref (ovar, ctx);
abe55632 15428
15429 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
b656be3a 15430 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
15431 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
15432 && TREE_CODE (TREE_TYPE (ovar)) == ARRAY_TYPE)
bc7bff74 15433 {
ca4c3545 15434 gcc_assert (offloaded);
bc7bff74 15435 tree avar
f9e245b2 15436 = create_tmp_var (TREE_TYPE (TREE_TYPE (x)));
bc7bff74 15437 mark_addressable (avar);
15438 gimplify_assign (avar, build_fold_addr_expr (var), &ilist);
4f3b8d78 15439 talign = DECL_ALIGN_UNIT (avar);
bc7bff74 15440 avar = build_fold_addr_expr (avar);
15441 gimplify_assign (x, avar, &ilist);
15442 }
b656be3a 15443 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
15444 {
15445 gcc_assert (is_gimple_omp_oacc (ctx->stmt));
15446 if (!is_reference (var))
15447 var = build_fold_addr_expr (var);
15448 else
15449 talign = TYPE_ALIGN_UNIT (TREE_TYPE (TREE_TYPE (ovar)));
15450 gimplify_assign (x, var, &ilist);
15451 }
bc7bff74 15452 else if (is_gimple_reg (var))
15453 {
ca4c3545 15454 gcc_assert (offloaded);
f9e245b2 15455 tree avar = create_tmp_var (TREE_TYPE (var));
bc7bff74 15456 mark_addressable (avar);
ca4c3545 15457 enum gomp_map_kind map_kind = OMP_CLAUSE_MAP_KIND (c);
15458 if (GOMP_MAP_COPY_TO_P (map_kind)
15459 || map_kind == GOMP_MAP_POINTER
15460 || map_kind == GOMP_MAP_TO_PSET
15461 || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
bc7bff74 15462 gimplify_assign (avar, var, &ilist);
15463 avar = build_fold_addr_expr (avar);
15464 gimplify_assign (x, avar, &ilist);
ca4c3545 15465 if ((GOMP_MAP_COPY_FROM_P (map_kind)
15466 || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
bc7bff74 15467 && !TYPE_READONLY (TREE_TYPE (var)))
15468 {
43895be5 15469 x = unshare_expr (x);
bc7bff74 15470 x = build_simple_mem_ref (x);
15471 gimplify_assign (var, x, &olist);
15472 }
15473 }
15474 else
15475 {
15476 var = build_fold_addr_expr (var);
15477 gimplify_assign (x, var, &ilist);
15478 }
15479 }
b656be3a 15480 s = NULL_TREE;
15481 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
15482 {
15483 gcc_checking_assert (is_gimple_omp_oacc (ctx->stmt));
15484 s = TREE_TYPE (ovar);
15485 if (TREE_CODE (s) == REFERENCE_TYPE)
15486 s = TREE_TYPE (s);
15487 s = TYPE_SIZE_UNIT (s);
15488 }
15489 else
15490 s = OMP_CLAUSE_SIZE (c);
bc7bff74 15491 if (s == NULL_TREE)
15492 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
15493 s = fold_convert (size_type_node, s);
43895be5 15494 purpose = size_int (map_idx++);
bc7bff74 15495 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
15496 if (TREE_CODE (s) != INTEGER_CST)
15497 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
15498
43895be5 15499 unsigned HOST_WIDE_INT tkind, tkind_zero;
bc7bff74 15500 switch (OMP_CLAUSE_CODE (c))
15501 {
15502 case OMP_CLAUSE_MAP:
15503 tkind = OMP_CLAUSE_MAP_KIND (c);
43895be5 15504 tkind_zero = tkind;
15505 if (OMP_CLAUSE_MAP_MAYBE_ZERO_LENGTH_ARRAY_SECTION (c))
15506 switch (tkind)
15507 {
15508 case GOMP_MAP_ALLOC:
15509 case GOMP_MAP_TO:
15510 case GOMP_MAP_FROM:
15511 case GOMP_MAP_TOFROM:
15512 case GOMP_MAP_ALWAYS_TO:
15513 case GOMP_MAP_ALWAYS_FROM:
15514 case GOMP_MAP_ALWAYS_TOFROM:
15515 case GOMP_MAP_RELEASE:
15516 tkind_zero = GOMP_MAP_ZERO_LEN_ARRAY_SECTION;
15517 break;
15518 case GOMP_MAP_DELETE:
15519 tkind_zero = GOMP_MAP_DELETE_ZERO_LEN_ARRAY_SECTION;
15520 default:
15521 break;
15522 }
15523 if (tkind_zero != tkind)
15524 {
15525 if (integer_zerop (s))
15526 tkind = tkind_zero;
15527 else if (integer_nonzerop (s))
15528 tkind_zero = tkind;
15529 }
bc7bff74 15530 break;
b656be3a 15531 case OMP_CLAUSE_FIRSTPRIVATE:
15532 gcc_checking_assert (is_gimple_omp_oacc (ctx->stmt));
15533 tkind = GOMP_MAP_TO;
15534 tkind_zero = tkind;
15535 break;
bc7bff74 15536 case OMP_CLAUSE_TO:
ca4c3545 15537 tkind = GOMP_MAP_TO;
43895be5 15538 tkind_zero = tkind;
bc7bff74 15539 break;
15540 case OMP_CLAUSE_FROM:
ca4c3545 15541 tkind = GOMP_MAP_FROM;
43895be5 15542 tkind_zero = tkind;
bc7bff74 15543 break;
15544 default:
15545 gcc_unreachable ();
15546 }
ca4c3545 15547 gcc_checking_assert (tkind
15548 < (HOST_WIDE_INT_C (1U) << talign_shift));
43895be5 15549 gcc_checking_assert (tkind_zero
15550 < (HOST_WIDE_INT_C (1U) << talign_shift));
bc7bff74 15551 talign = ceil_log2 (talign);
ca4c3545 15552 tkind |= talign << talign_shift;
43895be5 15553 tkind_zero |= talign << talign_shift;
ca4c3545 15554 gcc_checking_assert (tkind
15555 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
43895be5 15556 gcc_checking_assert (tkind_zero
15557 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
15558 if (tkind == tkind_zero)
15559 x = build_int_cstu (tkind_type, tkind);
15560 else
15561 {
15562 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 0;
15563 x = build3 (COND_EXPR, tkind_type,
15564 fold_build2 (EQ_EXPR, boolean_type_node,
15565 unshare_expr (s), size_zero_node),
15566 build_int_cstu (tkind_type, tkind_zero),
15567 build_int_cstu (tkind_type, tkind));
15568 }
15569 CONSTRUCTOR_APPEND_ELT (vkind, purpose, x);
bc7bff74 15570 if (nc && nc != c)
15571 c = nc;
43895be5 15572 break;
15573
15574 case OMP_CLAUSE_FIRSTPRIVATE:
b656be3a 15575 if (is_oacc_parallel (ctx))
15576 goto oacc_firstprivate_map;
43895be5 15577 ovar = OMP_CLAUSE_DECL (c);
15578 if (is_reference (ovar))
15579 talign = TYPE_ALIGN_UNIT (TREE_TYPE (TREE_TYPE (ovar)));
15580 else
15581 talign = DECL_ALIGN_UNIT (ovar);
15582 var = lookup_decl_in_outer_ctx (ovar, ctx);
15583 x = build_sender_ref (ovar, ctx);
15584 tkind = GOMP_MAP_FIRSTPRIVATE;
15585 type = TREE_TYPE (ovar);
15586 if (is_reference (ovar))
15587 type = TREE_TYPE (type);
15588 bool use_firstprivate_int, force_addr;
15589 use_firstprivate_int = false;
15590 force_addr = false;
15591 if ((INTEGRAL_TYPE_P (type)
15592 && TYPE_PRECISION (type) <= POINTER_SIZE)
15593 || TREE_CODE (type) == POINTER_TYPE)
15594 use_firstprivate_int = true;
15595 if (has_depend)
15596 {
15597 if (is_reference (var))
15598 use_firstprivate_int = false;
15599 else if (is_gimple_reg (var))
15600 {
15601 if (DECL_HAS_VALUE_EXPR_P (var))
15602 {
15603 tree v = get_base_address (var);
15604 if (DECL_P (v) && TREE_ADDRESSABLE (v))
15605 {
15606 use_firstprivate_int = false;
15607 force_addr = true;
15608 }
15609 else
15610 switch (TREE_CODE (v))
15611 {
15612 case INDIRECT_REF:
15613 case MEM_REF:
15614 use_firstprivate_int = false;
15615 force_addr = true;
15616 break;
15617 default:
15618 break;
15619 }
15620 }
15621 }
15622 else
15623 use_firstprivate_int = false;
15624 }
15625 if (use_firstprivate_int)
15626 {
15627 tkind = GOMP_MAP_FIRSTPRIVATE_INT;
15628 tree t = var;
15629 if (is_reference (var))
15630 t = build_simple_mem_ref (var);
15631 if (TREE_CODE (type) != POINTER_TYPE)
15632 t = fold_convert (pointer_sized_int_node, t);
15633 t = fold_convert (TREE_TYPE (x), t);
15634 gimplify_assign (x, t, &ilist);
15635 }
15636 else if (is_reference (var))
15637 gimplify_assign (x, var, &ilist);
15638 else if (!force_addr && is_gimple_reg (var))
15639 {
15640 tree avar = create_tmp_var (TREE_TYPE (var));
15641 mark_addressable (avar);
15642 gimplify_assign (avar, var, &ilist);
15643 avar = build_fold_addr_expr (avar);
15644 gimplify_assign (x, avar, &ilist);
15645 }
15646 else
15647 {
15648 var = build_fold_addr_expr (var);
15649 gimplify_assign (x, var, &ilist);
15650 }
15651 if (tkind == GOMP_MAP_FIRSTPRIVATE_INT)
15652 s = size_int (0);
15653 else if (is_reference (var))
15654 s = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (ovar)));
15655 else
15656 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
15657 s = fold_convert (size_type_node, s);
15658 purpose = size_int (map_idx++);
15659 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
15660 if (TREE_CODE (s) != INTEGER_CST)
15661 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
15662
15663 gcc_checking_assert (tkind
15664 < (HOST_WIDE_INT_C (1U) << talign_shift));
15665 talign = ceil_log2 (talign);
15666 tkind |= talign << talign_shift;
15667 gcc_checking_assert (tkind
15668 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
15669 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
15670 build_int_cstu (tkind_type, tkind));
15671 break;
15672
15673 case OMP_CLAUSE_USE_DEVICE_PTR:
15674 case OMP_CLAUSE_IS_DEVICE_PTR:
15675 ovar = OMP_CLAUSE_DECL (c);
15676 var = lookup_decl_in_outer_ctx (ovar, ctx);
15677 x = build_sender_ref (ovar, ctx);
9d5fd7c6 15678 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_PTR)
43895be5 15679 tkind = GOMP_MAP_USE_DEVICE_PTR;
15680 else
15681 tkind = GOMP_MAP_FIRSTPRIVATE_INT;
15682 type = TREE_TYPE (ovar);
15683 if (TREE_CODE (type) == ARRAY_TYPE)
15684 var = build_fold_addr_expr (var);
15685 else
15686 {
15687 if (is_reference (ovar))
15688 {
15689 type = TREE_TYPE (type);
15690 if (TREE_CODE (type) != ARRAY_TYPE)
15691 var = build_simple_mem_ref (var);
15692 var = fold_convert (TREE_TYPE (x), var);
15693 }
15694 }
15695 gimplify_assign (x, var, &ilist);
15696 s = size_int (0);
15697 purpose = size_int (map_idx++);
15698 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
15699 gcc_checking_assert (tkind
15700 < (HOST_WIDE_INT_C (1U) << talign_shift));
15701 gcc_checking_assert (tkind
15702 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
15703 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
15704 build_int_cstu (tkind_type, tkind));
15705 break;
bc7bff74 15706 }
15707
15708 gcc_assert (map_idx == map_cnt);
15709
15710 DECL_INITIAL (TREE_VEC_ELT (t, 1))
15711 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)), vsize);
15712 DECL_INITIAL (TREE_VEC_ELT (t, 2))
15713 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 2)), vkind);
43895be5 15714 for (int i = 1; i <= 2; i++)
15715 if (!TREE_STATIC (TREE_VEC_ELT (t, i)))
15716 {
15717 gimple_seq initlist = NULL;
15718 force_gimple_operand (build1 (DECL_EXPR, void_type_node,
15719 TREE_VEC_ELT (t, i)),
15720 &initlist, true, NULL_TREE);
15721 gimple_seq_add_seq (&ilist, initlist);
15722
15723 tree clobber = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, i)),
15724 NULL);
15725 TREE_THIS_VOLATILE (clobber) = 1;
15726 gimple_seq_add_stmt (&olist,
15727 gimple_build_assign (TREE_VEC_ELT (t, i),
15728 clobber));
15729 }
bc7bff74 15730
15731 tree clobber = build_constructor (ctx->record_type, NULL);
15732 TREE_THIS_VOLATILE (clobber) = 1;
15733 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
15734 clobber));
15735 }
15736
15737 /* Once all the expansions are done, sequence all the different
15738 fragments inside gimple_omp_body. */
15739
15740 new_body = NULL;
15741
ca4c3545 15742 if (offloaded
15743 && ctx->record_type)
bc7bff74 15744 {
15745 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
15746 /* fixup_child_record_type might have changed receiver_decl's type. */
15747 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
15748 gimple_seq_add_stmt (&new_body,
15749 gimple_build_assign (ctx->receiver_decl, t));
15750 }
b656be3a 15751 gimple_seq_add_seq (&new_body, fplist);
bc7bff74 15752
43895be5 15753 if (offloaded || data_region)
bc7bff74 15754 {
43895be5 15755 tree prev = NULL_TREE;
15756 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
15757 switch (OMP_CLAUSE_CODE (c))
15758 {
15759 tree var, x;
15760 default:
15761 break;
15762 case OMP_CLAUSE_FIRSTPRIVATE:
b656be3a 15763 if (is_gimple_omp_oacc (ctx->stmt))
15764 break;
43895be5 15765 var = OMP_CLAUSE_DECL (c);
15766 if (is_reference (var)
15767 || is_gimple_reg_type (TREE_TYPE (var)))
15768 {
15769 tree new_var = lookup_decl (var, ctx);
15770 tree type;
15771 type = TREE_TYPE (var);
15772 if (is_reference (var))
15773 type = TREE_TYPE (type);
15774 bool use_firstprivate_int;
15775 use_firstprivate_int = false;
15776 if ((INTEGRAL_TYPE_P (type)
15777 && TYPE_PRECISION (type) <= POINTER_SIZE)
15778 || TREE_CODE (type) == POINTER_TYPE)
15779 use_firstprivate_int = true;
15780 if (has_depend)
15781 {
15782 tree v = lookup_decl_in_outer_ctx (var, ctx);
15783 if (is_reference (v))
15784 use_firstprivate_int = false;
15785 else if (is_gimple_reg (v))
15786 {
15787 if (DECL_HAS_VALUE_EXPR_P (v))
15788 {
15789 v = get_base_address (v);
15790 if (DECL_P (v) && TREE_ADDRESSABLE (v))
15791 use_firstprivate_int = false;
15792 else
15793 switch (TREE_CODE (v))
15794 {
15795 case INDIRECT_REF:
15796 case MEM_REF:
15797 use_firstprivate_int = false;
15798 break;
15799 default:
15800 break;
15801 }
15802 }
15803 }
15804 else
15805 use_firstprivate_int = false;
15806 }
15807 if (use_firstprivate_int)
15808 {
15809 x = build_receiver_ref (var, false, ctx);
15810 if (TREE_CODE (type) != POINTER_TYPE)
15811 x = fold_convert (pointer_sized_int_node, x);
15812 x = fold_convert (type, x);
15813 gimplify_expr (&x, &new_body, NULL, is_gimple_val,
15814 fb_rvalue);
15815 if (is_reference (var))
15816 {
15817 tree v = create_tmp_var_raw (type, get_name (var));
15818 gimple_add_tmp_var (v);
15819 TREE_ADDRESSABLE (v) = 1;
15820 gimple_seq_add_stmt (&new_body,
15821 gimple_build_assign (v, x));
15822 x = build_fold_addr_expr (v);
15823 }
15824 gimple_seq_add_stmt (&new_body,
15825 gimple_build_assign (new_var, x));
15826 }
15827 else
15828 {
15829 x = build_receiver_ref (var, !is_reference (var), ctx);
15830 gimplify_expr (&x, &new_body, NULL, is_gimple_val,
15831 fb_rvalue);
15832 gimple_seq_add_stmt (&new_body,
15833 gimple_build_assign (new_var, x));
15834 }
15835 }
15836 else if (is_variable_sized (var))
15837 {
15838 tree pvar = DECL_VALUE_EXPR (var);
15839 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15840 pvar = TREE_OPERAND (pvar, 0);
15841 gcc_assert (DECL_P (pvar));
15842 tree new_var = lookup_decl (pvar, ctx);
15843 x = build_receiver_ref (var, false, ctx);
15844 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
15845 gimple_seq_add_stmt (&new_body,
15846 gimple_build_assign (new_var, x));
15847 }
15848 break;
15849 case OMP_CLAUSE_PRIVATE:
b656be3a 15850 if (is_gimple_omp_oacc (ctx->stmt))
15851 break;
43895be5 15852 var = OMP_CLAUSE_DECL (c);
15853 if (is_reference (var))
15854 {
15855 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
15856 tree new_var = lookup_decl (var, ctx);
15857 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
15858 if (TREE_CONSTANT (x))
15859 {
15860 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
15861 get_name (var));
15862 gimple_add_tmp_var (x);
15863 TREE_ADDRESSABLE (x) = 1;
15864 x = build_fold_addr_expr_loc (clause_loc, x);
15865 }
15866 else
15867 {
15868 tree atmp
15869 = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
15870 tree rtype = TREE_TYPE (TREE_TYPE (new_var));
15871 tree al = size_int (TYPE_ALIGN (rtype));
15872 x = build_call_expr_loc (clause_loc, atmp, 2, x, al);
15873 }
15874
15875 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
15876 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
15877 gimple_seq_add_stmt (&new_body,
15878 gimple_build_assign (new_var, x));
15879 }
15880 break;
15881 case OMP_CLAUSE_USE_DEVICE_PTR:
15882 case OMP_CLAUSE_IS_DEVICE_PTR:
15883 var = OMP_CLAUSE_DECL (c);
9d5fd7c6 15884 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_PTR)
43895be5 15885 x = build_sender_ref (var, ctx);
15886 else
15887 x = build_receiver_ref (var, false, ctx);
15888 if (is_variable_sized (var))
15889 {
15890 tree pvar = DECL_VALUE_EXPR (var);
15891 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15892 pvar = TREE_OPERAND (pvar, 0);
15893 gcc_assert (DECL_P (pvar));
15894 tree new_var = lookup_decl (pvar, ctx);
15895 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
15896 gimple_seq_add_stmt (&new_body,
15897 gimple_build_assign (new_var, x));
15898 }
15899 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
15900 {
15901 tree new_var = lookup_decl (var, ctx);
15902 new_var = DECL_VALUE_EXPR (new_var);
15903 gcc_assert (TREE_CODE (new_var) == MEM_REF);
15904 new_var = TREE_OPERAND (new_var, 0);
15905 gcc_assert (DECL_P (new_var));
15906 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
15907 gimple_seq_add_stmt (&new_body,
15908 gimple_build_assign (new_var, x));
15909 }
15910 else
15911 {
15912 tree type = TREE_TYPE (var);
15913 tree new_var = lookup_decl (var, ctx);
15914 if (is_reference (var))
15915 {
15916 type = TREE_TYPE (type);
15917 if (TREE_CODE (type) != ARRAY_TYPE)
15918 {
15919 tree v = create_tmp_var_raw (type, get_name (var));
15920 gimple_add_tmp_var (v);
15921 TREE_ADDRESSABLE (v) = 1;
15922 x = fold_convert (type, x);
15923 gimplify_expr (&x, &new_body, NULL, is_gimple_val,
15924 fb_rvalue);
15925 gimple_seq_add_stmt (&new_body,
15926 gimple_build_assign (v, x));
15927 x = build_fold_addr_expr (v);
15928 }
15929 }
15930 x = fold_convert (TREE_TYPE (new_var), x);
15931 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
15932 gimple_seq_add_stmt (&new_body,
15933 gimple_build_assign (new_var, x));
15934 }
15935 break;
15936 }
9561765e 15937 /* Handle GOMP_MAP_FIRSTPRIVATE_{POINTER,REFERENCE} in second pass,
43895be5 15938 so that firstprivate vars holding OMP_CLAUSE_SIZE if needed
15939 are already handled. */
b656be3a 15940 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
43895be5 15941 switch (OMP_CLAUSE_CODE (c))
15942 {
15943 tree var;
15944 default:
15945 break;
15946 case OMP_CLAUSE_MAP:
9561765e 15947 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
15948 || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_REFERENCE)
43895be5 15949 {
15950 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
15951 HOST_WIDE_INT offset = 0;
15952 gcc_assert (prev);
15953 var = OMP_CLAUSE_DECL (c);
15954 if (DECL_P (var)
15955 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
15956 && is_global_var (maybe_lookup_decl_in_outer_ctx (var,
15957 ctx))
15958 && varpool_node::get_create (var)->offloadable)
15959 break;
15960 if (TREE_CODE (var) == INDIRECT_REF
15961 && TREE_CODE (TREE_OPERAND (var, 0)) == COMPONENT_REF)
15962 var = TREE_OPERAND (var, 0);
15963 if (TREE_CODE (var) == COMPONENT_REF)
15964 {
15965 var = get_addr_base_and_unit_offset (var, &offset);
15966 gcc_assert (var != NULL_TREE && DECL_P (var));
15967 }
15968 else if (DECL_SIZE (var)
15969 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
15970 {
15971 tree var2 = DECL_VALUE_EXPR (var);
15972 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
15973 var2 = TREE_OPERAND (var2, 0);
15974 gcc_assert (DECL_P (var2));
15975 var = var2;
15976 }
15977 tree new_var = lookup_decl (var, ctx), x;
15978 tree type = TREE_TYPE (new_var);
15979 bool is_ref;
15980 if (TREE_CODE (OMP_CLAUSE_DECL (c)) == INDIRECT_REF
15981 && (TREE_CODE (TREE_OPERAND (OMP_CLAUSE_DECL (c), 0))
15982 == COMPONENT_REF))
15983 {
15984 type = TREE_TYPE (TREE_OPERAND (OMP_CLAUSE_DECL (c), 0));
15985 is_ref = true;
15986 new_var = build2 (MEM_REF, type,
15987 build_fold_addr_expr (new_var),
15988 build_int_cst (build_pointer_type (type),
15989 offset));
15990 }
15991 else if (TREE_CODE (OMP_CLAUSE_DECL (c)) == COMPONENT_REF)
15992 {
15993 type = TREE_TYPE (OMP_CLAUSE_DECL (c));
15994 is_ref = TREE_CODE (type) == REFERENCE_TYPE;
15995 new_var = build2 (MEM_REF, type,
15996 build_fold_addr_expr (new_var),
15997 build_int_cst (build_pointer_type (type),
15998 offset));
15999 }
16000 else
16001 is_ref = is_reference (var);
9561765e 16002 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_REFERENCE)
16003 is_ref = false;
43895be5 16004 bool ref_to_array = false;
16005 if (is_ref)
16006 {
16007 type = TREE_TYPE (type);
16008 if (TREE_CODE (type) == ARRAY_TYPE)
16009 {
16010 type = build_pointer_type (type);
16011 ref_to_array = true;
16012 }
16013 }
16014 else if (TREE_CODE (type) == ARRAY_TYPE)
16015 {
16016 tree decl2 = DECL_VALUE_EXPR (new_var);
16017 gcc_assert (TREE_CODE (decl2) == MEM_REF);
16018 decl2 = TREE_OPERAND (decl2, 0);
16019 gcc_assert (DECL_P (decl2));
16020 new_var = decl2;
16021 type = TREE_TYPE (new_var);
16022 }
16023 x = build_receiver_ref (OMP_CLAUSE_DECL (prev), false, ctx);
16024 x = fold_convert_loc (clause_loc, type, x);
16025 if (!integer_zerop (OMP_CLAUSE_SIZE (c)))
16026 {
16027 tree bias = OMP_CLAUSE_SIZE (c);
16028 if (DECL_P (bias))
16029 bias = lookup_decl (bias, ctx);
16030 bias = fold_convert_loc (clause_loc, sizetype, bias);
16031 bias = fold_build1_loc (clause_loc, NEGATE_EXPR, sizetype,
16032 bias);
16033 x = fold_build2_loc (clause_loc, POINTER_PLUS_EXPR,
16034 TREE_TYPE (x), x, bias);
16035 }
16036 if (ref_to_array)
16037 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
16038 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16039 if (is_ref && !ref_to_array)
16040 {
16041 tree t = create_tmp_var_raw (type, get_name (var));
16042 gimple_add_tmp_var (t);
16043 TREE_ADDRESSABLE (t) = 1;
16044 gimple_seq_add_stmt (&new_body,
16045 gimple_build_assign (t, x));
16046 x = build_fold_addr_expr_loc (clause_loc, t);
16047 }
16048 gimple_seq_add_stmt (&new_body,
16049 gimple_build_assign (new_var, x));
16050 prev = NULL_TREE;
16051 }
16052 else if (OMP_CLAUSE_CHAIN (c)
16053 && OMP_CLAUSE_CODE (OMP_CLAUSE_CHAIN (c))
16054 == OMP_CLAUSE_MAP
9561765e 16055 && (OMP_CLAUSE_MAP_KIND (OMP_CLAUSE_CHAIN (c))
16056 == GOMP_MAP_FIRSTPRIVATE_POINTER
16057 || (OMP_CLAUSE_MAP_KIND (OMP_CLAUSE_CHAIN (c))
16058 == GOMP_MAP_FIRSTPRIVATE_REFERENCE)))
43895be5 16059 prev = c;
16060 break;
16061 case OMP_CLAUSE_PRIVATE:
16062 var = OMP_CLAUSE_DECL (c);
16063 if (is_variable_sized (var))
16064 {
16065 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
16066 tree new_var = lookup_decl (var, ctx);
16067 tree pvar = DECL_VALUE_EXPR (var);
16068 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
16069 pvar = TREE_OPERAND (pvar, 0);
16070 gcc_assert (DECL_P (pvar));
16071 tree new_pvar = lookup_decl (pvar, ctx);
16072 tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
16073 tree al = size_int (DECL_ALIGN (var));
16074 tree x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
16075 x = build_call_expr_loc (clause_loc, atmp, 2, x, al);
16076 x = fold_convert_loc (clause_loc, TREE_TYPE (new_pvar), x);
16077 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16078 gimple_seq_add_stmt (&new_body,
16079 gimple_build_assign (new_pvar, x));
16080 }
16081 break;
16082 }
2eab8648 16083
641a0fa1 16084 gimple_seq fork_seq = NULL;
16085 gimple_seq join_seq = NULL;
16086
16087 if (is_oacc_parallel (ctx))
16088 {
16089 /* If there are reductions on the offloaded region itself, treat
16090 them as a dummy GANG loop. */
16091 tree level = build_int_cst (integer_type_node, GOMP_DIM_GANG);
16092
16093 lower_oacc_reductions (gimple_location (ctx->stmt), clauses, level,
16094 false, NULL, NULL, &fork_seq, &join_seq, ctx);
16095 }
16096
16097 gimple_seq_add_seq (&new_body, fork_seq);
bc7bff74 16098 gimple_seq_add_seq (&new_body, tgt_body);
641a0fa1 16099 gimple_seq_add_seq (&new_body, join_seq);
2eab8648 16100
43895be5 16101 if (offloaded)
16102 new_body = maybe_catch_exception (new_body);
2eab8648 16103
bc7bff74 16104 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
16105 gimple_omp_set_body (stmt, new_body);
16106 }
16107
16108 bind = gimple_build_bind (NULL, NULL,
16109 tgt_bind ? gimple_bind_block (tgt_bind)
16110 : NULL_TREE);
43895be5 16111 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
e3a19533 16112 gimple_bind_add_seq (bind, ilist);
16113 gimple_bind_add_stmt (bind, stmt);
16114 gimple_bind_add_seq (bind, olist);
773c5ba7 16115
75a70cf9 16116 pop_gimplify_context (NULL);
43895be5 16117
16118 if (dep_bind)
16119 {
16120 gimple_bind_add_seq (dep_bind, dep_ilist);
16121 gimple_bind_add_stmt (dep_bind, bind);
16122 gimple_bind_add_seq (dep_bind, dep_olist);
16123 pop_gimplify_context (dep_bind);
16124 }
773c5ba7 16125}
16126
bc7bff74 16127/* Expand code for an OpenMP teams directive. */
16128
16129static void
16130lower_omp_teams (gimple_stmt_iterator *gsi_p, omp_context *ctx)
16131{
1a91d914 16132 gomp_teams *teams_stmt = as_a <gomp_teams *> (gsi_stmt (*gsi_p));
8a4a28a8 16133 push_gimplify_context ();
bc7bff74 16134
16135 tree block = make_node (BLOCK);
1a91d914 16136 gbind *bind = gimple_build_bind (NULL, NULL, block);
bc7bff74 16137 gsi_replace (gsi_p, bind, true);
16138 gimple_seq bind_body = NULL;
16139 gimple_seq dlist = NULL;
16140 gimple_seq olist = NULL;
16141
16142 tree num_teams = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
16143 OMP_CLAUSE_NUM_TEAMS);
16144 if (num_teams == NULL_TREE)
16145 num_teams = build_int_cst (unsigned_type_node, 0);
16146 else
16147 {
16148 num_teams = OMP_CLAUSE_NUM_TEAMS_EXPR (num_teams);
16149 num_teams = fold_convert (unsigned_type_node, num_teams);
16150 gimplify_expr (&num_teams, &bind_body, NULL, is_gimple_val, fb_rvalue);
16151 }
16152 tree thread_limit = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
16153 OMP_CLAUSE_THREAD_LIMIT);
16154 if (thread_limit == NULL_TREE)
16155 thread_limit = build_int_cst (unsigned_type_node, 0);
16156 else
16157 {
16158 thread_limit = OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit);
16159 thread_limit = fold_convert (unsigned_type_node, thread_limit);
16160 gimplify_expr (&thread_limit, &bind_body, NULL, is_gimple_val,
16161 fb_rvalue);
16162 }
16163
16164 lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt),
16165 &bind_body, &dlist, ctx, NULL);
16166 lower_omp (gimple_omp_body_ptr (teams_stmt), ctx);
16167 lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt), &olist, ctx);
16168 gimple_seq_add_stmt (&bind_body, teams_stmt);
16169
16170 location_t loc = gimple_location (teams_stmt);
16171 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TEAMS);
42acab1c 16172 gimple *call = gimple_build_call (decl, 2, num_teams, thread_limit);
bc7bff74 16173 gimple_set_location (call, loc);
16174 gimple_seq_add_stmt (&bind_body, call);
16175
16176 gimple_seq_add_seq (&bind_body, gimple_omp_body (teams_stmt));
16177 gimple_omp_set_body (teams_stmt, NULL);
16178 gimple_seq_add_seq (&bind_body, olist);
16179 gimple_seq_add_seq (&bind_body, dlist);
16180 gimple_seq_add_stmt (&bind_body, gimple_build_omp_return (true));
16181 gimple_bind_set_body (bind, bind_body);
16182
16183 pop_gimplify_context (bind);
16184
16185 gimple_bind_append_vars (bind, ctx->block_vars);
16186 BLOCK_VARS (block) = ctx->block_vars;
16187 if (BLOCK_VARS (block))
16188 TREE_USED (block) = 1;
16189}
16190
16191
a4890dc9 16192/* Callback for lower_omp_1. Return non-NULL if *tp needs to be
75a70cf9 16193 regimplified. If DATA is non-NULL, lower_omp_1 is outside
ca4c3545 16194 of OMP context, but with task_shared_vars set. */
46515c92 16195
16196static tree
75a70cf9 16197lower_omp_regimplify_p (tree *tp, int *walk_subtrees,
16198 void *data)
46515c92 16199{
a4890dc9 16200 tree t = *tp;
46515c92 16201
a4890dc9 16202 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
75a70cf9 16203 if (TREE_CODE (t) == VAR_DECL && data == NULL && DECL_HAS_VALUE_EXPR_P (t))
9f49e155 16204 return t;
16205
16206 if (task_shared_vars
16207 && DECL_P (t)
16208 && bitmap_bit_p (task_shared_vars, DECL_UID (t)))
a4890dc9 16209 return t;
46515c92 16210
a4890dc9 16211 /* If a global variable has been privatized, TREE_CONSTANT on
16212 ADDR_EXPR might be wrong. */
75a70cf9 16213 if (data == NULL && TREE_CODE (t) == ADDR_EXPR)
a4890dc9 16214 recompute_tree_invariant_for_addr_expr (t);
46515c92 16215
43895be5 16216 *walk_subtrees = !IS_TYPE_OR_DECL_P (t);
16217 return NULL_TREE;
16218}
16219
16220/* Data to be communicated between lower_omp_regimplify_operands and
16221 lower_omp_regimplify_operands_p. */
16222
16223struct lower_omp_regimplify_operands_data
16224{
16225 omp_context *ctx;
16226 vec<tree> *decls;
16227};
16228
16229/* Helper function for lower_omp_regimplify_operands. Find
16230 omp_member_access_dummy_var vars and adjust temporarily their
16231 DECL_VALUE_EXPRs if needed. */
16232
16233static tree
16234lower_omp_regimplify_operands_p (tree *tp, int *walk_subtrees,
16235 void *data)
16236{
16237 tree t = omp_member_access_dummy_var (*tp);
16238 if (t)
16239 {
16240 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
16241 lower_omp_regimplify_operands_data *ldata
16242 = (lower_omp_regimplify_operands_data *) wi->info;
16243 tree o = maybe_lookup_decl (t, ldata->ctx);
16244 if (o != t)
16245 {
16246 ldata->decls->safe_push (DECL_VALUE_EXPR (*tp));
16247 ldata->decls->safe_push (*tp);
16248 tree v = unshare_and_remap (DECL_VALUE_EXPR (*tp), t, o);
16249 SET_DECL_VALUE_EXPR (*tp, v);
16250 }
16251 }
16252 *walk_subtrees = !IS_TYPE_OR_DECL_P (*tp);
a4890dc9 16253 return NULL_TREE;
46515c92 16254}
773c5ba7 16255
43895be5 16256/* Wrapper around gimple_regimplify_operands that adjusts DECL_VALUE_EXPRs
16257 of omp_member_access_dummy_var vars during regimplification. */
16258
16259static void
16260lower_omp_regimplify_operands (omp_context *ctx, gimple *stmt,
16261 gimple_stmt_iterator *gsi_p)
16262{
16263 auto_vec<tree, 10> decls;
16264 if (ctx)
16265 {
16266 struct walk_stmt_info wi;
16267 memset (&wi, '\0', sizeof (wi));
16268 struct lower_omp_regimplify_operands_data data;
16269 data.ctx = ctx;
16270 data.decls = &decls;
16271 wi.info = &data;
16272 walk_gimple_op (stmt, lower_omp_regimplify_operands_p, &wi);
16273 }
16274 gimple_regimplify_operands (stmt, gsi_p);
16275 while (!decls.is_empty ())
16276 {
16277 tree t = decls.pop ();
16278 tree v = decls.pop ();
16279 SET_DECL_VALUE_EXPR (t, v);
16280 }
16281}
16282
a4890dc9 16283static void
75a70cf9 16284lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
1e8e9920 16285{
42acab1c 16286 gimple *stmt = gsi_stmt (*gsi_p);
75a70cf9 16287 struct walk_stmt_info wi;
1a91d914 16288 gcall *call_stmt;
1e8e9920 16289
75a70cf9 16290 if (gimple_has_location (stmt))
16291 input_location = gimple_location (stmt);
a4890dc9 16292
75a70cf9 16293 if (task_shared_vars)
16294 memset (&wi, '\0', sizeof (wi));
a4890dc9 16295
773c5ba7 16296 /* If we have issued syntax errors, avoid doing any heavy lifting.
ca4c3545 16297 Just replace the OMP directives with a NOP to avoid
773c5ba7 16298 confusing RTL expansion. */
852f689e 16299 if (seen_error () && is_gimple_omp (stmt))
773c5ba7 16300 {
75a70cf9 16301 gsi_replace (gsi_p, gimple_build_nop (), true);
a4890dc9 16302 return;
773c5ba7 16303 }
16304
75a70cf9 16305 switch (gimple_code (stmt))
1e8e9920 16306 {
75a70cf9 16307 case GIMPLE_COND:
1a91d914 16308 {
16309 gcond *cond_stmt = as_a <gcond *> (stmt);
16310 if ((ctx || task_shared_vars)
16311 && (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
16312 lower_omp_regimplify_p,
16313 ctx ? NULL : &wi, NULL)
16314 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
16315 lower_omp_regimplify_p,
16316 ctx ? NULL : &wi, NULL)))
43895be5 16317 lower_omp_regimplify_operands (ctx, cond_stmt, gsi_p);
1a91d914 16318 }
a4890dc9 16319 break;
75a70cf9 16320 case GIMPLE_CATCH:
1a91d914 16321 lower_omp (gimple_catch_handler_ptr (as_a <gcatch *> (stmt)), ctx);
a4890dc9 16322 break;
75a70cf9 16323 case GIMPLE_EH_FILTER:
e3a19533 16324 lower_omp (gimple_eh_filter_failure_ptr (stmt), ctx);
a4890dc9 16325 break;
75a70cf9 16326 case GIMPLE_TRY:
e3a19533 16327 lower_omp (gimple_try_eval_ptr (stmt), ctx);
16328 lower_omp (gimple_try_cleanup_ptr (stmt), ctx);
a4890dc9 16329 break;
35215227 16330 case GIMPLE_TRANSACTION:
1a91d914 16331 lower_omp (gimple_transaction_body_ptr (
16332 as_a <gtransaction *> (stmt)),
16333 ctx);
35215227 16334 break;
75a70cf9 16335 case GIMPLE_BIND:
1a91d914 16336 lower_omp (gimple_bind_body_ptr (as_a <gbind *> (stmt)), ctx);
a4890dc9 16337 break;
75a70cf9 16338 case GIMPLE_OMP_PARALLEL:
16339 case GIMPLE_OMP_TASK:
16340 ctx = maybe_lookup_ctx (stmt);
bc7bff74 16341 gcc_assert (ctx);
16342 if (ctx->cancellable)
16343 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
75a70cf9 16344 lower_omp_taskreg (gsi_p, ctx);
a4890dc9 16345 break;
75a70cf9 16346 case GIMPLE_OMP_FOR:
16347 ctx = maybe_lookup_ctx (stmt);
1e8e9920 16348 gcc_assert (ctx);
bc7bff74 16349 if (ctx->cancellable)
16350 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
75a70cf9 16351 lower_omp_for (gsi_p, ctx);
1e8e9920 16352 break;
75a70cf9 16353 case GIMPLE_OMP_SECTIONS:
16354 ctx = maybe_lookup_ctx (stmt);
1e8e9920 16355 gcc_assert (ctx);
bc7bff74 16356 if (ctx->cancellable)
16357 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
75a70cf9 16358 lower_omp_sections (gsi_p, ctx);
1e8e9920 16359 break;
75a70cf9 16360 case GIMPLE_OMP_SINGLE:
16361 ctx = maybe_lookup_ctx (stmt);
1e8e9920 16362 gcc_assert (ctx);
75a70cf9 16363 lower_omp_single (gsi_p, ctx);
1e8e9920 16364 break;
75a70cf9 16365 case GIMPLE_OMP_MASTER:
16366 ctx = maybe_lookup_ctx (stmt);
1e8e9920 16367 gcc_assert (ctx);
75a70cf9 16368 lower_omp_master (gsi_p, ctx);
1e8e9920 16369 break;
bc7bff74 16370 case GIMPLE_OMP_TASKGROUP:
16371 ctx = maybe_lookup_ctx (stmt);
16372 gcc_assert (ctx);
16373 lower_omp_taskgroup (gsi_p, ctx);
16374 break;
75a70cf9 16375 case GIMPLE_OMP_ORDERED:
16376 ctx = maybe_lookup_ctx (stmt);
1e8e9920 16377 gcc_assert (ctx);
75a70cf9 16378 lower_omp_ordered (gsi_p, ctx);
1e8e9920 16379 break;
75a70cf9 16380 case GIMPLE_OMP_CRITICAL:
16381 ctx = maybe_lookup_ctx (stmt);
1e8e9920 16382 gcc_assert (ctx);
75a70cf9 16383 lower_omp_critical (gsi_p, ctx);
16384 break;
16385 case GIMPLE_OMP_ATOMIC_LOAD:
16386 if ((ctx || task_shared_vars)
1a91d914 16387 && walk_tree (gimple_omp_atomic_load_rhs_ptr (
16388 as_a <gomp_atomic_load *> (stmt)),
75a70cf9 16389 lower_omp_regimplify_p, ctx ? NULL : &wi, NULL))
43895be5 16390 lower_omp_regimplify_operands (ctx, stmt, gsi_p);
1e8e9920 16391 break;
bc7bff74 16392 case GIMPLE_OMP_TARGET:
16393 ctx = maybe_lookup_ctx (stmt);
16394 gcc_assert (ctx);
16395 lower_omp_target (gsi_p, ctx);
16396 break;
16397 case GIMPLE_OMP_TEAMS:
16398 ctx = maybe_lookup_ctx (stmt);
16399 gcc_assert (ctx);
16400 lower_omp_teams (gsi_p, ctx);
16401 break;
16402 case GIMPLE_CALL:
16403 tree fndecl;
1a91d914 16404 call_stmt = as_a <gcall *> (stmt);
16405 fndecl = gimple_call_fndecl (call_stmt);
bc7bff74 16406 if (fndecl
16407 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
16408 switch (DECL_FUNCTION_CODE (fndecl))
16409 {
16410 case BUILT_IN_GOMP_BARRIER:
16411 if (ctx == NULL)
16412 break;
16413 /* FALLTHRU */
16414 case BUILT_IN_GOMP_CANCEL:
16415 case BUILT_IN_GOMP_CANCELLATION_POINT:
16416 omp_context *cctx;
16417 cctx = ctx;
16418 if (gimple_code (cctx->stmt) == GIMPLE_OMP_SECTION)
16419 cctx = cctx->outer;
1a91d914 16420 gcc_assert (gimple_call_lhs (call_stmt) == NULL_TREE);
bc7bff74 16421 if (!cctx->cancellable)
16422 {
16423 if (DECL_FUNCTION_CODE (fndecl)
16424 == BUILT_IN_GOMP_CANCELLATION_POINT)
16425 {
16426 stmt = gimple_build_nop ();
16427 gsi_replace (gsi_p, stmt, false);
16428 }
16429 break;
16430 }
bc7bff74 16431 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
16432 {
16433 fndecl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL);
1a91d914 16434 gimple_call_set_fndecl (call_stmt, fndecl);
16435 gimple_call_set_fntype (call_stmt, TREE_TYPE (fndecl));
bc7bff74 16436 }
15b28553 16437 tree lhs;
f9e245b2 16438 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (fndecl)));
1a91d914 16439 gimple_call_set_lhs (call_stmt, lhs);
bc7bff74 16440 tree fallthru_label;
16441 fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
42acab1c 16442 gimple *g;
bc7bff74 16443 g = gimple_build_label (fallthru_label);
16444 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
15b28553 16445 g = gimple_build_cond (NE_EXPR, lhs,
16446 fold_convert (TREE_TYPE (lhs),
16447 boolean_false_node),
bc7bff74 16448 cctx->cancel_label, fallthru_label);
16449 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
16450 break;
16451 default:
16452 break;
16453 }
16454 /* FALLTHRU */
a4890dc9 16455 default:
fd6481cf 16456 if ((ctx || task_shared_vars)
75a70cf9 16457 && walk_gimple_op (stmt, lower_omp_regimplify_p,
16458 ctx ? NULL : &wi))
ef8cfd4d 16459 {
16460 /* Just remove clobbers, this should happen only if we have
16461 "privatized" local addressable variables in SIMD regions,
16462 the clobber isn't needed in that case and gimplifying address
16463 of the ARRAY_REF into a pointer and creating MEM_REF based
16464 clobber would create worse code than we get with the clobber
16465 dropped. */
16466 if (gimple_clobber_p (stmt))
16467 {
16468 gsi_replace (gsi_p, gimple_build_nop (), true);
16469 break;
16470 }
43895be5 16471 lower_omp_regimplify_operands (ctx, stmt, gsi_p);
ef8cfd4d 16472 }
1e8e9920 16473 break;
1e8e9920 16474 }
1e8e9920 16475}
16476
16477static void
e3a19533 16478lower_omp (gimple_seq *body, omp_context *ctx)
1e8e9920 16479{
1d22f541 16480 location_t saved_location = input_location;
e3a19533 16481 gimple_stmt_iterator gsi;
16482 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
75a70cf9 16483 lower_omp_1 (&gsi, ctx);
ca4c3545 16484 /* During gimplification, we haven't folded statments inside offloading
c3a81971 16485 or taskreg regions (gimplify.c:maybe_fold_stmt); do that now. */
16486 if (target_nesting_level || taskreg_nesting_level)
bc7bff74 16487 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
16488 fold_stmt (&gsi);
1d22f541 16489 input_location = saved_location;
1e8e9920 16490}
16491\f
16492/* Main entry point. */
16493
2a1990e9 16494static unsigned int
1e8e9920 16495execute_lower_omp (void)
16496{
75a70cf9 16497 gimple_seq body;
37eaded9 16498 int i;
16499 omp_context *ctx;
75a70cf9 16500
41709826 16501 /* This pass always runs, to provide PROP_gimple_lomp.
ca4c3545 16502 But often, there is nothing to do. */
16503 if (flag_cilkplus == 0 && flag_openacc == 0 && flag_openmp == 0
16504 && flag_openmp_simd == 0)
41709826 16505 return 0;
16506
1e8e9920 16507 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
16508 delete_omp_context);
16509
75a70cf9 16510 body = gimple_body (current_function_decl);
ab129075 16511 scan_omp (&body, NULL);
fd6481cf 16512 gcc_assert (taskreg_nesting_level == 0);
37eaded9 16513 FOR_EACH_VEC_ELT (taskreg_contexts, i, ctx)
16514 finish_taskreg_scan (ctx);
16515 taskreg_contexts.release ();
1e8e9920 16516
16517 if (all_contexts->root)
fd6481cf 16518 {
16519 if (task_shared_vars)
8a4a28a8 16520 push_gimplify_context ();
e3a19533 16521 lower_omp (&body, NULL);
fd6481cf 16522 if (task_shared_vars)
16523 pop_gimplify_context (NULL);
16524 }
1e8e9920 16525
773c5ba7 16526 if (all_contexts)
16527 {
16528 splay_tree_delete (all_contexts);
16529 all_contexts = NULL;
16530 }
fd6481cf 16531 BITMAP_FREE (task_shared_vars);
2a1990e9 16532 return 0;
1e8e9920 16533}
16534
7620bc82 16535namespace {
16536
16537const pass_data pass_data_lower_omp =
cbe8bda8 16538{
16539 GIMPLE_PASS, /* type */
16540 "omplower", /* name */
16541 OPTGROUP_NONE, /* optinfo_flags */
cbe8bda8 16542 TV_NONE, /* tv_id */
16543 PROP_gimple_any, /* properties_required */
16544 PROP_gimple_lomp, /* properties_provided */
16545 0, /* properties_destroyed */
16546 0, /* todo_flags_start */
16547 0, /* todo_flags_finish */
1e8e9920 16548};
cbe8bda8 16549
7620bc82 16550class pass_lower_omp : public gimple_opt_pass
cbe8bda8 16551{
16552public:
9af5ce0c 16553 pass_lower_omp (gcc::context *ctxt)
16554 : gimple_opt_pass (pass_data_lower_omp, ctxt)
cbe8bda8 16555 {}
16556
16557 /* opt_pass methods: */
65b0537f 16558 virtual unsigned int execute (function *) { return execute_lower_omp (); }
cbe8bda8 16559
16560}; // class pass_lower_omp
16561
7620bc82 16562} // anon namespace
16563
cbe8bda8 16564gimple_opt_pass *
16565make_pass_lower_omp (gcc::context *ctxt)
16566{
16567 return new pass_lower_omp (ctxt);
16568}
1e8e9920 16569\f
ca4c3545 16570/* The following is a utility to diagnose structured block violations.
61e47ac8 16571 It is not part of the "omplower" pass, as that's invoked too late. It
16572 should be invoked by the respective front ends after gimplification. */
1e8e9920 16573
16574static splay_tree all_labels;
16575
16576/* Check for mismatched contexts and generate an error if needed. Return
16577 true if an error is detected. */
16578
16579static bool
75a70cf9 16580diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
42acab1c 16581 gimple *branch_ctx, gimple *label_ctx)
1e8e9920 16582{
ca4c3545 16583 gcc_checking_assert (!branch_ctx || is_gimple_omp (branch_ctx));
16584 gcc_checking_assert (!label_ctx || is_gimple_omp (label_ctx));
16585
75a70cf9 16586 if (label_ctx == branch_ctx)
1e8e9920 16587 return false;
16588
ca4c3545 16589 const char* kind = NULL;
16590
16591 if (flag_cilkplus)
16592 {
16593 if ((branch_ctx
16594 && gimple_code (branch_ctx) == GIMPLE_OMP_FOR
16595 && gimple_omp_for_kind (branch_ctx) == GF_OMP_FOR_KIND_CILKSIMD)
16596 || (label_ctx
16597 && gimple_code (label_ctx) == GIMPLE_OMP_FOR
16598 && gimple_omp_for_kind (label_ctx) == GF_OMP_FOR_KIND_CILKSIMD))
16599 kind = "Cilk Plus";
16600 }
16601 if (flag_openacc)
16602 {
16603 if ((branch_ctx && is_gimple_omp_oacc (branch_ctx))
16604 || (label_ctx && is_gimple_omp_oacc (label_ctx)))
16605 {
16606 gcc_checking_assert (kind == NULL);
16607 kind = "OpenACC";
16608 }
16609 }
16610 if (kind == NULL)
16611 {
16612 gcc_checking_assert (flag_openmp);
16613 kind = "OpenMP";
16614 }
48e1416a 16615
75a70cf9 16616 /*
16617 Previously we kept track of the label's entire context in diagnose_sb_[12]
16618 so we could traverse it and issue a correct "exit" or "enter" error
16619 message upon a structured block violation.
16620
16621 We built the context by building a list with tree_cons'ing, but there is
16622 no easy counterpart in gimple tuples. It seems like far too much work
16623 for issuing exit/enter error messages. If someone really misses the
16624 distinct error message... patches welcome.
16625 */
48e1416a 16626
75a70cf9 16627#if 0
1e8e9920 16628 /* Try to avoid confusing the user by producing and error message
f0b5f617 16629 with correct "exit" or "enter" verbiage. We prefer "exit"
1e8e9920 16630 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
16631 if (branch_ctx == NULL)
16632 exit_p = false;
16633 else
16634 {
16635 while (label_ctx)
16636 {
16637 if (TREE_VALUE (label_ctx) == branch_ctx)
16638 {
16639 exit_p = false;
16640 break;
16641 }
16642 label_ctx = TREE_CHAIN (label_ctx);
16643 }
16644 }
16645
16646 if (exit_p)
ca4c3545 16647 error ("invalid exit from %s structured block", kind);
1e8e9920 16648 else
ca4c3545 16649 error ("invalid entry to %s structured block", kind);
75a70cf9 16650#endif
1e8e9920 16651
75a70cf9 16652 /* If it's obvious we have an invalid entry, be specific about the error. */
16653 if (branch_ctx == NULL)
ca4c3545 16654 error ("invalid entry to %s structured block", kind);
75a70cf9 16655 else
f2697631 16656 {
16657 /* Otherwise, be vague and lazy, but efficient. */
ca4c3545 16658 error ("invalid branch to/from %s structured block", kind);
f2697631 16659 }
75a70cf9 16660
16661 gsi_replace (gsi_p, gimple_build_nop (), false);
1e8e9920 16662 return true;
16663}
16664
ca4c3545 16665/* Pass 1: Create a minimal tree of structured blocks, and record
75a70cf9 16666 where each label is found. */
1e8e9920 16667
16668static tree
75a70cf9 16669diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
16670 struct walk_stmt_info *wi)
1e8e9920 16671{
42acab1c 16672 gimple *context = (gimple *) wi->info;
16673 gimple *inner_context;
16674 gimple *stmt = gsi_stmt (*gsi_p);
1e8e9920 16675
75a70cf9 16676 *handled_ops_p = true;
16677
ca4c3545 16678 switch (gimple_code (stmt))
1e8e9920 16679 {
75a70cf9 16680 WALK_SUBSTMTS;
48e1416a 16681
75a70cf9 16682 case GIMPLE_OMP_PARALLEL:
16683 case GIMPLE_OMP_TASK:
16684 case GIMPLE_OMP_SECTIONS:
16685 case GIMPLE_OMP_SINGLE:
16686 case GIMPLE_OMP_SECTION:
16687 case GIMPLE_OMP_MASTER:
16688 case GIMPLE_OMP_ORDERED:
16689 case GIMPLE_OMP_CRITICAL:
bc7bff74 16690 case GIMPLE_OMP_TARGET:
16691 case GIMPLE_OMP_TEAMS:
16692 case GIMPLE_OMP_TASKGROUP:
75a70cf9 16693 /* The minimal context here is just the current OMP construct. */
16694 inner_context = stmt;
1e8e9920 16695 wi->info = inner_context;
75a70cf9 16696 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
1e8e9920 16697 wi->info = context;
16698 break;
16699
75a70cf9 16700 case GIMPLE_OMP_FOR:
16701 inner_context = stmt;
1e8e9920 16702 wi->info = inner_context;
75a70cf9 16703 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
16704 walk them. */
16705 walk_gimple_seq (gimple_omp_for_pre_body (stmt),
16706 diagnose_sb_1, NULL, wi);
16707 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
1e8e9920 16708 wi->info = context;
16709 break;
16710
75a70cf9 16711 case GIMPLE_LABEL:
1a91d914 16712 splay_tree_insert (all_labels,
16713 (splay_tree_key) gimple_label_label (
16714 as_a <glabel *> (stmt)),
1e8e9920 16715 (splay_tree_value) context);
16716 break;
16717
16718 default:
16719 break;
16720 }
16721
16722 return NULL_TREE;
16723}
16724
16725/* Pass 2: Check each branch and see if its context differs from that of
16726 the destination label's context. */
16727
16728static tree
75a70cf9 16729diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
16730 struct walk_stmt_info *wi)
1e8e9920 16731{
42acab1c 16732 gimple *context = (gimple *) wi->info;
1e8e9920 16733 splay_tree_node n;
42acab1c 16734 gimple *stmt = gsi_stmt (*gsi_p);
1e8e9920 16735
75a70cf9 16736 *handled_ops_p = true;
16737
16738 switch (gimple_code (stmt))
1e8e9920 16739 {
75a70cf9 16740 WALK_SUBSTMTS;
16741
16742 case GIMPLE_OMP_PARALLEL:
16743 case GIMPLE_OMP_TASK:
16744 case GIMPLE_OMP_SECTIONS:
16745 case GIMPLE_OMP_SINGLE:
16746 case GIMPLE_OMP_SECTION:
16747 case GIMPLE_OMP_MASTER:
16748 case GIMPLE_OMP_ORDERED:
16749 case GIMPLE_OMP_CRITICAL:
bc7bff74 16750 case GIMPLE_OMP_TARGET:
16751 case GIMPLE_OMP_TEAMS:
16752 case GIMPLE_OMP_TASKGROUP:
75a70cf9 16753 wi->info = stmt;
e3a19533 16754 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
1e8e9920 16755 wi->info = context;
16756 break;
16757
75a70cf9 16758 case GIMPLE_OMP_FOR:
16759 wi->info = stmt;
16760 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
16761 walk them. */
e3a19533 16762 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt),
16763 diagnose_sb_2, NULL, wi);
16764 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
1e8e9920 16765 wi->info = context;
16766 break;
16767
0e1818e7 16768 case GIMPLE_COND:
16769 {
1a91d914 16770 gcond *cond_stmt = as_a <gcond *> (stmt);
16771 tree lab = gimple_cond_true_label (cond_stmt);
0e1818e7 16772 if (lab)
16773 {
16774 n = splay_tree_lookup (all_labels,
16775 (splay_tree_key) lab);
16776 diagnose_sb_0 (gsi_p, context,
42acab1c 16777 n ? (gimple *) n->value : NULL);
0e1818e7 16778 }
1a91d914 16779 lab = gimple_cond_false_label (cond_stmt);
0e1818e7 16780 if (lab)
16781 {
16782 n = splay_tree_lookup (all_labels,
16783 (splay_tree_key) lab);
16784 diagnose_sb_0 (gsi_p, context,
42acab1c 16785 n ? (gimple *) n->value : NULL);
0e1818e7 16786 }
16787 }
16788 break;
16789
75a70cf9 16790 case GIMPLE_GOTO:
1e8e9920 16791 {
75a70cf9 16792 tree lab = gimple_goto_dest (stmt);
1e8e9920 16793 if (TREE_CODE (lab) != LABEL_DECL)
16794 break;
16795
16796 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
42acab1c 16797 diagnose_sb_0 (gsi_p, context, n ? (gimple *) n->value : NULL);
1e8e9920 16798 }
16799 break;
16800
75a70cf9 16801 case GIMPLE_SWITCH:
1e8e9920 16802 {
1a91d914 16803 gswitch *switch_stmt = as_a <gswitch *> (stmt);
75a70cf9 16804 unsigned int i;
1a91d914 16805 for (i = 0; i < gimple_switch_num_labels (switch_stmt); ++i)
1e8e9920 16806 {
1a91d914 16807 tree lab = CASE_LABEL (gimple_switch_label (switch_stmt, i));
1e8e9920 16808 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
42acab1c 16809 if (n && diagnose_sb_0 (gsi_p, context, (gimple *) n->value))
1e8e9920 16810 break;
16811 }
16812 }
16813 break;
16814
75a70cf9 16815 case GIMPLE_RETURN:
16816 diagnose_sb_0 (gsi_p, context, NULL);
1e8e9920 16817 break;
16818
16819 default:
16820 break;
16821 }
16822
16823 return NULL_TREE;
16824}
16825
ca4c3545 16826/* Called from tree-cfg.c::make_edges to create cfg edges for all relevant
16827 GIMPLE_* codes. */
7740abd8 16828bool
b2c0e0b7 16829make_gimple_omp_edges (basic_block bb, struct omp_region **region,
16830 int *region_idx)
7740abd8 16831{
42acab1c 16832 gimple *last = last_stmt (bb);
7740abd8 16833 enum gimple_code code = gimple_code (last);
16834 struct omp_region *cur_region = *region;
16835 bool fallthru = false;
16836
16837 switch (code)
16838 {
16839 case GIMPLE_OMP_PARALLEL:
16840 case GIMPLE_OMP_TASK:
16841 case GIMPLE_OMP_FOR:
16842 case GIMPLE_OMP_SINGLE:
16843 case GIMPLE_OMP_TEAMS:
16844 case GIMPLE_OMP_MASTER:
16845 case GIMPLE_OMP_TASKGROUP:
7740abd8 16846 case GIMPLE_OMP_CRITICAL:
16847 case GIMPLE_OMP_SECTION:
16848 cur_region = new_omp_region (bb, code, cur_region);
16849 fallthru = true;
16850 break;
16851
43895be5 16852 case GIMPLE_OMP_ORDERED:
16853 cur_region = new_omp_region (bb, code, cur_region);
16854 fallthru = true;
16855 if (find_omp_clause (gimple_omp_ordered_clauses
16856 (as_a <gomp_ordered *> (last)),
16857 OMP_CLAUSE_DEPEND))
16858 cur_region = cur_region->outer;
16859 break;
16860
7740abd8 16861 case GIMPLE_OMP_TARGET:
16862 cur_region = new_omp_region (bb, code, cur_region);
16863 fallthru = true;
ca4c3545 16864 switch (gimple_omp_target_kind (last))
16865 {
16866 case GF_OMP_TARGET_KIND_REGION:
16867 case GF_OMP_TARGET_KIND_DATA:
16868 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
16869 case GF_OMP_TARGET_KIND_OACC_KERNELS:
16870 case GF_OMP_TARGET_KIND_OACC_DATA:
571b3486 16871 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
ca4c3545 16872 break;
16873 case GF_OMP_TARGET_KIND_UPDATE:
43895be5 16874 case GF_OMP_TARGET_KIND_ENTER_DATA:
16875 case GF_OMP_TARGET_KIND_EXIT_DATA:
ca4c3545 16876 case GF_OMP_TARGET_KIND_OACC_UPDATE:
16877 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
2fc5e987 16878 case GF_OMP_TARGET_KIND_OACC_DECLARE:
ca4c3545 16879 cur_region = cur_region->outer;
16880 break;
16881 default:
16882 gcc_unreachable ();
16883 }
7740abd8 16884 break;
16885
16886 case GIMPLE_OMP_SECTIONS:
16887 cur_region = new_omp_region (bb, code, cur_region);
16888 fallthru = true;
16889 break;
16890
16891 case GIMPLE_OMP_SECTIONS_SWITCH:
16892 fallthru = false;
16893 break;
16894
16895 case GIMPLE_OMP_ATOMIC_LOAD:
16896 case GIMPLE_OMP_ATOMIC_STORE:
16897 fallthru = true;
16898 break;
16899
16900 case GIMPLE_OMP_RETURN:
16901 /* In the case of a GIMPLE_OMP_SECTION, the edge will go
16902 somewhere other than the next block. This will be
16903 created later. */
16904 cur_region->exit = bb;
b25f70fd 16905 if (cur_region->type == GIMPLE_OMP_TASK)
16906 /* Add an edge corresponding to not scheduling the task
16907 immediately. */
16908 make_edge (cur_region->entry, bb, EDGE_ABNORMAL);
7740abd8 16909 fallthru = cur_region->type != GIMPLE_OMP_SECTION;
16910 cur_region = cur_region->outer;
16911 break;
16912
16913 case GIMPLE_OMP_CONTINUE:
16914 cur_region->cont = bb;
16915 switch (cur_region->type)
16916 {
16917 case GIMPLE_OMP_FOR:
16918 /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
16919 succs edges as abnormal to prevent splitting
16920 them. */
16921 single_succ_edge (cur_region->entry)->flags |= EDGE_ABNORMAL;
16922 /* Make the loopback edge. */
16923 make_edge (bb, single_succ (cur_region->entry),
16924 EDGE_ABNORMAL);
16925
16926 /* Create an edge from GIMPLE_OMP_FOR to exit, which
16927 corresponds to the case that the body of the loop
16928 is not executed at all. */
16929 make_edge (cur_region->entry, bb->next_bb, EDGE_ABNORMAL);
16930 make_edge (bb, bb->next_bb, EDGE_FALLTHRU | EDGE_ABNORMAL);
16931 fallthru = false;
16932 break;
16933
16934 case GIMPLE_OMP_SECTIONS:
16935 /* Wire up the edges into and out of the nested sections. */
16936 {
16937 basic_block switch_bb = single_succ (cur_region->entry);
16938
16939 struct omp_region *i;
16940 for (i = cur_region->inner; i ; i = i->next)
16941 {
16942 gcc_assert (i->type == GIMPLE_OMP_SECTION);
16943 make_edge (switch_bb, i->entry, 0);
16944 make_edge (i->exit, bb, EDGE_FALLTHRU);
16945 }
16946
16947 /* Make the loopback edge to the block with
16948 GIMPLE_OMP_SECTIONS_SWITCH. */
16949 make_edge (bb, switch_bb, 0);
16950
16951 /* Make the edge from the switch to exit. */
16952 make_edge (switch_bb, bb->next_bb, 0);
16953 fallthru = false;
16954 }
16955 break;
16956
b25f70fd 16957 case GIMPLE_OMP_TASK:
16958 fallthru = true;
16959 break;
16960
7740abd8 16961 default:
16962 gcc_unreachable ();
16963 }
16964 break;
16965
16966 default:
16967 gcc_unreachable ();
16968 }
16969
16970 if (*region != cur_region)
b2c0e0b7 16971 {
16972 *region = cur_region;
16973 if (cur_region)
16974 *region_idx = cur_region->entry->index;
16975 else
16976 *region_idx = 0;
16977 }
7740abd8 16978
16979 return fallthru;
16980}
16981
bfec3452 16982static unsigned int
16983diagnose_omp_structured_block_errors (void)
1e8e9920 16984{
1e8e9920 16985 struct walk_stmt_info wi;
bfec3452 16986 gimple_seq body = gimple_body (current_function_decl);
1e8e9920 16987
16988 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
16989
16990 memset (&wi, 0, sizeof (wi));
75a70cf9 16991 walk_gimple_seq (body, diagnose_sb_1, NULL, &wi);
1e8e9920 16992
16993 memset (&wi, 0, sizeof (wi));
1e8e9920 16994 wi.want_locations = true;
e3a19533 16995 walk_gimple_seq_mod (&body, diagnose_sb_2, NULL, &wi);
16996
16997 gimple_set_body (current_function_decl, body);
1e8e9920 16998
16999 splay_tree_delete (all_labels);
17000 all_labels = NULL;
17001
bfec3452 17002 return 0;
1e8e9920 17003}
17004
7620bc82 17005namespace {
17006
17007const pass_data pass_data_diagnose_omp_blocks =
cbe8bda8 17008{
17009 GIMPLE_PASS, /* type */
17010 "*diagnose_omp_blocks", /* name */
17011 OPTGROUP_NONE, /* optinfo_flags */
cbe8bda8 17012 TV_NONE, /* tv_id */
17013 PROP_gimple_any, /* properties_required */
17014 0, /* properties_provided */
17015 0, /* properties_destroyed */
17016 0, /* todo_flags_start */
17017 0, /* todo_flags_finish */
bfec3452 17018};
17019
7620bc82 17020class pass_diagnose_omp_blocks : public gimple_opt_pass
cbe8bda8 17021{
17022public:
9af5ce0c 17023 pass_diagnose_omp_blocks (gcc::context *ctxt)
17024 : gimple_opt_pass (pass_data_diagnose_omp_blocks, ctxt)
cbe8bda8 17025 {}
17026
17027 /* opt_pass methods: */
ca4c3545 17028 virtual bool gate (function *)
17029 {
17030 return flag_cilkplus || flag_openacc || flag_openmp;
17031 }
65b0537f 17032 virtual unsigned int execute (function *)
17033 {
17034 return diagnose_omp_structured_block_errors ();
17035 }
cbe8bda8 17036
17037}; // class pass_diagnose_omp_blocks
17038
7620bc82 17039} // anon namespace
17040
cbe8bda8 17041gimple_opt_pass *
17042make_pass_diagnose_omp_blocks (gcc::context *ctxt)
17043{
17044 return new pass_diagnose_omp_blocks (ctxt);
17045}
d09768a4 17046\f
17047/* SIMD clone supporting code. */
17048
17049/* Allocate a fresh `simd_clone' and return it. NARGS is the number
17050 of arguments to reserve space for. */
17051
17052static struct cgraph_simd_clone *
17053simd_clone_struct_alloc (int nargs)
17054{
17055 struct cgraph_simd_clone *clone_info;
17056 size_t len = (sizeof (struct cgraph_simd_clone)
17057 + nargs * sizeof (struct cgraph_simd_clone_arg));
17058 clone_info = (struct cgraph_simd_clone *)
ea7d8c7a 17059 ggc_internal_cleared_alloc (len);
d09768a4 17060 return clone_info;
17061}
17062
17063/* Make a copy of the `struct cgraph_simd_clone' in FROM to TO. */
17064
17065static inline void
17066simd_clone_struct_copy (struct cgraph_simd_clone *to,
17067 struct cgraph_simd_clone *from)
17068{
17069 memcpy (to, from, (sizeof (struct cgraph_simd_clone)
46c0fd4b 17070 + ((from->nargs - from->inbranch)
17071 * sizeof (struct cgraph_simd_clone_arg))));
d09768a4 17072}
17073
17074/* Return vector of parameter types of function FNDECL. This uses
17075 TYPE_ARG_TYPES if available, otherwise falls back to types of
17076 DECL_ARGUMENTS types. */
17077
17078vec<tree>
17079simd_clone_vector_of_formal_parm_types (tree fndecl)
17080{
17081 if (TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
17082 return ipa_get_vector_of_formal_parm_types (TREE_TYPE (fndecl));
17083 vec<tree> args = ipa_get_vector_of_formal_parms (fndecl);
17084 unsigned int i;
17085 tree arg;
17086 FOR_EACH_VEC_ELT (args, i, arg)
17087 args[i] = TREE_TYPE (args[i]);
17088 return args;
17089}
17090
17091/* Given a simd function in NODE, extract the simd specific
17092 information from the OMP clauses passed in CLAUSES, and return
17093 the struct cgraph_simd_clone * if it should be cloned. *INBRANCH_SPECIFIED
17094 is set to TRUE if the `inbranch' or `notinbranch' clause specified,
17095 otherwise set to FALSE. */
17096
17097static struct cgraph_simd_clone *
17098simd_clone_clauses_extract (struct cgraph_node *node, tree clauses,
17099 bool *inbranch_specified)
17100{
17101 vec<tree> args = simd_clone_vector_of_formal_parm_types (node->decl);
17102 tree t;
17103 int n;
17104 *inbranch_specified = false;
17105
17106 n = args.length ();
17107 if (n > 0 && args.last () == void_type_node)
17108 n--;
17109
17110 /* To distinguish from an OpenMP simd clone, Cilk Plus functions to
17111 be cloned have a distinctive artificial label in addition to "omp
17112 declare simd". */
17113 bool cilk_clone
a89e6c15 17114 = (flag_cilkplus
74acc703 17115 && lookup_attribute ("cilk simd function",
d09768a4 17116 DECL_ATTRIBUTES (node->decl)));
17117
17118 /* Allocate one more than needed just in case this is an in-branch
17119 clone which will require a mask argument. */
17120 struct cgraph_simd_clone *clone_info = simd_clone_struct_alloc (n + 1);
17121 clone_info->nargs = n;
17122 clone_info->cilk_elemental = cilk_clone;
17123
17124 if (!clauses)
17125 {
17126 args.release ();
17127 return clone_info;
17128 }
17129 clauses = TREE_VALUE (clauses);
17130 if (!clauses || TREE_CODE (clauses) != OMP_CLAUSE)
17131 return clone_info;
17132
17133 for (t = clauses; t; t = OMP_CLAUSE_CHAIN (t))
17134 {
17135 switch (OMP_CLAUSE_CODE (t))
17136 {
17137 case OMP_CLAUSE_INBRANCH:
17138 clone_info->inbranch = 1;
17139 *inbranch_specified = true;
17140 break;
17141 case OMP_CLAUSE_NOTINBRANCH:
17142 clone_info->inbranch = 0;
17143 *inbranch_specified = true;
17144 break;
17145 case OMP_CLAUSE_SIMDLEN:
17146 clone_info->simdlen
17147 = TREE_INT_CST_LOW (OMP_CLAUSE_SIMDLEN_EXPR (t));
17148 break;
17149 case OMP_CLAUSE_LINEAR:
17150 {
17151 tree decl = OMP_CLAUSE_DECL (t);
17152 tree step = OMP_CLAUSE_LINEAR_STEP (t);
17153 int argno = TREE_INT_CST_LOW (decl);
17154 if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (t))
17155 {
9561765e 17156 enum cgraph_simd_clone_arg_type arg_type;
17157 if (TREE_CODE (args[argno]) == REFERENCE_TYPE)
17158 switch (OMP_CLAUSE_LINEAR_KIND (t))
17159 {
17160 case OMP_CLAUSE_LINEAR_REF:
17161 arg_type
17162 = SIMD_CLONE_ARG_TYPE_LINEAR_REF_VARIABLE_STEP;
17163 break;
17164 case OMP_CLAUSE_LINEAR_UVAL:
17165 arg_type
17166 = SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_VARIABLE_STEP;
17167 break;
17168 case OMP_CLAUSE_LINEAR_VAL:
17169 case OMP_CLAUSE_LINEAR_DEFAULT:
17170 arg_type
17171 = SIMD_CLONE_ARG_TYPE_LINEAR_VAL_VARIABLE_STEP;
17172 break;
17173 default:
17174 gcc_unreachable ();
17175 }
17176 else
17177 arg_type = SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP;
17178 clone_info->args[argno].arg_type = arg_type;
d09768a4 17179 clone_info->args[argno].linear_step = tree_to_shwi (step);
17180 gcc_assert (clone_info->args[argno].linear_step >= 0
17181 && clone_info->args[argno].linear_step < n);
17182 }
17183 else
17184 {
17185 if (POINTER_TYPE_P (args[argno]))
17186 step = fold_convert (ssizetype, step);
17187 if (!tree_fits_shwi_p (step))
17188 {
17189 warning_at (OMP_CLAUSE_LOCATION (t), 0,
17190 "ignoring large linear step");
17191 args.release ();
17192 return NULL;
17193 }
17194 else if (integer_zerop (step))
17195 {
17196 warning_at (OMP_CLAUSE_LOCATION (t), 0,
17197 "ignoring zero linear step");
17198 args.release ();
17199 return NULL;
17200 }
17201 else
17202 {
43895be5 17203 enum cgraph_simd_clone_arg_type arg_type;
17204 if (TREE_CODE (args[argno]) == REFERENCE_TYPE)
17205 switch (OMP_CLAUSE_LINEAR_KIND (t))
17206 {
17207 case OMP_CLAUSE_LINEAR_REF:
17208 arg_type
17209 = SIMD_CLONE_ARG_TYPE_LINEAR_REF_CONSTANT_STEP;
17210 break;
17211 case OMP_CLAUSE_LINEAR_UVAL:
17212 arg_type
17213 = SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP;
17214 break;
17215 case OMP_CLAUSE_LINEAR_VAL:
17216 case OMP_CLAUSE_LINEAR_DEFAULT:
17217 arg_type
17218 = SIMD_CLONE_ARG_TYPE_LINEAR_VAL_CONSTANT_STEP;
17219 break;
17220 default:
17221 gcc_unreachable ();
17222 }
17223 else
17224 arg_type = SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP;
17225 clone_info->args[argno].arg_type = arg_type;
d09768a4 17226 clone_info->args[argno].linear_step = tree_to_shwi (step);
17227 }
17228 }
17229 break;
17230 }
17231 case OMP_CLAUSE_UNIFORM:
17232 {
17233 tree decl = OMP_CLAUSE_DECL (t);
17234 int argno = tree_to_uhwi (decl);
17235 clone_info->args[argno].arg_type
17236 = SIMD_CLONE_ARG_TYPE_UNIFORM;
17237 break;
17238 }
17239 case OMP_CLAUSE_ALIGNED:
17240 {
17241 tree decl = OMP_CLAUSE_DECL (t);
17242 int argno = tree_to_uhwi (decl);
17243 clone_info->args[argno].alignment
17244 = TREE_INT_CST_LOW (OMP_CLAUSE_ALIGNED_ALIGNMENT (t));
17245 break;
17246 }
17247 default:
17248 break;
17249 }
17250 }
17251 args.release ();
17252 return clone_info;
17253}
17254
17255/* Given a SIMD clone in NODE, calculate the characteristic data
17256 type and return the coresponding type. The characteristic data
17257 type is computed as described in the Intel Vector ABI. */
17258
17259static tree
17260simd_clone_compute_base_data_type (struct cgraph_node *node,
17261 struct cgraph_simd_clone *clone_info)
17262{
17263 tree type = integer_type_node;
17264 tree fndecl = node->decl;
17265
17266 /* a) For non-void function, the characteristic data type is the
17267 return type. */
17268 if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) != VOID_TYPE)
17269 type = TREE_TYPE (TREE_TYPE (fndecl));
17270
17271 /* b) If the function has any non-uniform, non-linear parameters,
17272 then the characteristic data type is the type of the first
17273 such parameter. */
17274 else
17275 {
17276 vec<tree> map = simd_clone_vector_of_formal_parm_types (fndecl);
17277 for (unsigned int i = 0; i < clone_info->nargs; ++i)
17278 if (clone_info->args[i].arg_type == SIMD_CLONE_ARG_TYPE_VECTOR)
17279 {
17280 type = map[i];
17281 break;
17282 }
17283 map.release ();
17284 }
17285
17286 /* c) If the characteristic data type determined by a) or b) above
17287 is struct, union, or class type which is pass-by-value (except
17288 for the type that maps to the built-in complex data type), the
17289 characteristic data type is int. */
17290 if (RECORD_OR_UNION_TYPE_P (type)
17291 && !aggregate_value_p (type, NULL)
17292 && TREE_CODE (type) != COMPLEX_TYPE)
17293 return integer_type_node;
17294
17295 /* d) If none of the above three classes is applicable, the
17296 characteristic data type is int. */
17297
17298 return type;
17299
17300 /* e) For Intel Xeon Phi native and offload compilation, if the
17301 resulting characteristic data type is 8-bit or 16-bit integer
17302 data type, the characteristic data type is int. */
17303 /* Well, we don't handle Xeon Phi yet. */
17304}
17305
17306static tree
17307simd_clone_mangle (struct cgraph_node *node,
17308 struct cgraph_simd_clone *clone_info)
17309{
17310 char vecsize_mangle = clone_info->vecsize_mangle;
17311 char mask = clone_info->inbranch ? 'M' : 'N';
17312 unsigned int simdlen = clone_info->simdlen;
17313 unsigned int n;
17314 pretty_printer pp;
17315
17316 gcc_assert (vecsize_mangle && simdlen);
17317
17318 pp_string (&pp, "_ZGV");
17319 pp_character (&pp, vecsize_mangle);
17320 pp_character (&pp, mask);
17321 pp_decimal_int (&pp, simdlen);
17322
17323 for (n = 0; n < clone_info->nargs; ++n)
17324 {
17325 struct cgraph_simd_clone_arg arg = clone_info->args[n];
17326
43895be5 17327 switch (arg.arg_type)
d09768a4 17328 {
43895be5 17329 case SIMD_CLONE_ARG_TYPE_UNIFORM:
17330 pp_character (&pp, 'u');
17331 break;
17332 case SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP:
d09768a4 17333 pp_character (&pp, 'l');
43895be5 17334 goto mangle_linear;
17335 case SIMD_CLONE_ARG_TYPE_LINEAR_REF_CONSTANT_STEP:
17336 pp_character (&pp, 'R');
17337 goto mangle_linear;
17338 case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_CONSTANT_STEP:
17339 pp_character (&pp, 'L');
17340 goto mangle_linear;
17341 case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP:
17342 pp_character (&pp, 'U');
17343 goto mangle_linear;
17344 mangle_linear:
17345 gcc_assert (arg.linear_step != 0);
d09768a4 17346 if (arg.linear_step > 1)
17347 pp_unsigned_wide_integer (&pp, arg.linear_step);
17348 else if (arg.linear_step < 0)
17349 {
17350 pp_character (&pp, 'n');
17351 pp_unsigned_wide_integer (&pp, (-(unsigned HOST_WIDE_INT)
17352 arg.linear_step));
17353 }
43895be5 17354 break;
17355 case SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP:
9561765e 17356 pp_string (&pp, "ls");
17357 pp_unsigned_wide_integer (&pp, arg.linear_step);
17358 break;
17359 case SIMD_CLONE_ARG_TYPE_LINEAR_REF_VARIABLE_STEP:
17360 pp_string (&pp, "Rs");
17361 pp_unsigned_wide_integer (&pp, arg.linear_step);
17362 break;
17363 case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_VARIABLE_STEP:
17364 pp_string (&pp, "Ls");
17365 pp_unsigned_wide_integer (&pp, arg.linear_step);
17366 break;
17367 case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_VARIABLE_STEP:
17368 pp_string (&pp, "Us");
d09768a4 17369 pp_unsigned_wide_integer (&pp, arg.linear_step);
43895be5 17370 break;
17371 default:
17372 pp_character (&pp, 'v');
d09768a4 17373 }
d09768a4 17374 if (arg.alignment)
17375 {
17376 pp_character (&pp, 'a');
17377 pp_decimal_int (&pp, arg.alignment);
17378 }
17379 }
17380
17381 pp_underscore (&pp);
4e4baaad 17382 const char *str = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl));
17383 if (*str == '*')
17384 ++str;
17385 pp_string (&pp, str);
17386 str = pp_formatted_text (&pp);
d09768a4 17387
17388 /* If there already is a SIMD clone with the same mangled name, don't
17389 add another one. This can happen e.g. for
17390 #pragma omp declare simd
17391 #pragma omp declare simd simdlen(8)
17392 int foo (int, int);
17393 if the simdlen is assumed to be 8 for the first one, etc. */
17394 for (struct cgraph_node *clone = node->simd_clones; clone;
17395 clone = clone->simdclone->next_clone)
17396 if (strcmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (clone->decl)),
17397 str) == 0)
17398 return NULL_TREE;
17399
17400 return get_identifier (str);
17401}
17402
17403/* Create a simd clone of OLD_NODE and return it. */
17404
17405static struct cgraph_node *
17406simd_clone_create (struct cgraph_node *old_node)
17407{
17408 struct cgraph_node *new_node;
17409 if (old_node->definition)
ea0695f9 17410 {
415d1b9a 17411 if (!old_node->has_gimple_body_p ())
ea0695f9 17412 return NULL;
415d1b9a 17413 old_node->get_body ();
17414 new_node = old_node->create_version_clone_with_body (vNULL, NULL, NULL,
17415 false, NULL, NULL,
17416 "simdclone");
ea0695f9 17417 }
d09768a4 17418 else
17419 {
17420 tree old_decl = old_node->decl;
17421 tree new_decl = copy_node (old_node->decl);
17422 DECL_NAME (new_decl) = clone_function_name (old_decl, "simdclone");
17423 SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl));
17424 SET_DECL_RTL (new_decl, NULL);
17425 DECL_STATIC_CONSTRUCTOR (new_decl) = 0;
17426 DECL_STATIC_DESTRUCTOR (new_decl) = 0;
415d1b9a 17427 new_node = old_node->create_version_clone (new_decl, vNULL, NULL);
64c7c74a 17428 if (old_node->in_other_partition)
17429 new_node->in_other_partition = 1;
35ee1c66 17430 symtab->call_cgraph_insertion_hooks (new_node);
d09768a4 17431 }
17432 if (new_node == NULL)
17433 return new_node;
17434
17435 TREE_PUBLIC (new_node->decl) = TREE_PUBLIC (old_node->decl);
17436
17437 /* The function cgraph_function_versioning () will force the new
17438 symbol local. Undo this, and inherit external visability from
17439 the old node. */
17440 new_node->local.local = old_node->local.local;
17441 new_node->externally_visible = old_node->externally_visible;
17442
17443 return new_node;
17444}
17445
17446/* Adjust the return type of the given function to its appropriate
17447 vector counterpart. Returns a simd array to be used throughout the
17448 function as a return value. */
17449
17450static tree
17451simd_clone_adjust_return_type (struct cgraph_node *node)
17452{
17453 tree fndecl = node->decl;
17454 tree orig_rettype = TREE_TYPE (TREE_TYPE (fndecl));
17455 unsigned int veclen;
17456 tree t;
17457
17458 /* Adjust the function return type. */
17459 if (orig_rettype == void_type_node)
17460 return NULL_TREE;
17461 TREE_TYPE (fndecl) = build_distinct_type_copy (TREE_TYPE (fndecl));
fdf7662c 17462 t = TREE_TYPE (TREE_TYPE (fndecl));
17463 if (INTEGRAL_TYPE_P (t) || POINTER_TYPE_P (t))
d09768a4 17464 veclen = node->simdclone->vecsize_int;
17465 else
17466 veclen = node->simdclone->vecsize_float;
fdf7662c 17467 veclen /= GET_MODE_BITSIZE (TYPE_MODE (t));
d09768a4 17468 if (veclen > node->simdclone->simdlen)
17469 veclen = node->simdclone->simdlen;
fdf7662c 17470 if (POINTER_TYPE_P (t))
17471 t = pointer_sized_int_node;
d09768a4 17472 if (veclen == node->simdclone->simdlen)
fdf7662c 17473 t = build_vector_type (t, node->simdclone->simdlen);
d09768a4 17474 else
17475 {
fdf7662c 17476 t = build_vector_type (t, veclen);
d09768a4 17477 t = build_array_type_nelts (t, node->simdclone->simdlen / veclen);
d09768a4 17478 }
fdf7662c 17479 TREE_TYPE (TREE_TYPE (fndecl)) = t;
d09768a4 17480 if (!node->definition)
17481 return NULL_TREE;
17482
17483 t = DECL_RESULT (fndecl);
17484 /* Adjust the DECL_RESULT. */
17485 gcc_assert (TREE_TYPE (t) != void_type_node);
17486 TREE_TYPE (t) = TREE_TYPE (TREE_TYPE (fndecl));
17487 relayout_decl (t);
17488
17489 tree atype = build_array_type_nelts (orig_rettype,
17490 node->simdclone->simdlen);
17491 if (veclen != node->simdclone->simdlen)
17492 return build1 (VIEW_CONVERT_EXPR, atype, t);
17493
17494 /* Set up a SIMD array to use as the return value. */
17495 tree retval = create_tmp_var_raw (atype, "retval");
17496 gimple_add_tmp_var (retval);
17497 return retval;
17498}
17499
17500/* Each vector argument has a corresponding array to be used locally
17501 as part of the eventual loop. Create such temporary array and
17502 return it.
17503
17504 PREFIX is the prefix to be used for the temporary.
17505
17506 TYPE is the inner element type.
17507
17508 SIMDLEN is the number of elements. */
17509
17510static tree
17511create_tmp_simd_array (const char *prefix, tree type, int simdlen)
17512{
17513 tree atype = build_array_type_nelts (type, simdlen);
17514 tree avar = create_tmp_var_raw (atype, prefix);
17515 gimple_add_tmp_var (avar);
17516 return avar;
17517}
17518
17519/* Modify the function argument types to their corresponding vector
17520 counterparts if appropriate. Also, create one array for each simd
17521 argument to be used locally when using the function arguments as
17522 part of the loop.
17523
17524 NODE is the function whose arguments are to be adjusted.
17525
17526 Returns an adjustment vector that will be filled describing how the
17527 argument types will be adjusted. */
17528
17529static ipa_parm_adjustment_vec
17530simd_clone_adjust_argument_types (struct cgraph_node *node)
17531{
17532 vec<tree> args;
17533 ipa_parm_adjustment_vec adjustments;
17534
17535 if (node->definition)
17536 args = ipa_get_vector_of_formal_parms (node->decl);
17537 else
17538 args = simd_clone_vector_of_formal_parm_types (node->decl);
17539 adjustments.create (args.length ());
17540 unsigned i, j, veclen;
17541 struct ipa_parm_adjustment adj;
17542 for (i = 0; i < node->simdclone->nargs; ++i)
17543 {
17544 memset (&adj, 0, sizeof (adj));
17545 tree parm = args[i];
17546 tree parm_type = node->definition ? TREE_TYPE (parm) : parm;
17547 adj.base_index = i;
17548 adj.base = parm;
17549
17550 node->simdclone->args[i].orig_arg = node->definition ? parm : NULL_TREE;
17551 node->simdclone->args[i].orig_type = parm_type;
17552
43895be5 17553 switch (node->simdclone->args[i].arg_type)
d09768a4 17554 {
43895be5 17555 default:
d09768a4 17556 /* No adjustment necessary for scalar arguments. */
17557 adj.op = IPA_PARM_OP_COPY;
43895be5 17558 break;
17559 case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP:
9561765e 17560 case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_VARIABLE_STEP:
43895be5 17561 if (node->definition)
17562 node->simdclone->args[i].simd_array
17563 = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm)),
17564 TREE_TYPE (parm_type),
17565 node->simdclone->simdlen);
17566 adj.op = IPA_PARM_OP_COPY;
17567 break;
17568 case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_CONSTANT_STEP:
9561765e 17569 case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_VARIABLE_STEP:
43895be5 17570 case SIMD_CLONE_ARG_TYPE_VECTOR:
d09768a4 17571 if (INTEGRAL_TYPE_P (parm_type) || POINTER_TYPE_P (parm_type))
17572 veclen = node->simdclone->vecsize_int;
17573 else
17574 veclen = node->simdclone->vecsize_float;
17575 veclen /= GET_MODE_BITSIZE (TYPE_MODE (parm_type));
17576 if (veclen > node->simdclone->simdlen)
17577 veclen = node->simdclone->simdlen;
17578 adj.arg_prefix = "simd";
fdf7662c 17579 if (POINTER_TYPE_P (parm_type))
17580 adj.type = build_vector_type (pointer_sized_int_node, veclen);
17581 else
17582 adj.type = build_vector_type (parm_type, veclen);
d09768a4 17583 node->simdclone->args[i].vector_type = adj.type;
17584 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
17585 {
17586 adjustments.safe_push (adj);
17587 if (j == veclen)
17588 {
17589 memset (&adj, 0, sizeof (adj));
17590 adj.op = IPA_PARM_OP_NEW;
17591 adj.arg_prefix = "simd";
17592 adj.base_index = i;
17593 adj.type = node->simdclone->args[i].vector_type;
17594 }
17595 }
17596
17597 if (node->definition)
17598 node->simdclone->args[i].simd_array
17599 = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm)),
17600 parm_type, node->simdclone->simdlen);
17601 }
17602 adjustments.safe_push (adj);
17603 }
17604
17605 if (node->simdclone->inbranch)
17606 {
17607 tree base_type
17608 = simd_clone_compute_base_data_type (node->simdclone->origin,
17609 node->simdclone);
17610
17611 memset (&adj, 0, sizeof (adj));
17612 adj.op = IPA_PARM_OP_NEW;
17613 adj.arg_prefix = "mask";
17614
17615 adj.base_index = i;
17616 if (INTEGRAL_TYPE_P (base_type) || POINTER_TYPE_P (base_type))
17617 veclen = node->simdclone->vecsize_int;
17618 else
17619 veclen = node->simdclone->vecsize_float;
17620 veclen /= GET_MODE_BITSIZE (TYPE_MODE (base_type));
17621 if (veclen > node->simdclone->simdlen)
17622 veclen = node->simdclone->simdlen;
fdf7662c 17623 if (POINTER_TYPE_P (base_type))
17624 adj.type = build_vector_type (pointer_sized_int_node, veclen);
17625 else
17626 adj.type = build_vector_type (base_type, veclen);
d09768a4 17627 adjustments.safe_push (adj);
17628
17629 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
17630 adjustments.safe_push (adj);
17631
17632 /* We have previously allocated one extra entry for the mask. Use
17633 it and fill it. */
17634 struct cgraph_simd_clone *sc = node->simdclone;
17635 sc->nargs++;
17636 if (node->definition)
17637 {
17638 sc->args[i].orig_arg
17639 = build_decl (UNKNOWN_LOCATION, PARM_DECL, NULL, base_type);
17640 sc->args[i].simd_array
17641 = create_tmp_simd_array ("mask", base_type, sc->simdlen);
17642 }
17643 sc->args[i].orig_type = base_type;
17644 sc->args[i].arg_type = SIMD_CLONE_ARG_TYPE_MASK;
17645 }
17646
17647 if (node->definition)
17648 ipa_modify_formal_parameters (node->decl, adjustments);
17649 else
17650 {
17651 tree new_arg_types = NULL_TREE, new_reversed;
17652 bool last_parm_void = false;
17653 if (args.length () > 0 && args.last () == void_type_node)
17654 last_parm_void = true;
17655
17656 gcc_assert (TYPE_ARG_TYPES (TREE_TYPE (node->decl)));
17657 j = adjustments.length ();
17658 for (i = 0; i < j; i++)
17659 {
17660 struct ipa_parm_adjustment *adj = &adjustments[i];
17661 tree ptype;
17662 if (adj->op == IPA_PARM_OP_COPY)
17663 ptype = args[adj->base_index];
17664 else
17665 ptype = adj->type;
17666 new_arg_types = tree_cons (NULL_TREE, ptype, new_arg_types);
17667 }
17668 new_reversed = nreverse (new_arg_types);
17669 if (last_parm_void)
17670 {
17671 if (new_reversed)
17672 TREE_CHAIN (new_arg_types) = void_list_node;
17673 else
17674 new_reversed = void_list_node;
17675 }
17676
17677 tree new_type = build_distinct_type_copy (TREE_TYPE (node->decl));
17678 TYPE_ARG_TYPES (new_type) = new_reversed;
17679 TREE_TYPE (node->decl) = new_type;
17680
17681 adjustments.release ();
17682 }
17683 args.release ();
17684 return adjustments;
17685}
17686
17687/* Initialize and copy the function arguments in NODE to their
17688 corresponding local simd arrays. Returns a fresh gimple_seq with
17689 the instruction sequence generated. */
17690
17691static gimple_seq
17692simd_clone_init_simd_arrays (struct cgraph_node *node,
17693 ipa_parm_adjustment_vec adjustments)
17694{
17695 gimple_seq seq = NULL;
17696 unsigned i = 0, j = 0, k;
17697
17698 for (tree arg = DECL_ARGUMENTS (node->decl);
17699 arg;
17700 arg = DECL_CHAIN (arg), i++, j++)
17701 {
43895be5 17702 if (adjustments[j].op == IPA_PARM_OP_COPY
17703 || POINTER_TYPE_P (TREE_TYPE (arg)))
d09768a4 17704 continue;
17705
17706 node->simdclone->args[i].vector_arg = arg;
17707
17708 tree array = node->simdclone->args[i].simd_array;
17709 if (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg)) == node->simdclone->simdlen)
17710 {
17711 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
17712 tree ptr = build_fold_addr_expr (array);
17713 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
17714 build_int_cst (ptype, 0));
17715 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
17716 gimplify_and_add (t, &seq);
17717 }
17718 else
17719 {
17720 unsigned int simdlen = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg));
17721 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
17722 for (k = 0; k < node->simdclone->simdlen; k += simdlen)
17723 {
17724 tree ptr = build_fold_addr_expr (array);
17725 int elemsize;
17726 if (k)
17727 {
17728 arg = DECL_CHAIN (arg);
17729 j++;
17730 }
17731 elemsize
17732 = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg))));
17733 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
17734 build_int_cst (ptype, k * elemsize));
17735 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
17736 gimplify_and_add (t, &seq);
17737 }
17738 }
17739 }
17740 return seq;
17741}
17742
17743/* Callback info for ipa_simd_modify_stmt_ops below. */
17744
17745struct modify_stmt_info {
17746 ipa_parm_adjustment_vec adjustments;
42acab1c 17747 gimple *stmt;
d09768a4 17748 /* True if the parent statement was modified by
17749 ipa_simd_modify_stmt_ops. */
17750 bool modified;
17751};
17752
17753/* Callback for walk_gimple_op.
17754
17755 Adjust operands from a given statement as specified in the
17756 adjustments vector in the callback data. */
17757
17758static tree
17759ipa_simd_modify_stmt_ops (tree *tp, int *walk_subtrees, void *data)
17760{
17761 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
2d78e89f 17762 struct modify_stmt_info *info = (struct modify_stmt_info *) wi->info;
17763 tree *orig_tp = tp;
17764 if (TREE_CODE (*tp) == ADDR_EXPR)
17765 tp = &TREE_OPERAND (*tp, 0);
17766 struct ipa_parm_adjustment *cand = NULL;
17767 if (TREE_CODE (*tp) == PARM_DECL)
17768 cand = ipa_get_adjustment_candidate (&tp, NULL, info->adjustments, true);
17769 else
d09768a4 17770 {
d09768a4 17771 if (TYPE_P (*tp))
17772 *walk_subtrees = 0;
d09768a4 17773 }
d09768a4 17774
2d78e89f 17775 tree repl = NULL_TREE;
17776 if (cand)
17777 repl = unshare_expr (cand->new_decl);
17778 else
d09768a4 17779 {
2d78e89f 17780 if (tp != orig_tp)
17781 {
17782 *walk_subtrees = 0;
17783 bool modified = info->modified;
17784 info->modified = false;
17785 walk_tree (tp, ipa_simd_modify_stmt_ops, wi, wi->pset);
17786 if (!info->modified)
17787 {
17788 info->modified = modified;
17789 return NULL_TREE;
17790 }
17791 info->modified = modified;
17792 repl = *tp;
17793 }
17794 else
17795 return NULL_TREE;
d09768a4 17796 }
2d78e89f 17797
17798 if (tp != orig_tp)
d09768a4 17799 {
2d78e89f 17800 repl = build_fold_addr_expr (repl);
42acab1c 17801 gimple *stmt;
9c1dd4d9 17802 if (is_gimple_debug (info->stmt))
17803 {
17804 tree vexpr = make_node (DEBUG_EXPR_DECL);
17805 stmt = gimple_build_debug_source_bind (vexpr, repl, NULL);
17806 DECL_ARTIFICIAL (vexpr) = 1;
17807 TREE_TYPE (vexpr) = TREE_TYPE (repl);
17808 DECL_MODE (vexpr) = TYPE_MODE (TREE_TYPE (repl));
17809 repl = vexpr;
17810 }
17811 else
17812 {
f9e245b2 17813 stmt = gimple_build_assign (make_ssa_name (TREE_TYPE (repl)), repl);
9c1dd4d9 17814 repl = gimple_assign_lhs (stmt);
17815 }
2d78e89f 17816 gimple_stmt_iterator gsi = gsi_for_stmt (info->stmt);
d09768a4 17817 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
2d78e89f 17818 *orig_tp = repl;
d09768a4 17819 }
2d78e89f 17820 else if (!useless_type_conversion_p (TREE_TYPE (*tp), TREE_TYPE (repl)))
d09768a4 17821 {
17822 tree vce = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (*tp), repl);
17823 *tp = vce;
17824 }
17825 else
17826 *tp = repl;
17827
17828 info->modified = true;
d09768a4 17829 return NULL_TREE;
17830}
17831
17832/* Traverse the function body and perform all modifications as
17833 described in ADJUSTMENTS. At function return, ADJUSTMENTS will be
17834 modified such that the replacement/reduction value will now be an
17835 offset into the corresponding simd_array.
17836
17837 This function will replace all function argument uses with their
17838 corresponding simd array elements, and ajust the return values
17839 accordingly. */
17840
17841static void
17842ipa_simd_modify_function_body (struct cgraph_node *node,
17843 ipa_parm_adjustment_vec adjustments,
17844 tree retval_array, tree iter)
17845{
17846 basic_block bb;
2d78e89f 17847 unsigned int i, j, l;
d09768a4 17848
17849 /* Re-use the adjustments array, but this time use it to replace
17850 every function argument use to an offset into the corresponding
17851 simd_array. */
17852 for (i = 0, j = 0; i < node->simdclone->nargs; ++i, ++j)
17853 {
17854 if (!node->simdclone->args[i].vector_arg)
17855 continue;
17856
17857 tree basetype = TREE_TYPE (node->simdclone->args[i].orig_arg);
17858 tree vectype = TREE_TYPE (node->simdclone->args[i].vector_arg);
17859 adjustments[j].new_decl
17860 = build4 (ARRAY_REF,
17861 basetype,
17862 node->simdclone->args[i].simd_array,
17863 iter,
17864 NULL_TREE, NULL_TREE);
17865 if (adjustments[j].op == IPA_PARM_OP_NONE
17866 && TYPE_VECTOR_SUBPARTS (vectype) < node->simdclone->simdlen)
17867 j += node->simdclone->simdlen / TYPE_VECTOR_SUBPARTS (vectype) - 1;
17868 }
17869
2d78e89f 17870 l = adjustments.length ();
17871 for (i = 1; i < num_ssa_names; i++)
17872 {
17873 tree name = ssa_name (i);
17874 if (name
17875 && SSA_NAME_VAR (name)
17876 && TREE_CODE (SSA_NAME_VAR (name)) == PARM_DECL)
17877 {
17878 for (j = 0; j < l; j++)
17879 if (SSA_NAME_VAR (name) == adjustments[j].base
17880 && adjustments[j].new_decl)
17881 {
17882 tree base_var;
17883 if (adjustments[j].new_ssa_base == NULL_TREE)
17884 {
17885 base_var
17886 = copy_var_decl (adjustments[j].base,
17887 DECL_NAME (adjustments[j].base),
17888 TREE_TYPE (adjustments[j].base));
17889 adjustments[j].new_ssa_base = base_var;
17890 }
17891 else
17892 base_var = adjustments[j].new_ssa_base;
17893 if (SSA_NAME_IS_DEFAULT_DEF (name))
17894 {
17895 bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
17896 gimple_stmt_iterator gsi = gsi_after_labels (bb);
17897 tree new_decl = unshare_expr (adjustments[j].new_decl);
17898 set_ssa_default_def (cfun, adjustments[j].base, NULL_TREE);
17899 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
17900 SSA_NAME_IS_DEFAULT_DEF (name) = 0;
42acab1c 17901 gimple *stmt = gimple_build_assign (name, new_decl);
2d78e89f 17902 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
17903 }
17904 else
17905 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
17906 }
17907 }
17908 }
17909
d09768a4 17910 struct modify_stmt_info info;
17911 info.adjustments = adjustments;
17912
17913 FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl))
17914 {
17915 gimple_stmt_iterator gsi;
17916
17917 gsi = gsi_start_bb (bb);
17918 while (!gsi_end_p (gsi))
17919 {
42acab1c 17920 gimple *stmt = gsi_stmt (gsi);
d09768a4 17921 info.stmt = stmt;
17922 struct walk_stmt_info wi;
17923
17924 memset (&wi, 0, sizeof (wi));
17925 info.modified = false;
17926 wi.info = &info;
17927 walk_gimple_op (stmt, ipa_simd_modify_stmt_ops, &wi);
17928
1a91d914 17929 if (greturn *return_stmt = dyn_cast <greturn *> (stmt))
d09768a4 17930 {
1a91d914 17931 tree retval = gimple_return_retval (return_stmt);
d09768a4 17932 if (!retval)
17933 {
17934 gsi_remove (&gsi, true);
17935 continue;
17936 }
17937
17938 /* Replace `return foo' with `retval_array[iter] = foo'. */
17939 tree ref = build4 (ARRAY_REF, TREE_TYPE (retval),
17940 retval_array, iter, NULL, NULL);
17941 stmt = gimple_build_assign (ref, retval);
17942 gsi_replace (&gsi, stmt, true);
17943 info.modified = true;
17944 }
17945
17946 if (info.modified)
17947 {
17948 update_stmt (stmt);
17949 if (maybe_clean_eh_stmt (stmt))
17950 gimple_purge_dead_eh_edges (gimple_bb (stmt));
17951 }
17952 gsi_next (&gsi);
17953 }
17954 }
17955}
17956
9561765e 17957/* Helper function of simd_clone_adjust, return linear step addend
17958 of Ith argument. */
17959
17960static tree
17961simd_clone_linear_addend (struct cgraph_node *node, unsigned int i,
17962 tree addtype, basic_block entry_bb)
17963{
17964 tree ptype = NULL_TREE;
17965 switch (node->simdclone->args[i].arg_type)
17966 {
17967 case SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP:
17968 case SIMD_CLONE_ARG_TYPE_LINEAR_REF_CONSTANT_STEP:
17969 case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_CONSTANT_STEP:
17970 case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP:
17971 return build_int_cst (addtype, node->simdclone->args[i].linear_step);
17972 case SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP:
17973 case SIMD_CLONE_ARG_TYPE_LINEAR_REF_VARIABLE_STEP:
17974 ptype = TREE_TYPE (node->simdclone->args[i].orig_arg);
17975 break;
17976 case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_VARIABLE_STEP:
17977 case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_VARIABLE_STEP:
17978 ptype = TREE_TYPE (TREE_TYPE (node->simdclone->args[i].orig_arg));
17979 break;
17980 default:
17981 gcc_unreachable ();
17982 }
17983
17984 unsigned int idx = node->simdclone->args[i].linear_step;
17985 tree arg = node->simdclone->args[idx].orig_arg;
17986 gcc_assert (is_gimple_reg_type (TREE_TYPE (arg)));
17987 gimple_stmt_iterator gsi = gsi_after_labels (entry_bb);
17988 gimple *g;
17989 tree ret;
17990 if (is_gimple_reg (arg))
17991 ret = get_or_create_ssa_default_def (cfun, arg);
17992 else
17993 {
17994 g = gimple_build_assign (make_ssa_name (TREE_TYPE (arg)), arg);
17995 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
17996 ret = gimple_assign_lhs (g);
17997 }
17998 if (TREE_CODE (TREE_TYPE (arg)) == REFERENCE_TYPE)
17999 {
18000 g = gimple_build_assign (make_ssa_name (TREE_TYPE (TREE_TYPE (arg))),
18001 build_simple_mem_ref (ret));
18002 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
18003 ret = gimple_assign_lhs (g);
18004 }
18005 if (!useless_type_conversion_p (addtype, TREE_TYPE (ret)))
18006 {
18007 g = gimple_build_assign (make_ssa_name (addtype), NOP_EXPR, ret);
18008 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
18009 ret = gimple_assign_lhs (g);
18010 }
18011 if (POINTER_TYPE_P (ptype))
18012 {
18013 tree size = TYPE_SIZE_UNIT (TREE_TYPE (ptype));
18014 if (size && TREE_CODE (size) == INTEGER_CST)
18015 {
18016 g = gimple_build_assign (make_ssa_name (addtype), MULT_EXPR,
18017 ret, fold_convert (addtype, size));
18018 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
18019 ret = gimple_assign_lhs (g);
18020 }
18021 }
18022 return ret;
18023}
18024
d09768a4 18025/* Adjust the argument types in NODE to their appropriate vector
18026 counterparts. */
18027
18028static void
18029simd_clone_adjust (struct cgraph_node *node)
18030{
18031 push_cfun (DECL_STRUCT_FUNCTION (node->decl));
18032
18033 targetm.simd_clone.adjust (node);
18034
18035 tree retval = simd_clone_adjust_return_type (node);
18036 ipa_parm_adjustment_vec adjustments
18037 = simd_clone_adjust_argument_types (node);
18038
18039 push_gimplify_context ();
18040
18041 gimple_seq seq = simd_clone_init_simd_arrays (node, adjustments);
18042
18043 /* Adjust all uses of vector arguments accordingly. Adjust all
18044 return values accordingly. */
18045 tree iter = create_tmp_var (unsigned_type_node, "iter");
f9e245b2 18046 tree iter1 = make_ssa_name (iter);
18047 tree iter2 = make_ssa_name (iter);
d09768a4 18048 ipa_simd_modify_function_body (node, adjustments, retval, iter1);
18049
18050 /* Initialize the iteration variable. */
18051 basic_block entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
18052 basic_block body_bb = split_block_after_labels (entry_bb)->dest;
18053 gimple_stmt_iterator gsi = gsi_after_labels (entry_bb);
18054 /* Insert the SIMD array and iv initialization at function
18055 entry. */
18056 gsi_insert_seq_before (&gsi, seq, GSI_NEW_STMT);
18057
18058 pop_gimplify_context (NULL);
18059
18060 /* Create a new BB right before the original exit BB, to hold the
18061 iteration increment and the condition/branch. */
18062 basic_block orig_exit = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), 0)->src;
18063 basic_block incr_bb = create_empty_bb (orig_exit);
343ee723 18064 add_bb_to_loop (incr_bb, body_bb->loop_father);
d09768a4 18065 /* The succ of orig_exit was EXIT_BLOCK_PTR_FOR_FN (cfun), with an empty
18066 flag. Set it now to be a FALLTHRU_EDGE. */
18067 gcc_assert (EDGE_COUNT (orig_exit->succs) == 1);
18068 EDGE_SUCC (orig_exit, 0)->flags |= EDGE_FALLTHRU;
18069 for (unsigned i = 0;
18070 i < EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds); ++i)
18071 {
18072 edge e = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), i);
18073 redirect_edge_succ (e, incr_bb);
18074 }
18075 edge e = make_edge (incr_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
18076 e->probability = REG_BR_PROB_BASE;
18077 gsi = gsi_last_bb (incr_bb);
42acab1c 18078 gimple *g = gimple_build_assign (iter2, PLUS_EXPR, iter1,
e9cf809e 18079 build_int_cst (unsigned_type_node, 1));
d09768a4 18080 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
18081
18082 /* Mostly annotate the loop for the vectorizer (the rest is done below). */
18083 struct loop *loop = alloc_loop ();
4c73695b 18084 cfun->has_force_vectorize_loops = true;
d09768a4 18085 loop->safelen = node->simdclone->simdlen;
4c73695b 18086 loop->force_vectorize = true;
d09768a4 18087 loop->header = body_bb;
d09768a4 18088
18089 /* Branch around the body if the mask applies. */
18090 if (node->simdclone->inbranch)
18091 {
18092 gimple_stmt_iterator gsi = gsi_last_bb (loop->header);
18093 tree mask_array
18094 = node->simdclone->args[node->simdclone->nargs - 1].simd_array;
f9e245b2 18095 tree mask = make_ssa_name (TREE_TYPE (TREE_TYPE (mask_array)));
d09768a4 18096 tree aref = build4 (ARRAY_REF,
18097 TREE_TYPE (TREE_TYPE (mask_array)),
18098 mask_array, iter1,
18099 NULL, NULL);
18100 g = gimple_build_assign (mask, aref);
18101 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
18102 int bitsize = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (aref)));
18103 if (!INTEGRAL_TYPE_P (TREE_TYPE (aref)))
18104 {
18105 aref = build1 (VIEW_CONVERT_EXPR,
18106 build_nonstandard_integer_type (bitsize, 0), mask);
f9e245b2 18107 mask = make_ssa_name (TREE_TYPE (aref));
d09768a4 18108 g = gimple_build_assign (mask, aref);
18109 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
18110 }
18111
18112 g = gimple_build_cond (EQ_EXPR, mask, build_zero_cst (TREE_TYPE (mask)),
18113 NULL, NULL);
18114 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
18115 make_edge (loop->header, incr_bb, EDGE_TRUE_VALUE);
18116 FALLTHRU_EDGE (loop->header)->flags = EDGE_FALSE_VALUE;
18117 }
18118
18119 /* Generate the condition. */
18120 g = gimple_build_cond (LT_EXPR,
18121 iter2,
18122 build_int_cst (unsigned_type_node,
18123 node->simdclone->simdlen),
18124 NULL, NULL);
18125 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
18126 e = split_block (incr_bb, gsi_stmt (gsi));
18127 basic_block latch_bb = e->dest;
343ee723 18128 basic_block new_exit_bb;
4302d619 18129 new_exit_bb = split_block_after_labels (latch_bb)->dest;
d09768a4 18130 loop->latch = latch_bb;
18131
18132 redirect_edge_succ (FALLTHRU_EDGE (latch_bb), body_bb);
18133
18134 make_edge (incr_bb, new_exit_bb, EDGE_FALSE_VALUE);
18135 /* The successor of incr_bb is already pointing to latch_bb; just
18136 change the flags.
18137 make_edge (incr_bb, latch_bb, EDGE_TRUE_VALUE); */
18138 FALLTHRU_EDGE (incr_bb)->flags = EDGE_TRUE_VALUE;
18139
1a91d914 18140 gphi *phi = create_phi_node (iter1, body_bb);
d09768a4 18141 edge preheader_edge = find_edge (entry_bb, body_bb);
18142 edge latch_edge = single_succ_edge (latch_bb);
18143 add_phi_arg (phi, build_zero_cst (unsigned_type_node), preheader_edge,
18144 UNKNOWN_LOCATION);
18145 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
18146
18147 /* Generate the new return. */
18148 gsi = gsi_last_bb (new_exit_bb);
18149 if (retval
18150 && TREE_CODE (retval) == VIEW_CONVERT_EXPR
18151 && TREE_CODE (TREE_OPERAND (retval, 0)) == RESULT_DECL)
18152 retval = TREE_OPERAND (retval, 0);
18153 else if (retval)
18154 {
18155 retval = build1 (VIEW_CONVERT_EXPR,
18156 TREE_TYPE (TREE_TYPE (node->decl)),
18157 retval);
18158 retval = force_gimple_operand_gsi (&gsi, retval, true, NULL,
18159 false, GSI_CONTINUE_LINKING);
18160 }
18161 g = gimple_build_return (retval);
18162 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
18163
18164 /* Handle aligned clauses by replacing default defs of the aligned
18165 uniform args with __builtin_assume_aligned (arg_N(D), alignment)
18166 lhs. Handle linear by adding PHIs. */
18167 for (unsigned i = 0; i < node->simdclone->nargs; i++)
97a82d40 18168 if (node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
18169 && (TREE_ADDRESSABLE (node->simdclone->args[i].orig_arg)
18170 || !is_gimple_reg_type
18171 (TREE_TYPE (node->simdclone->args[i].orig_arg))))
18172 {
18173 tree orig_arg = node->simdclone->args[i].orig_arg;
18174 if (is_gimple_reg_type (TREE_TYPE (orig_arg)))
18175 iter1 = make_ssa_name (TREE_TYPE (orig_arg));
18176 else
18177 {
18178 iter1 = create_tmp_var_raw (TREE_TYPE (orig_arg));
18179 gimple_add_tmp_var (iter1);
18180 }
18181 gsi = gsi_after_labels (entry_bb);
18182 g = gimple_build_assign (iter1, orig_arg);
18183 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
18184 gsi = gsi_after_labels (body_bb);
18185 g = gimple_build_assign (orig_arg, iter1);
18186 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
18187 }
18188 else if (node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
18189 && DECL_BY_REFERENCE (node->simdclone->args[i].orig_arg)
18190 && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
18191 == REFERENCE_TYPE
18192 && TREE_ADDRESSABLE
18193 (TREE_TYPE (TREE_TYPE (node->simdclone->args[i].orig_arg))))
18194 {
18195 tree orig_arg = node->simdclone->args[i].orig_arg;
18196 tree def = ssa_default_def (cfun, orig_arg);
18197 if (def && !has_zero_uses (def))
18198 {
18199 iter1 = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (orig_arg)));
18200 gimple_add_tmp_var (iter1);
18201 gsi = gsi_after_labels (entry_bb);
18202 g = gimple_build_assign (iter1, build_simple_mem_ref (def));
18203 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
18204 gsi = gsi_after_labels (body_bb);
18205 g = gimple_build_assign (build_simple_mem_ref (def), iter1);
18206 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
18207 }
18208 }
18209 else if (node->simdclone->args[i].alignment
18210 && node->simdclone->args[i].arg_type
18211 == SIMD_CLONE_ARG_TYPE_UNIFORM
18212 && (node->simdclone->args[i].alignment
18213 & (node->simdclone->args[i].alignment - 1)) == 0
18214 && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
18215 == POINTER_TYPE)
d09768a4 18216 {
18217 unsigned int alignment = node->simdclone->args[i].alignment;
18218 tree orig_arg = node->simdclone->args[i].orig_arg;
18219 tree def = ssa_default_def (cfun, orig_arg);
6db33a3d 18220 if (def && !has_zero_uses (def))
d09768a4 18221 {
18222 tree fn = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
18223 gimple_seq seq = NULL;
18224 bool need_cvt = false;
1a91d914 18225 gcall *call
d09768a4 18226 = gimple_build_call (fn, 2, def, size_int (alignment));
18227 g = call;
18228 if (!useless_type_conversion_p (TREE_TYPE (orig_arg),
18229 ptr_type_node))
18230 need_cvt = true;
f9e245b2 18231 tree t = make_ssa_name (need_cvt ? ptr_type_node : orig_arg);
d09768a4 18232 gimple_call_set_lhs (g, t);
18233 gimple_seq_add_stmt_without_update (&seq, g);
18234 if (need_cvt)
18235 {
f9e245b2 18236 t = make_ssa_name (orig_arg);
e9cf809e 18237 g = gimple_build_assign (t, NOP_EXPR, gimple_call_lhs (g));
d09768a4 18238 gimple_seq_add_stmt_without_update (&seq, g);
18239 }
18240 gsi_insert_seq_on_edge_immediate
18241 (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)), seq);
18242
18243 entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
18244 int freq = compute_call_stmt_bb_frequency (current_function_decl,
18245 entry_bb);
415d1b9a 18246 node->create_edge (cgraph_node::get_create (fn),
18247 call, entry_bb->count, freq);
d09768a4 18248
18249 imm_use_iterator iter;
18250 use_operand_p use_p;
42acab1c 18251 gimple *use_stmt;
d09768a4 18252 tree repl = gimple_get_lhs (g);
18253 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
18254 if (is_gimple_debug (use_stmt) || use_stmt == call)
18255 continue;
18256 else
18257 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
18258 SET_USE (use_p, repl);
18259 }
18260 }
43895be5 18261 else if ((node->simdclone->args[i].arg_type
18262 == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
18263 || (node->simdclone->args[i].arg_type
9561765e 18264 == SIMD_CLONE_ARG_TYPE_LINEAR_REF_CONSTANT_STEP)
18265 || (node->simdclone->args[i].arg_type
18266 == SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP)
18267 || (node->simdclone->args[i].arg_type
18268 == SIMD_CLONE_ARG_TYPE_LINEAR_REF_VARIABLE_STEP))
d09768a4 18269 {
18270 tree orig_arg = node->simdclone->args[i].orig_arg;
d09768a4 18271 gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
18272 || POINTER_TYPE_P (TREE_TYPE (orig_arg)));
97a82d40 18273 tree def = NULL_TREE;
18274 if (TREE_ADDRESSABLE (orig_arg))
18275 {
18276 def = make_ssa_name (TREE_TYPE (orig_arg));
18277 iter1 = make_ssa_name (TREE_TYPE (orig_arg));
18278 iter2 = make_ssa_name (TREE_TYPE (orig_arg));
18279 gsi = gsi_after_labels (entry_bb);
18280 g = gimple_build_assign (def, orig_arg);
18281 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
18282 }
18283 else
18284 {
18285 def = ssa_default_def (cfun, orig_arg);
18286 if (!def || has_zero_uses (def))
18287 def = NULL_TREE;
18288 else
18289 {
18290 iter1 = make_ssa_name (orig_arg);
18291 iter2 = make_ssa_name (orig_arg);
18292 }
18293 }
18294 if (def)
d09768a4 18295 {
d09768a4 18296 phi = create_phi_node (iter1, body_bb);
18297 add_phi_arg (phi, def, preheader_edge, UNKNOWN_LOCATION);
18298 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
18299 enum tree_code code = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
18300 ? PLUS_EXPR : POINTER_PLUS_EXPR;
18301 tree addtype = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
18302 ? TREE_TYPE (orig_arg) : sizetype;
9561765e 18303 tree addcst = simd_clone_linear_addend (node, i, addtype,
18304 entry_bb);
d09768a4 18305 gsi = gsi_last_bb (incr_bb);
9561765e 18306 g = gimple_build_assign (iter2, code, iter1, addcst);
d09768a4 18307 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
18308
18309 imm_use_iterator iter;
18310 use_operand_p use_p;
42acab1c 18311 gimple *use_stmt;
97a82d40 18312 if (TREE_ADDRESSABLE (orig_arg))
18313 {
18314 gsi = gsi_after_labels (body_bb);
18315 g = gimple_build_assign (orig_arg, iter1);
18316 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
18317 }
18318 else
18319 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
18320 if (use_stmt == phi)
18321 continue;
18322 else
18323 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
18324 SET_USE (use_p, iter1);
d09768a4 18325 }
18326 }
43895be5 18327 else if (node->simdclone->args[i].arg_type
9561765e 18328 == SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP
18329 || (node->simdclone->args[i].arg_type
18330 == SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_VARIABLE_STEP))
43895be5 18331 {
18332 tree orig_arg = node->simdclone->args[i].orig_arg;
18333 tree def = ssa_default_def (cfun, orig_arg);
18334 gcc_assert (!TREE_ADDRESSABLE (orig_arg)
18335 && TREE_CODE (TREE_TYPE (orig_arg)) == REFERENCE_TYPE);
18336 if (def && !has_zero_uses (def))
18337 {
18338 tree rtype = TREE_TYPE (TREE_TYPE (orig_arg));
18339 iter1 = make_ssa_name (orig_arg);
18340 iter2 = make_ssa_name (orig_arg);
18341 tree iter3 = make_ssa_name (rtype);
18342 tree iter4 = make_ssa_name (rtype);
18343 tree iter5 = make_ssa_name (rtype);
18344 gsi = gsi_after_labels (entry_bb);
18345 gimple *load
18346 = gimple_build_assign (iter3, build_simple_mem_ref (def));
18347 gsi_insert_before (&gsi, load, GSI_NEW_STMT);
18348
18349 tree array = node->simdclone->args[i].simd_array;
18350 TREE_ADDRESSABLE (array) = 1;
18351 tree ptr = build_fold_addr_expr (array);
18352 phi = create_phi_node (iter1, body_bb);
18353 add_phi_arg (phi, ptr, preheader_edge, UNKNOWN_LOCATION);
18354 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
18355 g = gimple_build_assign (iter2, POINTER_PLUS_EXPR, iter1,
18356 TYPE_SIZE_UNIT (TREE_TYPE (iter3)));
18357 gsi = gsi_last_bb (incr_bb);
18358 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
18359
18360 phi = create_phi_node (iter4, body_bb);
18361 add_phi_arg (phi, iter3, preheader_edge, UNKNOWN_LOCATION);
18362 add_phi_arg (phi, iter5, latch_edge, UNKNOWN_LOCATION);
18363 enum tree_code code = INTEGRAL_TYPE_P (TREE_TYPE (iter3))
18364 ? PLUS_EXPR : POINTER_PLUS_EXPR;
18365 tree addtype = INTEGRAL_TYPE_P (TREE_TYPE (iter3))
18366 ? TREE_TYPE (iter3) : sizetype;
9561765e 18367 tree addcst = simd_clone_linear_addend (node, i, addtype,
18368 entry_bb);
43895be5 18369 g = gimple_build_assign (iter5, code, iter4, addcst);
18370 gsi = gsi_last_bb (incr_bb);
18371 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
18372
18373 g = gimple_build_assign (build_simple_mem_ref (iter1), iter4);
18374 gsi = gsi_after_labels (body_bb);
18375 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
18376
18377 imm_use_iterator iter;
18378 use_operand_p use_p;
18379 gimple *use_stmt;
18380 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
18381 if (use_stmt == load)
18382 continue;
18383 else
18384 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
18385 SET_USE (use_p, iter1);
18386
18387 if (!TYPE_READONLY (rtype))
18388 {
18389 tree v = make_ssa_name (rtype);
18390 tree aref = build4 (ARRAY_REF, rtype, array,
18391 size_zero_node, NULL_TREE,
18392 NULL_TREE);
18393 gsi = gsi_after_labels (new_exit_bb);
18394 g = gimple_build_assign (v, aref);
18395 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
18396 g = gimple_build_assign (build_simple_mem_ref (def), v);
18397 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
18398 }
18399 }
18400 }
d09768a4 18401
18402 calculate_dominance_info (CDI_DOMINATORS);
18403 add_loop (loop, loop->header->loop_father);
18404 update_ssa (TODO_update_ssa);
18405
18406 pop_cfun ();
18407}
18408
18409/* If the function in NODE is tagged as an elemental SIMD function,
18410 create the appropriate SIMD clones. */
18411
18412static void
18413expand_simd_clones (struct cgraph_node *node)
18414{
d09768a4 18415 tree attr = lookup_attribute ("omp declare simd",
18416 DECL_ATTRIBUTES (node->decl));
ea0695f9 18417 if (attr == NULL_TREE
18418 || node->global.inlined_to
18419 || lookup_attribute ("noclone", DECL_ATTRIBUTES (node->decl)))
d09768a4 18420 return;
ea0695f9 18421
d09768a4 18422 /* Ignore
18423 #pragma omp declare simd
18424 extern int foo ();
18425 in C, there we don't know the argument types at all. */
18426 if (!node->definition
18427 && TYPE_ARG_TYPES (TREE_TYPE (node->decl)) == NULL_TREE)
18428 return;
18429
b2fbac0f 18430 /* Call this before creating clone_info, as it might ggc_collect. */
18431 if (node->definition && node->has_gimple_body_p ())
18432 node->get_body ();
18433
d09768a4 18434 do
18435 {
18436 /* Start with parsing the "omp declare simd" attribute(s). */
18437 bool inbranch_clause_specified;
18438 struct cgraph_simd_clone *clone_info
18439 = simd_clone_clauses_extract (node, TREE_VALUE (attr),
18440 &inbranch_clause_specified);
18441 if (clone_info == NULL)
18442 continue;
18443
18444 int orig_simdlen = clone_info->simdlen;
18445 tree base_type = simd_clone_compute_base_data_type (node, clone_info);
18446 /* The target can return 0 (no simd clones should be created),
18447 1 (just one ISA of simd clones should be created) or higher
18448 count of ISA variants. In that case, clone_info is initialized
18449 for the first ISA variant. */
18450 int count
18451 = targetm.simd_clone.compute_vecsize_and_simdlen (node, clone_info,
18452 base_type, 0);
18453 if (count == 0)
18454 continue;
18455
18456 /* Loop over all COUNT ISA variants, and if !INBRANCH_CLAUSE_SPECIFIED,
18457 also create one inbranch and one !inbranch clone of it. */
18458 for (int i = 0; i < count * 2; i++)
18459 {
18460 struct cgraph_simd_clone *clone = clone_info;
18461 if (inbranch_clause_specified && (i & 1) != 0)
18462 continue;
18463
18464 if (i != 0)
18465 {
18466 clone = simd_clone_struct_alloc (clone_info->nargs
d09768a4 18467 + ((i & 1) != 0));
18468 simd_clone_struct_copy (clone, clone_info);
18469 /* Undo changes targetm.simd_clone.compute_vecsize_and_simdlen
18470 and simd_clone_adjust_argument_types did to the first
18471 clone's info. */
18472 clone->nargs -= clone_info->inbranch;
18473 clone->simdlen = orig_simdlen;
18474 /* And call the target hook again to get the right ISA. */
18475 targetm.simd_clone.compute_vecsize_and_simdlen (node, clone,
18476 base_type,
18477 i / 2);
18478 if ((i & 1) != 0)
18479 clone->inbranch = 1;
18480 }
18481
18482 /* simd_clone_mangle might fail if such a clone has been created
18483 already. */
18484 tree id = simd_clone_mangle (node, clone);
18485 if (id == NULL_TREE)
18486 continue;
18487
18488 /* Only when we are sure we want to create the clone actually
18489 clone the function (or definitions) or create another
18490 extern FUNCTION_DECL (for prototypes without definitions). */
18491 struct cgraph_node *n = simd_clone_create (node);
18492 if (n == NULL)
18493 continue;
18494
18495 n->simdclone = clone;
18496 clone->origin = node;
18497 clone->next_clone = NULL;
18498 if (node->simd_clones == NULL)
18499 {
18500 clone->prev_clone = n;
18501 node->simd_clones = n;
18502 }
18503 else
18504 {
18505 clone->prev_clone = node->simd_clones->simdclone->prev_clone;
18506 clone->prev_clone->simdclone->next_clone = n;
18507 node->simd_clones->simdclone->prev_clone = n;
18508 }
35ee1c66 18509 symtab->change_decl_assembler_name (n->decl, id);
d09768a4 18510 /* And finally adjust the return type, parameters and for
18511 definitions also function body. */
18512 if (node->definition)
18513 simd_clone_adjust (n);
18514 else
18515 {
18516 simd_clone_adjust_return_type (n);
18517 simd_clone_adjust_argument_types (n);
18518 }
18519 }
18520 }
18521 while ((attr = lookup_attribute ("omp declare simd", TREE_CHAIN (attr))));
18522}
18523
18524/* Entry point for IPA simd clone creation pass. */
18525
18526static unsigned int
18527ipa_omp_simd_clone (void)
18528{
18529 struct cgraph_node *node;
18530 FOR_EACH_FUNCTION (node)
18531 expand_simd_clones (node);
18532 return 0;
18533}
18534
7620bc82 18535namespace {
18536
18537const pass_data pass_data_omp_simd_clone =
d09768a4 18538{
18539 SIMPLE_IPA_PASS, /* type */
18540 "simdclone", /* name */
18541 OPTGROUP_NONE, /* optinfo_flags */
d09768a4 18542 TV_NONE, /* tv_id */
18543 ( PROP_ssa | PROP_cfg ), /* properties_required */
18544 0, /* properties_provided */
18545 0, /* properties_destroyed */
18546 0, /* todo_flags_start */
18547 0, /* todo_flags_finish */
18548};
18549
7620bc82 18550class pass_omp_simd_clone : public simple_ipa_opt_pass
d09768a4 18551{
18552public:
18553 pass_omp_simd_clone(gcc::context *ctxt)
18554 : simple_ipa_opt_pass(pass_data_omp_simd_clone, ctxt)
18555 {}
18556
18557 /* opt_pass methods: */
31315c24 18558 virtual bool gate (function *);
65b0537f 18559 virtual unsigned int execute (function *) { return ipa_omp_simd_clone (); }
d09768a4 18560};
18561
31315c24 18562bool
18563pass_omp_simd_clone::gate (function *)
18564{
c58a4cfd 18565 return targetm.simd_clone.compute_vecsize_and_simdlen != NULL;
31315c24 18566}
18567
7620bc82 18568} // anon namespace
18569
d09768a4 18570simple_ipa_opt_pass *
18571make_pass_omp_simd_clone (gcc::context *ctxt)
18572{
18573 return new pass_omp_simd_clone (ctxt);
18574}
cbe8bda8 18575
dccabdd1 18576/* Helper function for omp_finish_file routine. Takes decls from V_DECLS and
18577 adds their addresses and sizes to constructor-vector V_CTOR. */
18578static void
18579add_decls_addresses_to_decl_constructor (vec<tree, va_gc> *v_decls,
18580 vec<constructor_elt, va_gc> *v_ctor)
18581{
18582 unsigned len = vec_safe_length (v_decls);
18583 for (unsigned i = 0; i < len; i++)
18584 {
18585 tree it = (*v_decls)[i];
c0998828 18586 bool is_var = TREE_CODE (it) == VAR_DECL;
18587 bool is_link_var
18588 = is_var
18589#ifdef ACCEL_COMPILER
18590 && DECL_HAS_VALUE_EXPR_P (it)
18591#endif
18592 && lookup_attribute ("omp declare target link", DECL_ATTRIBUTES (it));
dccabdd1 18593
c0998828 18594 tree size = NULL_TREE;
18595 if (is_var)
18596 size = fold_convert (const_ptr_type_node, DECL_SIZE_UNIT (it));
18597
18598 tree addr;
18599 if (!is_link_var)
18600 addr = build_fold_addr_expr (it);
18601 else
18602 {
18603#ifdef ACCEL_COMPILER
18604 /* For "omp declare target link" vars add address of the pointer to
18605 the target table, instead of address of the var. */
18606 tree value_expr = DECL_VALUE_EXPR (it);
18607 tree link_ptr_decl = TREE_OPERAND (value_expr, 0);
18608 varpool_node::finalize_decl (link_ptr_decl);
18609 addr = build_fold_addr_expr (link_ptr_decl);
18610#else
18611 addr = build_fold_addr_expr (it);
18612#endif
18613
18614 /* Most significant bit of the size marks "omp declare target link"
18615 vars in host and target tables. */
18616 unsigned HOST_WIDE_INT isize = tree_to_uhwi (size);
18617 isize |= 1ULL << (int_size_in_bytes (const_ptr_type_node)
18618 * BITS_PER_UNIT - 1);
18619 size = wide_int_to_tree (const_ptr_type_node, isize);
18620 }
18621
18622 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE, addr);
18623 if (is_var)
18624 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE, size);
dccabdd1 18625 }
18626}
18627
18628/* Create new symbols containing (address, size) pairs for global variables,
18629 marked with "omp declare target" attribute, as well as addresses for the
ca4c3545 18630 functions, which are outlined offloading regions. */
dccabdd1 18631void
18632omp_finish_file (void)
18633{
18634 unsigned num_funcs = vec_safe_length (offload_funcs);
18635 unsigned num_vars = vec_safe_length (offload_vars);
18636
18637 if (num_funcs == 0 && num_vars == 0)
18638 return;
18639
18640 if (targetm_common.have_named_sections)
18641 {
18642 vec<constructor_elt, va_gc> *v_f, *v_v;
18643 vec_alloc (v_f, num_funcs);
18644 vec_alloc (v_v, num_vars * 2);
18645
18646 add_decls_addresses_to_decl_constructor (offload_funcs, v_f);
18647 add_decls_addresses_to_decl_constructor (offload_vars, v_v);
18648
18649 tree vars_decl_type = build_array_type_nelts (pointer_sized_int_node,
18650 num_vars * 2);
18651 tree funcs_decl_type = build_array_type_nelts (pointer_sized_int_node,
18652 num_funcs);
18653 TYPE_ALIGN (vars_decl_type) = TYPE_ALIGN (pointer_sized_int_node);
18654 TYPE_ALIGN (funcs_decl_type) = TYPE_ALIGN (pointer_sized_int_node);
18655 tree ctor_v = build_constructor (vars_decl_type, v_v);
18656 tree ctor_f = build_constructor (funcs_decl_type, v_f);
18657 TREE_CONSTANT (ctor_v) = TREE_CONSTANT (ctor_f) = 1;
18658 TREE_STATIC (ctor_v) = TREE_STATIC (ctor_f) = 1;
18659 tree funcs_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
18660 get_identifier (".offload_func_table"),
18661 funcs_decl_type);
18662 tree vars_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
18663 get_identifier (".offload_var_table"),
18664 vars_decl_type);
18665 TREE_STATIC (funcs_decl) = TREE_STATIC (vars_decl) = 1;
18666 /* Do not align tables more than TYPE_ALIGN (pointer_sized_int_node),
18667 otherwise a joint table in a binary will contain padding between
18668 tables from multiple object files. */
18669 DECL_USER_ALIGN (funcs_decl) = DECL_USER_ALIGN (vars_decl) = 1;
18670 DECL_ALIGN (funcs_decl) = TYPE_ALIGN (funcs_decl_type);
18671 DECL_ALIGN (vars_decl) = TYPE_ALIGN (vars_decl_type);
18672 DECL_INITIAL (funcs_decl) = ctor_f;
18673 DECL_INITIAL (vars_decl) = ctor_v;
18674 set_decl_section_name (funcs_decl, OFFLOAD_FUNC_TABLE_SECTION_NAME);
18675 set_decl_section_name (vars_decl, OFFLOAD_VAR_TABLE_SECTION_NAME);
18676
18677 varpool_node::finalize_decl (vars_decl);
18678 varpool_node::finalize_decl (funcs_decl);
7114ebdd 18679 }
dccabdd1 18680 else
18681 {
18682 for (unsigned i = 0; i < num_funcs; i++)
18683 {
18684 tree it = (*offload_funcs)[i];
18685 targetm.record_offload_symbol (it);
18686 }
18687 for (unsigned i = 0; i < num_vars; i++)
18688 {
18689 tree it = (*offload_vars)[i];
18690 targetm.record_offload_symbol (it);
18691 }
18692 }
18693}
18694
cbba99a0 18695/* Find the number of threads (POS = false), or thread number (POS =
18696 true) for an OpenACC region partitioned as MASK. Setup code
18697 required for the calculation is added to SEQ. */
18698
18699static tree
18700oacc_thread_numbers (bool pos, int mask, gimple_seq *seq)
18701{
18702 tree res = pos ? NULL_TREE : build_int_cst (unsigned_type_node, 1);
18703 unsigned ix;
18704
18705 /* Start at gang level, and examine relevant dimension indices. */
18706 for (ix = GOMP_DIM_GANG; ix != GOMP_DIM_MAX; ix++)
18707 if (GOMP_DIM_MASK (ix) & mask)
18708 {
18709 tree arg = build_int_cst (unsigned_type_node, ix);
18710
18711 if (res)
18712 {
18713 /* We had an outer index, so scale that by the size of
18714 this dimension. */
18715 tree n = create_tmp_var (integer_type_node);
18716 gimple *call
18717 = gimple_build_call_internal (IFN_GOACC_DIM_SIZE, 1, arg);
18718
18719 gimple_call_set_lhs (call, n);
18720 gimple_seq_add_stmt (seq, call);
18721 res = fold_build2 (MULT_EXPR, integer_type_node, res, n);
18722 }
18723 if (pos)
18724 {
18725 /* Determine index in this dimension. */
18726 tree id = create_tmp_var (integer_type_node);
18727 gimple *call = gimple_build_call_internal
18728 (IFN_GOACC_DIM_POS, 1, arg);
18729
18730 gimple_call_set_lhs (call, id);
18731 gimple_seq_add_stmt (seq, call);
18732 if (res)
18733 res = fold_build2 (PLUS_EXPR, integer_type_node, res, id);
18734 else
18735 res = id;
18736 }
18737 }
18738
18739 if (res == NULL_TREE)
18740 res = integer_zero_node;
18741
18742 return res;
18743}
18744
18745/* Transform IFN_GOACC_LOOP calls to actual code. See
18746 expand_oacc_for for where these are generated. At the vector
18747 level, we stride loops, such that each member of a warp will
18748 operate on adjacent iterations. At the worker and gang level,
18749 each gang/warp executes a set of contiguous iterations. Chunking
18750 can override this such that each iteration engine executes a
18751 contiguous chunk, and then moves on to stride to the next chunk. */
18752
18753static void
18754oacc_xform_loop (gcall *call)
18755{
18756 gimple_stmt_iterator gsi = gsi_for_stmt (call);
18757 enum ifn_goacc_loop_kind code
18758 = (enum ifn_goacc_loop_kind) TREE_INT_CST_LOW (gimple_call_arg (call, 0));
18759 tree dir = gimple_call_arg (call, 1);
18760 tree range = gimple_call_arg (call, 2);
18761 tree step = gimple_call_arg (call, 3);
18762 tree chunk_size = NULL_TREE;
18763 unsigned mask = (unsigned) TREE_INT_CST_LOW (gimple_call_arg (call, 5));
18764 tree lhs = gimple_call_lhs (call);
18765 tree type = TREE_TYPE (lhs);
18766 tree diff_type = TREE_TYPE (range);
18767 tree r = NULL_TREE;
18768 gimple_seq seq = NULL;
18769 bool chunking = false, striding = true;
18770 unsigned outer_mask = mask & (~mask + 1); // Outermost partitioning
18771 unsigned inner_mask = mask & ~outer_mask; // Inner partitioning (if any)
18772
18773#ifdef ACCEL_COMPILER
18774 chunk_size = gimple_call_arg (call, 4);
18775 if (integer_minus_onep (chunk_size) /* Force static allocation. */
18776 || integer_zerop (chunk_size)) /* Default (also static). */
18777 {
18778 /* If we're at the gang level, we want each to execute a
18779 contiguous run of iterations. Otherwise we want each element
18780 to stride. */
18781 striding = !(outer_mask & GOMP_DIM_MASK (GOMP_DIM_GANG));
18782 chunking = false;
18783 }
18784 else
18785 {
18786 /* Chunk of size 1 is striding. */
18787 striding = integer_onep (chunk_size);
18788 chunking = !striding;
18789 }
18790#endif
18791
18792 /* striding=true, chunking=true
18793 -> invalid.
18794 striding=true, chunking=false
18795 -> chunks=1
18796 striding=false,chunking=true
18797 -> chunks=ceil (range/(chunksize*threads*step))
18798 striding=false,chunking=false
18799 -> chunk_size=ceil(range/(threads*step)),chunks=1 */
18800 push_gimplify_context (true);
18801
18802 switch (code)
18803 {
18804 default: gcc_unreachable ();
18805
18806 case IFN_GOACC_LOOP_CHUNKS:
18807 if (!chunking)
18808 r = build_int_cst (type, 1);
18809 else
18810 {
18811 /* chunk_max
18812 = (range - dir) / (chunks * step * num_threads) + dir */
18813 tree per = oacc_thread_numbers (false, mask, &seq);
18814 per = fold_convert (type, per);
18815 chunk_size = fold_convert (type, chunk_size);
18816 per = fold_build2 (MULT_EXPR, type, per, chunk_size);
18817 per = fold_build2 (MULT_EXPR, type, per, step);
18818 r = build2 (MINUS_EXPR, type, range, dir);
18819 r = build2 (PLUS_EXPR, type, r, per);
18820 r = build2 (TRUNC_DIV_EXPR, type, r, per);
18821 }
18822 break;
18823
18824 case IFN_GOACC_LOOP_STEP:
18825 {
18826 /* If striding, step by the entire compute volume, otherwise
18827 step by the inner volume. */
18828 unsigned volume = striding ? mask : inner_mask;
18829
18830 r = oacc_thread_numbers (false, volume, &seq);
18831 r = build2 (MULT_EXPR, type, fold_convert (type, r), step);
18832 }
18833 break;
18834
18835 case IFN_GOACC_LOOP_OFFSET:
18836 if (striding)
18837 {
18838 r = oacc_thread_numbers (true, mask, &seq);
18839 r = fold_convert (diff_type, r);
18840 }
18841 else
18842 {
18843 tree inner_size = oacc_thread_numbers (false, inner_mask, &seq);
18844 tree outer_size = oacc_thread_numbers (false, outer_mask, &seq);
18845 tree volume = fold_build2 (MULT_EXPR, TREE_TYPE (inner_size),
18846 inner_size, outer_size);
18847
18848 volume = fold_convert (diff_type, volume);
18849 if (chunking)
18850 chunk_size = fold_convert (diff_type, chunk_size);
18851 else
18852 {
18853 tree per = fold_build2 (MULT_EXPR, diff_type, volume, step);
18854
18855 chunk_size = build2 (MINUS_EXPR, diff_type, range, dir);
18856 chunk_size = build2 (PLUS_EXPR, diff_type, chunk_size, per);
18857 chunk_size = build2 (TRUNC_DIV_EXPR, diff_type, chunk_size, per);
18858 }
18859
18860 tree span = build2 (MULT_EXPR, diff_type, chunk_size,
18861 fold_convert (diff_type, inner_size));
18862 r = oacc_thread_numbers (true, outer_mask, &seq);
18863 r = fold_convert (diff_type, r);
18864 r = build2 (MULT_EXPR, diff_type, r, span);
18865
18866 tree inner = oacc_thread_numbers (true, inner_mask, &seq);
18867 inner = fold_convert (diff_type, inner);
18868 r = fold_build2 (PLUS_EXPR, diff_type, r, inner);
18869
18870 if (chunking)
18871 {
18872 tree chunk = fold_convert (diff_type, gimple_call_arg (call, 6));
18873 tree per
18874 = fold_build2 (MULT_EXPR, diff_type, volume, chunk_size);
18875 per = build2 (MULT_EXPR, diff_type, per, chunk);
18876
18877 r = build2 (PLUS_EXPR, diff_type, r, per);
18878 }
18879 }
18880 r = fold_build2 (MULT_EXPR, diff_type, r, step);
18881 if (type != diff_type)
18882 r = fold_convert (type, r);
18883 break;
18884
18885 case IFN_GOACC_LOOP_BOUND:
18886 if (striding)
18887 r = range;
18888 else
18889 {
18890 tree inner_size = oacc_thread_numbers (false, inner_mask, &seq);
18891 tree outer_size = oacc_thread_numbers (false, outer_mask, &seq);
18892 tree volume = fold_build2 (MULT_EXPR, TREE_TYPE (inner_size),
18893 inner_size, outer_size);
18894
18895 volume = fold_convert (diff_type, volume);
18896 if (chunking)
18897 chunk_size = fold_convert (diff_type, chunk_size);
18898 else
18899 {
18900 tree per = fold_build2 (MULT_EXPR, diff_type, volume, step);
18901
18902 chunk_size = build2 (MINUS_EXPR, diff_type, range, dir);
18903 chunk_size = build2 (PLUS_EXPR, diff_type, chunk_size, per);
18904 chunk_size = build2 (TRUNC_DIV_EXPR, diff_type, chunk_size, per);
18905 }
18906
18907 tree span = build2 (MULT_EXPR, diff_type, chunk_size,
18908 fold_convert (diff_type, inner_size));
18909
18910 r = fold_build2 (MULT_EXPR, diff_type, span, step);
18911
18912 tree offset = gimple_call_arg (call, 6);
18913 r = build2 (PLUS_EXPR, diff_type, r,
18914 fold_convert (diff_type, offset));
18915 r = build2 (integer_onep (dir) ? MIN_EXPR : MAX_EXPR,
18916 diff_type, r, range);
18917 }
18918 if (diff_type != type)
18919 r = fold_convert (type, r);
18920 break;
18921 }
18922
18923 gimplify_assign (lhs, r, &seq);
18924
18925 pop_gimplify_context (NULL);
18926
18927 gsi_replace_with_seq (&gsi, seq, true);
18928}
18929
0bb0f256 18930/* Validate and update the dimensions for offloaded FN. ATTRS is the
18931 raw attribute. DIMS is an array of dimensions, which is returned.
18932 Returns the function level dimensionality -- the level at which an
18933 offload routine wishes to partition a loop. */
18934
18935static int
18936oacc_validate_dims (tree fn, tree attrs, int *dims)
18937{
18938 tree purpose[GOMP_DIM_MAX];
18939 unsigned ix;
18940 tree pos = TREE_VALUE (attrs);
18941 int fn_level = -1;
18942
18943 /* Make sure the attribute creator attached the dimension
18944 information. */
18945 gcc_assert (pos);
18946
18947 for (ix = 0; ix != GOMP_DIM_MAX; ix++)
18948 {
18949 purpose[ix] = TREE_PURPOSE (pos);
18950
18951 if (purpose[ix])
18952 {
18953 if (integer_zerop (purpose[ix]))
18954 fn_level = ix + 1;
18955 else if (fn_level < 0)
18956 fn_level = ix;
18957 }
18958
18959 tree val = TREE_VALUE (pos);
18960 dims[ix] = val ? TREE_INT_CST_LOW (val) : -1;
18961 pos = TREE_CHAIN (pos);
18962 }
18963
18964 bool changed = targetm.goacc.validate_dims (fn, dims, fn_level);
18965
18966 /* Default anything left to 1. */
18967 for (ix = 0; ix != GOMP_DIM_MAX; ix++)
18968 if (dims[ix] < 0)
18969 {
18970 dims[ix] = 1;
18971 changed = true;
18972 }
18973
18974 if (changed)
18975 {
18976 /* Replace the attribute with new values. */
18977 pos = NULL_TREE;
18978 for (ix = GOMP_DIM_MAX; ix--;)
18979 pos = tree_cons (purpose[ix],
18980 build_int_cst (integer_type_node, dims[ix]),
18981 pos);
18982 replace_oacc_fn_attrib (fn, pos);
18983 }
18984
18985 return fn_level;
18986}
18987
cbba99a0 18988/* Create an empty OpenACC loop structure at LOC. */
18989
18990static oacc_loop *
18991new_oacc_loop_raw (oacc_loop *parent, location_t loc)
18992{
18993 oacc_loop *loop = XCNEW (oacc_loop);
18994
18995 loop->parent = parent;
18996 loop->child = loop->sibling = NULL;
18997
18998 if (parent)
18999 {
19000 loop->sibling = parent->child;
19001 parent->child = loop;
19002 }
19003
19004 loop->loc = loc;
19005 loop->marker = NULL;
19006 memset (loop->heads, 0, sizeof (loop->heads));
19007 memset (loop->tails, 0, sizeof (loop->tails));
19008 loop->routine = NULL_TREE;
19009
19010 loop->mask = loop->flags = 0;
19011 loop->chunk_size = 0;
19012 loop->head_end = NULL;
19013
19014 return loop;
19015}
19016
19017/* Create an outermost, dummy OpenACC loop for offloaded function
19018 DECL. */
19019
19020static oacc_loop *
19021new_oacc_loop_outer (tree decl)
19022{
19023 return new_oacc_loop_raw (NULL, DECL_SOURCE_LOCATION (decl));
19024}
19025
19026/* Start a new OpenACC loop structure beginning at head marker HEAD.
19027 Link into PARENT loop. Return the new loop. */
19028
19029static oacc_loop *
19030new_oacc_loop (oacc_loop *parent, gcall *marker)
19031{
19032 oacc_loop *loop = new_oacc_loop_raw (parent, gimple_location (marker));
19033
19034 loop->marker = marker;
19035
19036 /* TODO: This is where device_type flattening would occur for the loop
19037 flags. */
19038
19039 loop->flags = TREE_INT_CST_LOW (gimple_call_arg (marker, 3));
19040
19041 tree chunk_size = integer_zero_node;
19042 if (loop->flags & OLF_GANG_STATIC)
19043 chunk_size = gimple_call_arg (marker, 4);
19044 loop->chunk_size = chunk_size;
19045
19046 return loop;
19047}
19048
19049/* Create a dummy loop encompassing a call to a openACC routine.
19050 Extract the routine's partitioning requirements. */
19051
19052static void
19053new_oacc_loop_routine (oacc_loop *parent, gcall *call, tree decl, tree attrs)
19054{
19055 oacc_loop *loop = new_oacc_loop_raw (parent, gimple_location (call));
19056 int dims[GOMP_DIM_MAX];
19057 int level = oacc_validate_dims (decl, attrs, dims);
19058
19059 gcc_assert (level >= 0);
19060
19061 loop->marker = call;
19062 loop->routine = decl;
19063 loop->mask = ((GOMP_DIM_MASK (GOMP_DIM_MAX) - 1)
19064 ^ (GOMP_DIM_MASK (level) - 1));
19065}
19066
19067/* Finish off the current OpenACC loop ending at tail marker TAIL.
19068 Return the parent loop. */
19069
19070static oacc_loop *
19071finish_oacc_loop (oacc_loop *loop)
19072{
19073 return loop->parent;
19074}
19075
19076/* Free all OpenACC loop structures within LOOP (inclusive). */
19077
19078static void
19079free_oacc_loop (oacc_loop *loop)
19080{
19081 if (loop->sibling)
19082 free_oacc_loop (loop->sibling);
19083 if (loop->child)
19084 free_oacc_loop (loop->child);
19085
19086 free (loop);
19087}
19088
19089/* Dump out the OpenACC loop head or tail beginning at FROM. */
19090
19091static void
19092dump_oacc_loop_part (FILE *file, gcall *from, int depth,
19093 const char *title, int level)
19094{
19095 enum ifn_unique_kind kind
19096 = (enum ifn_unique_kind) TREE_INT_CST_LOW (gimple_call_arg (from, 0));
19097
19098 fprintf (file, "%*s%s-%d:\n", depth * 2, "", title, level);
19099 for (gimple_stmt_iterator gsi = gsi_for_stmt (from);;)
19100 {
19101 gimple *stmt = gsi_stmt (gsi);
19102
19103 if (is_gimple_call (stmt)
19104 && gimple_call_internal_p (stmt)
19105 && gimple_call_internal_fn (stmt) == IFN_UNIQUE)
19106 {
19107 enum ifn_unique_kind k
19108 = ((enum ifn_unique_kind) TREE_INT_CST_LOW
19109 (gimple_call_arg (stmt, 0)));
19110
19111 if (k == kind && stmt != from)
19112 break;
19113 }
19114 print_gimple_stmt (file, stmt, depth * 2 + 2, 0);
19115
19116 gsi_next (&gsi);
19117 while (gsi_end_p (gsi))
19118 gsi = gsi_start_bb (single_succ (gsi_bb (gsi)));
19119 }
19120}
19121
19122/* Dump OpenACC loops LOOP, its siblings and its children. */
19123
19124static void
19125dump_oacc_loop (FILE *file, oacc_loop *loop, int depth)
19126{
19127 int ix;
19128
19129 fprintf (file, "%*sLoop %x(%x) %s:%u\n", depth * 2, "",
19130 loop->flags, loop->mask,
19131 LOCATION_FILE (loop->loc), LOCATION_LINE (loop->loc));
19132
19133 if (loop->marker)
19134 print_gimple_stmt (file, loop->marker, depth * 2, 0);
19135
19136 if (loop->routine)
19137 fprintf (file, "%*sRoutine %s:%u:%s\n",
19138 depth * 2, "", DECL_SOURCE_FILE (loop->routine),
19139 DECL_SOURCE_LINE (loop->routine),
19140 IDENTIFIER_POINTER (DECL_NAME (loop->routine)));
19141
19142 for (ix = GOMP_DIM_GANG; ix != GOMP_DIM_MAX; ix++)
19143 if (loop->heads[ix])
19144 dump_oacc_loop_part (file, loop->heads[ix], depth, "Head", ix);
19145 for (ix = GOMP_DIM_MAX; ix--;)
19146 if (loop->tails[ix])
19147 dump_oacc_loop_part (file, loop->tails[ix], depth, "Tail", ix);
19148
19149 if (loop->child)
19150 dump_oacc_loop (file, loop->child, depth + 1);
19151 if (loop->sibling)
19152 dump_oacc_loop (file, loop->sibling, depth);
19153}
19154
19155void debug_oacc_loop (oacc_loop *);
19156
19157/* Dump loops to stderr. */
19158
19159DEBUG_FUNCTION void
19160debug_oacc_loop (oacc_loop *loop)
19161{
19162 dump_oacc_loop (stderr, loop, 0);
19163}
19164
19165/* DFS walk of basic blocks BB onwards, creating OpenACC loop
19166 structures as we go. By construction these loops are properly
19167 nested. */
19168
19169static void
19170oacc_loop_discover_walk (oacc_loop *loop, basic_block bb)
19171{
19172 int marker = 0;
19173 int remaining = 0;
19174
19175 if (bb->flags & BB_VISITED)
19176 return;
19177
19178 follow:
19179 bb->flags |= BB_VISITED;
19180
19181 /* Scan for loop markers. */
19182 for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);
19183 gsi_next (&gsi))
19184 {
19185 gimple *stmt = gsi_stmt (gsi);
19186
19187 if (!is_gimple_call (stmt))
19188 continue;
19189
19190 gcall *call = as_a <gcall *> (stmt);
19191
19192 /* If this is a routine, make a dummy loop for it. */
19193 if (tree decl = gimple_call_fndecl (call))
19194 if (tree attrs = get_oacc_fn_attrib (decl))
19195 {
19196 gcc_assert (!marker);
19197 new_oacc_loop_routine (loop, call, decl, attrs);
19198 }
19199
19200 if (!gimple_call_internal_p (call))
19201 continue;
19202
19203 if (gimple_call_internal_fn (call) != IFN_UNIQUE)
19204 continue;
19205
19206 enum ifn_unique_kind kind
19207 = (enum ifn_unique_kind) TREE_INT_CST_LOW (gimple_call_arg (call, 0));
19208 if (kind == IFN_UNIQUE_OACC_HEAD_MARK
19209 || kind == IFN_UNIQUE_OACC_TAIL_MARK)
19210 {
19211 if (gimple_call_num_args (call) == 2)
19212 {
19213 gcc_assert (marker && !remaining);
19214 marker = 0;
19215 if (kind == IFN_UNIQUE_OACC_TAIL_MARK)
19216 loop = finish_oacc_loop (loop);
19217 else
19218 loop->head_end = call;
19219 }
19220 else
19221 {
19222 int count = TREE_INT_CST_LOW (gimple_call_arg (call, 2));
19223
19224 if (!marker)
19225 {
19226 if (kind == IFN_UNIQUE_OACC_HEAD_MARK)
19227 loop = new_oacc_loop (loop, call);
19228 remaining = count;
19229 }
19230 gcc_assert (count == remaining);
19231 if (remaining)
19232 {
19233 remaining--;
19234 if (kind == IFN_UNIQUE_OACC_HEAD_MARK)
19235 loop->heads[marker] = call;
19236 else
19237 loop->tails[remaining] = call;
19238 }
19239 marker++;
19240 }
19241 }
19242 }
19243 if (remaining || marker)
19244 {
19245 bb = single_succ (bb);
19246 gcc_assert (single_pred_p (bb) && !(bb->flags & BB_VISITED));
19247 goto follow;
19248 }
19249
19250 /* Walk successor blocks. */
19251 edge e;
19252 edge_iterator ei;
19253
19254 FOR_EACH_EDGE (e, ei, bb->succs)
19255 oacc_loop_discover_walk (loop, e->dest);
19256}
19257
19258/* LOOP is the first sibling. Reverse the order in place and return
19259 the new first sibling. Recurse to child loops. */
19260
19261static oacc_loop *
19262oacc_loop_sibling_nreverse (oacc_loop *loop)
19263{
19264 oacc_loop *last = NULL;
19265 do
19266 {
19267 if (loop->child)
19268 loop->child = oacc_loop_sibling_nreverse (loop->child);
19269
19270 oacc_loop *next = loop->sibling;
19271 loop->sibling = last;
19272 last = loop;
19273 loop = next;
19274 }
19275 while (loop);
19276
19277 return last;
19278}
19279
19280/* Discover the OpenACC loops marked up by HEAD and TAIL markers for
19281 the current function. */
19282
19283static oacc_loop *
19284oacc_loop_discovery ()
19285{
19286 basic_block bb;
19287
19288 oacc_loop *top = new_oacc_loop_outer (current_function_decl);
19289 oacc_loop_discover_walk (top, ENTRY_BLOCK_PTR_FOR_FN (cfun));
19290
19291 /* The siblings were constructed in reverse order, reverse them so
19292 that diagnostics come out in an unsurprising order. */
19293 top = oacc_loop_sibling_nreverse (top);
19294
19295 /* Reset the visited flags. */
19296 FOR_ALL_BB_FN (bb, cfun)
19297 bb->flags &= ~BB_VISITED;
19298
19299 return top;
19300}
19301
19302/* Transform the abstract internal function markers starting at FROM
19303 to be for partitioning level LEVEL. Stop when we meet another HEAD
19304 or TAIL marker. */
19305
19306static void
19307oacc_loop_xform_head_tail (gcall *from, int level)
19308{
19309 enum ifn_unique_kind kind
19310 = (enum ifn_unique_kind) TREE_INT_CST_LOW (gimple_call_arg (from, 0));
19311 tree replacement = build_int_cst (unsigned_type_node, level);
19312
19313 for (gimple_stmt_iterator gsi = gsi_for_stmt (from);;)
19314 {
19315 gimple *stmt = gsi_stmt (gsi);
19316
19317 if (is_gimple_call (stmt)
19318 && gimple_call_internal_p (stmt)
19319 && gimple_call_internal_fn (stmt) == IFN_UNIQUE)
19320 {
19321 enum ifn_unique_kind k
19322 = ((enum ifn_unique_kind)
19323 TREE_INT_CST_LOW (gimple_call_arg (stmt, 0)));
19324
19325 if (k == IFN_UNIQUE_OACC_FORK || k == IFN_UNIQUE_OACC_JOIN)
19326 *gimple_call_arg_ptr (stmt, 2) = replacement;
19327 else if (k == kind && stmt != from)
19328 break;
19329 }
641a0fa1 19330 else if (is_gimple_call (stmt)
19331 && gimple_call_internal_p (stmt)
19332 && gimple_call_internal_fn (stmt) == IFN_GOACC_REDUCTION)
19333 *gimple_call_arg_ptr (stmt, 3) = replacement;
19334
cbba99a0 19335 gsi_next (&gsi);
19336 while (gsi_end_p (gsi))
19337 gsi = gsi_start_bb (single_succ (gsi_bb (gsi)));
19338 }
19339}
19340
19341/* Transform the IFN_GOACC_LOOP internal functions by providing the
19342 determined partitioning mask and chunking argument. */
19343
19344static void
19345oacc_loop_xform_loop (gcall *end_marker, tree mask_arg, tree chunk_arg)
19346{
19347 gimple_stmt_iterator gsi = gsi_for_stmt (end_marker);
19348
19349 for (;;)
19350 {
19351 for (; !gsi_end_p (gsi); gsi_next (&gsi))
19352 {
19353 gimple *stmt = gsi_stmt (gsi);
19354
19355 if (!is_gimple_call (stmt))
19356 continue;
19357
19358 gcall *call = as_a <gcall *> (stmt);
19359
19360 if (!gimple_call_internal_p (call))
19361 continue;
19362
19363 if (gimple_call_internal_fn (call) != IFN_GOACC_LOOP)
19364 continue;
19365
19366 *gimple_call_arg_ptr (call, 5) = mask_arg;
19367 *gimple_call_arg_ptr (call, 4) = chunk_arg;
19368 if (TREE_INT_CST_LOW (gimple_call_arg (call, 0))
19369 == IFN_GOACC_LOOP_BOUND)
19370 return;
19371 }
19372
19373 /* If we didn't see LOOP_BOUND, it should be in the single
19374 successor block. */
19375 basic_block bb = single_succ (gsi_bb (gsi));
19376 gsi = gsi_start_bb (bb);
19377 }
19378}
19379
19380/* Process the discovered OpenACC loops, setting the correct
19381 partitioning level etc. */
19382
19383static void
19384oacc_loop_process (oacc_loop *loop)
19385{
19386 if (loop->child)
19387 oacc_loop_process (loop->child);
19388
19389 if (loop->mask && !loop->routine)
19390 {
19391 int ix;
19392 unsigned mask = loop->mask;
19393 unsigned dim = GOMP_DIM_GANG;
19394 tree mask_arg = build_int_cst (unsigned_type_node, mask);
19395 tree chunk_arg = loop->chunk_size;
19396
19397 oacc_loop_xform_loop (loop->head_end, mask_arg, chunk_arg);
19398
19399 for (ix = 0; ix != GOMP_DIM_MAX && loop->heads[ix]; ix++)
19400 {
19401 gcc_assert (mask);
19402
19403 while (!(GOMP_DIM_MASK (dim) & mask))
19404 dim++;
19405
19406 oacc_loop_xform_head_tail (loop->heads[ix], dim);
19407 oacc_loop_xform_head_tail (loop->tails[ix], dim);
19408
19409 mask ^= GOMP_DIM_MASK (dim);
19410 }
19411 }
19412
19413 if (loop->sibling)
19414 oacc_loop_process (loop->sibling);
19415}
19416
19417/* Walk the OpenACC loop heirarchy checking and assigning the
19418 programmer-specified partitionings. OUTER_MASK is the partitioning
f4f5b4b4 19419 this loop is contained within. Return true if we contain an
19420 auto-partitionable loop. */
cbba99a0 19421
f4f5b4b4 19422static bool
cbba99a0 19423oacc_loop_fixed_partitions (oacc_loop *loop, unsigned outer_mask)
19424{
19425 unsigned this_mask = loop->mask;
19426 bool has_auto = false;
19427 bool noisy = true;
19428
19429#ifdef ACCEL_COMPILER
19430 /* When device_type is supported, we want the device compiler to be
19431 noisy, if the loop parameters are device_type-specific. */
19432 noisy = false;
19433#endif
19434
19435 if (!loop->routine)
19436 {
19437 bool auto_par = (loop->flags & OLF_AUTO) != 0;
19438 bool seq_par = (loop->flags & OLF_SEQ) != 0;
19439
19440 this_mask = ((loop->flags >> OLF_DIM_BASE)
19441 & (GOMP_DIM_MASK (GOMP_DIM_MAX) - 1));
19442
19443 if ((this_mask != 0) + auto_par + seq_par > 1)
19444 {
19445 if (noisy)
19446 error_at (loop->loc,
19447 seq_par
19448 ? "%<seq%> overrides other OpenACC loop specifiers"
19449 : "%<auto%> conflicts with other OpenACC loop specifiers");
19450 auto_par = false;
19451 loop->flags &= ~OLF_AUTO;
19452 if (seq_par)
19453 {
19454 loop->flags &=
19455 ~((GOMP_DIM_MASK (GOMP_DIM_MAX) - 1) << OLF_DIM_BASE);
19456 this_mask = 0;
19457 }
19458 }
19459 if (auto_par && (loop->flags & OLF_INDEPENDENT))
19460 has_auto = true;
19461 }
19462
19463 if (this_mask & outer_mask)
19464 {
19465 const oacc_loop *outer;
19466 for (outer = loop->parent; outer; outer = outer->parent)
19467 if (outer->mask & this_mask)
19468 break;
19469
19470 if (noisy)
19471 {
19472 if (outer)
19473 {
19474 error_at (loop->loc,
19475 "%s uses same OpenACC parallelism as containing loop",
19476 loop->routine ? "routine call" : "inner loop");
19477 inform (outer->loc, "containing loop here");
19478 }
19479 else
19480 error_at (loop->loc,
19481 "%s uses OpenACC parallelism disallowed by containing routine",
19482 loop->routine ? "routine call" : "loop");
19483
19484 if (loop->routine)
19485 inform (DECL_SOURCE_LOCATION (loop->routine),
19486 "routine %qD declared here", loop->routine);
19487 }
19488 this_mask &= ~outer_mask;
19489 }
19490 else
19491 {
19492 unsigned outermost = this_mask & -this_mask;
19493
19494 if (outermost && outermost <= outer_mask)
19495 {
19496 if (noisy)
19497 {
19498 error_at (loop->loc,
19499 "incorrectly nested OpenACC loop parallelism");
19500
19501 const oacc_loop *outer;
19502 for (outer = loop->parent;
19503 outer->flags && outer->flags < outermost;
19504 outer = outer->parent)
19505 continue;
19506 inform (outer->loc, "containing loop here");
19507 }
19508
19509 this_mask &= ~outermost;
19510 }
19511 }
19512
19513 loop->mask = this_mask;
19514
19515 if (loop->child
19516 && oacc_loop_fixed_partitions (loop->child, outer_mask | this_mask))
19517 has_auto = true;
19518
19519 if (loop->sibling
19520 && oacc_loop_fixed_partitions (loop->sibling, outer_mask))
19521 has_auto = true;
19522
19523 return has_auto;
19524}
19525
f4f5b4b4 19526/* Walk the OpenACC loop heirarchy to assign auto-partitioned loops.
19527 OUTER_MASK is the partitioning this loop is contained within.
19528 Return the cumulative partitioning used by this loop, siblings and
19529 children. */
19530
19531static unsigned
19532oacc_loop_auto_partitions (oacc_loop *loop, unsigned outer_mask)
19533{
19534 unsigned inner_mask = 0;
19535 bool noisy = true;
19536
19537#ifdef ACCEL_COMPILER
19538 /* When device_type is supported, we want the device compiler to be
19539 noisy, if the loop parameters are device_type-specific. */
19540 noisy = false;
19541#endif
19542
19543 if (loop->child)
19544 inner_mask |= oacc_loop_auto_partitions (loop->child,
19545 outer_mask | loop->mask);
19546
19547 if ((loop->flags & OLF_AUTO) && (loop->flags & OLF_INDEPENDENT))
19548 {
19549 unsigned this_mask = 0;
19550
19551 /* Determine the outermost partitioning used within this loop. */
19552 this_mask = inner_mask | GOMP_DIM_MASK (GOMP_DIM_MAX);
19553 this_mask = (this_mask & -this_mask);
19554
19555 /* Pick the partitioning just inside that one. */
19556 this_mask >>= 1;
19557
19558 /* And avoid picking one use by an outer loop. */
19559 this_mask &= ~outer_mask;
19560
19561 if (!this_mask && noisy)
19562 warning_at (loop->loc, 0,
19563 "insufficient partitioning available to parallelize loop");
19564
19565 loop->mask = this_mask;
19566 }
19567 inner_mask |= loop->mask;
19568
19569 if (loop->sibling)
19570 inner_mask |= oacc_loop_auto_partitions (loop->sibling, outer_mask);
19571
19572 return inner_mask;
19573}
19574
cbba99a0 19575/* Walk the OpenACC loop heirarchy to check and assign partitioning
19576 axes. */
19577
19578static void
f4f5b4b4 19579oacc_loop_partition (oacc_loop *loop, unsigned outer_mask)
cbba99a0 19580{
f4f5b4b4 19581 if (oacc_loop_fixed_partitions (loop, outer_mask))
19582 oacc_loop_auto_partitions (loop, outer_mask);
cbba99a0 19583}
19584
c25f1934 19585/* Default fork/join early expander. Delete the function calls if
19586 there is no RTL expander. */
19587
19588bool
19589default_goacc_fork_join (gcall *ARG_UNUSED (call),
19590 const int *ARG_UNUSED (dims), bool is_fork)
19591{
19592 if (is_fork)
19593 return targetm.have_oacc_fork ();
19594 else
19595 return targetm.have_oacc_join ();
19596}
19597
641a0fa1 19598/* Default goacc.reduction early expander.
19599
19600 LHS-opt = IFN_REDUCTION (KIND, RES_PTR, VAR, LEVEL, OP, OFFSET)
19601 If RES_PTR is not integer-zerop:
19602 SETUP - emit 'LHS = *RES_PTR', LHS = NULL
19603 TEARDOWN - emit '*RES_PTR = VAR'
19604 If LHS is not NULL
19605 emit 'LHS = VAR' */
19606
19607void
19608default_goacc_reduction (gcall *call)
19609{
19610 unsigned code = (unsigned)TREE_INT_CST_LOW (gimple_call_arg (call, 0));
19611 gimple_stmt_iterator gsi = gsi_for_stmt (call);
19612 tree lhs = gimple_call_lhs (call);
19613 tree var = gimple_call_arg (call, 2);
19614 gimple_seq seq = NULL;
19615
19616 if (code == IFN_GOACC_REDUCTION_SETUP
19617 || code == IFN_GOACC_REDUCTION_TEARDOWN)
19618 {
19619 /* Setup and Teardown need to copy from/to the receiver object,
19620 if there is one. */
19621 tree ref_to_res = gimple_call_arg (call, 1);
19622
19623 if (!integer_zerop (ref_to_res))
19624 {
19625 tree dst = build_simple_mem_ref (ref_to_res);
19626 tree src = var;
19627
19628 if (code == IFN_GOACC_REDUCTION_SETUP)
19629 {
19630 src = dst;
19631 dst = lhs;
19632 lhs = NULL;
19633 }
19634 gimple_seq_add_stmt (&seq, gimple_build_assign (dst, src));
19635 }
19636 }
19637
19638 /* Copy VAR to LHS, if there is an LHS. */
19639 if (lhs)
19640 gimple_seq_add_stmt (&seq, gimple_build_assign (lhs, var));
19641
19642 gsi_replace_with_seq (&gsi, seq, true);
19643}
19644
0bb0f256 19645/* Main entry point for oacc transformations which run on the device
19646 compiler after LTO, so we know what the target device is at this
19647 point (including the host fallback). */
19648
19649static unsigned int
19650execute_oacc_device_lower ()
19651{
19652 tree attrs = get_oacc_fn_attrib (current_function_decl);
19653 int dims[GOMP_DIM_MAX];
19654
19655 if (!attrs)
19656 /* Not an offloaded function. */
19657 return 0;
19658
cbba99a0 19659 int fn_level = oacc_validate_dims (current_function_decl, attrs, dims);
19660
19661 /* Discover, partition and process the loops. */
19662 oacc_loop *loops = oacc_loop_discovery ();
f4f5b4b4 19663 unsigned outer_mask = fn_level >= 0 ? GOMP_DIM_MASK (fn_level) - 1 : 0;
19664 oacc_loop_partition (loops, outer_mask);
cbba99a0 19665 oacc_loop_process (loops);
19666 if (dump_file)
19667 {
19668 fprintf (dump_file, "OpenACC loops\n");
19669 dump_oacc_loop (dump_file, loops, 0);
19670 fprintf (dump_file, "\n");
19671 }
19672
641a0fa1 19673 /* Offloaded targets may introduce new basic blocks, which require
19674 dominance information to update SSA. */
19675 calculate_dominance_info (CDI_DOMINATORS);
19676
cbba99a0 19677 /* Now lower internal loop functions to target-specific code
19678 sequences. */
19679 basic_block bb;
19680 FOR_ALL_BB_FN (bb, cfun)
19681 for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);)
19682 {
19683 gimple *stmt = gsi_stmt (gsi);
19684 if (!is_gimple_call (stmt))
19685 {
19686 gsi_next (&gsi);
19687 continue;
19688 }
19689
19690 gcall *call = as_a <gcall *> (stmt);
19691 if (!gimple_call_internal_p (call))
19692 {
19693 gsi_next (&gsi);
19694 continue;
19695 }
19696
19697 /* Rewind to allow rescan. */
19698 gsi_prev (&gsi);
19699 bool rescan = false, remove = false;
19700 enum internal_fn ifn_code = gimple_call_internal_fn (call);
19701
19702 switch (ifn_code)
19703 {
19704 default: break;
19705
19706 case IFN_GOACC_LOOP:
19707 oacc_xform_loop (call);
19708 rescan = true;
19709 break;
19710
641a0fa1 19711 case IFN_GOACC_REDUCTION:
19712 /* Mark the function for SSA renaming. */
19713 mark_virtual_operands_for_renaming (cfun);
19714
19715 /* If the level is -1, this ended up being an unused
19716 axis. Handle as a default. */
19717 if (integer_minus_onep (gimple_call_arg (call, 3)))
19718 default_goacc_reduction (call);
19719 else
19720 targetm.goacc.reduction (call);
19721 rescan = true;
19722 break;
19723
cbba99a0 19724 case IFN_UNIQUE:
19725 {
19726 enum ifn_unique_kind kind
19727 = ((enum ifn_unique_kind)
19728 TREE_INT_CST_LOW (gimple_call_arg (call, 0)));
19729
19730 switch (kind)
19731 {
19732 default:
19733 gcc_unreachable ();
19734
19735 case IFN_UNIQUE_OACC_FORK:
19736 case IFN_UNIQUE_OACC_JOIN:
19737 if (integer_minus_onep (gimple_call_arg (call, 2)))
19738 remove = true;
19739 else if (!targetm.goacc.fork_join
19740 (call, dims, kind == IFN_UNIQUE_OACC_FORK))
19741 remove = true;
19742 break;
19743
19744 case IFN_UNIQUE_OACC_HEAD_MARK:
19745 case IFN_UNIQUE_OACC_TAIL_MARK:
19746 remove = true;
19747 break;
19748 }
19749 break;
19750 }
19751 }
19752
19753 if (gsi_end_p (gsi))
19754 /* We rewound past the beginning of the BB. */
19755 gsi = gsi_start_bb (bb);
19756 else
19757 /* Undo the rewind. */
19758 gsi_next (&gsi);
19759
19760 if (remove)
19761 {
19762 if (gimple_vdef (call))
19763 replace_uses_by (gimple_vdef (call), gimple_vuse (call));
19764 if (gimple_call_lhs (call))
19765 {
19766 /* Propagate the data dependency var. */
19767 gimple *ass = gimple_build_assign (gimple_call_lhs (call),
19768 gimple_call_arg (call, 1));
19769 gsi_replace (&gsi, ass, false);
19770 }
19771 else
19772 gsi_remove (&gsi, true);
19773 }
19774 else if (!rescan)
19775 /* If not rescanning, advance over the call. */
19776 gsi_next (&gsi);
19777 }
19778
19779 free_oacc_loop (loops);
19780
0bb0f256 19781 return 0;
19782}
19783
19784/* Default launch dimension validator. Force everything to 1. A
19785 backend that wants to provide larger dimensions must override this
19786 hook. */
19787
19788bool
19789default_goacc_validate_dims (tree ARG_UNUSED (decl), int *dims,
19790 int ARG_UNUSED (fn_level))
19791{
19792 bool changed = false;
19793
19794 for (unsigned ix = 0; ix != GOMP_DIM_MAX; ix++)
19795 {
19796 if (dims[ix] != 1)
19797 {
19798 dims[ix] = 1;
19799 changed = true;
19800 }
19801 }
19802
19803 return changed;
19804}
19805
e1037942 19806/* Default dimension bound is unknown on accelerator and 1 on host. */
19807
19808int
19809default_goacc_dim_limit (int ARG_UNUSED (axis))
19810{
19811#ifdef ACCEL_COMPILER
19812 return 0;
19813#else
19814 return 1;
19815#endif
19816}
19817
0bb0f256 19818namespace {
19819
19820const pass_data pass_data_oacc_device_lower =
19821{
19822 GIMPLE_PASS, /* type */
19823 "oaccdevlow", /* name */
19824 OPTGROUP_NONE, /* optinfo_flags */
19825 TV_NONE, /* tv_id */
19826 PROP_cfg, /* properties_required */
19827 0 /* Possibly PROP_gimple_eomp. */, /* properties_provided */
19828 0, /* properties_destroyed */
19829 0, /* todo_flags_start */
19830 TODO_update_ssa | TODO_cleanup_cfg, /* todo_flags_finish */
19831};
19832
19833class pass_oacc_device_lower : public gimple_opt_pass
19834{
19835public:
19836 pass_oacc_device_lower (gcc::context *ctxt)
19837 : gimple_opt_pass (pass_data_oacc_device_lower, ctxt)
19838 {}
19839
19840 /* opt_pass methods: */
19841 virtual unsigned int execute (function *)
19842 {
173dfdf5 19843 bool gate = flag_openacc != 0;
0bb0f256 19844
19845 if (!gate)
19846 return 0;
19847
19848 return execute_oacc_device_lower ();
19849 }
19850
f69b8a4c 19851}; // class pass_oacc_device_lower
0bb0f256 19852
19853} // anon namespace
19854
19855gimple_opt_pass *
19856make_pass_oacc_device_lower (gcc::context *ctxt)
19857{
19858 return new pass_oacc_device_lower (ctxt);
19859}
19860
c0998828 19861/* "omp declare target link" handling pass. */
19862
19863namespace {
19864
19865const pass_data pass_data_omp_target_link =
19866{
19867 GIMPLE_PASS, /* type */
19868 "omptargetlink", /* name */
19869 OPTGROUP_NONE, /* optinfo_flags */
19870 TV_NONE, /* tv_id */
19871 PROP_ssa, /* properties_required */
19872 0, /* properties_provided */
19873 0, /* properties_destroyed */
19874 0, /* todo_flags_start */
19875 TODO_update_ssa, /* todo_flags_finish */
19876};
19877
19878class pass_omp_target_link : public gimple_opt_pass
19879{
19880public:
19881 pass_omp_target_link (gcc::context *ctxt)
19882 : gimple_opt_pass (pass_data_omp_target_link, ctxt)
19883 {}
19884
19885 /* opt_pass methods: */
19886 virtual bool gate (function *fun)
19887 {
19888#ifdef ACCEL_COMPILER
19889 tree attrs = DECL_ATTRIBUTES (fun->decl);
19890 return lookup_attribute ("omp declare target", attrs)
19891 || lookup_attribute ("omp target entrypoint", attrs);
19892#else
19893 (void) fun;
19894 return false;
19895#endif
19896 }
19897
19898 virtual unsigned execute (function *);
19899};
19900
19901/* Callback for walk_gimple_stmt used to scan for link var operands. */
19902
19903static tree
19904find_link_var_op (tree *tp, int *walk_subtrees, void *)
19905{
19906 tree t = *tp;
19907
19908 if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t)
19909 && lookup_attribute ("omp declare target link", DECL_ATTRIBUTES (t)))
19910 {
19911 *walk_subtrees = 0;
19912 return t;
19913 }
19914
19915 return NULL_TREE;
19916}
19917
19918unsigned
19919pass_omp_target_link::execute (function *fun)
19920{
19921 basic_block bb;
19922 FOR_EACH_BB_FN (bb, fun)
19923 {
19924 gimple_stmt_iterator gsi;
19925 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
19926 if (walk_gimple_stmt (&gsi, NULL, find_link_var_op, NULL))
19927 gimple_regimplify_operands (gsi_stmt (gsi), &gsi);
19928 }
19929
19930 return 0;
19931}
19932
19933} // anon namespace
19934
19935gimple_opt_pass *
19936make_pass_omp_target_link (gcc::context *ctxt)
19937{
19938 return new pass_omp_target_link (ctxt);
19939}
19940
1e8e9920 19941#include "gt-omp-low.h"