]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/omp-low.c
omp-low.c (lower_omp_ordered): Add argument to GOMP_SMD_ORDERED_* internal calls...
[thirdparty/gcc.git] / gcc / omp-low.c
CommitLineData
41dbbb37
TS
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
953ff289
DN
5 Contributed by Diego Novillo <dnovillo@redhat.com>
6
5624e564 7 Copyright (C) 2005-2015 Free Software Foundation, Inc.
953ff289
DN
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
9dcd6f09 13Software Foundation; either version 3, or (at your option) any later
953ff289
DN
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
9dcd6f09
NC
22along with GCC; see the file COPYING3. If not see
23<http://www.gnu.org/licenses/>. */
953ff289
DN
24
25#include "config.h"
26#include "system.h"
27#include "coretypes.h"
c7131fb2 28#include "backend.h"
957060b5
AM
29#include "target.h"
30#include "rtl.h"
953ff289 31#include "tree.h"
c7131fb2 32#include "gimple.h"
957060b5
AM
33#include "cfghooks.h"
34#include "alloc-pool.h"
35#include "tree-pass.h"
c7131fb2 36#include "ssa.h"
957060b5
AM
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"
c7131fb2 43#include "alias.h"
40e23961 44#include "fold-const.h"
d8a2d370 45#include "stor-layout.h"
60393bbc 46#include "cfganal.h"
2fb9a547
AM
47#include "internal-fn.h"
48#include "gimple-fold.h"
45b0be94 49#include "gimplify.h"
5be5c238 50#include "gimple-iterator.h"
18f429e2 51#include "gimplify-me.h"
5be5c238 52#include "gimple-walk.h"
726a989a 53#include "tree-iterator.h"
953ff289
DN
54#include "tree-inline.h"
55#include "langhooks.h"
442b4905 56#include "tree-cfg.h"
442b4905 57#include "tree-into-ssa.h"
36566b39 58#include "flags.h"
36566b39
PK
59#include "dojump.h"
60#include "explow.h"
61#include "calls.h"
36566b39
PK
62#include "varasm.h"
63#include "stmt.h"
d8a2d370 64#include "expr.h"
442b4905 65#include "tree-dfa.h"
7a300452 66#include "tree-ssa.h"
953ff289 67#include "except.h"
6be42dd4 68#include "splay-tree.h"
a509ebb5 69#include "cfgloop.h"
ec6fe917 70#include "common/common-target.h"
0645c1a2 71#include "omp-low.h"
4484a35a
AM
72#include "gimple-low.h"
73#include "tree-cfgcleanup.h"
dd912cb8 74#include "symbol-summary.h"
0136f8f0 75#include "ipa-prop.h"
1fe37220 76#include "tree-nested.h"
0136f8f0 77#include "tree-eh.h"
9a771876 78#include "cilk.h"
1f6be682 79#include "context.h"
ec6fe917 80#include "lto-section-names.h"
41dbbb37 81#include "gomp-constants.h"
9bd46bc9 82#include "gimple-pretty-print.h"
953ff289 83
41dbbb37 84/* Lowering of OMP parallel and workshare constructs proceeds in two
953ff289
DN
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
c0220ea4 88 re-gimplifying things when variables have been replaced with complex
953ff289
DN
89 expressions.
90
7ebaeab5 91 Final code generation is done by pass_expand_omp. The flowgraph is
41dbbb37
TS
92 scanned for regions which are then moved to a new
93 function, to be invoked by the thread library, or offloaded. */
953ff289 94
41dbbb37 95/* OMP region information. Every parallel and workshare
0645c1a2 96 directive is enclosed between two markers, the OMP_* directive
d9a6bd32 97 and a corresponding GIMPLE_OMP_RETURN statement. */
0645c1a2
AM
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
d9a6bd32 113 /* Block containing the GIMPLE_OMP_RETURN as its last stmt. */
0645c1a2
AM
114 basic_block exit;
115
d9a6bd32 116 /* Block containing the GIMPLE_OMP_CONTINUE as its last stmt. */
0645c1a2
AM
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
d9a6bd32 127 /* Schedule kind, only used for GIMPLE_OMP_FOR type regions. */
0645c1a2
AM
128 enum omp_clause_schedule_kind sched_kind;
129
e01d41e5
JJ
130 /* Schedule modifiers. */
131 unsigned char sched_modifiers;
132
0645c1a2
AM
133 /* True if this is a combined parallel+workshare region. */
134 bool is_combined_parallel;
d9a6bd32
JJ
135
136 /* The ordered stmt if type is GIMPLE_OMP_ORDERED and it has
137 a depend clause. */
138 gomp_ordered *ord_stmt;
0645c1a2
AM
139};
140
953ff289
DN
141/* Context structure. Used to store information about each parallel
142 directive in the code. */
143
a79683d5 144struct omp_context
953ff289
DN
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;
355fe088 154 gimple *stmt;
953ff289 155
b8698a0f 156 /* Map variables to fields in a structure that allows communication
953ff289
DN
157 between sending and receiving threads. */
158 splay_tree field_map;
159 tree record_type;
160 tree sender_decl;
161 tree receiver_decl;
162
a68ab351
JJ
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
953ff289
DN
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
acf0174b
JJ
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
953ff289
DN
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
953ff289
DN
188 /* True if this parallel directive is nested within another. */
189 bool is_nested;
acf0174b
JJ
190
191 /* True if this construct can be cancelled. */
192 bool cancellable;
a79683d5 193};
953ff289 194
41dbbb37
TS
195/* A structure holding the elements of:
196 for (V = N1; V cond N2; V += STEP) [...] */
953ff289 197
a68ab351
JJ
198struct omp_for_data_loop
199{
200 tree v, n1, n2, step;
201 enum tree_code cond_code;
202};
203
50674e96 204/* A structure describing the main elements of a parallel loop. */
953ff289 205
50674e96 206struct omp_for_data
953ff289 207{
a68ab351 208 struct omp_for_data_loop loop;
726a989a 209 tree chunk_size;
538dd0b7 210 gomp_for *for_stmt;
a68ab351
JJ
211 tree pre, iter_type;
212 int collapse;
d9a6bd32
JJ
213 int ordered;
214 bool have_nowait, have_ordered, simd_schedule;
e01d41e5 215 unsigned char sched_modifiers;
953ff289 216 enum omp_clause_schedule_kind sched_kind;
a68ab351 217 struct omp_for_data_loop *loops;
953ff289
DN
218};
219
9bd46bc9
NS
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
50674e96 263
953ff289 264static splay_tree all_contexts;
a68ab351 265static int taskreg_nesting_level;
acf0174b 266static int target_nesting_level;
0645c1a2 267static struct omp_region *root_omp_region;
a68ab351 268static bitmap task_shared_vars;
5771c391 269static vec<omp_context *> taskreg_contexts;
e01d41e5 270static bool omp_any_child_fn_dumped;
953ff289 271
26127932 272static void scan_omp (gimple_seq *, omp_context *);
726a989a 273static tree scan_omp_1_op (tree *, int *, void *);
56102c7f 274static gphi *find_phi_with_arg_on_edge (tree, edge);
726a989a
RB
275
276#define WALK_SUBSTMTS \
277 case GIMPLE_BIND: \
278 case GIMPLE_TRY: \
279 case GIMPLE_CATCH: \
280 case GIMPLE_EH_FILTER: \
0a35513e 281 case GIMPLE_TRANSACTION: \
726a989a
RB
282 /* The sub-statements for these should be walked. */ \
283 *handled_ops_p = false; \
284 break;
285
e4834818
NS
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
d9a6bd32
JJ
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
ec6fe917
IV
375/* Holds offload tables with decls. */
376vec<tree, va_gc> *offload_funcs, *offload_vars;
377
726a989a
RB
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
355a7673 392static void lower_omp (gimple_seq *, omp_context *);
8ca5b2a2
JJ
393static tree lookup_decl_in_outer_ctx (tree, omp_context *);
394static tree maybe_lookup_decl_in_outer_ctx (tree, omp_context *);
953ff289 395
41dbbb37 396/* Find an OMP clause of type KIND within CLAUSES. */
953ff289 397
917948d3 398tree
e0c68ce9 399find_omp_clause (tree clauses, enum omp_clause_code kind)
953ff289
DN
400{
401 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
aaf46ef9 402 if (OMP_CLAUSE_CODE (clauses) == kind)
953ff289
DN
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{
726a989a 413 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL;
953ff289
DN
414}
415
50674e96 416
a68ab351
JJ
417/* Return true if CTX is for an omp task. */
418
419static inline bool
420is_task_ctx (omp_context *ctx)
421{
726a989a 422 return gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
a68ab351
JJ
423}
424
425
d9a6bd32
JJ
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
a68ab351
JJ
436/* Return true if CTX is for an omp parallel or omp task. */
437
438static inline bool
439is_taskreg_ctx (omp_context *ctx)
440{
d9a6bd32 441 return is_parallel_ctx (ctx) || is_task_ctx (ctx);
a68ab351
JJ
442}
443
444
50674e96 445/* Return true if REGION is a combined parallel+workshare region. */
953ff289
DN
446
447static inline bool
50674e96
DN
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
538dd0b7 458extract_omp_for_data (gomp_for *for_stmt, struct omp_for_data *fd,
a68ab351 459 struct omp_for_data_loop *loops)
50674e96 460{
a68ab351
JJ
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;
db3927fb 466 location_t loc = gimple_location (for_stmt);
0aadce73 467 bool simd = gimple_omp_for_kind (for_stmt) & GF_OMP_FOR_SIMD;
acf0174b
JJ
468 bool distribute = gimple_omp_for_kind (for_stmt)
469 == GF_OMP_FOR_KIND_DISTRIBUTE;
d9a6bd32
JJ
470 bool taskloop = gimple_omp_for_kind (for_stmt)
471 == GF_OMP_FOR_KIND_TASKLOOP;
472 tree iterv, countv;
50674e96
DN
473
474 fd->for_stmt = for_stmt;
475 fd->pre = NULL;
d9a6bd32 476 if (gimple_omp_for_collapse (for_stmt) > 1)
a68ab351
JJ
477 fd->loops = loops;
478 else
479 fd->loops = &fd->loop;
50674e96 480
acf0174b
JJ
481 fd->have_nowait = distribute || simd;
482 fd->have_ordered = false;
d9a6bd32
JJ
483 fd->collapse = 1;
484 fd->ordered = 0;
50674e96 485 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
e01d41e5 486 fd->sched_modifiers = 0;
50674e96 487 fd->chunk_size = NULL_TREE;
d9a6bd32 488 fd->simd_schedule = false;
9a771876
JJ
489 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
490 fd->sched_kind = OMP_CLAUSE_SCHEDULE_CILKFOR;
a68ab351
JJ
491 collapse_iter = NULL;
492 collapse_count = NULL;
50674e96 493
726a989a 494 for (t = gimple_omp_for_clauses (for_stmt); t ; t = OMP_CLAUSE_CHAIN (t))
aaf46ef9 495 switch (OMP_CLAUSE_CODE (t))
50674e96
DN
496 {
497 case OMP_CLAUSE_NOWAIT:
498 fd->have_nowait = true;
499 break;
500 case OMP_CLAUSE_ORDERED:
501 fd->have_ordered = true;
d9a6bd32
JJ
502 if (OMP_CLAUSE_ORDERED_EXPR (t))
503 fd->ordered = tree_to_shwi (OMP_CLAUSE_ORDERED_EXPR (t));
50674e96
DN
504 break;
505 case OMP_CLAUSE_SCHEDULE:
d9a6bd32 506 gcc_assert (!distribute && !taskloop);
e01d41e5
JJ
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);
50674e96 512 fd->chunk_size = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t);
d9a6bd32 513 fd->simd_schedule = OMP_CLAUSE_SCHEDULE_SIMD (t);
50674e96 514 break;
acf0174b
JJ
515 case OMP_CLAUSE_DIST_SCHEDULE:
516 gcc_assert (distribute);
517 fd->chunk_size = OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (t);
518 break;
a68ab351 519 case OMP_CLAUSE_COLLAPSE:
d9a6bd32 520 fd->collapse = tree_to_shwi (OMP_CLAUSE_COLLAPSE_EXPR (t));
a68ab351
JJ
521 if (fd->collapse > 1)
522 {
523 collapse_iter = &OMP_CLAUSE_COLLAPSE_ITERVAR (t);
524 collapse_count = &OMP_CLAUSE_COLLAPSE_COUNT (t);
525 }
34f2124e 526 break;
50674e96
DN
527 default:
528 break;
529 }
d9a6bd32
JJ
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 }
50674e96 538
a68ab351
JJ
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)
1cbc62c0 542 is best) or if it varies (then schedule(dynamic,N) is better). */
a68ab351
JJ
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);
d9a6bd32
JJ
549 if (taskloop)
550 fd->sched_kind = OMP_CLAUSE_SCHEDULE_RUNTIME;
50674e96
DN
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. */
a68ab351 557 if (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
acf0174b 558 || fd->have_ordered)
50674e96
DN
559 fd->chunk_size = (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
560 ? integer_zero_node : integer_one_node;
561 }
a68ab351 562
d9a6bd32
JJ
563 int cnt = fd->ordered ? fd->ordered : fd->collapse;
564 for (i = 0; i < cnt; i++)
a68ab351 565 {
d9a6bd32 566 if (i == 0 && fd->collapse == 1 && (fd->ordered == 0 || loops == NULL))
a68ab351
JJ
567 loop = &fd->loop;
568 else if (loops != NULL)
569 loop = loops + i;
570 else
571 loop = &dummy_loop;
572
726a989a 573 loop->v = gimple_omp_for_index (for_stmt, i);
a68ab351
JJ
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;
726a989a 578 loop->n1 = gimple_omp_for_initial (for_stmt, i);
a68ab351 579
726a989a
RB
580 loop->cond_code = gimple_omp_for_cond (for_stmt, i);
581 loop->n2 = gimple_omp_for_final (for_stmt, i);
a68ab351
JJ
582 switch (loop->cond_code)
583 {
584 case LT_EXPR:
585 case GT_EXPR:
586 break;
c02065fc
AH
587 case NE_EXPR:
588 gcc_assert (gimple_omp_for_kind (for_stmt)
9a771876
JJ
589 == GF_OMP_FOR_KIND_CILKSIMD
590 || (gimple_omp_for_kind (for_stmt)
591 == GF_OMP_FOR_KIND_CILKFOR));
c02065fc 592 break;
a68ab351
JJ
593 case LE_EXPR:
594 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
5d49b6a7 595 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, 1);
a68ab351 596 else
db3927fb
AH
597 loop->n2 = fold_build2_loc (loc,
598 PLUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
a68ab351
JJ
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)))
5d49b6a7 604 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, -1);
a68ab351 605 else
db3927fb
AH
606 loop->n2 = fold_build2_loc (loc,
607 MINUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
a68ab351
JJ
608 build_int_cst (TREE_TYPE (loop->n2), 1));
609 loop->cond_code = GT_EXPR;
610 break;
611 default:
612 gcc_unreachable ();
613 }
614
726a989a 615 t = gimple_omp_for_incr (for_stmt, i);
a68ab351
JJ
616 gcc_assert (TREE_OPERAND (t, 0) == var);
617 switch (TREE_CODE (t))
618 {
619 case PLUS_EXPR:
a68ab351
JJ
620 loop->step = TREE_OPERAND (t, 1);
621 break;
56099f00
RG
622 case POINTER_PLUS_EXPR:
623 loop->step = fold_convert (ssizetype, TREE_OPERAND (t, 1));
624 break;
a68ab351
JJ
625 case MINUS_EXPR:
626 loop->step = TREE_OPERAND (t, 1);
db3927fb
AH
627 loop->step = fold_build1_loc (loc,
628 NEGATE_EXPR, TREE_TYPE (loop->step),
a68ab351
JJ
629 loop->step);
630 break;
631 default:
632 gcc_unreachable ();
633 }
634
acf0174b
JJ
635 if (simd
636 || (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
637 && !fd->have_ordered))
74bf76ed
JJ
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
acf0174b 646 (TYPE_PRECISION (TREE_TYPE (loop->v)), 1);
74bf76ed
JJ
647 }
648 else if (iter_type != long_long_unsigned_type_node)
a68ab351
JJ
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)
db3927fb
AH
659 n = fold_build2_loc (loc,
660 PLUS_EXPR, TREE_TYPE (loop->v),
a68ab351
JJ
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;
db3927fb
AH
676 n2 = fold_build2_loc (loc,
677 PLUS_EXPR, TREE_TYPE (loop->v),
a68ab351
JJ
678 loop->n2, loop->step);
679 }
680 else
681 {
db3927fb
AH
682 n1 = fold_build2_loc (loc,
683 MINUS_EXPR, TREE_TYPE (loop->v),
a68ab351
JJ
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
d9a6bd32
JJ
695 if (i >= fd->collapse)
696 continue;
697
a68ab351
JJ
698 if (collapse_count && *collapse_count == NULL)
699 {
5a0f4dd3
JJ
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)
a68ab351
JJ
710 {
711 tree itype = TREE_TYPE (loop->v);
712
713 if (POINTER_TYPE_P (itype))
96f9265a 714 itype = signed_type_for (itype);
a68ab351 715 t = build_int_cst (itype, (loop->cond_code == LT_EXPR ? -1 : 1));
db3927fb
AH
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));
a68ab351 723 if (TYPE_UNSIGNED (itype) && loop->cond_code == GT_EXPR)
db3927fb
AH
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)));
a68ab351 729 else
db3927fb
AH
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);
a68ab351 733 if (count != NULL_TREE)
db3927fb
AH
734 count = fold_build2_loc (loc,
735 MULT_EXPR, long_long_unsigned_type_node,
a68ab351
JJ
736 count, t);
737 else
738 count = t;
739 if (TREE_CODE (count) != INTEGER_CST)
740 count = NULL_TREE;
741 }
5a0f4dd3 742 else if (count && !integer_zerop (count))
a68ab351
JJ
743 count = NULL_TREE;
744 }
745 }
746
74bf76ed 747 if (count
acf0174b
JJ
748 && !simd
749 && (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
750 || fd->have_ordered))
a68ab351
JJ
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)
db3927fb 765 *collapse_count = fold_convert_loc (loc, iter_type, count);
a68ab351
JJ
766 else
767 *collapse_count = create_tmp_var (iter_type, ".count");
768 }
769
d9a6bd32 770 if (fd->collapse > 1 || (fd->ordered && loops))
a68ab351
JJ
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 }
d9a6bd32
JJ
778 else if (loops)
779 loops[0] = fd->loop;
50674e96
DN
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
726a989a
RB
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:
50674e96
DN
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)
b8698a0f 802
50674e96
DN
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
726a989a 816 GIMPLE_OMP_FOR header check whether they appear on the LHS of any
50674e96
DN
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
0f900dfa 826workshare_safe_to_combine_p (basic_block ws_entry_bb)
50674e96
DN
827{
828 struct omp_for_data fd;
355fe088 829 gimple *ws_stmt = last_stmt (ws_entry_bb);
50674e96 830
726a989a 831 if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
50674e96
DN
832 return true;
833
726a989a 834 gcc_assert (gimple_code (ws_stmt) == GIMPLE_OMP_FOR);
50674e96 835
538dd0b7 836 extract_omp_for_data (as_a <gomp_for *> (ws_stmt), &fd, NULL);
a68ab351
JJ
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;
50674e96
DN
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. */
a68ab351
JJ
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)
50674e96
DN
851 || (fd.chunk_size && !is_gimple_min_invariant (fd.chunk_size)))
852 return false;
853
854 return true;
855}
856
857
d9a6bd32
JJ
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
50674e96
DN
881/* Collect additional arguments needed to emit a combined
882 parallel+workshare call. WS_STMT is the workshare directive being
883 expanded. */
884
9771b263 885static vec<tree, va_gc> *
355fe088 886get_ws_args_for (gimple *par_stmt, gimple *ws_stmt)
50674e96
DN
887{
888 tree t;
db3927fb 889 location_t loc = gimple_location (ws_stmt);
9771b263 890 vec<tree, va_gc> *ws_args;
50674e96 891
538dd0b7 892 if (gomp_for *for_stmt = dyn_cast <gomp_for *> (ws_stmt))
50674e96
DN
893 {
894 struct omp_for_data fd;
acf0174b 895 tree n1, n2;
50674e96 896
538dd0b7 897 extract_omp_for_data (for_stmt, &fd, NULL);
acf0174b
JJ
898 n1 = fd.loop.n1;
899 n2 = fd.loop.n2;
900
538dd0b7 901 if (gimple_omp_for_combined_into_p (for_stmt))
acf0174b
JJ
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 }
50674e96 913
9771b263 914 vec_alloc (ws_args, 3 + (fd.chunk_size != 0));
50674e96 915
acf0174b 916 t = fold_convert_loc (loc, long_integer_type_node, n1);
9771b263 917 ws_args->quick_push (t);
50674e96 918
acf0174b 919 t = fold_convert_loc (loc, long_integer_type_node, n2);
9771b263 920 ws_args->quick_push (t);
50674e96 921
3bb06db4 922 t = fold_convert_loc (loc, long_integer_type_node, fd.loop.step);
9771b263 923 ws_args->quick_push (t);
3bb06db4
NF
924
925 if (fd.chunk_size)
926 {
927 t = fold_convert_loc (loc, long_integer_type_node, fd.chunk_size);
d9a6bd32 928 t = omp_adjust_chunk_size (t, fd.simd_schedule);
9771b263 929 ws_args->quick_push (t);
3bb06db4 930 }
50674e96
DN
931
932 return ws_args;
933 }
726a989a 934 else if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
50674e96 935 {
e5c95afe 936 /* Number of sections is equal to the number of edges from the
726a989a
RB
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));
e5c95afe 940 t = build_int_cst (unsigned_type_node, EDGE_COUNT (bb->succs) - 1);
9771b263
DN
941 vec_alloc (ws_args, 1);
942 ws_args->quick_push (t);
3bb06db4 943 return ws_args;
50674e96
DN
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)
953ff289 954{
50674e96
DN
955 basic_block par_entry_bb, par_exit_bb;
956 basic_block ws_entry_bb, ws_exit_bb;
957
d3c673c7 958 if (region == NULL || region->inner == NULL
e5c95afe
ZD
959 || region->exit == NULL || region->inner->exit == NULL
960 || region->inner->cont == NULL)
50674e96
DN
961 return;
962
963 /* We only support parallel+for and parallel+sections. */
726a989a
RB
964 if (region->type != GIMPLE_OMP_PARALLEL
965 || (region->inner->type != GIMPLE_OMP_FOR
966 && region->inner->type != GIMPLE_OMP_SECTIONS))
50674e96
DN
967 return;
968
969 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
970 WS_EXIT_BB -> PAR_EXIT_BB. */
777f7f9a
RH
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;
50674e96
DN
975
976 if (single_succ (par_entry_bb) == ws_entry_bb
977 && single_succ (ws_exit_bb) == par_exit_bb
0f900dfa 978 && workshare_safe_to_combine_p (ws_entry_bb)
726a989a 979 && (gimple_omp_parallel_combined_p (last_stmt (par_entry_bb))
69f1837b
JJ
980 || (last_and_only_stmt (ws_entry_bb)
981 && last_and_only_stmt (par_exit_bb))))
50674e96 982 {
355fe088
TS
983 gimple *par_stmt = last_stmt (par_entry_bb);
984 gimple *ws_stmt = last_stmt (ws_entry_bb);
777f7f9a 985
726a989a 986 if (region->inner->type == GIMPLE_OMP_FOR)
50674e96
DN
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. */
726a989a 997 tree clauses = gimple_omp_for_clauses (ws_stmt);
50674e96
DN
998 tree c = find_omp_clause (clauses, OMP_CLAUSE_SCHEDULE);
999 if (c == NULL
e01d41e5
JJ
1000 || ((OMP_CLAUSE_SCHEDULE_KIND (c) & OMP_CLAUSE_SCHEDULE_MASK)
1001 == OMP_CLAUSE_SCHEDULE_STATIC)
50674e96
DN
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;
acf0174b 1012 region->ws_args = get_ws_args_for (par_stmt, ws_stmt);
50674e96 1013 }
953ff289
DN
1014}
1015
50674e96 1016
953ff289
DN
1017/* Return true if EXPR is variable sized. */
1018
1019static inline bool
22ea9ec0 1020is_variable_sized (const_tree expr)
953ff289
DN
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
41dbbb37
TS
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
953ff289
DN
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{
b787e7a2 1051 tree *n = ctx->cb.decl_map->get (var);
6be42dd4 1052 return *n;
953ff289
DN
1053}
1054
1055static inline tree
7c8f7639 1056maybe_lookup_decl (const_tree var, omp_context *ctx)
953ff289 1057{
b787e7a2 1058 tree *n = ctx->cb.decl_map->get (const_cast<tree> (var));
6be42dd4 1059 return n ? *n : NULL_TREE;
953ff289
DN
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
a68ab351 1070static inline tree
d9a6bd32 1071lookup_sfield (splay_tree_key key, omp_context *ctx)
a68ab351
JJ
1072{
1073 splay_tree_node n;
1074 n = splay_tree_lookup (ctx->sfield_map
d9a6bd32 1075 ? ctx->sfield_map : ctx->field_map, key);
a68ab351
JJ
1076 return (tree) n->value;
1077}
1078
953ff289 1079static inline tree
d9a6bd32
JJ
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)
953ff289
DN
1087{
1088 splay_tree_node n;
d9a6bd32 1089 n = splay_tree_lookup (ctx->field_map, key);
953ff289
DN
1090 return n ? (tree) n->value : NULL_TREE;
1091}
1092
d9a6bd32
JJ
1093static inline tree
1094maybe_lookup_field (tree var, omp_context *ctx)
1095{
1096 return maybe_lookup_field ((splay_tree_key) var, ctx);
1097}
1098
7c8f7639
JJ
1099/* Return true if DECL should be copied by pointer. SHARED_CTX is
1100 the parallel context if DECL is to be shared. */
953ff289
DN
1101
1102static bool
a68ab351 1103use_pointer_for_field (tree decl, omp_context *shared_ctx)
953ff289
DN
1104{
1105 if (AGGREGATE_TYPE_P (TREE_TYPE (decl)))
1106 return true;
1107
6fc0bb99 1108 /* We can only use copy-in/copy-out semantics for shared variables
953ff289 1109 when we know the value is not accessible from an outer scope. */
7c8f7639 1110 if (shared_ctx)
953ff289 1111 {
41dbbb37
TS
1112 gcc_assert (!is_gimple_omp_oacc (shared_ctx->stmt));
1113
953ff289
DN
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. */
077b0dfb 1125 if (TREE_CODE (decl) != RESULT_DECL && DECL_HAS_VALUE_EXPR_P (decl))
953ff289
DN
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;
7c8f7639 1132
6d840d99
JJ
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
7c8f7639
JJ
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. */
6d840d99 1146 if (shared_ctx->is_nested)
7c8f7639
JJ
1147 {
1148 omp_context *up;
1149
1150 for (up = shared_ctx->outer; up; up = up->outer)
d9c194cb 1151 if (is_taskreg_ctx (up) && maybe_lookup_decl (decl, up))
7c8f7639
JJ
1152 break;
1153
d9c194cb 1154 if (up)
7c8f7639
JJ
1155 {
1156 tree c;
1157
726a989a 1158 for (c = gimple_omp_taskreg_clauses (up->stmt);
7c8f7639
JJ
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)
25142650 1165 goto maybe_mark_addressable_and_ret;
7c8f7639
JJ
1166 }
1167 }
a68ab351 1168
6d840d99 1169 /* For tasks avoid using copy-in/out. As tasks can be
a68ab351
JJ
1170 deferred or executed in different thread, when GOMP_task
1171 returns, the task hasn't necessarily terminated. */
6d840d99 1172 if (is_task_ctx (shared_ctx))
a68ab351 1173 {
25142650
JJ
1174 tree outer;
1175 maybe_mark_addressable_and_ret:
1176 outer = maybe_lookup_decl_in_outer_ctx (decl, shared_ctx);
d9a6bd32 1177 if (is_gimple_reg (outer) && !omp_member_access_dummy_var (outer))
a68ab351
JJ
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 }
953ff289
DN
1189 }
1190
1191 return false;
1192}
1193
917948d3
ZD
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;
910ad8de 1202 DECL_CHAIN (copy) = ctx->block_vars;
d9a6bd32
JJ
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;
953ff289
DN
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
a9a58711
JJ
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
953ff289
DN
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
70f34814 1248 x = build_simple_mem_ref (ctx->receiver_decl);
f1b9b669 1249 TREE_THIS_NOTRAP (x) = 1;
a9a58711 1250 x = omp_build_component_ref (x, field);
953ff289 1251 if (by_ref)
70f34814 1252 x = build_simple_mem_ref (x);
953ff289
DN
1253
1254 return x;
1255}
1256
1257/* Build tree nodes to access VAR in the scope outer to CTX. In the case
1258 of a parallel, this is a component reference; for workshare constructs
1259 this is some variable. */
1260
1261static tree
d9a6bd32 1262build_outer_var_ref (tree var, omp_context *ctx, bool lastprivate = false)
953ff289
DN
1263{
1264 tree x;
1265
8ca5b2a2 1266 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx)))
953ff289
DN
1267 x = var;
1268 else if (is_variable_sized (var))
1269 {
1270 x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
d9a6bd32 1271 x = build_outer_var_ref (x, ctx, lastprivate);
70f34814 1272 x = build_simple_mem_ref (x);
953ff289 1273 }
a68ab351 1274 else if (is_taskreg_ctx (ctx))
953ff289 1275 {
7c8f7639 1276 bool by_ref = use_pointer_for_field (var, NULL);
953ff289
DN
1277 x = build_receiver_ref (var, by_ref, ctx);
1278 }
74bf76ed 1279 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
0aadce73 1280 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
74bf76ed
JJ
1281 {
1282 /* #pragma omp simd isn't a worksharing construct, and can reference even
1283 private vars in its linear etc. clauses. */
1284 x = NULL_TREE;
1285 if (ctx->outer && is_taskreg_ctx (ctx))
1286 x = lookup_decl (var, ctx->outer);
1287 else if (ctx->outer)
f3b331d1 1288 x = maybe_lookup_decl_in_outer_ctx (var, ctx);
74bf76ed
JJ
1289 if (x == NULL_TREE)
1290 x = var;
1291 }
d9a6bd32
JJ
1292 else if (lastprivate && is_taskloop_ctx (ctx))
1293 {
1294 gcc_assert (ctx->outer);
1295 splay_tree_node n
1296 = splay_tree_lookup (ctx->outer->field_map,
1297 (splay_tree_key) &DECL_UID (var));
1298 if (n == NULL)
1299 {
1300 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx->outer)))
1301 x = var;
1302 else
1303 x = lookup_decl (var, ctx->outer);
1304 }
1305 else
1306 {
1307 tree field = (tree) n->value;
1308 /* If the receiver record type was remapped in the child function,
1309 remap the field into the new record type. */
1310 x = maybe_lookup_field (field, ctx->outer);
1311 if (x != NULL)
1312 field = x;
1313
1314 x = build_simple_mem_ref (ctx->outer->receiver_decl);
1315 x = omp_build_component_ref (x, field);
1316 if (use_pointer_for_field (var, ctx->outer))
1317 x = build_simple_mem_ref (x);
1318 }
1319 }
953ff289
DN
1320 else if (ctx->outer)
1321 x = lookup_decl (var, ctx->outer);
eeb1d9e0
JJ
1322 else if (is_reference (var))
1323 /* This can happen with orphaned constructs. If var is reference, it is
1324 possible it is shared and as such valid. */
1325 x = var;
d9a6bd32
JJ
1326 else if (omp_member_access_dummy_var (var))
1327 x = var;
953ff289
DN
1328 else
1329 gcc_unreachable ();
1330
d9a6bd32
JJ
1331 if (x == var)
1332 {
1333 tree t = omp_member_access_dummy_var (var);
1334 if (t)
1335 {
1336 x = DECL_VALUE_EXPR (var);
1337 tree o = maybe_lookup_decl_in_outer_ctx (t, ctx);
1338 if (o != t)
1339 x = unshare_and_remap (x, t, o);
1340 else
1341 x = unshare_expr (x);
1342 }
1343 }
1344
953ff289 1345 if (is_reference (var))
70f34814 1346 x = build_simple_mem_ref (x);
953ff289
DN
1347
1348 return x;
1349}
1350
1351/* Build tree nodes to access the field for VAR on the sender side. */
1352
1353static tree
d9a6bd32 1354build_sender_ref (splay_tree_key key, omp_context *ctx)
953ff289 1355{
d9a6bd32 1356 tree field = lookup_sfield (key, ctx);
a9a58711 1357 return omp_build_component_ref (ctx->sender_decl, field);
953ff289
DN
1358}
1359
d9a6bd32
JJ
1360static tree
1361build_sender_ref (tree var, omp_context *ctx)
1362{
1363 return build_sender_ref ((splay_tree_key) var, ctx);
1364}
1365
953ff289
DN
1366/* Add a new field for VAR inside the structure CTX->SENDER_DECL. */
1367
1368static void
a68ab351 1369install_var_field (tree var, bool by_ref, int mask, omp_context *ctx)
953ff289 1370{
a68ab351 1371 tree field, type, sfield = NULL_TREE;
d9a6bd32 1372 splay_tree_key key = (splay_tree_key) var;
953ff289 1373
d9a6bd32
JJ
1374 if ((mask & 8) != 0)
1375 {
1376 key = (splay_tree_key) &DECL_UID (var);
1377 gcc_checking_assert (key != (splay_tree_key) var);
1378 }
a68ab351 1379 gcc_assert ((mask & 1) == 0
d9a6bd32 1380 || !splay_tree_lookup (ctx->field_map, key));
a68ab351 1381 gcc_assert ((mask & 2) == 0 || !ctx->sfield_map
d9a6bd32 1382 || !splay_tree_lookup (ctx->sfield_map, key));
41dbbb37
TS
1383 gcc_assert ((mask & 3) == 3
1384 || !is_gimple_omp_oacc (ctx->stmt));
953ff289
DN
1385
1386 type = TREE_TYPE (var);
acf0174b
JJ
1387 if (mask & 4)
1388 {
1389 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
1390 type = build_pointer_type (build_pointer_type (type));
1391 }
1392 else if (by_ref)
953ff289 1393 type = build_pointer_type (type);
a68ab351
JJ
1394 else if ((mask & 3) == 1 && is_reference (var))
1395 type = TREE_TYPE (type);
953ff289 1396
c2255bc4
AH
1397 field = build_decl (DECL_SOURCE_LOCATION (var),
1398 FIELD_DECL, DECL_NAME (var), type);
953ff289
DN
1399
1400 /* Remember what variable this field was created for. This does have a
1401 side effect of making dwarf2out ignore this member, so for helpful
1402 debugging we clear it later in delete_omp_context. */
1403 DECL_ABSTRACT_ORIGIN (field) = var;
a68ab351
JJ
1404 if (type == TREE_TYPE (var))
1405 {
1406 DECL_ALIGN (field) = DECL_ALIGN (var);
1407 DECL_USER_ALIGN (field) = DECL_USER_ALIGN (var);
1408 TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (var);
1409 }
1410 else
1411 DECL_ALIGN (field) = TYPE_ALIGN (type);
953ff289 1412
a68ab351
JJ
1413 if ((mask & 3) == 3)
1414 {
1415 insert_field_into_struct (ctx->record_type, field);
1416 if (ctx->srecord_type)
1417 {
c2255bc4
AH
1418 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1419 FIELD_DECL, DECL_NAME (var), type);
a68ab351
JJ
1420 DECL_ABSTRACT_ORIGIN (sfield) = var;
1421 DECL_ALIGN (sfield) = DECL_ALIGN (field);
1422 DECL_USER_ALIGN (sfield) = DECL_USER_ALIGN (field);
1423 TREE_THIS_VOLATILE (sfield) = TREE_THIS_VOLATILE (field);
1424 insert_field_into_struct (ctx->srecord_type, sfield);
1425 }
1426 }
1427 else
1428 {
1429 if (ctx->srecord_type == NULL_TREE)
1430 {
1431 tree t;
1432
1433 ctx->srecord_type = lang_hooks.types.make_type (RECORD_TYPE);
1434 ctx->sfield_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1435 for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
1436 {
d9a6bd32 1437 sfield = build_decl (DECL_SOURCE_LOCATION (t),
c2255bc4 1438 FIELD_DECL, DECL_NAME (t), TREE_TYPE (t));
a68ab351
JJ
1439 DECL_ABSTRACT_ORIGIN (sfield) = DECL_ABSTRACT_ORIGIN (t);
1440 insert_field_into_struct (ctx->srecord_type, sfield);
1441 splay_tree_insert (ctx->sfield_map,
1442 (splay_tree_key) DECL_ABSTRACT_ORIGIN (t),
1443 (splay_tree_value) sfield);
1444 }
1445 }
1446 sfield = field;
1447 insert_field_into_struct ((mask & 1) ? ctx->record_type
1448 : ctx->srecord_type, field);
1449 }
953ff289 1450
a68ab351 1451 if (mask & 1)
d9a6bd32 1452 splay_tree_insert (ctx->field_map, key, (splay_tree_value) field);
a68ab351 1453 if ((mask & 2) && ctx->sfield_map)
d9a6bd32 1454 splay_tree_insert (ctx->sfield_map, key, (splay_tree_value) sfield);
953ff289
DN
1455}
1456
1457static tree
1458install_var_local (tree var, omp_context *ctx)
1459{
1460 tree new_var = omp_copy_decl_1 (var, ctx);
1461 insert_decl_map (&ctx->cb, var, new_var);
1462 return new_var;
1463}
1464
1465/* Adjust the replacement for DECL in CTX for the new context. This means
1466 copying the DECL_VALUE_EXPR, and fixing up the type. */
1467
1468static void
1469fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug)
1470{
1471 tree new_decl, size;
1472
1473 new_decl = lookup_decl (decl, ctx);
1474
1475 TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb);
1476
1477 if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug)
1478 && DECL_HAS_VALUE_EXPR_P (decl))
1479 {
1480 tree ve = DECL_VALUE_EXPR (decl);
726a989a 1481 walk_tree (&ve, copy_tree_body_r, &ctx->cb, NULL);
953ff289
DN
1482 SET_DECL_VALUE_EXPR (new_decl, ve);
1483 DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
1484 }
1485
1486 if (!TREE_CONSTANT (DECL_SIZE (new_decl)))
1487 {
1488 size = remap_decl (DECL_SIZE (decl), &ctx->cb);
1489 if (size == error_mark_node)
1490 size = TYPE_SIZE (TREE_TYPE (new_decl));
1491 DECL_SIZE (new_decl) = size;
1492
1493 size = remap_decl (DECL_SIZE_UNIT (decl), &ctx->cb);
1494 if (size == error_mark_node)
1495 size = TYPE_SIZE_UNIT (TREE_TYPE (new_decl));
1496 DECL_SIZE_UNIT (new_decl) = size;
1497 }
1498}
1499
1500/* The callback for remap_decl. Search all containing contexts for a
1501 mapping of the variable; this avoids having to duplicate the splay
1502 tree ahead of time. We know a mapping doesn't already exist in the
1503 given context. Create new mappings to implement default semantics. */
1504
1505static tree
1506omp_copy_decl (tree var, copy_body_data *cb)
1507{
1508 omp_context *ctx = (omp_context *) cb;
1509 tree new_var;
1510
953ff289
DN
1511 if (TREE_CODE (var) == LABEL_DECL)
1512 {
c2255bc4 1513 new_var = create_artificial_label (DECL_SOURCE_LOCATION (var));
50674e96 1514 DECL_CONTEXT (new_var) = current_function_decl;
953ff289
DN
1515 insert_decl_map (&ctx->cb, var, new_var);
1516 return new_var;
1517 }
1518
a68ab351 1519 while (!is_taskreg_ctx (ctx))
953ff289
DN
1520 {
1521 ctx = ctx->outer;
1522 if (ctx == NULL)
1523 return var;
1524 new_var = maybe_lookup_decl (var, ctx);
1525 if (new_var)
1526 return new_var;
1527 }
1528
8ca5b2a2
JJ
1529 if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn)
1530 return var;
1531
953ff289
DN
1532 return error_mark_node;
1533}
1534
50674e96 1535
50674e96
DN
1536/* Debugging dumps for parallel regions. */
1537void dump_omp_region (FILE *, struct omp_region *, int);
1538void debug_omp_region (struct omp_region *);
1539void debug_all_omp_regions (void);
1540
1541/* Dump the parallel region tree rooted at REGION. */
1542
1543void
1544dump_omp_region (FILE *file, struct omp_region *region, int indent)
1545{
777f7f9a 1546 fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index,
726a989a 1547 gimple_code_name[region->type]);
50674e96
DN
1548
1549 if (region->inner)
1550 dump_omp_region (file, region->inner, indent + 4);
1551
777f7f9a
RH
1552 if (region->cont)
1553 {
726a989a 1554 fprintf (file, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent, "",
777f7f9a
RH
1555 region->cont->index);
1556 }
b8698a0f 1557
50674e96 1558 if (region->exit)
726a989a 1559 fprintf (file, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent, "",
777f7f9a 1560 region->exit->index);
50674e96 1561 else
777f7f9a 1562 fprintf (file, "%*s[no exit marker]\n", indent, "");
50674e96
DN
1563
1564 if (region->next)
777f7f9a 1565 dump_omp_region (file, region->next, indent);
50674e96
DN
1566}
1567
24e47c76 1568DEBUG_FUNCTION void
50674e96
DN
1569debug_omp_region (struct omp_region *region)
1570{
1571 dump_omp_region (stderr, region, 0);
1572}
1573
24e47c76 1574DEBUG_FUNCTION void
50674e96
DN
1575debug_all_omp_regions (void)
1576{
1577 dump_omp_region (stderr, root_omp_region, 0);
1578}
1579
1580
1581/* Create a new parallel region starting at STMT inside region PARENT. */
1582
0645c1a2 1583static struct omp_region *
726a989a
RB
1584new_omp_region (basic_block bb, enum gimple_code type,
1585 struct omp_region *parent)
50674e96 1586{
d3bfe4de 1587 struct omp_region *region = XCNEW (struct omp_region);
50674e96
DN
1588
1589 region->outer = parent;
777f7f9a
RH
1590 region->entry = bb;
1591 region->type = type;
50674e96
DN
1592
1593 if (parent)
1594 {
1595 /* This is a nested region. Add it to the list of inner
1596 regions in PARENT. */
1597 region->next = parent->inner;
1598 parent->inner = region;
1599 }
777f7f9a 1600 else
50674e96
DN
1601 {
1602 /* This is a toplevel region. Add it to the list of toplevel
1603 regions in ROOT_OMP_REGION. */
1604 region->next = root_omp_region;
1605 root_omp_region = region;
1606 }
777f7f9a
RH
1607
1608 return region;
1609}
1610
1611/* Release the memory associated with the region tree rooted at REGION. */
1612
1613static void
1614free_omp_region_1 (struct omp_region *region)
1615{
1616 struct omp_region *i, *n;
1617
1618 for (i = region->inner; i ; i = n)
50674e96 1619 {
777f7f9a
RH
1620 n = i->next;
1621 free_omp_region_1 (i);
50674e96
DN
1622 }
1623
777f7f9a
RH
1624 free (region);
1625}
50674e96 1626
777f7f9a
RH
1627/* Release the memory for the entire omp region tree. */
1628
1629void
1630free_omp_regions (void)
1631{
1632 struct omp_region *r, *n;
1633 for (r = root_omp_region; r ; r = n)
1634 {
1635 n = r->next;
1636 free_omp_region_1 (r);
1637 }
1638 root_omp_region = NULL;
50674e96
DN
1639}
1640
1641
953ff289
DN
1642/* Create a new context, with OUTER_CTX being the surrounding context. */
1643
1644static omp_context *
355fe088 1645new_omp_context (gimple *stmt, omp_context *outer_ctx)
953ff289
DN
1646{
1647 omp_context *ctx = XCNEW (omp_context);
1648
1649 splay_tree_insert (all_contexts, (splay_tree_key) stmt,
1650 (splay_tree_value) ctx);
1651 ctx->stmt = stmt;
1652
1653 if (outer_ctx)
1654 {
1655 ctx->outer = outer_ctx;
1656 ctx->cb = outer_ctx->cb;
1657 ctx->cb.block = NULL;
1658 ctx->depth = outer_ctx->depth + 1;
1659 }
1660 else
1661 {
1662 ctx->cb.src_fn = current_function_decl;
1663 ctx->cb.dst_fn = current_function_decl;
d52f5295 1664 ctx->cb.src_node = cgraph_node::get (current_function_decl);
fe660d7b 1665 gcc_checking_assert (ctx->cb.src_node);
953ff289
DN
1666 ctx->cb.dst_node = ctx->cb.src_node;
1667 ctx->cb.src_cfun = cfun;
1668 ctx->cb.copy_decl = omp_copy_decl;
1d65f45c 1669 ctx->cb.eh_lp_nr = 0;
953ff289
DN
1670 ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
1671 ctx->depth = 1;
1672 }
1673
b787e7a2 1674 ctx->cb.decl_map = new hash_map<tree, tree>;
953ff289
DN
1675
1676 return ctx;
1677}
1678
726a989a 1679static gimple_seq maybe_catch_exception (gimple_seq);
2368a460
JJ
1680
1681/* Finalize task copyfn. */
1682
1683static void
538dd0b7 1684finalize_task_copyfn (gomp_task *task_stmt)
2368a460
JJ
1685{
1686 struct function *child_cfun;
af16bc76 1687 tree child_fn;
355a7673 1688 gimple_seq seq = NULL, new_seq;
538dd0b7 1689 gbind *bind;
2368a460 1690
726a989a 1691 child_fn = gimple_omp_task_copy_fn (task_stmt);
2368a460
JJ
1692 if (child_fn == NULL_TREE)
1693 return;
1694
1695 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
d7ed20db 1696 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
2368a460 1697
2368a460 1698 push_cfun (child_cfun);
3ad065ef 1699 bind = gimplify_body (child_fn, false);
726a989a
RB
1700 gimple_seq_add_stmt (&seq, bind);
1701 new_seq = maybe_catch_exception (seq);
1702 if (new_seq != seq)
1703 {
1704 bind = gimple_build_bind (NULL, new_seq, NULL);
355a7673 1705 seq = NULL;
726a989a
RB
1706 gimple_seq_add_stmt (&seq, bind);
1707 }
1708 gimple_set_body (child_fn, seq);
2368a460 1709 pop_cfun ();
2368a460 1710
d7ed20db 1711 /* Inform the callgraph about the new function. */
edafad14
TV
1712 cgraph_node *node = cgraph_node::get_create (child_fn);
1713 node->parallelized_function = 1;
d52f5295 1714 cgraph_node::add_new_function (child_fn, false);
2368a460
JJ
1715}
1716
953ff289
DN
1717/* Destroy a omp_context data structures. Called through the splay tree
1718 value delete callback. */
1719
1720static void
1721delete_omp_context (splay_tree_value value)
1722{
1723 omp_context *ctx = (omp_context *) value;
1724
b787e7a2 1725 delete ctx->cb.decl_map;
953ff289
DN
1726
1727 if (ctx->field_map)
1728 splay_tree_delete (ctx->field_map);
a68ab351
JJ
1729 if (ctx->sfield_map)
1730 splay_tree_delete (ctx->sfield_map);
953ff289
DN
1731
1732 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
1733 it produces corrupt debug information. */
1734 if (ctx->record_type)
1735 {
1736 tree t;
910ad8de 1737 for (t = TYPE_FIELDS (ctx->record_type); t ; t = DECL_CHAIN (t))
953ff289
DN
1738 DECL_ABSTRACT_ORIGIN (t) = NULL;
1739 }
a68ab351
JJ
1740 if (ctx->srecord_type)
1741 {
1742 tree t;
910ad8de 1743 for (t = TYPE_FIELDS (ctx->srecord_type); t ; t = DECL_CHAIN (t))
a68ab351
JJ
1744 DECL_ABSTRACT_ORIGIN (t) = NULL;
1745 }
953ff289 1746
2368a460 1747 if (is_task_ctx (ctx))
538dd0b7 1748 finalize_task_copyfn (as_a <gomp_task *> (ctx->stmt));
2368a460 1749
953ff289
DN
1750 XDELETE (ctx);
1751}
1752
1753/* Fix up RECEIVER_DECL with a type that has been remapped to the child
1754 context. */
1755
1756static void
1757fixup_child_record_type (omp_context *ctx)
1758{
1759 tree f, type = ctx->record_type;
1760
1761 /* ??? It isn't sufficient to just call remap_type here, because
1762 variably_modified_type_p doesn't work the way we expect for
1763 record types. Testing each field for whether it needs remapping
1764 and creating a new record by hand works, however. */
910ad8de 1765 for (f = TYPE_FIELDS (type); f ; f = DECL_CHAIN (f))
953ff289
DN
1766 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
1767 break;
1768 if (f)
1769 {
1770 tree name, new_fields = NULL;
1771
1772 type = lang_hooks.types.make_type (RECORD_TYPE);
1773 name = DECL_NAME (TYPE_NAME (ctx->record_type));
c2255bc4
AH
1774 name = build_decl (DECL_SOURCE_LOCATION (ctx->receiver_decl),
1775 TYPE_DECL, name, type);
953ff289
DN
1776 TYPE_NAME (type) = name;
1777
910ad8de 1778 for (f = TYPE_FIELDS (ctx->record_type); f ; f = DECL_CHAIN (f))
953ff289
DN
1779 {
1780 tree new_f = copy_node (f);
1781 DECL_CONTEXT (new_f) = type;
1782 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
910ad8de 1783 DECL_CHAIN (new_f) = new_fields;
726a989a
RB
1784 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &ctx->cb, NULL);
1785 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r,
1786 &ctx->cb, NULL);
1787 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
1788 &ctx->cb, NULL);
953ff289
DN
1789 new_fields = new_f;
1790
1791 /* Arrange to be able to look up the receiver field
1792 given the sender field. */
1793 splay_tree_insert (ctx->field_map, (splay_tree_key) f,
1794 (splay_tree_value) new_f);
1795 }
1796 TYPE_FIELDS (type) = nreverse (new_fields);
1797 layout_type (type);
1798 }
1799
d9a6bd32
JJ
1800 /* In a target region we never modify any of the pointers in *.omp_data_i,
1801 so attempt to help the optimizers. */
1802 if (is_gimple_omp_offloaded (ctx->stmt))
1803 type = build_qualified_type (type, TYPE_QUAL_CONST);
1804
a2a2fe4b
RB
1805 TREE_TYPE (ctx->receiver_decl)
1806 = build_qualified_type (build_reference_type (type), TYPE_QUAL_RESTRICT);
953ff289
DN
1807}
1808
1809/* Instantiate decls as necessary in CTX to satisfy the data sharing
1810 specified by CLAUSES. */
1811
1812static void
1813scan_sharing_clauses (tree clauses, omp_context *ctx)
1814{
1815 tree c, decl;
1816 bool scan_array_reductions = false;
1817
1818 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1819 {
1820 bool by_ref;
1821
aaf46ef9 1822 switch (OMP_CLAUSE_CODE (c))
953ff289
DN
1823 {
1824 case OMP_CLAUSE_PRIVATE:
1825 decl = OMP_CLAUSE_DECL (c);
a68ab351
JJ
1826 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
1827 goto do_private;
1828 else if (!is_variable_sized (decl))
953ff289
DN
1829 install_var_local (decl, ctx);
1830 break;
1831
1832 case OMP_CLAUSE_SHARED:
9cf32741 1833 decl = OMP_CLAUSE_DECL (c);
acf0174b
JJ
1834 /* Ignore shared directives in teams construct. */
1835 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
9cf32741
JJ
1836 {
1837 /* Global variables don't need to be copied,
1838 the receiver side will use them directly. */
1839 tree odecl = maybe_lookup_decl_in_outer_ctx (decl, ctx);
1840 if (is_global_var (odecl))
1841 break;
1842 insert_decl_map (&ctx->cb, decl, odecl);
1843 break;
1844 }
a68ab351 1845 gcc_assert (is_taskreg_ctx (ctx));
5da250fc
JJ
1846 gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl))
1847 || !is_variable_sized (decl));
8ca5b2a2
JJ
1848 /* Global variables don't need to be copied,
1849 the receiver side will use them directly. */
1850 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1851 break;
a68ab351 1852 by_ref = use_pointer_for_field (decl, ctx);
d9a6bd32
JJ
1853 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
1854 break;
953ff289
DN
1855 if (! TREE_READONLY (decl)
1856 || TREE_ADDRESSABLE (decl)
1857 || by_ref
1858 || is_reference (decl))
1859 {
a68ab351 1860 install_var_field (decl, by_ref, 3, ctx);
953ff289
DN
1861 install_var_local (decl, ctx);
1862 break;
1863 }
1864 /* We don't need to copy const scalar vars back. */
aaf46ef9 1865 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
953ff289
DN
1866 goto do_private;
1867
d9a6bd32
JJ
1868 case OMP_CLAUSE_REDUCTION:
1869 decl = OMP_CLAUSE_DECL (c);
1870 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1871 && TREE_CODE (decl) == MEM_REF)
1872 {
1873 tree t = TREE_OPERAND (decl, 0);
e01d41e5
JJ
1874 if (TREE_CODE (t) == POINTER_PLUS_EXPR)
1875 t = TREE_OPERAND (t, 0);
d9a6bd32
JJ
1876 if (TREE_CODE (t) == INDIRECT_REF
1877 || TREE_CODE (t) == ADDR_EXPR)
1878 t = TREE_OPERAND (t, 0);
1879 install_var_local (t, ctx);
1880 if (is_taskreg_ctx (ctx)
1881 && !is_global_var (maybe_lookup_decl_in_outer_ctx (t, ctx))
1882 && !is_variable_sized (t))
1883 {
1884 by_ref = use_pointer_for_field (t, ctx);
1885 install_var_field (t, by_ref, 3, ctx);
1886 }
1887 break;
1888 }
1889 goto do_private;
1890
953ff289
DN
1891 case OMP_CLAUSE_LASTPRIVATE:
1892 /* Let the corresponding firstprivate clause create
1893 the variable. */
1894 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1895 break;
1896 /* FALLTHRU */
1897
1898 case OMP_CLAUSE_FIRSTPRIVATE:
74bf76ed 1899 case OMP_CLAUSE_LINEAR:
953ff289
DN
1900 decl = OMP_CLAUSE_DECL (c);
1901 do_private:
d9a6bd32
JJ
1902 if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
1903 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IS_DEVICE_PTR)
1904 && is_gimple_omp_offloaded (ctx->stmt))
1905 {
1906 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
1907 install_var_field (decl, !is_reference (decl), 3, ctx);
1908 else if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1909 install_var_field (decl, true, 3, ctx);
1910 else
1911 install_var_field (decl, false, 3, ctx);
1912 }
953ff289 1913 if (is_variable_sized (decl))
953ff289 1914 {
a68ab351
JJ
1915 if (is_task_ctx (ctx))
1916 install_var_field (decl, false, 1, ctx);
1917 break;
1918 }
1919 else if (is_taskreg_ctx (ctx))
1920 {
1921 bool global
1922 = is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx));
7c8f7639 1923 by_ref = use_pointer_for_field (decl, NULL);
a68ab351
JJ
1924
1925 if (is_task_ctx (ctx)
1926 && (global || by_ref || is_reference (decl)))
1927 {
1928 install_var_field (decl, false, 1, ctx);
1929 if (!global)
1930 install_var_field (decl, by_ref, 2, ctx);
1931 }
1932 else if (!global)
1933 install_var_field (decl, by_ref, 3, ctx);
953ff289
DN
1934 }
1935 install_var_local (decl, ctx);
1936 break;
1937
d9a6bd32
JJ
1938 case OMP_CLAUSE_USE_DEVICE_PTR:
1939 decl = OMP_CLAUSE_DECL (c);
1940 if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1941 install_var_field (decl, true, 3, ctx);
1942 else
1943 install_var_field (decl, false, 3, ctx);
1944 if (DECL_SIZE (decl)
1945 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1946 {
1947 tree decl2 = DECL_VALUE_EXPR (decl);
1948 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1949 decl2 = TREE_OPERAND (decl2, 0);
1950 gcc_assert (DECL_P (decl2));
1951 install_var_local (decl2, ctx);
1952 }
1953 install_var_local (decl, ctx);
1954 break;
1955
1956 case OMP_CLAUSE_IS_DEVICE_PTR:
1957 decl = OMP_CLAUSE_DECL (c);
1958 goto do_private;
1959
acf0174b 1960 case OMP_CLAUSE__LOOPTEMP_:
d9a6bd32 1961 gcc_assert (is_taskreg_ctx (ctx));
acf0174b
JJ
1962 decl = OMP_CLAUSE_DECL (c);
1963 install_var_field (decl, false, 3, ctx);
1964 install_var_local (decl, ctx);
1965 break;
1966
953ff289 1967 case OMP_CLAUSE_COPYPRIVATE:
953ff289
DN
1968 case OMP_CLAUSE_COPYIN:
1969 decl = OMP_CLAUSE_DECL (c);
7c8f7639 1970 by_ref = use_pointer_for_field (decl, NULL);
a68ab351 1971 install_var_field (decl, by_ref, 3, ctx);
953ff289
DN
1972 break;
1973
1974 case OMP_CLAUSE_DEFAULT:
1975 ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
1976 break;
1977
20906c66 1978 case OMP_CLAUSE_FINAL:
953ff289
DN
1979 case OMP_CLAUSE_IF:
1980 case OMP_CLAUSE_NUM_THREADS:
acf0174b
JJ
1981 case OMP_CLAUSE_NUM_TEAMS:
1982 case OMP_CLAUSE_THREAD_LIMIT:
1983 case OMP_CLAUSE_DEVICE:
953ff289 1984 case OMP_CLAUSE_SCHEDULE:
acf0174b
JJ
1985 case OMP_CLAUSE_DIST_SCHEDULE:
1986 case OMP_CLAUSE_DEPEND:
d9a6bd32
JJ
1987 case OMP_CLAUSE_PRIORITY:
1988 case OMP_CLAUSE_GRAINSIZE:
1989 case OMP_CLAUSE_NUM_TASKS:
9a771876 1990 case OMP_CLAUSE__CILK_FOR_COUNT_:
41dbbb37
TS
1991 case OMP_CLAUSE_NUM_GANGS:
1992 case OMP_CLAUSE_NUM_WORKERS:
1993 case OMP_CLAUSE_VECTOR_LENGTH:
953ff289 1994 if (ctx->outer)
726a989a 1995 scan_omp_op (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
953ff289
DN
1996 break;
1997
acf0174b
JJ
1998 case OMP_CLAUSE_TO:
1999 case OMP_CLAUSE_FROM:
2000 case OMP_CLAUSE_MAP:
2001 if (ctx->outer)
2002 scan_omp_op (&OMP_CLAUSE_SIZE (c), ctx->outer);
2003 decl = OMP_CLAUSE_DECL (c);
2004 /* Global variables with "omp declare target" attribute
2005 don't need to be copied, the receiver side will use them
2006 directly. */
2007 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
2008 && DECL_P (decl)
e01d41e5
JJ
2009 && ((OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_FIRSTPRIVATE_POINTER
2010 && (OMP_CLAUSE_MAP_KIND (c)
2011 != GOMP_MAP_FIRSTPRIVATE_REFERENCE))
d9a6bd32 2012 || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
acf0174b 2013 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
1f6be682 2014 && varpool_node::get_create (decl)->offloadable)
acf0174b
JJ
2015 break;
2016 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
41dbbb37 2017 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER)
acf0174b 2018 {
41dbbb37
TS
2019 /* Ignore GOMP_MAP_POINTER kind for arrays in regions that are
2020 not offloaded; there is nothing to map for those. */
2021 if (!is_gimple_omp_offloaded (ctx->stmt)
b8910447
JJ
2022 && !POINTER_TYPE_P (TREE_TYPE (decl))
2023 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
acf0174b
JJ
2024 break;
2025 }
d9a6bd32 2026 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
e01d41e5
JJ
2027 && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
2028 || (OMP_CLAUSE_MAP_KIND (c)
2029 == GOMP_MAP_FIRSTPRIVATE_REFERENCE)))
d9a6bd32
JJ
2030 {
2031 if (TREE_CODE (decl) == COMPONENT_REF
2032 || (TREE_CODE (decl) == INDIRECT_REF
2033 && TREE_CODE (TREE_OPERAND (decl, 0)) == COMPONENT_REF
2034 && (TREE_CODE (TREE_TYPE (TREE_OPERAND (decl, 0)))
2035 == REFERENCE_TYPE)))
2036 break;
2037 if (DECL_SIZE (decl)
2038 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
2039 {
2040 tree decl2 = DECL_VALUE_EXPR (decl);
2041 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2042 decl2 = TREE_OPERAND (decl2, 0);
2043 gcc_assert (DECL_P (decl2));
2044 install_var_local (decl2, ctx);
2045 }
2046 install_var_local (decl, ctx);
2047 break;
2048 }
acf0174b
JJ
2049 if (DECL_P (decl))
2050 {
2051 if (DECL_SIZE (decl)
2052 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
2053 {
2054 tree decl2 = DECL_VALUE_EXPR (decl);
2055 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2056 decl2 = TREE_OPERAND (decl2, 0);
2057 gcc_assert (DECL_P (decl2));
e01d41e5 2058 install_var_field (decl2, true, 3, ctx);
acf0174b
JJ
2059 install_var_local (decl2, ctx);
2060 install_var_local (decl, ctx);
2061 }
2062 else
2063 {
2064 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
41dbbb37 2065 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
acf0174b
JJ
2066 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
2067 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
2068 install_var_field (decl, true, 7, ctx);
2069 else
2070 install_var_field (decl, true, 3, ctx);
41dbbb37 2071 if (is_gimple_omp_offloaded (ctx->stmt))
acf0174b
JJ
2072 install_var_local (decl, ctx);
2073 }
2074 }
2075 else
2076 {
2077 tree base = get_base_address (decl);
2078 tree nc = OMP_CLAUSE_CHAIN (c);
2079 if (DECL_P (base)
2080 && nc != NULL_TREE
2081 && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
2082 && OMP_CLAUSE_DECL (nc) == base
41dbbb37 2083 && OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_POINTER
acf0174b
JJ
2084 && integer_zerop (OMP_CLAUSE_SIZE (nc)))
2085 {
2086 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c) = 1;
2087 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (nc) = 1;
2088 }
2089 else
2090 {
f014c653
JJ
2091 if (ctx->outer)
2092 {
2093 scan_omp_op (&OMP_CLAUSE_DECL (c), ctx->outer);
2094 decl = OMP_CLAUSE_DECL (c);
2095 }
acf0174b
JJ
2096 gcc_assert (!splay_tree_lookup (ctx->field_map,
2097 (splay_tree_key) decl));
2098 tree field
2099 = build_decl (OMP_CLAUSE_LOCATION (c),
2100 FIELD_DECL, NULL_TREE, ptr_type_node);
2101 DECL_ALIGN (field) = TYPE_ALIGN (ptr_type_node);
2102 insert_field_into_struct (ctx->record_type, field);
2103 splay_tree_insert (ctx->field_map, (splay_tree_key) decl,
2104 (splay_tree_value) field);
2105 }
2106 }
2107 break;
2108
953ff289
DN
2109 case OMP_CLAUSE_NOWAIT:
2110 case OMP_CLAUSE_ORDERED:
a68ab351
JJ
2111 case OMP_CLAUSE_COLLAPSE:
2112 case OMP_CLAUSE_UNTIED:
20906c66 2113 case OMP_CLAUSE_MERGEABLE:
acf0174b 2114 case OMP_CLAUSE_PROC_BIND:
74bf76ed 2115 case OMP_CLAUSE_SAFELEN:
d9a6bd32
JJ
2116 case OMP_CLAUSE_SIMDLEN:
2117 case OMP_CLAUSE_THREADS:
2118 case OMP_CLAUSE_SIMD:
2119 case OMP_CLAUSE_NOGROUP:
2120 case OMP_CLAUSE_DEFAULTMAP:
41dbbb37
TS
2121 case OMP_CLAUSE_ASYNC:
2122 case OMP_CLAUSE_WAIT:
2123 case OMP_CLAUSE_GANG:
2124 case OMP_CLAUSE_WORKER:
2125 case OMP_CLAUSE_VECTOR:
7a5e4956 2126 case OMP_CLAUSE_TILE:
c5a64cfe
NS
2127 case OMP_CLAUSE_INDEPENDENT:
2128 case OMP_CLAUSE_AUTO:
2129 case OMP_CLAUSE_SEQ:
953ff289
DN
2130 break;
2131
acf0174b
JJ
2132 case OMP_CLAUSE_ALIGNED:
2133 decl = OMP_CLAUSE_DECL (c);
2134 if (is_global_var (decl)
2135 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
2136 install_var_local (decl, ctx);
2137 break;
2138
41dbbb37
TS
2139 case OMP_CLAUSE_DEVICE_RESIDENT:
2140 case OMP_CLAUSE_USE_DEVICE:
2141 case OMP_CLAUSE__CACHE_:
41dbbb37
TS
2142 sorry ("Clause not supported yet");
2143 break;
2144
953ff289
DN
2145 default:
2146 gcc_unreachable ();
2147 }
2148 }
2149
2150 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2151 {
aaf46ef9 2152 switch (OMP_CLAUSE_CODE (c))
953ff289
DN
2153 {
2154 case OMP_CLAUSE_LASTPRIVATE:
2155 /* Let the corresponding firstprivate clause create
2156 the variable. */
726a989a 2157 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
a68ab351 2158 scan_array_reductions = true;
953ff289
DN
2159 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
2160 break;
2161 /* FALLTHRU */
2162
953ff289 2163 case OMP_CLAUSE_FIRSTPRIVATE:
41dbbb37 2164 case OMP_CLAUSE_PRIVATE:
74bf76ed 2165 case OMP_CLAUSE_LINEAR:
d9a6bd32 2166 case OMP_CLAUSE_IS_DEVICE_PTR:
953ff289
DN
2167 decl = OMP_CLAUSE_DECL (c);
2168 if (is_variable_sized (decl))
d9a6bd32
JJ
2169 {
2170 if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
2171 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IS_DEVICE_PTR)
2172 && is_gimple_omp_offloaded (ctx->stmt))
2173 {
2174 tree decl2 = DECL_VALUE_EXPR (decl);
2175 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2176 decl2 = TREE_OPERAND (decl2, 0);
2177 gcc_assert (DECL_P (decl2));
2178 install_var_local (decl2, ctx);
2179 fixup_remapped_decl (decl2, ctx, false);
2180 }
2181 install_var_local (decl, ctx);
2182 }
953ff289 2183 fixup_remapped_decl (decl, ctx,
aaf46ef9 2184 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
953ff289 2185 && OMP_CLAUSE_PRIVATE_DEBUG (c));
d9a6bd32
JJ
2186 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
2187 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
953ff289 2188 scan_array_reductions = true;
d9a6bd32
JJ
2189 break;
2190
2191 case OMP_CLAUSE_REDUCTION:
2192 decl = OMP_CLAUSE_DECL (c);
2193 if (TREE_CODE (decl) != MEM_REF)
2194 {
2195 if (is_variable_sized (decl))
2196 install_var_local (decl, ctx);
2197 fixup_remapped_decl (decl, ctx, false);
2198 }
2199 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
f7468577 2200 scan_array_reductions = true;
953ff289
DN
2201 break;
2202
2203 case OMP_CLAUSE_SHARED:
acf0174b
JJ
2204 /* Ignore shared directives in teams construct. */
2205 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
2206 break;
953ff289 2207 decl = OMP_CLAUSE_DECL (c);
d9a6bd32
JJ
2208 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
2209 break;
2210 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
2211 {
2212 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl,
2213 ctx->outer)))
2214 break;
2215 bool by_ref = use_pointer_for_field (decl, ctx);
2216 install_var_field (decl, by_ref, 11, ctx);
2217 break;
2218 }
2219 fixup_remapped_decl (decl, ctx, false);
953ff289
DN
2220 break;
2221
acf0174b 2222 case OMP_CLAUSE_MAP:
41dbbb37 2223 if (!is_gimple_omp_offloaded (ctx->stmt))
acf0174b
JJ
2224 break;
2225 decl = OMP_CLAUSE_DECL (c);
2226 if (DECL_P (decl)
e01d41e5
JJ
2227 && ((OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_FIRSTPRIVATE_POINTER
2228 && (OMP_CLAUSE_MAP_KIND (c)
2229 != GOMP_MAP_FIRSTPRIVATE_REFERENCE))
d9a6bd32 2230 || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
acf0174b 2231 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
1f6be682 2232 && varpool_node::get_create (decl)->offloadable)
acf0174b
JJ
2233 break;
2234 if (DECL_P (decl))
2235 {
d9a6bd32
JJ
2236 if ((OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
2237 || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER)
acf0174b
JJ
2238 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
2239 && !COMPLETE_TYPE_P (TREE_TYPE (decl)))
2240 {
2241 tree new_decl = lookup_decl (decl, ctx);
2242 TREE_TYPE (new_decl)
2243 = remap_type (TREE_TYPE (decl), &ctx->cb);
2244 }
2245 else if (DECL_SIZE (decl)
2246 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
2247 {
2248 tree decl2 = DECL_VALUE_EXPR (decl);
2249 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2250 decl2 = TREE_OPERAND (decl2, 0);
2251 gcc_assert (DECL_P (decl2));
2252 fixup_remapped_decl (decl2, ctx, false);
2253 fixup_remapped_decl (decl, ctx, true);
2254 }
2255 else
2256 fixup_remapped_decl (decl, ctx, false);
2257 }
2258 break;
2259
953ff289
DN
2260 case OMP_CLAUSE_COPYPRIVATE:
2261 case OMP_CLAUSE_COPYIN:
2262 case OMP_CLAUSE_DEFAULT:
2263 case OMP_CLAUSE_IF:
2264 case OMP_CLAUSE_NUM_THREADS:
acf0174b
JJ
2265 case OMP_CLAUSE_NUM_TEAMS:
2266 case OMP_CLAUSE_THREAD_LIMIT:
2267 case OMP_CLAUSE_DEVICE:
953ff289 2268 case OMP_CLAUSE_SCHEDULE:
acf0174b 2269 case OMP_CLAUSE_DIST_SCHEDULE:
953ff289
DN
2270 case OMP_CLAUSE_NOWAIT:
2271 case OMP_CLAUSE_ORDERED:
a68ab351
JJ
2272 case OMP_CLAUSE_COLLAPSE:
2273 case OMP_CLAUSE_UNTIED:
20906c66
JJ
2274 case OMP_CLAUSE_FINAL:
2275 case OMP_CLAUSE_MERGEABLE:
acf0174b 2276 case OMP_CLAUSE_PROC_BIND:
74bf76ed 2277 case OMP_CLAUSE_SAFELEN:
d9a6bd32 2278 case OMP_CLAUSE_SIMDLEN:
acf0174b
JJ
2279 case OMP_CLAUSE_ALIGNED:
2280 case OMP_CLAUSE_DEPEND:
2281 case OMP_CLAUSE__LOOPTEMP_:
2282 case OMP_CLAUSE_TO:
2283 case OMP_CLAUSE_FROM:
d9a6bd32
JJ
2284 case OMP_CLAUSE_PRIORITY:
2285 case OMP_CLAUSE_GRAINSIZE:
2286 case OMP_CLAUSE_NUM_TASKS:
2287 case OMP_CLAUSE_THREADS:
2288 case OMP_CLAUSE_SIMD:
2289 case OMP_CLAUSE_NOGROUP:
2290 case OMP_CLAUSE_DEFAULTMAP:
2291 case OMP_CLAUSE_USE_DEVICE_PTR:
9a771876 2292 case OMP_CLAUSE__CILK_FOR_COUNT_:
41dbbb37
TS
2293 case OMP_CLAUSE_ASYNC:
2294 case OMP_CLAUSE_WAIT:
2295 case OMP_CLAUSE_NUM_GANGS:
2296 case OMP_CLAUSE_NUM_WORKERS:
2297 case OMP_CLAUSE_VECTOR_LENGTH:
2298 case OMP_CLAUSE_GANG:
2299 case OMP_CLAUSE_WORKER:
2300 case OMP_CLAUSE_VECTOR:
7a5e4956 2301 case OMP_CLAUSE_TILE:
c5a64cfe
NS
2302 case OMP_CLAUSE_INDEPENDENT:
2303 case OMP_CLAUSE_AUTO:
2304 case OMP_CLAUSE_SEQ:
41dbbb37
TS
2305 break;
2306
2307 case OMP_CLAUSE_DEVICE_RESIDENT:
2308 case OMP_CLAUSE_USE_DEVICE:
2309 case OMP_CLAUSE__CACHE_:
41dbbb37 2310 sorry ("Clause not supported yet");
953ff289
DN
2311 break;
2312
2313 default:
2314 gcc_unreachable ();
2315 }
2316 }
2317
41dbbb37
TS
2318 gcc_checking_assert (!scan_array_reductions
2319 || !is_gimple_omp_oacc (ctx->stmt));
953ff289
DN
2320 if (scan_array_reductions)
2321 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
aaf46ef9 2322 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
953ff289
DN
2323 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2324 {
26127932
JJ
2325 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
2326 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
953ff289 2327 }
a68ab351 2328 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
726a989a 2329 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
26127932 2330 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
f7468577
JJ
2331 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
2332 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
2333 scan_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
953ff289
DN
2334}
2335
9a771876
JJ
2336/* Create a new name for omp child function. Returns an identifier. If
2337 IS_CILK_FOR is true then the suffix for the child function is
2338 "_cilk_for_fn." */
953ff289 2339
953ff289 2340static tree
9a771876 2341create_omp_child_function_name (bool task_copy, bool is_cilk_for)
953ff289 2342{
9a771876
JJ
2343 if (is_cilk_for)
2344 return clone_function_name (current_function_decl, "_cilk_for_fn");
2345 return clone_function_name (current_function_decl,
2346 task_copy ? "_omp_cpyfn" : "_omp_fn");
2347}
2348
2349/* Returns the type of the induction variable for the child function for
2350 _Cilk_for and the types for _high and _low variables based on TYPE. */
2351
2352static tree
2353cilk_for_check_loop_diff_type (tree type)
2354{
2355 if (TYPE_PRECISION (type) <= TYPE_PRECISION (uint32_type_node))
2356 {
2357 if (TYPE_UNSIGNED (type))
2358 return uint32_type_node;
2359 else
2360 return integer_type_node;
2361 }
2362 else
2363 {
2364 if (TYPE_UNSIGNED (type))
2365 return uint64_type_node;
2366 else
2367 return long_long_integer_type_node;
2368 }
953ff289
DN
2369}
2370
2371/* Build a decl for the omp child function. It'll not contain a body
2372 yet, just the bare decl. */
2373
2374static void
a68ab351 2375create_omp_child_function (omp_context *ctx, bool task_copy)
953ff289
DN
2376{
2377 tree decl, type, name, t;
2378
9a771876
JJ
2379 tree cilk_for_count
2380 = (flag_cilkplus && gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2381 ? find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
2382 OMP_CLAUSE__CILK_FOR_COUNT_) : NULL_TREE;
2383 tree cilk_var_type = NULL_TREE;
2384
2385 name = create_omp_child_function_name (task_copy,
2386 cilk_for_count != NULL_TREE);
a68ab351
JJ
2387 if (task_copy)
2388 type = build_function_type_list (void_type_node, ptr_type_node,
2389 ptr_type_node, NULL_TREE);
9a771876
JJ
2390 else if (cilk_for_count)
2391 {
2392 type = TREE_TYPE (OMP_CLAUSE_OPERAND (cilk_for_count, 0));
2393 cilk_var_type = cilk_for_check_loop_diff_type (type);
2394 type = build_function_type_list (void_type_node, ptr_type_node,
2395 cilk_var_type, cilk_var_type, NULL_TREE);
2396 }
a68ab351
JJ
2397 else
2398 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
953ff289 2399
9a771876 2400 decl = build_decl (gimple_location (ctx->stmt), FUNCTION_DECL, name, type);
953ff289 2401
41dbbb37
TS
2402 gcc_checking_assert (!is_gimple_omp_oacc (ctx->stmt)
2403 || !task_copy);
a68ab351
JJ
2404 if (!task_copy)
2405 ctx->cb.dst_fn = decl;
2406 else
726a989a 2407 gimple_omp_task_set_copy_fn (ctx->stmt, decl);
953ff289
DN
2408
2409 TREE_STATIC (decl) = 1;
2410 TREE_USED (decl) = 1;
2411 DECL_ARTIFICIAL (decl) = 1;
2412 DECL_IGNORED_P (decl) = 0;
2413 TREE_PUBLIC (decl) = 0;
2414 DECL_UNINLINABLE (decl) = 1;
2415 DECL_EXTERNAL (decl) = 0;
2416 DECL_CONTEXT (decl) = NULL_TREE;
50674e96 2417 DECL_INITIAL (decl) = make_node (BLOCK);
1f6be682
IV
2418 if (cgraph_node::get (current_function_decl)->offloadable)
2419 cgraph_node::get_create (decl)->offloadable = 1;
acf0174b
JJ
2420 else
2421 {
2422 omp_context *octx;
2423 for (octx = ctx; octx; octx = octx->outer)
41dbbb37 2424 if (is_gimple_omp_offloaded (octx->stmt))
acf0174b 2425 {
1f6be682 2426 cgraph_node::get_create (decl)->offloadable = 1;
844b0125 2427#ifdef ENABLE_OFFLOADING
1f6be682 2428 g->have_offload = true;
844b0125 2429#endif
acf0174b
JJ
2430 break;
2431 }
2432 }
953ff289 2433
d7823208
BS
2434 if (cgraph_node::get_create (decl)->offloadable
2435 && !lookup_attribute ("omp declare target",
2436 DECL_ATTRIBUTES (current_function_decl)))
2437 DECL_ATTRIBUTES (decl)
2438 = tree_cons (get_identifier ("omp target entrypoint"),
2439 NULL_TREE, DECL_ATTRIBUTES (decl));
2440
c2255bc4
AH
2441 t = build_decl (DECL_SOURCE_LOCATION (decl),
2442 RESULT_DECL, NULL_TREE, void_type_node);
953ff289
DN
2443 DECL_ARTIFICIAL (t) = 1;
2444 DECL_IGNORED_P (t) = 1;
07485407 2445 DECL_CONTEXT (t) = decl;
953ff289
DN
2446 DECL_RESULT (decl) = t;
2447
9a771876
JJ
2448 /* _Cilk_for's child function requires two extra parameters called
2449 __low and __high that are set the by Cilk runtime when it calls this
2450 function. */
2451 if (cilk_for_count)
2452 {
2453 t = build_decl (DECL_SOURCE_LOCATION (decl),
2454 PARM_DECL, get_identifier ("__high"), cilk_var_type);
2455 DECL_ARTIFICIAL (t) = 1;
2456 DECL_NAMELESS (t) = 1;
2457 DECL_ARG_TYPE (t) = ptr_type_node;
2458 DECL_CONTEXT (t) = current_function_decl;
2459 TREE_USED (t) = 1;
2460 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2461 DECL_ARGUMENTS (decl) = t;
2462
2463 t = build_decl (DECL_SOURCE_LOCATION (decl),
2464 PARM_DECL, get_identifier ("__low"), cilk_var_type);
2465 DECL_ARTIFICIAL (t) = 1;
2466 DECL_NAMELESS (t) = 1;
2467 DECL_ARG_TYPE (t) = ptr_type_node;
2468 DECL_CONTEXT (t) = current_function_decl;
2469 TREE_USED (t) = 1;
2470 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2471 DECL_ARGUMENTS (decl) = t;
2472 }
2473
2474 tree data_name = get_identifier (".omp_data_i");
2475 t = build_decl (DECL_SOURCE_LOCATION (decl), PARM_DECL, data_name,
2476 ptr_type_node);
953ff289 2477 DECL_ARTIFICIAL (t) = 1;
cd3f04c8 2478 DECL_NAMELESS (t) = 1;
953ff289 2479 DECL_ARG_TYPE (t) = ptr_type_node;
50674e96 2480 DECL_CONTEXT (t) = current_function_decl;
953ff289 2481 TREE_USED (t) = 1;
d9a6bd32 2482 TREE_READONLY (t) = 1;
9a771876
JJ
2483 if (cilk_for_count)
2484 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
953ff289 2485 DECL_ARGUMENTS (decl) = t;
a68ab351
JJ
2486 if (!task_copy)
2487 ctx->receiver_decl = t;
2488 else
2489 {
c2255bc4
AH
2490 t = build_decl (DECL_SOURCE_LOCATION (decl),
2491 PARM_DECL, get_identifier (".omp_data_o"),
a68ab351
JJ
2492 ptr_type_node);
2493 DECL_ARTIFICIAL (t) = 1;
cd3f04c8 2494 DECL_NAMELESS (t) = 1;
a68ab351
JJ
2495 DECL_ARG_TYPE (t) = ptr_type_node;
2496 DECL_CONTEXT (t) = current_function_decl;
2497 TREE_USED (t) = 1;
628c189e 2498 TREE_ADDRESSABLE (t) = 1;
910ad8de 2499 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
a68ab351
JJ
2500 DECL_ARGUMENTS (decl) = t;
2501 }
953ff289 2502
b8698a0f 2503 /* Allocate memory for the function structure. The call to
50674e96 2504 allocate_struct_function clobbers CFUN, so we need to restore
953ff289 2505 it afterward. */
db2960f4 2506 push_struct_function (decl);
726a989a 2507 cfun->function_end_locus = gimple_location (ctx->stmt);
db2960f4 2508 pop_cfun ();
953ff289
DN
2509}
2510
acf0174b
JJ
2511/* Callback for walk_gimple_seq. Check if combined parallel
2512 contains gimple_omp_for_combined_into_p OMP_FOR. */
2513
2514static tree
2515find_combined_for (gimple_stmt_iterator *gsi_p,
2516 bool *handled_ops_p,
2517 struct walk_stmt_info *wi)
2518{
355fe088 2519 gimple *stmt = gsi_stmt (*gsi_p);
acf0174b
JJ
2520
2521 *handled_ops_p = true;
2522 switch (gimple_code (stmt))
2523 {
2524 WALK_SUBSTMTS;
2525
2526 case GIMPLE_OMP_FOR:
2527 if (gimple_omp_for_combined_into_p (stmt)
d9a6bd32
JJ
2528 && gimple_omp_for_kind (stmt)
2529 == *(const enum gf_mask *) (wi->info))
acf0174b
JJ
2530 {
2531 wi->info = stmt;
2532 return integer_zero_node;
2533 }
2534 break;
2535 default:
2536 break;
2537 }
2538 return NULL;
2539}
2540
d9a6bd32
JJ
2541/* Add _LOOPTEMP_ clauses on OpenMP parallel or task. */
2542
2543static void
2544add_taskreg_looptemp_clauses (enum gf_mask msk, gimple *stmt,
2545 omp_context *outer_ctx)
2546{
2547 struct walk_stmt_info wi;
2548
2549 memset (&wi, 0, sizeof (wi));
2550 wi.val_only = true;
2551 wi.info = (void *) &msk;
2552 walk_gimple_seq (gimple_omp_body (stmt), find_combined_for, NULL, &wi);
2553 if (wi.info != (void *) &msk)
2554 {
2555 gomp_for *for_stmt = as_a <gomp_for *> ((gimple *) wi.info);
2556 struct omp_for_data fd;
2557 extract_omp_for_data (for_stmt, &fd, NULL);
2558 /* We need two temporaries with fd.loop.v type (istart/iend)
2559 and then (fd.collapse - 1) temporaries with the same
2560 type for count2 ... countN-1 vars if not constant. */
2561 size_t count = 2, i;
2562 tree type = fd.iter_type;
2563 if (fd.collapse > 1
2564 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
2565 {
2566 count += fd.collapse - 1;
e01d41e5 2567 /* If there are lastprivate clauses on the inner
d9a6bd32
JJ
2568 GIMPLE_OMP_FOR, add one more temporaries for the total number
2569 of iterations (product of count1 ... countN-1). */
e01d41e5
JJ
2570 if (find_omp_clause (gimple_omp_for_clauses (for_stmt),
2571 OMP_CLAUSE_LASTPRIVATE))
2572 count++;
2573 else if (msk == GF_OMP_FOR_KIND_FOR
2574 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
2575 OMP_CLAUSE_LASTPRIVATE))
d9a6bd32
JJ
2576 count++;
2577 }
2578 for (i = 0; i < count; i++)
2579 {
2580 tree temp = create_tmp_var (type);
2581 tree c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
2582 insert_decl_map (&outer_ctx->cb, temp, temp);
2583 OMP_CLAUSE_DECL (c) = temp;
2584 OMP_CLAUSE_CHAIN (c) = gimple_omp_taskreg_clauses (stmt);
2585 gimple_omp_taskreg_set_clauses (stmt, c);
2586 }
2587 }
2588}
2589
953ff289
DN
2590/* Scan an OpenMP parallel directive. */
2591
2592static void
726a989a 2593scan_omp_parallel (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
953ff289
DN
2594{
2595 omp_context *ctx;
2596 tree name;
538dd0b7 2597 gomp_parallel *stmt = as_a <gomp_parallel *> (gsi_stmt (*gsi));
953ff289
DN
2598
2599 /* Ignore parallel directives with empty bodies, unless there
2600 are copyin clauses. */
2601 if (optimize > 0
726a989a
RB
2602 && empty_body_p (gimple_omp_body (stmt))
2603 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
2604 OMP_CLAUSE_COPYIN) == NULL)
953ff289 2605 {
726a989a 2606 gsi_replace (gsi, gimple_build_nop (), false);
953ff289
DN
2607 return;
2608 }
2609
acf0174b 2610 if (gimple_omp_parallel_combined_p (stmt))
d9a6bd32 2611 add_taskreg_looptemp_clauses (GF_OMP_FOR_KIND_FOR, stmt, outer_ctx);
acf0174b 2612
726a989a 2613 ctx = new_omp_context (stmt, outer_ctx);
5771c391 2614 taskreg_contexts.safe_push (ctx);
a68ab351 2615 if (taskreg_nesting_level > 1)
50674e96 2616 ctx->is_nested = true;
953ff289 2617 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
953ff289
DN
2618 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2619 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
953ff289 2620 name = create_tmp_var_name (".omp_data_s");
c2255bc4
AH
2621 name = build_decl (gimple_location (stmt),
2622 TYPE_DECL, name, ctx->record_type);
cd3f04c8
JJ
2623 DECL_ARTIFICIAL (name) = 1;
2624 DECL_NAMELESS (name) = 1;
953ff289 2625 TYPE_NAME (ctx->record_type) = name;
f7484978 2626 TYPE_ARTIFICIAL (ctx->record_type) = 1;
a68ab351 2627 create_omp_child_function (ctx, false);
726a989a 2628 gimple_omp_parallel_set_child_fn (stmt, ctx->cb.dst_fn);
953ff289 2629
726a989a 2630 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt), ctx);
26127932 2631 scan_omp (gimple_omp_body_ptr (stmt), ctx);
953ff289
DN
2632
2633 if (TYPE_FIELDS (ctx->record_type) == NULL)
2634 ctx->record_type = ctx->receiver_decl = NULL;
953ff289
DN
2635}
2636
a68ab351
JJ
2637/* Scan an OpenMP task directive. */
2638
2639static void
726a989a 2640scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
a68ab351
JJ
2641{
2642 omp_context *ctx;
726a989a 2643 tree name, t;
538dd0b7 2644 gomp_task *stmt = as_a <gomp_task *> (gsi_stmt (*gsi));
a68ab351
JJ
2645
2646 /* Ignore task directives with empty bodies. */
2647 if (optimize > 0
726a989a 2648 && empty_body_p (gimple_omp_body (stmt)))
a68ab351 2649 {
726a989a 2650 gsi_replace (gsi, gimple_build_nop (), false);
a68ab351
JJ
2651 return;
2652 }
2653
d9a6bd32
JJ
2654 if (gimple_omp_task_taskloop_p (stmt))
2655 add_taskreg_looptemp_clauses (GF_OMP_FOR_KIND_TASKLOOP, stmt, outer_ctx);
2656
726a989a 2657 ctx = new_omp_context (stmt, outer_ctx);
5771c391 2658 taskreg_contexts.safe_push (ctx);
a68ab351
JJ
2659 if (taskreg_nesting_level > 1)
2660 ctx->is_nested = true;
2661 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2662 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2663 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2664 name = create_tmp_var_name (".omp_data_s");
c2255bc4
AH
2665 name = build_decl (gimple_location (stmt),
2666 TYPE_DECL, name, ctx->record_type);
cd3f04c8
JJ
2667 DECL_ARTIFICIAL (name) = 1;
2668 DECL_NAMELESS (name) = 1;
a68ab351 2669 TYPE_NAME (ctx->record_type) = name;
f7484978 2670 TYPE_ARTIFICIAL (ctx->record_type) = 1;
a68ab351 2671 create_omp_child_function (ctx, false);
726a989a 2672 gimple_omp_task_set_child_fn (stmt, ctx->cb.dst_fn);
a68ab351 2673
726a989a 2674 scan_sharing_clauses (gimple_omp_task_clauses (stmt), ctx);
a68ab351
JJ
2675
2676 if (ctx->srecord_type)
2677 {
2678 name = create_tmp_var_name (".omp_data_a");
c2255bc4
AH
2679 name = build_decl (gimple_location (stmt),
2680 TYPE_DECL, name, ctx->srecord_type);
cd3f04c8
JJ
2681 DECL_ARTIFICIAL (name) = 1;
2682 DECL_NAMELESS (name) = 1;
a68ab351 2683 TYPE_NAME (ctx->srecord_type) = name;
f7484978 2684 TYPE_ARTIFICIAL (ctx->srecord_type) = 1;
a68ab351
JJ
2685 create_omp_child_function (ctx, true);
2686 }
2687
26127932 2688 scan_omp (gimple_omp_body_ptr (stmt), ctx);
a68ab351
JJ
2689
2690 if (TYPE_FIELDS (ctx->record_type) == NULL)
2691 {
2692 ctx->record_type = ctx->receiver_decl = NULL;
726a989a
RB
2693 t = build_int_cst (long_integer_type_node, 0);
2694 gimple_omp_task_set_arg_size (stmt, t);
2695 t = build_int_cst (long_integer_type_node, 1);
2696 gimple_omp_task_set_arg_align (stmt, t);
a68ab351 2697 }
5771c391
JJ
2698}
2699
2700
2701/* If any decls have been made addressable during scan_omp,
2702 adjust their fields if needed, and layout record types
2703 of parallel/task constructs. */
2704
2705static void
2706finish_taskreg_scan (omp_context *ctx)
2707{
2708 if (ctx->record_type == NULL_TREE)
2709 return;
2710
2711 /* If any task_shared_vars were needed, verify all
2712 OMP_CLAUSE_SHARED clauses on GIMPLE_OMP_{PARALLEL,TASK}
2713 statements if use_pointer_for_field hasn't changed
2714 because of that. If it did, update field types now. */
2715 if (task_shared_vars)
2716 {
2717 tree c;
2718
2719 for (c = gimple_omp_taskreg_clauses (ctx->stmt);
2720 c; c = OMP_CLAUSE_CHAIN (c))
d9a6bd32
JJ
2721 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
2722 && !OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
5771c391
JJ
2723 {
2724 tree decl = OMP_CLAUSE_DECL (c);
2725
2726 /* Global variables don't need to be copied,
2727 the receiver side will use them directly. */
2728 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
2729 continue;
2730 if (!bitmap_bit_p (task_shared_vars, DECL_UID (decl))
2731 || !use_pointer_for_field (decl, ctx))
2732 continue;
2733 tree field = lookup_field (decl, ctx);
2734 if (TREE_CODE (TREE_TYPE (field)) == POINTER_TYPE
2735 && TREE_TYPE (TREE_TYPE (field)) == TREE_TYPE (decl))
2736 continue;
2737 TREE_TYPE (field) = build_pointer_type (TREE_TYPE (decl));
2738 TREE_THIS_VOLATILE (field) = 0;
2739 DECL_USER_ALIGN (field) = 0;
2740 DECL_ALIGN (field) = TYPE_ALIGN (TREE_TYPE (field));
2741 if (TYPE_ALIGN (ctx->record_type) < DECL_ALIGN (field))
2742 TYPE_ALIGN (ctx->record_type) = DECL_ALIGN (field);
2743 if (ctx->srecord_type)
2744 {
2745 tree sfield = lookup_sfield (decl, ctx);
2746 TREE_TYPE (sfield) = TREE_TYPE (field);
2747 TREE_THIS_VOLATILE (sfield) = 0;
2748 DECL_USER_ALIGN (sfield) = 0;
2749 DECL_ALIGN (sfield) = DECL_ALIGN (field);
2750 if (TYPE_ALIGN (ctx->srecord_type) < DECL_ALIGN (sfield))
2751 TYPE_ALIGN (ctx->srecord_type) = DECL_ALIGN (sfield);
2752 }
2753 }
2754 }
2755
2756 if (gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2757 {
2758 layout_type (ctx->record_type);
2759 fixup_child_record_type (ctx);
2760 }
a68ab351
JJ
2761 else
2762 {
5771c391 2763 location_t loc = gimple_location (ctx->stmt);
a68ab351
JJ
2764 tree *p, vla_fields = NULL_TREE, *q = &vla_fields;
2765 /* Move VLA fields to the end. */
2766 p = &TYPE_FIELDS (ctx->record_type);
2767 while (*p)
2768 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p))
2769 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p))))
2770 {
2771 *q = *p;
2772 *p = TREE_CHAIN (*p);
2773 TREE_CHAIN (*q) = NULL_TREE;
2774 q = &TREE_CHAIN (*q);
2775 }
2776 else
910ad8de 2777 p = &DECL_CHAIN (*p);
a68ab351 2778 *p = vla_fields;
d9a6bd32
JJ
2779 if (gimple_omp_task_taskloop_p (ctx->stmt))
2780 {
2781 /* Move fields corresponding to first and second _looptemp_
2782 clause first. There are filled by GOMP_taskloop
2783 and thus need to be in specific positions. */
2784 tree c1 = gimple_omp_task_clauses (ctx->stmt);
2785 c1 = find_omp_clause (c1, OMP_CLAUSE__LOOPTEMP_);
2786 tree c2 = find_omp_clause (OMP_CLAUSE_CHAIN (c1),
2787 OMP_CLAUSE__LOOPTEMP_);
2788 tree f1 = lookup_field (OMP_CLAUSE_DECL (c1), ctx);
2789 tree f2 = lookup_field (OMP_CLAUSE_DECL (c2), ctx);
2790 p = &TYPE_FIELDS (ctx->record_type);
2791 while (*p)
2792 if (*p == f1 || *p == f2)
2793 *p = DECL_CHAIN (*p);
2794 else
2795 p = &DECL_CHAIN (*p);
2796 DECL_CHAIN (f1) = f2;
2797 DECL_CHAIN (f2) = TYPE_FIELDS (ctx->record_type);
2798 TYPE_FIELDS (ctx->record_type) = f1;
2799 if (ctx->srecord_type)
2800 {
2801 f1 = lookup_sfield (OMP_CLAUSE_DECL (c1), ctx);
2802 f2 = lookup_sfield (OMP_CLAUSE_DECL (c2), ctx);
2803 p = &TYPE_FIELDS (ctx->srecord_type);
2804 while (*p)
2805 if (*p == f1 || *p == f2)
2806 *p = DECL_CHAIN (*p);
2807 else
2808 p = &DECL_CHAIN (*p);
2809 DECL_CHAIN (f1) = f2;
2810 DECL_CHAIN (f2) = TYPE_FIELDS (ctx->srecord_type);
2811 TYPE_FIELDS (ctx->srecord_type) = f1;
2812 }
2813 }
a68ab351
JJ
2814 layout_type (ctx->record_type);
2815 fixup_child_record_type (ctx);
2816 if (ctx->srecord_type)
2817 layout_type (ctx->srecord_type);
5771c391
JJ
2818 tree t = fold_convert_loc (loc, long_integer_type_node,
2819 TYPE_SIZE_UNIT (ctx->record_type));
2820 gimple_omp_task_set_arg_size (ctx->stmt, t);
726a989a 2821 t = build_int_cst (long_integer_type_node,
a68ab351 2822 TYPE_ALIGN_UNIT (ctx->record_type));
5771c391 2823 gimple_omp_task_set_arg_align (ctx->stmt, t);
a68ab351
JJ
2824 }
2825}
2826
e4834818 2827/* Find the enclosing offload context. */
953ff289 2828
41dbbb37
TS
2829static omp_context *
2830enclosing_target_ctx (omp_context *ctx)
2831{
e4834818
NS
2832 for (; ctx; ctx = ctx->outer)
2833 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET)
2834 break;
2835
41dbbb37
TS
2836 return ctx;
2837}
2838
e4834818
NS
2839/* Return true if ctx is part of an oacc kernels region. */
2840
41dbbb37 2841static bool
e4834818 2842ctx_in_oacc_kernels_region (omp_context *ctx)
41dbbb37 2843{
e4834818
NS
2844 for (;ctx != NULL; ctx = ctx->outer)
2845 {
2846 gimple *stmt = ctx->stmt;
2847 if (gimple_code (stmt) == GIMPLE_OMP_TARGET
2848 && gimple_omp_target_kind (stmt) == GF_OMP_TARGET_KIND_OACC_KERNELS)
2849 return true;
2850 }
2851
2852 return false;
2853}
2854
2855/* Check the parallelism clauses inside a kernels regions.
2856 Until kernels handling moves to use the same loop indirection
2857 scheme as parallel, we need to do this checking early. */
2858
2859static unsigned
2860check_oacc_kernel_gwv (gomp_for *stmt, omp_context *ctx)
2861{
2862 bool checking = true;
2863 unsigned outer_mask = 0;
2864 unsigned this_mask = 0;
2865 bool has_seq = false, has_auto = false;
2866
2867 if (ctx->outer)
2868 outer_mask = check_oacc_kernel_gwv (NULL, ctx->outer);
2869 if (!stmt)
2870 {
2871 checking = false;
2872 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR)
2873 return outer_mask;
2874 stmt = as_a <gomp_for *> (ctx->stmt);
2875 }
2876
2877 for (tree c = gimple_omp_for_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
2878 {
2879 switch (OMP_CLAUSE_CODE (c))
2880 {
2881 case OMP_CLAUSE_GANG:
2882 this_mask |= GOMP_DIM_MASK (GOMP_DIM_GANG);
2883 break;
2884 case OMP_CLAUSE_WORKER:
2885 this_mask |= GOMP_DIM_MASK (GOMP_DIM_WORKER);
2886 break;
2887 case OMP_CLAUSE_VECTOR:
2888 this_mask |= GOMP_DIM_MASK (GOMP_DIM_VECTOR);
2889 break;
2890 case OMP_CLAUSE_SEQ:
2891 has_seq = true;
2892 break;
2893 case OMP_CLAUSE_AUTO:
2894 has_auto = true;
2895 break;
2896 default:
2897 break;
2898 }
2899 }
2900
2901 if (checking)
2902 {
2903 if (has_seq && (this_mask || has_auto))
2904 error_at (gimple_location (stmt), "%<seq%> overrides other"
2905 " OpenACC loop specifiers");
2906 else if (has_auto && this_mask)
2907 error_at (gimple_location (stmt), "%<auto%> conflicts with other"
2908 " OpenACC loop specifiers");
2909
2910 if (this_mask & outer_mask)
2911 error_at (gimple_location (stmt), "inner loop uses same"
2912 " OpenACC parallelism as containing loop");
2913 }
2914
2915 return outer_mask | this_mask;
41dbbb37
TS
2916}
2917
2918/* Scan a GIMPLE_OMP_FOR. */
953ff289
DN
2919
2920static void
538dd0b7 2921scan_omp_for (gomp_for *stmt, omp_context *outer_ctx)
953ff289 2922{
50674e96 2923 omp_context *ctx;
726a989a 2924 size_t i;
41dbbb37
TS
2925 tree clauses = gimple_omp_for_clauses (stmt);
2926
50674e96 2927 ctx = new_omp_context (stmt, outer_ctx);
953ff289 2928
41dbbb37
TS
2929 if (is_gimple_omp_oacc (stmt))
2930 {
e4834818
NS
2931 omp_context *tgt = enclosing_target_ctx (outer_ctx);
2932
2933 if (!tgt || is_oacc_parallel (tgt))
2934 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2935 {
2936 char const *check = NULL;
2937
2938 switch (OMP_CLAUSE_CODE (c))
2939 {
2940 case OMP_CLAUSE_GANG:
2941 check = "gang";
2942 break;
2943
2944 case OMP_CLAUSE_WORKER:
2945 check = "worker";
2946 break;
2947
2948 case OMP_CLAUSE_VECTOR:
2949 check = "vector";
2950 break;
2951
2952 default:
2953 break;
2954 }
2955
2956 if (check && OMP_CLAUSE_OPERAND (c, 0))
2957 error_at (gimple_location (stmt),
2958 "argument not permitted on %qs clause in"
2959 " OpenACC %<parallel%>", check);
2960 }
2961
2962 if (tgt && is_oacc_kernels (tgt))
2963 {
2964 /* Strip out reductions, as they are not handled yet. */
2965 tree *prev_ptr = &clauses;
2966
2967 while (tree probe = *prev_ptr)
41dbbb37 2968 {
e4834818
NS
2969 tree *next_ptr = &OMP_CLAUSE_CHAIN (probe);
2970
2971 if (OMP_CLAUSE_CODE (probe) == OMP_CLAUSE_REDUCTION)
2972 *prev_ptr = *next_ptr;
2973 else
2974 prev_ptr = next_ptr;
41dbbb37 2975 }
e4834818
NS
2976
2977 gimple_omp_for_set_clauses (stmt, clauses);
2978 check_oacc_kernel_gwv (stmt, ctx);
41dbbb37
TS
2979 }
2980 }
2981
2982 scan_sharing_clauses (clauses, ctx);
953ff289 2983
26127932 2984 scan_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
726a989a 2985 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
a68ab351 2986 {
726a989a
RB
2987 scan_omp_op (gimple_omp_for_index_ptr (stmt, i), ctx);
2988 scan_omp_op (gimple_omp_for_initial_ptr (stmt, i), ctx);
2989 scan_omp_op (gimple_omp_for_final_ptr (stmt, i), ctx);
2990 scan_omp_op (gimple_omp_for_incr_ptr (stmt, i), ctx);
a68ab351 2991 }
26127932 2992 scan_omp (gimple_omp_body_ptr (stmt), ctx);
953ff289
DN
2993}
2994
2995/* Scan an OpenMP sections directive. */
2996
2997static void
538dd0b7 2998scan_omp_sections (gomp_sections *stmt, omp_context *outer_ctx)
953ff289 2999{
953ff289
DN
3000 omp_context *ctx;
3001
3002 ctx = new_omp_context (stmt, outer_ctx);
726a989a 3003 scan_sharing_clauses (gimple_omp_sections_clauses (stmt), ctx);
26127932 3004 scan_omp (gimple_omp_body_ptr (stmt), ctx);
953ff289
DN
3005}
3006
3007/* Scan an OpenMP single directive. */
3008
3009static void
538dd0b7 3010scan_omp_single (gomp_single *stmt, omp_context *outer_ctx)
953ff289 3011{
953ff289
DN
3012 omp_context *ctx;
3013 tree name;
3014
3015 ctx = new_omp_context (stmt, outer_ctx);
3016 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
3017 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
3018 name = create_tmp_var_name (".omp_copy_s");
c2255bc4
AH
3019 name = build_decl (gimple_location (stmt),
3020 TYPE_DECL, name, ctx->record_type);
953ff289
DN
3021 TYPE_NAME (ctx->record_type) = name;
3022
726a989a 3023 scan_sharing_clauses (gimple_omp_single_clauses (stmt), ctx);
26127932 3024 scan_omp (gimple_omp_body_ptr (stmt), ctx);
953ff289
DN
3025
3026 if (TYPE_FIELDS (ctx->record_type) == NULL)
3027 ctx->record_type = NULL;
3028 else
3029 layout_type (ctx->record_type);
3030}
3031
41dbbb37 3032/* Scan a GIMPLE_OMP_TARGET. */
acf0174b
JJ
3033
3034static void
538dd0b7 3035scan_omp_target (gomp_target *stmt, omp_context *outer_ctx)
acf0174b
JJ
3036{
3037 omp_context *ctx;
3038 tree name;
41dbbb37
TS
3039 bool offloaded = is_gimple_omp_offloaded (stmt);
3040 tree clauses = gimple_omp_target_clauses (stmt);
acf0174b
JJ
3041
3042 ctx = new_omp_context (stmt, outer_ctx);
3043 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
3044 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
3045 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
3046 name = create_tmp_var_name (".omp_data_t");
3047 name = build_decl (gimple_location (stmt),
3048 TYPE_DECL, name, ctx->record_type);
3049 DECL_ARTIFICIAL (name) = 1;
3050 DECL_NAMELESS (name) = 1;
3051 TYPE_NAME (ctx->record_type) = name;
f7484978 3052 TYPE_ARTIFICIAL (ctx->record_type) = 1;
41dbbb37 3053 if (offloaded)
acf0174b
JJ
3054 {
3055 create_omp_child_function (ctx, false);
3056 gimple_omp_target_set_child_fn (stmt, ctx->cb.dst_fn);
3057 }
3058
41dbbb37 3059 scan_sharing_clauses (clauses, ctx);
acf0174b
JJ
3060 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3061
3062 if (TYPE_FIELDS (ctx->record_type) == NULL)
3063 ctx->record_type = ctx->receiver_decl = NULL;
3064 else
3065 {
3066 TYPE_FIELDS (ctx->record_type)
3067 = nreverse (TYPE_FIELDS (ctx->record_type));
b2b29377
MM
3068 if (flag_checking)
3069 {
3070 unsigned int align = DECL_ALIGN (TYPE_FIELDS (ctx->record_type));
3071 for (tree field = TYPE_FIELDS (ctx->record_type);
3072 field;
3073 field = DECL_CHAIN (field))
3074 gcc_assert (DECL_ALIGN (field) == align);
3075 }
acf0174b 3076 layout_type (ctx->record_type);
41dbbb37 3077 if (offloaded)
acf0174b
JJ
3078 fixup_child_record_type (ctx);
3079 }
3080}
3081
3082/* Scan an OpenMP teams directive. */
3083
3084static void
538dd0b7 3085scan_omp_teams (gomp_teams *stmt, omp_context *outer_ctx)
acf0174b
JJ
3086{
3087 omp_context *ctx = new_omp_context (stmt, outer_ctx);
3088 scan_sharing_clauses (gimple_omp_teams_clauses (stmt), ctx);
3089 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3090}
953ff289 3091
41dbbb37 3092/* Check nesting restrictions. */
26127932 3093static bool
355fe088 3094check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx)
a6fc8e21 3095{
d9a6bd32
JJ
3096 tree c;
3097
41dbbb37
TS
3098 /* No nesting of non-OpenACC STMT (that is, an OpenMP one, or a GOMP builtin)
3099 inside an OpenACC CTX. */
3100 if (!(is_gimple_omp (stmt)
3101 && is_gimple_omp_oacc (stmt)))
3102 {
d9f4ea18
JJ
3103 for (omp_context *octx = ctx; octx != NULL; octx = octx->outer)
3104 if (is_gimple_omp (octx->stmt)
3105 && is_gimple_omp_oacc (octx->stmt)
4bf9e5a8
TS
3106 /* Except for atomic codes that we share with OpenMP. */
3107 && ! (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD
3108 || gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE))
41dbbb37
TS
3109 {
3110 error_at (gimple_location (stmt),
3111 "non-OpenACC construct inside of OpenACC region");
3112 return false;
3113 }
3114 }
3115
74bf76ed
JJ
3116 if (ctx != NULL)
3117 {
3118 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
0aadce73 3119 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
74bf76ed 3120 {
d9a6bd32
JJ
3121 c = NULL_TREE;
3122 if (gimple_code (stmt) == GIMPLE_OMP_ORDERED)
3123 {
3124 c = gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt));
d9f4ea18
JJ
3125 if (find_omp_clause (c, OMP_CLAUSE_SIMD))
3126 {
3127 if (find_omp_clause (c, OMP_CLAUSE_THREADS)
3128 && (ctx->outer == NULL
3129 || !gimple_omp_for_combined_into_p (ctx->stmt)
3130 || gimple_code (ctx->outer->stmt) != GIMPLE_OMP_FOR
3131 || (gimple_omp_for_kind (ctx->outer->stmt)
3132 != GF_OMP_FOR_KIND_FOR)
3133 || !gimple_omp_for_combined_p (ctx->outer->stmt)))
3134 {
3135 error_at (gimple_location (stmt),
3136 "%<ordered simd threads%> must be closely "
3137 "nested inside of %<for simd%> region");
3138 return false;
3139 }
3140 return true;
3141 }
d9a6bd32 3142 }
74bf76ed 3143 error_at (gimple_location (stmt),
d9a6bd32 3144 "OpenMP constructs other than %<#pragma omp ordered simd%>"
d9f4ea18 3145 " may not be nested inside %<simd%> region");
74bf76ed
JJ
3146 return false;
3147 }
acf0174b
JJ
3148 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3149 {
3150 if ((gimple_code (stmt) != GIMPLE_OMP_FOR
3151 || (gimple_omp_for_kind (stmt)
3152 != GF_OMP_FOR_KIND_DISTRIBUTE))
3153 && gimple_code (stmt) != GIMPLE_OMP_PARALLEL)
3154 {
3155 error_at (gimple_location (stmt),
d9f4ea18
JJ
3156 "only %<distribute%> or %<parallel%> regions are "
3157 "allowed to be strictly nested inside %<teams%> "
3158 "region");
acf0174b
JJ
3159 return false;
3160 }
3161 }
74bf76ed 3162 }
726a989a 3163 switch (gimple_code (stmt))
a6fc8e21 3164 {
726a989a 3165 case GIMPLE_OMP_FOR:
0aadce73 3166 if (gimple_omp_for_kind (stmt) & GF_OMP_FOR_SIMD)
74bf76ed 3167 return true;
acf0174b
JJ
3168 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
3169 {
3170 if (ctx != NULL && gimple_code (ctx->stmt) != GIMPLE_OMP_TEAMS)
3171 {
3172 error_at (gimple_location (stmt),
d9f4ea18
JJ
3173 "%<distribute%> region must be strictly nested "
3174 "inside %<teams%> construct");
acf0174b
JJ
3175 return false;
3176 }
3177 return true;
3178 }
d9a6bd32
JJ
3179 /* We split taskloop into task and nested taskloop in it. */
3180 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_TASKLOOP)
3181 return true;
68d58afb
NS
3182 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
3183 {
3184 bool ok = false;
3185
3186 if (ctx)
3187 switch (gimple_code (ctx->stmt))
3188 {
3189 case GIMPLE_OMP_FOR:
3190 ok = (gimple_omp_for_kind (ctx->stmt)
3191 == GF_OMP_FOR_KIND_OACC_LOOP);
3192 break;
3193
3194 case GIMPLE_OMP_TARGET:
3195 switch (gimple_omp_target_kind (ctx->stmt))
3196 {
3197 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
3198 case GF_OMP_TARGET_KIND_OACC_KERNELS:
3199 ok = true;
3200 break;
3201
3202 default:
3203 break;
3204 }
3205
3206 default:
3207 break;
3208 }
3209 else if (get_oacc_fn_attrib (current_function_decl))
3210 ok = true;
3211 if (!ok)
3212 {
3213 error_at (gimple_location (stmt),
3214 "OpenACC loop directive must be associated with"
3215 " an OpenACC compute region");
3216 return false;
3217 }
3218 }
acf0174b
JJ
3219 /* FALLTHRU */
3220 case GIMPLE_CALL:
3221 if (is_gimple_call (stmt)
3222 && (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3223 == BUILT_IN_GOMP_CANCEL
3224 || DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3225 == BUILT_IN_GOMP_CANCELLATION_POINT))
3226 {
3227 const char *bad = NULL;
3228 const char *kind = NULL;
d9f4ea18
JJ
3229 const char *construct
3230 = (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3231 == BUILT_IN_GOMP_CANCEL)
3232 ? "#pragma omp cancel"
3233 : "#pragma omp cancellation point";
acf0174b
JJ
3234 if (ctx == NULL)
3235 {
3236 error_at (gimple_location (stmt), "orphaned %qs construct",
d9f4ea18 3237 construct);
acf0174b
JJ
3238 return false;
3239 }
9541ffee 3240 switch (tree_fits_shwi_p (gimple_call_arg (stmt, 0))
9439e9a1 3241 ? tree_to_shwi (gimple_call_arg (stmt, 0))
acf0174b
JJ
3242 : 0)
3243 {
3244 case 1:
3245 if (gimple_code (ctx->stmt) != GIMPLE_OMP_PARALLEL)
3246 bad = "#pragma omp parallel";
3247 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3248 == BUILT_IN_GOMP_CANCEL
3249 && !integer_zerop (gimple_call_arg (stmt, 1)))
3250 ctx->cancellable = true;
3251 kind = "parallel";
3252 break;
3253 case 2:
3254 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
3255 || gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR)
3256 bad = "#pragma omp for";
3257 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3258 == BUILT_IN_GOMP_CANCEL
3259 && !integer_zerop (gimple_call_arg (stmt, 1)))
3260 {
3261 ctx->cancellable = true;
3262 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3263 OMP_CLAUSE_NOWAIT))
3264 warning_at (gimple_location (stmt), 0,
3265 "%<#pragma omp cancel for%> inside "
3266 "%<nowait%> for construct");
3267 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3268 OMP_CLAUSE_ORDERED))
3269 warning_at (gimple_location (stmt), 0,
3270 "%<#pragma omp cancel for%> inside "
3271 "%<ordered%> for construct");
3272 }
3273 kind = "for";
3274 break;
3275 case 4:
3276 if (gimple_code (ctx->stmt) != GIMPLE_OMP_SECTIONS
3277 && gimple_code (ctx->stmt) != GIMPLE_OMP_SECTION)
3278 bad = "#pragma omp sections";
3279 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3280 == BUILT_IN_GOMP_CANCEL
3281 && !integer_zerop (gimple_call_arg (stmt, 1)))
3282 {
3283 if (gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS)
3284 {
3285 ctx->cancellable = true;
3286 if (find_omp_clause (gimple_omp_sections_clauses
3287 (ctx->stmt),
3288 OMP_CLAUSE_NOWAIT))
3289 warning_at (gimple_location (stmt), 0,
3290 "%<#pragma omp cancel sections%> inside "
3291 "%<nowait%> sections construct");
3292 }
3293 else
3294 {
3295 gcc_assert (ctx->outer
3296 && gimple_code (ctx->outer->stmt)
3297 == GIMPLE_OMP_SECTIONS);
3298 ctx->outer->cancellable = true;
3299 if (find_omp_clause (gimple_omp_sections_clauses
3300 (ctx->outer->stmt),
3301 OMP_CLAUSE_NOWAIT))
3302 warning_at (gimple_location (stmt), 0,
3303 "%<#pragma omp cancel sections%> inside "
3304 "%<nowait%> sections construct");
3305 }
3306 }
3307 kind = "sections";
3308 break;
3309 case 8:
3310 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TASK)
3311 bad = "#pragma omp task";
3312 else
d9f4ea18
JJ
3313 {
3314 for (omp_context *octx = ctx->outer;
3315 octx; octx = octx->outer)
3316 {
3317 switch (gimple_code (octx->stmt))
3318 {
3319 case GIMPLE_OMP_TASKGROUP:
3320 break;
3321 case GIMPLE_OMP_TARGET:
3322 if (gimple_omp_target_kind (octx->stmt)
3323 != GF_OMP_TARGET_KIND_REGION)
3324 continue;
3325 /* FALLTHRU */
3326 case GIMPLE_OMP_PARALLEL:
3327 case GIMPLE_OMP_TEAMS:
3328 error_at (gimple_location (stmt),
3329 "%<%s taskgroup%> construct not closely "
3330 "nested inside of %<taskgroup%> region",
3331 construct);
3332 return false;
3333 default:
3334 continue;
3335 }
3336 break;
3337 }
3338 ctx->cancellable = true;
3339 }
acf0174b
JJ
3340 kind = "taskgroup";
3341 break;
3342 default:
3343 error_at (gimple_location (stmt), "invalid arguments");
3344 return false;
3345 }
3346 if (bad)
3347 {
3348 error_at (gimple_location (stmt),
3349 "%<%s %s%> construct not closely nested inside of %qs",
d9f4ea18 3350 construct, kind, bad);
acf0174b
JJ
3351 return false;
3352 }
3353 }
74bf76ed 3354 /* FALLTHRU */
726a989a
RB
3355 case GIMPLE_OMP_SECTIONS:
3356 case GIMPLE_OMP_SINGLE:
a6fc8e21 3357 for (; ctx != NULL; ctx = ctx->outer)
726a989a 3358 switch (gimple_code (ctx->stmt))
a6fc8e21 3359 {
726a989a 3360 case GIMPLE_OMP_FOR:
d9f4ea18
JJ
3361 if (gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR
3362 && gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_TASKLOOP)
3363 break;
3364 /* FALLTHRU */
726a989a
RB
3365 case GIMPLE_OMP_SECTIONS:
3366 case GIMPLE_OMP_SINGLE:
3367 case GIMPLE_OMP_ORDERED:
3368 case GIMPLE_OMP_MASTER:
3369 case GIMPLE_OMP_TASK:
acf0174b 3370 case GIMPLE_OMP_CRITICAL:
726a989a 3371 if (is_gimple_call (stmt))
a68ab351 3372 {
acf0174b
JJ
3373 if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3374 != BUILT_IN_GOMP_BARRIER)
3375 return true;
26127932
JJ
3376 error_at (gimple_location (stmt),
3377 "barrier region may not be closely nested inside "
d9f4ea18
JJ
3378 "of work-sharing, %<critical%>, %<ordered%>, "
3379 "%<master%>, explicit %<task%> or %<taskloop%> "
3380 "region");
26127932 3381 return false;
a68ab351 3382 }
26127932
JJ
3383 error_at (gimple_location (stmt),
3384 "work-sharing region may not be closely nested inside "
d9f4ea18
JJ
3385 "of work-sharing, %<critical%>, %<ordered%>, "
3386 "%<master%>, explicit %<task%> or %<taskloop%> region");
26127932 3387 return false;
726a989a 3388 case GIMPLE_OMP_PARALLEL:
d9f4ea18 3389 case GIMPLE_OMP_TEAMS:
26127932 3390 return true;
d9f4ea18
JJ
3391 case GIMPLE_OMP_TARGET:
3392 if (gimple_omp_target_kind (ctx->stmt)
3393 == GF_OMP_TARGET_KIND_REGION)
3394 return true;
3395 break;
a6fc8e21
JJ
3396 default:
3397 break;
3398 }
3399 break;
726a989a 3400 case GIMPLE_OMP_MASTER:
a6fc8e21 3401 for (; ctx != NULL; ctx = ctx->outer)
726a989a 3402 switch (gimple_code (ctx->stmt))
a6fc8e21 3403 {
726a989a 3404 case GIMPLE_OMP_FOR:
d9f4ea18
JJ
3405 if (gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR
3406 && gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_TASKLOOP)
3407 break;
3408 /* FALLTHRU */
726a989a
RB
3409 case GIMPLE_OMP_SECTIONS:
3410 case GIMPLE_OMP_SINGLE:
3411 case GIMPLE_OMP_TASK:
26127932 3412 error_at (gimple_location (stmt),
d9f4ea18
JJ
3413 "%<master%> region may not be closely nested inside "
3414 "of work-sharing, explicit %<task%> or %<taskloop%> "
3415 "region");
26127932 3416 return false;
726a989a 3417 case GIMPLE_OMP_PARALLEL:
d9f4ea18 3418 case GIMPLE_OMP_TEAMS:
26127932 3419 return true;
d9f4ea18
JJ
3420 case GIMPLE_OMP_TARGET:
3421 if (gimple_omp_target_kind (ctx->stmt)
3422 == GF_OMP_TARGET_KIND_REGION)
3423 return true;
3424 break;
a6fc8e21
JJ
3425 default:
3426 break;
3427 }
3428 break;
d9a6bd32
JJ
3429 case GIMPLE_OMP_TASK:
3430 for (c = gimple_omp_task_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
3431 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
3432 && (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE
3433 || OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK))
3434 {
3435 enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c);
3436 error_at (OMP_CLAUSE_LOCATION (c),
3437 "%<depend(%s)%> is only allowed in %<omp ordered%>",
3438 kind == OMP_CLAUSE_DEPEND_SOURCE ? "source" : "sink");
3439 return false;
3440 }
3441 break;
726a989a 3442 case GIMPLE_OMP_ORDERED:
d9a6bd32
JJ
3443 for (c = gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt));
3444 c; c = OMP_CLAUSE_CHAIN (c))
3445 {
3446 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND)
3447 {
3448 gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_THREADS
d9f4ea18 3449 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SIMD);
d9a6bd32
JJ
3450 continue;
3451 }
3452 enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c);
3453 if (kind == OMP_CLAUSE_DEPEND_SOURCE
3454 || kind == OMP_CLAUSE_DEPEND_SINK)
3455 {
3456 tree oclause;
3457 /* Look for containing ordered(N) loop. */
3458 if (ctx == NULL
3459 || gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
3460 || (oclause
3461 = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3462 OMP_CLAUSE_ORDERED)) == NULL_TREE)
3463 {
3464 error_at (OMP_CLAUSE_LOCATION (c),
d9f4ea18
JJ
3465 "%<ordered%> construct with %<depend%> clause "
3466 "must be closely nested inside an %<ordered%> "
3467 "loop");
d9a6bd32
JJ
3468 return false;
3469 }
3470 else if (OMP_CLAUSE_ORDERED_EXPR (oclause) == NULL_TREE)
3471 {
3472 error_at (OMP_CLAUSE_LOCATION (c),
d9f4ea18
JJ
3473 "%<ordered%> construct with %<depend%> clause "
3474 "must be closely nested inside a loop with "
3475 "%<ordered%> clause with a parameter");
d9a6bd32
JJ
3476 return false;
3477 }
3478 }
3479 else
3480 {
3481 error_at (OMP_CLAUSE_LOCATION (c),
d9f4ea18
JJ
3482 "invalid depend kind in omp %<ordered%> %<depend%>");
3483 return false;
3484 }
3485 }
3486 c = gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt));
3487 if (find_omp_clause (c, OMP_CLAUSE_SIMD))
3488 {
3489 /* ordered simd must be closely nested inside of simd region,
3490 and simd region must not encounter constructs other than
3491 ordered simd, therefore ordered simd may be either orphaned,
3492 or ctx->stmt must be simd. The latter case is handled already
3493 earlier. */
3494 if (ctx != NULL)
3495 {
3496 error_at (gimple_location (stmt),
3497 "%<ordered%> %<simd%> must be closely nested inside "
3498 "%<simd%> region");
d9a6bd32
JJ
3499 return false;
3500 }
3501 }
a6fc8e21 3502 for (; ctx != NULL; ctx = ctx->outer)
726a989a 3503 switch (gimple_code (ctx->stmt))
a6fc8e21 3504 {
726a989a
RB
3505 case GIMPLE_OMP_CRITICAL:
3506 case GIMPLE_OMP_TASK:
d9f4ea18
JJ
3507 case GIMPLE_OMP_ORDERED:
3508 ordered_in_taskloop:
26127932 3509 error_at (gimple_location (stmt),
d9f4ea18
JJ
3510 "%<ordered%> region may not be closely nested inside "
3511 "of %<critical%>, %<ordered%>, explicit %<task%> or "
3512 "%<taskloop%> region");
26127932 3513 return false;
726a989a 3514 case GIMPLE_OMP_FOR:
d9f4ea18
JJ
3515 if (gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_TASKLOOP)
3516 goto ordered_in_taskloop;
726a989a 3517 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
a6fc8e21 3518 OMP_CLAUSE_ORDERED) == NULL)
26127932
JJ
3519 {
3520 error_at (gimple_location (stmt),
d9f4ea18
JJ
3521 "%<ordered%> region must be closely nested inside "
3522 "a loop region with an %<ordered%> clause");
26127932
JJ
3523 return false;
3524 }
3525 return true;
d9f4ea18
JJ
3526 case GIMPLE_OMP_TARGET:
3527 if (gimple_omp_target_kind (ctx->stmt)
3528 != GF_OMP_TARGET_KIND_REGION)
3529 break;
3530 /* FALLTHRU */
726a989a 3531 case GIMPLE_OMP_PARALLEL:
d9f4ea18 3532 case GIMPLE_OMP_TEAMS:
acf0174b 3533 error_at (gimple_location (stmt),
d9f4ea18
JJ
3534 "%<ordered%> region must be closely nested inside "
3535 "a loop region with an %<ordered%> clause");
acf0174b 3536 return false;
a6fc8e21
JJ
3537 default:
3538 break;
3539 }
3540 break;
726a989a 3541 case GIMPLE_OMP_CRITICAL:
538dd0b7
DM
3542 {
3543 tree this_stmt_name
3544 = gimple_omp_critical_name (as_a <gomp_critical *> (stmt));
3545 for (; ctx != NULL; ctx = ctx->outer)
3546 if (gomp_critical *other_crit
3547 = dyn_cast <gomp_critical *> (ctx->stmt))
3548 if (this_stmt_name == gimple_omp_critical_name (other_crit))
3549 {
3550 error_at (gimple_location (stmt),
d9f4ea18
JJ
3551 "%<critical%> region may not be nested inside "
3552 "a %<critical%> region with the same name");
538dd0b7
DM
3553 return false;
3554 }
3555 }
a6fc8e21 3556 break;
acf0174b
JJ
3557 case GIMPLE_OMP_TEAMS:
3558 if (ctx == NULL
3559 || gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET
3560 || gimple_omp_target_kind (ctx->stmt) != GF_OMP_TARGET_KIND_REGION)
3561 {
3562 error_at (gimple_location (stmt),
d9f4ea18
JJ
3563 "%<teams%> construct not closely nested inside of "
3564 "%<target%> construct");
acf0174b
JJ
3565 return false;
3566 }
3567 break;
f014c653 3568 case GIMPLE_OMP_TARGET:
d9a6bd32
JJ
3569 for (c = gimple_omp_target_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
3570 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
3571 && (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE
3572 || OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK))
3573 {
3574 enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c);
3575 error_at (OMP_CLAUSE_LOCATION (c),
3576 "%<depend(%s)%> is only allowed in %<omp ordered%>",
3577 kind == OMP_CLAUSE_DEPEND_SOURCE ? "source" : "sink");
3578 return false;
3579 }
f014c653 3580 for (; ctx != NULL; ctx = ctx->outer)
41dbbb37
TS
3581 {
3582 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET)
3583 {
3584 if (is_gimple_omp (stmt)
3585 && is_gimple_omp_oacc (stmt)
3586 && is_gimple_omp (ctx->stmt))
3587 {
3588 error_at (gimple_location (stmt),
3589 "OpenACC construct inside of non-OpenACC region");
3590 return false;
3591 }
3592 continue;
3593 }
3594
3595 const char *stmt_name, *ctx_stmt_name;
3596 switch (gimple_omp_target_kind (stmt))
3597 {
3598 case GF_OMP_TARGET_KIND_REGION: stmt_name = "target"; break;
3599 case GF_OMP_TARGET_KIND_DATA: stmt_name = "target data"; break;
3600 case GF_OMP_TARGET_KIND_UPDATE: stmt_name = "target update"; break;
d9a6bd32
JJ
3601 case GF_OMP_TARGET_KIND_ENTER_DATA:
3602 stmt_name = "target enter data"; break;
3603 case GF_OMP_TARGET_KIND_EXIT_DATA:
3604 stmt_name = "target exit data"; break;
41dbbb37
TS
3605 case GF_OMP_TARGET_KIND_OACC_PARALLEL: stmt_name = "parallel"; break;
3606 case GF_OMP_TARGET_KIND_OACC_KERNELS: stmt_name = "kernels"; break;
3607 case GF_OMP_TARGET_KIND_OACC_DATA: stmt_name = "data"; break;
3608 case GF_OMP_TARGET_KIND_OACC_UPDATE: stmt_name = "update"; break;
d9a6bd32
JJ
3609 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
3610 stmt_name = "enter/exit data"; break;
41dbbb37
TS
3611 default: gcc_unreachable ();
3612 }
3613 switch (gimple_omp_target_kind (ctx->stmt))
3614 {
3615 case GF_OMP_TARGET_KIND_REGION: ctx_stmt_name = "target"; break;
3616 case GF_OMP_TARGET_KIND_DATA: ctx_stmt_name = "target data"; break;
d9a6bd32
JJ
3617 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
3618 ctx_stmt_name = "parallel"; break;
3619 case GF_OMP_TARGET_KIND_OACC_KERNELS:
3620 ctx_stmt_name = "kernels"; break;
41dbbb37
TS
3621 case GF_OMP_TARGET_KIND_OACC_DATA: ctx_stmt_name = "data"; break;
3622 default: gcc_unreachable ();
3623 }
3624
3625 /* OpenACC/OpenMP mismatch? */
3626 if (is_gimple_omp_oacc (stmt)
3627 != is_gimple_omp_oacc (ctx->stmt))
3628 {
3629 error_at (gimple_location (stmt),
d9f4ea18 3630 "%s %qs construct inside of %s %qs region",
41dbbb37
TS
3631 (is_gimple_omp_oacc (stmt)
3632 ? "OpenACC" : "OpenMP"), stmt_name,
3633 (is_gimple_omp_oacc (ctx->stmt)
3634 ? "OpenACC" : "OpenMP"), ctx_stmt_name);
3635 return false;
3636 }
3637 if (is_gimple_omp_offloaded (ctx->stmt))
3638 {
3639 /* No GIMPLE_OMP_TARGET inside offloaded OpenACC CTX. */
3640 if (is_gimple_omp_oacc (ctx->stmt))
3641 {
3642 error_at (gimple_location (stmt),
d9f4ea18 3643 "%qs construct inside of %qs region",
41dbbb37
TS
3644 stmt_name, ctx_stmt_name);
3645 return false;
3646 }
3647 else
3648 {
41dbbb37 3649 warning_at (gimple_location (stmt), 0,
d9f4ea18 3650 "%qs construct inside of %qs region",
41dbbb37
TS
3651 stmt_name, ctx_stmt_name);
3652 }
3653 }
3654 }
f014c653 3655 break;
a6fc8e21
JJ
3656 default:
3657 break;
3658 }
26127932 3659 return true;
a6fc8e21
JJ
3660}
3661
3662
726a989a
RB
3663/* Helper function scan_omp.
3664
3665 Callback for walk_tree or operators in walk_gimple_stmt used to
41dbbb37 3666 scan for OMP directives in TP. */
953ff289
DN
3667
3668static tree
726a989a 3669scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
953ff289 3670{
d3bfe4de
KG
3671 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
3672 omp_context *ctx = (omp_context *) wi->info;
953ff289
DN
3673 tree t = *tp;
3674
726a989a
RB
3675 switch (TREE_CODE (t))
3676 {
3677 case VAR_DECL:
3678 case PARM_DECL:
3679 case LABEL_DECL:
3680 case RESULT_DECL:
3681 if (ctx)
3682 *tp = remap_decl (t, &ctx->cb);
3683 break;
3684
3685 default:
3686 if (ctx && TYPE_P (t))
3687 *tp = remap_type (t, &ctx->cb);
3688 else if (!DECL_P (t))
a900ae6b
JJ
3689 {
3690 *walk_subtrees = 1;
3691 if (ctx)
70f34814
RG
3692 {
3693 tree tem = remap_type (TREE_TYPE (t), &ctx->cb);
3694 if (tem != TREE_TYPE (t))
3695 {
3696 if (TREE_CODE (t) == INTEGER_CST)
807e902e 3697 *tp = wide_int_to_tree (tem, t);
70f34814
RG
3698 else
3699 TREE_TYPE (t) = tem;
3700 }
3701 }
a900ae6b 3702 }
726a989a
RB
3703 break;
3704 }
3705
3706 return NULL_TREE;
3707}
3708
c02065fc
AH
3709/* Return true if FNDECL is a setjmp or a longjmp. */
3710
3711static bool
3712setjmp_or_longjmp_p (const_tree fndecl)
3713{
3714 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
3715 && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_SETJMP
3716 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LONGJMP))
3717 return true;
3718
3719 tree declname = DECL_NAME (fndecl);
3720 if (!declname)
3721 return false;
3722 const char *name = IDENTIFIER_POINTER (declname);
3723 return !strcmp (name, "setjmp") || !strcmp (name, "longjmp");
3724}
3725
726a989a
RB
3726
3727/* Helper function for scan_omp.
3728
41dbbb37 3729 Callback for walk_gimple_stmt used to scan for OMP directives in
726a989a
RB
3730 the current statement in GSI. */
3731
3732static tree
3733scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
3734 struct walk_stmt_info *wi)
3735{
355fe088 3736 gimple *stmt = gsi_stmt (*gsi);
726a989a
RB
3737 omp_context *ctx = (omp_context *) wi->info;
3738
3739 if (gimple_has_location (stmt))
3740 input_location = gimple_location (stmt);
953ff289 3741
41dbbb37 3742 /* Check the nesting restrictions. */
acf0174b
JJ
3743 bool remove = false;
3744 if (is_gimple_omp (stmt))
3745 remove = !check_omp_nesting_restrictions (stmt, ctx);
3746 else if (is_gimple_call (stmt))
3747 {
3748 tree fndecl = gimple_call_fndecl (stmt);
c02065fc
AH
3749 if (fndecl)
3750 {
3751 if (setjmp_or_longjmp_p (fndecl)
3752 && ctx
3753 && gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
0aadce73 3754 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
c02065fc
AH
3755 {
3756 remove = true;
3757 error_at (gimple_location (stmt),
3758 "setjmp/longjmp inside simd construct");
3759 }
3760 else if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
3761 switch (DECL_FUNCTION_CODE (fndecl))
3762 {
3763 case BUILT_IN_GOMP_BARRIER:
3764 case BUILT_IN_GOMP_CANCEL:
3765 case BUILT_IN_GOMP_CANCELLATION_POINT:
3766 case BUILT_IN_GOMP_TASKYIELD:
3767 case BUILT_IN_GOMP_TASKWAIT:
3768 case BUILT_IN_GOMP_TASKGROUP_START:
3769 case BUILT_IN_GOMP_TASKGROUP_END:
3770 remove = !check_omp_nesting_restrictions (stmt, ctx);
3771 break;
3772 default:
3773 break;
3774 }
3775 }
acf0174b
JJ
3776 }
3777 if (remove)
3778 {
3779 stmt = gimple_build_nop ();
3780 gsi_replace (gsi, stmt, false);
a68ab351 3781 }
a6fc8e21 3782
726a989a
RB
3783 *handled_ops_p = true;
3784
3785 switch (gimple_code (stmt))
953ff289 3786 {
726a989a 3787 case GIMPLE_OMP_PARALLEL:
a68ab351 3788 taskreg_nesting_level++;
726a989a 3789 scan_omp_parallel (gsi, ctx);
a68ab351
JJ
3790 taskreg_nesting_level--;
3791 break;
3792
726a989a 3793 case GIMPLE_OMP_TASK:
a68ab351 3794 taskreg_nesting_level++;
726a989a 3795 scan_omp_task (gsi, ctx);
a68ab351 3796 taskreg_nesting_level--;
953ff289
DN
3797 break;
3798
726a989a 3799 case GIMPLE_OMP_FOR:
538dd0b7 3800 scan_omp_for (as_a <gomp_for *> (stmt), ctx);
953ff289
DN
3801 break;
3802
726a989a 3803 case GIMPLE_OMP_SECTIONS:
538dd0b7 3804 scan_omp_sections (as_a <gomp_sections *> (stmt), ctx);
953ff289
DN
3805 break;
3806
726a989a 3807 case GIMPLE_OMP_SINGLE:
538dd0b7 3808 scan_omp_single (as_a <gomp_single *> (stmt), ctx);
953ff289
DN
3809 break;
3810
726a989a
RB
3811 case GIMPLE_OMP_SECTION:
3812 case GIMPLE_OMP_MASTER:
acf0174b 3813 case GIMPLE_OMP_TASKGROUP:
726a989a
RB
3814 case GIMPLE_OMP_ORDERED:
3815 case GIMPLE_OMP_CRITICAL:
3816 ctx = new_omp_context (stmt, ctx);
26127932 3817 scan_omp (gimple_omp_body_ptr (stmt), ctx);
953ff289
DN
3818 break;
3819
acf0174b 3820 case GIMPLE_OMP_TARGET:
538dd0b7 3821 scan_omp_target (as_a <gomp_target *> (stmt), ctx);
acf0174b
JJ
3822 break;
3823
3824 case GIMPLE_OMP_TEAMS:
538dd0b7 3825 scan_omp_teams (as_a <gomp_teams *> (stmt), ctx);
acf0174b
JJ
3826 break;
3827
726a989a 3828 case GIMPLE_BIND:
953ff289
DN
3829 {
3830 tree var;
953ff289 3831
726a989a
RB
3832 *handled_ops_p = false;
3833 if (ctx)
538dd0b7
DM
3834 for (var = gimple_bind_vars (as_a <gbind *> (stmt));
3835 var ;
3836 var = DECL_CHAIN (var))
726a989a 3837 insert_decl_map (&ctx->cb, var, var);
953ff289
DN
3838 }
3839 break;
953ff289 3840 default:
726a989a 3841 *handled_ops_p = false;
953ff289
DN
3842 break;
3843 }
3844
3845 return NULL_TREE;
3846}
3847
3848
726a989a 3849/* Scan all the statements starting at the current statement. CTX
41dbbb37 3850 contains context information about the OMP directives and
726a989a 3851 clauses found during the scan. */
953ff289
DN
3852
3853static void
26127932 3854scan_omp (gimple_seq *body_p, omp_context *ctx)
953ff289
DN
3855{
3856 location_t saved_location;
3857 struct walk_stmt_info wi;
3858
3859 memset (&wi, 0, sizeof (wi));
953ff289 3860 wi.info = ctx;
953ff289
DN
3861 wi.want_locations = true;
3862
3863 saved_location = input_location;
26127932 3864 walk_gimple_seq_mod (body_p, scan_omp_1_stmt, scan_omp_1_op, &wi);
953ff289
DN
3865 input_location = saved_location;
3866}
3867\f
3868/* Re-gimplification and code generation routines. */
3869
3870/* Build a call to GOMP_barrier. */
3871
355fe088 3872static gimple *
acf0174b
JJ
3873build_omp_barrier (tree lhs)
3874{
3875 tree fndecl = builtin_decl_explicit (lhs ? BUILT_IN_GOMP_BARRIER_CANCEL
3876 : BUILT_IN_GOMP_BARRIER);
538dd0b7 3877 gcall *g = gimple_build_call (fndecl, 0);
acf0174b
JJ
3878 if (lhs)
3879 gimple_call_set_lhs (g, lhs);
3880 return g;
953ff289
DN
3881}
3882
3883/* If a context was created for STMT when it was scanned, return it. */
3884
3885static omp_context *
355fe088 3886maybe_lookup_ctx (gimple *stmt)
953ff289
DN
3887{
3888 splay_tree_node n;
3889 n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
3890 return n ? (omp_context *) n->value : NULL;
3891}
3892
50674e96
DN
3893
3894/* Find the mapping for DECL in CTX or the immediately enclosing
3895 context that has a mapping for DECL.
3896
3897 If CTX is a nested parallel directive, we may have to use the decl
3898 mappings created in CTX's parent context. Suppose that we have the
3899 following parallel nesting (variable UIDs showed for clarity):
3900
3901 iD.1562 = 0;
3902 #omp parallel shared(iD.1562) -> outer parallel
3903 iD.1562 = iD.1562 + 1;
3904
3905 #omp parallel shared (iD.1562) -> inner parallel
3906 iD.1562 = iD.1562 - 1;
3907
3908 Each parallel structure will create a distinct .omp_data_s structure
3909 for copying iD.1562 in/out of the directive:
3910
3911 outer parallel .omp_data_s.1.i -> iD.1562
3912 inner parallel .omp_data_s.2.i -> iD.1562
3913
3914 A shared variable mapping will produce a copy-out operation before
3915 the parallel directive and a copy-in operation after it. So, in
3916 this case we would have:
3917
3918 iD.1562 = 0;
3919 .omp_data_o.1.i = iD.1562;
3920 #omp parallel shared(iD.1562) -> outer parallel
3921 .omp_data_i.1 = &.omp_data_o.1
3922 .omp_data_i.1->i = .omp_data_i.1->i + 1;
3923
3924 .omp_data_o.2.i = iD.1562; -> **
3925 #omp parallel shared(iD.1562) -> inner parallel
3926 .omp_data_i.2 = &.omp_data_o.2
3927 .omp_data_i.2->i = .omp_data_i.2->i - 1;
3928
3929
3930 ** This is a problem. The symbol iD.1562 cannot be referenced
3931 inside the body of the outer parallel region. But since we are
3932 emitting this copy operation while expanding the inner parallel
3933 directive, we need to access the CTX structure of the outer
3934 parallel directive to get the correct mapping:
3935
3936 .omp_data_o.2.i = .omp_data_i.1->i
3937
3938 Since there may be other workshare or parallel directives enclosing
3939 the parallel directive, it may be necessary to walk up the context
3940 parent chain. This is not a problem in general because nested
3941 parallelism happens only rarely. */
3942
3943static tree
3944lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
3945{
3946 tree t;
3947 omp_context *up;
3948
50674e96
DN
3949 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
3950 t = maybe_lookup_decl (decl, up);
3951
d2dda7fe 3952 gcc_assert (!ctx->is_nested || t || is_global_var (decl));
50674e96 3953
64964499 3954 return t ? t : decl;
50674e96
DN
3955}
3956
3957
8ca5b2a2
JJ
3958/* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
3959 in outer contexts. */
3960
3961static tree
3962maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
3963{
3964 tree t = NULL;
3965 omp_context *up;
3966
d2dda7fe
JJ
3967 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
3968 t = maybe_lookup_decl (decl, up);
8ca5b2a2
JJ
3969
3970 return t ? t : decl;
3971}
3972
3973
f2c9f71d 3974/* Construct the initialization value for reduction operation OP. */
953ff289
DN
3975
3976tree
f2c9f71d 3977omp_reduction_init_op (location_t loc, enum tree_code op, tree type)
953ff289 3978{
f2c9f71d 3979 switch (op)
953ff289
DN
3980 {
3981 case PLUS_EXPR:
3982 case MINUS_EXPR:
3983 case BIT_IOR_EXPR:
3984 case BIT_XOR_EXPR:
3985 case TRUTH_OR_EXPR:
3986 case TRUTH_ORIF_EXPR:
3987 case TRUTH_XOR_EXPR:
3988 case NE_EXPR:
e8160c9a 3989 return build_zero_cst (type);
953ff289
DN
3990
3991 case MULT_EXPR:
3992 case TRUTH_AND_EXPR:
3993 case TRUTH_ANDIF_EXPR:
3994 case EQ_EXPR:
db3927fb 3995 return fold_convert_loc (loc, type, integer_one_node);
953ff289
DN
3996
3997 case BIT_AND_EXPR:
db3927fb 3998 return fold_convert_loc (loc, type, integer_minus_one_node);
953ff289
DN
3999
4000 case MAX_EXPR:
4001 if (SCALAR_FLOAT_TYPE_P (type))
4002 {
4003 REAL_VALUE_TYPE max, min;
3d3dbadd 4004 if (HONOR_INFINITIES (type))
953ff289
DN
4005 {
4006 real_inf (&max);
4007 real_arithmetic (&min, NEGATE_EXPR, &max, NULL);
4008 }
4009 else
4010 real_maxval (&min, 1, TYPE_MODE (type));
4011 return build_real (type, min);
4012 }
3ff2d74e
TV
4013 else if (POINTER_TYPE_P (type))
4014 {
4015 wide_int min
4016 = wi::min_value (TYPE_PRECISION (type), TYPE_SIGN (type));
4017 return wide_int_to_tree (type, min);
4018 }
953ff289
DN
4019 else
4020 {
4021 gcc_assert (INTEGRAL_TYPE_P (type));
4022 return TYPE_MIN_VALUE (type);
4023 }
4024
4025 case MIN_EXPR:
4026 if (SCALAR_FLOAT_TYPE_P (type))
4027 {
4028 REAL_VALUE_TYPE max;
3d3dbadd 4029 if (HONOR_INFINITIES (type))
953ff289
DN
4030 real_inf (&max);
4031 else
4032 real_maxval (&max, 0, TYPE_MODE (type));
4033 return build_real (type, max);
4034 }
3ff2d74e
TV
4035 else if (POINTER_TYPE_P (type))
4036 {
4037 wide_int max
4038 = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type));
4039 return wide_int_to_tree (type, max);
4040 }
953ff289
DN
4041 else
4042 {
4043 gcc_assert (INTEGRAL_TYPE_P (type));
4044 return TYPE_MAX_VALUE (type);
4045 }
4046
4047 default:
4048 gcc_unreachable ();
4049 }
4050}
4051
f2c9f71d
TS
4052/* Construct the initialization value for reduction CLAUSE. */
4053
4054tree
4055omp_reduction_init (tree clause, tree type)
4056{
4057 return omp_reduction_init_op (OMP_CLAUSE_LOCATION (clause),
4058 OMP_CLAUSE_REDUCTION_CODE (clause), type);
4059}
4060
acf0174b
JJ
4061/* Return alignment to be assumed for var in CLAUSE, which should be
4062 OMP_CLAUSE_ALIGNED. */
4063
4064static tree
4065omp_clause_aligned_alignment (tree clause)
4066{
4067 if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause))
4068 return OMP_CLAUSE_ALIGNED_ALIGNMENT (clause);
4069
4070 /* Otherwise return implementation defined alignment. */
4071 unsigned int al = 1;
ef4bddc2 4072 machine_mode mode, vmode;
acf0174b
JJ
4073 int vs = targetm.vectorize.autovectorize_vector_sizes ();
4074 if (vs)
4075 vs = 1 << floor_log2 (vs);
4076 static enum mode_class classes[]
4077 = { MODE_INT, MODE_VECTOR_INT, MODE_FLOAT, MODE_VECTOR_FLOAT };
4078 for (int i = 0; i < 4; i += 2)
4079 for (mode = GET_CLASS_NARROWEST_MODE (classes[i]);
4080 mode != VOIDmode;
4081 mode = GET_MODE_WIDER_MODE (mode))
4082 {
4083 vmode = targetm.vectorize.preferred_simd_mode (mode);
4084 if (GET_MODE_CLASS (vmode) != classes[i + 1])
4085 continue;
4086 while (vs
4087 && GET_MODE_SIZE (vmode) < vs
4088 && GET_MODE_2XWIDER_MODE (vmode) != VOIDmode)
4089 vmode = GET_MODE_2XWIDER_MODE (vmode);
4090
4091 tree type = lang_hooks.types.type_for_mode (mode, 1);
4092 if (type == NULL_TREE || TYPE_MODE (type) != mode)
4093 continue;
4094 type = build_vector_type (type, GET_MODE_SIZE (vmode)
4095 / GET_MODE_SIZE (mode));
4096 if (TYPE_MODE (type) != vmode)
4097 continue;
4098 if (TYPE_ALIGN_UNIT (type) > al)
4099 al = TYPE_ALIGN_UNIT (type);
4100 }
4101 return build_int_cst (integer_type_node, al);
4102}
4103
74bf76ed
JJ
4104/* Return maximum possible vectorization factor for the target. */
4105
4106static int
4107omp_max_vf (void)
4108{
4109 if (!optimize
4110 || optimize_debug
ab2ffbeb 4111 || !flag_tree_loop_optimize
ea0f3e87
XDL
4112 || (!flag_tree_loop_vectorize
4113 && (global_options_set.x_flag_tree_loop_vectorize
4114 || global_options_set.x_flag_tree_vectorize)))
74bf76ed
JJ
4115 return 1;
4116
4117 int vs = targetm.vectorize.autovectorize_vector_sizes ();
4118 if (vs)
4119 {
4120 vs = 1 << floor_log2 (vs);
4121 return vs;
4122 }
ef4bddc2 4123 machine_mode vqimode = targetm.vectorize.preferred_simd_mode (QImode);
74bf76ed
JJ
4124 if (GET_MODE_CLASS (vqimode) == MODE_VECTOR_INT)
4125 return GET_MODE_NUNITS (vqimode);
4126 return 1;
4127}
4128
4129/* Helper function of lower_rec_input_clauses, used for #pragma omp simd
4130 privatization. */
4131
4132static bool
4133lower_rec_simd_input_clauses (tree new_var, omp_context *ctx, int &max_vf,
4134 tree &idx, tree &lane, tree &ivar, tree &lvar)
4135{
4136 if (max_vf == 0)
4137 {
4138 max_vf = omp_max_vf ();
4139 if (max_vf > 1)
4140 {
4141 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
4142 OMP_CLAUSE_SAFELEN);
b46ebd6c
JJ
4143 if (c && TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) != INTEGER_CST)
4144 max_vf = 1;
4145 else if (c && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
4146 max_vf) == -1)
9439e9a1 4147 max_vf = tree_to_shwi (OMP_CLAUSE_SAFELEN_EXPR (c));
74bf76ed
JJ
4148 }
4149 if (max_vf > 1)
4150 {
b731b390
JJ
4151 idx = create_tmp_var (unsigned_type_node);
4152 lane = create_tmp_var (unsigned_type_node);
74bf76ed
JJ
4153 }
4154 }
4155 if (max_vf == 1)
4156 return false;
4157
4158 tree atype = build_array_type_nelts (TREE_TYPE (new_var), max_vf);
b731b390 4159 tree avar = create_tmp_var_raw (atype);
74bf76ed
JJ
4160 if (TREE_ADDRESSABLE (new_var))
4161 TREE_ADDRESSABLE (avar) = 1;
4162 DECL_ATTRIBUTES (avar)
4163 = tree_cons (get_identifier ("omp simd array"), NULL,
4164 DECL_ATTRIBUTES (avar));
4165 gimple_add_tmp_var (avar);
4166 ivar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, idx,
4167 NULL_TREE, NULL_TREE);
4168 lvar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, lane,
4169 NULL_TREE, NULL_TREE);
acf0174b
JJ
4170 if (DECL_P (new_var))
4171 {
4172 SET_DECL_VALUE_EXPR (new_var, lvar);
4173 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4174 }
74bf76ed
JJ
4175 return true;
4176}
4177
decaaec8
JJ
4178/* Helper function of lower_rec_input_clauses. For a reference
4179 in simd reduction, add an underlying variable it will reference. */
4180
4181static void
4182handle_simd_reference (location_t loc, tree new_vard, gimple_seq *ilist)
4183{
4184 tree z = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard)));
4185 if (TREE_CONSTANT (z))
4186 {
d9a6bd32
JJ
4187 z = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_vard)),
4188 get_name (new_vard));
decaaec8
JJ
4189 gimple_add_tmp_var (z);
4190 TREE_ADDRESSABLE (z) = 1;
4191 z = build_fold_addr_expr_loc (loc, z);
4192 gimplify_assign (new_vard, z, ilist);
4193 }
4194}
4195
953ff289
DN
4196/* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
4197 from the receiver (aka child) side and initializers for REFERENCE_TYPE
4198 private variables. Initialization statements go in ILIST, while calls
4199 to destructors go in DLIST. */
4200
4201static void
726a989a 4202lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
acf0174b 4203 omp_context *ctx, struct omp_for_data *fd)
953ff289 4204{
5039610b 4205 tree c, dtor, copyin_seq, x, ptr;
953ff289 4206 bool copyin_by_ref = false;
8ca5b2a2 4207 bool lastprivate_firstprivate = false;
acf0174b 4208 bool reduction_omp_orig_ref = false;
953ff289 4209 int pass;
74bf76ed 4210 bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
0aadce73 4211 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD);
74bf76ed
JJ
4212 int max_vf = 0;
4213 tree lane = NULL_TREE, idx = NULL_TREE;
4214 tree ivar = NULL_TREE, lvar = NULL_TREE;
4215 gimple_seq llist[2] = { NULL, NULL };
953ff289 4216
953ff289
DN
4217 copyin_seq = NULL;
4218
74bf76ed
JJ
4219 /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
4220 with data sharing clauses referencing variable sized vars. That
4221 is unnecessarily hard to support and very unlikely to result in
4222 vectorized code anyway. */
4223 if (is_simd)
4224 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4225 switch (OMP_CLAUSE_CODE (c))
4226 {
da6f124d
JJ
4227 case OMP_CLAUSE_LINEAR:
4228 if (OMP_CLAUSE_LINEAR_ARRAY (c))
4229 max_vf = 1;
4230 /* FALLTHRU */
74bf76ed
JJ
4231 case OMP_CLAUSE_PRIVATE:
4232 case OMP_CLAUSE_FIRSTPRIVATE:
4233 case OMP_CLAUSE_LASTPRIVATE:
74bf76ed
JJ
4234 if (is_variable_sized (OMP_CLAUSE_DECL (c)))
4235 max_vf = 1;
4236 break;
d9a6bd32
JJ
4237 case OMP_CLAUSE_REDUCTION:
4238 if (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF
4239 || is_variable_sized (OMP_CLAUSE_DECL (c)))
4240 max_vf = 1;
4241 break;
74bf76ed
JJ
4242 default:
4243 continue;
4244 }
4245
953ff289
DN
4246 /* Do all the fixed sized types in the first pass, and the variable sized
4247 types in the second pass. This makes sure that the scalar arguments to
b8698a0f 4248 the variable sized types are processed before we use them in the
953ff289
DN
4249 variable sized operations. */
4250 for (pass = 0; pass < 2; ++pass)
4251 {
4252 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4253 {
aaf46ef9 4254 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
953ff289
DN
4255 tree var, new_var;
4256 bool by_ref;
db3927fb 4257 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
953ff289
DN
4258
4259 switch (c_kind)
4260 {
4261 case OMP_CLAUSE_PRIVATE:
4262 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
4263 continue;
4264 break;
4265 case OMP_CLAUSE_SHARED:
acf0174b
JJ
4266 /* Ignore shared directives in teams construct. */
4267 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
4268 continue;
8ca5b2a2
JJ
4269 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
4270 {
d9a6bd32
JJ
4271 gcc_assert (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c)
4272 || is_global_var (OMP_CLAUSE_DECL (c)));
8ca5b2a2
JJ
4273 continue;
4274 }
953ff289 4275 case OMP_CLAUSE_FIRSTPRIVATE:
953ff289 4276 case OMP_CLAUSE_COPYIN:
d9a6bd32 4277 break;
acf0174b 4278 case OMP_CLAUSE_LINEAR:
d9a6bd32
JJ
4279 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c)
4280 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
4281 lastprivate_firstprivate = true;
acf0174b 4282 break;
953ff289 4283 case OMP_CLAUSE_REDUCTION:
acf0174b
JJ
4284 if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
4285 reduction_omp_orig_ref = true;
953ff289 4286 break;
acf0174b 4287 case OMP_CLAUSE__LOOPTEMP_:
d9a6bd32 4288 /* Handle _looptemp_ clauses only on parallel/task. */
acf0174b
JJ
4289 if (fd)
4290 continue;
74bf76ed 4291 break;
077b0dfb 4292 case OMP_CLAUSE_LASTPRIVATE:
8ca5b2a2
JJ
4293 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4294 {
4295 lastprivate_firstprivate = true;
d9a6bd32 4296 if (pass != 0 || is_taskloop_ctx (ctx))
8ca5b2a2
JJ
4297 continue;
4298 }
92d28cbb
JJ
4299 /* Even without corresponding firstprivate, if
4300 decl is Fortran allocatable, it needs outer var
4301 reference. */
4302 else if (pass == 0
4303 && lang_hooks.decls.omp_private_outer_ref
4304 (OMP_CLAUSE_DECL (c)))
4305 lastprivate_firstprivate = true;
077b0dfb 4306 break;
acf0174b
JJ
4307 case OMP_CLAUSE_ALIGNED:
4308 if (pass == 0)
4309 continue;
4310 var = OMP_CLAUSE_DECL (c);
4311 if (TREE_CODE (TREE_TYPE (var)) == POINTER_TYPE
4312 && !is_global_var (var))
4313 {
4314 new_var = maybe_lookup_decl (var, ctx);
4315 if (new_var == NULL_TREE)
4316 new_var = maybe_lookup_decl_in_outer_ctx (var, ctx);
4317 x = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
4318 x = build_call_expr_loc (clause_loc, x, 2, new_var,
4319 omp_clause_aligned_alignment (c));
4320 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
4321 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
4322 gimplify_and_add (x, ilist);
4323 }
4324 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
4325 && is_global_var (var))
4326 {
4327 tree ptype = build_pointer_type (TREE_TYPE (var)), t, t2;
4328 new_var = lookup_decl (var, ctx);
4329 t = maybe_lookup_decl_in_outer_ctx (var, ctx);
4330 t = build_fold_addr_expr_loc (clause_loc, t);
4331 t2 = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
4332 t = build_call_expr_loc (clause_loc, t2, 2, t,
4333 omp_clause_aligned_alignment (c));
4334 t = fold_convert_loc (clause_loc, ptype, t);
b731b390 4335 x = create_tmp_var (ptype);
acf0174b
JJ
4336 t = build2 (MODIFY_EXPR, ptype, x, t);
4337 gimplify_and_add (t, ilist);
4338 t = build_simple_mem_ref_loc (clause_loc, x);
4339 SET_DECL_VALUE_EXPR (new_var, t);
4340 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4341 }
4342 continue;
953ff289
DN
4343 default:
4344 continue;
4345 }
4346
4347 new_var = var = OMP_CLAUSE_DECL (c);
d9a6bd32
JJ
4348 if (c_kind == OMP_CLAUSE_REDUCTION && TREE_CODE (var) == MEM_REF)
4349 {
4350 var = TREE_OPERAND (var, 0);
e01d41e5
JJ
4351 if (TREE_CODE (var) == POINTER_PLUS_EXPR)
4352 var = TREE_OPERAND (var, 0);
d9a6bd32
JJ
4353 if (TREE_CODE (var) == INDIRECT_REF
4354 || TREE_CODE (var) == ADDR_EXPR)
4355 var = TREE_OPERAND (var, 0);
4356 if (is_variable_sized (var))
4357 {
4358 gcc_assert (DECL_HAS_VALUE_EXPR_P (var));
4359 var = DECL_VALUE_EXPR (var);
4360 gcc_assert (TREE_CODE (var) == INDIRECT_REF);
4361 var = TREE_OPERAND (var, 0);
4362 gcc_assert (DECL_P (var));
4363 }
4364 new_var = var;
4365 }
953ff289
DN
4366 if (c_kind != OMP_CLAUSE_COPYIN)
4367 new_var = lookup_decl (var, ctx);
4368
4369 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
4370 {
4371 if (pass != 0)
4372 continue;
4373 }
d9a6bd32
JJ
4374 /* C/C++ array section reductions. */
4375 else if (c_kind == OMP_CLAUSE_REDUCTION
4376 && var != OMP_CLAUSE_DECL (c))
953ff289
DN
4377 {
4378 if (pass == 0)
4379 continue;
4380
e01d41e5 4381 tree bias = TREE_OPERAND (OMP_CLAUSE_DECL (c), 1);
d9a6bd32 4382 tree orig_var = TREE_OPERAND (OMP_CLAUSE_DECL (c), 0);
e01d41e5
JJ
4383 if (TREE_CODE (orig_var) == POINTER_PLUS_EXPR)
4384 {
4385 tree b = TREE_OPERAND (orig_var, 1);
4386 b = maybe_lookup_decl (b, ctx);
4387 if (b == NULL)
4388 {
4389 b = TREE_OPERAND (orig_var, 1);
4390 b = maybe_lookup_decl_in_outer_ctx (b, ctx);
4391 }
4392 if (integer_zerop (bias))
4393 bias = b;
4394 else
4395 {
4396 bias = fold_convert_loc (clause_loc,
4397 TREE_TYPE (b), bias);
4398 bias = fold_build2_loc (clause_loc, PLUS_EXPR,
4399 TREE_TYPE (b), b, bias);
4400 }
4401 orig_var = TREE_OPERAND (orig_var, 0);
4402 }
d9a6bd32
JJ
4403 if (TREE_CODE (orig_var) == INDIRECT_REF
4404 || TREE_CODE (orig_var) == ADDR_EXPR)
4405 orig_var = TREE_OPERAND (orig_var, 0);
4406 tree d = OMP_CLAUSE_DECL (c);
4407 tree type = TREE_TYPE (d);
4408 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
4409 tree v = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
4410 const char *name = get_name (orig_var);
4411 if (TREE_CONSTANT (v))
a68ab351 4412 {
d9a6bd32
JJ
4413 x = create_tmp_var_raw (type, name);
4414 gimple_add_tmp_var (x);
4415 TREE_ADDRESSABLE (x) = 1;
4416 x = build_fold_addr_expr_loc (clause_loc, x);
4417 }
4418 else
4419 {
4420 tree atmp
4421 = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
4422 tree t = maybe_lookup_decl (v, ctx);
4423 if (t)
4424 v = t;
4425 else
4426 v = maybe_lookup_decl_in_outer_ctx (v, ctx);
4427 gimplify_expr (&v, ilist, NULL, is_gimple_val, fb_rvalue);
4428 t = fold_build2_loc (clause_loc, PLUS_EXPR,
4429 TREE_TYPE (v), v,
4430 build_int_cst (TREE_TYPE (v), 1));
4431 t = fold_build2_loc (clause_loc, MULT_EXPR,
4432 TREE_TYPE (v), t,
4433 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4434 tree al = size_int (TYPE_ALIGN (TREE_TYPE (type)));
4435 x = build_call_expr_loc (clause_loc, atmp, 2, t, al);
4436 }
4437
4438 tree ptype = build_pointer_type (TREE_TYPE (type));
4439 x = fold_convert_loc (clause_loc, ptype, x);
4440 tree y = create_tmp_var (ptype, name);
4441 gimplify_assign (y, x, ilist);
4442 x = y;
e01d41e5
JJ
4443 tree yb = y;
4444
4445 if (!integer_zerop (bias))
4446 {
4447 bias = fold_convert_loc (clause_loc, sizetype, bias);
4448 bias = fold_build1_loc (clause_loc, NEGATE_EXPR,
4449 sizetype, bias);
4450 x = fold_build2_loc (clause_loc, POINTER_PLUS_EXPR,
4451 TREE_TYPE (x), x, bias);
4452 yb = create_tmp_var (ptype, name);
4453 gimplify_assign (yb, x, ilist);
4454 x = yb;
4455 }
4456
4457 d = TREE_OPERAND (d, 0);
4458 if (TREE_CODE (d) == POINTER_PLUS_EXPR)
4459 d = TREE_OPERAND (d, 0);
4460 if (TREE_CODE (d) == ADDR_EXPR)
d9a6bd32
JJ
4461 {
4462 if (orig_var != var)
4463 {
4464 gcc_assert (is_variable_sized (orig_var));
4465 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var),
4466 x);
4467 gimplify_assign (new_var, x, ilist);
4468 tree new_orig_var = lookup_decl (orig_var, ctx);
4469 tree t = build_fold_indirect_ref (new_var);
4470 DECL_IGNORED_P (new_var) = 0;
4471 TREE_THIS_NOTRAP (t);
4472 SET_DECL_VALUE_EXPR (new_orig_var, t);
4473 DECL_HAS_VALUE_EXPR_P (new_orig_var) = 1;
4474 }
4475 else
4476 {
4477 x = build2 (MEM_REF, TREE_TYPE (new_var), x,
4478 build_int_cst (ptype, 0));
4479 SET_DECL_VALUE_EXPR (new_var, x);
4480 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4481 }
4482 }
4483 else
4484 {
4485 gcc_assert (orig_var == var);
e01d41e5 4486 if (TREE_CODE (d) == INDIRECT_REF)
d9a6bd32
JJ
4487 {
4488 x = create_tmp_var (ptype, name);
4489 TREE_ADDRESSABLE (x) = 1;
e01d41e5 4490 gimplify_assign (x, yb, ilist);
d9a6bd32
JJ
4491 x = build_fold_addr_expr_loc (clause_loc, x);
4492 }
4493 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
4494 gimplify_assign (new_var, x, ilist);
4495 }
4496 tree y1 = create_tmp_var (ptype, NULL);
4497 gimplify_assign (y1, y, ilist);
4498 tree i2 = NULL_TREE, y2 = NULL_TREE;
4499 tree body2 = NULL_TREE, end2 = NULL_TREE;
4500 tree y3 = NULL_TREE, y4 = NULL_TREE;
4501 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) || is_simd)
4502 {
4503 y2 = create_tmp_var (ptype, NULL);
4504 gimplify_assign (y2, y, ilist);
4505 tree ref = build_outer_var_ref (var, ctx);
4506 /* For ref build_outer_var_ref already performs this. */
e01d41e5 4507 if (TREE_CODE (d) == INDIRECT_REF)
d9a6bd32 4508 gcc_assert (is_reference (var));
e01d41e5 4509 else if (TREE_CODE (d) == ADDR_EXPR)
d9a6bd32
JJ
4510 ref = build_fold_addr_expr (ref);
4511 else if (is_reference (var))
4512 ref = build_fold_addr_expr (ref);
4513 ref = fold_convert_loc (clause_loc, ptype, ref);
4514 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
4515 && OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
4516 {
4517 y3 = create_tmp_var (ptype, NULL);
4518 gimplify_assign (y3, unshare_expr (ref), ilist);
4519 }
4520 if (is_simd)
4521 {
4522 y4 = create_tmp_var (ptype, NULL);
4523 gimplify_assign (y4, ref, dlist);
4524 }
4525 }
4526 tree i = create_tmp_var (TREE_TYPE (v), NULL);
4527 gimplify_assign (i, build_int_cst (TREE_TYPE (v), 0), ilist);
4528 tree body = create_artificial_label (UNKNOWN_LOCATION);
4529 tree end = create_artificial_label (UNKNOWN_LOCATION);
4530 gimple_seq_add_stmt (ilist, gimple_build_label (body));
4531 if (y2)
4532 {
4533 i2 = create_tmp_var (TREE_TYPE (v), NULL);
4534 gimplify_assign (i2, build_int_cst (TREE_TYPE (v), 0), dlist);
4535 body2 = create_artificial_label (UNKNOWN_LOCATION);
4536 end2 = create_artificial_label (UNKNOWN_LOCATION);
4537 gimple_seq_add_stmt (dlist, gimple_build_label (body2));
4538 }
4539 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4540 {
4541 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
4542 tree decl_placeholder
4543 = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c);
4544 SET_DECL_VALUE_EXPR (decl_placeholder,
4545 build_simple_mem_ref (y1));
4546 DECL_HAS_VALUE_EXPR_P (decl_placeholder) = 1;
4547 SET_DECL_VALUE_EXPR (placeholder,
4548 y3 ? build_simple_mem_ref (y3)
4549 : error_mark_node);
4550 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
4551 x = lang_hooks.decls.omp_clause_default_ctor
4552 (c, build_simple_mem_ref (y1),
4553 y3 ? build_simple_mem_ref (y3) : NULL_TREE);
4554 if (x)
4555 gimplify_and_add (x, ilist);
4556 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
4557 {
4558 gimple_seq tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
4559 lower_omp (&tseq, ctx);
4560 gimple_seq_add_seq (ilist, tseq);
4561 }
4562 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
4563 if (is_simd)
4564 {
4565 SET_DECL_VALUE_EXPR (decl_placeholder,
4566 build_simple_mem_ref (y2));
4567 SET_DECL_VALUE_EXPR (placeholder,
4568 build_simple_mem_ref (y4));
4569 gimple_seq tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
4570 lower_omp (&tseq, ctx);
4571 gimple_seq_add_seq (dlist, tseq);
4572 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4573 }
4574 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
4575 DECL_HAS_VALUE_EXPR_P (decl_placeholder) = 0;
4576 x = lang_hooks.decls.omp_clause_dtor
4577 (c, build_simple_mem_ref (y2));
4578 if (x)
4579 {
4580 gimple_seq tseq = NULL;
4581 dtor = x;
4582 gimplify_stmt (&dtor, &tseq);
4583 gimple_seq_add_seq (dlist, tseq);
4584 }
4585 }
4586 else
4587 {
4588 x = omp_reduction_init (c, TREE_TYPE (type));
4589 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
4590
4591 /* reduction(-:var) sums up the partial results, so it
4592 acts identically to reduction(+:var). */
4593 if (code == MINUS_EXPR)
4594 code = PLUS_EXPR;
4595
4596 gimplify_assign (build_simple_mem_ref (y1), x, ilist);
4597 if (is_simd)
4598 {
4599 x = build2 (code, TREE_TYPE (type),
4600 build_simple_mem_ref (y4),
4601 build_simple_mem_ref (y2));
4602 gimplify_assign (build_simple_mem_ref (y4), x, dlist);
4603 }
4604 }
4605 gimple *g
4606 = gimple_build_assign (y1, POINTER_PLUS_EXPR, y1,
4607 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4608 gimple_seq_add_stmt (ilist, g);
4609 if (y3)
4610 {
4611 g = gimple_build_assign (y3, POINTER_PLUS_EXPR, y3,
4612 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4613 gimple_seq_add_stmt (ilist, g);
4614 }
4615 g = gimple_build_assign (i, PLUS_EXPR, i,
4616 build_int_cst (TREE_TYPE (i), 1));
4617 gimple_seq_add_stmt (ilist, g);
4618 g = gimple_build_cond (LE_EXPR, i, v, body, end);
4619 gimple_seq_add_stmt (ilist, g);
4620 gimple_seq_add_stmt (ilist, gimple_build_label (end));
4621 if (y2)
4622 {
4623 g = gimple_build_assign (y2, POINTER_PLUS_EXPR, y2,
4624 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4625 gimple_seq_add_stmt (dlist, g);
4626 if (y4)
4627 {
4628 g = gimple_build_assign
4629 (y4, POINTER_PLUS_EXPR, y4,
4630 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4631 gimple_seq_add_stmt (dlist, g);
4632 }
4633 g = gimple_build_assign (i2, PLUS_EXPR, i2,
4634 build_int_cst (TREE_TYPE (i2), 1));
4635 gimple_seq_add_stmt (dlist, g);
4636 g = gimple_build_cond (LE_EXPR, i2, v, body2, end2);
4637 gimple_seq_add_stmt (dlist, g);
4638 gimple_seq_add_stmt (dlist, gimple_build_label (end2));
4639 }
4640 continue;
4641 }
4642 else if (is_variable_sized (var))
4643 {
4644 /* For variable sized types, we need to allocate the
4645 actual storage here. Call alloca and store the
4646 result in the pointer decl that we created elsewhere. */
4647 if (pass == 0)
4648 continue;
4649
4650 if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
4651 {
4652 gcall *stmt;
4653 tree tmp, atmp;
4654
4655 ptr = DECL_VALUE_EXPR (new_var);
4656 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
4657 ptr = TREE_OPERAND (ptr, 0);
a68ab351
JJ
4658 gcc_assert (DECL_P (ptr));
4659 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
726a989a
RB
4660
4661 /* void *tmp = __builtin_alloca */
d9a6bd32
JJ
4662 atmp = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
4663 stmt = gimple_build_call (atmp, 2, x,
4664 size_int (DECL_ALIGN (var)));
b731b390 4665 tmp = create_tmp_var_raw (ptr_type_node);
726a989a
RB
4666 gimple_add_tmp_var (tmp);
4667 gimple_call_set_lhs (stmt, tmp);
4668
4669 gimple_seq_add_stmt (ilist, stmt);
4670
db3927fb 4671 x = fold_convert_loc (clause_loc, TREE_TYPE (ptr), tmp);
726a989a 4672 gimplify_assign (ptr, x, ilist);
a68ab351 4673 }
953ff289 4674 }
182190f2 4675 else if (is_reference (var) && !is_oacc_parallel (ctx))
953ff289 4676 {
50674e96
DN
4677 /* For references that are being privatized for Fortran,
4678 allocate new backing storage for the new pointer
4679 variable. This allows us to avoid changing all the
4680 code that expects a pointer to something that expects
acf0174b 4681 a direct variable. */
953ff289
DN
4682 if (pass == 0)
4683 continue;
4684
4685 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
a68ab351
JJ
4686 if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx))
4687 {
4688 x = build_receiver_ref (var, false, ctx);
db3927fb 4689 x = build_fold_addr_expr_loc (clause_loc, x);
a68ab351
JJ
4690 }
4691 else if (TREE_CONSTANT (x))
953ff289 4692 {
decaaec8
JJ
4693 /* For reduction in SIMD loop, defer adding the
4694 initialization of the reference, because if we decide
4695 to use SIMD array for it, the initilization could cause
4696 expansion ICE. */
4697 if (c_kind == OMP_CLAUSE_REDUCTION && is_simd)
4ceffa27
JJ
4698 x = NULL_TREE;
4699 else
4700 {
4ceffa27 4701 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
d9a6bd32 4702 get_name (var));
4ceffa27
JJ
4703 gimple_add_tmp_var (x);
4704 TREE_ADDRESSABLE (x) = 1;
4705 x = build_fold_addr_expr_loc (clause_loc, x);
4706 }
953ff289
DN
4707 }
4708 else
4709 {
d9a6bd32
JJ
4710 tree atmp
4711 = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
4712 tree rtype = TREE_TYPE (TREE_TYPE (new_var));
4713 tree al = size_int (TYPE_ALIGN (rtype));
4714 x = build_call_expr_loc (clause_loc, atmp, 2, x, al);
953ff289
DN
4715 }
4716
4ceffa27
JJ
4717 if (x)
4718 {
4719 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
4720 gimplify_assign (new_var, x, ilist);
4721 }
953ff289 4722
70f34814 4723 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
953ff289
DN
4724 }
4725 else if (c_kind == OMP_CLAUSE_REDUCTION
4726 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4727 {
4728 if (pass == 0)
4729 continue;
4730 }
4731 else if (pass != 0)
4732 continue;
4733
aaf46ef9 4734 switch (OMP_CLAUSE_CODE (c))
953ff289
DN
4735 {
4736 case OMP_CLAUSE_SHARED:
acf0174b
JJ
4737 /* Ignore shared directives in teams construct. */
4738 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
4739 continue;
8ca5b2a2
JJ
4740 /* Shared global vars are just accessed directly. */
4741 if (is_global_var (new_var))
4742 break;
d9a6bd32
JJ
4743 /* For taskloop firstprivate/lastprivate, represented
4744 as firstprivate and shared clause on the task, new_var
4745 is the firstprivate var. */
4746 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
4747 break;
953ff289
DN
4748 /* Set up the DECL_VALUE_EXPR for shared variables now. This
4749 needs to be delayed until after fixup_child_record_type so
4750 that we get the correct type during the dereference. */
7c8f7639 4751 by_ref = use_pointer_for_field (var, ctx);
953ff289
DN
4752 x = build_receiver_ref (var, by_ref, ctx);
4753 SET_DECL_VALUE_EXPR (new_var, x);
4754 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4755
4756 /* ??? If VAR is not passed by reference, and the variable
4757 hasn't been initialized yet, then we'll get a warning for
4758 the store into the omp_data_s structure. Ideally, we'd be
b8698a0f 4759 able to notice this and not store anything at all, but
953ff289
DN
4760 we're generating code too early. Suppress the warning. */
4761 if (!by_ref)
4762 TREE_NO_WARNING (var) = 1;
4763 break;
4764
4765 case OMP_CLAUSE_LASTPRIVATE:
4766 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4767 break;
4768 /* FALLTHRU */
4769
4770 case OMP_CLAUSE_PRIVATE:
a68ab351
JJ
4771 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE)
4772 x = build_outer_var_ref (var, ctx);
4773 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
4774 {
4775 if (is_task_ctx (ctx))
4776 x = build_receiver_ref (var, false, ctx);
4777 else
4778 x = build_outer_var_ref (var, ctx);
4779 }
4780 else
4781 x = NULL;
74bf76ed 4782 do_private:
acf0174b 4783 tree nx;
d9a6bd32
JJ
4784 nx = lang_hooks.decls.omp_clause_default_ctor
4785 (c, unshare_expr (new_var), x);
74bf76ed
JJ
4786 if (is_simd)
4787 {
4788 tree y = lang_hooks.decls.omp_clause_dtor (c, new_var);
acf0174b 4789 if ((TREE_ADDRESSABLE (new_var) || nx || y
74bf76ed
JJ
4790 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
4791 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4792 idx, lane, ivar, lvar))
4793 {
acf0174b 4794 if (nx)
74bf76ed
JJ
4795 x = lang_hooks.decls.omp_clause_default_ctor
4796 (c, unshare_expr (ivar), x);
acf0174b 4797 if (nx && x)
74bf76ed
JJ
4798 gimplify_and_add (x, &llist[0]);
4799 if (y)
4800 {
4801 y = lang_hooks.decls.omp_clause_dtor (c, ivar);
4802 if (y)
4803 {
4804 gimple_seq tseq = NULL;
4805
4806 dtor = y;
4807 gimplify_stmt (&dtor, &tseq);
4808 gimple_seq_add_seq (&llist[1], tseq);
4809 }
4810 }
4811 break;
4812 }
4813 }
acf0174b
JJ
4814 if (nx)
4815 gimplify_and_add (nx, ilist);
953ff289
DN
4816 /* FALLTHRU */
4817
4818 do_dtor:
4819 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
4820 if (x)
4821 {
726a989a
RB
4822 gimple_seq tseq = NULL;
4823
953ff289 4824 dtor = x;
726a989a 4825 gimplify_stmt (&dtor, &tseq);
355a7673 4826 gimple_seq_add_seq (dlist, tseq);
953ff289
DN
4827 }
4828 break;
4829
74bf76ed
JJ
4830 case OMP_CLAUSE_LINEAR:
4831 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c))
4832 goto do_firstprivate;
4833 if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
4834 x = NULL;
4835 else
4836 x = build_outer_var_ref (var, ctx);
4837 goto do_private;
4838
953ff289 4839 case OMP_CLAUSE_FIRSTPRIVATE:
a68ab351
JJ
4840 if (is_task_ctx (ctx))
4841 {
4842 if (is_reference (var) || is_variable_sized (var))
4843 goto do_dtor;
4844 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var,
4845 ctx))
4846 || use_pointer_for_field (var, NULL))
4847 {
4848 x = build_receiver_ref (var, false, ctx);
4849 SET_DECL_VALUE_EXPR (new_var, x);
4850 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4851 goto do_dtor;
4852 }
4853 }
74bf76ed 4854 do_firstprivate:
953ff289 4855 x = build_outer_var_ref (var, ctx);
74bf76ed
JJ
4856 if (is_simd)
4857 {
acf0174b
JJ
4858 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
4859 && gimple_omp_for_combined_into_p (ctx->stmt))
4860 {
da6f124d
JJ
4861 tree t = OMP_CLAUSE_LINEAR_STEP (c);
4862 tree stept = TREE_TYPE (t);
4863 tree ct = find_omp_clause (clauses,
4864 OMP_CLAUSE__LOOPTEMP_);
4865 gcc_assert (ct);
4866 tree l = OMP_CLAUSE_DECL (ct);
56ad0e38
JJ
4867 tree n1 = fd->loop.n1;
4868 tree step = fd->loop.step;
4869 tree itype = TREE_TYPE (l);
4870 if (POINTER_TYPE_P (itype))
4871 itype = signed_type_for (itype);
4872 l = fold_build2 (MINUS_EXPR, itype, l, n1);
4873 if (TYPE_UNSIGNED (itype)
4874 && fd->loop.cond_code == GT_EXPR)
4875 l = fold_build2 (TRUNC_DIV_EXPR, itype,
4876 fold_build1 (NEGATE_EXPR, itype, l),
4877 fold_build1 (NEGATE_EXPR,
4878 itype, step));
4879 else
4880 l = fold_build2 (TRUNC_DIV_EXPR, itype, l, step);
acf0174b
JJ
4881 t = fold_build2 (MULT_EXPR, stept,
4882 fold_convert (stept, l), t);
da6f124d
JJ
4883
4884 if (OMP_CLAUSE_LINEAR_ARRAY (c))
4885 {
4886 x = lang_hooks.decls.omp_clause_linear_ctor
4887 (c, new_var, x, t);
4888 gimplify_and_add (x, ilist);
4889 goto do_dtor;
4890 }
4891
acf0174b
JJ
4892 if (POINTER_TYPE_P (TREE_TYPE (x)))
4893 x = fold_build2 (POINTER_PLUS_EXPR,
4894 TREE_TYPE (x), x, t);
4895 else
4896 x = fold_build2 (PLUS_EXPR, TREE_TYPE (x), x, t);
4897 }
4898
74bf76ed
JJ
4899 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
4900 || TREE_ADDRESSABLE (new_var))
4901 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4902 idx, lane, ivar, lvar))
4903 {
4904 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR)
4905 {
b731b390 4906 tree iv = create_tmp_var (TREE_TYPE (new_var));
74bf76ed
JJ
4907 x = lang_hooks.decls.omp_clause_copy_ctor (c, iv, x);
4908 gimplify_and_add (x, ilist);
4909 gimple_stmt_iterator gsi
4910 = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
538dd0b7 4911 gassign *g
74bf76ed
JJ
4912 = gimple_build_assign (unshare_expr (lvar), iv);
4913 gsi_insert_before_without_update (&gsi, g,
4914 GSI_SAME_STMT);
da6f124d 4915 tree t = OMP_CLAUSE_LINEAR_STEP (c);
74bf76ed
JJ
4916 enum tree_code code = PLUS_EXPR;
4917 if (POINTER_TYPE_P (TREE_TYPE (new_var)))
4918 code = POINTER_PLUS_EXPR;
0d0e4a03 4919 g = gimple_build_assign (iv, code, iv, t);
74bf76ed
JJ
4920 gsi_insert_before_without_update (&gsi, g,
4921 GSI_SAME_STMT);
4922 break;
4923 }
4924 x = lang_hooks.decls.omp_clause_copy_ctor
4925 (c, unshare_expr (ivar), x);
4926 gimplify_and_add (x, &llist[0]);
4927 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
4928 if (x)
4929 {
4930 gimple_seq tseq = NULL;
4931
4932 dtor = x;
4933 gimplify_stmt (&dtor, &tseq);
4934 gimple_seq_add_seq (&llist[1], tseq);
4935 }
4936 break;
4937 }
4938 }
d9a6bd32
JJ
4939 x = lang_hooks.decls.omp_clause_copy_ctor
4940 (c, unshare_expr (new_var), x);
953ff289
DN
4941 gimplify_and_add (x, ilist);
4942 goto do_dtor;
953ff289 4943
acf0174b 4944 case OMP_CLAUSE__LOOPTEMP_:
d9a6bd32 4945 gcc_assert (is_taskreg_ctx (ctx));
acf0174b
JJ
4946 x = build_outer_var_ref (var, ctx);
4947 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
4948 gimplify_and_add (x, ilist);
4949 break;
4950
953ff289 4951 case OMP_CLAUSE_COPYIN:
7c8f7639 4952 by_ref = use_pointer_for_field (var, NULL);
953ff289
DN
4953 x = build_receiver_ref (var, by_ref, ctx);
4954 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
4955 append_to_statement_list (x, &copyin_seq);
4956 copyin_by_ref |= by_ref;
4957 break;
4958
4959 case OMP_CLAUSE_REDUCTION:
e5014671
NS
4960 /* OpenACC reductions are initialized using the
4961 GOACC_REDUCTION internal function. */
4962 if (is_gimple_omp_oacc (ctx->stmt))
4963 break;
953ff289
DN
4964 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4965 {
a68ab351 4966 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
355fe088 4967 gimple *tseq;
a68ab351
JJ
4968 x = build_outer_var_ref (var, ctx);
4969
acf0174b
JJ
4970 if (is_reference (var)
4971 && !useless_type_conversion_p (TREE_TYPE (placeholder),
4972 TREE_TYPE (x)))
db3927fb 4973 x = build_fold_addr_expr_loc (clause_loc, x);
a68ab351
JJ
4974 SET_DECL_VALUE_EXPR (placeholder, x);
4975 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
acf0174b
JJ
4976 tree new_vard = new_var;
4977 if (is_reference (var))
4978 {
4979 gcc_assert (TREE_CODE (new_var) == MEM_REF);
4980 new_vard = TREE_OPERAND (new_var, 0);
4981 gcc_assert (DECL_P (new_vard));
4982 }
74bf76ed
JJ
4983 if (is_simd
4984 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4985 idx, lane, ivar, lvar))
4986 {
acf0174b
JJ
4987 if (new_vard == new_var)
4988 {
4989 gcc_assert (DECL_VALUE_EXPR (new_var) == lvar);
4990 SET_DECL_VALUE_EXPR (new_var, ivar);
4991 }
4992 else
4993 {
4994 SET_DECL_VALUE_EXPR (new_vard,
4995 build_fold_addr_expr (ivar));
4996 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
4997 }
4998 x = lang_hooks.decls.omp_clause_default_ctor
4999 (c, unshare_expr (ivar),
5000 build_outer_var_ref (var, ctx));
5001 if (x)
5002 gimplify_and_add (x, &llist[0]);
5003 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
5004 {
5005 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
5006 lower_omp (&tseq, ctx);
5007 gimple_seq_add_seq (&llist[0], tseq);
5008 }
5009 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
5010 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
5011 lower_omp (&tseq, ctx);
5012 gimple_seq_add_seq (&llist[1], tseq);
5013 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
5014 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
5015 if (new_vard == new_var)
5016 SET_DECL_VALUE_EXPR (new_var, lvar);
5017 else
5018 SET_DECL_VALUE_EXPR (new_vard,
5019 build_fold_addr_expr (lvar));
5020 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
5021 if (x)
5022 {
5023 tseq = NULL;
5024 dtor = x;
5025 gimplify_stmt (&dtor, &tseq);
5026 gimple_seq_add_seq (&llist[1], tseq);
5027 }
5028 break;
5029 }
4ceffa27
JJ
5030 /* If this is a reference to constant size reduction var
5031 with placeholder, we haven't emitted the initializer
5032 for it because it is undesirable if SIMD arrays are used.
5033 But if they aren't used, we need to emit the deferred
5034 initialization now. */
5035 else if (is_reference (var) && is_simd)
decaaec8 5036 handle_simd_reference (clause_loc, new_vard, ilist);
acf0174b 5037 x = lang_hooks.decls.omp_clause_default_ctor
92d28cbb
JJ
5038 (c, unshare_expr (new_var),
5039 build_outer_var_ref (var, ctx));
acf0174b
JJ
5040 if (x)
5041 gimplify_and_add (x, ilist);
5042 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
5043 {
5044 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
5045 lower_omp (&tseq, ctx);
5046 gimple_seq_add_seq (ilist, tseq);
5047 }
5048 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
5049 if (is_simd)
5050 {
5051 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
5052 lower_omp (&tseq, ctx);
5053 gimple_seq_add_seq (dlist, tseq);
5054 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
5055 }
5056 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
5057 goto do_dtor;
5058 }
5059 else
5060 {
5061 x = omp_reduction_init (c, TREE_TYPE (new_var));
5062 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
e9792e1d
JJ
5063 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
5064
5065 /* reduction(-:var) sums up the partial results, so it
5066 acts identically to reduction(+:var). */
5067 if (code == MINUS_EXPR)
5068 code = PLUS_EXPR;
5069
decaaec8
JJ
5070 tree new_vard = new_var;
5071 if (is_simd && is_reference (var))
5072 {
5073 gcc_assert (TREE_CODE (new_var) == MEM_REF);
5074 new_vard = TREE_OPERAND (new_var, 0);
5075 gcc_assert (DECL_P (new_vard));
5076 }
acf0174b
JJ
5077 if (is_simd
5078 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
5079 idx, lane, ivar, lvar))
5080 {
acf0174b
JJ
5081 tree ref = build_outer_var_ref (var, ctx);
5082
5083 gimplify_assign (unshare_expr (ivar), x, &llist[0]);
5084
acf0174b 5085 x = build2 (code, TREE_TYPE (ref), ref, ivar);
74bf76ed
JJ
5086 ref = build_outer_var_ref (var, ctx);
5087 gimplify_assign (ref, x, &llist[1]);
decaaec8
JJ
5088
5089 if (new_vard != new_var)
5090 {
5091 SET_DECL_VALUE_EXPR (new_vard,
5092 build_fold_addr_expr (lvar));
5093 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
5094 }
74bf76ed
JJ
5095 }
5096 else
5097 {
decaaec8
JJ
5098 if (is_reference (var) && is_simd)
5099 handle_simd_reference (clause_loc, new_vard, ilist);
74bf76ed
JJ
5100 gimplify_assign (new_var, x, ilist);
5101 if (is_simd)
e9792e1d
JJ
5102 {
5103 tree ref = build_outer_var_ref (var, ctx);
5104
5105 x = build2 (code, TREE_TYPE (ref), ref, new_var);
5106 ref = build_outer_var_ref (var, ctx);
5107 gimplify_assign (ref, x, dlist);
5108 }
74bf76ed 5109 }
953ff289
DN
5110 }
5111 break;
5112
5113 default:
5114 gcc_unreachable ();
5115 }
5116 }
5117 }
5118
74bf76ed
JJ
5119 if (lane)
5120 {
5121 tree uid = create_tmp_var (ptr_type_node, "simduid");
8928eff3
JJ
5122 /* Don't want uninit warnings on simduid, it is always uninitialized,
5123 but we use it not for the value, but for the DECL_UID only. */
5124 TREE_NO_WARNING (uid) = 1;
355fe088 5125 gimple *g
74bf76ed
JJ
5126 = gimple_build_call_internal (IFN_GOMP_SIMD_LANE, 1, uid);
5127 gimple_call_set_lhs (g, lane);
5128 gimple_stmt_iterator gsi = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
5129 gsi_insert_before_without_update (&gsi, g, GSI_SAME_STMT);
5130 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SIMDUID_);
5131 OMP_CLAUSE__SIMDUID__DECL (c) = uid;
5132 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
5133 gimple_omp_for_set_clauses (ctx->stmt, c);
0d0e4a03
JJ
5134 g = gimple_build_assign (lane, INTEGER_CST,
5135 build_int_cst (unsigned_type_node, 0));
74bf76ed
JJ
5136 gimple_seq_add_stmt (ilist, g);
5137 for (int i = 0; i < 2; i++)
5138 if (llist[i])
5139 {
b731b390 5140 tree vf = create_tmp_var (unsigned_type_node);
74bf76ed
JJ
5141 g = gimple_build_call_internal (IFN_GOMP_SIMD_VF, 1, uid);
5142 gimple_call_set_lhs (g, vf);
5143 gimple_seq *seq = i == 0 ? ilist : dlist;
5144 gimple_seq_add_stmt (seq, g);
5145 tree t = build_int_cst (unsigned_type_node, 0);
0d0e4a03 5146 g = gimple_build_assign (idx, INTEGER_CST, t);
74bf76ed
JJ
5147 gimple_seq_add_stmt (seq, g);
5148 tree body = create_artificial_label (UNKNOWN_LOCATION);
5149 tree header = create_artificial_label (UNKNOWN_LOCATION);
5150 tree end = create_artificial_label (UNKNOWN_LOCATION);
5151 gimple_seq_add_stmt (seq, gimple_build_goto (header));
5152 gimple_seq_add_stmt (seq, gimple_build_label (body));
5153 gimple_seq_add_seq (seq, llist[i]);
5154 t = build_int_cst (unsigned_type_node, 1);
0d0e4a03 5155 g = gimple_build_assign (idx, PLUS_EXPR, idx, t);
74bf76ed
JJ
5156 gimple_seq_add_stmt (seq, g);
5157 gimple_seq_add_stmt (seq, gimple_build_label (header));
5158 g = gimple_build_cond (LT_EXPR, idx, vf, body, end);
5159 gimple_seq_add_stmt (seq, g);
5160 gimple_seq_add_stmt (seq, gimple_build_label (end));
5161 }
5162 }
5163
953ff289
DN
5164 /* The copyin sequence is not to be executed by the main thread, since
5165 that would result in self-copies. Perhaps not visible to scalars,
5166 but it certainly is to C++ operator=. */
5167 if (copyin_seq)
5168 {
e79983f4
MM
5169 x = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM),
5170 0);
953ff289
DN
5171 x = build2 (NE_EXPR, boolean_type_node, x,
5172 build_int_cst (TREE_TYPE (x), 0));
5173 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
5174 gimplify_and_add (x, ilist);
5175 }
5176
5177 /* If any copyin variable is passed by reference, we must ensure the
5178 master thread doesn't modify it before it is copied over in all
8ca5b2a2
JJ
5179 threads. Similarly for variables in both firstprivate and
5180 lastprivate clauses we need to ensure the lastprivate copying
acf0174b
JJ
5181 happens after firstprivate copying in all threads. And similarly
5182 for UDRs if initializer expression refers to omp_orig. */
5183 if (copyin_by_ref || lastprivate_firstprivate || reduction_omp_orig_ref)
74bf76ed
JJ
5184 {
5185 /* Don't add any barrier for #pragma omp simd or
5186 #pragma omp distribute. */
5187 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
e2110f8f 5188 || gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_FOR)
acf0174b 5189 gimple_seq_add_stmt (ilist, build_omp_barrier (NULL_TREE));
74bf76ed
JJ
5190 }
5191
5192 /* If max_vf is non-zero, then we can use only a vectorization factor
5193 up to the max_vf we chose. So stick it into the safelen clause. */
5194 if (max_vf)
5195 {
5196 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
5197 OMP_CLAUSE_SAFELEN);
5198 if (c == NULL_TREE
b46ebd6c
JJ
5199 || (TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) == INTEGER_CST
5200 && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
5201 max_vf) == 1))
74bf76ed
JJ
5202 {
5203 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_SAFELEN);
5204 OMP_CLAUSE_SAFELEN_EXPR (c) = build_int_cst (integer_type_node,
5205 max_vf);
5206 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
5207 gimple_omp_for_set_clauses (ctx->stmt, c);
5208 }
5209 }
953ff289
DN
5210}
5211
50674e96 5212
953ff289
DN
5213/* Generate code to implement the LASTPRIVATE clauses. This is used for
5214 both parallel and workshare constructs. PREDICATE may be NULL if it's
5215 always true. */
5216
5217static void
726a989a 5218lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
acf0174b 5219 omp_context *ctx)
953ff289 5220{
74bf76ed 5221 tree x, c, label = NULL, orig_clauses = clauses;
a68ab351 5222 bool par_clauses = false;
74bf76ed 5223 tree simduid = NULL, lastlane = NULL;
953ff289 5224
74bf76ed
JJ
5225 /* Early exit if there are no lastprivate or linear clauses. */
5226 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
5227 if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LASTPRIVATE
5228 || (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LINEAR
5229 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses)))
5230 break;
953ff289
DN
5231 if (clauses == NULL)
5232 {
5233 /* If this was a workshare clause, see if it had been combined
5234 with its parallel. In that case, look for the clauses on the
5235 parallel statement itself. */
5236 if (is_parallel_ctx (ctx))
5237 return;
5238
5239 ctx = ctx->outer;
5240 if (ctx == NULL || !is_parallel_ctx (ctx))
5241 return;
5242
726a989a 5243 clauses = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
953ff289
DN
5244 OMP_CLAUSE_LASTPRIVATE);
5245 if (clauses == NULL)
5246 return;
a68ab351 5247 par_clauses = true;
953ff289
DN
5248 }
5249
726a989a
RB
5250 if (predicate)
5251 {
538dd0b7 5252 gcond *stmt;
726a989a
RB
5253 tree label_true, arm1, arm2;
5254
c2255bc4
AH
5255 label = create_artificial_label (UNKNOWN_LOCATION);
5256 label_true = create_artificial_label (UNKNOWN_LOCATION);
726a989a
RB
5257 arm1 = TREE_OPERAND (predicate, 0);
5258 arm2 = TREE_OPERAND (predicate, 1);
5259 gimplify_expr (&arm1, stmt_list, NULL, is_gimple_val, fb_rvalue);
5260 gimplify_expr (&arm2, stmt_list, NULL, is_gimple_val, fb_rvalue);
5261 stmt = gimple_build_cond (TREE_CODE (predicate), arm1, arm2,
5262 label_true, label);
5263 gimple_seq_add_stmt (stmt_list, stmt);
5264 gimple_seq_add_stmt (stmt_list, gimple_build_label (label_true));
5265 }
953ff289 5266
74bf76ed 5267 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
0aadce73 5268 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
74bf76ed
JJ
5269 {
5270 simduid = find_omp_clause (orig_clauses, OMP_CLAUSE__SIMDUID_);
5271 if (simduid)
5272 simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
5273 }
5274
a68ab351 5275 for (c = clauses; c ;)
953ff289
DN
5276 {
5277 tree var, new_var;
db3927fb 5278 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
953ff289 5279
74bf76ed
JJ
5280 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5281 || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
5282 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
a68ab351
JJ
5283 {
5284 var = OMP_CLAUSE_DECL (c);
d9a6bd32
JJ
5285 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5286 && OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c)
5287 && is_taskloop_ctx (ctx))
5288 {
5289 gcc_checking_assert (ctx->outer && is_task_ctx (ctx->outer));
5290 new_var = lookup_decl (var, ctx->outer);
5291 }
5292 else
5293 new_var = lookup_decl (var, ctx);
953ff289 5294
74bf76ed
JJ
5295 if (simduid && DECL_HAS_VALUE_EXPR_P (new_var))
5296 {
5297 tree val = DECL_VALUE_EXPR (new_var);
5298 if (TREE_CODE (val) == ARRAY_REF
5299 && VAR_P (TREE_OPERAND (val, 0))
5300 && lookup_attribute ("omp simd array",
5301 DECL_ATTRIBUTES (TREE_OPERAND (val,
5302 0))))
5303 {
5304 if (lastlane == NULL)
5305 {
b731b390 5306 lastlane = create_tmp_var (unsigned_type_node);
538dd0b7 5307 gcall *g
74bf76ed
JJ
5308 = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE,
5309 2, simduid,
5310 TREE_OPERAND (val, 1));
5311 gimple_call_set_lhs (g, lastlane);
5312 gimple_seq_add_stmt (stmt_list, g);
5313 }
5314 new_var = build4 (ARRAY_REF, TREE_TYPE (val),
5315 TREE_OPERAND (val, 0), lastlane,
5316 NULL_TREE, NULL_TREE);
5317 }
5318 }
5319
5320 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5321 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
726a989a 5322 {
355a7673 5323 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
726a989a
RB
5324 gimple_seq_add_seq (stmt_list,
5325 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
74bf76ed 5326 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) = NULL;
726a989a 5327 }
f7468577
JJ
5328 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
5329 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
5330 {
5331 lower_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
5332 gimple_seq_add_seq (stmt_list,
5333 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c));
5334 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c) = NULL;
5335 }
953ff289 5336
d9a6bd32
JJ
5337 x = NULL_TREE;
5338 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5339 && OMP_CLAUSE_LASTPRIVATE_TASKLOOP_IV (c))
5340 {
5341 gcc_checking_assert (is_taskloop_ctx (ctx));
5342 tree ovar = maybe_lookup_decl_in_outer_ctx (var,
5343 ctx->outer->outer);
5344 if (is_global_var (ovar))
5345 x = ovar;
5346 }
5347 if (!x)
5348 x = build_outer_var_ref (var, ctx, true);
a68ab351 5349 if (is_reference (var))
70f34814 5350 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
a68ab351 5351 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
726a989a 5352 gimplify_and_add (x, stmt_list);
a68ab351
JJ
5353 }
5354 c = OMP_CLAUSE_CHAIN (c);
5355 if (c == NULL && !par_clauses)
5356 {
5357 /* If this was a workshare clause, see if it had been combined
5358 with its parallel. In that case, continue looking for the
5359 clauses also on the parallel statement itself. */
5360 if (is_parallel_ctx (ctx))
5361 break;
5362
5363 ctx = ctx->outer;
5364 if (ctx == NULL || !is_parallel_ctx (ctx))
5365 break;
5366
726a989a 5367 c = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
a68ab351
JJ
5368 OMP_CLAUSE_LASTPRIVATE);
5369 par_clauses = true;
5370 }
953ff289
DN
5371 }
5372
726a989a
RB
5373 if (label)
5374 gimple_seq_add_stmt (stmt_list, gimple_build_label (label));
953ff289
DN
5375}
5376
e5014671
NS
5377/* Lower the OpenACC reductions of CLAUSES for compute axis LEVEL
5378 (which might be a placeholder). INNER is true if this is an inner
5379 axis of a multi-axis loop. FORK and JOIN are (optional) fork and
5380 join markers. Generate the before-loop forking sequence in
5381 FORK_SEQ and the after-loop joining sequence to JOIN_SEQ. The
5382 general form of these sequences is
5383
5384 GOACC_REDUCTION_SETUP
5385 GOACC_FORK
5386 GOACC_REDUCTION_INIT
5387 ...
5388 GOACC_REDUCTION_FINI
5389 GOACC_JOIN
5390 GOACC_REDUCTION_TEARDOWN. */
5391
41dbbb37 5392static void
e5014671
NS
5393lower_oacc_reductions (location_t loc, tree clauses, tree level, bool inner,
5394 gcall *fork, gcall *join, gimple_seq *fork_seq,
5395 gimple_seq *join_seq, omp_context *ctx)
41dbbb37 5396{
e5014671
NS
5397 gimple_seq before_fork = NULL;
5398 gimple_seq after_fork = NULL;
5399 gimple_seq before_join = NULL;
5400 gimple_seq after_join = NULL;
5401 tree init_code = NULL_TREE, fini_code = NULL_TREE,
5402 setup_code = NULL_TREE, teardown_code = NULL_TREE;
5403 unsigned offset = 0;
5404
5405 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
5406 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
5407 {
5408 tree orig = OMP_CLAUSE_DECL (c);
5409 tree var = maybe_lookup_decl (orig, ctx);
5410 tree ref_to_res = NULL_TREE;
5411 tree incoming, outgoing;
5412
5413 enum tree_code rcode = OMP_CLAUSE_REDUCTION_CODE (c);
5414 if (rcode == MINUS_EXPR)
5415 rcode = PLUS_EXPR;
5416 else if (rcode == TRUTH_ANDIF_EXPR)
5417 rcode = BIT_AND_EXPR;
5418 else if (rcode == TRUTH_ORIF_EXPR)
5419 rcode = BIT_IOR_EXPR;
5420 tree op = build_int_cst (unsigned_type_node, rcode);
5421
5422 if (!var)
5423 var = orig;
5424 gcc_assert (!is_reference (var));
5425
5426 incoming = outgoing = var;
5427
5428 if (!inner)
5429 {
5430 /* See if an outer construct also reduces this variable. */
5431 omp_context *outer = ctx;
41dbbb37 5432
e5014671
NS
5433 while (omp_context *probe = outer->outer)
5434 {
5435 enum gimple_code type = gimple_code (probe->stmt);
5436 tree cls;
41dbbb37 5437
e5014671
NS
5438 switch (type)
5439 {
5440 case GIMPLE_OMP_FOR:
5441 cls = gimple_omp_for_clauses (probe->stmt);
5442 break;
41dbbb37 5443
e5014671
NS
5444 case GIMPLE_OMP_TARGET:
5445 if (gimple_omp_target_kind (probe->stmt)
5446 != GF_OMP_TARGET_KIND_OACC_PARALLEL)
5447 goto do_lookup;
41dbbb37 5448
e5014671
NS
5449 cls = gimple_omp_target_clauses (probe->stmt);
5450 break;
41dbbb37 5451
e5014671
NS
5452 default:
5453 goto do_lookup;
5454 }
5455
5456 outer = probe;
5457 for (; cls; cls = OMP_CLAUSE_CHAIN (cls))
5458 if (OMP_CLAUSE_CODE (cls) == OMP_CLAUSE_REDUCTION
5459 && orig == OMP_CLAUSE_DECL (cls))
5460 goto has_outer_reduction;
5461 }
41dbbb37 5462
e5014671
NS
5463 do_lookup:
5464 /* This is the outermost construct with this reduction,
5465 see if there's a mapping for it. */
5466 if (gimple_code (outer->stmt) == GIMPLE_OMP_TARGET
5467 && maybe_lookup_field (orig, outer))
5468 {
5469 ref_to_res = build_receiver_ref (orig, false, outer);
5470 if (is_reference (orig))
5471 ref_to_res = build_simple_mem_ref (ref_to_res);
41dbbb37 5472
e5014671
NS
5473 outgoing = var;
5474 incoming = omp_reduction_init_op (loc, rcode, TREE_TYPE (var));
5475 }
5476 else
5477 incoming = outgoing = orig;
5478
5479 has_outer_reduction:;
5480 }
41dbbb37 5481
e5014671
NS
5482 if (!ref_to_res)
5483 ref_to_res = integer_zero_node;
41dbbb37 5484
e5014671
NS
5485 /* Determine position in reduction buffer, which may be used
5486 by target. */
5487 enum machine_mode mode = TYPE_MODE (TREE_TYPE (var));
5488 unsigned align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
5489 offset = (offset + align - 1) & ~(align - 1);
5490 tree off = build_int_cst (sizetype, offset);
5491 offset += GET_MODE_SIZE (mode);
41dbbb37 5492
e5014671
NS
5493 if (!init_code)
5494 {
5495 init_code = build_int_cst (integer_type_node,
5496 IFN_GOACC_REDUCTION_INIT);
5497 fini_code = build_int_cst (integer_type_node,
5498 IFN_GOACC_REDUCTION_FINI);
5499 setup_code = build_int_cst (integer_type_node,
5500 IFN_GOACC_REDUCTION_SETUP);
5501 teardown_code = build_int_cst (integer_type_node,
5502 IFN_GOACC_REDUCTION_TEARDOWN);
5503 }
5504
5505 tree setup_call
5506 = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
5507 TREE_TYPE (var), 6, setup_code,
5508 unshare_expr (ref_to_res),
5509 incoming, level, op, off);
5510 tree init_call
5511 = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
5512 TREE_TYPE (var), 6, init_code,
5513 unshare_expr (ref_to_res),
5514 var, level, op, off);
5515 tree fini_call
5516 = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
5517 TREE_TYPE (var), 6, fini_code,
5518 unshare_expr (ref_to_res),
5519 var, level, op, off);
5520 tree teardown_call
5521 = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
5522 TREE_TYPE (var), 6, teardown_code,
5523 ref_to_res, var, level, op, off);
5524
5525 gimplify_assign (var, setup_call, &before_fork);
5526 gimplify_assign (var, init_call, &after_fork);
5527 gimplify_assign (var, fini_call, &before_join);
5528 gimplify_assign (outgoing, teardown_call, &after_join);
5529 }
5530
5531 /* Now stitch things together. */
5532 gimple_seq_add_seq (fork_seq, before_fork);
5533 if (fork)
5534 gimple_seq_add_stmt (fork_seq, fork);
5535 gimple_seq_add_seq (fork_seq, after_fork);
5536
5537 gimple_seq_add_seq (join_seq, before_join);
5538 if (join)
5539 gimple_seq_add_stmt (join_seq, join);
5540 gimple_seq_add_seq (join_seq, after_join);
41dbbb37 5541}
50674e96 5542
953ff289
DN
5543/* Generate code to implement the REDUCTION clauses. */
5544
5545static void
726a989a 5546lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
953ff289 5547{
726a989a 5548 gimple_seq sub_seq = NULL;
355fe088 5549 gimple *stmt;
374d0225 5550 tree x, c;
953ff289
DN
5551 int count = 0;
5552
e5014671
NS
5553 /* OpenACC loop reductions are handled elsewhere. */
5554 if (is_gimple_omp_oacc (ctx->stmt))
5555 return;
5556
74bf76ed
JJ
5557 /* SIMD reductions are handled in lower_rec_input_clauses. */
5558 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
0aadce73 5559 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
74bf76ed
JJ
5560 return;
5561
953ff289
DN
5562 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
5563 update in that case, otherwise use a lock. */
5564 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
aaf46ef9 5565 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
953ff289 5566 {
d9a6bd32
JJ
5567 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
5568 || TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF)
953ff289 5569 {
acf0174b 5570 /* Never use OMP_ATOMIC for array reductions or UDRs. */
953ff289
DN
5571 count = -1;
5572 break;
5573 }
5574 count++;
5575 }
5576
5577 if (count == 0)
5578 return;
5579
5580 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
5581 {
d9a6bd32 5582 tree var, ref, new_var, orig_var;
953ff289 5583 enum tree_code code;
db3927fb 5584 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
953ff289 5585
aaf46ef9 5586 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
953ff289
DN
5587 continue;
5588
d9a6bd32
JJ
5589 orig_var = var = OMP_CLAUSE_DECL (c);
5590 if (TREE_CODE (var) == MEM_REF)
5591 {
5592 var = TREE_OPERAND (var, 0);
e01d41e5
JJ
5593 if (TREE_CODE (var) == POINTER_PLUS_EXPR)
5594 var = TREE_OPERAND (var, 0);
d9a6bd32
JJ
5595 if (TREE_CODE (var) == INDIRECT_REF
5596 || TREE_CODE (var) == ADDR_EXPR)
5597 var = TREE_OPERAND (var, 0);
5598 orig_var = var;
5599 if (is_variable_sized (var))
5600 {
5601 gcc_assert (DECL_HAS_VALUE_EXPR_P (var));
5602 var = DECL_VALUE_EXPR (var);
5603 gcc_assert (TREE_CODE (var) == INDIRECT_REF);
5604 var = TREE_OPERAND (var, 0);
5605 gcc_assert (DECL_P (var));
5606 }
5607 }
953ff289 5608 new_var = lookup_decl (var, ctx);
d9a6bd32 5609 if (var == OMP_CLAUSE_DECL (c) && is_reference (var))
70f34814 5610 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
953ff289
DN
5611 ref = build_outer_var_ref (var, ctx);
5612 code = OMP_CLAUSE_REDUCTION_CODE (c);
50674e96
DN
5613
5614 /* reduction(-:var) sums up the partial results, so it acts
5615 identically to reduction(+:var). */
953ff289
DN
5616 if (code == MINUS_EXPR)
5617 code = PLUS_EXPR;
5618
e5014671 5619 if (count == 1)
953ff289 5620 {
db3927fb 5621 tree addr = build_fold_addr_expr_loc (clause_loc, ref);
953ff289
DN
5622
5623 addr = save_expr (addr);
5624 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
db3927fb 5625 x = fold_build2_loc (clause_loc, code, TREE_TYPE (ref), ref, new_var);
953ff289 5626 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
726a989a 5627 gimplify_and_add (x, stmt_seqp);
953ff289
DN
5628 return;
5629 }
d9a6bd32
JJ
5630 else if (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF)
5631 {
5632 tree d = OMP_CLAUSE_DECL (c);
5633 tree type = TREE_TYPE (d);
5634 tree v = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
5635 tree i = create_tmp_var (TREE_TYPE (v), NULL);
5636 tree ptype = build_pointer_type (TREE_TYPE (type));
e01d41e5
JJ
5637 tree bias = TREE_OPERAND (d, 1);
5638 d = TREE_OPERAND (d, 0);
5639 if (TREE_CODE (d) == POINTER_PLUS_EXPR)
5640 {
5641 tree b = TREE_OPERAND (d, 1);
5642 b = maybe_lookup_decl (b, ctx);
5643 if (b == NULL)
5644 {
5645 b = TREE_OPERAND (d, 1);
5646 b = maybe_lookup_decl_in_outer_ctx (b, ctx);
5647 }
5648 if (integer_zerop (bias))
5649 bias = b;
5650 else
5651 {
5652 bias = fold_convert_loc (clause_loc, TREE_TYPE (b), bias);
5653 bias = fold_build2_loc (clause_loc, PLUS_EXPR,
5654 TREE_TYPE (b), b, bias);
5655 }
5656 d = TREE_OPERAND (d, 0);
5657 }
d9a6bd32
JJ
5658 /* For ref build_outer_var_ref already performs this, so
5659 only new_var needs a dereference. */
e01d41e5 5660 if (TREE_CODE (d) == INDIRECT_REF)
d9a6bd32
JJ
5661 {
5662 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
5663 gcc_assert (is_reference (var) && var == orig_var);
5664 }
e01d41e5 5665 else if (TREE_CODE (d) == ADDR_EXPR)
d9a6bd32
JJ
5666 {
5667 if (orig_var == var)
5668 {
5669 new_var = build_fold_addr_expr (new_var);
5670 ref = build_fold_addr_expr (ref);
5671 }
5672 }
5673 else
5674 {
5675 gcc_assert (orig_var == var);
5676 if (is_reference (var))
5677 ref = build_fold_addr_expr (ref);
5678 }
5679 if (DECL_P (v))
5680 {
5681 tree t = maybe_lookup_decl (v, ctx);
5682 if (t)
5683 v = t;
5684 else
5685 v = maybe_lookup_decl_in_outer_ctx (v, ctx);
5686 gimplify_expr (&v, stmt_seqp, NULL, is_gimple_val, fb_rvalue);
5687 }
e01d41e5
JJ
5688 if (!integer_zerop (bias))
5689 {
5690 bias = fold_convert_loc (clause_loc, sizetype, bias);
5691 new_var = fold_build2_loc (clause_loc, POINTER_PLUS_EXPR,
5692 TREE_TYPE (new_var), new_var,
5693 unshare_expr (bias));
5694 ref = fold_build2_loc (clause_loc, POINTER_PLUS_EXPR,
5695 TREE_TYPE (ref), ref, bias);
5696 }
d9a6bd32
JJ
5697 new_var = fold_convert_loc (clause_loc, ptype, new_var);
5698 ref = fold_convert_loc (clause_loc, ptype, ref);
5699 tree m = create_tmp_var (ptype, NULL);
5700 gimplify_assign (m, new_var, stmt_seqp);
5701 new_var = m;
5702 m = create_tmp_var (ptype, NULL);
5703 gimplify_assign (m, ref, stmt_seqp);
5704 ref = m;
5705 gimplify_assign (i, build_int_cst (TREE_TYPE (v), 0), stmt_seqp);
5706 tree body = create_artificial_label (UNKNOWN_LOCATION);
5707 tree end = create_artificial_label (UNKNOWN_LOCATION);
5708 gimple_seq_add_stmt (&sub_seq, gimple_build_label (body));
5709 tree priv = build_simple_mem_ref_loc (clause_loc, new_var);
5710 tree out = build_simple_mem_ref_loc (clause_loc, ref);
5711 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
5712 {
5713 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
5714 tree decl_placeholder
5715 = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c);
5716 SET_DECL_VALUE_EXPR (placeholder, out);
5717 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
5718 SET_DECL_VALUE_EXPR (decl_placeholder, priv);
5719 DECL_HAS_VALUE_EXPR_P (decl_placeholder) = 1;
5720 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
5721 gimple_seq_add_seq (&sub_seq,
5722 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
5723 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
5724 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
5725 OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c) = NULL;
5726 }
5727 else
5728 {
5729 x = build2 (code, TREE_TYPE (out), out, priv);
5730 out = unshare_expr (out);
5731 gimplify_assign (out, x, &sub_seq);
5732 }
5733 gimple *g = gimple_build_assign (new_var, POINTER_PLUS_EXPR, new_var,
5734 TYPE_SIZE_UNIT (TREE_TYPE (type)));
5735 gimple_seq_add_stmt (&sub_seq, g);
5736 g = gimple_build_assign (ref, POINTER_PLUS_EXPR, ref,
5737 TYPE_SIZE_UNIT (TREE_TYPE (type)));
5738 gimple_seq_add_stmt (&sub_seq, g);
5739 g = gimple_build_assign (i, PLUS_EXPR, i,
5740 build_int_cst (TREE_TYPE (i), 1));
5741 gimple_seq_add_stmt (&sub_seq, g);
5742 g = gimple_build_cond (LE_EXPR, i, v, body, end);
5743 gimple_seq_add_stmt (&sub_seq, g);
5744 gimple_seq_add_stmt (&sub_seq, gimple_build_label (end));
5745 }
41dbbb37 5746 else if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
953ff289
DN
5747 {
5748 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
5749
acf0174b
JJ
5750 if (is_reference (var)
5751 && !useless_type_conversion_p (TREE_TYPE (placeholder),
5752 TREE_TYPE (ref)))
db3927fb 5753 ref = build_fold_addr_expr_loc (clause_loc, ref);
953ff289
DN
5754 SET_DECL_VALUE_EXPR (placeholder, ref);
5755 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
355a7673 5756 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
726a989a
RB
5757 gimple_seq_add_seq (&sub_seq, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
5758 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
953ff289
DN
5759 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
5760 }
5761 else
5762 {
5763 x = build2 (code, TREE_TYPE (ref), ref, new_var);
5764 ref = build_outer_var_ref (var, ctx);
726a989a 5765 gimplify_assign (ref, x, &sub_seq);
953ff289
DN
5766 }
5767 }
5768
41dbbb37
TS
5769 if (is_gimple_omp_oacc (ctx->stmt))
5770 return;
5771
e79983f4
MM
5772 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START),
5773 0);
726a989a 5774 gimple_seq_add_stmt (stmt_seqp, stmt);
953ff289 5775
726a989a 5776 gimple_seq_add_seq (stmt_seqp, sub_seq);
953ff289 5777
e79983f4
MM
5778 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END),
5779 0);
726a989a 5780 gimple_seq_add_stmt (stmt_seqp, stmt);
953ff289
DN
5781}
5782
50674e96 5783
953ff289
DN
5784/* Generate code to implement the COPYPRIVATE clauses. */
5785
5786static void
726a989a 5787lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist,
953ff289
DN
5788 omp_context *ctx)
5789{
5790 tree c;
5791
5792 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
5793 {
78db7d92 5794 tree var, new_var, ref, x;
953ff289 5795 bool by_ref;
db3927fb 5796 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
953ff289 5797
aaf46ef9 5798 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
953ff289
DN
5799 continue;
5800
5801 var = OMP_CLAUSE_DECL (c);
7c8f7639 5802 by_ref = use_pointer_for_field (var, NULL);
953ff289
DN
5803
5804 ref = build_sender_ref (var, ctx);
78db7d92
JJ
5805 x = new_var = lookup_decl_in_outer_ctx (var, ctx);
5806 if (by_ref)
5807 {
5808 x = build_fold_addr_expr_loc (clause_loc, new_var);
5809 x = fold_convert_loc (clause_loc, TREE_TYPE (ref), x);
5810 }
726a989a 5811 gimplify_assign (ref, x, slist);
953ff289 5812
78db7d92
JJ
5813 ref = build_receiver_ref (var, false, ctx);
5814 if (by_ref)
5815 {
5816 ref = fold_convert_loc (clause_loc,
5817 build_pointer_type (TREE_TYPE (new_var)),
5818 ref);
5819 ref = build_fold_indirect_ref_loc (clause_loc, ref);
5820 }
953ff289
DN
5821 if (is_reference (var))
5822 {
78db7d92 5823 ref = fold_convert_loc (clause_loc, TREE_TYPE (new_var), ref);
70f34814
RG
5824 ref = build_simple_mem_ref_loc (clause_loc, ref);
5825 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
953ff289 5826 }
78db7d92 5827 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, ref);
953ff289
DN
5828 gimplify_and_add (x, rlist);
5829 }
5830}
5831
50674e96 5832
953ff289
DN
5833/* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
5834 and REDUCTION from the sender (aka parent) side. */
5835
5836static void
726a989a
RB
5837lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
5838 omp_context *ctx)
953ff289 5839{
d9a6bd32
JJ
5840 tree c, t;
5841 int ignored_looptemp = 0;
5842 bool is_taskloop = false;
5843
5844 /* For taskloop, ignore first two _looptemp_ clauses, those are initialized
5845 by GOMP_taskloop. */
5846 if (is_task_ctx (ctx) && gimple_omp_task_taskloop_p (ctx->stmt))
5847 {
5848 ignored_looptemp = 2;
5849 is_taskloop = true;
5850 }
953ff289
DN
5851
5852 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
5853 {
50674e96 5854 tree val, ref, x, var;
953ff289 5855 bool by_ref, do_in = false, do_out = false;
db3927fb 5856 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
953ff289 5857
aaf46ef9 5858 switch (OMP_CLAUSE_CODE (c))
953ff289 5859 {
a68ab351
JJ
5860 case OMP_CLAUSE_PRIVATE:
5861 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
5862 break;
5863 continue;
953ff289
DN
5864 case OMP_CLAUSE_FIRSTPRIVATE:
5865 case OMP_CLAUSE_COPYIN:
5866 case OMP_CLAUSE_LASTPRIVATE:
5867 case OMP_CLAUSE_REDUCTION:
d9a6bd32
JJ
5868 break;
5869 case OMP_CLAUSE_SHARED:
5870 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
5871 break;
5872 continue;
acf0174b 5873 case OMP_CLAUSE__LOOPTEMP_:
d9a6bd32
JJ
5874 if (ignored_looptemp)
5875 {
5876 ignored_looptemp--;
5877 continue;
5878 }
953ff289
DN
5879 break;
5880 default:
5881 continue;
5882 }
5883
d2dda7fe 5884 val = OMP_CLAUSE_DECL (c);
d9a6bd32
JJ
5885 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
5886 && TREE_CODE (val) == MEM_REF)
5887 {
5888 val = TREE_OPERAND (val, 0);
e01d41e5
JJ
5889 if (TREE_CODE (val) == POINTER_PLUS_EXPR)
5890 val = TREE_OPERAND (val, 0);
d9a6bd32
JJ
5891 if (TREE_CODE (val) == INDIRECT_REF
5892 || TREE_CODE (val) == ADDR_EXPR)
5893 val = TREE_OPERAND (val, 0);
5894 if (is_variable_sized (val))
5895 continue;
5896 }
5897
5898 /* For OMP_CLAUSE_SHARED_FIRSTPRIVATE, look beyond the
5899 outer taskloop region. */
5900 omp_context *ctx_for_o = ctx;
5901 if (is_taskloop
5902 && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
5903 && OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
5904 ctx_for_o = ctx->outer;
5905
5906 var = lookup_decl_in_outer_ctx (val, ctx_for_o);
50674e96 5907
8ca5b2a2
JJ
5908 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
5909 && is_global_var (var))
5910 continue;
d9a6bd32
JJ
5911
5912 t = omp_member_access_dummy_var (var);
5913 if (t)
5914 {
5915 var = DECL_VALUE_EXPR (var);
5916 tree o = maybe_lookup_decl_in_outer_ctx (t, ctx_for_o);
5917 if (o != t)
5918 var = unshare_and_remap (var, t, o);
5919 else
5920 var = unshare_expr (var);
5921 }
5922
5923 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED)
5924 {
5925 /* Handle taskloop firstprivate/lastprivate, where the
5926 lastprivate on GIMPLE_OMP_TASK is represented as
5927 OMP_CLAUSE_SHARED_FIRSTPRIVATE. */
5928 tree f = lookup_sfield ((splay_tree_key) &DECL_UID (val), ctx);
5929 x = omp_build_component_ref (ctx->sender_decl, f);
5930 if (use_pointer_for_field (val, ctx))
5931 var = build_fold_addr_expr (var);
5932 gimplify_assign (x, var, ilist);
5933 DECL_ABSTRACT_ORIGIN (f) = NULL;
5934 continue;
5935 }
5936
5937 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION
5938 || val == OMP_CLAUSE_DECL (c))
5939 && is_variable_sized (val))
953ff289 5940 continue;
7c8f7639 5941 by_ref = use_pointer_for_field (val, NULL);
953ff289 5942
aaf46ef9 5943 switch (OMP_CLAUSE_CODE (c))
953ff289 5944 {
a68ab351 5945 case OMP_CLAUSE_PRIVATE:
953ff289
DN
5946 case OMP_CLAUSE_FIRSTPRIVATE:
5947 case OMP_CLAUSE_COPYIN:
acf0174b 5948 case OMP_CLAUSE__LOOPTEMP_:
953ff289
DN
5949 do_in = true;
5950 break;
5951
5952 case OMP_CLAUSE_LASTPRIVATE:
5953 if (by_ref || is_reference (val))
5954 {
5955 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
5956 continue;
5957 do_in = true;
5958 }
5959 else
a68ab351
JJ
5960 {
5961 do_out = true;
5962 if (lang_hooks.decls.omp_private_outer_ref (val))
5963 do_in = true;
5964 }
953ff289
DN
5965 break;
5966
5967 case OMP_CLAUSE_REDUCTION:
5968 do_in = true;
d9a6bd32
JJ
5969 if (val == OMP_CLAUSE_DECL (c))
5970 do_out = !(by_ref || is_reference (val));
5971 else
5972 by_ref = TREE_CODE (TREE_TYPE (val)) == ARRAY_TYPE;
953ff289
DN
5973 break;
5974
5975 default:
5976 gcc_unreachable ();
5977 }
5978
5979 if (do_in)
5980 {
5981 ref = build_sender_ref (val, ctx);
db3927fb 5982 x = by_ref ? build_fold_addr_expr_loc (clause_loc, var) : var;
726a989a 5983 gimplify_assign (ref, x, ilist);
a68ab351
JJ
5984 if (is_task_ctx (ctx))
5985 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref, 1)) = NULL;
953ff289 5986 }
50674e96 5987
953ff289
DN
5988 if (do_out)
5989 {
5990 ref = build_sender_ref (val, ctx);
726a989a 5991 gimplify_assign (var, ref, olist);
953ff289
DN
5992 }
5993 }
5994}
5995
726a989a
RB
5996/* Generate code to implement SHARED from the sender (aka parent)
5997 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
5998 list things that got automatically shared. */
953ff289
DN
5999
6000static void
726a989a 6001lower_send_shared_vars (gimple_seq *ilist, gimple_seq *olist, omp_context *ctx)
953ff289 6002{
d9a6bd32 6003 tree var, ovar, nvar, t, f, x, record_type;
953ff289
DN
6004
6005 if (ctx->record_type == NULL)
6006 return;
50674e96 6007
a68ab351 6008 record_type = ctx->srecord_type ? ctx->srecord_type : ctx->record_type;
910ad8de 6009 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
953ff289
DN
6010 {
6011 ovar = DECL_ABSTRACT_ORIGIN (f);
d9a6bd32
JJ
6012 if (!ovar || TREE_CODE (ovar) == FIELD_DECL)
6013 continue;
6014
953ff289
DN
6015 nvar = maybe_lookup_decl (ovar, ctx);
6016 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
6017 continue;
6018
50674e96
DN
6019 /* If CTX is a nested parallel directive. Find the immediately
6020 enclosing parallel or workshare construct that contains a
6021 mapping for OVAR. */
d2dda7fe 6022 var = lookup_decl_in_outer_ctx (ovar, ctx);
50674e96 6023
d9a6bd32
JJ
6024 t = omp_member_access_dummy_var (var);
6025 if (t)
6026 {
6027 var = DECL_VALUE_EXPR (var);
6028 tree o = maybe_lookup_decl_in_outer_ctx (t, ctx);
6029 if (o != t)
6030 var = unshare_and_remap (var, t, o);
6031 else
6032 var = unshare_expr (var);
6033 }
6034
7c8f7639 6035 if (use_pointer_for_field (ovar, ctx))
953ff289
DN
6036 {
6037 x = build_sender_ref (ovar, ctx);
50674e96 6038 var = build_fold_addr_expr (var);
726a989a 6039 gimplify_assign (x, var, ilist);
953ff289
DN
6040 }
6041 else
6042 {
6043 x = build_sender_ref (ovar, ctx);
726a989a 6044 gimplify_assign (x, var, ilist);
953ff289 6045
14e5b285
RG
6046 if (!TREE_READONLY (var)
6047 /* We don't need to receive a new reference to a result
6048 or parm decl. In fact we may not store to it as we will
6049 invalidate any pending RSO and generate wrong gimple
6050 during inlining. */
6051 && !((TREE_CODE (var) == RESULT_DECL
6052 || TREE_CODE (var) == PARM_DECL)
6053 && DECL_BY_REFERENCE (var)))
a68ab351
JJ
6054 {
6055 x = build_sender_ref (ovar, ctx);
726a989a 6056 gimplify_assign (var, x, olist);
a68ab351 6057 }
953ff289
DN
6058 }
6059 }
6060}
6061
e4834818
NS
6062/* Emit an OpenACC head marker call, encapulating the partitioning and
6063 other information that must be processed by the target compiler.
6064 Return the maximum number of dimensions the associated loop might
6065 be partitioned over. */
6066
6067static unsigned
6068lower_oacc_head_mark (location_t loc, tree ddvar, tree clauses,
6069 gimple_seq *seq, omp_context *ctx)
6070{
6071 unsigned levels = 0;
6072 unsigned tag = 0;
6073 tree gang_static = NULL_TREE;
6074 auto_vec<tree, 5> args;
6075
6076 args.quick_push (build_int_cst
6077 (integer_type_node, IFN_UNIQUE_OACC_HEAD_MARK));
6078 args.quick_push (ddvar);
6079 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
6080 {
6081 switch (OMP_CLAUSE_CODE (c))
6082 {
6083 case OMP_CLAUSE_GANG:
6084 tag |= OLF_DIM_GANG;
6085 gang_static = OMP_CLAUSE_GANG_STATIC_EXPR (c);
6086 /* static:* is represented by -1, and we can ignore it, as
6087 scheduling is always static. */
6088 if (gang_static && integer_minus_onep (gang_static))
6089 gang_static = NULL_TREE;
6090 levels++;
6091 break;
6092
6093 case OMP_CLAUSE_WORKER:
6094 tag |= OLF_DIM_WORKER;
6095 levels++;
6096 break;
6097
6098 case OMP_CLAUSE_VECTOR:
6099 tag |= OLF_DIM_VECTOR;
6100 levels++;
6101 break;
6102
6103 case OMP_CLAUSE_SEQ:
6104 tag |= OLF_SEQ;
6105 break;
6106
6107 case OMP_CLAUSE_AUTO:
6108 tag |= OLF_AUTO;
6109 break;
6110
6111 case OMP_CLAUSE_INDEPENDENT:
6112 tag |= OLF_INDEPENDENT;
6113 break;
6114
6115 default:
6116 continue;
6117 }
6118 }
6119
6120 if (gang_static)
6121 {
6122 if (DECL_P (gang_static))
6123 gang_static = build_outer_var_ref (gang_static, ctx);
6124 tag |= OLF_GANG_STATIC;
6125 }
6126
6127 /* In a parallel region, loops are implicitly INDEPENDENT. */
6128 omp_context *tgt = enclosing_target_ctx (ctx);
6129 if (!tgt || is_oacc_parallel (tgt))
6130 tag |= OLF_INDEPENDENT;
6131
6132 /* A loop lacking SEQ, GANG, WORKER and/or VECTOR is implicitly AUTO. */
6133 if (!(tag & (((GOMP_DIM_MASK (GOMP_DIM_MAX) - 1) << OLF_DIM_BASE)
6134 | OLF_SEQ)))
6135 tag |= OLF_AUTO;
6136
6137 /* Ensure at least one level. */
6138 if (!levels)
6139 levels++;
6140
6141 args.quick_push (build_int_cst (integer_type_node, levels));
6142 args.quick_push (build_int_cst (integer_type_node, tag));
6143 if (gang_static)
6144 args.quick_push (gang_static);
6145
6146 gcall *call = gimple_build_call_internal_vec (IFN_UNIQUE, args);
6147 gimple_set_location (call, loc);
6148 gimple_set_lhs (call, ddvar);
6149 gimple_seq_add_stmt (seq, call);
6150
6151 return levels;
6152}
6153
6154/* Emit an OpenACC lopp head or tail marker to SEQ. LEVEL is the
6155 partitioning level of the enclosed region. */
6156
6157static void
6158lower_oacc_loop_marker (location_t loc, tree ddvar, bool head,
6159 tree tofollow, gimple_seq *seq)
6160{
6161 int marker_kind = (head ? IFN_UNIQUE_OACC_HEAD_MARK
6162 : IFN_UNIQUE_OACC_TAIL_MARK);
6163 tree marker = build_int_cst (integer_type_node, marker_kind);
6164 int nargs = 2 + (tofollow != NULL_TREE);
6165 gcall *call = gimple_build_call_internal (IFN_UNIQUE, nargs,
6166 marker, ddvar, tofollow);
6167 gimple_set_location (call, loc);
6168 gimple_set_lhs (call, ddvar);
6169 gimple_seq_add_stmt (seq, call);
6170}
6171
6172/* Generate the before and after OpenACC loop sequences. CLAUSES are
6173 the loop clauses, from which we extract reductions. Initialize
6174 HEAD and TAIL. */
6175
6176static void
6177lower_oacc_head_tail (location_t loc, tree clauses,
6178 gimple_seq *head, gimple_seq *tail, omp_context *ctx)
6179{
6180 bool inner = false;
6181 tree ddvar = create_tmp_var (integer_type_node, ".data_dep");
6182 gimple_seq_add_stmt (head, gimple_build_assign (ddvar, integer_zero_node));
6183
6184 unsigned count = lower_oacc_head_mark (loc, ddvar, clauses, head, ctx);
6185 if (!count)
6186 lower_oacc_loop_marker (loc, ddvar, false, integer_zero_node, tail);
6187
6188 tree fork_kind = build_int_cst (unsigned_type_node, IFN_UNIQUE_OACC_FORK);
6189 tree join_kind = build_int_cst (unsigned_type_node, IFN_UNIQUE_OACC_JOIN);
6190
6191 for (unsigned done = 1; count; count--, done++)
6192 {
6193 gimple_seq fork_seq = NULL;
6194 gimple_seq join_seq = NULL;
6195
6196 tree place = build_int_cst (integer_type_node, -1);
6197 gcall *fork = gimple_build_call_internal (IFN_UNIQUE, 3,
6198 fork_kind, ddvar, place);
6199 gimple_set_location (fork, loc);
6200 gimple_set_lhs (fork, ddvar);
6201
6202 gcall *join = gimple_build_call_internal (IFN_UNIQUE, 3,
6203 join_kind, ddvar, place);
6204 gimple_set_location (join, loc);
6205 gimple_set_lhs (join, ddvar);
6206
6207 /* Mark the beginning of this level sequence. */
6208 if (inner)
6209 lower_oacc_loop_marker (loc, ddvar, true,
6210 build_int_cst (integer_type_node, count),
6211 &fork_seq);
6212 lower_oacc_loop_marker (loc, ddvar, false,
6213 build_int_cst (integer_type_node, done),
6214 &join_seq);
6215
e5014671
NS
6216 lower_oacc_reductions (loc, clauses, place, inner,
6217 fork, join, &fork_seq, &join_seq, ctx);
e4834818
NS
6218
6219 /* Append this level to head. */
6220 gimple_seq_add_seq (head, fork_seq);
6221 /* Prepend it to tail. */
6222 gimple_seq_add_seq (&join_seq, *tail);
6223 *tail = join_seq;
6224
6225 inner = true;
6226 }
6227
6228 /* Mark the end of the sequence. */
6229 lower_oacc_loop_marker (loc, ddvar, true, NULL_TREE, head);
6230 lower_oacc_loop_marker (loc, ddvar, false, NULL_TREE, tail);
6231}
726a989a
RB
6232
6233/* A convenience function to build an empty GIMPLE_COND with just the
6234 condition. */
6235
538dd0b7 6236static gcond *
726a989a
RB
6237gimple_build_cond_empty (tree cond)
6238{
6239 enum tree_code pred_code;
6240 tree lhs, rhs;
6241
6242 gimple_cond_get_ops_from_tree (cond, &pred_code, &lhs, &rhs);
6243 return gimple_build_cond (pred_code, lhs, rhs, NULL_TREE, NULL_TREE);
6244}
6245
d9a6bd32
JJ
6246static void expand_omp_build_assign (gimple_stmt_iterator *, tree, tree,
6247 bool = false);
726a989a 6248
b8698a0f 6249/* Build the function calls to GOMP_parallel_start etc to actually
50674e96
DN
6250 generate the parallel operation. REGION is the parallel region
6251 being expanded. BB is the block where to insert the code. WS_ARGS
6252 will be set if this is a call to a combined parallel+workshare
6253 construct, it contains the list of additional arguments needed by
6254 the workshare construct. */
953ff289
DN
6255
6256static void
777f7f9a 6257expand_parallel_call (struct omp_region *region, basic_block bb,
538dd0b7
DM
6258 gomp_parallel *entry_stmt,
6259 vec<tree, va_gc> *ws_args)
953ff289 6260{
acf0174b 6261 tree t, t1, t2, val, cond, c, clauses, flags;
726a989a 6262 gimple_stmt_iterator gsi;
355fe088 6263 gimple *stmt;
e79983f4
MM
6264 enum built_in_function start_ix;
6265 int start_ix2;
db3927fb 6266 location_t clause_loc;
9771b263 6267 vec<tree, va_gc> *args;
50674e96 6268
726a989a 6269 clauses = gimple_omp_parallel_clauses (entry_stmt);
50674e96 6270
acf0174b 6271 /* Determine what flavor of GOMP_parallel we will be
50674e96 6272 emitting. */
acf0174b 6273 start_ix = BUILT_IN_GOMP_PARALLEL;
50674e96
DN
6274 if (is_combined_parallel (region))
6275 {
777f7f9a 6276 switch (region->inner->type)
50674e96 6277 {
726a989a 6278 case GIMPLE_OMP_FOR:
a68ab351 6279 gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
e01d41e5
JJ
6280 switch (region->inner->sched_kind)
6281 {
6282 case OMP_CLAUSE_SCHEDULE_RUNTIME:
6283 start_ix2 = 3;
6284 break;
6285 case OMP_CLAUSE_SCHEDULE_DYNAMIC:
6286 case OMP_CLAUSE_SCHEDULE_GUIDED:
6287 if (region->inner->sched_modifiers
6288 & OMP_CLAUSE_SCHEDULE_NONMONOTONIC)
6289 {
6290 start_ix2 = 3 + region->inner->sched_kind;
6291 break;
6292 }
6293 /* FALLTHRU */
6294 default:
6295 start_ix2 = region->inner->sched_kind;
6296 break;
6297 }
6298 start_ix2 += (int) BUILT_IN_GOMP_PARALLEL_LOOP_STATIC;
6299 start_ix = (enum built_in_function) start_ix2;
777f7f9a 6300 break;
726a989a 6301 case GIMPLE_OMP_SECTIONS:
acf0174b 6302 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS;
777f7f9a
RH
6303 break;
6304 default:
6305 gcc_unreachable ();
50674e96 6306 }
50674e96 6307 }
953ff289
DN
6308
6309 /* By default, the value of NUM_THREADS is zero (selected at run time)
6310 and there is no conditional. */
6311 cond = NULL_TREE;
6312 val = build_int_cst (unsigned_type_node, 0);
acf0174b 6313 flags = build_int_cst (unsigned_type_node, 0);
953ff289
DN
6314
6315 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
6316 if (c)
6317 cond = OMP_CLAUSE_IF_EXPR (c);
6318
6319 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
6320 if (c)
db3927fb
AH
6321 {
6322 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
6323 clause_loc = OMP_CLAUSE_LOCATION (c);
6324 }
6325 else
6326 clause_loc = gimple_location (entry_stmt);
953ff289 6327
acf0174b
JJ
6328 c = find_omp_clause (clauses, OMP_CLAUSE_PROC_BIND);
6329 if (c)
6330 flags = build_int_cst (unsigned_type_node, OMP_CLAUSE_PROC_BIND_KIND (c));
6331
953ff289 6332 /* Ensure 'val' is of the correct type. */
db3927fb 6333 val = fold_convert_loc (clause_loc, unsigned_type_node, val);
953ff289
DN
6334
6335 /* If we found the clause 'if (cond)', build either
6336 (cond != 0) or (cond ? val : 1u). */
6337 if (cond)
6338 {
50674e96
DN
6339 cond = gimple_boolify (cond);
6340
953ff289 6341 if (integer_zerop (val))
db3927fb
AH
6342 val = fold_build2_loc (clause_loc,
6343 EQ_EXPR, unsigned_type_node, cond,
917948d3 6344 build_int_cst (TREE_TYPE (cond), 0));
953ff289 6345 else
50674e96
DN
6346 {
6347 basic_block cond_bb, then_bb, else_bb;
917948d3 6348 edge e, e_then, e_else;
726a989a 6349 tree tmp_then, tmp_else, tmp_join, tmp_var;
917948d3 6350
b731b390 6351 tmp_var = create_tmp_var (TREE_TYPE (val));
917948d3
ZD
6352 if (gimple_in_ssa_p (cfun))
6353 {
b731b390
JJ
6354 tmp_then = make_ssa_name (tmp_var);
6355 tmp_else = make_ssa_name (tmp_var);
6356 tmp_join = make_ssa_name (tmp_var);
917948d3
ZD
6357 }
6358 else
6359 {
6360 tmp_then = tmp_var;
6361 tmp_else = tmp_var;
6362 tmp_join = tmp_var;
6363 }
50674e96 6364
c4d281b2 6365 e = split_block_after_labels (bb);
50674e96
DN
6366 cond_bb = e->src;
6367 bb = e->dest;
6368 remove_edge (e);
6369
6370 then_bb = create_empty_bb (cond_bb);
6371 else_bb = create_empty_bb (then_bb);
917948d3
ZD
6372 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
6373 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
50674e96 6374
726a989a
RB
6375 stmt = gimple_build_cond_empty (cond);
6376 gsi = gsi_start_bb (cond_bb);
6377 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
50674e96 6378
726a989a 6379 gsi = gsi_start_bb (then_bb);
d9a6bd32 6380 expand_omp_build_assign (&gsi, tmp_then, val, true);
50674e96 6381
726a989a 6382 gsi = gsi_start_bb (else_bb);
d9a6bd32
JJ
6383 expand_omp_build_assign (&gsi, tmp_else,
6384 build_int_cst (unsigned_type_node, 1),
6385 true);
50674e96
DN
6386
6387 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
6388 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
726338f4
RB
6389 add_bb_to_loop (then_bb, cond_bb->loop_father);
6390 add_bb_to_loop (else_bb, cond_bb->loop_father);
917948d3
ZD
6391 e_then = make_edge (then_bb, bb, EDGE_FALLTHRU);
6392 e_else = make_edge (else_bb, bb, EDGE_FALLTHRU);
50674e96 6393
917948d3
ZD
6394 if (gimple_in_ssa_p (cfun))
6395 {
538dd0b7 6396 gphi *phi = create_phi_node (tmp_join, bb);
9e227d60
DC
6397 add_phi_arg (phi, tmp_then, e_then, UNKNOWN_LOCATION);
6398 add_phi_arg (phi, tmp_else, e_else, UNKNOWN_LOCATION);
917948d3
ZD
6399 }
6400
6401 val = tmp_join;
50674e96
DN
6402 }
6403
726a989a
RB
6404 gsi = gsi_start_bb (bb);
6405 val = force_gimple_operand_gsi (&gsi, val, true, NULL_TREE,
6406 false, GSI_CONTINUE_LINKING);
953ff289
DN
6407 }
6408
726a989a
RB
6409 gsi = gsi_last_bb (bb);
6410 t = gimple_omp_parallel_data_arg (entry_stmt);
953ff289 6411 if (t == NULL)
5039610b 6412 t1 = null_pointer_node;
953ff289 6413 else
5039610b 6414 t1 = build_fold_addr_expr (t);
726a989a 6415 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
50674e96 6416
acf0174b 6417 vec_alloc (args, 4 + vec_safe_length (ws_args));
9771b263
DN
6418 args->quick_push (t2);
6419 args->quick_push (t1);
6420 args->quick_push (val);
6421 if (ws_args)
6422 args->splice (*ws_args);
acf0174b 6423 args->quick_push (flags);
3bb06db4
NF
6424
6425 t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
e79983f4 6426 builtin_decl_explicit (start_ix), args);
50674e96 6427
726a989a
RB
6428 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6429 false, GSI_CONTINUE_LINKING);
953ff289
DN
6430}
6431
9a771876
JJ
6432/* Insert a function call whose name is FUNC_NAME with the information from
6433 ENTRY_STMT into the basic_block BB. */
6434
6435static void
538dd0b7 6436expand_cilk_for_call (basic_block bb, gomp_parallel *entry_stmt,
9a771876
JJ
6437 vec <tree, va_gc> *ws_args)
6438{
6439 tree t, t1, t2;
6440 gimple_stmt_iterator gsi;
6441 vec <tree, va_gc> *args;
6442
6443 gcc_assert (vec_safe_length (ws_args) == 2);
6444 tree func_name = (*ws_args)[0];
6445 tree grain = (*ws_args)[1];
6446
6447 tree clauses = gimple_omp_parallel_clauses (entry_stmt);
6448 tree count = find_omp_clause (clauses, OMP_CLAUSE__CILK_FOR_COUNT_);
6449 gcc_assert (count != NULL_TREE);
6450 count = OMP_CLAUSE_OPERAND (count, 0);
6451
6452 gsi = gsi_last_bb (bb);
6453 t = gimple_omp_parallel_data_arg (entry_stmt);
6454 if (t == NULL)
6455 t1 = null_pointer_node;
6456 else
6457 t1 = build_fold_addr_expr (t);
6458 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
6459
6460 vec_alloc (args, 4);
6461 args->quick_push (t2);
6462 args->quick_push (t1);
6463 args->quick_push (count);
6464 args->quick_push (grain);
6465 t = build_call_expr_loc_vec (UNKNOWN_LOCATION, func_name, args);
6466
6467 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, false,
6468 GSI_CONTINUE_LINKING);
6469}
50674e96 6470
a68ab351
JJ
6471/* Build the function call to GOMP_task to actually
6472 generate the task operation. BB is the block where to insert the code. */
6473
6474static void
d9a6bd32
JJ
6475expand_task_call (struct omp_region *region, basic_block bb,
6476 gomp_task *entry_stmt)
a68ab351 6477{
d9a6bd32 6478 tree t1, t2, t3;
726a989a 6479 gimple_stmt_iterator gsi;
db3927fb 6480 location_t loc = gimple_location (entry_stmt);
a68ab351 6481
d9a6bd32
JJ
6482 tree clauses = gimple_omp_task_clauses (entry_stmt);
6483
6484 tree ifc = find_omp_clause (clauses, OMP_CLAUSE_IF);
6485 tree untied = find_omp_clause (clauses, OMP_CLAUSE_UNTIED);
6486 tree mergeable = find_omp_clause (clauses, OMP_CLAUSE_MERGEABLE);
6487 tree depend = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
6488 tree finalc = find_omp_clause (clauses, OMP_CLAUSE_FINAL);
6489 tree priority = find_omp_clause (clauses, OMP_CLAUSE_PRIORITY);
6490
6491 unsigned int iflags
6492 = (untied ? GOMP_TASK_FLAG_UNTIED : 0)
6493 | (mergeable ? GOMP_TASK_FLAG_MERGEABLE : 0)
6494 | (depend ? GOMP_TASK_FLAG_DEPEND : 0);
6495
6496 bool taskloop_p = gimple_omp_task_taskloop_p (entry_stmt);
6497 tree startvar = NULL_TREE, endvar = NULL_TREE, step = NULL_TREE;
6498 tree num_tasks = NULL_TREE;
6499 bool ull = false;
6500 if (taskloop_p)
6501 {
6502 gimple *g = last_stmt (region->outer->entry);
6503 gcc_assert (gimple_code (g) == GIMPLE_OMP_FOR
6504 && gimple_omp_for_kind (g) == GF_OMP_FOR_KIND_TASKLOOP);
6505 struct omp_for_data fd;
6506 extract_omp_for_data (as_a <gomp_for *> (g), &fd, NULL);
6507 startvar = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
6508 endvar = find_omp_clause (OMP_CLAUSE_CHAIN (startvar),
6509 OMP_CLAUSE__LOOPTEMP_);
6510 startvar = OMP_CLAUSE_DECL (startvar);
6511 endvar = OMP_CLAUSE_DECL (endvar);
6512 step = fold_convert_loc (loc, fd.iter_type, fd.loop.step);
6513 if (fd.loop.cond_code == LT_EXPR)
6514 iflags |= GOMP_TASK_FLAG_UP;
6515 tree tclauses = gimple_omp_for_clauses (g);
6516 num_tasks = find_omp_clause (tclauses, OMP_CLAUSE_NUM_TASKS);
6517 if (num_tasks)
6518 num_tasks = OMP_CLAUSE_NUM_TASKS_EXPR (num_tasks);
6519 else
6520 {
6521 num_tasks = find_omp_clause (tclauses, OMP_CLAUSE_GRAINSIZE);
6522 if (num_tasks)
6523 {
6524 iflags |= GOMP_TASK_FLAG_GRAINSIZE;
6525 num_tasks = OMP_CLAUSE_GRAINSIZE_EXPR (num_tasks);
6526 }
6527 else
6528 num_tasks = integer_zero_node;
6529 }
6530 num_tasks = fold_convert_loc (loc, long_integer_type_node, num_tasks);
6531 if (ifc == NULL_TREE)
6532 iflags |= GOMP_TASK_FLAG_IF;
6533 if (find_omp_clause (tclauses, OMP_CLAUSE_NOGROUP))
6534 iflags |= GOMP_TASK_FLAG_NOGROUP;
6535 ull = fd.iter_type == long_long_unsigned_type_node;
6536 }
6537 else if (priority)
6538 iflags |= GOMP_TASK_FLAG_PRIORITY;
a68ab351 6539
d9a6bd32 6540 tree flags = build_int_cst (unsigned_type_node, iflags);
a68ab351 6541
d9a6bd32
JJ
6542 tree cond = boolean_true_node;
6543 if (ifc)
6544 {
6545 if (taskloop_p)
6546 {
6547 tree t = gimple_boolify (OMP_CLAUSE_IF_EXPR (ifc));
6548 t = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, t,
6549 build_int_cst (unsigned_type_node,
6550 GOMP_TASK_FLAG_IF),
6551 build_int_cst (unsigned_type_node, 0));
6552 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node,
6553 flags, t);
6554 }
6555 else
6556 cond = gimple_boolify (OMP_CLAUSE_IF_EXPR (ifc));
6557 }
20906c66 6558
d9a6bd32 6559 if (finalc)
20906c66 6560 {
d9a6bd32
JJ
6561 tree t = gimple_boolify (OMP_CLAUSE_FINAL_EXPR (finalc));
6562 t = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, t,
6563 build_int_cst (unsigned_type_node,
6564 GOMP_TASK_FLAG_FINAL),
20906c66 6565 build_int_cst (unsigned_type_node, 0));
d9a6bd32 6566 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node, flags, t);
20906c66 6567 }
acf0174b
JJ
6568 if (depend)
6569 depend = OMP_CLAUSE_DECL (depend);
6570 else
6571 depend = build_int_cst (ptr_type_node, 0);
d9a6bd32
JJ
6572 if (priority)
6573 priority = fold_convert (integer_type_node,
6574 OMP_CLAUSE_PRIORITY_EXPR (priority));
6575 else
6576 priority = integer_zero_node;
a68ab351 6577
726a989a 6578 gsi = gsi_last_bb (bb);
d9a6bd32 6579 tree t = gimple_omp_task_data_arg (entry_stmt);
a68ab351
JJ
6580 if (t == NULL)
6581 t2 = null_pointer_node;
6582 else
db3927fb
AH
6583 t2 = build_fold_addr_expr_loc (loc, t);
6584 t1 = build_fold_addr_expr_loc (loc, gimple_omp_task_child_fn (entry_stmt));
726a989a 6585 t = gimple_omp_task_copy_fn (entry_stmt);
a68ab351
JJ
6586 if (t == NULL)
6587 t3 = null_pointer_node;
6588 else
db3927fb 6589 t3 = build_fold_addr_expr_loc (loc, t);
a68ab351 6590
d9a6bd32
JJ
6591 if (taskloop_p)
6592 t = build_call_expr (ull
6593 ? builtin_decl_explicit (BUILT_IN_GOMP_TASKLOOP_ULL)
6594 : builtin_decl_explicit (BUILT_IN_GOMP_TASKLOOP),
6595 11, t1, t2, t3,
6596 gimple_omp_task_arg_size (entry_stmt),
6597 gimple_omp_task_arg_align (entry_stmt), flags,
6598 num_tasks, priority, startvar, endvar, step);
6599 else
6600 t = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK),
6601 9, t1, t2, t3,
6602 gimple_omp_task_arg_size (entry_stmt),
6603 gimple_omp_task_arg_align (entry_stmt), cond, flags,
6604 depend, priority);
a68ab351 6605
726a989a
RB
6606 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6607 false, GSI_CONTINUE_LINKING);
a68ab351
JJ
6608}
6609
6610
726a989a
RB
6611/* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
6612 catch handler and return it. This prevents programs from violating the
6613 structured block semantics with throws. */
953ff289 6614
726a989a
RB
6615static gimple_seq
6616maybe_catch_exception (gimple_seq body)
953ff289 6617{
355fe088 6618 gimple *g;
1d65f45c 6619 tree decl;
953ff289
DN
6620
6621 if (!flag_exceptions)
726a989a 6622 return body;
953ff289 6623
3b06d379
SB
6624 if (lang_hooks.eh_protect_cleanup_actions != NULL)
6625 decl = lang_hooks.eh_protect_cleanup_actions ();
953ff289 6626 else
e79983f4 6627 decl = builtin_decl_explicit (BUILT_IN_TRAP);
726a989a 6628
1d65f45c
RH
6629 g = gimple_build_eh_must_not_throw (decl);
6630 g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g),
726a989a 6631 GIMPLE_TRY_CATCH);
953ff289 6632
1d65f45c 6633 return gimple_seq_alloc_with_stmt (g);
953ff289
DN
6634}
6635
50674e96 6636/* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
953ff289 6637
50674e96 6638static tree
9771b263 6639vec2chain (vec<tree, va_gc> *v)
953ff289 6640{
c021f10b
NF
6641 tree chain = NULL_TREE, t;
6642 unsigned ix;
953ff289 6643
9771b263 6644 FOR_EACH_VEC_SAFE_ELT_REVERSE (v, ix, t)
50674e96 6645 {
910ad8de 6646 DECL_CHAIN (t) = chain;
c021f10b 6647 chain = t;
50674e96 6648 }
953ff289 6649
c021f10b 6650 return chain;
50674e96 6651}
953ff289 6652
953ff289 6653
50674e96 6654/* Remove barriers in REGION->EXIT's block. Note that this is only
726a989a
RB
6655 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
6656 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
6657 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
50674e96 6658 removed. */
953ff289 6659
50674e96
DN
6660static void
6661remove_exit_barrier (struct omp_region *region)
6662{
726a989a 6663 gimple_stmt_iterator gsi;
50674e96 6664 basic_block exit_bb;
777f7f9a
RH
6665 edge_iterator ei;
6666 edge e;
355fe088 6667 gimple *stmt;
03742a9b 6668 int any_addressable_vars = -1;
953ff289 6669
777f7f9a 6670 exit_bb = region->exit;
953ff289 6671
2aee3e57
JJ
6672 /* If the parallel region doesn't return, we don't have REGION->EXIT
6673 block at all. */
6674 if (! exit_bb)
6675 return;
6676
726a989a
RB
6677 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
6678 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
777f7f9a
RH
6679 statements that can appear in between are extremely limited -- no
6680 memory operations at all. Here, we allow nothing at all, so the
726a989a
RB
6681 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
6682 gsi = gsi_last_bb (exit_bb);
6683 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
6684 gsi_prev (&gsi);
6685 if (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
50674e96 6686 return;
953ff289 6687
777f7f9a
RH
6688 FOR_EACH_EDGE (e, ei, exit_bb->preds)
6689 {
726a989a
RB
6690 gsi = gsi_last_bb (e->src);
6691 if (gsi_end_p (gsi))
777f7f9a 6692 continue;
726a989a 6693 stmt = gsi_stmt (gsi);
03742a9b
JJ
6694 if (gimple_code (stmt) == GIMPLE_OMP_RETURN
6695 && !gimple_omp_return_nowait_p (stmt))
6696 {
6697 /* OpenMP 3.0 tasks unfortunately prevent this optimization
6698 in many cases. If there could be tasks queued, the barrier
6699 might be needed to let the tasks run before some local
6700 variable of the parallel that the task uses as shared
6701 runs out of scope. The task can be spawned either
6702 from within current function (this would be easy to check)
6703 or from some function it calls and gets passed an address
6704 of such a variable. */
6705 if (any_addressable_vars < 0)
6706 {
538dd0b7
DM
6707 gomp_parallel *parallel_stmt
6708 = as_a <gomp_parallel *> (last_stmt (region->entry));
03742a9b 6709 tree child_fun = gimple_omp_parallel_child_fn (parallel_stmt);
c021f10b
NF
6710 tree local_decls, block, decl;
6711 unsigned ix;
03742a9b
JJ
6712
6713 any_addressable_vars = 0;
c021f10b
NF
6714 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun), ix, decl)
6715 if (TREE_ADDRESSABLE (decl))
03742a9b
JJ
6716 {
6717 any_addressable_vars = 1;
6718 break;
6719 }
6720 for (block = gimple_block (stmt);
6721 !any_addressable_vars
6722 && block
6723 && TREE_CODE (block) == BLOCK;
6724 block = BLOCK_SUPERCONTEXT (block))
6725 {
6726 for (local_decls = BLOCK_VARS (block);
6727 local_decls;
910ad8de 6728 local_decls = DECL_CHAIN (local_decls))
03742a9b
JJ
6729 if (TREE_ADDRESSABLE (local_decls))
6730 {
6731 any_addressable_vars = 1;
6732 break;
6733 }
6734 if (block == gimple_block (parallel_stmt))
6735 break;
6736 }
6737 }
6738 if (!any_addressable_vars)
6739 gimple_omp_return_set_nowait (stmt);
6740 }
777f7f9a 6741 }
953ff289
DN
6742}
6743
777f7f9a
RH
6744static void
6745remove_exit_barriers (struct omp_region *region)
6746{
726a989a 6747 if (region->type == GIMPLE_OMP_PARALLEL)
777f7f9a
RH
6748 remove_exit_barrier (region);
6749
6750 if (region->inner)
6751 {
6752 region = region->inner;
6753 remove_exit_barriers (region);
6754 while (region->next)
6755 {
6756 region = region->next;
6757 remove_exit_barriers (region);
6758 }
6759 }
6760}
50674e96 6761
2b4cf991
JJ
6762/* Optimize omp_get_thread_num () and omp_get_num_threads ()
6763 calls. These can't be declared as const functions, but
6764 within one parallel body they are constant, so they can be
6765 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
a68ab351
JJ
6766 which are declared const. Similarly for task body, except
6767 that in untied task omp_get_thread_num () can change at any task
6768 scheduling point. */
2b4cf991
JJ
6769
6770static void
355fe088 6771optimize_omp_library_calls (gimple *entry_stmt)
2b4cf991
JJ
6772{
6773 basic_block bb;
726a989a 6774 gimple_stmt_iterator gsi;
e79983f4
MM
6775 tree thr_num_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
6776 tree thr_num_id = DECL_ASSEMBLER_NAME (thr_num_tree);
6777 tree num_thr_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
6778 tree num_thr_id = DECL_ASSEMBLER_NAME (num_thr_tree);
726a989a
RB
6779 bool untied_task = (gimple_code (entry_stmt) == GIMPLE_OMP_TASK
6780 && find_omp_clause (gimple_omp_task_clauses (entry_stmt),
a68ab351 6781 OMP_CLAUSE_UNTIED) != NULL);
2b4cf991 6782
11cd3bed 6783 FOR_EACH_BB_FN (bb, cfun)
726a989a 6784 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
2b4cf991 6785 {
355fe088 6786 gimple *call = gsi_stmt (gsi);
2b4cf991
JJ
6787 tree decl;
6788
726a989a
RB
6789 if (is_gimple_call (call)
6790 && (decl = gimple_call_fndecl (call))
2b4cf991
JJ
6791 && DECL_EXTERNAL (decl)
6792 && TREE_PUBLIC (decl)
6793 && DECL_INITIAL (decl) == NULL)
6794 {
6795 tree built_in;
6796
6797 if (DECL_NAME (decl) == thr_num_id)
a68ab351
JJ
6798 {
6799 /* In #pragma omp task untied omp_get_thread_num () can change
6800 during the execution of the task region. */
6801 if (untied_task)
6802 continue;
e79983f4 6803 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
a68ab351 6804 }
2b4cf991 6805 else if (DECL_NAME (decl) == num_thr_id)
e79983f4 6806 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
2b4cf991
JJ
6807 else
6808 continue;
6809
6810 if (DECL_ASSEMBLER_NAME (decl) != DECL_ASSEMBLER_NAME (built_in)
726a989a 6811 || gimple_call_num_args (call) != 0)
2b4cf991
JJ
6812 continue;
6813
6814 if (flag_exceptions && !TREE_NOTHROW (decl))
6815 continue;
6816
6817 if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
9600efe1
MM
6818 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl)),
6819 TREE_TYPE (TREE_TYPE (built_in))))
2b4cf991
JJ
6820 continue;
6821
7c9577be 6822 gimple_call_set_fndecl (call, built_in);
2b4cf991
JJ
6823 }
6824 }
6825}
6826
5a0f4dd3
JJ
6827/* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
6828 regimplified. */
6829
6830static tree
6831expand_omp_regimplify_p (tree *tp, int *walk_subtrees, void *)
6832{
6833 tree t = *tp;
6834
6835 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
6836 if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t))
6837 return t;
6838
6839 if (TREE_CODE (t) == ADDR_EXPR)
6840 recompute_tree_invariant_for_addr_expr (t);
6841
6842 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
6843 return NULL_TREE;
6844}
6845
d9a6bd32 6846/* Prepend or append TO = FROM assignment before or after *GSI_P. */
74bf76ed
JJ
6847
6848static void
d9a6bd32
JJ
6849expand_omp_build_assign (gimple_stmt_iterator *gsi_p, tree to, tree from,
6850 bool after)
74bf76ed
JJ
6851{
6852 bool simple_p = DECL_P (to) && TREE_ADDRESSABLE (to);
6853 from = force_gimple_operand_gsi (gsi_p, from, simple_p, NULL_TREE,
d9a6bd32
JJ
6854 !after, after ? GSI_CONTINUE_LINKING
6855 : GSI_SAME_STMT);
355fe088 6856 gimple *stmt = gimple_build_assign (to, from);
d9a6bd32
JJ
6857 if (after)
6858 gsi_insert_after (gsi_p, stmt, GSI_CONTINUE_LINKING);
6859 else
6860 gsi_insert_before (gsi_p, stmt, GSI_SAME_STMT);
74bf76ed
JJ
6861 if (walk_tree (&from, expand_omp_regimplify_p, NULL, NULL)
6862 || walk_tree (&to, expand_omp_regimplify_p, NULL, NULL))
6863 {
6864 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
6865 gimple_regimplify_operands (stmt, &gsi);
6866 }
6867}
6868
a68ab351 6869/* Expand the OpenMP parallel or task directive starting at REGION. */
953ff289
DN
6870
6871static void
a68ab351 6872expand_omp_taskreg (struct omp_region *region)
953ff289 6873{
50674e96 6874 basic_block entry_bb, exit_bb, new_bb;
db2960f4 6875 struct function *child_cfun;
3bb06db4 6876 tree child_fn, block, t;
726a989a 6877 gimple_stmt_iterator gsi;
355fe088 6878 gimple *entry_stmt, *stmt;
50674e96 6879 edge e;
9771b263 6880 vec<tree, va_gc> *ws_args;
50674e96 6881
777f7f9a 6882 entry_stmt = last_stmt (region->entry);
726a989a 6883 child_fn = gimple_omp_taskreg_child_fn (entry_stmt);
50674e96 6884 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
50674e96 6885
777f7f9a 6886 entry_bb = region->entry;
b37dddbc
JJ
6887 if (gimple_code (entry_stmt) == GIMPLE_OMP_TASK)
6888 exit_bb = region->cont;
6889 else
6890 exit_bb = region->exit;
50674e96 6891
9a771876
JJ
6892 bool is_cilk_for
6893 = (flag_cilkplus
6894 && gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL
6895 && find_omp_clause (gimple_omp_parallel_clauses (entry_stmt),
6896 OMP_CLAUSE__CILK_FOR_COUNT_) != NULL_TREE);
6897
6898 if (is_cilk_for)
6899 /* If it is a _Cilk_for statement, it is modelled *like* a parallel for,
6900 and the inner statement contains the name of the built-in function
6901 and grain. */
6902 ws_args = region->inner->ws_args;
6903 else if (is_combined_parallel (region))
777f7f9a 6904 ws_args = region->ws_args;
50674e96 6905 else
3bb06db4 6906 ws_args = NULL;
953ff289 6907
777f7f9a 6908 if (child_cfun->cfg)
953ff289 6909 {
50674e96
DN
6910 /* Due to inlining, it may happen that we have already outlined
6911 the region, in which case all we need to do is make the
6912 sub-graph unreachable and emit the parallel call. */
6913 edge entry_succ_e, exit_succ_e;
50674e96
DN
6914
6915 entry_succ_e = single_succ_edge (entry_bb);
50674e96 6916
726a989a
RB
6917 gsi = gsi_last_bb (entry_bb);
6918 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_PARALLEL
6919 || gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_TASK);
6920 gsi_remove (&gsi, true);
50674e96
DN
6921
6922 new_bb = entry_bb;
d3c673c7
JJ
6923 if (exit_bb)
6924 {
6925 exit_succ_e = single_succ_edge (exit_bb);
6926 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
6927 }
917948d3 6928 remove_edge_and_dominated_blocks (entry_succ_e);
953ff289 6929 }
50674e96
DN
6930 else
6931 {
2fed2012 6932 unsigned srcidx, dstidx, num;
c021f10b 6933
50674e96 6934 /* If the parallel region needs data sent from the parent
b570947c
JJ
6935 function, then the very first statement (except possible
6936 tree profile counter updates) of the parallel body
50674e96
DN
6937 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
6938 &.OMP_DATA_O is passed as an argument to the child function,
6939 we need to replace it with the argument as seen by the child
6940 function.
6941
6942 In most cases, this will end up being the identity assignment
6943 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
6944 a function call that has been inlined, the original PARM_DECL
6945 .OMP_DATA_I may have been converted into a different local
6946 variable. In which case, we need to keep the assignment. */
726a989a 6947 if (gimple_omp_taskreg_data_arg (entry_stmt))
50674e96 6948 {
b37dddbc
JJ
6949 basic_block entry_succ_bb
6950 = single_succ_p (entry_bb) ? single_succ (entry_bb)
6951 : FALLTHRU_EDGE (entry_bb)->dest;
2eddac76 6952 tree arg;
355fe088 6953 gimple *parcopy_stmt = NULL;
953ff289 6954
726a989a 6955 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
b570947c 6956 {
355fe088 6957 gimple *stmt;
b570947c 6958
726a989a
RB
6959 gcc_assert (!gsi_end_p (gsi));
6960 stmt = gsi_stmt (gsi);
6961 if (gimple_code (stmt) != GIMPLE_ASSIGN)
018b899b
JJ
6962 continue;
6963
726a989a 6964 if (gimple_num_ops (stmt) == 2)
b570947c 6965 {
726a989a
RB
6966 tree arg = gimple_assign_rhs1 (stmt);
6967
6968 /* We're ignore the subcode because we're
6969 effectively doing a STRIP_NOPS. */
6970
6971 if (TREE_CODE (arg) == ADDR_EXPR
6972 && TREE_OPERAND (arg, 0)
6973 == gimple_omp_taskreg_data_arg (entry_stmt))
6974 {
6975 parcopy_stmt = stmt;
6976 break;
6977 }
b570947c
JJ
6978 }
6979 }
917948d3 6980
726a989a 6981 gcc_assert (parcopy_stmt != NULL);
917948d3
ZD
6982 arg = DECL_ARGUMENTS (child_fn);
6983
6984 if (!gimple_in_ssa_p (cfun))
6985 {
726a989a
RB
6986 if (gimple_assign_lhs (parcopy_stmt) == arg)
6987 gsi_remove (&gsi, true);
917948d3 6988 else
726a989a
RB
6989 {
6990 /* ?? Is setting the subcode really necessary ?? */
6991 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (arg));
6992 gimple_assign_set_rhs1 (parcopy_stmt, arg);
6993 }
917948d3
ZD
6994 }
6995 else
6996 {
2eddac76
TV
6997 tree lhs = gimple_assign_lhs (parcopy_stmt);
6998 gcc_assert (SSA_NAME_VAR (lhs) == arg);
6999 /* We'd like to set the rhs to the default def in the child_fn,
7000 but it's too early to create ssa names in the child_fn.
7001 Instead, we set the rhs to the parm. In
7002 move_sese_region_to_fn, we introduce a default def for the
7003 parm, map the parm to it's default def, and once we encounter
7004 this stmt, replace the parm with the default def. */
7005 gimple_assign_set_rhs1 (parcopy_stmt, arg);
917948d3
ZD
7006 update_stmt (parcopy_stmt);
7007 }
50674e96
DN
7008 }
7009
7010 /* Declare local variables needed in CHILD_CFUN. */
7011 block = DECL_INITIAL (child_fn);
c021f10b 7012 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
4f0ae266
JJ
7013 /* The gimplifier could record temporaries in parallel/task block
7014 rather than in containing function's local_decls chain,
7015 which would mean cgraph missed finalizing them. Do it now. */
910ad8de 7016 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
4f0ae266
JJ
7017 if (TREE_CODE (t) == VAR_DECL
7018 && TREE_STATIC (t)
7019 && !DECL_EXTERNAL (t))
9041d2e6 7020 varpool_node::finalize_decl (t);
726a989a 7021 DECL_SAVED_TREE (child_fn) = NULL;
355a7673
MM
7022 /* We'll create a CFG for child_fn, so no gimple body is needed. */
7023 gimple_set_body (child_fn, NULL);
b357f682 7024 TREE_USED (block) = 1;
50674e96 7025
917948d3 7026 /* Reset DECL_CONTEXT on function arguments. */
910ad8de 7027 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
50674e96
DN
7028 DECL_CONTEXT (t) = child_fn;
7029
726a989a
RB
7030 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
7031 so that it can be moved to the child function. */
7032 gsi = gsi_last_bb (entry_bb);
7033 stmt = gsi_stmt (gsi);
7034 gcc_assert (stmt && (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
7035 || gimple_code (stmt) == GIMPLE_OMP_TASK));
726a989a 7036 e = split_block (entry_bb, stmt);
b13c907a 7037 gsi_remove (&gsi, true);
50674e96 7038 entry_bb = e->dest;
b37dddbc
JJ
7039 edge e2 = NULL;
7040 if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
7041 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7042 else
7043 {
7044 e2 = make_edge (e->src, BRANCH_EDGE (entry_bb)->dest, EDGE_ABNORMAL);
7045 gcc_assert (e2->dest == region->exit);
7046 remove_edge (BRANCH_EDGE (entry_bb));
7047 set_immediate_dominator (CDI_DOMINATORS, e2->dest, e->src);
7048 gsi = gsi_last_bb (region->exit);
7049 gcc_assert (!gsi_end_p (gsi)
7050 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
7051 gsi_remove (&gsi, true);
7052 }
50674e96 7053
b37dddbc 7054 /* Convert GIMPLE_OMP_{RETURN,CONTINUE} into a RETURN_EXPR. */
2aee3e57
JJ
7055 if (exit_bb)
7056 {
726a989a
RB
7057 gsi = gsi_last_bb (exit_bb);
7058 gcc_assert (!gsi_end_p (gsi)
b37dddbc
JJ
7059 && (gimple_code (gsi_stmt (gsi))
7060 == (e2 ? GIMPLE_OMP_CONTINUE : GIMPLE_OMP_RETURN)));
726a989a
RB
7061 stmt = gimple_build_return (NULL);
7062 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
7063 gsi_remove (&gsi, true);
2aee3e57 7064 }
917948d3
ZD
7065
7066 /* Move the parallel region into CHILD_CFUN. */
b8698a0f 7067
917948d3
ZD
7068 if (gimple_in_ssa_p (cfun))
7069 {
5db9ba0c 7070 init_tree_ssa (child_cfun);
3828719a
RG
7071 init_ssa_operands (child_cfun);
7072 child_cfun->gimple_df->in_ssa_p = true;
b357f682 7073 block = NULL_TREE;
917948d3 7074 }
b357f682 7075 else
726a989a 7076 block = gimple_block (entry_stmt);
b357f682
JJ
7077
7078 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
917948d3
ZD
7079 if (exit_bb)
7080 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
b37dddbc
JJ
7081 if (e2)
7082 {
7083 basic_block dest_bb = e2->dest;
7084 if (!exit_bb)
7085 make_edge (new_bb, dest_bb, EDGE_FALLTHRU);
7086 remove_edge (e2);
7087 set_immediate_dominator (CDI_DOMINATORS, dest_bb, new_bb);
7088 }
6093bc06
RB
7089 /* When the OMP expansion process cannot guarantee an up-to-date
7090 loop tree arrange for the child function to fixup loops. */
7091 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
7092 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
917948d3 7093
b357f682 7094 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
9771b263 7095 num = vec_safe_length (child_cfun->local_decls);
2fed2012
JJ
7096 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
7097 {
9771b263 7098 t = (*child_cfun->local_decls)[srcidx];
2fed2012
JJ
7099 if (DECL_CONTEXT (t) == cfun->decl)
7100 continue;
7101 if (srcidx != dstidx)
9771b263 7102 (*child_cfun->local_decls)[dstidx] = t;
2fed2012
JJ
7103 dstidx++;
7104 }
7105 if (dstidx != num)
9771b263 7106 vec_safe_truncate (child_cfun->local_decls, dstidx);
b357f682 7107
917948d3 7108 /* Inform the callgraph about the new function. */
8c8b9f32
JJ
7109 child_cfun->curr_properties = cfun->curr_properties;
7110 child_cfun->has_simduid_loops |= cfun->has_simduid_loops;
7111 child_cfun->has_force_vectorize_loops |= cfun->has_force_vectorize_loops;
edafad14
TV
7112 cgraph_node *node = cgraph_node::get_create (child_fn);
7113 node->parallelized_function = 1;
d52f5295 7114 cgraph_node::add_new_function (child_fn, true);
917948d3 7115
e01d41e5
JJ
7116 bool need_asm = DECL_ASSEMBLER_NAME_SET_P (current_function_decl)
7117 && !DECL_ASSEMBLER_NAME_SET_P (child_fn);
7118
917948d3
ZD
7119 /* Fix the callgraph edges for child_cfun. Those for cfun will be
7120 fixed in a following pass. */
7121 push_cfun (child_cfun);
e01d41e5
JJ
7122 if (need_asm)
7123 assign_assembler_name_if_neeeded (child_fn);
7124
2b4cf991 7125 if (optimize)
a68ab351 7126 optimize_omp_library_calls (entry_stmt);
3dafb85c 7127 cgraph_edge::rebuild_edges ();
99819c63
JJ
7128
7129 /* Some EH regions might become dead, see PR34608. If
7130 pass_cleanup_cfg isn't the first pass to happen with the
7131 new child, these dead EH edges might cause problems.
7132 Clean them up now. */
7133 if (flag_exceptions)
7134 {
7135 basic_block bb;
99819c63
JJ
7136 bool changed = false;
7137
11cd3bed 7138 FOR_EACH_BB_FN (bb, cfun)
726a989a 7139 changed |= gimple_purge_dead_eh_edges (bb);
99819c63
JJ
7140 if (changed)
7141 cleanup_tree_cfg ();
99819c63 7142 }
5006671f
RG
7143 if (gimple_in_ssa_p (cfun))
7144 update_ssa (TODO_update_ssa);
b2b29377 7145 if (flag_checking && !loops_state_satisfies_p (LOOPS_NEED_FIXUP))
e67d7a1e 7146 verify_loop_structure ();
917948d3 7147 pop_cfun ();
e01d41e5
JJ
7148
7149 if (dump_file && !gimple_in_ssa_p (cfun))
7150 {
7151 omp_any_child_fn_dumped = true;
7152 dump_function_header (dump_file, child_fn, dump_flags);
7153 dump_function_to_file (child_fn, dump_file, dump_flags);
7154 }
50674e96 7155 }
b8698a0f 7156
50674e96 7157 /* Emit a library call to launch the children threads. */
9a771876 7158 if (is_cilk_for)
538dd0b7
DM
7159 expand_cilk_for_call (new_bb,
7160 as_a <gomp_parallel *> (entry_stmt), ws_args);
9a771876 7161 else if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
538dd0b7
DM
7162 expand_parallel_call (region, new_bb,
7163 as_a <gomp_parallel *> (entry_stmt), ws_args);
a68ab351 7164 else
d9a6bd32 7165 expand_task_call (region, new_bb, as_a <gomp_task *> (entry_stmt));
a5efada7
RG
7166 if (gimple_in_ssa_p (cfun))
7167 update_ssa (TODO_update_ssa_only_virtuals);
953ff289
DN
7168}
7169
e4834818
NS
7170/* Information about members of an OpenACC collapsed loop nest. */
7171
7172struct oacc_collapse
7173{
7174 tree base; /* Base value. */
7175 tree iters; /* Number of steps. */
7176 tree step; /* step size. */
7177};
7178
7179/* Helper for expand_oacc_for. Determine collapsed loop information.
7180 Fill in COUNTS array. Emit any initialization code before GSI.
7181 Return the calculated outer loop bound of BOUND_TYPE. */
7182
7183static tree
7184expand_oacc_collapse_init (const struct omp_for_data *fd,
7185 gimple_stmt_iterator *gsi,
7186 oacc_collapse *counts, tree bound_type)
7187{
7188 tree total = build_int_cst (bound_type, 1);
7189 int ix;
7190
7191 gcc_assert (integer_onep (fd->loop.step));
7192 gcc_assert (integer_zerop (fd->loop.n1));
7193
7194 for (ix = 0; ix != fd->collapse; ix++)
7195 {
7196 const omp_for_data_loop *loop = &fd->loops[ix];
7197
7198 tree iter_type = TREE_TYPE (loop->v);
7199 tree diff_type = iter_type;
7200 tree plus_type = iter_type;
7201
7202 gcc_assert (loop->cond_code == fd->loop.cond_code);
7203
7204 if (POINTER_TYPE_P (iter_type))
7205 plus_type = sizetype;
7206 if (POINTER_TYPE_P (diff_type) || TYPE_UNSIGNED (diff_type))
7207 diff_type = signed_type_for (diff_type);
7208
7209 tree b = loop->n1;
7210 tree e = loop->n2;
7211 tree s = loop->step;
7212 bool up = loop->cond_code == LT_EXPR;
7213 tree dir = build_int_cst (diff_type, up ? +1 : -1);
7214 bool negating;
7215 tree expr;
7216
7217 b = force_gimple_operand_gsi (gsi, b, true, NULL_TREE,
7218 true, GSI_SAME_STMT);
7219 e = force_gimple_operand_gsi (gsi, e, true, NULL_TREE,
7220 true, GSI_SAME_STMT);
7221
7222 /* Convert the step, avoiding possible unsigned->signed overflow. */
7223 negating = !up && TYPE_UNSIGNED (TREE_TYPE (s));
7224 if (negating)
7225 s = fold_build1 (NEGATE_EXPR, TREE_TYPE (s), s);
7226 s = fold_convert (diff_type, s);
7227 if (negating)
7228 s = fold_build1 (NEGATE_EXPR, diff_type, s);
7229 s = force_gimple_operand_gsi (gsi, s, true, NULL_TREE,
7230 true, GSI_SAME_STMT);
7231
7232 /* Determine the range, avoiding possible unsigned->signed overflow. */
7233 negating = !up && TYPE_UNSIGNED (iter_type);
7234 expr = fold_build2 (MINUS_EXPR, plus_type,
7235 fold_convert (plus_type, negating ? b : e),
7236 fold_convert (plus_type, negating ? e : b));
7237 expr = fold_convert (diff_type, expr);
7238 if (negating)
7239 expr = fold_build1 (NEGATE_EXPR, diff_type, expr);
7240 tree range = force_gimple_operand_gsi
7241 (gsi, expr, true, NULL_TREE, true, GSI_SAME_STMT);
7242
7243 /* Determine number of iterations. */
7244 expr = fold_build2 (MINUS_EXPR, diff_type, range, dir);
7245 expr = fold_build2 (PLUS_EXPR, diff_type, expr, s);
7246 expr = fold_build2 (TRUNC_DIV_EXPR, diff_type, expr, s);
7247
7248 tree iters = force_gimple_operand_gsi (gsi, expr, true, NULL_TREE,
7249 true, GSI_SAME_STMT);
7250
7251 counts[ix].base = b;
7252 counts[ix].iters = iters;
7253 counts[ix].step = s;
7254
7255 total = fold_build2 (MULT_EXPR, bound_type, total,
7256 fold_convert (bound_type, iters));
7257 }
7258
7259 return total;
7260}
7261
7262/* Emit initializers for collapsed loop members. IVAR is the outer
7263 loop iteration variable, from which collapsed loop iteration values
7264 are calculated. COUNTS array has been initialized by
7265 expand_oacc_collapse_inits. */
7266
7267static void
7268expand_oacc_collapse_vars (const struct omp_for_data *fd,
7269 gimple_stmt_iterator *gsi,
7270 const oacc_collapse *counts, tree ivar)
7271{
7272 tree ivar_type = TREE_TYPE (ivar);
7273
7274 /* The most rapidly changing iteration variable is the innermost
7275 one. */
7276 for (int ix = fd->collapse; ix--;)
7277 {
7278 const omp_for_data_loop *loop = &fd->loops[ix];
7279 const oacc_collapse *collapse = &counts[ix];
7280 tree iter_type = TREE_TYPE (loop->v);
7281 tree diff_type = TREE_TYPE (collapse->step);
7282 tree plus_type = iter_type;
7283 enum tree_code plus_code = PLUS_EXPR;
7284 tree expr;
7285
7286 if (POINTER_TYPE_P (iter_type))
7287 {
7288 plus_code = POINTER_PLUS_EXPR;
7289 plus_type = sizetype;
7290 }
7291
7292 expr = fold_build2 (TRUNC_MOD_EXPR, ivar_type, ivar,
7293 fold_convert (ivar_type, collapse->iters));
7294 expr = fold_build2 (MULT_EXPR, diff_type, fold_convert (diff_type, expr),
7295 collapse->step);
7296 expr = fold_build2 (plus_code, iter_type, collapse->base,
7297 fold_convert (plus_type, expr));
7298 expr = force_gimple_operand_gsi (gsi, expr, false, NULL_TREE,
7299 true, GSI_SAME_STMT);
7300 gassign *ass = gimple_build_assign (loop->v, expr);
7301 gsi_insert_before (gsi, ass, GSI_SAME_STMT);
7302
7303 if (ix)
7304 {
7305 expr = fold_build2 (TRUNC_DIV_EXPR, ivar_type, ivar,
7306 fold_convert (ivar_type, collapse->iters));
7307 ivar = force_gimple_operand_gsi (gsi, expr, true, NULL_TREE,
7308 true, GSI_SAME_STMT);
7309 }
7310 }
7311}
7312
50674e96 7313
74bf76ed
JJ
7314/* Helper function for expand_omp_{for_*,simd}. If this is the outermost
7315 of the combined collapse > 1 loop constructs, generate code like:
7316 if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
7317 if (cond3 is <)
7318 adj = STEP3 - 1;
7319 else
7320 adj = STEP3 + 1;
7321 count3 = (adj + N32 - N31) / STEP3;
7322 if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
7323 if (cond2 is <)
7324 adj = STEP2 - 1;
7325 else
7326 adj = STEP2 + 1;
7327 count2 = (adj + N22 - N21) / STEP2;
7328 if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
7329 if (cond1 is <)
7330 adj = STEP1 - 1;
7331 else
7332 adj = STEP1 + 1;
7333 count1 = (adj + N12 - N11) / STEP1;
7334 count = count1 * count2 * count3;
7335 Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
7336 count = 0;
acf0174b
JJ
7337 and set ZERO_ITER_BB to that bb. If this isn't the outermost
7338 of the combined loop constructs, just initialize COUNTS array
7339 from the _looptemp_ clauses. */
74bf76ed
JJ
7340
7341/* NOTE: It *could* be better to moosh all of the BBs together,
7342 creating one larger BB with all the computation and the unexpected
7343 jump at the end. I.e.
7344
7345 bool zero3, zero2, zero1, zero;
7346
7347 zero3 = N32 c3 N31;
7348 count3 = (N32 - N31) /[cl] STEP3;
7349 zero2 = N22 c2 N21;
7350 count2 = (N22 - N21) /[cl] STEP2;
7351 zero1 = N12 c1 N11;
7352 count1 = (N12 - N11) /[cl] STEP1;
7353 zero = zero3 || zero2 || zero1;
7354 count = count1 * count2 * count3;
7355 if (__builtin_expect(zero, false)) goto zero_iter_bb;
7356
7357 After all, we expect the zero=false, and thus we expect to have to
7358 evaluate all of the comparison expressions, so short-circuiting
7359 oughtn't be a win. Since the condition isn't protecting a
7360 denominator, we're not concerned about divide-by-zero, so we can
7361 fully evaluate count even if a numerator turned out to be wrong.
7362
7363 It seems like putting this all together would create much better
7364 scheduling opportunities, and less pressure on the chip's branch
7365 predictor. */
7366
7367static void
7368expand_omp_for_init_counts (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
7369 basic_block &entry_bb, tree *counts,
d9a6bd32
JJ
7370 basic_block &zero_iter1_bb, int &first_zero_iter1,
7371 basic_block &zero_iter2_bb, int &first_zero_iter2,
74bf76ed
JJ
7372 basic_block &l2_dom_bb)
7373{
7374 tree t, type = TREE_TYPE (fd->loop.v);
74bf76ed
JJ
7375 edge e, ne;
7376 int i;
7377
7378 /* Collapsed loops need work for expansion into SSA form. */
7379 gcc_assert (!gimple_in_ssa_p (cfun));
7380
acf0174b
JJ
7381 if (gimple_omp_for_combined_into_p (fd->for_stmt)
7382 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
7383 {
d9a6bd32 7384 gcc_assert (fd->ordered == 0);
acf0174b
JJ
7385 /* First two _looptemp_ clauses are for istart/iend, counts[0]
7386 isn't supposed to be handled, as the inner loop doesn't
7387 use it. */
7388 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7389 OMP_CLAUSE__LOOPTEMP_);
7390 gcc_assert (innerc);
7391 for (i = 0; i < fd->collapse; i++)
7392 {
7393 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7394 OMP_CLAUSE__LOOPTEMP_);
7395 gcc_assert (innerc);
7396 if (i)
7397 counts[i] = OMP_CLAUSE_DECL (innerc);
7398 else
7399 counts[0] = NULL_TREE;
7400 }
7401 return;
7402 }
7403
d9a6bd32
JJ
7404 for (i = fd->collapse; i < fd->ordered; i++)
7405 {
7406 tree itype = TREE_TYPE (fd->loops[i].v);
7407 counts[i] = NULL_TREE;
7408 t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
7409 fold_convert (itype, fd->loops[i].n1),
7410 fold_convert (itype, fd->loops[i].n2));
7411 if (t && integer_zerop (t))
7412 {
7413 for (i = fd->collapse; i < fd->ordered; i++)
7414 counts[i] = build_int_cst (type, 0);
7415 break;
7416 }
7417 }
7418 for (i = 0; i < (fd->ordered ? fd->ordered : fd->collapse); i++)
74bf76ed
JJ
7419 {
7420 tree itype = TREE_TYPE (fd->loops[i].v);
7421
d9a6bd32
JJ
7422 if (i >= fd->collapse && counts[i])
7423 continue;
7424 if ((SSA_VAR_P (fd->loop.n2) || i >= fd->collapse)
74bf76ed
JJ
7425 && ((t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
7426 fold_convert (itype, fd->loops[i].n1),
7427 fold_convert (itype, fd->loops[i].n2)))
7428 == NULL_TREE || !integer_onep (t)))
7429 {
538dd0b7 7430 gcond *cond_stmt;
74bf76ed
JJ
7431 tree n1, n2;
7432 n1 = fold_convert (itype, unshare_expr (fd->loops[i].n1));
7433 n1 = force_gimple_operand_gsi (gsi, n1, true, NULL_TREE,
7434 true, GSI_SAME_STMT);
7435 n2 = fold_convert (itype, unshare_expr (fd->loops[i].n2));
7436 n2 = force_gimple_operand_gsi (gsi, n2, true, NULL_TREE,
7437 true, GSI_SAME_STMT);
538dd0b7
DM
7438 cond_stmt = gimple_build_cond (fd->loops[i].cond_code, n1, n2,
7439 NULL_TREE, NULL_TREE);
7440 gsi_insert_before (gsi, cond_stmt, GSI_SAME_STMT);
7441 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
74bf76ed 7442 expand_omp_regimplify_p, NULL, NULL)
538dd0b7 7443 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
74bf76ed
JJ
7444 expand_omp_regimplify_p, NULL, NULL))
7445 {
538dd0b7
DM
7446 *gsi = gsi_for_stmt (cond_stmt);
7447 gimple_regimplify_operands (cond_stmt, gsi);
74bf76ed 7448 }
538dd0b7 7449 e = split_block (entry_bb, cond_stmt);
d9a6bd32
JJ
7450 basic_block &zero_iter_bb
7451 = i < fd->collapse ? zero_iter1_bb : zero_iter2_bb;
7452 int &first_zero_iter
7453 = i < fd->collapse ? first_zero_iter1 : first_zero_iter2;
74bf76ed
JJ
7454 if (zero_iter_bb == NULL)
7455 {
538dd0b7 7456 gassign *assign_stmt;
74bf76ed
JJ
7457 first_zero_iter = i;
7458 zero_iter_bb = create_empty_bb (entry_bb);
726338f4 7459 add_bb_to_loop (zero_iter_bb, entry_bb->loop_father);
74bf76ed 7460 *gsi = gsi_after_labels (zero_iter_bb);
d9a6bd32
JJ
7461 if (i < fd->collapse)
7462 assign_stmt = gimple_build_assign (fd->loop.n2,
7463 build_zero_cst (type));
7464 else
7465 {
7466 counts[i] = create_tmp_reg (type, ".count");
7467 assign_stmt
7468 = gimple_build_assign (counts[i], build_zero_cst (type));
7469 }
538dd0b7 7470 gsi_insert_before (gsi, assign_stmt, GSI_SAME_STMT);
74bf76ed
JJ
7471 set_immediate_dominator (CDI_DOMINATORS, zero_iter_bb,
7472 entry_bb);
7473 }
7474 ne = make_edge (entry_bb, zero_iter_bb, EDGE_FALSE_VALUE);
7475 ne->probability = REG_BR_PROB_BASE / 2000 - 1;
7476 e->flags = EDGE_TRUE_VALUE;
7477 e->probability = REG_BR_PROB_BASE - ne->probability;
7478 if (l2_dom_bb == NULL)
7479 l2_dom_bb = entry_bb;
7480 entry_bb = e->dest;
7481 *gsi = gsi_last_bb (entry_bb);
7482 }
7483
7484 if (POINTER_TYPE_P (itype))
7485 itype = signed_type_for (itype);
7486 t = build_int_cst (itype, (fd->loops[i].cond_code == LT_EXPR
7487 ? -1 : 1));
7488 t = fold_build2 (PLUS_EXPR, itype,
7489 fold_convert (itype, fd->loops[i].step), t);
7490 t = fold_build2 (PLUS_EXPR, itype, t,
7491 fold_convert (itype, fd->loops[i].n2));
7492 t = fold_build2 (MINUS_EXPR, itype, t,
7493 fold_convert (itype, fd->loops[i].n1));
7494 /* ?? We could probably use CEIL_DIV_EXPR instead of
7495 TRUNC_DIV_EXPR and adjusting by hand. Unless we can't
7496 generate the same code in the end because generically we
7497 don't know that the values involved must be negative for
7498 GT?? */
7499 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
7500 t = fold_build2 (TRUNC_DIV_EXPR, itype,
7501 fold_build1 (NEGATE_EXPR, itype, t),
7502 fold_build1 (NEGATE_EXPR, itype,
7503 fold_convert (itype,
7504 fd->loops[i].step)));
7505 else
7506 t = fold_build2 (TRUNC_DIV_EXPR, itype, t,
7507 fold_convert (itype, fd->loops[i].step));
7508 t = fold_convert (type, t);
7509 if (TREE_CODE (t) == INTEGER_CST)
7510 counts[i] = t;
7511 else
7512 {
d9a6bd32
JJ
7513 if (i < fd->collapse || i != first_zero_iter2)
7514 counts[i] = create_tmp_reg (type, ".count");
74bf76ed
JJ
7515 expand_omp_build_assign (gsi, counts[i], t);
7516 }
d9a6bd32 7517 if (SSA_VAR_P (fd->loop.n2) && i < fd->collapse)
74bf76ed
JJ
7518 {
7519 if (i == 0)
7520 t = counts[0];
7521 else
7522 t = fold_build2 (MULT_EXPR, type, fd->loop.n2, counts[i]);
7523 expand_omp_build_assign (gsi, fd->loop.n2, t);
7524 }
7525 }
7526}
7527
7528
7529/* Helper function for expand_omp_{for_*,simd}. Generate code like:
7530 T = V;
7531 V3 = N31 + (T % count3) * STEP3;
7532 T = T / count3;
7533 V2 = N21 + (T % count2) * STEP2;
7534 T = T / count2;
7535 V1 = N11 + T * STEP1;
acf0174b
JJ
7536 if this loop doesn't have an inner loop construct combined with it.
7537 If it does have an inner loop construct combined with it and the
7538 iteration count isn't known constant, store values from counts array
7539 into its _looptemp_ temporaries instead. */
74bf76ed
JJ
7540
7541static void
7542expand_omp_for_init_vars (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
355fe088 7543 tree *counts, gimple *inner_stmt, tree startvar)
74bf76ed
JJ
7544{
7545 int i;
acf0174b
JJ
7546 if (gimple_omp_for_combined_p (fd->for_stmt))
7547 {
7548 /* If fd->loop.n2 is constant, then no propagation of the counts
7549 is needed, they are constant. */
7550 if (TREE_CODE (fd->loop.n2) == INTEGER_CST)
7551 return;
7552
d9a6bd32
JJ
7553 tree clauses = gimple_code (inner_stmt) != GIMPLE_OMP_FOR
7554 ? gimple_omp_taskreg_clauses (inner_stmt)
acf0174b
JJ
7555 : gimple_omp_for_clauses (inner_stmt);
7556 /* First two _looptemp_ clauses are for istart/iend, counts[0]
7557 isn't supposed to be handled, as the inner loop doesn't
7558 use it. */
7559 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
7560 gcc_assert (innerc);
7561 for (i = 0; i < fd->collapse; i++)
7562 {
7563 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7564 OMP_CLAUSE__LOOPTEMP_);
7565 gcc_assert (innerc);
7566 if (i)
7567 {
7568 tree tem = OMP_CLAUSE_DECL (innerc);
7569 tree t = fold_convert (TREE_TYPE (tem), counts[i]);
7570 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
7571 false, GSI_CONTINUE_LINKING);
538dd0b7 7572 gassign *stmt = gimple_build_assign (tem, t);
acf0174b
JJ
7573 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7574 }
7575 }
7576 return;
7577 }
7578
74bf76ed
JJ
7579 tree type = TREE_TYPE (fd->loop.v);
7580 tree tem = create_tmp_reg (type, ".tem");
538dd0b7 7581 gassign *stmt = gimple_build_assign (tem, startvar);
74bf76ed
JJ
7582 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7583
7584 for (i = fd->collapse - 1; i >= 0; i--)
7585 {
7586 tree vtype = TREE_TYPE (fd->loops[i].v), itype, t;
7587 itype = vtype;
7588 if (POINTER_TYPE_P (vtype))
7589 itype = signed_type_for (vtype);
7590 if (i != 0)
7591 t = fold_build2 (TRUNC_MOD_EXPR, type, tem, counts[i]);
7592 else
7593 t = tem;
7594 t = fold_convert (itype, t);
7595 t = fold_build2 (MULT_EXPR, itype, t,
7596 fold_convert (itype, fd->loops[i].step));
7597 if (POINTER_TYPE_P (vtype))
7598 t = fold_build_pointer_plus (fd->loops[i].n1, t);
7599 else
7600 t = fold_build2 (PLUS_EXPR, itype, fd->loops[i].n1, t);
7601 t = force_gimple_operand_gsi (gsi, t,
7602 DECL_P (fd->loops[i].v)
7603 && TREE_ADDRESSABLE (fd->loops[i].v),
7604 NULL_TREE, false,
7605 GSI_CONTINUE_LINKING);
7606 stmt = gimple_build_assign (fd->loops[i].v, t);
7607 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7608 if (i != 0)
7609 {
7610 t = fold_build2 (TRUNC_DIV_EXPR, type, tem, counts[i]);
7611 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
7612 false, GSI_CONTINUE_LINKING);
7613 stmt = gimple_build_assign (tem, t);
7614 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7615 }
7616 }
7617}
7618
7619
7620/* Helper function for expand_omp_for_*. Generate code like:
7621 L10:
7622 V3 += STEP3;
7623 if (V3 cond3 N32) goto BODY_BB; else goto L11;
7624 L11:
7625 V3 = N31;
7626 V2 += STEP2;
7627 if (V2 cond2 N22) goto BODY_BB; else goto L12;
7628 L12:
7629 V2 = N21;
7630 V1 += STEP1;
7631 goto BODY_BB; */
7632
7633static basic_block
7634extract_omp_for_update_vars (struct omp_for_data *fd, basic_block cont_bb,
7635 basic_block body_bb)
7636{
7637 basic_block last_bb, bb, collapse_bb = NULL;
7638 int i;
7639 gimple_stmt_iterator gsi;
7640 edge e;
7641 tree t;
355fe088 7642 gimple *stmt;
74bf76ed
JJ
7643
7644 last_bb = cont_bb;
7645 for (i = fd->collapse - 1; i >= 0; i--)
7646 {
7647 tree vtype = TREE_TYPE (fd->loops[i].v);
7648
7649 bb = create_empty_bb (last_bb);
726338f4 7650 add_bb_to_loop (bb, last_bb->loop_father);
74bf76ed
JJ
7651 gsi = gsi_start_bb (bb);
7652
7653 if (i < fd->collapse - 1)
7654 {
7655 e = make_edge (last_bb, bb, EDGE_FALSE_VALUE);
7656 e->probability = REG_BR_PROB_BASE / 8;
7657
7658 t = fd->loops[i + 1].n1;
7659 t = force_gimple_operand_gsi (&gsi, t,
7660 DECL_P (fd->loops[i + 1].v)
7661 && TREE_ADDRESSABLE (fd->loops[i
7662 + 1].v),
7663 NULL_TREE, false,
7664 GSI_CONTINUE_LINKING);
7665 stmt = gimple_build_assign (fd->loops[i + 1].v, t);
7666 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7667 }
7668 else
7669 collapse_bb = bb;
7670
7671 set_immediate_dominator (CDI_DOMINATORS, bb, last_bb);
7672
7673 if (POINTER_TYPE_P (vtype))
7674 t = fold_build_pointer_plus (fd->loops[i].v, fd->loops[i].step);
7675 else
7676 t = fold_build2 (PLUS_EXPR, vtype, fd->loops[i].v, fd->loops[i].step);
7677 t = force_gimple_operand_gsi (&gsi, t,
7678 DECL_P (fd->loops[i].v)
7679 && TREE_ADDRESSABLE (fd->loops[i].v),
7680 NULL_TREE, false, GSI_CONTINUE_LINKING);
7681 stmt = gimple_build_assign (fd->loops[i].v, t);
7682 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7683
7684 if (i > 0)
7685 {
7686 t = fd->loops[i].n2;
7687 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7688 false, GSI_CONTINUE_LINKING);
7689 tree v = fd->loops[i].v;
7690 if (DECL_P (v) && TREE_ADDRESSABLE (v))
7691 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
7692 false, GSI_CONTINUE_LINKING);
7693 t = fold_build2 (fd->loops[i].cond_code, boolean_type_node, v, t);
7694 stmt = gimple_build_cond_empty (t);
7695 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7696 e = make_edge (bb, body_bb, EDGE_TRUE_VALUE);
7697 e->probability = REG_BR_PROB_BASE * 7 / 8;
7698 }
7699 else
7700 make_edge (bb, body_bb, EDGE_FALLTHRU);
7701 last_bb = bb;
7702 }
7703
7704 return collapse_bb;
7705}
7706
7707
d9a6bd32 7708/* Expand #pragma omp ordered depend(source). */
953ff289 7709
d9a6bd32
JJ
7710static void
7711expand_omp_ordered_source (gimple_stmt_iterator *gsi, struct omp_for_data *fd,
7712 tree *counts, location_t loc)
7713{
7714 enum built_in_function source_ix
7715 = fd->iter_type == long_integer_type_node
7716 ? BUILT_IN_GOMP_DOACROSS_POST : BUILT_IN_GOMP_DOACROSS_ULL_POST;
7717 gimple *g
7718 = gimple_build_call (builtin_decl_explicit (source_ix), 1,
7719 build_fold_addr_expr (counts[fd->ordered]));
7720 gimple_set_location (g, loc);
7721 gsi_insert_before (gsi, g, GSI_SAME_STMT);
7722}
953ff289 7723
d9a6bd32 7724/* Expand a single depend from #pragma omp ordered depend(sink:...). */
953ff289 7725
d9a6bd32
JJ
7726static void
7727expand_omp_ordered_sink (gimple_stmt_iterator *gsi, struct omp_for_data *fd,
7728 tree *counts, tree c, location_t loc)
7729{
7730 auto_vec<tree, 10> args;
7731 enum built_in_function sink_ix
7732 = fd->iter_type == long_integer_type_node
7733 ? BUILT_IN_GOMP_DOACROSS_WAIT : BUILT_IN_GOMP_DOACROSS_ULL_WAIT;
7734 tree t, off, coff = NULL_TREE, deps = OMP_CLAUSE_DECL (c), cond = NULL_TREE;
7735 int i;
7736 gimple_stmt_iterator gsi2 = *gsi;
7737 bool warned_step = false;
a68ab351 7738
d9a6bd32
JJ
7739 for (i = 0; i < fd->ordered; i++)
7740 {
7741 off = TREE_PURPOSE (deps);
7742 if (!integer_zerop (off))
7743 {
7744 gcc_assert (fd->loops[i].cond_code == LT_EXPR
7745 || fd->loops[i].cond_code == GT_EXPR);
7746 bool forward = fd->loops[i].cond_code == LT_EXPR;
7747 if (forward ^ OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
7748 warning_at (loc, 0, "%<depend(sink)%> clause waiting for "
7749 "lexically later iteration");
7750 break;
7751 }
7752 deps = TREE_CHAIN (deps);
7753 }
7754 /* If all offsets corresponding to the collapsed loops are zero,
7755 this depend clause can be ignored. FIXME: but there is still a
7756 flush needed. We need to emit one __sync_synchronize () for it
7757 though (perhaps conditionally)? Solve this together with the
7758 conservative dependence folding optimization.
7759 if (i >= fd->collapse)
7760 return; */
a68ab351 7761
d9a6bd32
JJ
7762 deps = OMP_CLAUSE_DECL (c);
7763 gsi_prev (&gsi2);
7764 edge e1 = split_block (gsi_bb (gsi2), gsi_stmt (gsi2));
7765 edge e2 = split_block_after_labels (e1->dest);
a68ab351 7766
d9a6bd32
JJ
7767 *gsi = gsi_after_labels (e1->dest);
7768 for (i = 0; i < fd->ordered; i++)
7769 {
7770 tree itype = TREE_TYPE (fd->loops[i].v);
7771 if (POINTER_TYPE_P (itype))
7772 itype = sizetype;
7773 if (i)
7774 deps = TREE_CHAIN (deps);
7775 off = TREE_PURPOSE (deps);
7776 tree s = fold_convert_loc (loc, itype, fd->loops[i].step);
7777
7778 if (integer_zerop (off))
7779 t = boolean_true_node;
7780 else
7781 {
7782 tree a;
7783 tree co = fold_convert_loc (loc, itype, off);
7784 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
7785 {
7786 if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
7787 co = fold_build1_loc (loc, NEGATE_EXPR, itype, co);
7788 a = fold_build2_loc (loc, POINTER_PLUS_EXPR,
7789 TREE_TYPE (fd->loops[i].v), fd->loops[i].v,
7790 co);
7791 }
7792 else if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
7793 a = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (fd->loops[i].v),
7794 fd->loops[i].v, co);
7795 else
7796 a = fold_build2_loc (loc, PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
7797 fd->loops[i].v, co);
7798 if (fd->loops[i].cond_code == LT_EXPR)
7799 {
7800 if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
7801 t = fold_build2_loc (loc, GE_EXPR, boolean_type_node, a,
7802 fd->loops[i].n1);
7803 else
7804 t = fold_build2_loc (loc, LT_EXPR, boolean_type_node, a,
7805 fd->loops[i].n2);
7806 }
7807 else if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
7808 t = fold_build2_loc (loc, GT_EXPR, boolean_type_node, a,
7809 fd->loops[i].n2);
7810 else
7811 t = fold_build2_loc (loc, LE_EXPR, boolean_type_node, a,
7812 fd->loops[i].n1);
7813 }
7814 if (cond)
7815 cond = fold_build2_loc (loc, BIT_AND_EXPR, boolean_type_node, cond, t);
7816 else
7817 cond = t;
7818
7819 off = fold_convert_loc (loc, itype, off);
7820
7821 if (fd->loops[i].cond_code == LT_EXPR
7822 ? !integer_onep (fd->loops[i].step)
7823 : !integer_minus_onep (fd->loops[i].step))
7824 {
7825 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
7826 t = fold_build2_loc (loc, TRUNC_MOD_EXPR, itype, off,
7827 fold_build1_loc (loc, NEGATE_EXPR, itype,
7828 s));
7829 else
7830 t = fold_build2_loc (loc, TRUNC_MOD_EXPR, itype, off, s);
7831 t = fold_build2_loc (loc, EQ_EXPR, boolean_type_node, t,
7832 build_int_cst (itype, 0));
7833 if (integer_zerop (t) && !warned_step)
7834 {
7835 warning_at (loc, 0, "%<depend(sink)%> refers to iteration never "
7836 "in the iteration space");
7837 warned_step = true;
7838 }
7839 cond = fold_build2_loc (loc, BIT_AND_EXPR, boolean_type_node,
7840 cond, t);
7841 }
7842
7843 if (i <= fd->collapse - 1 && fd->collapse > 1)
7844 t = fd->loop.v;
7845 else if (counts[i])
7846 t = counts[i];
7847 else
7848 {
7849 t = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (fd->loops[i].v),
7850 fd->loops[i].v, fd->loops[i].n1);
7851 t = fold_convert_loc (loc, fd->iter_type, t);
7852 }
7853 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
7854 off = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, off,
7855 fold_build1_loc (loc, NEGATE_EXPR, itype,
7856 s));
7857 else
7858 off = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, off, s);
7859 if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
7860 off = fold_build1_loc (loc, NEGATE_EXPR, itype, off);
7861 off = fold_convert_loc (loc, fd->iter_type, off);
7862 if (i <= fd->collapse - 1 && fd->collapse > 1)
7863 {
7864 if (i)
7865 off = fold_build2_loc (loc, PLUS_EXPR, fd->iter_type, coff,
7866 off);
7867 if (i < fd->collapse - 1)
7868 {
7869 coff = fold_build2_loc (loc, MULT_EXPR, fd->iter_type, off,
7870 counts[i]);
7871 continue;
7872 }
7873 }
7874 off = unshare_expr (off);
7875 t = fold_build2_loc (loc, PLUS_EXPR, fd->iter_type, t, off);
7876 t = force_gimple_operand_gsi (gsi, t, true, NULL_TREE,
7877 true, GSI_SAME_STMT);
7878 args.safe_push (t);
7879 }
7880 gimple *g = gimple_build_call_vec (builtin_decl_explicit (sink_ix), args);
7881 gimple_set_location (g, loc);
7882 gsi_insert_before (gsi, g, GSI_SAME_STMT);
7883
7884 *gsi = gsi_last_bb (e1->src);
7885 cond = unshare_expr (cond);
7886 cond = force_gimple_operand_gsi (gsi, cond, true, NULL_TREE, false,
7887 GSI_CONTINUE_LINKING);
7888 gsi_insert_after (gsi, gimple_build_cond_empty (cond), GSI_NEW_STMT);
7889 edge e3 = make_edge (e1->src, e2->dest, EDGE_FALSE_VALUE);
7890 e3->probability = REG_BR_PROB_BASE / 8;
7891 e1->probability = REG_BR_PROB_BASE - e3->probability;
7892 e1->flags = EDGE_TRUE_VALUE;
7893 set_immediate_dominator (CDI_DOMINATORS, e2->dest, e1->src);
7894
7895 *gsi = gsi_after_labels (e2->dest);
7896}
7897
7898/* Expand all #pragma omp ordered depend(source) and
7899 #pragma omp ordered depend(sink:...) constructs in the current
7900 #pragma omp for ordered(n) region. */
7901
7902static void
7903expand_omp_ordered_source_sink (struct omp_region *region,
7904 struct omp_for_data *fd, tree *counts,
7905 basic_block cont_bb)
7906{
7907 struct omp_region *inner;
7908 int i;
7909 for (i = fd->collapse - 1; i < fd->ordered; i++)
7910 if (i == fd->collapse - 1 && fd->collapse > 1)
7911 counts[i] = NULL_TREE;
7912 else if (i >= fd->collapse && !cont_bb)
7913 counts[i] = build_zero_cst (fd->iter_type);
7914 else if (!POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v))
7915 && integer_onep (fd->loops[i].step))
7916 counts[i] = NULL_TREE;
7917 else
7918 counts[i] = create_tmp_var (fd->iter_type, ".orditer");
7919 tree atype
7920 = build_array_type_nelts (fd->iter_type, fd->ordered - fd->collapse + 1);
7921 counts[fd->ordered] = create_tmp_var (atype, ".orditera");
7922 TREE_ADDRESSABLE (counts[fd->ordered]) = 1;
7923
7924 for (inner = region->inner; inner; inner = inner->next)
7925 if (inner->type == GIMPLE_OMP_ORDERED)
7926 {
7927 gomp_ordered *ord_stmt = inner->ord_stmt;
7928 gimple_stmt_iterator gsi = gsi_for_stmt (ord_stmt);
7929 location_t loc = gimple_location (ord_stmt);
7930 tree c;
7931 for (c = gimple_omp_ordered_clauses (ord_stmt);
7932 c; c = OMP_CLAUSE_CHAIN (c))
7933 if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE)
7934 break;
7935 if (c)
7936 expand_omp_ordered_source (&gsi, fd, counts, loc);
7937 for (c = gimple_omp_ordered_clauses (ord_stmt);
7938 c; c = OMP_CLAUSE_CHAIN (c))
7939 if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK)
7940 expand_omp_ordered_sink (&gsi, fd, counts, c, loc);
7941 gsi_remove (&gsi, true);
7942 }
7943}
7944
7945/* Wrap the body into fd->ordered - fd->collapse loops that aren't
7946 collapsed. */
7947
7948static basic_block
7949expand_omp_for_ordered_loops (struct omp_for_data *fd, tree *counts,
7950 basic_block cont_bb, basic_block body_bb,
7951 bool ordered_lastprivate)
7952{
7953 if (fd->ordered == fd->collapse)
7954 return cont_bb;
7955
7956 if (!cont_bb)
7957 {
7958 gimple_stmt_iterator gsi = gsi_after_labels (body_bb);
7959 for (int i = fd->collapse; i < fd->ordered; i++)
7960 {
7961 tree type = TREE_TYPE (fd->loops[i].v);
7962 tree n1 = fold_convert (type, fd->loops[i].n1);
7963 expand_omp_build_assign (&gsi, fd->loops[i].v, n1);
7964 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
7965 size_int (i - fd->collapse + 1),
7966 NULL_TREE, NULL_TREE);
7967 expand_omp_build_assign (&gsi, aref, build_zero_cst (fd->iter_type));
7968 }
7969 return NULL;
7970 }
7971
7972 for (int i = fd->ordered - 1; i >= fd->collapse; i--)
7973 {
7974 tree t, type = TREE_TYPE (fd->loops[i].v);
7975 gimple_stmt_iterator gsi = gsi_after_labels (body_bb);
7976 expand_omp_build_assign (&gsi, fd->loops[i].v,
7977 fold_convert (type, fd->loops[i].n1));
7978 if (counts[i])
7979 expand_omp_build_assign (&gsi, counts[i],
7980 build_zero_cst (fd->iter_type));
7981 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
7982 size_int (i - fd->collapse + 1),
7983 NULL_TREE, NULL_TREE);
7984 expand_omp_build_assign (&gsi, aref, build_zero_cst (fd->iter_type));
7985 if (!gsi_end_p (gsi))
7986 gsi_prev (&gsi);
7987 else
7988 gsi = gsi_last_bb (body_bb);
7989 edge e1 = split_block (body_bb, gsi_stmt (gsi));
7990 basic_block new_body = e1->dest;
7991 if (body_bb == cont_bb)
7992 cont_bb = new_body;
7993 edge e2 = NULL;
7994 basic_block new_header;
7995 if (EDGE_COUNT (cont_bb->preds) > 0)
7996 {
7997 gsi = gsi_last_bb (cont_bb);
7998 if (POINTER_TYPE_P (type))
7999 t = fold_build_pointer_plus (fd->loops[i].v,
8000 fold_convert (sizetype,
8001 fd->loops[i].step));
8002 else
8003 t = fold_build2 (PLUS_EXPR, type, fd->loops[i].v,
8004 fold_convert (type, fd->loops[i].step));
8005 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
8006 if (counts[i])
8007 {
8008 t = fold_build2 (PLUS_EXPR, fd->iter_type, counts[i],
8009 build_int_cst (fd->iter_type, 1));
8010 expand_omp_build_assign (&gsi, counts[i], t);
8011 t = counts[i];
8012 }
8013 else
8014 {
8015 t = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->loops[i].v),
8016 fd->loops[i].v, fd->loops[i].n1);
8017 t = fold_convert (fd->iter_type, t);
8018 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8019 true, GSI_SAME_STMT);
8020 }
8021 aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8022 size_int (i - fd->collapse + 1),
8023 NULL_TREE, NULL_TREE);
8024 expand_omp_build_assign (&gsi, aref, t);
8025 gsi_prev (&gsi);
8026 e2 = split_block (cont_bb, gsi_stmt (gsi));
8027 new_header = e2->dest;
8028 }
8029 else
8030 new_header = cont_bb;
8031 gsi = gsi_after_labels (new_header);
8032 tree v = force_gimple_operand_gsi (&gsi, fd->loops[i].v, true, NULL_TREE,
8033 true, GSI_SAME_STMT);
8034 tree n2
8035 = force_gimple_operand_gsi (&gsi, fold_convert (type, fd->loops[i].n2),
8036 true, NULL_TREE, true, GSI_SAME_STMT);
8037 t = build2 (fd->loops[i].cond_code, boolean_type_node, v, n2);
8038 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_NEW_STMT);
8039 edge e3 = split_block (new_header, gsi_stmt (gsi));
8040 cont_bb = e3->dest;
8041 remove_edge (e1);
8042 make_edge (body_bb, new_header, EDGE_FALLTHRU);
8043 e3->flags = EDGE_FALSE_VALUE;
8044 e3->probability = REG_BR_PROB_BASE / 8;
8045 e1 = make_edge (new_header, new_body, EDGE_TRUE_VALUE);
8046 e1->probability = REG_BR_PROB_BASE - e3->probability;
8047
8048 set_immediate_dominator (CDI_DOMINATORS, new_header, body_bb);
8049 set_immediate_dominator (CDI_DOMINATORS, new_body, new_header);
8050
8051 if (e2)
8052 {
8053 struct loop *loop = alloc_loop ();
8054 loop->header = new_header;
8055 loop->latch = e2->src;
8056 add_loop (loop, body_bb->loop_father);
8057 }
8058 }
8059
8060 /* If there are any lastprivate clauses and it is possible some loops
8061 might have zero iterations, ensure all the decls are initialized,
8062 otherwise we could crash evaluating C++ class iterators with lastprivate
8063 clauses. */
8064 bool need_inits = false;
8065 for (int i = fd->collapse; ordered_lastprivate && i < fd->ordered; i++)
8066 if (need_inits)
8067 {
8068 tree type = TREE_TYPE (fd->loops[i].v);
8069 gimple_stmt_iterator gsi = gsi_after_labels (body_bb);
8070 expand_omp_build_assign (&gsi, fd->loops[i].v,
8071 fold_convert (type, fd->loops[i].n1));
8072 }
8073 else
8074 {
8075 tree type = TREE_TYPE (fd->loops[i].v);
8076 tree this_cond = fold_build2 (fd->loops[i].cond_code,
8077 boolean_type_node,
8078 fold_convert (type, fd->loops[i].n1),
8079 fold_convert (type, fd->loops[i].n2));
8080 if (!integer_onep (this_cond))
8081 need_inits = true;
8082 }
8083
8084 return cont_bb;
8085}
8086
8087
8088/* A subroutine of expand_omp_for. Generate code for a parallel
8089 loop with any schedule. Given parameters:
8090
8091 for (V = N1; V cond N2; V += STEP) BODY;
8092
8093 where COND is "<" or ">", we generate pseudocode
8094
8095 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
8096 if (more) goto L0; else goto L3;
8097 L0:
8098 V = istart0;
8099 iend = iend0;
8100 L1:
8101 BODY;
8102 V += STEP;
8103 if (V cond iend) goto L1; else goto L2;
8104 L2:
8105 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
8106 L3:
8107
8108 If this is a combined omp parallel loop, instead of the call to
8109 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
8110 If this is gimple_omp_for_combined_p loop, then instead of assigning
8111 V and iend in L0 we assign the first two _looptemp_ clause decls of the
8112 inner GIMPLE_OMP_FOR and V += STEP; and
8113 if (V cond iend) goto L1; else goto L2; are removed.
8114
8115 For collapsed loops, given parameters:
8116 collapse(3)
8117 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
8118 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
8119 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
8120 BODY;
8121
8122 we generate pseudocode
8123
8124 if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
8125 if (cond3 is <)
8126 adj = STEP3 - 1;
8127 else
8128 adj = STEP3 + 1;
8129 count3 = (adj + N32 - N31) / STEP3;
8130 if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
8131 if (cond2 is <)
8132 adj = STEP2 - 1;
8133 else
8134 adj = STEP2 + 1;
a68ab351 8135 count2 = (adj + N22 - N21) / STEP2;
5a0f4dd3 8136 if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
a68ab351
JJ
8137 if (cond1 is <)
8138 adj = STEP1 - 1;
8139 else
8140 adj = STEP1 + 1;
8141 count1 = (adj + N12 - N11) / STEP1;
8142 count = count1 * count2 * count3;
5a0f4dd3
JJ
8143 goto Z1;
8144 Z0:
8145 count = 0;
8146 Z1:
a68ab351
JJ
8147 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
8148 if (more) goto L0; else goto L3;
8149 L0:
8150 V = istart0;
8151 T = V;
8152 V3 = N31 + (T % count3) * STEP3;
8153 T = T / count3;
8154 V2 = N21 + (T % count2) * STEP2;
8155 T = T / count2;
8156 V1 = N11 + T * STEP1;
8157 iend = iend0;
8158 L1:
8159 BODY;
8160 V += 1;
8161 if (V < iend) goto L10; else goto L2;
8162 L10:
8163 V3 += STEP3;
8164 if (V3 cond3 N32) goto L1; else goto L11;
8165 L11:
8166 V3 = N31;
8167 V2 += STEP2;
8168 if (V2 cond2 N22) goto L1; else goto L12;
8169 L12:
8170 V2 = N21;
8171 V1 += STEP1;
8172 goto L1;
8173 L2:
8174 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
8175 L3:
8176
8177 */
953ff289 8178
777f7f9a 8179static void
50674e96
DN
8180expand_omp_for_generic (struct omp_region *region,
8181 struct omp_for_data *fd,
953ff289 8182 enum built_in_function start_fn,
acf0174b 8183 enum built_in_function next_fn,
355fe088 8184 gimple *inner_stmt)
953ff289 8185{
726a989a 8186 tree type, istart0, iend0, iend;
a68ab351
JJ
8187 tree t, vmain, vback, bias = NULL_TREE;
8188 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, collapse_bb;
d3c673c7 8189 basic_block l2_bb = NULL, l3_bb = NULL;
726a989a 8190 gimple_stmt_iterator gsi;
538dd0b7 8191 gassign *assign_stmt;
50674e96 8192 bool in_combined_parallel = is_combined_parallel (region);
e5c95afe 8193 bool broken_loop = region->cont == NULL;
917948d3 8194 edge e, ne;
a68ab351
JJ
8195 tree *counts = NULL;
8196 int i;
d9a6bd32 8197 bool ordered_lastprivate = false;
e5c95afe
ZD
8198
8199 gcc_assert (!broken_loop || !in_combined_parallel);
a68ab351
JJ
8200 gcc_assert (fd->iter_type == long_integer_type_node
8201 || !in_combined_parallel);
953ff289 8202
777f7f9a 8203 entry_bb = region->entry;
d3c673c7 8204 cont_bb = region->cont;
a68ab351 8205 collapse_bb = NULL;
e5c95afe
ZD
8206 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
8207 gcc_assert (broken_loop
8208 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
8209 l0_bb = split_edge (FALLTHRU_EDGE (entry_bb));
8210 l1_bb = single_succ (l0_bb);
8211 if (!broken_loop)
d3c673c7
JJ
8212 {
8213 l2_bb = create_empty_bb (cont_bb);
7aab672f
TV
8214 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb
8215 || (single_succ_edge (BRANCH_EDGE (cont_bb)->dest)->dest
8216 == l1_bb));
e5c95afe 8217 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
d3c673c7 8218 }
e5c95afe
ZD
8219 else
8220 l2_bb = NULL;
8221 l3_bb = BRANCH_EDGE (entry_bb)->dest;
8222 exit_bb = region->exit;
50674e96 8223
726a989a 8224 gsi = gsi_last_bb (entry_bb);
a68ab351 8225
726a989a 8226 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
d9a6bd32
JJ
8227 if (fd->ordered
8228 && find_omp_clause (gimple_omp_for_clauses (gsi_stmt (gsi)),
8229 OMP_CLAUSE_LASTPRIVATE))
8230 ordered_lastprivate = false;
8231 if (fd->collapse > 1 || fd->ordered)
a68ab351 8232 {
d9a6bd32
JJ
8233 int first_zero_iter1 = -1, first_zero_iter2 = -1;
8234 basic_block zero_iter1_bb = NULL, zero_iter2_bb = NULL, l2_dom_bb = NULL;
5a0f4dd3 8235
d9a6bd32 8236 counts = XALLOCAVEC (tree, fd->ordered ? fd->ordered + 1 : fd->collapse);
74bf76ed 8237 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
d9a6bd32
JJ
8238 zero_iter1_bb, first_zero_iter1,
8239 zero_iter2_bb, first_zero_iter2, l2_dom_bb);
a68ab351 8240
d9a6bd32 8241 if (zero_iter1_bb)
5a0f4dd3
JJ
8242 {
8243 /* Some counts[i] vars might be uninitialized if
8244 some loop has zero iterations. But the body shouldn't
8245 be executed in that case, so just avoid uninit warnings. */
d9a6bd32
JJ
8246 for (i = first_zero_iter1;
8247 i < (fd->ordered ? fd->ordered : fd->collapse); i++)
5a0f4dd3
JJ
8248 if (SSA_VAR_P (counts[i]))
8249 TREE_NO_WARNING (counts[i]) = 1;
8250 gsi_prev (&gsi);
8251 e = split_block (entry_bb, gsi_stmt (gsi));
8252 entry_bb = e->dest;
d9a6bd32 8253 make_edge (zero_iter1_bb, entry_bb, EDGE_FALLTHRU);
5a0f4dd3
JJ
8254 gsi = gsi_last_bb (entry_bb);
8255 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
8256 get_immediate_dominator (CDI_DOMINATORS,
d9a6bd32
JJ
8257 zero_iter1_bb));
8258 }
8259 if (zero_iter2_bb)
8260 {
8261 /* Some counts[i] vars might be uninitialized if
8262 some loop has zero iterations. But the body shouldn't
8263 be executed in that case, so just avoid uninit warnings. */
8264 for (i = first_zero_iter2; i < fd->ordered; i++)
8265 if (SSA_VAR_P (counts[i]))
8266 TREE_NO_WARNING (counts[i]) = 1;
8267 if (zero_iter1_bb)
8268 make_edge (zero_iter2_bb, entry_bb, EDGE_FALLTHRU);
8269 else
8270 {
8271 gsi_prev (&gsi);
8272 e = split_block (entry_bb, gsi_stmt (gsi));
8273 entry_bb = e->dest;
8274 make_edge (zero_iter2_bb, entry_bb, EDGE_FALLTHRU);
8275 gsi = gsi_last_bb (entry_bb);
8276 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
8277 get_immediate_dominator
8278 (CDI_DOMINATORS, zero_iter2_bb));
8279 }
8280 }
8281 if (fd->collapse == 1)
8282 {
8283 counts[0] = fd->loop.n2;
8284 fd->loop = fd->loops[0];
8285 }
8286 }
8287
8288 type = TREE_TYPE (fd->loop.v);
8289 istart0 = create_tmp_var (fd->iter_type, ".istart0");
8290 iend0 = create_tmp_var (fd->iter_type, ".iend0");
8291 TREE_ADDRESSABLE (istart0) = 1;
8292 TREE_ADDRESSABLE (iend0) = 1;
8293
8294 /* See if we need to bias by LLONG_MIN. */
8295 if (fd->iter_type == long_long_unsigned_type_node
8296 && TREE_CODE (type) == INTEGER_TYPE
8297 && !TYPE_UNSIGNED (type)
8298 && fd->ordered == 0)
8299 {
8300 tree n1, n2;
8301
8302 if (fd->loop.cond_code == LT_EXPR)
8303 {
8304 n1 = fd->loop.n1;
8305 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
5a0f4dd3 8306 }
d9a6bd32
JJ
8307 else
8308 {
8309 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
8310 n2 = fd->loop.n1;
8311 }
8312 if (TREE_CODE (n1) != INTEGER_CST
8313 || TREE_CODE (n2) != INTEGER_CST
8314 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
8315 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
a68ab351 8316 }
d9a6bd32
JJ
8317
8318 gimple_stmt_iterator gsif = gsi;
8319 gsi_prev (&gsif);
8320
8321 tree arr = NULL_TREE;
917948d3
ZD
8322 if (in_combined_parallel)
8323 {
d9a6bd32 8324 gcc_assert (fd->ordered == 0);
917948d3
ZD
8325 /* In a combined parallel loop, emit a call to
8326 GOMP_loop_foo_next. */
e79983f4 8327 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
917948d3
ZD
8328 build_fold_addr_expr (istart0),
8329 build_fold_addr_expr (iend0));
8330 }
8331 else
953ff289 8332 {
5039610b 8333 tree t0, t1, t2, t3, t4;
50674e96
DN
8334 /* If this is not a combined parallel loop, emit a call to
8335 GOMP_loop_foo_start in ENTRY_BB. */
5039610b
SL
8336 t4 = build_fold_addr_expr (iend0);
8337 t3 = build_fold_addr_expr (istart0);
d9a6bd32 8338 if (fd->ordered)
c6ff4493 8339 {
d9a6bd32
JJ
8340 t0 = build_int_cst (unsigned_type_node,
8341 fd->ordered - fd->collapse + 1);
8342 arr = create_tmp_var (build_array_type_nelts (fd->iter_type,
8343 fd->ordered
8344 - fd->collapse + 1),
8345 ".omp_counts");
8346 DECL_NAMELESS (arr) = 1;
8347 TREE_ADDRESSABLE (arr) = 1;
8348 TREE_STATIC (arr) = 1;
8349 vec<constructor_elt, va_gc> *v;
8350 vec_alloc (v, fd->ordered - fd->collapse + 1);
8351 int idx;
8352
8353 for (idx = 0; idx < fd->ordered - fd->collapse + 1; idx++)
8354 {
8355 tree c;
8356 if (idx == 0 && fd->collapse > 1)
8357 c = fd->loop.n2;
8358 else
8359 c = counts[idx + fd->collapse - 1];
8360 tree purpose = size_int (idx);
8361 CONSTRUCTOR_APPEND_ELT (v, purpose, c);
8362 if (TREE_CODE (c) != INTEGER_CST)
8363 TREE_STATIC (arr) = 0;
8364 }
8365
8366 DECL_INITIAL (arr) = build_constructor (TREE_TYPE (arr), v);
8367 if (!TREE_STATIC (arr))
8368 force_gimple_operand_gsi (&gsi, build1 (DECL_EXPR,
8369 void_type_node, arr),
8370 true, NULL_TREE, true, GSI_SAME_STMT);
8371 t1 = build_fold_addr_expr (arr);
8372 t2 = NULL_TREE;
c6ff4493
SE
8373 }
8374 else
8375 {
d9a6bd32
JJ
8376 t2 = fold_convert (fd->iter_type, fd->loop.step);
8377 t1 = fd->loop.n2;
8378 t0 = fd->loop.n1;
8379 if (gimple_omp_for_combined_into_p (fd->for_stmt))
8380 {
8381 tree innerc
8382 = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
8383 OMP_CLAUSE__LOOPTEMP_);
8384 gcc_assert (innerc);
8385 t0 = OMP_CLAUSE_DECL (innerc);
8386 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
8387 OMP_CLAUSE__LOOPTEMP_);
8388 gcc_assert (innerc);
8389 t1 = OMP_CLAUSE_DECL (innerc);
8390 }
8391 if (POINTER_TYPE_P (TREE_TYPE (t0))
8392 && TYPE_PRECISION (TREE_TYPE (t0))
8393 != TYPE_PRECISION (fd->iter_type))
8394 {
8395 /* Avoid casting pointers to integer of a different size. */
8396 tree itype = signed_type_for (type);
8397 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
8398 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
8399 }
8400 else
8401 {
8402 t1 = fold_convert (fd->iter_type, t1);
8403 t0 = fold_convert (fd->iter_type, t0);
8404 }
8405 if (bias)
8406 {
8407 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
8408 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
8409 }
a68ab351 8410 }
d9a6bd32 8411 if (fd->iter_type == long_integer_type_node || fd->ordered)
a68ab351
JJ
8412 {
8413 if (fd->chunk_size)
8414 {
8415 t = fold_convert (fd->iter_type, fd->chunk_size);
d9a6bd32
JJ
8416 t = omp_adjust_chunk_size (t, fd->simd_schedule);
8417 if (fd->ordered)
8418 t = build_call_expr (builtin_decl_explicit (start_fn),
8419 5, t0, t1, t, t3, t4);
8420 else
8421 t = build_call_expr (builtin_decl_explicit (start_fn),
8422 6, t0, t1, t2, t, t3, t4);
a68ab351 8423 }
d9a6bd32
JJ
8424 else if (fd->ordered)
8425 t = build_call_expr (builtin_decl_explicit (start_fn),
8426 4, t0, t1, t3, t4);
a68ab351 8427 else
e79983f4
MM
8428 t = build_call_expr (builtin_decl_explicit (start_fn),
8429 5, t0, t1, t2, t3, t4);
953ff289 8430 }
5039610b 8431 else
a68ab351
JJ
8432 {
8433 tree t5;
8434 tree c_bool_type;
e79983f4 8435 tree bfn_decl;
a68ab351
JJ
8436
8437 /* The GOMP_loop_ull_*start functions have additional boolean
8438 argument, true for < loops and false for > loops.
8439 In Fortran, the C bool type can be different from
8440 boolean_type_node. */
e79983f4
MM
8441 bfn_decl = builtin_decl_explicit (start_fn);
8442 c_bool_type = TREE_TYPE (TREE_TYPE (bfn_decl));
a68ab351
JJ
8443 t5 = build_int_cst (c_bool_type,
8444 fd->loop.cond_code == LT_EXPR ? 1 : 0);
8445 if (fd->chunk_size)
8446 {
e79983f4 8447 tree bfn_decl = builtin_decl_explicit (start_fn);
a68ab351 8448 t = fold_convert (fd->iter_type, fd->chunk_size);
d9a6bd32 8449 t = omp_adjust_chunk_size (t, fd->simd_schedule);
e79983f4 8450 t = build_call_expr (bfn_decl, 7, t5, t0, t1, t2, t, t3, t4);
a68ab351
JJ
8451 }
8452 else
e79983f4
MM
8453 t = build_call_expr (builtin_decl_explicit (start_fn),
8454 6, t5, t0, t1, t2, t3, t4);
a68ab351 8455 }
953ff289 8456 }
a68ab351
JJ
8457 if (TREE_TYPE (t) != boolean_type_node)
8458 t = fold_build2 (NE_EXPR, boolean_type_node,
8459 t, build_int_cst (TREE_TYPE (t), 0));
726a989a
RB
8460 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8461 true, GSI_SAME_STMT);
d9a6bd32
JJ
8462 if (arr && !TREE_STATIC (arr))
8463 {
8464 tree clobber = build_constructor (TREE_TYPE (arr), NULL);
8465 TREE_THIS_VOLATILE (clobber) = 1;
8466 gsi_insert_before (&gsi, gimple_build_assign (arr, clobber),
8467 GSI_SAME_STMT);
8468 }
726a989a 8469 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
917948d3 8470
726a989a
RB
8471 /* Remove the GIMPLE_OMP_FOR statement. */
8472 gsi_remove (&gsi, true);
953ff289 8473
d9a6bd32
JJ
8474 if (gsi_end_p (gsif))
8475 gsif = gsi_after_labels (gsi_bb (gsif));
8476 gsi_next (&gsif);
8477
50674e96 8478 /* Iteration setup for sequential loop goes in L0_BB. */
74bf76ed
JJ
8479 tree startvar = fd->loop.v;
8480 tree endvar = NULL_TREE;
8481
acf0174b
JJ
8482 if (gimple_omp_for_combined_p (fd->for_stmt))
8483 {
8484 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_FOR
8485 && gimple_omp_for_kind (inner_stmt)
8486 == GF_OMP_FOR_KIND_SIMD);
8487 tree innerc = find_omp_clause (gimple_omp_for_clauses (inner_stmt),
8488 OMP_CLAUSE__LOOPTEMP_);
8489 gcc_assert (innerc);
8490 startvar = OMP_CLAUSE_DECL (innerc);
8491 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
8492 OMP_CLAUSE__LOOPTEMP_);
8493 gcc_assert (innerc);
8494 endvar = OMP_CLAUSE_DECL (innerc);
8495 }
8496
726a989a 8497 gsi = gsi_start_bb (l0_bb);
550918ca 8498 t = istart0;
d9a6bd32
JJ
8499 if (fd->ordered && fd->collapse == 1)
8500 t = fold_build2 (MULT_EXPR, fd->iter_type, t,
8501 fold_convert (fd->iter_type, fd->loop.step));
8502 else if (bias)
550918ca 8503 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
d9a6bd32
JJ
8504 if (fd->ordered && fd->collapse == 1)
8505 {
8506 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8507 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (startvar),
8508 fd->loop.n1, fold_convert (sizetype, t));
8509 else
8510 {
8511 t = fold_convert (TREE_TYPE (startvar), t);
8512 t = fold_build2 (PLUS_EXPR, TREE_TYPE (startvar),
8513 fd->loop.n1, t);
8514 }
8515 }
8516 else
8517 {
8518 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8519 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
8520 t = fold_convert (TREE_TYPE (startvar), t);
8521 }
ea3a0fde 8522 t = force_gimple_operand_gsi (&gsi, t,
74bf76ed
JJ
8523 DECL_P (startvar)
8524 && TREE_ADDRESSABLE (startvar),
ea3a0fde 8525 NULL_TREE, false, GSI_CONTINUE_LINKING);
538dd0b7
DM
8526 assign_stmt = gimple_build_assign (startvar, t);
8527 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
953ff289 8528
550918ca 8529 t = iend0;
d9a6bd32
JJ
8530 if (fd->ordered && fd->collapse == 1)
8531 t = fold_build2 (MULT_EXPR, fd->iter_type, t,
8532 fold_convert (fd->iter_type, fd->loop.step));
8533 else if (bias)
550918ca 8534 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
d9a6bd32 8535 if (fd->ordered && fd->collapse == 1)
a68ab351 8536 {
d9a6bd32
JJ
8537 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8538 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (startvar),
8539 fd->loop.n1, fold_convert (sizetype, t));
8540 else
8541 {
8542 t = fold_convert (TREE_TYPE (startvar), t);
8543 t = fold_build2 (PLUS_EXPR, TREE_TYPE (startvar),
8544 fd->loop.n1, t);
8545 }
8546 }
8547 else
8548 {
8549 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8550 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
8551 t = fold_convert (TREE_TYPE (startvar), t);
8552 }
8553 iend = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8554 false, GSI_CONTINUE_LINKING);
8555 if (endvar)
8556 {
8557 assign_stmt = gimple_build_assign (endvar, iend);
538dd0b7 8558 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
95782571 8559 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (iend)))
538dd0b7 8560 assign_stmt = gimple_build_assign (fd->loop.v, iend);
95782571 8561 else
0d0e4a03 8562 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, iend);
538dd0b7 8563 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
a68ab351 8564 }
d9a6bd32
JJ
8565 /* Handle linear clause adjustments. */
8566 tree itercnt = NULL_TREE;
8567 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_FOR)
8568 for (tree c = gimple_omp_for_clauses (fd->for_stmt);
8569 c; c = OMP_CLAUSE_CHAIN (c))
8570 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
8571 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
8572 {
8573 tree d = OMP_CLAUSE_DECL (c);
8574 bool is_ref = is_reference (d);
8575 tree t = d, a, dest;
8576 if (is_ref)
8577 t = build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c), t);
8578 tree type = TREE_TYPE (t);
8579 if (POINTER_TYPE_P (type))
8580 type = sizetype;
8581 dest = unshare_expr (t);
8582 tree v = create_tmp_var (TREE_TYPE (t), NULL);
8583 expand_omp_build_assign (&gsif, v, t);
8584 if (itercnt == NULL_TREE)
8585 {
8586 itercnt = startvar;
8587 tree n1 = fd->loop.n1;
8588 if (POINTER_TYPE_P (TREE_TYPE (itercnt)))
8589 {
8590 itercnt
8591 = fold_convert (signed_type_for (TREE_TYPE (itercnt)),
8592 itercnt);
8593 n1 = fold_convert (TREE_TYPE (itercnt), n1);
8594 }
8595 itercnt = fold_build2 (MINUS_EXPR, TREE_TYPE (itercnt),
8596 itercnt, n1);
8597 itercnt = fold_build2 (EXACT_DIV_EXPR, TREE_TYPE (itercnt),
8598 itercnt, fd->loop.step);
8599 itercnt = force_gimple_operand_gsi (&gsi, itercnt, true,
8600 NULL_TREE, false,
8601 GSI_CONTINUE_LINKING);
8602 }
8603 a = fold_build2 (MULT_EXPR, type,
8604 fold_convert (type, itercnt),
8605 fold_convert (type, OMP_CLAUSE_LINEAR_STEP (c)));
8606 t = fold_build2 (type == TREE_TYPE (t) ? PLUS_EXPR
8607 : POINTER_PLUS_EXPR, TREE_TYPE (t), v, a);
8608 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8609 false, GSI_CONTINUE_LINKING);
8610 assign_stmt = gimple_build_assign (dest, t);
8611 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
8612 }
74bf76ed 8613 if (fd->collapse > 1)
acf0174b 8614 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
50674e96 8615
d9a6bd32
JJ
8616 if (fd->ordered)
8617 {
8618 /* Until now, counts array contained number of iterations or
8619 variable containing it for ith loop. From now on, we need
8620 those counts only for collapsed loops, and only for the 2nd
8621 till the last collapsed one. Move those one element earlier,
8622 we'll use counts[fd->collapse - 1] for the first source/sink
8623 iteration counter and so on and counts[fd->ordered]
8624 as the array holding the current counter values for
8625 depend(source). */
8626 if (fd->collapse > 1)
8627 memmove (counts, counts + 1, (fd->collapse - 1) * sizeof (counts[0]));
8628 if (broken_loop)
8629 {
8630 int i;
8631 for (i = fd->collapse; i < fd->ordered; i++)
8632 {
8633 tree type = TREE_TYPE (fd->loops[i].v);
8634 tree this_cond
8635 = fold_build2 (fd->loops[i].cond_code, boolean_type_node,
8636 fold_convert (type, fd->loops[i].n1),
8637 fold_convert (type, fd->loops[i].n2));
8638 if (!integer_onep (this_cond))
8639 break;
8640 }
8641 if (i < fd->ordered)
8642 {
8643 cont_bb
8644 = create_empty_bb (EXIT_BLOCK_PTR_FOR_FN (cfun)->prev_bb);
8645 add_bb_to_loop (cont_bb, l1_bb->loop_father);
8646 gimple_stmt_iterator gsi = gsi_after_labels (cont_bb);
8647 gimple *g = gimple_build_omp_continue (fd->loop.v, fd->loop.v);
8648 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
8649 make_edge (cont_bb, l3_bb, EDGE_FALLTHRU);
8650 make_edge (cont_bb, l1_bb, 0);
8651 l2_bb = create_empty_bb (cont_bb);
8652 broken_loop = false;
8653 }
8654 }
8655 expand_omp_ordered_source_sink (region, fd, counts, cont_bb);
8656 cont_bb = expand_omp_for_ordered_loops (fd, counts, cont_bb, l1_bb,
8657 ordered_lastprivate);
8658 if (counts[fd->collapse - 1])
8659 {
8660 gcc_assert (fd->collapse == 1);
8661 gsi = gsi_last_bb (l0_bb);
8662 expand_omp_build_assign (&gsi, counts[fd->collapse - 1],
8663 istart0, true);
8664 gsi = gsi_last_bb (cont_bb);
8665 t = fold_build2 (PLUS_EXPR, fd->iter_type, counts[fd->collapse - 1],
8666 build_int_cst (fd->iter_type, 1));
8667 expand_omp_build_assign (&gsi, counts[fd->collapse - 1], t);
8668 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8669 size_zero_node, NULL_TREE, NULL_TREE);
8670 expand_omp_build_assign (&gsi, aref, counts[fd->collapse - 1]);
8671 t = counts[fd->collapse - 1];
8672 }
8673 else if (fd->collapse > 1)
8674 t = fd->loop.v;
8675 else
8676 {
8677 t = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->loops[0].v),
8678 fd->loops[0].v, fd->loops[0].n1);
8679 t = fold_convert (fd->iter_type, t);
8680 }
8681 gsi = gsi_last_bb (l0_bb);
8682 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8683 size_zero_node, NULL_TREE, NULL_TREE);
8684 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8685 false, GSI_CONTINUE_LINKING);
8686 expand_omp_build_assign (&gsi, aref, t, true);
8687 }
8688
e5c95afe 8689 if (!broken_loop)
d3c673c7 8690 {
e5c95afe
ZD
8691 /* Code to control the increment and predicate for the sequential
8692 loop goes in the CONT_BB. */
726a989a 8693 gsi = gsi_last_bb (cont_bb);
538dd0b7
DM
8694 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
8695 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
8696 vmain = gimple_omp_continue_control_use (cont_stmt);
8697 vback = gimple_omp_continue_control_def (cont_stmt);
917948d3 8698
acf0174b 8699 if (!gimple_omp_for_combined_p (fd->for_stmt))
74bf76ed
JJ
8700 {
8701 if (POINTER_TYPE_P (type))
8702 t = fold_build_pointer_plus (vmain, fd->loop.step);
8703 else
8704 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
8705 t = force_gimple_operand_gsi (&gsi, t,
8706 DECL_P (vback)
8707 && TREE_ADDRESSABLE (vback),
8708 NULL_TREE, true, GSI_SAME_STMT);
538dd0b7
DM
8709 assign_stmt = gimple_build_assign (vback, t);
8710 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
74bf76ed 8711
d9a6bd32
JJ
8712 if (fd->ordered && counts[fd->collapse - 1] == NULL_TREE)
8713 {
8714 if (fd->collapse > 1)
8715 t = fd->loop.v;
8716 else
8717 {
8718 t = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->loops[0].v),
8719 fd->loops[0].v, fd->loops[0].n1);
8720 t = fold_convert (fd->iter_type, t);
8721 }
8722 tree aref = build4 (ARRAY_REF, fd->iter_type,
8723 counts[fd->ordered], size_zero_node,
8724 NULL_TREE, NULL_TREE);
8725 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8726 true, GSI_SAME_STMT);
8727 expand_omp_build_assign (&gsi, aref, t);
8728 }
8729
74bf76ed
JJ
8730 t = build2 (fd->loop.cond_code, boolean_type_node,
8731 DECL_P (vback) && TREE_ADDRESSABLE (vback) ? t : vback,
8732 iend);
538dd0b7
DM
8733 gcond *cond_stmt = gimple_build_cond_empty (t);
8734 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
74bf76ed 8735 }
50674e96 8736
726a989a
RB
8737 /* Remove GIMPLE_OMP_CONTINUE. */
8738 gsi_remove (&gsi, true);
50674e96 8739
acf0174b 8740 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
74bf76ed 8741 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, l1_bb);
a68ab351 8742
e5c95afe 8743 /* Emit code to get the next parallel iteration in L2_BB. */
726a989a 8744 gsi = gsi_start_bb (l2_bb);
50674e96 8745
e79983f4 8746 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
e5c95afe
ZD
8747 build_fold_addr_expr (istart0),
8748 build_fold_addr_expr (iend0));
726a989a
RB
8749 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8750 false, GSI_CONTINUE_LINKING);
a68ab351
JJ
8751 if (TREE_TYPE (t) != boolean_type_node)
8752 t = fold_build2 (NE_EXPR, boolean_type_node,
8753 t, build_int_cst (TREE_TYPE (t), 0));
538dd0b7
DM
8754 gcond *cond_stmt = gimple_build_cond_empty (t);
8755 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
e5c95afe 8756 }
953ff289 8757
777f7f9a 8758 /* Add the loop cleanup function. */
726a989a
RB
8759 gsi = gsi_last_bb (exit_bb);
8760 if (gimple_omp_return_nowait_p (gsi_stmt (gsi)))
e79983f4 8761 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
acf0174b
JJ
8762 else if (gimple_omp_return_lhs (gsi_stmt (gsi)))
8763 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL);
777f7f9a 8764 else
e79983f4 8765 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END);
538dd0b7 8766 gcall *call_stmt = gimple_build_call (t, 0);
acf0174b 8767 if (gimple_omp_return_lhs (gsi_stmt (gsi)))
538dd0b7
DM
8768 gimple_call_set_lhs (call_stmt, gimple_omp_return_lhs (gsi_stmt (gsi)));
8769 gsi_insert_after (&gsi, call_stmt, GSI_SAME_STMT);
d9a6bd32
JJ
8770 if (fd->ordered)
8771 {
8772 tree arr = counts[fd->ordered];
8773 tree clobber = build_constructor (TREE_TYPE (arr), NULL);
8774 TREE_THIS_VOLATILE (clobber) = 1;
8775 gsi_insert_after (&gsi, gimple_build_assign (arr, clobber),
8776 GSI_SAME_STMT);
8777 }
726a989a 8778 gsi_remove (&gsi, true);
50674e96
DN
8779
8780 /* Connect the new blocks. */
917948d3
ZD
8781 find_edge (entry_bb, l0_bb)->flags = EDGE_TRUE_VALUE;
8782 find_edge (entry_bb, l3_bb)->flags = EDGE_FALSE_VALUE;
953ff289 8783
e5c95afe
ZD
8784 if (!broken_loop)
8785 {
726a989a
RB
8786 gimple_seq phis;
8787
917948d3
ZD
8788 e = find_edge (cont_bb, l3_bb);
8789 ne = make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
8790
726a989a
RB
8791 phis = phi_nodes (l3_bb);
8792 for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi))
8793 {
355fe088 8794 gimple *phi = gsi_stmt (gsi);
726a989a
RB
8795 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, ne),
8796 PHI_ARG_DEF_FROM_EDGE (phi, e));
8797 }
917948d3
ZD
8798 remove_edge (e);
8799
e5c95afe 8800 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
74bf76ed 8801 e = find_edge (cont_bb, l1_bb);
7aab672f
TV
8802 if (e == NULL)
8803 {
8804 e = BRANCH_EDGE (cont_bb);
8805 gcc_assert (single_succ (e->dest) == l1_bb);
8806 }
acf0174b
JJ
8807 if (gimple_omp_for_combined_p (fd->for_stmt))
8808 {
8809 remove_edge (e);
8810 e = NULL;
8811 }
74bf76ed 8812 else if (fd->collapse > 1)
a68ab351 8813 {
a68ab351
JJ
8814 remove_edge (e);
8815 e = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
8816 }
8817 else
74bf76ed
JJ
8818 e->flags = EDGE_TRUE_VALUE;
8819 if (e)
a68ab351 8820 {
74bf76ed
JJ
8821 e->probability = REG_BR_PROB_BASE * 7 / 8;
8822 find_edge (cont_bb, l2_bb)->probability = REG_BR_PROB_BASE / 8;
8823 }
8824 else
8825 {
8826 e = find_edge (cont_bb, l2_bb);
8827 e->flags = EDGE_FALLTHRU;
a68ab351 8828 }
e5c95afe 8829 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
917948d3 8830
56102c7f
TV
8831 if (gimple_in_ssa_p (cfun))
8832 {
8833 /* Add phis to the outer loop that connect to the phis in the inner,
8834 original loop, and move the loop entry value of the inner phi to
8835 the loop entry value of the outer phi. */
8836 gphi_iterator psi;
8837 for (psi = gsi_start_phis (l3_bb); !gsi_end_p (psi); gsi_next (&psi))
8838 {
8839 source_location locus;
8840 gphi *nphi;
8841 gphi *exit_phi = psi.phi ();
8842
8843 edge l2_to_l3 = find_edge (l2_bb, l3_bb);
8844 tree exit_res = PHI_ARG_DEF_FROM_EDGE (exit_phi, l2_to_l3);
8845
8846 basic_block latch = BRANCH_EDGE (cont_bb)->dest;
8847 edge latch_to_l1 = find_edge (latch, l1_bb);
8848 gphi *inner_phi
8849 = find_phi_with_arg_on_edge (exit_res, latch_to_l1);
8850
8851 tree t = gimple_phi_result (exit_phi);
8852 tree new_res = copy_ssa_name (t, NULL);
8853 nphi = create_phi_node (new_res, l0_bb);
8854
8855 edge l0_to_l1 = find_edge (l0_bb, l1_bb);
8856 t = PHI_ARG_DEF_FROM_EDGE (inner_phi, l0_to_l1);
8857 locus = gimple_phi_arg_location_from_edge (inner_phi, l0_to_l1);
8858 edge entry_to_l0 = find_edge (entry_bb, l0_bb);
8859 add_phi_arg (nphi, t, entry_to_l0, locus);
8860
8861 edge l2_to_l0 = find_edge (l2_bb, l0_bb);
8862 add_phi_arg (nphi, exit_res, l2_to_l0, UNKNOWN_LOCATION);
8863
8864 add_phi_arg (inner_phi, new_res, l0_to_l1, UNKNOWN_LOCATION);
8865 };
8866 }
8867
917948d3
ZD
8868 set_immediate_dominator (CDI_DOMINATORS, l2_bb,
8869 recompute_dominator (CDI_DOMINATORS, l2_bb));
8870 set_immediate_dominator (CDI_DOMINATORS, l3_bb,
8871 recompute_dominator (CDI_DOMINATORS, l3_bb));
8872 set_immediate_dominator (CDI_DOMINATORS, l0_bb,
8873 recompute_dominator (CDI_DOMINATORS, l0_bb));
8874 set_immediate_dominator (CDI_DOMINATORS, l1_bb,
8875 recompute_dominator (CDI_DOMINATORS, l1_bb));
6093bc06 8876
7fd103ef
TV
8877 /* We enter expand_omp_for_generic with a loop. This original loop may
8878 have its own loop struct, or it may be part of an outer loop struct
8879 (which may be the fake loop). */
8880 struct loop *outer_loop = entry_bb->loop_father;
8881 bool orig_loop_has_loop_struct = l1_bb->loop_father != outer_loop;
8882
8883 add_bb_to_loop (l2_bb, outer_loop);
8884
8885 /* We've added a new loop around the original loop. Allocate the
8886 corresponding loop struct. */
8887 struct loop *new_loop = alloc_loop ();
8888 new_loop->header = l0_bb;
8889 new_loop->latch = l2_bb;
8890 add_loop (new_loop, outer_loop);
8891
8892 /* Allocate a loop structure for the original loop unless we already
8893 had one. */
8894 if (!orig_loop_has_loop_struct
8895 && !gimple_omp_for_combined_p (fd->for_stmt))
74bf76ed 8896 {
7fd103ef
TV
8897 struct loop *orig_loop = alloc_loop ();
8898 orig_loop->header = l1_bb;
74bf76ed 8899 /* The loop may have multiple latches. */
7fd103ef 8900 add_loop (orig_loop, new_loop);
74bf76ed 8901 }
e5c95afe 8902 }
953ff289
DN
8903}
8904
8905
50674e96
DN
8906/* A subroutine of expand_omp_for. Generate code for a parallel
8907 loop with static schedule and no specified chunk size. Given
8908 parameters:
953ff289
DN
8909
8910 for (V = N1; V cond N2; V += STEP) BODY;
8911
8912 where COND is "<" or ">", we generate pseudocode
8913
5a0f4dd3 8914 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
953ff289
DN
8915 if (cond is <)
8916 adj = STEP - 1;
8917 else
8918 adj = STEP + 1;
a68ab351
JJ
8919 if ((__typeof (V)) -1 > 0 && cond is >)
8920 n = -(adj + N2 - N1) / -STEP;
8921 else
8922 n = (adj + N2 - N1) / STEP;
953ff289 8923 q = n / nthreads;
fb79f500
JJ
8924 tt = n % nthreads;
8925 if (threadid < tt) goto L3; else goto L4;
8926 L3:
8927 tt = 0;
8928 q = q + 1;
8929 L4:
8930 s0 = q * threadid + tt;
8931 e0 = s0 + q;
917948d3 8932 V = s0 * STEP + N1;
953ff289
DN
8933 if (s0 >= e0) goto L2; else goto L0;
8934 L0:
953ff289
DN
8935 e = e0 * STEP + N1;
8936 L1:
8937 BODY;
8938 V += STEP;
8939 if (V cond e) goto L1;
953ff289
DN
8940 L2:
8941*/
8942
777f7f9a 8943static void
50674e96 8944expand_omp_for_static_nochunk (struct omp_region *region,
acf0174b 8945 struct omp_for_data *fd,
355fe088 8946 gimple *inner_stmt)
953ff289 8947{
fb79f500 8948 tree n, q, s0, e0, e, t, tt, nthreads, threadid;
a68ab351 8949 tree type, itype, vmain, vback;
fb79f500 8950 basic_block entry_bb, second_bb, third_bb, exit_bb, seq_start_bb;
acf0174b 8951 basic_block body_bb, cont_bb, collapse_bb = NULL;
777f7f9a 8952 basic_block fin_bb;
726a989a 8953 gimple_stmt_iterator gsi;
fb79f500 8954 edge ep;
acf0174b
JJ
8955 bool broken_loop = region->cont == NULL;
8956 tree *counts = NULL;
8957 tree n1, n2, step;
953ff289 8958
a68ab351
JJ
8959 itype = type = TREE_TYPE (fd->loop.v);
8960 if (POINTER_TYPE_P (type))
96f9265a 8961 itype = signed_type_for (type);
953ff289 8962
777f7f9a 8963 entry_bb = region->entry;
777f7f9a 8964 cont_bb = region->cont;
e5c95afe 8965 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
acf0174b
JJ
8966 fin_bb = BRANCH_EDGE (entry_bb)->dest;
8967 gcc_assert (broken_loop
8968 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
e5c95afe
ZD
8969 seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb));
8970 body_bb = single_succ (seq_start_bb);
acf0174b
JJ
8971 if (!broken_loop)
8972 {
e67d7a1e
TV
8973 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb
8974 || single_succ (BRANCH_EDGE (cont_bb)->dest) == body_bb);
acf0174b
JJ
8975 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
8976 }
777f7f9a
RH
8977 exit_bb = region->exit;
8978
50674e96 8979 /* Iteration space partitioning goes in ENTRY_BB. */
726a989a
RB
8980 gsi = gsi_last_bb (entry_bb);
8981 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
777f7f9a 8982
acf0174b
JJ
8983 if (fd->collapse > 1)
8984 {
d9a6bd32
JJ
8985 int first_zero_iter = -1, dummy = -1;
8986 basic_block l2_dom_bb = NULL, dummy_bb = NULL;
acf0174b
JJ
8987
8988 counts = XALLOCAVEC (tree, fd->collapse);
8989 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
8990 fin_bb, first_zero_iter,
d9a6bd32 8991 dummy_bb, dummy, l2_dom_bb);
acf0174b
JJ
8992 t = NULL_TREE;
8993 }
8994 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
8995 t = integer_one_node;
8996 else
8997 t = fold_binary (fd->loop.cond_code, boolean_type_node,
8998 fold_convert (type, fd->loop.n1),
8999 fold_convert (type, fd->loop.n2));
9000 if (fd->collapse == 1
9001 && TYPE_UNSIGNED (type)
5a0f4dd3
JJ
9002 && (t == NULL_TREE || !integer_onep (t)))
9003 {
5a0f4dd3
JJ
9004 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
9005 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
9006 true, GSI_SAME_STMT);
9007 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
9008 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
9009 true, GSI_SAME_STMT);
538dd0b7
DM
9010 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
9011 NULL_TREE, NULL_TREE);
9012 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
9013 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
5a0f4dd3 9014 expand_omp_regimplify_p, NULL, NULL)
538dd0b7 9015 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
5a0f4dd3
JJ
9016 expand_omp_regimplify_p, NULL, NULL))
9017 {
538dd0b7
DM
9018 gsi = gsi_for_stmt (cond_stmt);
9019 gimple_regimplify_operands (cond_stmt, &gsi);
5a0f4dd3 9020 }
538dd0b7 9021 ep = split_block (entry_bb, cond_stmt);
5a0f4dd3
JJ
9022 ep->flags = EDGE_TRUE_VALUE;
9023 entry_bb = ep->dest;
9024 ep->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
9025 ep = make_edge (ep->src, fin_bb, EDGE_FALSE_VALUE);
9026 ep->probability = REG_BR_PROB_BASE / 2000 - 1;
9027 if (gimple_in_ssa_p (cfun))
9028 {
9029 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
538dd0b7
DM
9030 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
9031 !gsi_end_p (gpi); gsi_next (&gpi))
5a0f4dd3 9032 {
538dd0b7 9033 gphi *phi = gpi.phi ();
5a0f4dd3
JJ
9034 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
9035 ep, UNKNOWN_LOCATION);
9036 }
9037 }
9038 gsi = gsi_last_bb (entry_bb);
9039 }
9040
41dbbb37
TS
9041 switch (gimple_omp_for_kind (fd->for_stmt))
9042 {
9043 case GF_OMP_FOR_KIND_FOR:
9044 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
9045 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
9046 break;
9047 case GF_OMP_FOR_KIND_DISTRIBUTE:
9048 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
9049 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
9050 break;
41dbbb37
TS
9051 default:
9052 gcc_unreachable ();
9053 }
9054 nthreads = build_call_expr (nthreads, 0);
9055 nthreads = fold_convert (itype, nthreads);
9056 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
726a989a 9057 true, GSI_SAME_STMT);
41dbbb37
TS
9058 threadid = build_call_expr (threadid, 0);
9059 threadid = fold_convert (itype, threadid);
9060 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
726a989a 9061 true, GSI_SAME_STMT);
953ff289 9062
acf0174b
JJ
9063 n1 = fd->loop.n1;
9064 n2 = fd->loop.n2;
9065 step = fd->loop.step;
9066 if (gimple_omp_for_combined_into_p (fd->for_stmt))
9067 {
9068 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
9069 OMP_CLAUSE__LOOPTEMP_);
9070 gcc_assert (innerc);
9071 n1 = OMP_CLAUSE_DECL (innerc);
9072 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9073 OMP_CLAUSE__LOOPTEMP_);
9074 gcc_assert (innerc);
9075 n2 = OMP_CLAUSE_DECL (innerc);
9076 }
9077 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
9078 true, NULL_TREE, true, GSI_SAME_STMT);
9079 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
9080 true, NULL_TREE, true, GSI_SAME_STMT);
9081 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
9082 true, NULL_TREE, true, GSI_SAME_STMT);
a68ab351
JJ
9083
9084 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
acf0174b
JJ
9085 t = fold_build2 (PLUS_EXPR, itype, step, t);
9086 t = fold_build2 (PLUS_EXPR, itype, t, n2);
9087 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
a68ab351
JJ
9088 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
9089 t = fold_build2 (TRUNC_DIV_EXPR, itype,
9090 fold_build1 (NEGATE_EXPR, itype, t),
acf0174b 9091 fold_build1 (NEGATE_EXPR, itype, step));
a68ab351 9092 else
acf0174b 9093 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
a68ab351 9094 t = fold_convert (itype, t);
726a989a 9095 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
953ff289 9096
7cc434a3 9097 q = create_tmp_reg (itype, "q");
a68ab351 9098 t = fold_build2 (TRUNC_DIV_EXPR, itype, n, nthreads);
fb79f500
JJ
9099 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
9100 gsi_insert_before (&gsi, gimple_build_assign (q, t), GSI_SAME_STMT);
9101
7cc434a3 9102 tt = create_tmp_reg (itype, "tt");
fb79f500
JJ
9103 t = fold_build2 (TRUNC_MOD_EXPR, itype, n, nthreads);
9104 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
9105 gsi_insert_before (&gsi, gimple_build_assign (tt, t), GSI_SAME_STMT);
953ff289 9106
fb79f500 9107 t = build2 (LT_EXPR, boolean_type_node, threadid, tt);
538dd0b7
DM
9108 gcond *cond_stmt = gimple_build_cond_empty (t);
9109 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
fb79f500 9110
538dd0b7 9111 second_bb = split_block (entry_bb, cond_stmt)->dest;
fb79f500
JJ
9112 gsi = gsi_last_bb (second_bb);
9113 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
9114
9115 gsi_insert_before (&gsi, gimple_build_assign (tt, build_int_cst (itype, 0)),
9116 GSI_SAME_STMT);
538dd0b7 9117 gassign *assign_stmt
0d0e4a03 9118 = gimple_build_assign (q, PLUS_EXPR, q, build_int_cst (itype, 1));
538dd0b7 9119 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
fb79f500 9120
538dd0b7 9121 third_bb = split_block (second_bb, assign_stmt)->dest;
fb79f500
JJ
9122 gsi = gsi_last_bb (third_bb);
9123 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
953ff289 9124
a68ab351 9125 t = build2 (MULT_EXPR, itype, q, threadid);
fb79f500 9126 t = build2 (PLUS_EXPR, itype, t, tt);
726a989a 9127 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
953ff289 9128
a68ab351 9129 t = fold_build2 (PLUS_EXPR, itype, s0, q);
726a989a 9130 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
917948d3 9131
953ff289 9132 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
726a989a 9133 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
50674e96 9134
726a989a
RB
9135 /* Remove the GIMPLE_OMP_FOR statement. */
9136 gsi_remove (&gsi, true);
50674e96
DN
9137
9138 /* Setup code for sequential iteration goes in SEQ_START_BB. */
726a989a 9139 gsi = gsi_start_bb (seq_start_bb);
953ff289 9140
acf0174b
JJ
9141 tree startvar = fd->loop.v;
9142 tree endvar = NULL_TREE;
9143
9144 if (gimple_omp_for_combined_p (fd->for_stmt))
9145 {
9146 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
9147 ? gimple_omp_parallel_clauses (inner_stmt)
9148 : gimple_omp_for_clauses (inner_stmt);
9149 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
9150 gcc_assert (innerc);
9151 startvar = OMP_CLAUSE_DECL (innerc);
9152 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9153 OMP_CLAUSE__LOOPTEMP_);
9154 gcc_assert (innerc);
9155 endvar = OMP_CLAUSE_DECL (innerc);
e01d41e5
JJ
9156 if (fd->collapse > 1 && TREE_CODE (fd->loop.n2) != INTEGER_CST
9157 && gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
9158 {
9159 int i;
9160 for (i = 1; i < fd->collapse; i++)
9161 {
9162 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9163 OMP_CLAUSE__LOOPTEMP_);
9164 gcc_assert (innerc);
9165 }
9166 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9167 OMP_CLAUSE__LOOPTEMP_);
9168 if (innerc)
9169 {
9170 /* If needed (distribute parallel for with lastprivate),
9171 propagate down the total number of iterations. */
9172 tree t = fold_convert (TREE_TYPE (OMP_CLAUSE_DECL (innerc)),
9173 fd->loop.n2);
9174 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, false,
9175 GSI_CONTINUE_LINKING);
9176 assign_stmt = gimple_build_assign (OMP_CLAUSE_DECL (innerc), t);
9177 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9178 }
9179 }
acf0174b 9180 }
a68ab351 9181 t = fold_convert (itype, s0);
acf0174b 9182 t = fold_build2 (MULT_EXPR, itype, t, step);
a68ab351 9183 if (POINTER_TYPE_P (type))
acf0174b 9184 t = fold_build_pointer_plus (n1, t);
a68ab351 9185 else
acf0174b
JJ
9186 t = fold_build2 (PLUS_EXPR, type, t, n1);
9187 t = fold_convert (TREE_TYPE (startvar), t);
ea3a0fde 9188 t = force_gimple_operand_gsi (&gsi, t,
acf0174b
JJ
9189 DECL_P (startvar)
9190 && TREE_ADDRESSABLE (startvar),
ea3a0fde 9191 NULL_TREE, false, GSI_CONTINUE_LINKING);
538dd0b7
DM
9192 assign_stmt = gimple_build_assign (startvar, t);
9193 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
b8698a0f 9194
a68ab351 9195 t = fold_convert (itype, e0);
acf0174b 9196 t = fold_build2 (MULT_EXPR, itype, t, step);
a68ab351 9197 if (POINTER_TYPE_P (type))
acf0174b 9198 t = fold_build_pointer_plus (n1, t);
a68ab351 9199 else
acf0174b
JJ
9200 t = fold_build2 (PLUS_EXPR, type, t, n1);
9201 t = fold_convert (TREE_TYPE (startvar), t);
726a989a
RB
9202 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9203 false, GSI_CONTINUE_LINKING);
acf0174b
JJ
9204 if (endvar)
9205 {
538dd0b7
DM
9206 assign_stmt = gimple_build_assign (endvar, e);
9207 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
95782571 9208 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
538dd0b7 9209 assign_stmt = gimple_build_assign (fd->loop.v, e);
95782571 9210 else
0d0e4a03 9211 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
538dd0b7 9212 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
acf0174b 9213 }
d9a6bd32
JJ
9214 /* Handle linear clause adjustments. */
9215 tree itercnt = NULL_TREE;
9216 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_FOR)
9217 for (tree c = gimple_omp_for_clauses (fd->for_stmt);
9218 c; c = OMP_CLAUSE_CHAIN (c))
9219 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
9220 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
9221 {
9222 tree d = OMP_CLAUSE_DECL (c);
9223 bool is_ref = is_reference (d);
9224 tree t = d, a, dest;
9225 if (is_ref)
9226 t = build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c), t);
9227 if (itercnt == NULL_TREE)
9228 {
9229 if (gimple_omp_for_combined_into_p (fd->for_stmt))
9230 {
9231 itercnt = fold_build2 (MINUS_EXPR, itype,
9232 fold_convert (itype, n1),
9233 fold_convert (itype, fd->loop.n1));
9234 itercnt = fold_build2 (EXACT_DIV_EXPR, itype, itercnt, step);
9235 itercnt = fold_build2 (PLUS_EXPR, itype, itercnt, s0);
9236 itercnt = force_gimple_operand_gsi (&gsi, itercnt, true,
9237 NULL_TREE, false,
9238 GSI_CONTINUE_LINKING);
9239 }
9240 else
9241 itercnt = s0;
9242 }
9243 tree type = TREE_TYPE (t);
9244 if (POINTER_TYPE_P (type))
9245 type = sizetype;
9246 a = fold_build2 (MULT_EXPR, type,
9247 fold_convert (type, itercnt),
9248 fold_convert (type, OMP_CLAUSE_LINEAR_STEP (c)));
9249 dest = unshare_expr (t);
9250 t = fold_build2 (type == TREE_TYPE (t) ? PLUS_EXPR
9251 : POINTER_PLUS_EXPR, TREE_TYPE (t), t, a);
9252 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9253 false, GSI_CONTINUE_LINKING);
9254 assign_stmt = gimple_build_assign (dest, t);
9255 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9256 }
acf0174b
JJ
9257 if (fd->collapse > 1)
9258 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
953ff289 9259
acf0174b
JJ
9260 if (!broken_loop)
9261 {
9262 /* The code controlling the sequential loop replaces the
9263 GIMPLE_OMP_CONTINUE. */
9264 gsi = gsi_last_bb (cont_bb);
538dd0b7
DM
9265 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
9266 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
9267 vmain = gimple_omp_continue_control_use (cont_stmt);
9268 vback = gimple_omp_continue_control_def (cont_stmt);
917948d3 9269
acf0174b
JJ
9270 if (!gimple_omp_for_combined_p (fd->for_stmt))
9271 {
9272 if (POINTER_TYPE_P (type))
9273 t = fold_build_pointer_plus (vmain, step);
9274 else
9275 t = fold_build2 (PLUS_EXPR, type, vmain, step);
9276 t = force_gimple_operand_gsi (&gsi, t,
9277 DECL_P (vback)
9278 && TREE_ADDRESSABLE (vback),
9279 NULL_TREE, true, GSI_SAME_STMT);
538dd0b7
DM
9280 assign_stmt = gimple_build_assign (vback, t);
9281 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
917948d3 9282
acf0174b
JJ
9283 t = build2 (fd->loop.cond_code, boolean_type_node,
9284 DECL_P (vback) && TREE_ADDRESSABLE (vback)
9285 ? t : vback, e);
9286 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
9287 }
953ff289 9288
acf0174b
JJ
9289 /* Remove the GIMPLE_OMP_CONTINUE statement. */
9290 gsi_remove (&gsi, true);
9291
9292 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
9293 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
9294 }
50674e96 9295
726a989a
RB
9296 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
9297 gsi = gsi_last_bb (exit_bb);
9298 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
acf0174b
JJ
9299 {
9300 t = gimple_omp_return_lhs (gsi_stmt (gsi));
e4834818 9301 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
acf0174b 9302 }
726a989a 9303 gsi_remove (&gsi, true);
50674e96
DN
9304
9305 /* Connect all the blocks. */
fb79f500
JJ
9306 ep = make_edge (entry_bb, third_bb, EDGE_FALSE_VALUE);
9307 ep->probability = REG_BR_PROB_BASE / 4 * 3;
9308 ep = find_edge (entry_bb, second_bb);
9309 ep->flags = EDGE_TRUE_VALUE;
9310 ep->probability = REG_BR_PROB_BASE / 4;
9311 find_edge (third_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
9312 find_edge (third_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
917948d3 9313
acf0174b
JJ
9314 if (!broken_loop)
9315 {
9316 ep = find_edge (cont_bb, body_bb);
e67d7a1e
TV
9317 if (ep == NULL)
9318 {
9319 ep = BRANCH_EDGE (cont_bb);
9320 gcc_assert (single_succ (ep->dest) == body_bb);
9321 }
acf0174b
JJ
9322 if (gimple_omp_for_combined_p (fd->for_stmt))
9323 {
9324 remove_edge (ep);
9325 ep = NULL;
9326 }
9327 else if (fd->collapse > 1)
9328 {
9329 remove_edge (ep);
9330 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
9331 }
9332 else
9333 ep->flags = EDGE_TRUE_VALUE;
9334 find_edge (cont_bb, fin_bb)->flags
9335 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
9336 }
b8698a0f 9337
fb79f500
JJ
9338 set_immediate_dominator (CDI_DOMINATORS, second_bb, entry_bb);
9339 set_immediate_dominator (CDI_DOMINATORS, third_bb, entry_bb);
9340 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, third_bb);
acf0174b 9341
917948d3
ZD
9342 set_immediate_dominator (CDI_DOMINATORS, body_bb,
9343 recompute_dominator (CDI_DOMINATORS, body_bb));
9344 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
9345 recompute_dominator (CDI_DOMINATORS, fin_bb));
6093bc06 9346
e67d7a1e
TV
9347 struct loop *loop = body_bb->loop_father;
9348 if (loop != entry_bb->loop_father)
9349 {
9350 gcc_assert (loop->header == body_bb);
9351 gcc_assert (broken_loop
9352 || loop->latch == region->cont
9353 || single_pred (loop->latch) == region->cont);
9354 return;
9355 }
9356
acf0174b
JJ
9357 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
9358 {
e67d7a1e 9359 loop = alloc_loop ();
acf0174b
JJ
9360 loop->header = body_bb;
9361 if (collapse_bb == NULL)
9362 loop->latch = cont_bb;
9363 add_loop (loop, body_bb->loop_father);
9364 }
953ff289
DN
9365}
9366
1b96e9a4
TV
9367/* Return phi in E->DEST with ARG on edge E. */
9368
9369static gphi *
9370find_phi_with_arg_on_edge (tree arg, edge e)
9371{
9372 basic_block bb = e->dest;
9373
9374 for (gphi_iterator gpi = gsi_start_phis (bb);
9375 !gsi_end_p (gpi);
9376 gsi_next (&gpi))
9377 {
9378 gphi *phi = gpi.phi ();
9379 if (PHI_ARG_DEF_FROM_EDGE (phi, e) == arg)
9380 return phi;
9381 }
9382
9383 return NULL;
9384}
50674e96
DN
9385
9386/* A subroutine of expand_omp_for. Generate code for a parallel
9387 loop with static schedule and a specified chunk size. Given
9388 parameters:
953ff289
DN
9389
9390 for (V = N1; V cond N2; V += STEP) BODY;
9391
9392 where COND is "<" or ">", we generate pseudocode
9393
5a0f4dd3 9394 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
953ff289
DN
9395 if (cond is <)
9396 adj = STEP - 1;
9397 else
9398 adj = STEP + 1;
a68ab351
JJ
9399 if ((__typeof (V)) -1 > 0 && cond is >)
9400 n = -(adj + N2 - N1) / -STEP;
9401 else
9402 n = (adj + N2 - N1) / STEP;
953ff289 9403 trip = 0;
917948d3
ZD
9404 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
9405 here so that V is defined
9406 if the loop is not entered
953ff289
DN
9407 L0:
9408 s0 = (trip * nthreads + threadid) * CHUNK;
9409 e0 = min(s0 + CHUNK, n);
9410 if (s0 < n) goto L1; else goto L4;
9411 L1:
9412 V = s0 * STEP + N1;
9413 e = e0 * STEP + N1;
9414 L2:
9415 BODY;
9416 V += STEP;
9417 if (V cond e) goto L2; else goto L3;
9418 L3:
9419 trip += 1;
9420 goto L0;
9421 L4:
953ff289
DN
9422*/
9423
777f7f9a 9424static void
acf0174b 9425expand_omp_for_static_chunk (struct omp_region *region,
355fe088 9426 struct omp_for_data *fd, gimple *inner_stmt)
953ff289 9427{
726a989a 9428 tree n, s0, e0, e, t;
917948d3 9429 tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
ed20ae98 9430 tree type, itype, vmain, vback, vextra;
50674e96 9431 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
acf0174b 9432 basic_block trip_update_bb = NULL, cont_bb, collapse_bb = NULL, fin_bb;
ed20ae98 9433 gimple_stmt_iterator gsi;
726a989a 9434 edge se;
acf0174b
JJ
9435 bool broken_loop = region->cont == NULL;
9436 tree *counts = NULL;
9437 tree n1, n2, step;
953ff289 9438
a68ab351
JJ
9439 itype = type = TREE_TYPE (fd->loop.v);
9440 if (POINTER_TYPE_P (type))
96f9265a 9441 itype = signed_type_for (type);
953ff289 9442
777f7f9a 9443 entry_bb = region->entry;
e5c95afe
ZD
9444 se = split_block (entry_bb, last_stmt (entry_bb));
9445 entry_bb = se->src;
9446 iter_part_bb = se->dest;
777f7f9a 9447 cont_bb = region->cont;
e5c95afe 9448 gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
acf0174b
JJ
9449 fin_bb = BRANCH_EDGE (iter_part_bb)->dest;
9450 gcc_assert (broken_loop
9451 || fin_bb == FALLTHRU_EDGE (cont_bb)->dest);
e5c95afe
ZD
9452 seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
9453 body_bb = single_succ (seq_start_bb);
acf0174b
JJ
9454 if (!broken_loop)
9455 {
8cba6b95
TV
9456 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb
9457 || single_succ (BRANCH_EDGE (cont_bb)->dest) == body_bb);
acf0174b
JJ
9458 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
9459 trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
9460 }
777f7f9a 9461 exit_bb = region->exit;
50674e96 9462
50674e96 9463 /* Trip and adjustment setup goes in ENTRY_BB. */
ed20ae98
TS
9464 gsi = gsi_last_bb (entry_bb);
9465 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
50674e96 9466
acf0174b
JJ
9467 if (fd->collapse > 1)
9468 {
d9a6bd32
JJ
9469 int first_zero_iter = -1, dummy = -1;
9470 basic_block l2_dom_bb = NULL, dummy_bb = NULL;
acf0174b
JJ
9471
9472 counts = XALLOCAVEC (tree, fd->collapse);
ed20ae98 9473 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
acf0174b 9474 fin_bb, first_zero_iter,
d9a6bd32 9475 dummy_bb, dummy, l2_dom_bb);
acf0174b
JJ
9476 t = NULL_TREE;
9477 }
9478 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
9479 t = integer_one_node;
9480 else
9481 t = fold_binary (fd->loop.cond_code, boolean_type_node,
9482 fold_convert (type, fd->loop.n1),
9483 fold_convert (type, fd->loop.n2));
9484 if (fd->collapse == 1
9485 && TYPE_UNSIGNED (type)
5a0f4dd3
JJ
9486 && (t == NULL_TREE || !integer_onep (t)))
9487 {
5a0f4dd3 9488 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
ed20ae98 9489 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
5a0f4dd3
JJ
9490 true, GSI_SAME_STMT);
9491 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
ed20ae98 9492 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
5a0f4dd3 9493 true, GSI_SAME_STMT);
538dd0b7
DM
9494 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
9495 NULL_TREE, NULL_TREE);
9496 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
9497 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
5a0f4dd3 9498 expand_omp_regimplify_p, NULL, NULL)
538dd0b7 9499 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
5a0f4dd3
JJ
9500 expand_omp_regimplify_p, NULL, NULL))
9501 {
538dd0b7
DM
9502 gsi = gsi_for_stmt (cond_stmt);
9503 gimple_regimplify_operands (cond_stmt, &gsi);
5a0f4dd3 9504 }
538dd0b7 9505 se = split_block (entry_bb, cond_stmt);
5a0f4dd3
JJ
9506 se->flags = EDGE_TRUE_VALUE;
9507 entry_bb = se->dest;
9508 se->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
9509 se = make_edge (se->src, fin_bb, EDGE_FALSE_VALUE);
9510 se->probability = REG_BR_PROB_BASE / 2000 - 1;
9511 if (gimple_in_ssa_p (cfun))
9512 {
17720e84 9513 int dest_idx = find_edge (iter_part_bb, fin_bb)->dest_idx;
538dd0b7
DM
9514 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
9515 !gsi_end_p (gpi); gsi_next (&gpi))
5a0f4dd3 9516 {
538dd0b7 9517 gphi *phi = gpi.phi ();
5a0f4dd3
JJ
9518 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
9519 se, UNKNOWN_LOCATION);
9520 }
9521 }
ed20ae98 9522 gsi = gsi_last_bb (entry_bb);
5a0f4dd3
JJ
9523 }
9524
41dbbb37
TS
9525 switch (gimple_omp_for_kind (fd->for_stmt))
9526 {
9527 case GF_OMP_FOR_KIND_FOR:
9528 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
9529 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
9530 break;
9531 case GF_OMP_FOR_KIND_DISTRIBUTE:
9532 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
9533 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
9534 break;
41dbbb37
TS
9535 default:
9536 gcc_unreachable ();
9537 }
9538 nthreads = build_call_expr (nthreads, 0);
9539 nthreads = fold_convert (itype, nthreads);
9540 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
726a989a 9541 true, GSI_SAME_STMT);
41dbbb37
TS
9542 threadid = build_call_expr (threadid, 0);
9543 threadid = fold_convert (itype, threadid);
9544 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
726a989a 9545 true, GSI_SAME_STMT);
917948d3 9546
acf0174b
JJ
9547 n1 = fd->loop.n1;
9548 n2 = fd->loop.n2;
9549 step = fd->loop.step;
9550 if (gimple_omp_for_combined_into_p (fd->for_stmt))
9551 {
9552 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
9553 OMP_CLAUSE__LOOPTEMP_);
9554 gcc_assert (innerc);
9555 n1 = OMP_CLAUSE_DECL (innerc);
9556 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9557 OMP_CLAUSE__LOOPTEMP_);
9558 gcc_assert (innerc);
9559 n2 = OMP_CLAUSE_DECL (innerc);
9560 }
ed20ae98 9561 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
acf0174b 9562 true, NULL_TREE, true, GSI_SAME_STMT);
ed20ae98 9563 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
acf0174b 9564 true, NULL_TREE, true, GSI_SAME_STMT);
ed20ae98 9565 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
acf0174b 9566 true, NULL_TREE, true, GSI_SAME_STMT);
d9a6bd32
JJ
9567 tree chunk_size = fold_convert (itype, fd->chunk_size);
9568 chunk_size = omp_adjust_chunk_size (chunk_size, fd->simd_schedule);
9569 chunk_size
9570 = force_gimple_operand_gsi (&gsi, chunk_size, true, NULL_TREE, true,
9571 GSI_SAME_STMT);
a68ab351
JJ
9572
9573 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
acf0174b
JJ
9574 t = fold_build2 (PLUS_EXPR, itype, step, t);
9575 t = fold_build2 (PLUS_EXPR, itype, t, n2);
9576 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
a68ab351
JJ
9577 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
9578 t = fold_build2 (TRUNC_DIV_EXPR, itype,
9579 fold_build1 (NEGATE_EXPR, itype, t),
acf0174b 9580 fold_build1 (NEGATE_EXPR, itype, step));
a68ab351 9581 else
acf0174b 9582 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
a68ab351 9583 t = fold_convert (itype, t);
ed20ae98 9584 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
726a989a 9585 true, GSI_SAME_STMT);
917948d3 9586
a5efada7 9587 trip_var = create_tmp_reg (itype, ".trip");
917948d3
ZD
9588 if (gimple_in_ssa_p (cfun))
9589 {
b731b390
JJ
9590 trip_init = make_ssa_name (trip_var);
9591 trip_main = make_ssa_name (trip_var);
9592 trip_back = make_ssa_name (trip_var);
917948d3 9593 }
953ff289 9594 else
917948d3
ZD
9595 {
9596 trip_init = trip_var;
9597 trip_main = trip_var;
9598 trip_back = trip_var;
9599 }
953ff289 9600
538dd0b7
DM
9601 gassign *assign_stmt
9602 = gimple_build_assign (trip_init, build_int_cst (itype, 0));
9603 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
50674e96 9604
d9a6bd32 9605 t = fold_build2 (MULT_EXPR, itype, threadid, chunk_size);
acf0174b 9606 t = fold_build2 (MULT_EXPR, itype, t, step);
a68ab351 9607 if (POINTER_TYPE_P (type))
acf0174b 9608 t = fold_build_pointer_plus (n1, t);
a68ab351 9609 else
acf0174b 9610 t = fold_build2 (PLUS_EXPR, type, t, n1);
ed20ae98
TS
9611 vextra = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9612 true, GSI_SAME_STMT);
917948d3 9613
726a989a 9614 /* Remove the GIMPLE_OMP_FOR. */
ed20ae98 9615 gsi_remove (&gsi, true);
50674e96 9616
d9a6bd32
JJ
9617 gimple_stmt_iterator gsif = gsi;
9618
50674e96 9619 /* Iteration space partitioning goes in ITER_PART_BB. */
ed20ae98 9620 gsi = gsi_last_bb (iter_part_bb);
953ff289 9621
a68ab351
JJ
9622 t = fold_build2 (MULT_EXPR, itype, trip_main, nthreads);
9623 t = fold_build2 (PLUS_EXPR, itype, t, threadid);
d9a6bd32 9624 t = fold_build2 (MULT_EXPR, itype, t, chunk_size);
ed20ae98 9625 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
726a989a 9626 false, GSI_CONTINUE_LINKING);
953ff289 9627
d9a6bd32 9628 t = fold_build2 (PLUS_EXPR, itype, s0, chunk_size);
a68ab351 9629 t = fold_build2 (MIN_EXPR, itype, t, n);
ed20ae98 9630 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
726a989a 9631 false, GSI_CONTINUE_LINKING);
953ff289
DN
9632
9633 t = build2 (LT_EXPR, boolean_type_node, s0, n);
ed20ae98 9634 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_CONTINUE_LINKING);
50674e96
DN
9635
9636 /* Setup code for sequential iteration goes in SEQ_START_BB. */
ed20ae98 9637 gsi = gsi_start_bb (seq_start_bb);
953ff289 9638
acf0174b
JJ
9639 tree startvar = fd->loop.v;
9640 tree endvar = NULL_TREE;
9641
9642 if (gimple_omp_for_combined_p (fd->for_stmt))
9643 {
9644 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
9645 ? gimple_omp_parallel_clauses (inner_stmt)
9646 : gimple_omp_for_clauses (inner_stmt);
9647 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
9648 gcc_assert (innerc);
9649 startvar = OMP_CLAUSE_DECL (innerc);
9650 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9651 OMP_CLAUSE__LOOPTEMP_);
9652 gcc_assert (innerc);
9653 endvar = OMP_CLAUSE_DECL (innerc);
e01d41e5
JJ
9654 if (fd->collapse > 1 && TREE_CODE (fd->loop.n2) != INTEGER_CST
9655 && gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
9656 {
9657 int i;
9658 for (i = 1; i < fd->collapse; i++)
9659 {
9660 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9661 OMP_CLAUSE__LOOPTEMP_);
9662 gcc_assert (innerc);
9663 }
9664 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9665 OMP_CLAUSE__LOOPTEMP_);
9666 if (innerc)
9667 {
9668 /* If needed (distribute parallel for with lastprivate),
9669 propagate down the total number of iterations. */
9670 tree t = fold_convert (TREE_TYPE (OMP_CLAUSE_DECL (innerc)),
9671 fd->loop.n2);
9672 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, false,
9673 GSI_CONTINUE_LINKING);
9674 assign_stmt = gimple_build_assign (OMP_CLAUSE_DECL (innerc), t);
9675 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9676 }
9677 }
acf0174b
JJ
9678 }
9679
a68ab351 9680 t = fold_convert (itype, s0);
acf0174b 9681 t = fold_build2 (MULT_EXPR, itype, t, step);
a68ab351 9682 if (POINTER_TYPE_P (type))
acf0174b 9683 t = fold_build_pointer_plus (n1, t);
a68ab351 9684 else
acf0174b
JJ
9685 t = fold_build2 (PLUS_EXPR, type, t, n1);
9686 t = fold_convert (TREE_TYPE (startvar), t);
ed20ae98 9687 t = force_gimple_operand_gsi (&gsi, t,
acf0174b
JJ
9688 DECL_P (startvar)
9689 && TREE_ADDRESSABLE (startvar),
ea3a0fde 9690 NULL_TREE, false, GSI_CONTINUE_LINKING);
538dd0b7
DM
9691 assign_stmt = gimple_build_assign (startvar, t);
9692 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
953ff289 9693
a68ab351 9694 t = fold_convert (itype, e0);
acf0174b 9695 t = fold_build2 (MULT_EXPR, itype, t, step);
a68ab351 9696 if (POINTER_TYPE_P (type))
acf0174b 9697 t = fold_build_pointer_plus (n1, t);
a68ab351 9698 else
acf0174b
JJ
9699 t = fold_build2 (PLUS_EXPR, type, t, n1);
9700 t = fold_convert (TREE_TYPE (startvar), t);
ed20ae98 9701 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
726a989a 9702 false, GSI_CONTINUE_LINKING);
acf0174b
JJ
9703 if (endvar)
9704 {
538dd0b7
DM
9705 assign_stmt = gimple_build_assign (endvar, e);
9706 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
95782571 9707 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
538dd0b7 9708 assign_stmt = gimple_build_assign (fd->loop.v, e);
95782571 9709 else
0d0e4a03 9710 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
538dd0b7 9711 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
acf0174b 9712 }
d9a6bd32
JJ
9713 /* Handle linear clause adjustments. */
9714 tree itercnt = NULL_TREE, itercntbias = NULL_TREE;
9715 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_FOR)
9716 for (tree c = gimple_omp_for_clauses (fd->for_stmt);
9717 c; c = OMP_CLAUSE_CHAIN (c))
9718 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
9719 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
9720 {
9721 tree d = OMP_CLAUSE_DECL (c);
9722 bool is_ref = is_reference (d);
9723 tree t = d, a, dest;
9724 if (is_ref)
9725 t = build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c), t);
9726 tree type = TREE_TYPE (t);
9727 if (POINTER_TYPE_P (type))
9728 type = sizetype;
9729 dest = unshare_expr (t);
9730 tree v = create_tmp_var (TREE_TYPE (t), NULL);
9731 expand_omp_build_assign (&gsif, v, t);
9732 if (itercnt == NULL_TREE)
9733 {
9734 if (gimple_omp_for_combined_into_p (fd->for_stmt))
9735 {
9736 itercntbias
9737 = fold_build2 (MINUS_EXPR, itype, fold_convert (itype, n1),
9738 fold_convert (itype, fd->loop.n1));
9739 itercntbias = fold_build2 (EXACT_DIV_EXPR, itype,
9740 itercntbias, step);
9741 itercntbias
9742 = force_gimple_operand_gsi (&gsif, itercntbias, true,
9743 NULL_TREE, true,
9744 GSI_SAME_STMT);
9745 itercnt = fold_build2 (PLUS_EXPR, itype, itercntbias, s0);
9746 itercnt = force_gimple_operand_gsi (&gsi, itercnt, true,
9747 NULL_TREE, false,
9748 GSI_CONTINUE_LINKING);
9749 }
9750 else
9751 itercnt = s0;
9752 }
9753 a = fold_build2 (MULT_EXPR, type,
9754 fold_convert (type, itercnt),
9755 fold_convert (type, OMP_CLAUSE_LINEAR_STEP (c)));
9756 t = fold_build2 (type == TREE_TYPE (t) ? PLUS_EXPR
9757 : POINTER_PLUS_EXPR, TREE_TYPE (t), v, a);
9758 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9759 false, GSI_CONTINUE_LINKING);
9760 assign_stmt = gimple_build_assign (dest, t);
9761 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9762 }
acf0174b 9763 if (fd->collapse > 1)
ed20ae98 9764 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
acf0174b
JJ
9765
9766 if (!broken_loop)
9767 {
9768 /* The code controlling the sequential loop goes in CONT_BB,
9769 replacing the GIMPLE_OMP_CONTINUE. */
ed20ae98 9770 gsi = gsi_last_bb (cont_bb);
538dd0b7
DM
9771 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
9772 vmain = gimple_omp_continue_control_use (cont_stmt);
9773 vback = gimple_omp_continue_control_def (cont_stmt);
953ff289 9774
acf0174b
JJ
9775 if (!gimple_omp_for_combined_p (fd->for_stmt))
9776 {
9777 if (POINTER_TYPE_P (type))
ed20ae98 9778 t = fold_build_pointer_plus (vmain, step);
acf0174b 9779 else
ed20ae98
TS
9780 t = fold_build2 (PLUS_EXPR, type, vmain, step);
9781 if (DECL_P (vback) && TREE_ADDRESSABLE (vback))
9782 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
acf0174b 9783 true, GSI_SAME_STMT);
538dd0b7
DM
9784 assign_stmt = gimple_build_assign (vback, t);
9785 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
917948d3 9786
6be5c241
TV
9787 if (tree_int_cst_equal (fd->chunk_size, integer_one_node))
9788 t = build2 (EQ_EXPR, boolean_type_node,
9789 build_int_cst (itype, 0),
9790 build_int_cst (itype, 1));
9791 else
9792 t = build2 (fd->loop.cond_code, boolean_type_node,
9793 DECL_P (vback) && TREE_ADDRESSABLE (vback)
9794 ? t : vback, e);
ed20ae98 9795 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
acf0174b 9796 }
917948d3 9797
acf0174b 9798 /* Remove GIMPLE_OMP_CONTINUE. */
ed20ae98 9799 gsi_remove (&gsi, true);
b8698a0f 9800
acf0174b
JJ
9801 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
9802 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
50674e96 9803
acf0174b 9804 /* Trip update code goes into TRIP_UPDATE_BB. */
ed20ae98 9805 gsi = gsi_start_bb (trip_update_bb);
953ff289 9806
acf0174b
JJ
9807 t = build_int_cst (itype, 1);
9808 t = build2 (PLUS_EXPR, itype, trip_main, t);
538dd0b7
DM
9809 assign_stmt = gimple_build_assign (trip_back, t);
9810 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
acf0174b 9811 }
953ff289 9812
726a989a 9813 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
ed20ae98
TS
9814 gsi = gsi_last_bb (exit_bb);
9815 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
acf0174b 9816 {
ed20ae98 9817 t = gimple_omp_return_lhs (gsi_stmt (gsi));
e4834818 9818 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
acf0174b 9819 }
ed20ae98 9820 gsi_remove (&gsi, true);
953ff289 9821
50674e96 9822 /* Connect the new blocks. */
e5c95afe
ZD
9823 find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
9824 find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
917948d3 9825
acf0174b
JJ
9826 if (!broken_loop)
9827 {
9828 se = find_edge (cont_bb, body_bb);
8cba6b95
TV
9829 if (se == NULL)
9830 {
9831 se = BRANCH_EDGE (cont_bb);
9832 gcc_assert (single_succ (se->dest) == body_bb);
9833 }
acf0174b
JJ
9834 if (gimple_omp_for_combined_p (fd->for_stmt))
9835 {
9836 remove_edge (se);
9837 se = NULL;
9838 }
9839 else if (fd->collapse > 1)
9840 {
9841 remove_edge (se);
9842 se = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
9843 }
9844 else
9845 se->flags = EDGE_TRUE_VALUE;
9846 find_edge (cont_bb, trip_update_bb)->flags
9847 = se ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
917948d3 9848
acf0174b
JJ
9849 redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb);
9850 }
917948d3
ZD
9851
9852 if (gimple_in_ssa_p (cfun))
9853 {
538dd0b7
DM
9854 gphi_iterator psi;
9855 gphi *phi;
726a989a 9856 edge re, ene;
726a989a
RB
9857 edge_var_map *vm;
9858 size_t i;
9859
acf0174b
JJ
9860 gcc_assert (fd->collapse == 1 && !broken_loop);
9861
917948d3
ZD
9862 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
9863 remove arguments of the phi nodes in fin_bb. We need to create
9864 appropriate phi nodes in iter_part_bb instead. */
17720e84 9865 se = find_edge (iter_part_bb, fin_bb);
917948d3 9866 re = single_succ_edge (trip_update_bb);
b787e7a2 9867 vec<edge_var_map> *head = redirect_edge_var_map_vector (re);
917948d3
ZD
9868 ene = single_succ_edge (entry_bb);
9869
726a989a 9870 psi = gsi_start_phis (fin_bb);
9771b263 9871 for (i = 0; !gsi_end_p (psi) && head->iterate (i, &vm);
726a989a 9872 gsi_next (&psi), ++i)
917948d3 9873 {
538dd0b7 9874 gphi *nphi;
f5045c96 9875 source_location locus;
726a989a 9876
538dd0b7 9877 phi = psi.phi ();
726a989a
RB
9878 t = gimple_phi_result (phi);
9879 gcc_assert (t == redirect_edge_var_map_result (vm));
17720e84
TV
9880
9881 if (!single_pred_p (fin_bb))
9882 t = copy_ssa_name (t, phi);
9883
917948d3 9884 nphi = create_phi_node (t, iter_part_bb);
917948d3
ZD
9885
9886 t = PHI_ARG_DEF_FROM_EDGE (phi, se);
f5045c96
AM
9887 locus = gimple_phi_arg_location_from_edge (phi, se);
9888
a68ab351 9889 /* A special case -- fd->loop.v is not yet computed in
ed20ae98 9890 iter_part_bb, we need to use vextra instead. */
a68ab351 9891 if (t == fd->loop.v)
ed20ae98 9892 t = vextra;
9e227d60 9893 add_phi_arg (nphi, t, ene, locus);
f5045c96 9894 locus = redirect_edge_var_map_location (vm);
1b96e9a4
TV
9895 tree back_arg = redirect_edge_var_map_def (vm);
9896 add_phi_arg (nphi, back_arg, re, locus);
9897 edge ce = find_edge (cont_bb, body_bb);
9898 if (ce == NULL)
9899 {
9900 ce = BRANCH_EDGE (cont_bb);
9901 gcc_assert (single_succ (ce->dest) == body_bb);
9902 ce = single_succ_edge (ce->dest);
9903 }
9904 gphi *inner_loop_phi = find_phi_with_arg_on_edge (back_arg, ce);
9905 gcc_assert (inner_loop_phi != NULL);
9906 add_phi_arg (inner_loop_phi, gimple_phi_result (nphi),
9907 find_edge (seq_start_bb, body_bb), locus);
17720e84
TV
9908
9909 if (!single_pred_p (fin_bb))
9910 add_phi_arg (phi, gimple_phi_result (nphi), se, locus);
726a989a 9911 }
8050766e 9912 gcc_assert (gsi_end_p (psi) && (head == NULL || i == head->length ()));
726a989a 9913 redirect_edge_var_map_clear (re);
17720e84
TV
9914 if (single_pred_p (fin_bb))
9915 while (1)
9916 {
9917 psi = gsi_start_phis (fin_bb);
9918 if (gsi_end_p (psi))
9919 break;
9920 remove_phi_node (&psi, false);
9921 }
917948d3
ZD
9922
9923 /* Make phi node for trip. */
9924 phi = create_phi_node (trip_main, iter_part_bb);
f5045c96 9925 add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb),
9e227d60 9926 UNKNOWN_LOCATION);
f5045c96 9927 add_phi_arg (phi, trip_init, single_succ_edge (entry_bb),
9e227d60 9928 UNKNOWN_LOCATION);
917948d3
ZD
9929 }
9930
acf0174b
JJ
9931 if (!broken_loop)
9932 set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
917948d3
ZD
9933 set_immediate_dominator (CDI_DOMINATORS, iter_part_bb,
9934 recompute_dominator (CDI_DOMINATORS, iter_part_bb));
9935 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
9936 recompute_dominator (CDI_DOMINATORS, fin_bb));
9937 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb,
9938 recompute_dominator (CDI_DOMINATORS, seq_start_bb));
9939 set_immediate_dominator (CDI_DOMINATORS, body_bb,
9940 recompute_dominator (CDI_DOMINATORS, body_bb));
6093bc06 9941
acf0174b
JJ
9942 if (!broken_loop)
9943 {
8cba6b95 9944 struct loop *loop = body_bb->loop_father;
acf0174b
JJ
9945 struct loop *trip_loop = alloc_loop ();
9946 trip_loop->header = iter_part_bb;
9947 trip_loop->latch = trip_update_bb;
9948 add_loop (trip_loop, iter_part_bb->loop_father);
6093bc06 9949
8cba6b95
TV
9950 if (loop != entry_bb->loop_father)
9951 {
9952 gcc_assert (loop->header == body_bb);
9953 gcc_assert (loop->latch == region->cont
9954 || single_pred (loop->latch) == region->cont);
9955 trip_loop->inner = loop;
9956 return;
9957 }
9958
acf0174b
JJ
9959 if (!gimple_omp_for_combined_p (fd->for_stmt))
9960 {
8cba6b95 9961 loop = alloc_loop ();
acf0174b 9962 loop->header = body_bb;
01dde9b0
JJ
9963 if (collapse_bb == NULL)
9964 loop->latch = cont_bb;
acf0174b
JJ
9965 add_loop (loop, trip_loop);
9966 }
9967 }
953ff289
DN
9968}
9969
9a771876
JJ
9970/* A subroutine of expand_omp_for. Generate code for _Cilk_for loop.
9971 Given parameters:
9972 for (V = N1; V cond N2; V += STEP) BODY;
9973
9974 where COND is "<" or ">" or "!=", we generate pseudocode
9975
9976 for (ind_var = low; ind_var < high; ind_var++)
9977 {
9978 V = n1 + (ind_var * STEP)
9979
9980 <BODY>
9981 }
9982
9983 In the above pseudocode, low and high are function parameters of the
9984 child function. In the function below, we are inserting a temp.
9985 variable that will be making a call to two OMP functions that will not be
9986 found in the body of _Cilk_for (since OMP_FOR cannot be mixed
9987 with _Cilk_for). These functions are replaced with low and high
9988 by the function that handles taskreg. */
9989
9990
9991static void
9992expand_cilk_for (struct omp_region *region, struct omp_for_data *fd)
9993{
9994 bool broken_loop = region->cont == NULL;
9995 basic_block entry_bb = region->entry;
9996 basic_block cont_bb = region->cont;
9997
9998 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
9999 gcc_assert (broken_loop
10000 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
10001 basic_block l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
10002 basic_block l1_bb, l2_bb;
10003
10004 if (!broken_loop)
10005 {
10006 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
10007 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
10008 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
10009 l2_bb = BRANCH_EDGE (entry_bb)->dest;
10010 }
10011 else
10012 {
10013 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
10014 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
10015 l2_bb = single_succ (l1_bb);
10016 }
10017 basic_block exit_bb = region->exit;
10018 basic_block l2_dom_bb = NULL;
10019
10020 gimple_stmt_iterator gsi = gsi_last_bb (entry_bb);
10021
10022 /* Below statements until the "tree high_val = ..." are pseudo statements
10023 used to pass information to be used by expand_omp_taskreg.
10024 low_val and high_val will be replaced by the __low and __high
10025 parameter from the child function.
10026
10027 The call_exprs part is a place-holder, it is mainly used
10028 to distinctly identify to the top-level part that this is
10029 where we should put low and high (reasoning given in header
10030 comment). */
10031
10032 tree child_fndecl
538dd0b7
DM
10033 = gimple_omp_parallel_child_fn (
10034 as_a <gomp_parallel *> (last_stmt (region->outer->entry)));
9a771876
JJ
10035 tree t, low_val = NULL_TREE, high_val = NULL_TREE;
10036 for (t = DECL_ARGUMENTS (child_fndecl); t; t = TREE_CHAIN (t))
10037 {
10038 if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__high"))
10039 high_val = t;
10040 else if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__low"))
10041 low_val = t;
10042 }
10043 gcc_assert (low_val && high_val);
10044
10045 tree type = TREE_TYPE (low_val);
10046 tree ind_var = create_tmp_reg (type, "__cilk_ind_var");
10047 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
10048
10049 /* Not needed in SSA form right now. */
10050 gcc_assert (!gimple_in_ssa_p (cfun));
10051 if (l2_dom_bb == NULL)
10052 l2_dom_bb = l1_bb;
10053
10054 tree n1 = low_val;
10055 tree n2 = high_val;
10056
355fe088 10057 gimple *stmt = gimple_build_assign (ind_var, n1);
9a771876
JJ
10058
10059 /* Replace the GIMPLE_OMP_FOR statement. */
10060 gsi_replace (&gsi, stmt, true);
10061
10062 if (!broken_loop)
10063 {
10064 /* Code to control the increment goes in the CONT_BB. */
10065 gsi = gsi_last_bb (cont_bb);
10066 stmt = gsi_stmt (gsi);
10067 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
0d0e4a03
JJ
10068 stmt = gimple_build_assign (ind_var, PLUS_EXPR, ind_var,
10069 build_one_cst (type));
9a771876
JJ
10070
10071 /* Replace GIMPLE_OMP_CONTINUE. */
10072 gsi_replace (&gsi, stmt, true);
10073 }
10074
10075 /* Emit the condition in L1_BB. */
10076 gsi = gsi_after_labels (l1_bb);
10077 t = fold_build2 (MULT_EXPR, TREE_TYPE (fd->loop.step),
10078 fold_convert (TREE_TYPE (fd->loop.step), ind_var),
10079 fd->loop.step);
10080 if (POINTER_TYPE_P (TREE_TYPE (fd->loop.n1)))
10081 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (fd->loop.n1),
10082 fd->loop.n1, fold_convert (sizetype, t));
10083 else
10084 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loop.n1),
10085 fd->loop.n1, fold_convert (TREE_TYPE (fd->loop.n1), t));
10086 t = fold_convert (TREE_TYPE (fd->loop.v), t);
10087 expand_omp_build_assign (&gsi, fd->loop.v, t);
10088
10089 /* The condition is always '<' since the runtime will fill in the low
10090 and high values. */
10091 stmt = gimple_build_cond (LT_EXPR, ind_var, n2, NULL_TREE, NULL_TREE);
10092 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
10093
10094 /* Remove GIMPLE_OMP_RETURN. */
10095 gsi = gsi_last_bb (exit_bb);
10096 gsi_remove (&gsi, true);
10097
10098 /* Connect the new blocks. */
10099 remove_edge (FALLTHRU_EDGE (entry_bb));
10100
10101 edge e, ne;
10102 if (!broken_loop)
10103 {
10104 remove_edge (BRANCH_EDGE (entry_bb));
10105 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
10106
10107 e = BRANCH_EDGE (l1_bb);
10108 ne = FALLTHRU_EDGE (l1_bb);
10109 e->flags = EDGE_TRUE_VALUE;
10110 }
10111 else
10112 {
10113 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
10114
10115 ne = single_succ_edge (l1_bb);
10116 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
10117
10118 }
10119 ne->flags = EDGE_FALSE_VALUE;
10120 e->probability = REG_BR_PROB_BASE * 7 / 8;
10121 ne->probability = REG_BR_PROB_BASE / 8;
10122
10123 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
10124 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
10125 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
10126
10127 if (!broken_loop)
10128 {
10129 struct loop *loop = alloc_loop ();
10130 loop->header = l1_bb;
10131 loop->latch = cont_bb;
10132 add_loop (loop, l1_bb->loop_father);
10133 loop->safelen = INT_MAX;
10134 }
10135
10136 /* Pick the correct library function based on the precision of the
10137 induction variable type. */
10138 tree lib_fun = NULL_TREE;
10139 if (TYPE_PRECISION (type) == 32)
10140 lib_fun = cilk_for_32_fndecl;
10141 else if (TYPE_PRECISION (type) == 64)
10142 lib_fun = cilk_for_64_fndecl;
10143 else
10144 gcc_unreachable ();
10145
10146 gcc_assert (fd->sched_kind == OMP_CLAUSE_SCHEDULE_CILKFOR);
10147
10148 /* WS_ARGS contains the library function flavor to call:
10149 __libcilkrts_cilk_for_64 or __libcilkrts_cilk_for_32), and the
10150 user-defined grain value. If the user does not define one, then zero
10151 is passed in by the parser. */
10152 vec_alloc (region->ws_args, 2);
10153 region->ws_args->quick_push (lib_fun);
10154 region->ws_args->quick_push (fd->chunk_size);
10155}
acf0174b 10156
74bf76ed
JJ
10157/* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
10158 loop. Given parameters:
10159
10160 for (V = N1; V cond N2; V += STEP) BODY;
10161
10162 where COND is "<" or ">", we generate pseudocode
10163
10164 V = N1;
10165 goto L1;
10166 L0:
10167 BODY;
10168 V += STEP;
10169 L1:
10170 if (V cond N2) goto L0; else goto L2;
10171 L2:
10172
10173 For collapsed loops, given parameters:
10174 collapse(3)
10175 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
10176 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
10177 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
10178 BODY;
10179
10180 we generate pseudocode
10181
10182 if (cond3 is <)
10183 adj = STEP3 - 1;
10184 else
10185 adj = STEP3 + 1;
10186 count3 = (adj + N32 - N31) / STEP3;
10187 if (cond2 is <)
10188 adj = STEP2 - 1;
10189 else
10190 adj = STEP2 + 1;
10191 count2 = (adj + N22 - N21) / STEP2;
10192 if (cond1 is <)
10193 adj = STEP1 - 1;
10194 else
10195 adj = STEP1 + 1;
10196 count1 = (adj + N12 - N11) / STEP1;
10197 count = count1 * count2 * count3;
10198 V = 0;
10199 V1 = N11;
10200 V2 = N21;
10201 V3 = N31;
10202 goto L1;
10203 L0:
10204 BODY;
10205 V += 1;
10206 V3 += STEP3;
10207 V2 += (V3 cond3 N32) ? 0 : STEP2;
10208 V3 = (V3 cond3 N32) ? V3 : N31;
10209 V1 += (V2 cond2 N22) ? 0 : STEP1;
10210 V2 = (V2 cond2 N22) ? V2 : N21;
10211 L1:
10212 if (V < count) goto L0; else goto L2;
10213 L2:
10214
10215 */
10216
10217static void
10218expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
10219{
10220 tree type, t;
10221 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, l2_bb, l2_dom_bb;
10222 gimple_stmt_iterator gsi;
355fe088 10223 gimple *stmt;
538dd0b7 10224 gcond *cond_stmt;
74bf76ed
JJ
10225 bool broken_loop = region->cont == NULL;
10226 edge e, ne;
10227 tree *counts = NULL;
10228 int i;
10229 tree safelen = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
10230 OMP_CLAUSE_SAFELEN);
10231 tree simduid = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
10232 OMP_CLAUSE__SIMDUID_);
acf0174b 10233 tree n1, n2;
74bf76ed
JJ
10234
10235 type = TREE_TYPE (fd->loop.v);
10236 entry_bb = region->entry;
10237 cont_bb = region->cont;
10238 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
10239 gcc_assert (broken_loop
10240 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
10241 l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
10242 if (!broken_loop)
10243 {
10244 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
10245 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
10246 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
10247 l2_bb = BRANCH_EDGE (entry_bb)->dest;
10248 }
10249 else
10250 {
10251 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
10252 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
10253 l2_bb = single_succ (l1_bb);
10254 }
10255 exit_bb = region->exit;
10256 l2_dom_bb = NULL;
10257
10258 gsi = gsi_last_bb (entry_bb);
10259
10260 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
10261 /* Not needed in SSA form right now. */
10262 gcc_assert (!gimple_in_ssa_p (cfun));
10263 if (fd->collapse > 1)
10264 {
d9a6bd32
JJ
10265 int first_zero_iter = -1, dummy = -1;
10266 basic_block zero_iter_bb = l2_bb, dummy_bb = NULL;
74bf76ed
JJ
10267
10268 counts = XALLOCAVEC (tree, fd->collapse);
10269 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
10270 zero_iter_bb, first_zero_iter,
d9a6bd32 10271 dummy_bb, dummy, l2_dom_bb);
74bf76ed
JJ
10272 }
10273 if (l2_dom_bb == NULL)
10274 l2_dom_bb = l1_bb;
10275
acf0174b 10276 n1 = fd->loop.n1;
74bf76ed 10277 n2 = fd->loop.n2;
acf0174b
JJ
10278 if (gimple_omp_for_combined_into_p (fd->for_stmt))
10279 {
10280 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
10281 OMP_CLAUSE__LOOPTEMP_);
10282 gcc_assert (innerc);
10283 n1 = OMP_CLAUSE_DECL (innerc);
10284 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
10285 OMP_CLAUSE__LOOPTEMP_);
10286 gcc_assert (innerc);
10287 n2 = OMP_CLAUSE_DECL (innerc);
10288 expand_omp_build_assign (&gsi, fd->loop.v,
10289 fold_convert (type, n1));
10290 if (fd->collapse > 1)
10291 {
10292 gsi_prev (&gsi);
10293 expand_omp_for_init_vars (fd, &gsi, counts, NULL, n1);
10294 gsi_next (&gsi);
10295 }
10296 }
74bf76ed
JJ
10297 else
10298 {
10299 expand_omp_build_assign (&gsi, fd->loop.v,
10300 fold_convert (type, fd->loop.n1));
10301 if (fd->collapse > 1)
10302 for (i = 0; i < fd->collapse; i++)
10303 {
10304 tree itype = TREE_TYPE (fd->loops[i].v);
10305 if (POINTER_TYPE_P (itype))
10306 itype = signed_type_for (itype);
10307 t = fold_convert (TREE_TYPE (fd->loops[i].v), fd->loops[i].n1);
10308 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
10309 }
10310 }
10311
10312 /* Remove the GIMPLE_OMP_FOR statement. */
10313 gsi_remove (&gsi, true);
10314
10315 if (!broken_loop)
10316 {
10317 /* Code to control the increment goes in the CONT_BB. */
10318 gsi = gsi_last_bb (cont_bb);
10319 stmt = gsi_stmt (gsi);
10320 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
10321
10322 if (POINTER_TYPE_P (type))
10323 t = fold_build_pointer_plus (fd->loop.v, fd->loop.step);
10324 else
10325 t = fold_build2 (PLUS_EXPR, type, fd->loop.v, fd->loop.step);
10326 expand_omp_build_assign (&gsi, fd->loop.v, t);
10327
10328 if (fd->collapse > 1)
10329 {
10330 i = fd->collapse - 1;
10331 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
10332 {
10333 t = fold_convert (sizetype, fd->loops[i].step);
10334 t = fold_build_pointer_plus (fd->loops[i].v, t);
10335 }
10336 else
10337 {
10338 t = fold_convert (TREE_TYPE (fd->loops[i].v),
10339 fd->loops[i].step);
10340 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
10341 fd->loops[i].v, t);
10342 }
10343 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
10344
10345 for (i = fd->collapse - 1; i > 0; i--)
10346 {
10347 tree itype = TREE_TYPE (fd->loops[i].v);
10348 tree itype2 = TREE_TYPE (fd->loops[i - 1].v);
10349 if (POINTER_TYPE_P (itype2))
10350 itype2 = signed_type_for (itype2);
10351 t = build3 (COND_EXPR, itype2,
10352 build2 (fd->loops[i].cond_code, boolean_type_node,
10353 fd->loops[i].v,
10354 fold_convert (itype, fd->loops[i].n2)),
10355 build_int_cst (itype2, 0),
10356 fold_convert (itype2, fd->loops[i - 1].step));
10357 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i - 1].v)))
10358 t = fold_build_pointer_plus (fd->loops[i - 1].v, t);
10359 else
10360 t = fold_build2 (PLUS_EXPR, itype2, fd->loops[i - 1].v, t);
10361 expand_omp_build_assign (&gsi, fd->loops[i - 1].v, t);
10362
10363 t = build3 (COND_EXPR, itype,
10364 build2 (fd->loops[i].cond_code, boolean_type_node,
10365 fd->loops[i].v,
10366 fold_convert (itype, fd->loops[i].n2)),
10367 fd->loops[i].v,
10368 fold_convert (itype, fd->loops[i].n1));
10369 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
10370 }
10371 }
10372
10373 /* Remove GIMPLE_OMP_CONTINUE. */
10374 gsi_remove (&gsi, true);
10375 }
10376
10377 /* Emit the condition in L1_BB. */
10378 gsi = gsi_start_bb (l1_bb);
10379
10380 t = fold_convert (type, n2);
10381 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
10382 false, GSI_CONTINUE_LINKING);
d9a6bd32
JJ
10383 tree v = fd->loop.v;
10384 if (DECL_P (v) && TREE_ADDRESSABLE (v))
10385 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
10386 false, GSI_CONTINUE_LINKING);
10387 t = build2 (fd->loop.cond_code, boolean_type_node, v, t);
538dd0b7
DM
10388 cond_stmt = gimple_build_cond_empty (t);
10389 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
10390 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt), expand_omp_regimplify_p,
74bf76ed 10391 NULL, NULL)
538dd0b7 10392 || walk_tree (gimple_cond_rhs_ptr (cond_stmt), expand_omp_regimplify_p,
74bf76ed
JJ
10393 NULL, NULL))
10394 {
538dd0b7
DM
10395 gsi = gsi_for_stmt (cond_stmt);
10396 gimple_regimplify_operands (cond_stmt, &gsi);
74bf76ed
JJ
10397 }
10398
10399 /* Remove GIMPLE_OMP_RETURN. */
10400 gsi = gsi_last_bb (exit_bb);
10401 gsi_remove (&gsi, true);
10402
10403 /* Connect the new blocks. */
10404 remove_edge (FALLTHRU_EDGE (entry_bb));
10405
10406 if (!broken_loop)
10407 {
10408 remove_edge (BRANCH_EDGE (entry_bb));
10409 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
10410
10411 e = BRANCH_EDGE (l1_bb);
10412 ne = FALLTHRU_EDGE (l1_bb);
10413 e->flags = EDGE_TRUE_VALUE;
10414 }
10415 else
10416 {
10417 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
10418
10419 ne = single_succ_edge (l1_bb);
10420 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
10421
10422 }
10423 ne->flags = EDGE_FALSE_VALUE;
10424 e->probability = REG_BR_PROB_BASE * 7 / 8;
10425 ne->probability = REG_BR_PROB_BASE / 8;
10426
10427 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
10428 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
10429 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
10430
10431 if (!broken_loop)
10432 {
10433 struct loop *loop = alloc_loop ();
10434 loop->header = l1_bb;
01dde9b0 10435 loop->latch = cont_bb;
74bf76ed
JJ
10436 add_loop (loop, l1_bb->loop_father);
10437 if (safelen == NULL_TREE)
10438 loop->safelen = INT_MAX;
10439 else
10440 {
10441 safelen = OMP_CLAUSE_SAFELEN_EXPR (safelen);
b46ebd6c
JJ
10442 if (TREE_CODE (safelen) != INTEGER_CST)
10443 loop->safelen = 0;
10444 else if (!tree_fits_uhwi_p (safelen)
10445 || tree_to_uhwi (safelen) > INT_MAX)
74bf76ed
JJ
10446 loop->safelen = INT_MAX;
10447 else
ae7e9ddd 10448 loop->safelen = tree_to_uhwi (safelen);
74bf76ed
JJ
10449 if (loop->safelen == 1)
10450 loop->safelen = 0;
10451 }
10452 if (simduid)
10453 {
d9a6bd32
JJ
10454 loop->simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
10455 cfun->has_simduid_loops = true;
10456 }
10457 /* If not -fno-tree-loop-vectorize, hint that we want to vectorize
10458 the loop. */
10459 if ((flag_tree_loop_vectorize
10460 || (!global_options_set.x_flag_tree_loop_vectorize
10461 && !global_options_set.x_flag_tree_vectorize))
10462 && flag_tree_loop_optimize
10463 && loop->safelen > 1)
10464 {
10465 loop->force_vectorize = true;
10466 cfun->has_force_vectorize_loops = true;
10467 }
10468 }
10469 else if (simduid)
10470 cfun->has_simduid_loops = true;
10471}
10472
10473/* Taskloop construct is represented after gimplification with
10474 two GIMPLE_OMP_FOR constructs with GIMPLE_OMP_TASK sandwiched
10475 in between them. This routine expands the outer GIMPLE_OMP_FOR,
10476 which should just compute all the needed loop temporaries
10477 for GIMPLE_OMP_TASK. */
10478
10479static void
10480expand_omp_taskloop_for_outer (struct omp_region *region,
10481 struct omp_for_data *fd,
10482 gimple *inner_stmt)
10483{
10484 tree type, bias = NULL_TREE;
10485 basic_block entry_bb, cont_bb, exit_bb;
10486 gimple_stmt_iterator gsi;
10487 gassign *assign_stmt;
10488 tree *counts = NULL;
10489 int i;
10490
10491 gcc_assert (inner_stmt);
10492 gcc_assert (region->cont);
10493 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_TASK
10494 && gimple_omp_task_taskloop_p (inner_stmt));
10495 type = TREE_TYPE (fd->loop.v);
10496
10497 /* See if we need to bias by LLONG_MIN. */
10498 if (fd->iter_type == long_long_unsigned_type_node
10499 && TREE_CODE (type) == INTEGER_TYPE
10500 && !TYPE_UNSIGNED (type))
10501 {
10502 tree n1, n2;
10503
10504 if (fd->loop.cond_code == LT_EXPR)
10505 {
10506 n1 = fd->loop.n1;
10507 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
10508 }
10509 else
10510 {
10511 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
10512 n2 = fd->loop.n1;
10513 }
10514 if (TREE_CODE (n1) != INTEGER_CST
10515 || TREE_CODE (n2) != INTEGER_CST
10516 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
10517 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
10518 }
10519
10520 entry_bb = region->entry;
10521 cont_bb = region->cont;
10522 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
10523 gcc_assert (BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
10524 exit_bb = region->exit;
10525
10526 gsi = gsi_last_bb (entry_bb);
10527 gimple *for_stmt = gsi_stmt (gsi);
10528 gcc_assert (gimple_code (for_stmt) == GIMPLE_OMP_FOR);
10529 if (fd->collapse > 1)
10530 {
10531 int first_zero_iter = -1, dummy = -1;
10532 basic_block zero_iter_bb = NULL, dummy_bb = NULL, l2_dom_bb = NULL;
10533
10534 counts = XALLOCAVEC (tree, fd->collapse);
10535 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
10536 zero_iter_bb, first_zero_iter,
10537 dummy_bb, dummy, l2_dom_bb);
10538
10539 if (zero_iter_bb)
10540 {
10541 /* Some counts[i] vars might be uninitialized if
10542 some loop has zero iterations. But the body shouldn't
10543 be executed in that case, so just avoid uninit warnings. */
10544 for (i = first_zero_iter; i < fd->collapse; i++)
10545 if (SSA_VAR_P (counts[i]))
10546 TREE_NO_WARNING (counts[i]) = 1;
10547 gsi_prev (&gsi);
10548 edge e = split_block (entry_bb, gsi_stmt (gsi));
10549 entry_bb = e->dest;
10550 make_edge (zero_iter_bb, entry_bb, EDGE_FALLTHRU);
10551 gsi = gsi_last_bb (entry_bb);
10552 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
10553 get_immediate_dominator (CDI_DOMINATORS,
10554 zero_iter_bb));
10555 }
10556 }
10557
10558 tree t0, t1;
10559 t1 = fd->loop.n2;
10560 t0 = fd->loop.n1;
10561 if (POINTER_TYPE_P (TREE_TYPE (t0))
10562 && TYPE_PRECISION (TREE_TYPE (t0))
10563 != TYPE_PRECISION (fd->iter_type))
10564 {
10565 /* Avoid casting pointers to integer of a different size. */
10566 tree itype = signed_type_for (type);
10567 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
10568 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
10569 }
10570 else
10571 {
10572 t1 = fold_convert (fd->iter_type, t1);
10573 t0 = fold_convert (fd->iter_type, t0);
10574 }
10575 if (bias)
10576 {
10577 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
10578 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
10579 }
10580
10581 tree innerc = find_omp_clause (gimple_omp_task_clauses (inner_stmt),
10582 OMP_CLAUSE__LOOPTEMP_);
10583 gcc_assert (innerc);
10584 tree startvar = OMP_CLAUSE_DECL (innerc);
10585 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc), OMP_CLAUSE__LOOPTEMP_);
10586 gcc_assert (innerc);
10587 tree endvar = OMP_CLAUSE_DECL (innerc);
10588 if (fd->collapse > 1 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
10589 {
10590 gcc_assert (innerc);
10591 for (i = 1; i < fd->collapse; i++)
10592 {
10593 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
10594 OMP_CLAUSE__LOOPTEMP_);
10595 gcc_assert (innerc);
10596 }
10597 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
10598 OMP_CLAUSE__LOOPTEMP_);
10599 if (innerc)
10600 {
10601 /* If needed (inner taskloop has lastprivate clause), propagate
10602 down the total number of iterations. */
10603 tree t = force_gimple_operand_gsi (&gsi, fd->loop.n2, false,
10604 NULL_TREE, false,
10605 GSI_CONTINUE_LINKING);
10606 assign_stmt = gimple_build_assign (OMP_CLAUSE_DECL (innerc), t);
10607 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10608 }
10609 }
10610
10611 t0 = force_gimple_operand_gsi (&gsi, t0, false, NULL_TREE, false,
10612 GSI_CONTINUE_LINKING);
10613 assign_stmt = gimple_build_assign (startvar, t0);
10614 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10615
10616 t1 = force_gimple_operand_gsi (&gsi, t1, false, NULL_TREE, false,
10617 GSI_CONTINUE_LINKING);
10618 assign_stmt = gimple_build_assign (endvar, t1);
10619 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10620 if (fd->collapse > 1)
10621 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
10622
10623 /* Remove the GIMPLE_OMP_FOR statement. */
10624 gsi = gsi_for_stmt (for_stmt);
10625 gsi_remove (&gsi, true);
10626
10627 gsi = gsi_last_bb (cont_bb);
10628 gsi_remove (&gsi, true);
10629
10630 gsi = gsi_last_bb (exit_bb);
10631 gsi_remove (&gsi, true);
10632
10633 FALLTHRU_EDGE (entry_bb)->probability = REG_BR_PROB_BASE;
10634 remove_edge (BRANCH_EDGE (entry_bb));
10635 FALLTHRU_EDGE (cont_bb)->probability = REG_BR_PROB_BASE;
10636 remove_edge (BRANCH_EDGE (cont_bb));
10637 set_immediate_dominator (CDI_DOMINATORS, exit_bb, cont_bb);
10638 set_immediate_dominator (CDI_DOMINATORS, region->entry,
10639 recompute_dominator (CDI_DOMINATORS, region->entry));
10640}
10641
10642/* Taskloop construct is represented after gimplification with
10643 two GIMPLE_OMP_FOR constructs with GIMPLE_OMP_TASK sandwiched
10644 in between them. This routine expands the inner GIMPLE_OMP_FOR.
10645 GOMP_taskloop{,_ull} function arranges for each task to be given just
10646 a single range of iterations. */
10647
10648static void
10649expand_omp_taskloop_for_inner (struct omp_region *region,
10650 struct omp_for_data *fd,
10651 gimple *inner_stmt)
10652{
10653 tree e, t, type, itype, vmain, vback, bias = NULL_TREE;
10654 basic_block entry_bb, exit_bb, body_bb, cont_bb, collapse_bb = NULL;
10655 basic_block fin_bb;
10656 gimple_stmt_iterator gsi;
10657 edge ep;
10658 bool broken_loop = region->cont == NULL;
10659 tree *counts = NULL;
10660 tree n1, n2, step;
10661
10662 itype = type = TREE_TYPE (fd->loop.v);
10663 if (POINTER_TYPE_P (type))
10664 itype = signed_type_for (type);
10665
10666 /* See if we need to bias by LLONG_MIN. */
10667 if (fd->iter_type == long_long_unsigned_type_node
10668 && TREE_CODE (type) == INTEGER_TYPE
10669 && !TYPE_UNSIGNED (type))
10670 {
10671 tree n1, n2;
10672
10673 if (fd->loop.cond_code == LT_EXPR)
10674 {
10675 n1 = fd->loop.n1;
10676 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
10677 }
10678 else
10679 {
10680 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
10681 n2 = fd->loop.n1;
10682 }
10683 if (TREE_CODE (n1) != INTEGER_CST
10684 || TREE_CODE (n2) != INTEGER_CST
10685 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
10686 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
10687 }
10688
10689 entry_bb = region->entry;
10690 cont_bb = region->cont;
10691 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
10692 fin_bb = BRANCH_EDGE (entry_bb)->dest;
10693 gcc_assert (broken_loop
10694 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
10695 body_bb = FALLTHRU_EDGE (entry_bb)->dest;
10696 if (!broken_loop)
10697 {
10698 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
10699 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
10700 }
10701 exit_bb = region->exit;
10702
10703 /* Iteration space partitioning goes in ENTRY_BB. */
10704 gsi = gsi_last_bb (entry_bb);
10705 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
10706
10707 if (fd->collapse > 1)
10708 {
10709 int first_zero_iter = -1, dummy = -1;
10710 basic_block l2_dom_bb = NULL, dummy_bb = NULL;
10711
10712 counts = XALLOCAVEC (tree, fd->collapse);
10713 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
10714 fin_bb, first_zero_iter,
10715 dummy_bb, dummy, l2_dom_bb);
10716 t = NULL_TREE;
10717 }
10718 else
10719 t = integer_one_node;
10720
10721 step = fd->loop.step;
10722 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
10723 OMP_CLAUSE__LOOPTEMP_);
10724 gcc_assert (innerc);
10725 n1 = OMP_CLAUSE_DECL (innerc);
10726 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc), OMP_CLAUSE__LOOPTEMP_);
10727 gcc_assert (innerc);
10728 n2 = OMP_CLAUSE_DECL (innerc);
10729 if (bias)
10730 {
10731 n1 = fold_build2 (PLUS_EXPR, fd->iter_type, n1, bias);
10732 n2 = fold_build2 (PLUS_EXPR, fd->iter_type, n2, bias);
10733 }
10734 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
10735 true, NULL_TREE, true, GSI_SAME_STMT);
10736 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
10737 true, NULL_TREE, true, GSI_SAME_STMT);
10738 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
10739 true, NULL_TREE, true, GSI_SAME_STMT);
10740
10741 tree startvar = fd->loop.v;
10742 tree endvar = NULL_TREE;
10743
10744 if (gimple_omp_for_combined_p (fd->for_stmt))
10745 {
10746 tree clauses = gimple_omp_for_clauses (inner_stmt);
10747 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
10748 gcc_assert (innerc);
10749 startvar = OMP_CLAUSE_DECL (innerc);
10750 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
10751 OMP_CLAUSE__LOOPTEMP_);
10752 gcc_assert (innerc);
10753 endvar = OMP_CLAUSE_DECL (innerc);
10754 }
10755 t = fold_convert (TREE_TYPE (startvar), n1);
10756 t = force_gimple_operand_gsi (&gsi, t,
10757 DECL_P (startvar)
10758 && TREE_ADDRESSABLE (startvar),
10759 NULL_TREE, false, GSI_CONTINUE_LINKING);
10760 gimple *assign_stmt = gimple_build_assign (startvar, t);
10761 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10762
10763 t = fold_convert (TREE_TYPE (startvar), n2);
10764 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
10765 false, GSI_CONTINUE_LINKING);
10766 if (endvar)
10767 {
10768 assign_stmt = gimple_build_assign (endvar, e);
10769 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10770 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
10771 assign_stmt = gimple_build_assign (fd->loop.v, e);
10772 else
10773 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
10774 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10775 }
10776 if (fd->collapse > 1)
10777 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
10778
10779 if (!broken_loop)
10780 {
10781 /* The code controlling the sequential loop replaces the
10782 GIMPLE_OMP_CONTINUE. */
10783 gsi = gsi_last_bb (cont_bb);
10784 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
10785 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
10786 vmain = gimple_omp_continue_control_use (cont_stmt);
10787 vback = gimple_omp_continue_control_def (cont_stmt);
10788
10789 if (!gimple_omp_for_combined_p (fd->for_stmt))
10790 {
10791 if (POINTER_TYPE_P (type))
10792 t = fold_build_pointer_plus (vmain, step);
10793 else
10794 t = fold_build2 (PLUS_EXPR, type, vmain, step);
10795 t = force_gimple_operand_gsi (&gsi, t,
10796 DECL_P (vback)
10797 && TREE_ADDRESSABLE (vback),
10798 NULL_TREE, true, GSI_SAME_STMT);
10799 assign_stmt = gimple_build_assign (vback, t);
10800 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
10801
10802 t = build2 (fd->loop.cond_code, boolean_type_node,
10803 DECL_P (vback) && TREE_ADDRESSABLE (vback)
10804 ? t : vback, e);
10805 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
10806 }
10807
10808 /* Remove the GIMPLE_OMP_CONTINUE statement. */
10809 gsi_remove (&gsi, true);
10810
10811 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
10812 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
10813 }
10814
10815 /* Remove the GIMPLE_OMP_FOR statement. */
10816 gsi = gsi_for_stmt (fd->for_stmt);
10817 gsi_remove (&gsi, true);
10818
10819 /* Remove the GIMPLE_OMP_RETURN statement. */
10820 gsi = gsi_last_bb (exit_bb);
10821 gsi_remove (&gsi, true);
10822
10823 FALLTHRU_EDGE (entry_bb)->probability = REG_BR_PROB_BASE;
10824 if (!broken_loop)
10825 remove_edge (BRANCH_EDGE (entry_bb));
10826 else
10827 {
10828 remove_edge_and_dominated_blocks (BRANCH_EDGE (entry_bb));
10829 region->outer->cont = NULL;
10830 }
10831
10832 /* Connect all the blocks. */
10833 if (!broken_loop)
10834 {
10835 ep = find_edge (cont_bb, body_bb);
10836 if (gimple_omp_for_combined_p (fd->for_stmt))
10837 {
10838 remove_edge (ep);
10839 ep = NULL;
74bf76ed 10840 }
d9a6bd32 10841 else if (fd->collapse > 1)
74bf76ed 10842 {
d9a6bd32
JJ
10843 remove_edge (ep);
10844 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
74bf76ed 10845 }
d9a6bd32
JJ
10846 else
10847 ep->flags = EDGE_TRUE_VALUE;
10848 find_edge (cont_bb, fin_bb)->flags
10849 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
74bf76ed 10850 }
74bf76ed 10851
d9a6bd32
JJ
10852 set_immediate_dominator (CDI_DOMINATORS, body_bb,
10853 recompute_dominator (CDI_DOMINATORS, body_bb));
10854 if (!broken_loop)
10855 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
10856 recompute_dominator (CDI_DOMINATORS, fin_bb));
10857
10858 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
10859 {
10860 struct loop *loop = alloc_loop ();
10861 loop->header = body_bb;
10862 if (collapse_bb == NULL)
10863 loop->latch = cont_bb;
10864 add_loop (loop, body_bb->loop_father);
10865 }
10866}
953ff289 10867
e4834818
NS
10868/* A subroutine of expand_omp_for. Generate code for an OpenACC
10869 partitioned loop. The lowering here is abstracted, in that the
10870 loop parameters are passed through internal functions, which are
10871 further lowered by oacc_device_lower, once we get to the target
10872 compiler. The loop is of the form:
10873
10874 for (V = B; V LTGT E; V += S) {BODY}
10875
10876 where LTGT is < or >. We may have a specified chunking size, CHUNKING
10877 (constant 0 for no chunking) and we will have a GWV partitioning
10878 mask, specifying dimensions over which the loop is to be
10879 partitioned (see note below). We generate code that looks like:
10880
10881 <entry_bb> [incoming FALL->body, BRANCH->exit]
10882 typedef signedintify (typeof (V)) T; // underlying signed integral type
10883 T range = E - B;
10884 T chunk_no = 0;
10885 T DIR = LTGT == '<' ? +1 : -1;
10886 T chunk_max = GOACC_LOOP_CHUNK (dir, range, S, CHUNK_SIZE, GWV);
10887 T step = GOACC_LOOP_STEP (dir, range, S, CHUNK_SIZE, GWV);
10888
10889 <head_bb> [created by splitting end of entry_bb]
10890 T offset = GOACC_LOOP_OFFSET (dir, range, S, CHUNK_SIZE, GWV, chunk_no);
10891 T bound = GOACC_LOOP_BOUND (dir, range, S, CHUNK_SIZE, GWV, offset);
10892 if (!(offset LTGT bound)) goto bottom_bb;
10893
10894 <body_bb> [incoming]
10895 V = B + offset;
10896 {BODY}
10897
10898 <cont_bb> [incoming, may == body_bb FALL->exit_bb, BRANCH->body_bb]
10899 offset += step;
10900 if (offset LTGT bound) goto body_bb; [*]
10901
10902 <bottom_bb> [created by splitting start of exit_bb] insert BRANCH->head_bb
10903 chunk_no++;
10904 if (chunk < chunk_max) goto head_bb;
10905
10906 <exit_bb> [incoming]
10907 V = B + ((range -/+ 1) / S +/- 1) * S [*]
10908
10909 [*] Needed if V live at end of loop
10910
10911 Note: CHUNKING & GWV mask are specified explicitly here. This is a
10912 transition, and will be specified by a more general mechanism shortly.
10913 */
10914
10915static void
10916expand_oacc_for (struct omp_region *region, struct omp_for_data *fd)
10917{
10918 tree v = fd->loop.v;
10919 enum tree_code cond_code = fd->loop.cond_code;
10920 enum tree_code plus_code = PLUS_EXPR;
10921
10922 tree chunk_size = integer_minus_one_node;
10923 tree gwv = integer_zero_node;
10924 tree iter_type = TREE_TYPE (v);
10925 tree diff_type = iter_type;
10926 tree plus_type = iter_type;
10927 struct oacc_collapse *counts = NULL;
10928
10929 gcc_checking_assert (gimple_omp_for_kind (fd->for_stmt)
10930 == GF_OMP_FOR_KIND_OACC_LOOP);
10931 gcc_assert (!gimple_omp_for_combined_into_p (fd->for_stmt));
10932 gcc_assert (cond_code == LT_EXPR || cond_code == GT_EXPR);
10933
10934 if (POINTER_TYPE_P (iter_type))
10935 {
10936 plus_code = POINTER_PLUS_EXPR;
10937 plus_type = sizetype;
10938 }
10939 if (POINTER_TYPE_P (diff_type) || TYPE_UNSIGNED (diff_type))
10940 diff_type = signed_type_for (diff_type);
10941
10942 basic_block entry_bb = region->entry; /* BB ending in OMP_FOR */
10943 basic_block exit_bb = region->exit; /* BB ending in OMP_RETURN */
10944 basic_block cont_bb = region->cont; /* BB ending in OMP_CONTINUE */
10945 basic_block bottom_bb = NULL;
10946
10947 /* entry_bb has two sucessors; the branch edge is to the exit
10948 block, fallthrough edge to body. */
10949 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2
10950 && BRANCH_EDGE (entry_bb)->dest == exit_bb);
10951
10952 /* If cont_bb non-NULL, it has 2 successors. The branch successor is
10953 body_bb, or to a block whose only successor is the body_bb. Its
10954 fallthrough successor is the final block (same as the branch
10955 successor of the entry_bb). */
10956 if (cont_bb)
10957 {
10958 basic_block body_bb = FALLTHRU_EDGE (entry_bb)->dest;
10959 basic_block bed = BRANCH_EDGE (cont_bb)->dest;
10960
10961 gcc_assert (FALLTHRU_EDGE (cont_bb)->dest == exit_bb);
10962 gcc_assert (bed == body_bb || single_succ_edge (bed)->dest == body_bb);
10963 }
10964 else
10965 gcc_assert (!gimple_in_ssa_p (cfun));
10966
10967 /* The exit block only has entry_bb and cont_bb as predecessors. */
10968 gcc_assert (EDGE_COUNT (exit_bb->preds) == 1 + (cont_bb != NULL));
10969
10970 tree chunk_no;
10971 tree chunk_max = NULL_TREE;
10972 tree bound, offset;
10973 tree step = create_tmp_var (diff_type, ".step");
10974 bool up = cond_code == LT_EXPR;
10975 tree dir = build_int_cst (diff_type, up ? +1 : -1);
10976 bool chunking = !gimple_in_ssa_p (cfun);;
10977 bool negating;
10978
10979 /* SSA instances. */
10980 tree offset_incr = NULL_TREE;
10981 tree offset_init = NULL_TREE;
10982
10983 gimple_stmt_iterator gsi;
10984 gassign *ass;
10985 gcall *call;
10986 gimple *stmt;
10987 tree expr;
10988 location_t loc;
10989 edge split, be, fte;
10990
10991 /* Split the end of entry_bb to create head_bb. */
10992 split = split_block (entry_bb, last_stmt (entry_bb));
10993 basic_block head_bb = split->dest;
10994 entry_bb = split->src;
10995
10996 /* Chunk setup goes at end of entry_bb, replacing the omp_for. */
10997 gsi = gsi_last_bb (entry_bb);
10998 gomp_for *for_stmt = as_a <gomp_for *> (gsi_stmt (gsi));
10999 loc = gimple_location (for_stmt);
11000
11001 if (gimple_in_ssa_p (cfun))
11002 {
11003 offset_init = gimple_omp_for_index (for_stmt, 0);
11004 gcc_assert (integer_zerop (fd->loop.n1));
11005 /* The SSA parallelizer does gang parallelism. */
11006 gwv = build_int_cst (integer_type_node, GOMP_DIM_MASK (GOMP_DIM_GANG));
11007 }
11008
11009 if (fd->collapse > 1)
11010 {
11011 counts = XALLOCAVEC (struct oacc_collapse, fd->collapse);
11012 tree total = expand_oacc_collapse_init (fd, &gsi, counts,
11013 TREE_TYPE (fd->loop.n2));
11014
11015 if (SSA_VAR_P (fd->loop.n2))
11016 {
11017 total = force_gimple_operand_gsi (&gsi, total, false, NULL_TREE,
11018 true, GSI_SAME_STMT);
11019 ass = gimple_build_assign (fd->loop.n2, total);
11020 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11021 }
11022
11023 }
11024
11025 tree b = fd->loop.n1;
11026 tree e = fd->loop.n2;
11027 tree s = fd->loop.step;
11028
11029 b = force_gimple_operand_gsi (&gsi, b, true, NULL_TREE, true, GSI_SAME_STMT);
11030 e = force_gimple_operand_gsi (&gsi, e, true, NULL_TREE, true, GSI_SAME_STMT);
11031
11032 /* Convert the step, avoiding possible unsigned->signed overflow. */
11033 negating = !up && TYPE_UNSIGNED (TREE_TYPE (s));
11034 if (negating)
11035 s = fold_build1 (NEGATE_EXPR, TREE_TYPE (s), s);
11036 s = fold_convert (diff_type, s);
11037 if (negating)
11038 s = fold_build1 (NEGATE_EXPR, diff_type, s);
11039 s = force_gimple_operand_gsi (&gsi, s, true, NULL_TREE, true, GSI_SAME_STMT);
11040
11041 if (!chunking)
11042 chunk_size = integer_zero_node;
11043 expr = fold_convert (diff_type, chunk_size);
11044 chunk_size = force_gimple_operand_gsi (&gsi, expr, true,
11045 NULL_TREE, true, GSI_SAME_STMT);
11046 /* Determine the range, avoiding possible unsigned->signed overflow. */
11047 negating = !up && TYPE_UNSIGNED (iter_type);
11048 expr = fold_build2 (MINUS_EXPR, plus_type,
11049 fold_convert (plus_type, negating ? b : e),
11050 fold_convert (plus_type, negating ? e : b));
11051 expr = fold_convert (diff_type, expr);
11052 if (negating)
11053 expr = fold_build1 (NEGATE_EXPR, diff_type, expr);
11054 tree range = force_gimple_operand_gsi (&gsi, expr, true,
11055 NULL_TREE, true, GSI_SAME_STMT);
11056
11057 chunk_no = build_int_cst (diff_type, 0);
11058 if (chunking)
11059 {
11060 gcc_assert (!gimple_in_ssa_p (cfun));
11061
11062 expr = chunk_no;
11063 chunk_max = create_tmp_var (diff_type, ".chunk_max");
11064 chunk_no = create_tmp_var (diff_type, ".chunk_no");
11065
11066 ass = gimple_build_assign (chunk_no, expr);
11067 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11068
11069 call = gimple_build_call_internal (IFN_GOACC_LOOP, 6,
11070 build_int_cst (integer_type_node,
11071 IFN_GOACC_LOOP_CHUNKS),
11072 dir, range, s, chunk_size, gwv);
11073 gimple_call_set_lhs (call, chunk_max);
11074 gimple_set_location (call, loc);
11075 gsi_insert_before (&gsi, call, GSI_SAME_STMT);
11076 }
11077 else
11078 chunk_size = chunk_no;
11079
11080 call = gimple_build_call_internal (IFN_GOACC_LOOP, 6,
11081 build_int_cst (integer_type_node,
11082 IFN_GOACC_LOOP_STEP),
11083 dir, range, s, chunk_size, gwv);
11084 gimple_call_set_lhs (call, step);
11085 gimple_set_location (call, loc);
11086 gsi_insert_before (&gsi, call, GSI_SAME_STMT);
11087
11088 /* Remove the GIMPLE_OMP_FOR. */
11089 gsi_remove (&gsi, true);
11090
11091 /* Fixup edges from head_bb */
11092 be = BRANCH_EDGE (head_bb);
11093 fte = FALLTHRU_EDGE (head_bb);
11094 be->flags |= EDGE_FALSE_VALUE;
11095 fte->flags ^= EDGE_FALLTHRU | EDGE_TRUE_VALUE;
11096
11097 basic_block body_bb = fte->dest;
11098
11099 if (gimple_in_ssa_p (cfun))
11100 {
11101 gsi = gsi_last_bb (cont_bb);
11102 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
11103
11104 offset = gimple_omp_continue_control_use (cont_stmt);
11105 offset_incr = gimple_omp_continue_control_def (cont_stmt);
11106 }
11107 else
11108 {
11109 offset = create_tmp_var (diff_type, ".offset");
11110 offset_init = offset_incr = offset;
11111 }
11112 bound = create_tmp_var (TREE_TYPE (offset), ".bound");
11113
11114 /* Loop offset & bound go into head_bb. */
11115 gsi = gsi_start_bb (head_bb);
11116
11117 call = gimple_build_call_internal (IFN_GOACC_LOOP, 7,
11118 build_int_cst (integer_type_node,
11119 IFN_GOACC_LOOP_OFFSET),
11120 dir, range, s,
11121 chunk_size, gwv, chunk_no);
11122 gimple_call_set_lhs (call, offset_init);
11123 gimple_set_location (call, loc);
11124 gsi_insert_after (&gsi, call, GSI_CONTINUE_LINKING);
11125
11126 call = gimple_build_call_internal (IFN_GOACC_LOOP, 7,
11127 build_int_cst (integer_type_node,
11128 IFN_GOACC_LOOP_BOUND),
11129 dir, range, s,
11130 chunk_size, gwv, offset_init);
11131 gimple_call_set_lhs (call, bound);
11132 gimple_set_location (call, loc);
11133 gsi_insert_after (&gsi, call, GSI_CONTINUE_LINKING);
11134
11135 expr = build2 (cond_code, boolean_type_node, offset_init, bound);
11136 gsi_insert_after (&gsi, gimple_build_cond_empty (expr),
11137 GSI_CONTINUE_LINKING);
11138
11139 /* V assignment goes into body_bb. */
11140 if (!gimple_in_ssa_p (cfun))
11141 {
11142 gsi = gsi_start_bb (body_bb);
11143
11144 expr = build2 (plus_code, iter_type, b,
11145 fold_convert (plus_type, offset));
11146 expr = force_gimple_operand_gsi (&gsi, expr, false, NULL_TREE,
11147 true, GSI_SAME_STMT);
11148 ass = gimple_build_assign (v, expr);
11149 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11150 if (fd->collapse > 1)
11151 expand_oacc_collapse_vars (fd, &gsi, counts, v);
11152 }
11153
11154 /* Loop increment goes into cont_bb. If this is not a loop, we
11155 will have spawned threads as if it was, and each one will
11156 execute one iteration. The specification is not explicit about
11157 whether such constructs are ill-formed or not, and they can
11158 occur, especially when noreturn routines are involved. */
11159 if (cont_bb)
11160 {
11161 gsi = gsi_last_bb (cont_bb);
11162 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
11163 loc = gimple_location (cont_stmt);
11164
11165 /* Increment offset. */
11166 if (gimple_in_ssa_p (cfun))
11167 expr= build2 (plus_code, iter_type, offset,
11168 fold_convert (plus_type, step));
11169 else
11170 expr = build2 (PLUS_EXPR, diff_type, offset, step);
11171 expr = force_gimple_operand_gsi (&gsi, expr, false, NULL_TREE,
11172 true, GSI_SAME_STMT);
11173 ass = gimple_build_assign (offset_incr, expr);
11174 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11175 expr = build2 (cond_code, boolean_type_node, offset_incr, bound);
11176 gsi_insert_before (&gsi, gimple_build_cond_empty (expr), GSI_SAME_STMT);
11177
11178 /* Remove the GIMPLE_OMP_CONTINUE. */
11179 gsi_remove (&gsi, true);
11180
11181 /* Fixup edges from cont_bb */
11182 be = BRANCH_EDGE (cont_bb);
11183 fte = FALLTHRU_EDGE (cont_bb);
11184 be->flags |= EDGE_TRUE_VALUE;
11185 fte->flags ^= EDGE_FALLTHRU | EDGE_FALSE_VALUE;
11186
11187 if (chunking)
11188 {
11189 /* Split the beginning of exit_bb to make bottom_bb. We
11190 need to insert a nop at the start, because splitting is
11191 after a stmt, not before. */
11192 gsi = gsi_start_bb (exit_bb);
11193 stmt = gimple_build_nop ();
11194 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
11195 split = split_block (exit_bb, stmt);
11196 bottom_bb = split->src;
11197 exit_bb = split->dest;
11198 gsi = gsi_last_bb (bottom_bb);
11199
11200 /* Chunk increment and test goes into bottom_bb. */
11201 expr = build2 (PLUS_EXPR, diff_type, chunk_no,
11202 build_int_cst (diff_type, 1));
11203 ass = gimple_build_assign (chunk_no, expr);
11204 gsi_insert_after (&gsi, ass, GSI_CONTINUE_LINKING);
11205
11206 /* Chunk test at end of bottom_bb. */
11207 expr = build2 (LT_EXPR, boolean_type_node, chunk_no, chunk_max);
11208 gsi_insert_after (&gsi, gimple_build_cond_empty (expr),
11209 GSI_CONTINUE_LINKING);
11210
11211 /* Fixup edges from bottom_bb. */
11212 split->flags ^= EDGE_FALLTHRU | EDGE_FALSE_VALUE;
11213 make_edge (bottom_bb, head_bb, EDGE_TRUE_VALUE);
11214 }
11215 }
11216
11217 gsi = gsi_last_bb (exit_bb);
11218 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
11219 loc = gimple_location (gsi_stmt (gsi));
11220
11221 if (!gimple_in_ssa_p (cfun))
11222 {
11223 /* Insert the final value of V, in case it is live. This is the
11224 value for the only thread that survives past the join. */
11225 expr = fold_build2 (MINUS_EXPR, diff_type, range, dir);
11226 expr = fold_build2 (PLUS_EXPR, diff_type, expr, s);
11227 expr = fold_build2 (TRUNC_DIV_EXPR, diff_type, expr, s);
11228 expr = fold_build2 (MULT_EXPR, diff_type, expr, s);
11229 expr = build2 (plus_code, iter_type, b, fold_convert (plus_type, expr));
11230 expr = force_gimple_operand_gsi (&gsi, expr, false, NULL_TREE,
11231 true, GSI_SAME_STMT);
11232 ass = gimple_build_assign (v, expr);
11233 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11234 }
11235
11236 /* Remove the OMP_RETURN. */
11237 gsi_remove (&gsi, true);
11238
11239 if (cont_bb)
11240 {
11241 /* We now have one or two nested loops. Update the loop
11242 structures. */
11243 struct loop *parent = entry_bb->loop_father;
11244 struct loop *body = body_bb->loop_father;
11245
11246 if (chunking)
11247 {
11248 struct loop *chunk_loop = alloc_loop ();
11249 chunk_loop->header = head_bb;
11250 chunk_loop->latch = bottom_bb;
11251 add_loop (chunk_loop, parent);
11252 parent = chunk_loop;
11253 }
11254 else if (parent != body)
11255 {
11256 gcc_assert (body->header == body_bb);
11257 gcc_assert (body->latch == cont_bb
11258 || single_pred (body->latch) == cont_bb);
11259 parent = NULL;
11260 }
11261
11262 if (parent)
11263 {
11264 struct loop *body_loop = alloc_loop ();
11265 body_loop->header = body_bb;
11266 body_loop->latch = cont_bb;
11267 add_loop (body_loop, parent);
11268 }
11269 }
11270}
11271
41dbbb37 11272/* Expand the OMP loop defined by REGION. */
953ff289 11273
50674e96 11274static void
355fe088 11275expand_omp_for (struct omp_region *region, gimple *inner_stmt)
50674e96
DN
11276{
11277 struct omp_for_data fd;
a68ab351 11278 struct omp_for_data_loop *loops;
953ff289 11279
a68ab351
JJ
11280 loops
11281 = (struct omp_for_data_loop *)
726a989a 11282 alloca (gimple_omp_for_collapse (last_stmt (region->entry))
a68ab351 11283 * sizeof (struct omp_for_data_loop));
538dd0b7
DM
11284 extract_omp_for_data (as_a <gomp_for *> (last_stmt (region->entry)),
11285 &fd, loops);
21a66e91 11286 region->sched_kind = fd.sched_kind;
e01d41e5 11287 region->sched_modifiers = fd.sched_modifiers;
953ff289 11288
135a171d
JJ
11289 gcc_assert (EDGE_COUNT (region->entry->succs) == 2);
11290 BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
11291 FALLTHRU_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
11292 if (region->cont)
11293 {
11294 gcc_assert (EDGE_COUNT (region->cont->succs) == 2);
11295 BRANCH_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
11296 FALLTHRU_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
11297 }
6093bc06 11298 else
1aa95df7 11299 /* If there isn't a continue then this is a degerate case where
6093bc06
RB
11300 the introduction of abnormal edges during lowering will prevent
11301 original loops from being detected. Fix that up. */
11302 loops_state_set (LOOPS_NEED_FIXUP);
135a171d 11303
0aadce73 11304 if (gimple_omp_for_kind (fd.for_stmt) & GF_OMP_FOR_SIMD)
74bf76ed 11305 expand_omp_simd (region, &fd);
9a771876
JJ
11306 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
11307 expand_cilk_for (region, &fd);
e4834818
NS
11308 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
11309 {
11310 gcc_assert (!inner_stmt);
11311 expand_oacc_for (region, &fd);
11312 }
d9a6bd32
JJ
11313 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_TASKLOOP)
11314 {
11315 if (gimple_omp_for_combined_into_p (fd.for_stmt))
11316 expand_omp_taskloop_for_inner (region, &fd, inner_stmt);
11317 else
11318 expand_omp_taskloop_for_outer (region, &fd, inner_stmt);
11319 }
74bf76ed 11320 else if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
acf0174b 11321 && !fd.have_ordered)
953ff289
DN
11322 {
11323 if (fd.chunk_size == NULL)
acf0174b 11324 expand_omp_for_static_nochunk (region, &fd, inner_stmt);
953ff289 11325 else
acf0174b 11326 expand_omp_for_static_chunk (region, &fd, inner_stmt);
953ff289
DN
11327 }
11328 else
11329 {
a68ab351
JJ
11330 int fn_index, start_ix, next_ix;
11331
74bf76ed
JJ
11332 gcc_assert (gimple_omp_for_kind (fd.for_stmt)
11333 == GF_OMP_FOR_KIND_FOR);
9abd5ed9
JJ
11334 if (fd.chunk_size == NULL
11335 && fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
11336 fd.chunk_size = integer_zero_node;
a68ab351 11337 gcc_assert (fd.sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
e01d41e5
JJ
11338 switch (fd.sched_kind)
11339 {
11340 case OMP_CLAUSE_SCHEDULE_RUNTIME:
11341 fn_index = 3;
11342 break;
11343 case OMP_CLAUSE_SCHEDULE_DYNAMIC:
11344 case OMP_CLAUSE_SCHEDULE_GUIDED:
11345 if ((fd.sched_modifiers & OMP_CLAUSE_SCHEDULE_NONMONOTONIC)
11346 && !fd.ordered
11347 && !fd.have_ordered)
11348 {
11349 fn_index = 3 + fd.sched_kind;
11350 break;
11351 }
11352 /* FALLTHRU */
11353 default:
11354 fn_index = fd.sched_kind;
11355 break;
11356 }
d9a6bd32 11357 if (!fd.ordered)
e01d41e5 11358 fn_index += fd.have_ordered * 6;
d9a6bd32
JJ
11359 if (fd.ordered)
11360 start_ix = ((int)BUILT_IN_GOMP_LOOP_DOACROSS_STATIC_START) + fn_index;
11361 else
11362 start_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_START) + fn_index;
e79983f4 11363 next_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT) + fn_index;
a68ab351
JJ
11364 if (fd.iter_type == long_long_unsigned_type_node)
11365 {
e79983f4
MM
11366 start_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
11367 - (int)BUILT_IN_GOMP_LOOP_STATIC_START);
11368 next_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
11369 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT);
a68ab351 11370 }
bbbbb16a 11371 expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
acf0174b 11372 (enum built_in_function) next_ix, inner_stmt);
953ff289 11373 }
5f40b3cb 11374
a5efada7
RG
11375 if (gimple_in_ssa_p (cfun))
11376 update_ssa (TODO_update_ssa_only_virtuals);
953ff289
DN
11377}
11378
953ff289
DN
11379
11380/* Expand code for an OpenMP sections directive. In pseudo code, we generate
11381
953ff289
DN
11382 v = GOMP_sections_start (n);
11383 L0:
11384 switch (v)
11385 {
11386 case 0:
11387 goto L2;
11388 case 1:
11389 section 1;
11390 goto L1;
11391 case 2:
11392 ...
11393 case n:
11394 ...
953ff289
DN
11395 default:
11396 abort ();
11397 }
11398 L1:
11399 v = GOMP_sections_next ();
11400 goto L0;
11401 L2:
11402 reduction;
11403
50674e96 11404 If this is a combined parallel sections, replace the call to
917948d3 11405 GOMP_sections_start with call to GOMP_sections_next. */
953ff289
DN
11406
11407static void
50674e96 11408expand_omp_sections (struct omp_region *region)
953ff289 11409{
0f900dfa 11410 tree t, u, vin = NULL, vmain, vnext, l2;
726a989a 11411 unsigned len;
e5c95afe 11412 basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
726a989a 11413 gimple_stmt_iterator si, switch_si;
538dd0b7 11414 gomp_sections *sections_stmt;
355fe088 11415 gimple *stmt;
538dd0b7 11416 gomp_continue *cont;
c34938a8
JJ
11417 edge_iterator ei;
11418 edge e;
777f7f9a 11419 struct omp_region *inner;
726a989a 11420 unsigned i, casei;
e5c95afe 11421 bool exit_reachable = region->cont != NULL;
953ff289 11422
65e7bfe3 11423 gcc_assert (region->exit != NULL);
777f7f9a 11424 entry_bb = region->entry;
e5c95afe 11425 l0_bb = single_succ (entry_bb);
777f7f9a 11426 l1_bb = region->cont;
e5c95afe 11427 l2_bb = region->exit;
65e7bfe3
JJ
11428 if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
11429 l2 = gimple_block_label (l2_bb);
11430 else
d3c673c7 11431 {
65e7bfe3
JJ
11432 /* This can happen if there are reductions. */
11433 len = EDGE_COUNT (l0_bb->succs);
11434 gcc_assert (len > 0);
11435 e = EDGE_SUCC (l0_bb, len - 1);
11436 si = gsi_last_bb (e->dest);
11437 l2 = NULL_TREE;
11438 if (gsi_end_p (si)
11439 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
11440 l2 = gimple_block_label (e->dest);
c34938a8 11441 else
65e7bfe3
JJ
11442 FOR_EACH_EDGE (e, ei, l0_bb->succs)
11443 {
11444 si = gsi_last_bb (e->dest);
11445 if (gsi_end_p (si)
11446 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
c34938a8 11447 {
65e7bfe3
JJ
11448 l2 = gimple_block_label (e->dest);
11449 break;
c34938a8 11450 }
65e7bfe3 11451 }
d3c673c7 11452 }
65e7bfe3
JJ
11453 if (exit_reachable)
11454 default_bb = create_empty_bb (l1_bb->prev_bb);
d3c673c7 11455 else
65e7bfe3 11456 default_bb = create_empty_bb (l0_bb);
50674e96
DN
11457
11458 /* We will build a switch() with enough cases for all the
726a989a 11459 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
50674e96 11460 and a default case to abort if something goes wrong. */
e5c95afe 11461 len = EDGE_COUNT (l0_bb->succs);
726a989a 11462
9771b263 11463 /* Use vec::quick_push on label_vec throughout, since we know the size
726a989a 11464 in advance. */
ef062b13 11465 auto_vec<tree> label_vec (len);
953ff289 11466
777f7f9a 11467 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
726a989a
RB
11468 GIMPLE_OMP_SECTIONS statement. */
11469 si = gsi_last_bb (entry_bb);
538dd0b7 11470 sections_stmt = as_a <gomp_sections *> (gsi_stmt (si));
726a989a
RB
11471 gcc_assert (gimple_code (sections_stmt) == GIMPLE_OMP_SECTIONS);
11472 vin = gimple_omp_sections_control (sections_stmt);
50674e96 11473 if (!is_combined_parallel (region))
953ff289 11474 {
50674e96
DN
11475 /* If we are not inside a combined parallel+sections region,
11476 call GOMP_sections_start. */
4befd127 11477 t = build_int_cst (unsigned_type_node, len - 1);
e79983f4 11478 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START);
726a989a 11479 stmt = gimple_build_call (u, 1, t);
953ff289 11480 }
917948d3
ZD
11481 else
11482 {
11483 /* Otherwise, call GOMP_sections_next. */
e79983f4 11484 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
726a989a 11485 stmt = gimple_build_call (u, 0);
917948d3 11486 }
726a989a
RB
11487 gimple_call_set_lhs (stmt, vin);
11488 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
11489 gsi_remove (&si, true);
11490
11491 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
11492 L0_BB. */
11493 switch_si = gsi_last_bb (l0_bb);
11494 gcc_assert (gimple_code (gsi_stmt (switch_si)) == GIMPLE_OMP_SECTIONS_SWITCH);
917948d3
ZD
11495 if (exit_reachable)
11496 {
538dd0b7 11497 cont = as_a <gomp_continue *> (last_stmt (l1_bb));
726a989a
RB
11498 gcc_assert (gimple_code (cont) == GIMPLE_OMP_CONTINUE);
11499 vmain = gimple_omp_continue_control_use (cont);
11500 vnext = gimple_omp_continue_control_def (cont);
917948d3
ZD
11501 }
11502 else
11503 {
11504 vmain = vin;
11505 vnext = NULL_TREE;
11506 }
953ff289 11507
65e7bfe3 11508 t = build_case_label (build_int_cst (unsigned_type_node, 0), NULL, l2);
9771b263 11509 label_vec.quick_push (t);
65e7bfe3 11510 i = 1;
d3c673c7 11511
726a989a 11512 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
e5c95afe
ZD
11513 for (inner = region->inner, casei = 1;
11514 inner;
11515 inner = inner->next, i++, casei++)
953ff289 11516 {
50674e96
DN
11517 basic_block s_entry_bb, s_exit_bb;
11518
c34938a8 11519 /* Skip optional reduction region. */
726a989a 11520 if (inner->type == GIMPLE_OMP_ATOMIC_LOAD)
c34938a8
JJ
11521 {
11522 --i;
11523 --casei;
11524 continue;
11525 }
11526
777f7f9a
RH
11527 s_entry_bb = inner->entry;
11528 s_exit_bb = inner->exit;
953ff289 11529
726a989a 11530 t = gimple_block_label (s_entry_bb);
e5c95afe 11531 u = build_int_cst (unsigned_type_node, casei);
3d528853 11532 u = build_case_label (u, NULL, t);
9771b263 11533 label_vec.quick_push (u);
777f7f9a 11534
726a989a
RB
11535 si = gsi_last_bb (s_entry_bb);
11536 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SECTION);
11537 gcc_assert (i < len || gimple_omp_section_last_p (gsi_stmt (si)));
11538 gsi_remove (&si, true);
777f7f9a 11539 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
d3c673c7
JJ
11540
11541 if (s_exit_bb == NULL)
11542 continue;
11543
726a989a
RB
11544 si = gsi_last_bb (s_exit_bb);
11545 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
11546 gsi_remove (&si, true);
d3c673c7 11547
50674e96 11548 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
953ff289
DN
11549 }
11550
50674e96 11551 /* Error handling code goes in DEFAULT_BB. */
726a989a 11552 t = gimple_block_label (default_bb);
3d528853 11553 u = build_case_label (NULL, NULL, t);
777f7f9a 11554 make_edge (l0_bb, default_bb, 0);
726338f4 11555 add_bb_to_loop (default_bb, current_loops->tree_root);
953ff289 11556
fd8d363e 11557 stmt = gimple_build_switch (vmain, u, label_vec);
726a989a
RB
11558 gsi_insert_after (&switch_si, stmt, GSI_SAME_STMT);
11559 gsi_remove (&switch_si, true);
726a989a
RB
11560
11561 si = gsi_start_bb (default_bb);
e79983f4 11562 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
726a989a 11563 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
50674e96 11564
e5c95afe 11565 if (exit_reachable)
d3c673c7 11566 {
e79983f4
MM
11567 tree bfn_decl;
11568
e5c95afe 11569 /* Code to get the next section goes in L1_BB. */
726a989a
RB
11570 si = gsi_last_bb (l1_bb);
11571 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
953ff289 11572
e79983f4
MM
11573 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
11574 stmt = gimple_build_call (bfn_decl, 0);
726a989a
RB
11575 gimple_call_set_lhs (stmt, vnext);
11576 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
11577 gsi_remove (&si, true);
50674e96 11578
e5c95afe 11579 single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
d3c673c7 11580 }
50674e96 11581
65e7bfe3
JJ
11582 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
11583 si = gsi_last_bb (l2_bb);
11584 if (gimple_omp_return_nowait_p (gsi_stmt (si)))
11585 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
acf0174b
JJ
11586 else if (gimple_omp_return_lhs (gsi_stmt (si)))
11587 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL);
65e7bfe3
JJ
11588 else
11589 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
11590 stmt = gimple_build_call (t, 0);
acf0174b
JJ
11591 if (gimple_omp_return_lhs (gsi_stmt (si)))
11592 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (si)));
65e7bfe3
JJ
11593 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
11594 gsi_remove (&si, true);
11595
917948d3 11596 set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
50674e96 11597}
953ff289 11598
953ff289 11599
777f7f9a
RH
11600/* Expand code for an OpenMP single directive. We've already expanded
11601 much of the code, here we simply place the GOMP_barrier call. */
11602
11603static void
11604expand_omp_single (struct omp_region *region)
11605{
11606 basic_block entry_bb, exit_bb;
726a989a 11607 gimple_stmt_iterator si;
777f7f9a
RH
11608
11609 entry_bb = region->entry;
11610 exit_bb = region->exit;
11611
726a989a 11612 si = gsi_last_bb (entry_bb);
726a989a
RB
11613 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE);
11614 gsi_remove (&si, true);
777f7f9a
RH
11615 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
11616
726a989a 11617 si = gsi_last_bb (exit_bb);
acf0174b
JJ
11618 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
11619 {
11620 tree t = gimple_omp_return_lhs (gsi_stmt (si));
11621 gsi_insert_after (&si, build_omp_barrier (t), GSI_SAME_STMT);
11622 }
726a989a 11623 gsi_remove (&si, true);
777f7f9a
RH
11624 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
11625}
11626
11627
11628/* Generic expansion for OpenMP synchronization directives: master,
11629 ordered and critical. All we need to do here is remove the entry
11630 and exit markers for REGION. */
50674e96
DN
11631
11632static void
11633expand_omp_synch (struct omp_region *region)
11634{
11635 basic_block entry_bb, exit_bb;
726a989a 11636 gimple_stmt_iterator si;
50674e96 11637
777f7f9a
RH
11638 entry_bb = region->entry;
11639 exit_bb = region->exit;
50674e96 11640
726a989a
RB
11641 si = gsi_last_bb (entry_bb);
11642 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE
11643 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASTER
acf0174b 11644 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TASKGROUP
726a989a 11645 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ORDERED
acf0174b
JJ
11646 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CRITICAL
11647 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TEAMS);
726a989a 11648 gsi_remove (&si, true);
50674e96
DN
11649 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
11650
d3c673c7
JJ
11651 if (exit_bb)
11652 {
726a989a
RB
11653 si = gsi_last_bb (exit_bb);
11654 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
11655 gsi_remove (&si, true);
d3c673c7
JJ
11656 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
11657 }
50674e96 11658}
953ff289 11659
20906c66
JJ
11660/* A subroutine of expand_omp_atomic. Attempt to implement the atomic
11661 operation as a normal volatile load. */
11662
11663static bool
05409788
RH
11664expand_omp_atomic_load (basic_block load_bb, tree addr,
11665 tree loaded_val, int index)
20906c66 11666{
05409788
RH
11667 enum built_in_function tmpbase;
11668 gimple_stmt_iterator gsi;
11669 basic_block store_bb;
11670 location_t loc;
355fe088 11671 gimple *stmt;
05409788
RH
11672 tree decl, call, type, itype;
11673
11674 gsi = gsi_last_bb (load_bb);
11675 stmt = gsi_stmt (gsi);
11676 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
11677 loc = gimple_location (stmt);
11678
11679 /* ??? If the target does not implement atomic_load_optab[mode], and mode
11680 is smaller than word size, then expand_atomic_load assumes that the load
11681 is atomic. We could avoid the builtin entirely in this case. */
11682
11683 tmpbase = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
11684 decl = builtin_decl_explicit (tmpbase);
11685 if (decl == NULL_TREE)
11686 return false;
11687
11688 type = TREE_TYPE (loaded_val);
11689 itype = TREE_TYPE (TREE_TYPE (decl));
11690
11691 call = build_call_expr_loc (loc, decl, 2, addr,
acf0174b
JJ
11692 build_int_cst (NULL,
11693 gimple_omp_atomic_seq_cst_p (stmt)
11694 ? MEMMODEL_SEQ_CST
11695 : MEMMODEL_RELAXED));
05409788
RH
11696 if (!useless_type_conversion_p (type, itype))
11697 call = fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
11698 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
11699
11700 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
11701 gsi_remove (&gsi, true);
11702
11703 store_bb = single_succ (load_bb);
11704 gsi = gsi_last_bb (store_bb);
11705 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
11706 gsi_remove (&gsi, true);
11707
11708 if (gimple_in_ssa_p (cfun))
11709 update_ssa (TODO_update_ssa_no_phi);
11710
11711 return true;
20906c66
JJ
11712}
11713
11714/* A subroutine of expand_omp_atomic. Attempt to implement the atomic
11715 operation as a normal volatile store. */
11716
11717static bool
05409788
RH
11718expand_omp_atomic_store (basic_block load_bb, tree addr,
11719 tree loaded_val, tree stored_val, int index)
20906c66 11720{
05409788
RH
11721 enum built_in_function tmpbase;
11722 gimple_stmt_iterator gsi;
11723 basic_block store_bb = single_succ (load_bb);
11724 location_t loc;
355fe088 11725 gimple *stmt;
05409788 11726 tree decl, call, type, itype;
ef4bddc2 11727 machine_mode imode;
05409788
RH
11728 bool exchange;
11729
11730 gsi = gsi_last_bb (load_bb);
11731 stmt = gsi_stmt (gsi);
11732 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
11733
11734 /* If the load value is needed, then this isn't a store but an exchange. */
11735 exchange = gimple_omp_atomic_need_value_p (stmt);
11736
11737 gsi = gsi_last_bb (store_bb);
11738 stmt = gsi_stmt (gsi);
11739 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE);
11740 loc = gimple_location (stmt);
11741
11742 /* ??? If the target does not implement atomic_store_optab[mode], and mode
11743 is smaller than word size, then expand_atomic_store assumes that the store
11744 is atomic. We could avoid the builtin entirely in this case. */
11745
11746 tmpbase = (exchange ? BUILT_IN_ATOMIC_EXCHANGE_N : BUILT_IN_ATOMIC_STORE_N);
11747 tmpbase = (enum built_in_function) ((int) tmpbase + index + 1);
11748 decl = builtin_decl_explicit (tmpbase);
11749 if (decl == NULL_TREE)
11750 return false;
11751
11752 type = TREE_TYPE (stored_val);
11753
11754 /* Dig out the type of the function's second argument. */
11755 itype = TREE_TYPE (decl);
11756 itype = TYPE_ARG_TYPES (itype);
11757 itype = TREE_CHAIN (itype);
11758 itype = TREE_VALUE (itype);
11759 imode = TYPE_MODE (itype);
11760
11761 if (exchange && !can_atomic_exchange_p (imode, true))
11762 return false;
11763
11764 if (!useless_type_conversion_p (itype, type))
11765 stored_val = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, stored_val);
11766 call = build_call_expr_loc (loc, decl, 3, addr, stored_val,
acf0174b
JJ
11767 build_int_cst (NULL,
11768 gimple_omp_atomic_seq_cst_p (stmt)
11769 ? MEMMODEL_SEQ_CST
11770 : MEMMODEL_RELAXED));
05409788
RH
11771 if (exchange)
11772 {
11773 if (!useless_type_conversion_p (type, itype))
11774 call = build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
11775 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
11776 }
11777
11778 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
11779 gsi_remove (&gsi, true);
11780
11781 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
11782 gsi = gsi_last_bb (load_bb);
11783 gsi_remove (&gsi, true);
11784
11785 if (gimple_in_ssa_p (cfun))
11786 update_ssa (TODO_update_ssa_no_phi);
11787
11788 return true;
20906c66
JJ
11789}
11790
a509ebb5 11791/* A subroutine of expand_omp_atomic. Attempt to implement the atomic
86951993 11792 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
a509ebb5
RL
11793 size of the data type, and thus usable to find the index of the builtin
11794 decl. Returns false if the expression is not of the proper form. */
11795
11796static bool
11797expand_omp_atomic_fetch_op (basic_block load_bb,
11798 tree addr, tree loaded_val,
11799 tree stored_val, int index)
11800{
e79983f4 11801 enum built_in_function oldbase, newbase, tmpbase;
a509ebb5 11802 tree decl, itype, call;
20906c66 11803 tree lhs, rhs;
a509ebb5 11804 basic_block store_bb = single_succ (load_bb);
726a989a 11805 gimple_stmt_iterator gsi;
355fe088 11806 gimple *stmt;
db3927fb 11807 location_t loc;
86951993 11808 enum tree_code code;
20906c66 11809 bool need_old, need_new;
ef4bddc2 11810 machine_mode imode;
acf0174b 11811 bool seq_cst;
a509ebb5
RL
11812
11813 /* We expect to find the following sequences:
b8698a0f 11814
a509ebb5 11815 load_bb:
726a989a 11816 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
a509ebb5
RL
11817
11818 store_bb:
11819 val = tmp OP something; (or: something OP tmp)
b8698a0f 11820 GIMPLE_OMP_STORE (val)
a509ebb5 11821
b8698a0f 11822 ???FIXME: Allow a more flexible sequence.
a509ebb5 11823 Perhaps use data flow to pick the statements.
b8698a0f 11824
a509ebb5
RL
11825 */
11826
726a989a
RB
11827 gsi = gsi_after_labels (store_bb);
11828 stmt = gsi_stmt (gsi);
db3927fb 11829 loc = gimple_location (stmt);
726a989a 11830 if (!is_gimple_assign (stmt))
a509ebb5 11831 return false;
726a989a
RB
11832 gsi_next (&gsi);
11833 if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE)
a509ebb5 11834 return false;
20906c66
JJ
11835 need_new = gimple_omp_atomic_need_value_p (gsi_stmt (gsi));
11836 need_old = gimple_omp_atomic_need_value_p (last_stmt (load_bb));
acf0174b 11837 seq_cst = gimple_omp_atomic_seq_cst_p (last_stmt (load_bb));
20906c66 11838 gcc_checking_assert (!need_old || !need_new);
a509ebb5 11839
726a989a 11840 if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
a509ebb5
RL
11841 return false;
11842
a509ebb5 11843 /* Check for one of the supported fetch-op operations. */
86951993
AM
11844 code = gimple_assign_rhs_code (stmt);
11845 switch (code)
a509ebb5
RL
11846 {
11847 case PLUS_EXPR:
11848 case POINTER_PLUS_EXPR:
86951993
AM
11849 oldbase = BUILT_IN_ATOMIC_FETCH_ADD_N;
11850 newbase = BUILT_IN_ATOMIC_ADD_FETCH_N;
a509ebb5
RL
11851 break;
11852 case MINUS_EXPR:
86951993
AM
11853 oldbase = BUILT_IN_ATOMIC_FETCH_SUB_N;
11854 newbase = BUILT_IN_ATOMIC_SUB_FETCH_N;
a509ebb5
RL
11855 break;
11856 case BIT_AND_EXPR:
86951993
AM
11857 oldbase = BUILT_IN_ATOMIC_FETCH_AND_N;
11858 newbase = BUILT_IN_ATOMIC_AND_FETCH_N;
a509ebb5
RL
11859 break;
11860 case BIT_IOR_EXPR:
86951993
AM
11861 oldbase = BUILT_IN_ATOMIC_FETCH_OR_N;
11862 newbase = BUILT_IN_ATOMIC_OR_FETCH_N;
a509ebb5
RL
11863 break;
11864 case BIT_XOR_EXPR:
86951993
AM
11865 oldbase = BUILT_IN_ATOMIC_FETCH_XOR_N;
11866 newbase = BUILT_IN_ATOMIC_XOR_FETCH_N;
a509ebb5
RL
11867 break;
11868 default:
11869 return false;
11870 }
86951993 11871
a509ebb5 11872 /* Make sure the expression is of the proper form. */
726a989a
RB
11873 if (operand_equal_p (gimple_assign_rhs1 (stmt), loaded_val, 0))
11874 rhs = gimple_assign_rhs2 (stmt);
11875 else if (commutative_tree_code (gimple_assign_rhs_code (stmt))
11876 && operand_equal_p (gimple_assign_rhs2 (stmt), loaded_val, 0))
11877 rhs = gimple_assign_rhs1 (stmt);
a509ebb5
RL
11878 else
11879 return false;
11880
e79983f4
MM
11881 tmpbase = ((enum built_in_function)
11882 ((need_new ? newbase : oldbase) + index + 1));
11883 decl = builtin_decl_explicit (tmpbase);
20790697
JJ
11884 if (decl == NULL_TREE)
11885 return false;
a509ebb5 11886 itype = TREE_TYPE (TREE_TYPE (decl));
86951993 11887 imode = TYPE_MODE (itype);
a509ebb5 11888
86951993
AM
11889 /* We could test all of the various optabs involved, but the fact of the
11890 matter is that (with the exception of i486 vs i586 and xadd) all targets
11891 that support any atomic operaton optab also implements compare-and-swap.
11892 Let optabs.c take care of expanding any compare-and-swap loop. */
cedb4a1a 11893 if (!can_compare_and_swap_p (imode, true))
a509ebb5
RL
11894 return false;
11895
726a989a
RB
11896 gsi = gsi_last_bb (load_bb);
11897 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
86951993
AM
11898
11899 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
11900 It only requires that the operation happen atomically. Thus we can
11901 use the RELAXED memory model. */
11902 call = build_call_expr_loc (loc, decl, 3, addr,
11903 fold_convert_loc (loc, itype, rhs),
acf0174b
JJ
11904 build_int_cst (NULL,
11905 seq_cst ? MEMMODEL_SEQ_CST
11906 : MEMMODEL_RELAXED));
86951993 11907
20906c66
JJ
11908 if (need_old || need_new)
11909 {
11910 lhs = need_old ? loaded_val : stored_val;
11911 call = fold_convert_loc (loc, TREE_TYPE (lhs), call);
11912 call = build2_loc (loc, MODIFY_EXPR, void_type_node, lhs, call);
11913 }
11914 else
11915 call = fold_convert_loc (loc, void_type_node, call);
726a989a
RB
11916 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
11917 gsi_remove (&gsi, true);
a509ebb5 11918
726a989a
RB
11919 gsi = gsi_last_bb (store_bb);
11920 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
11921 gsi_remove (&gsi, true);
11922 gsi = gsi_last_bb (store_bb);
11923 gsi_remove (&gsi, true);
a509ebb5
RL
11924
11925 if (gimple_in_ssa_p (cfun))
11926 update_ssa (TODO_update_ssa_no_phi);
11927
11928 return true;
11929}
11930
11931/* A subroutine of expand_omp_atomic. Implement the atomic operation as:
11932
11933 oldval = *addr;
11934 repeat:
11935 newval = rhs; // with oldval replacing *addr in rhs
11936 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
11937 if (oldval != newval)
11938 goto repeat;
11939
11940 INDEX is log2 of the size of the data type, and thus usable to find the
11941 index of the builtin decl. */
11942
11943static bool
11944expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
11945 tree addr, tree loaded_val, tree stored_val,
11946 int index)
11947{
c18c98c0 11948 tree loadedi, storedi, initial, new_storedi, old_vali;
a509ebb5 11949 tree type, itype, cmpxchg, iaddr;
726a989a 11950 gimple_stmt_iterator si;
a509ebb5 11951 basic_block loop_header = single_succ (load_bb);
355fe088 11952 gimple *phi, *stmt;
a509ebb5 11953 edge e;
e79983f4 11954 enum built_in_function fncode;
a509ebb5 11955
86951993
AM
11956 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
11957 order to use the RELAXED memory model effectively. */
e79983f4
MM
11958 fncode = (enum built_in_function)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
11959 + index + 1);
11960 cmpxchg = builtin_decl_explicit (fncode);
20790697
JJ
11961 if (cmpxchg == NULL_TREE)
11962 return false;
a509ebb5
RL
11963 type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
11964 itype = TREE_TYPE (TREE_TYPE (cmpxchg));
11965
cedb4a1a 11966 if (!can_compare_and_swap_p (TYPE_MODE (itype), true))
a509ebb5
RL
11967 return false;
11968
726a989a
RB
11969 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
11970 si = gsi_last_bb (load_bb);
11971 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
11972
c18c98c0
JJ
11973 /* For floating-point values, we'll need to view-convert them to integers
11974 so that we can perform the atomic compare and swap. Simplify the
11975 following code by always setting up the "i"ntegral variables. */
11976 if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
11977 {
726a989a
RB
11978 tree iaddr_val;
11979
7cc434a3 11980 iaddr = create_tmp_reg (build_pointer_type_for_mode (itype, ptr_mode,
b731b390 11981 true));
726a989a
RB
11982 iaddr_val
11983 = force_gimple_operand_gsi (&si,
11984 fold_convert (TREE_TYPE (iaddr), addr),
11985 false, NULL_TREE, true, GSI_SAME_STMT);
11986 stmt = gimple_build_assign (iaddr, iaddr_val);
11987 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
b731b390 11988 loadedi = create_tmp_var (itype);
c18c98c0 11989 if (gimple_in_ssa_p (cfun))
b731b390 11990 loadedi = make_ssa_name (loadedi);
c18c98c0
JJ
11991 }
11992 else
11993 {
11994 iaddr = addr;
11995 loadedi = loaded_val;
11996 }
726a989a 11997
8175be9a
JJ
11998 fncode = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
11999 tree loaddecl = builtin_decl_explicit (fncode);
12000 if (loaddecl)
12001 initial
12002 = fold_convert (TREE_TYPE (TREE_TYPE (iaddr)),
12003 build_call_expr (loaddecl, 2, iaddr,
12004 build_int_cst (NULL_TREE,
12005 MEMMODEL_RELAXED)));
12006 else
12007 initial = build2 (MEM_REF, TREE_TYPE (TREE_TYPE (iaddr)), iaddr,
12008 build_int_cst (TREE_TYPE (iaddr), 0));
12009
70f34814 12010 initial
8175be9a
JJ
12011 = force_gimple_operand_gsi (&si, initial, true, NULL_TREE, true,
12012 GSI_SAME_STMT);
c18c98c0
JJ
12013
12014 /* Move the value to the LOADEDI temporary. */
a509ebb5
RL
12015 if (gimple_in_ssa_p (cfun))
12016 {
726a989a 12017 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header)));
c18c98c0 12018 phi = create_phi_node (loadedi, loop_header);
a509ebb5
RL
12019 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)),
12020 initial);
12021 }
12022 else
726a989a
RB
12023 gsi_insert_before (&si,
12024 gimple_build_assign (loadedi, initial),
12025 GSI_SAME_STMT);
c18c98c0
JJ
12026 if (loadedi != loaded_val)
12027 {
726a989a
RB
12028 gimple_stmt_iterator gsi2;
12029 tree x;
c18c98c0
JJ
12030
12031 x = build1 (VIEW_CONVERT_EXPR, type, loadedi);
726a989a 12032 gsi2 = gsi_start_bb (loop_header);
c18c98c0
JJ
12033 if (gimple_in_ssa_p (cfun))
12034 {
538dd0b7 12035 gassign *stmt;
726a989a
RB
12036 x = force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
12037 true, GSI_SAME_STMT);
12038 stmt = gimple_build_assign (loaded_val, x);
12039 gsi_insert_before (&gsi2, stmt, GSI_SAME_STMT);
c18c98c0
JJ
12040 }
12041 else
12042 {
726a989a
RB
12043 x = build2 (MODIFY_EXPR, TREE_TYPE (loaded_val), loaded_val, x);
12044 force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
12045 true, GSI_SAME_STMT);
c18c98c0
JJ
12046 }
12047 }
726a989a 12048 gsi_remove (&si, true);
a509ebb5 12049
726a989a
RB
12050 si = gsi_last_bb (store_bb);
12051 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
a509ebb5 12052
c18c98c0
JJ
12053 if (iaddr == addr)
12054 storedi = stored_val;
a509ebb5 12055 else
c18c98c0 12056 storedi =
726a989a 12057 force_gimple_operand_gsi (&si,
c18c98c0
JJ
12058 build1 (VIEW_CONVERT_EXPR, itype,
12059 stored_val), true, NULL_TREE, true,
726a989a 12060 GSI_SAME_STMT);
a509ebb5
RL
12061
12062 /* Build the compare&swap statement. */
12063 new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi);
726a989a 12064 new_storedi = force_gimple_operand_gsi (&si,
587aa063
RG
12065 fold_convert (TREE_TYPE (loadedi),
12066 new_storedi),
a509ebb5 12067 true, NULL_TREE,
726a989a 12068 true, GSI_SAME_STMT);
a509ebb5
RL
12069
12070 if (gimple_in_ssa_p (cfun))
12071 old_vali = loadedi;
12072 else
12073 {
b731b390 12074 old_vali = create_tmp_var (TREE_TYPE (loadedi));
726a989a
RB
12075 stmt = gimple_build_assign (old_vali, loadedi);
12076 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
a509ebb5 12077
726a989a
RB
12078 stmt = gimple_build_assign (loadedi, new_storedi);
12079 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
a509ebb5
RL
12080 }
12081
12082 /* Note that we always perform the comparison as an integer, even for
b8698a0f 12083 floating point. This allows the atomic operation to properly
a509ebb5 12084 succeed even with NaNs and -0.0. */
726a989a
RB
12085 stmt = gimple_build_cond_empty
12086 (build2 (NE_EXPR, boolean_type_node,
12087 new_storedi, old_vali));
12088 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
a509ebb5
RL
12089
12090 /* Update cfg. */
12091 e = single_succ_edge (store_bb);
12092 e->flags &= ~EDGE_FALLTHRU;
12093 e->flags |= EDGE_FALSE_VALUE;
12094
12095 e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE);
12096
c18c98c0 12097 /* Copy the new value to loadedi (we already did that before the condition
a509ebb5
RL
12098 if we are not in SSA). */
12099 if (gimple_in_ssa_p (cfun))
12100 {
726a989a 12101 phi = gimple_seq_first_stmt (phi_nodes (loop_header));
c18c98c0 12102 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), new_storedi);
a509ebb5
RL
12103 }
12104
726a989a
RB
12105 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
12106 gsi_remove (&si, true);
a509ebb5 12107
6093bc06
RB
12108 struct loop *loop = alloc_loop ();
12109 loop->header = loop_header;
a1756c0a 12110 loop->latch = store_bb;
6093bc06
RB
12111 add_loop (loop, loop_header->loop_father);
12112
a509ebb5
RL
12113 if (gimple_in_ssa_p (cfun))
12114 update_ssa (TODO_update_ssa_no_phi);
12115
12116 return true;
12117}
12118
12119/* A subroutine of expand_omp_atomic. Implement the atomic operation as:
12120
12121 GOMP_atomic_start ();
12122 *addr = rhs;
12123 GOMP_atomic_end ();
12124
12125 The result is not globally atomic, but works so long as all parallel
12126 references are within #pragma omp atomic directives. According to
12127 responses received from omp@openmp.org, appears to be within spec.
12128 Which makes sense, since that's how several other compilers handle
b8698a0f 12129 this situation as well.
726a989a
RB
12130 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
12131 expanding. STORED_VAL is the operand of the matching
12132 GIMPLE_OMP_ATOMIC_STORE.
a509ebb5 12133
b8698a0f
L
12134 We replace
12135 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
a509ebb5
RL
12136 loaded_val = *addr;
12137
12138 and replace
05409788 12139 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
b8698a0f 12140 *addr = stored_val;
a509ebb5
RL
12141*/
12142
12143static bool
12144expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
12145 tree addr, tree loaded_val, tree stored_val)
12146{
726a989a 12147 gimple_stmt_iterator si;
538dd0b7 12148 gassign *stmt;
a509ebb5
RL
12149 tree t;
12150
726a989a
RB
12151 si = gsi_last_bb (load_bb);
12152 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
a509ebb5 12153
e79983f4 12154 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
3bb06db4 12155 t = build_call_expr (t, 0);
726a989a 12156 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
a509ebb5 12157
70f34814 12158 stmt = gimple_build_assign (loaded_val, build_simple_mem_ref (addr));
726a989a
RB
12159 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
12160 gsi_remove (&si, true);
a509ebb5 12161
726a989a
RB
12162 si = gsi_last_bb (store_bb);
12163 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
a509ebb5 12164
70f34814
RG
12165 stmt = gimple_build_assign (build_simple_mem_ref (unshare_expr (addr)),
12166 stored_val);
726a989a 12167 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
a509ebb5 12168
e79983f4 12169 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
3bb06db4 12170 t = build_call_expr (t, 0);
726a989a
RB
12171 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
12172 gsi_remove (&si, true);
a509ebb5
RL
12173
12174 if (gimple_in_ssa_p (cfun))
12175 update_ssa (TODO_update_ssa_no_phi);
12176 return true;
12177}
12178
b8698a0f
L
12179/* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
12180 using expand_omp_atomic_fetch_op. If it failed, we try to
a509ebb5
RL
12181 call expand_omp_atomic_pipeline, and if it fails too, the
12182 ultimate fallback is wrapping the operation in a mutex
b8698a0f
L
12183 (expand_omp_atomic_mutex). REGION is the atomic region built
12184 by build_omp_regions_1(). */
a509ebb5
RL
12185
12186static void
12187expand_omp_atomic (struct omp_region *region)
12188{
12189 basic_block load_bb = region->entry, store_bb = region->exit;
538dd0b7
DM
12190 gomp_atomic_load *load = as_a <gomp_atomic_load *> (last_stmt (load_bb));
12191 gomp_atomic_store *store = as_a <gomp_atomic_store *> (last_stmt (store_bb));
726a989a
RB
12192 tree loaded_val = gimple_omp_atomic_load_lhs (load);
12193 tree addr = gimple_omp_atomic_load_rhs (load);
12194 tree stored_val = gimple_omp_atomic_store_val (store);
a509ebb5
RL
12195 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
12196 HOST_WIDE_INT index;
12197
12198 /* Make sure the type is one of the supported sizes. */
ae7e9ddd 12199 index = tree_to_uhwi (TYPE_SIZE_UNIT (type));
a509ebb5
RL
12200 index = exact_log2 (index);
12201 if (index >= 0 && index <= 4)
12202 {
12203 unsigned int align = TYPE_ALIGN_UNIT (type);
12204
12205 /* __sync builtins require strict data alignment. */
4999c62c 12206 if (exact_log2 (align) >= index)
a509ebb5 12207 {
05409788 12208 /* Atomic load. */
20906c66
JJ
12209 if (loaded_val == stored_val
12210 && (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
12211 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
12212 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
05409788 12213 && expand_omp_atomic_load (load_bb, addr, loaded_val, index))
20906c66
JJ
12214 return;
12215
05409788 12216 /* Atomic store. */
20906c66
JJ
12217 if ((GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
12218 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
12219 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
12220 && store_bb == single_succ (load_bb)
12221 && first_stmt (store_bb) == store
05409788
RH
12222 && expand_omp_atomic_store (load_bb, addr, loaded_val,
12223 stored_val, index))
20906c66
JJ
12224 return;
12225
a509ebb5
RL
12226 /* When possible, use specialized atomic update functions. */
12227 if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
05409788
RH
12228 && store_bb == single_succ (load_bb)
12229 && expand_omp_atomic_fetch_op (load_bb, addr,
12230 loaded_val, stored_val, index))
12231 return;
a509ebb5
RL
12232
12233 /* If we don't have specialized __sync builtins, try and implement
12234 as a compare and swap loop. */
12235 if (expand_omp_atomic_pipeline (load_bb, store_bb, addr,
12236 loaded_val, stored_val, index))
12237 return;
12238 }
12239 }
12240
12241 /* The ultimate fallback is wrapping the operation in a mutex. */
12242 expand_omp_atomic_mutex (load_bb, store_bb, addr, loaded_val, stored_val);
12243}
12244
953ff289 12245
374d0225 12246/* Encode an oacc launch argument. This matches the GOMP_LAUNCH_PACK
3e32ee19
NS
12247 macro on gomp-constants.h. We do not check for overflow. */
12248
12249static tree
12250oacc_launch_pack (unsigned code, tree device, unsigned op)
12251{
12252 tree res;
12253
12254 res = build_int_cst (unsigned_type_node, GOMP_LAUNCH_PACK (code, 0, op));
12255 if (device)
12256 {
12257 device = fold_build2 (LSHIFT_EXPR, unsigned_type_node,
12258 device, build_int_cst (unsigned_type_node,
12259 GOMP_LAUNCH_DEVICE_SHIFT));
12260 res = fold_build2 (BIT_IOR_EXPR, unsigned_type_node, res, device);
12261 }
12262 return res;
12263}
12264
12265/* Look for compute grid dimension clauses and convert to an attribute
12266 attached to FN. This permits the target-side code to (a) massage
12267 the dimensions, (b) emit that data and (c) optimize. Non-constant
12268 dimensions are pushed onto ARGS.
12269
12270 The attribute value is a TREE_LIST. A set of dimensions is
12271 represented as a list of INTEGER_CST. Those that are runtime
374d0225 12272 exprs are represented as an INTEGER_CST of zero.
3e32ee19
NS
12273
12274 TOOO. Normally the attribute will just contain a single such list. If
12275 however it contains a list of lists, this will represent the use of
12276 device_type. Each member of the outer list is an assoc list of
12277 dimensions, keyed by the device type. The first entry will be the
12278 default. Well, that's the plan. */
12279
12280#define OACC_FN_ATTRIB "oacc function"
12281
12282/* Replace any existing oacc fn attribute with updated dimensions. */
12283
12284void
12285replace_oacc_fn_attrib (tree fn, tree dims)
12286{
12287 tree ident = get_identifier (OACC_FN_ATTRIB);
12288 tree attribs = DECL_ATTRIBUTES (fn);
12289
12290 /* If we happen to be present as the first attrib, drop it. */
12291 if (attribs && TREE_PURPOSE (attribs) == ident)
12292 attribs = TREE_CHAIN (attribs);
12293 DECL_ATTRIBUTES (fn) = tree_cons (ident, dims, attribs);
12294}
12295
12296/* Scan CLAUSES for launch dimensions and attach them to the oacc
12297 function attribute. Push any that are non-constant onto the ARGS
12298 list, along with an appropriate GOMP_LAUNCH_DIM tag. */
12299
12300static void
12301set_oacc_fn_attrib (tree fn, tree clauses, vec<tree> *args)
12302{
12303 /* Must match GOMP_DIM ordering. */
12304 static const omp_clause_code ids[]
12305 = { OMP_CLAUSE_NUM_GANGS, OMP_CLAUSE_NUM_WORKERS,
12306 OMP_CLAUSE_VECTOR_LENGTH };
12307 unsigned ix;
12308 tree dims[GOMP_DIM_MAX];
12309 tree attr = NULL_TREE;
12310 unsigned non_const = 0;
12311
12312 for (ix = GOMP_DIM_MAX; ix--;)
12313 {
12314 tree clause = find_omp_clause (clauses, ids[ix]);
12315 tree dim = NULL_TREE;
12316
12317 if (clause)
12318 dim = OMP_CLAUSE_EXPR (clause, ids[ix]);
12319 dims[ix] = dim;
12320 if (dim && TREE_CODE (dim) != INTEGER_CST)
12321 {
12322 dim = integer_zero_node;
12323 non_const |= GOMP_DIM_MASK (ix);
12324 }
12325 attr = tree_cons (NULL_TREE, dim, attr);
12326 }
12327
12328 replace_oacc_fn_attrib (fn, attr);
12329
12330 if (non_const)
12331 {
12332 /* Push a dynamic argument set. */
12333 args->safe_push (oacc_launch_pack (GOMP_LAUNCH_DIM,
12334 NULL_TREE, non_const));
12335 for (unsigned ix = 0; ix != GOMP_DIM_MAX; ix++)
12336 if (non_const & GOMP_DIM_MASK (ix))
12337 args->safe_push (dims[ix]);
12338 }
12339}
12340
3a40d81d
NS
12341/* Process the routine's dimension clauess to generate an attribute
12342 value. Issue diagnostics as appropriate. We default to SEQ
12343 (OpenACC 2.5 clarifies this). All dimensions have a size of zero
12344 (dynamic). TREE_PURPOSE is set to indicate whether that dimension
12345 can have a loop partitioned on it. non-zero indicates
12346 yes, zero indicates no. By construction once a non-zero has been
12347 reached, further inner dimensions must also be non-zero. We set
12348 TREE_VALUE to zero for the dimensions that may be partitioned and
12349 1 for the other ones -- if a loop is (erroneously) spawned at
12350 an outer level, we don't want to try and partition it. */
12351
12352tree
12353build_oacc_routine_dims (tree clauses)
12354{
12355 /* Must match GOMP_DIM ordering. */
12356 static const omp_clause_code ids[] =
12357 {OMP_CLAUSE_GANG, OMP_CLAUSE_WORKER, OMP_CLAUSE_VECTOR, OMP_CLAUSE_SEQ};
12358 int ix;
12359 int level = -1;
12360
12361 for (; clauses; clauses = OMP_CLAUSE_CHAIN (clauses))
12362 for (ix = GOMP_DIM_MAX + 1; ix--;)
12363 if (OMP_CLAUSE_CODE (clauses) == ids[ix])
12364 {
12365 if (level >= 0)
12366 error_at (OMP_CLAUSE_LOCATION (clauses),
12367 "multiple loop axes specified for routine");
12368 level = ix;
12369 break;
12370 }
12371
12372 /* Default to SEQ. */
12373 if (level < 0)
12374 level = GOMP_DIM_MAX;
12375
12376 tree dims = NULL_TREE;
12377
12378 for (ix = GOMP_DIM_MAX; ix--;)
12379 dims = tree_cons (build_int_cst (boolean_type_node, ix >= level),
12380 build_int_cst (integer_type_node, ix < level), dims);
12381
12382 return dims;
12383}
12384
3e32ee19
NS
12385/* Retrieve the oacc function attrib and return it. Non-oacc
12386 functions will return NULL. */
12387
12388tree
12389get_oacc_fn_attrib (tree fn)
12390{
12391 return lookup_attribute (OACC_FN_ATTRIB, DECL_ATTRIBUTES (fn));
12392}
12393
bd751975
NS
12394/* Extract an oacc execution dimension from FN. FN must be an
12395 offloaded function or routine that has already had its execution
12396 dimensions lowered to the target-specific values. */
12397
12398int
12399get_oacc_fn_dim_size (tree fn, int axis)
12400{
12401 tree attrs = get_oacc_fn_attrib (fn);
12402
12403 gcc_assert (axis < GOMP_DIM_MAX);
12404
12405 tree dims = TREE_VALUE (attrs);
12406 while (axis--)
12407 dims = TREE_CHAIN (dims);
12408
12409 int size = TREE_INT_CST_LOW (TREE_VALUE (dims));
12410
12411 return size;
12412}
12413
12414/* Extract the dimension axis from an IFN_GOACC_DIM_POS or
12415 IFN_GOACC_DIM_SIZE call. */
12416
12417int
12418get_oacc_ifn_dim_arg (const gimple *stmt)
12419{
12420 gcc_checking_assert (gimple_call_internal_fn (stmt) == IFN_GOACC_DIM_SIZE
12421 || gimple_call_internal_fn (stmt) == IFN_GOACC_DIM_POS);
12422 tree arg = gimple_call_arg (stmt, 0);
12423 HOST_WIDE_INT axis = TREE_INT_CST_LOW (arg);
12424
12425 gcc_checking_assert (axis >= 0 && axis < GOMP_DIM_MAX);
12426 return (int) axis;
12427}
12428
41dbbb37 12429/* Expand the GIMPLE_OMP_TARGET starting at REGION. */
acf0174b
JJ
12430
12431static void
12432expand_omp_target (struct omp_region *region)
12433{
12434 basic_block entry_bb, exit_bb, new_bb;
41dbbb37
TS
12435 struct function *child_cfun;
12436 tree child_fn, block, t;
acf0174b 12437 gimple_stmt_iterator gsi;
538dd0b7 12438 gomp_target *entry_stmt;
355fe088 12439 gimple *stmt;
acf0174b 12440 edge e;
41dbbb37 12441 bool offloaded, data_region;
acf0174b 12442
538dd0b7 12443 entry_stmt = as_a <gomp_target *> (last_stmt (region->entry));
acf0174b 12444 new_bb = region->entry;
41dbbb37
TS
12445
12446 offloaded = is_gimple_omp_offloaded (entry_stmt);
12447 switch (gimple_omp_target_kind (entry_stmt))
12448 {
3e32ee19
NS
12449 case GF_OMP_TARGET_KIND_REGION:
12450 case GF_OMP_TARGET_KIND_UPDATE:
d9a6bd32
JJ
12451 case GF_OMP_TARGET_KIND_ENTER_DATA:
12452 case GF_OMP_TARGET_KIND_EXIT_DATA:
12453 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
12454 case GF_OMP_TARGET_KIND_OACC_KERNELS:
41dbbb37
TS
12455 case GF_OMP_TARGET_KIND_OACC_UPDATE:
12456 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
6e232ba4 12457 case GF_OMP_TARGET_KIND_OACC_DECLARE:
41dbbb37
TS
12458 data_region = false;
12459 break;
12460 case GF_OMP_TARGET_KIND_DATA:
12461 case GF_OMP_TARGET_KIND_OACC_DATA:
12462 data_region = true;
12463 break;
12464 default:
12465 gcc_unreachable ();
12466 }
12467
12468 child_fn = NULL_TREE;
12469 child_cfun = NULL;
12470 if (offloaded)
acf0174b
JJ
12471 {
12472 child_fn = gimple_omp_target_child_fn (entry_stmt);
12473 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
12474 }
12475
41dbbb37
TS
12476 /* Supported by expand_omp_taskreg, but not here. */
12477 if (child_cfun != NULL)
12478 gcc_checking_assert (!child_cfun->cfg);
12479 gcc_checking_assert (!gimple_in_ssa_p (cfun));
12480
acf0174b
JJ
12481 entry_bb = region->entry;
12482 exit_bb = region->exit;
12483
41dbbb37 12484 if (offloaded)
acf0174b
JJ
12485 {
12486 unsigned srcidx, dstidx, num;
12487
41dbbb37 12488 /* If the offloading region needs data sent from the parent
acf0174b 12489 function, then the very first statement (except possible
41dbbb37 12490 tree profile counter updates) of the offloading body
acf0174b
JJ
12491 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
12492 &.OMP_DATA_O is passed as an argument to the child function,
12493 we need to replace it with the argument as seen by the child
12494 function.
12495
12496 In most cases, this will end up being the identity assignment
41dbbb37 12497 .OMP_DATA_I = .OMP_DATA_I. However, if the offloading body had
acf0174b
JJ
12498 a function call that has been inlined, the original PARM_DECL
12499 .OMP_DATA_I may have been converted into a different local
12500 variable. In which case, we need to keep the assignment. */
41dbbb37
TS
12501 tree data_arg = gimple_omp_target_data_arg (entry_stmt);
12502 if (data_arg)
acf0174b
JJ
12503 {
12504 basic_block entry_succ_bb = single_succ (entry_bb);
12505 gimple_stmt_iterator gsi;
12506 tree arg;
355fe088 12507 gimple *tgtcopy_stmt = NULL;
41dbbb37 12508 tree sender = TREE_VEC_ELT (data_arg, 0);
acf0174b
JJ
12509
12510 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
12511 {
12512 gcc_assert (!gsi_end_p (gsi));
12513 stmt = gsi_stmt (gsi);
12514 if (gimple_code (stmt) != GIMPLE_ASSIGN)
12515 continue;
12516
12517 if (gimple_num_ops (stmt) == 2)
12518 {
12519 tree arg = gimple_assign_rhs1 (stmt);
12520
12521 /* We're ignoring the subcode because we're
12522 effectively doing a STRIP_NOPS. */
12523
12524 if (TREE_CODE (arg) == ADDR_EXPR
12525 && TREE_OPERAND (arg, 0) == sender)
12526 {
12527 tgtcopy_stmt = stmt;
12528 break;
12529 }
12530 }
12531 }
12532
12533 gcc_assert (tgtcopy_stmt != NULL);
12534 arg = DECL_ARGUMENTS (child_fn);
12535
12536 gcc_assert (gimple_assign_lhs (tgtcopy_stmt) == arg);
12537 gsi_remove (&gsi, true);
12538 }
12539
12540 /* Declare local variables needed in CHILD_CFUN. */
12541 block = DECL_INITIAL (child_fn);
12542 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
41dbbb37 12543 /* The gimplifier could record temporaries in the offloading block
acf0174b
JJ
12544 rather than in containing function's local_decls chain,
12545 which would mean cgraph missed finalizing them. Do it now. */
12546 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
12547 if (TREE_CODE (t) == VAR_DECL
12548 && TREE_STATIC (t)
12549 && !DECL_EXTERNAL (t))
9041d2e6 12550 varpool_node::finalize_decl (t);
acf0174b
JJ
12551 DECL_SAVED_TREE (child_fn) = NULL;
12552 /* We'll create a CFG for child_fn, so no gimple body is needed. */
12553 gimple_set_body (child_fn, NULL);
12554 TREE_USED (block) = 1;
12555
12556 /* Reset DECL_CONTEXT on function arguments. */
12557 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
12558 DECL_CONTEXT (t) = child_fn;
12559
41dbbb37 12560 /* Split ENTRY_BB at GIMPLE_*,
acf0174b
JJ
12561 so that it can be moved to the child function. */
12562 gsi = gsi_last_bb (entry_bb);
12563 stmt = gsi_stmt (gsi);
41dbbb37
TS
12564 gcc_assert (stmt
12565 && gimple_code (stmt) == gimple_code (entry_stmt));
acf0174b 12566 e = split_block (entry_bb, stmt);
b13c907a 12567 gsi_remove (&gsi, true);
acf0174b
JJ
12568 entry_bb = e->dest;
12569 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
12570
12571 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
12572 if (exit_bb)
12573 {
12574 gsi = gsi_last_bb (exit_bb);
12575 gcc_assert (!gsi_end_p (gsi)
12576 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
12577 stmt = gimple_build_return (NULL);
12578 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
12579 gsi_remove (&gsi, true);
12580 }
12581
41dbbb37 12582 /* Move the offloading region into CHILD_CFUN. */
acf0174b
JJ
12583
12584 block = gimple_block (entry_stmt);
12585
12586 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
12587 if (exit_bb)
12588 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
12589 /* When the OMP expansion process cannot guarantee an up-to-date
12590 loop tree arrange for the child function to fixup loops. */
12591 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
12592 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
12593
12594 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
12595 num = vec_safe_length (child_cfun->local_decls);
12596 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
12597 {
12598 t = (*child_cfun->local_decls)[srcidx];
12599 if (DECL_CONTEXT (t) == cfun->decl)
12600 continue;
12601 if (srcidx != dstidx)
12602 (*child_cfun->local_decls)[dstidx] = t;
12603 dstidx++;
12604 }
12605 if (dstidx != num)
12606 vec_safe_truncate (child_cfun->local_decls, dstidx);
12607
12608 /* Inform the callgraph about the new function. */
a1ceb604
JJ
12609 child_cfun->curr_properties = cfun->curr_properties;
12610 child_cfun->has_simduid_loops |= cfun->has_simduid_loops;
12611 child_cfun->has_force_vectorize_loops |= cfun->has_force_vectorize_loops;
c2f57691
TV
12612 cgraph_node *node = cgraph_node::get_create (child_fn);
12613 node->parallelized_function = 1;
d52f5295 12614 cgraph_node::add_new_function (child_fn, true);
acf0174b 12615
844b0125 12616#ifdef ENABLE_OFFLOADING
ec6fe917
IV
12617 /* Add the new function to the offload table. */
12618 vec_safe_push (offload_funcs, child_fn);
844b0125 12619#endif
ec6fe917 12620
e01d41e5
JJ
12621 bool need_asm = DECL_ASSEMBLER_NAME_SET_P (current_function_decl)
12622 && !DECL_ASSEMBLER_NAME_SET_P (child_fn);
12623
acf0174b
JJ
12624 /* Fix the callgraph edges for child_cfun. Those for cfun will be
12625 fixed in a following pass. */
12626 push_cfun (child_cfun);
e01d41e5
JJ
12627 if (need_asm)
12628 assign_assembler_name_if_neeeded (child_fn);
3dafb85c 12629 cgraph_edge::rebuild_edges ();
acf0174b 12630
844b0125 12631#ifdef ENABLE_OFFLOADING
1f6be682
IV
12632 /* Prevent IPA from removing child_fn as unreachable, since there are no
12633 refs from the parent function to child_fn in offload LTO mode. */
68706112 12634 cgraph_node::get (child_fn)->mark_force_output ();
844b0125 12635#endif
1f6be682 12636
acf0174b
JJ
12637 /* Some EH regions might become dead, see PR34608. If
12638 pass_cleanup_cfg isn't the first pass to happen with the
12639 new child, these dead EH edges might cause problems.
12640 Clean them up now. */
12641 if (flag_exceptions)
12642 {
12643 basic_block bb;
12644 bool changed = false;
12645
11cd3bed 12646 FOR_EACH_BB_FN (bb, cfun)
acf0174b
JJ
12647 changed |= gimple_purge_dead_eh_edges (bb);
12648 if (changed)
12649 cleanup_tree_cfg ();
12650 }
b2b29377 12651 if (flag_checking && !loops_state_satisfies_p (LOOPS_NEED_FIXUP))
e67d7a1e 12652 verify_loop_structure ();
acf0174b 12653 pop_cfun ();
e01d41e5
JJ
12654
12655 if (dump_file && !gimple_in_ssa_p (cfun))
12656 {
12657 omp_any_child_fn_dumped = true;
12658 dump_function_header (dump_file, child_fn, dump_flags);
12659 dump_function_to_file (child_fn, dump_file, dump_flags);
12660 }
acf0174b
JJ
12661 }
12662
41dbbb37 12663 /* Emit a library call to launch the offloading region, or do data
acf0174b 12664 transfers. */
d9a6bd32 12665 tree t1, t2, t3, t4, device, cond, depend, c, clauses;
acf0174b
JJ
12666 enum built_in_function start_ix;
12667 location_t clause_loc;
d9a6bd32 12668 unsigned int flags_i = 0;
acf0174b 12669
41dbbb37
TS
12670 switch (gimple_omp_target_kind (entry_stmt))
12671 {
12672 case GF_OMP_TARGET_KIND_REGION:
12673 start_ix = BUILT_IN_GOMP_TARGET;
12674 break;
12675 case GF_OMP_TARGET_KIND_DATA:
12676 start_ix = BUILT_IN_GOMP_TARGET_DATA;
12677 break;
12678 case GF_OMP_TARGET_KIND_UPDATE:
12679 start_ix = BUILT_IN_GOMP_TARGET_UPDATE;
12680 break;
d9a6bd32
JJ
12681 case GF_OMP_TARGET_KIND_ENTER_DATA:
12682 start_ix = BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA;
12683 break;
12684 case GF_OMP_TARGET_KIND_EXIT_DATA:
12685 start_ix = BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA;
12686 flags_i |= GOMP_TARGET_FLAG_EXIT_DATA;
12687 break;
41dbbb37
TS
12688 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
12689 case GF_OMP_TARGET_KIND_OACC_KERNELS:
12690 start_ix = BUILT_IN_GOACC_PARALLEL;
12691 break;
12692 case GF_OMP_TARGET_KIND_OACC_DATA:
12693 start_ix = BUILT_IN_GOACC_DATA_START;
12694 break;
12695 case GF_OMP_TARGET_KIND_OACC_UPDATE:
12696 start_ix = BUILT_IN_GOACC_UPDATE;
12697 break;
12698 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
12699 start_ix = BUILT_IN_GOACC_ENTER_EXIT_DATA;
12700 break;
6e232ba4
JN
12701 case GF_OMP_TARGET_KIND_OACC_DECLARE:
12702 start_ix = BUILT_IN_GOACC_DECLARE;
12703 break;
41dbbb37
TS
12704 default:
12705 gcc_unreachable ();
12706 }
acf0174b 12707
41dbbb37 12708 clauses = gimple_omp_target_clauses (entry_stmt);
acf0174b 12709
41dbbb37
TS
12710 /* By default, the value of DEVICE is GOMP_DEVICE_ICV (let runtime
12711 library choose) and there is no conditional. */
acf0174b 12712 cond = NULL_TREE;
41dbbb37 12713 device = build_int_cst (integer_type_node, GOMP_DEVICE_ICV);
acf0174b
JJ
12714
12715 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
12716 if (c)
12717 cond = OMP_CLAUSE_IF_EXPR (c);
12718
12719 c = find_omp_clause (clauses, OMP_CLAUSE_DEVICE);
12720 if (c)
12721 {
41dbbb37
TS
12722 /* Even if we pass it to all library function calls, it is currently only
12723 defined/used for the OpenMP target ones. */
12724 gcc_checking_assert (start_ix == BUILT_IN_GOMP_TARGET
12725 || start_ix == BUILT_IN_GOMP_TARGET_DATA
d9a6bd32
JJ
12726 || start_ix == BUILT_IN_GOMP_TARGET_UPDATE
12727 || start_ix == BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA);
41dbbb37 12728
acf0174b
JJ
12729 device = OMP_CLAUSE_DEVICE_ID (c);
12730 clause_loc = OMP_CLAUSE_LOCATION (c);
12731 }
12732 else
12733 clause_loc = gimple_location (entry_stmt);
12734
d9a6bd32
JJ
12735 c = find_omp_clause (clauses, OMP_CLAUSE_NOWAIT);
12736 if (c)
12737 flags_i |= GOMP_TARGET_FLAG_NOWAIT;
12738
acf0174b
JJ
12739 /* Ensure 'device' is of the correct type. */
12740 device = fold_convert_loc (clause_loc, integer_type_node, device);
12741
12742 /* If we found the clause 'if (cond)', build
41dbbb37 12743 (cond ? device : GOMP_DEVICE_HOST_FALLBACK). */
acf0174b
JJ
12744 if (cond)
12745 {
12746 cond = gimple_boolify (cond);
12747
12748 basic_block cond_bb, then_bb, else_bb;
12749 edge e;
12750 tree tmp_var;
12751
b731b390 12752 tmp_var = create_tmp_var (TREE_TYPE (device));
41dbbb37 12753 if (offloaded)
c4d281b2 12754 e = split_block_after_labels (new_bb);
41dbbb37 12755 else
acf0174b
JJ
12756 {
12757 gsi = gsi_last_bb (new_bb);
12758 gsi_prev (&gsi);
12759 e = split_block (new_bb, gsi_stmt (gsi));
12760 }
acf0174b
JJ
12761 cond_bb = e->src;
12762 new_bb = e->dest;
12763 remove_edge (e);
12764
12765 then_bb = create_empty_bb (cond_bb);
12766 else_bb = create_empty_bb (then_bb);
12767 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
12768 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
12769
12770 stmt = gimple_build_cond_empty (cond);
12771 gsi = gsi_last_bb (cond_bb);
12772 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
12773
12774 gsi = gsi_start_bb (then_bb);
12775 stmt = gimple_build_assign (tmp_var, device);
12776 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
12777
12778 gsi = gsi_start_bb (else_bb);
12779 stmt = gimple_build_assign (tmp_var,
41dbbb37
TS
12780 build_int_cst (integer_type_node,
12781 GOMP_DEVICE_HOST_FALLBACK));
acf0174b
JJ
12782 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
12783
12784 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
12785 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
726338f4
RB
12786 add_bb_to_loop (then_bb, cond_bb->loop_father);
12787 add_bb_to_loop (else_bb, cond_bb->loop_father);
acf0174b
JJ
12788 make_edge (then_bb, new_bb, EDGE_FALLTHRU);
12789 make_edge (else_bb, new_bb, EDGE_FALLTHRU);
12790
12791 device = tmp_var;
12792 }
12793
12794 gsi = gsi_last_bb (new_bb);
12795 t = gimple_omp_target_data_arg (entry_stmt);
12796 if (t == NULL)
12797 {
12798 t1 = size_zero_node;
12799 t2 = build_zero_cst (ptr_type_node);
12800 t3 = t2;
12801 t4 = t2;
12802 }
12803 else
12804 {
12805 t1 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t, 1))));
12806 t1 = size_binop (PLUS_EXPR, t1, size_int (1));
12807 t2 = build_fold_addr_expr (TREE_VEC_ELT (t, 0));
12808 t3 = build_fold_addr_expr (TREE_VEC_ELT (t, 1));
12809 t4 = build_fold_addr_expr (TREE_VEC_ELT (t, 2));
12810 }
12811
355fe088 12812 gimple *g;
3e32ee19 12813 bool tagging = false;
41dbbb37 12814 /* The maximum number used by any start_ix, without varargs. */
9410d9b2
JJ
12815 auto_vec<tree, 11> args;
12816 args.quick_push (device);
41dbbb37 12817 if (offloaded)
9410d9b2 12818 args.quick_push (build_fold_addr_expr (child_fn));
9410d9b2
JJ
12819 args.quick_push (t1);
12820 args.quick_push (t2);
12821 args.quick_push (t3);
12822 args.quick_push (t4);
41dbbb37
TS
12823 switch (start_ix)
12824 {
12825 case BUILT_IN_GOACC_DATA_START:
6e232ba4 12826 case BUILT_IN_GOACC_DECLARE:
41dbbb37 12827 case BUILT_IN_GOMP_TARGET_DATA:
d9a6bd32
JJ
12828 break;
12829 case BUILT_IN_GOMP_TARGET:
41dbbb37 12830 case BUILT_IN_GOMP_TARGET_UPDATE:
d9a6bd32
JJ
12831 case BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA:
12832 args.quick_push (build_int_cst (unsigned_type_node, flags_i));
12833 c = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
12834 if (c)
12835 depend = OMP_CLAUSE_DECL (c);
12836 else
12837 depend = build_int_cst (ptr_type_node, 0);
12838 args.quick_push (depend);
e01d41e5
JJ
12839 if (start_ix == BUILT_IN_GOMP_TARGET)
12840 {
12841 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_TEAMS);
12842 if (c)
12843 {
12844 t = fold_convert (integer_type_node,
12845 OMP_CLAUSE_NUM_TEAMS_EXPR (c));
12846 t = force_gimple_operand_gsi (&gsi, t, true, NULL,
12847 true, GSI_SAME_STMT);
12848 }
12849 else
12850 t = integer_minus_one_node;
12851 args.quick_push (t);
12852 c = find_omp_clause (clauses, OMP_CLAUSE_THREAD_LIMIT);
12853 if (c)
12854 {
12855 t = fold_convert (integer_type_node,
12856 OMP_CLAUSE_THREAD_LIMIT_EXPR (c));
12857 t = force_gimple_operand_gsi (&gsi, t, true, NULL,
12858 true, GSI_SAME_STMT);
12859 }
12860 else
12861 t = integer_minus_one_node;
12862 args.quick_push (t);
12863 }
41dbbb37
TS
12864 break;
12865 case BUILT_IN_GOACC_PARALLEL:
12866 {
3e32ee19
NS
12867 set_oacc_fn_attrib (child_fn, clauses, &args);
12868 tagging = true;
41dbbb37
TS
12869 }
12870 /* FALLTHRU */
12871 case BUILT_IN_GOACC_ENTER_EXIT_DATA:
12872 case BUILT_IN_GOACC_UPDATE:
12873 {
3e32ee19
NS
12874 tree t_async = NULL_TREE;
12875
12876 /* If present, use the value specified by the respective
41dbbb37
TS
12877 clause, making sure that is of the correct type. */
12878 c = find_omp_clause (clauses, OMP_CLAUSE_ASYNC);
12879 if (c)
12880 t_async = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
12881 integer_type_node,
12882 OMP_CLAUSE_ASYNC_EXPR (c));
3e32ee19
NS
12883 else if (!tagging)
12884 /* Default values for t_async. */
12885 t_async = fold_convert_loc (gimple_location (entry_stmt),
12886 integer_type_node,
12887 build_int_cst (integer_type_node,
12888 GOMP_ASYNC_SYNC));
12889 if (tagging && t_async)
41dbbb37 12890 {
3e32ee19 12891 unsigned HOST_WIDE_INT i_async;
41dbbb37 12892
3e32ee19 12893 if (TREE_CODE (t_async) == INTEGER_CST)
41dbbb37 12894 {
3e32ee19
NS
12895 /* See if we can pack the async arg in to the tag's
12896 operand. */
12897 i_async = TREE_INT_CST_LOW (t_async);
12898
12899 if (i_async < GOMP_LAUNCH_OP_MAX)
12900 t_async = NULL_TREE;
41dbbb37 12901 }
3e32ee19
NS
12902 if (t_async)
12903 i_async = GOMP_LAUNCH_OP_MAX;
12904 args.safe_push (oacc_launch_pack
12905 (GOMP_LAUNCH_ASYNC, NULL_TREE, i_async));
12906 }
12907 if (t_async)
12908 args.safe_push (t_async);
41dbbb37 12909
3e32ee19
NS
12910 /* Save the argument index, and ... */
12911 unsigned t_wait_idx = args.length ();
12912 unsigned num_waits = 0;
12913 c = find_omp_clause (clauses, OMP_CLAUSE_WAIT);
12914 if (!tagging || c)
12915 /* ... push a placeholder. */
12916 args.safe_push (integer_zero_node);
12917
12918 for (; c; c = OMP_CLAUSE_CHAIN (c))
12919 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_WAIT)
12920 {
12921 args.safe_push (fold_convert_loc (OMP_CLAUSE_LOCATION (c),
12922 integer_type_node,
12923 OMP_CLAUSE_WAIT_EXPR (c)));
12924 num_waits++;
12925 }
12926
12927 if (!tagging || num_waits)
12928 {
12929 tree len;
12930
12931 /* Now that we know the number, update the placeholder. */
12932 if (tagging)
12933 len = oacc_launch_pack (GOMP_LAUNCH_WAIT, NULL_TREE, num_waits);
12934 else
12935 len = build_int_cst (integer_type_node, num_waits);
12936 len = fold_convert_loc (gimple_location (entry_stmt),
12937 unsigned_type_node, len);
12938 args[t_wait_idx] = len;
41dbbb37
TS
12939 }
12940 }
12941 break;
12942 default:
12943 gcc_unreachable ();
acf0174b 12944 }
3e32ee19
NS
12945 if (tagging)
12946 /* Push terminal marker - zero. */
12947 args.safe_push (oacc_launch_pack (0, NULL_TREE, 0));
41dbbb37 12948
9410d9b2 12949 g = gimple_build_call_vec (builtin_decl_explicit (start_ix), args);
acf0174b
JJ
12950 gimple_set_location (g, gimple_location (entry_stmt));
12951 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
41dbbb37 12952 if (!offloaded)
acf0174b
JJ
12953 {
12954 g = gsi_stmt (gsi);
12955 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_TARGET);
12956 gsi_remove (&gsi, true);
12957 }
d9a6bd32 12958 if (data_region && region->exit)
acf0174b
JJ
12959 {
12960 gsi = gsi_last_bb (region->exit);
12961 g = gsi_stmt (gsi);
12962 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_RETURN);
12963 gsi_remove (&gsi, true);
12964 }
12965}
12966
12967
12968/* Expand the parallel region tree rooted at REGION. Expansion
12969 proceeds in depth-first order. Innermost regions are expanded
12970 first. This way, parallel regions that require a new function to
726a989a 12971 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
50674e96
DN
12972 internal dependencies in their body. */
12973
12974static void
12975expand_omp (struct omp_region *region)
12976{
e01d41e5 12977 omp_any_child_fn_dumped = false;
50674e96
DN
12978 while (region)
12979 {
b357f682 12980 location_t saved_location;
355fe088 12981 gimple *inner_stmt = NULL;
b357f682 12982
068e1875
ZD
12983 /* First, determine whether this is a combined parallel+workshare
12984 region. */
726a989a 12985 if (region->type == GIMPLE_OMP_PARALLEL)
068e1875
ZD
12986 determine_parallel_type (region);
12987
acf0174b
JJ
12988 if (region->type == GIMPLE_OMP_FOR
12989 && gimple_omp_for_combined_p (last_stmt (region->entry)))
12990 inner_stmt = last_stmt (region->inner->entry);
12991
50674e96
DN
12992 if (region->inner)
12993 expand_omp (region->inner);
12994
b357f682 12995 saved_location = input_location;
726a989a
RB
12996 if (gimple_has_location (last_stmt (region->entry)))
12997 input_location = gimple_location (last_stmt (region->entry));
b357f682 12998
777f7f9a 12999 switch (region->type)
50674e96 13000 {
726a989a
RB
13001 case GIMPLE_OMP_PARALLEL:
13002 case GIMPLE_OMP_TASK:
a68ab351
JJ
13003 expand_omp_taskreg (region);
13004 break;
13005
726a989a 13006 case GIMPLE_OMP_FOR:
acf0174b 13007 expand_omp_for (region, inner_stmt);
777f7f9a 13008 break;
50674e96 13009
726a989a 13010 case GIMPLE_OMP_SECTIONS:
777f7f9a
RH
13011 expand_omp_sections (region);
13012 break;
50674e96 13013
726a989a 13014 case GIMPLE_OMP_SECTION:
777f7f9a 13015 /* Individual omp sections are handled together with their
726a989a 13016 parent GIMPLE_OMP_SECTIONS region. */
777f7f9a 13017 break;
50674e96 13018
726a989a 13019 case GIMPLE_OMP_SINGLE:
777f7f9a
RH
13020 expand_omp_single (region);
13021 break;
50674e96 13022
d9a6bd32
JJ
13023 case GIMPLE_OMP_ORDERED:
13024 {
13025 gomp_ordered *ord_stmt
13026 = as_a <gomp_ordered *> (last_stmt (region->entry));
13027 if (find_omp_clause (gimple_omp_ordered_clauses (ord_stmt),
13028 OMP_CLAUSE_DEPEND))
13029 {
13030 /* We'll expand these when expanding corresponding
13031 worksharing region with ordered(n) clause. */
13032 gcc_assert (region->outer
13033 && region->outer->type == GIMPLE_OMP_FOR);
13034 region->ord_stmt = ord_stmt;
13035 break;
13036 }
13037 }
13038 /* FALLTHRU */
726a989a 13039 case GIMPLE_OMP_MASTER:
acf0174b 13040 case GIMPLE_OMP_TASKGROUP:
726a989a 13041 case GIMPLE_OMP_CRITICAL:
acf0174b 13042 case GIMPLE_OMP_TEAMS:
777f7f9a
RH
13043 expand_omp_synch (region);
13044 break;
50674e96 13045
726a989a 13046 case GIMPLE_OMP_ATOMIC_LOAD:
a509ebb5
RL
13047 expand_omp_atomic (region);
13048 break;
13049
acf0174b
JJ
13050 case GIMPLE_OMP_TARGET:
13051 expand_omp_target (region);
13052 break;
13053
777f7f9a
RH
13054 default:
13055 gcc_unreachable ();
13056 }
8d9c1aec 13057
b357f682 13058 input_location = saved_location;
50674e96
DN
13059 region = region->next;
13060 }
e01d41e5
JJ
13061 if (omp_any_child_fn_dumped)
13062 {
13063 if (dump_file)
13064 dump_function_header (dump_file, current_function_decl, dump_flags);
13065 omp_any_child_fn_dumped = false;
13066 }
50674e96
DN
13067}
13068
13069
13070/* Helper for build_omp_regions. Scan the dominator tree starting at
5f40b3cb
ZD
13071 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
13072 true, the function ends once a single tree is built (otherwise, whole
13073 forest of OMP constructs may be built). */
50674e96
DN
13074
13075static void
5f40b3cb
ZD
13076build_omp_regions_1 (basic_block bb, struct omp_region *parent,
13077 bool single_tree)
50674e96 13078{
726a989a 13079 gimple_stmt_iterator gsi;
355fe088 13080 gimple *stmt;
50674e96
DN
13081 basic_block son;
13082
726a989a
RB
13083 gsi = gsi_last_bb (bb);
13084 if (!gsi_end_p (gsi) && is_gimple_omp (gsi_stmt (gsi)))
50674e96
DN
13085 {
13086 struct omp_region *region;
726a989a 13087 enum gimple_code code;
50674e96 13088
726a989a
RB
13089 stmt = gsi_stmt (gsi);
13090 code = gimple_code (stmt);
13091 if (code == GIMPLE_OMP_RETURN)
50674e96
DN
13092 {
13093 /* STMT is the return point out of region PARENT. Mark it
13094 as the exit point and make PARENT the immediately
13095 enclosing region. */
13096 gcc_assert (parent);
13097 region = parent;
777f7f9a 13098 region->exit = bb;
50674e96 13099 parent = parent->outer;
50674e96 13100 }
726a989a 13101 else if (code == GIMPLE_OMP_ATOMIC_STORE)
a509ebb5 13102 {
726a989a
RB
13103 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
13104 GIMPLE_OMP_RETURN, but matches with
13105 GIMPLE_OMP_ATOMIC_LOAD. */
a509ebb5 13106 gcc_assert (parent);
726a989a 13107 gcc_assert (parent->type == GIMPLE_OMP_ATOMIC_LOAD);
a509ebb5
RL
13108 region = parent;
13109 region->exit = bb;
13110 parent = parent->outer;
13111 }
726a989a 13112 else if (code == GIMPLE_OMP_CONTINUE)
777f7f9a
RH
13113 {
13114 gcc_assert (parent);
13115 parent->cont = bb;
13116 }
726a989a 13117 else if (code == GIMPLE_OMP_SECTIONS_SWITCH)
e5c95afe 13118 {
726a989a
RB
13119 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
13120 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
e5c95afe 13121 }
50674e96
DN
13122 else
13123 {
777f7f9a 13124 region = new_omp_region (bb, code, parent);
41dbbb37
TS
13125 /* Otherwise... */
13126 if (code == GIMPLE_OMP_TARGET)
13127 {
13128 switch (gimple_omp_target_kind (stmt))
13129 {
13130 case GF_OMP_TARGET_KIND_REGION:
13131 case GF_OMP_TARGET_KIND_DATA:
13132 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
13133 case GF_OMP_TARGET_KIND_OACC_KERNELS:
13134 case GF_OMP_TARGET_KIND_OACC_DATA:
13135 break;
13136 case GF_OMP_TARGET_KIND_UPDATE:
d9a6bd32
JJ
13137 case GF_OMP_TARGET_KIND_ENTER_DATA:
13138 case GF_OMP_TARGET_KIND_EXIT_DATA:
41dbbb37
TS
13139 case GF_OMP_TARGET_KIND_OACC_UPDATE:
13140 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
6e232ba4 13141 case GF_OMP_TARGET_KIND_OACC_DECLARE:
41dbbb37
TS
13142 /* ..., other than for those stand-alone directives... */
13143 region = NULL;
13144 break;
13145 default:
13146 gcc_unreachable ();
13147 }
13148 }
d9a6bd32
JJ
13149 else if (code == GIMPLE_OMP_ORDERED
13150 && find_omp_clause (gimple_omp_ordered_clauses
13151 (as_a <gomp_ordered *> (stmt)),
13152 OMP_CLAUSE_DEPEND))
13153 /* #pragma omp ordered depend is also just a stand-alone
13154 directive. */
13155 region = NULL;
41dbbb37
TS
13156 /* ..., this directive becomes the parent for a new region. */
13157 if (region)
13158 parent = region;
50674e96 13159 }
50674e96
DN
13160 }
13161
5f40b3cb
ZD
13162 if (single_tree && !parent)
13163 return;
13164
50674e96
DN
13165 for (son = first_dom_son (CDI_DOMINATORS, bb);
13166 son;
13167 son = next_dom_son (CDI_DOMINATORS, son))
5f40b3cb
ZD
13168 build_omp_regions_1 (son, parent, single_tree);
13169}
13170
13171/* Builds the tree of OMP regions rooted at ROOT, storing it to
13172 root_omp_region. */
13173
13174static void
13175build_omp_regions_root (basic_block root)
13176{
13177 gcc_assert (root_omp_region == NULL);
13178 build_omp_regions_1 (root, NULL, true);
13179 gcc_assert (root_omp_region != NULL);
50674e96
DN
13180}
13181
5f40b3cb
ZD
13182/* Expands omp construct (and its subconstructs) starting in HEAD. */
13183
13184void
13185omp_expand_local (basic_block head)
13186{
13187 build_omp_regions_root (head);
13188 if (dump_file && (dump_flags & TDF_DETAILS))
13189 {
13190 fprintf (dump_file, "\nOMP region tree\n\n");
13191 dump_omp_region (dump_file, root_omp_region, 0);
13192 fprintf (dump_file, "\n");
13193 }
13194
13195 remove_exit_barriers (root_omp_region);
13196 expand_omp (root_omp_region);
13197
13198 free_omp_regions ();
13199}
50674e96
DN
13200
13201/* Scan the CFG and build a tree of OMP regions. Return the root of
13202 the OMP region tree. */
13203
13204static void
13205build_omp_regions (void)
13206{
777f7f9a 13207 gcc_assert (root_omp_region == NULL);
50674e96 13208 calculate_dominance_info (CDI_DOMINATORS);
fefa31b5 13209 build_omp_regions_1 (ENTRY_BLOCK_PTR_FOR_FN (cfun), NULL, false);
50674e96
DN
13210}
13211
50674e96
DN
13212/* Main entry point for expanding OMP-GIMPLE into runtime calls. */
13213
c2924966 13214static unsigned int
50674e96
DN
13215execute_expand_omp (void)
13216{
13217 build_omp_regions ();
13218
777f7f9a
RH
13219 if (!root_omp_region)
13220 return 0;
50674e96 13221
777f7f9a
RH
13222 if (dump_file)
13223 {
13224 fprintf (dump_file, "\nOMP region tree\n\n");
13225 dump_omp_region (dump_file, root_omp_region, 0);
13226 fprintf (dump_file, "\n");
50674e96 13227 }
777f7f9a
RH
13228
13229 remove_exit_barriers (root_omp_region);
13230
13231 expand_omp (root_omp_region);
13232
b2b29377 13233 if (flag_checking && !loops_state_satisfies_p (LOOPS_NEED_FIXUP))
e67d7a1e 13234 verify_loop_structure ();
777f7f9a
RH
13235 cleanup_tree_cfg ();
13236
13237 free_omp_regions ();
13238
c2924966 13239 return 0;
50674e96
DN
13240}
13241
917948d3
ZD
13242/* OMP expansion -- the default pass, run before creation of SSA form. */
13243
17795822
TS
13244namespace {
13245
13246const pass_data pass_data_expand_omp =
27a4cd48
DM
13247{
13248 GIMPLE_PASS, /* type */
13249 "ompexp", /* name */
13250 OPTGROUP_NONE, /* optinfo_flags */
27a4cd48
DM
13251 TV_NONE, /* tv_id */
13252 PROP_gimple_any, /* properties_required */
18751894 13253 PROP_gimple_eomp, /* properties_provided */
27a4cd48
DM
13254 0, /* properties_destroyed */
13255 0, /* todo_flags_start */
13256 0, /* todo_flags_finish */
50674e96 13257};
27a4cd48 13258
17795822 13259class pass_expand_omp : public gimple_opt_pass
27a4cd48
DM
13260{
13261public:
c3284718
RS
13262 pass_expand_omp (gcc::context *ctxt)
13263 : gimple_opt_pass (pass_data_expand_omp, ctxt)
27a4cd48
DM
13264 {}
13265
13266 /* opt_pass methods: */
18751894 13267 virtual unsigned int execute (function *)
1a3d085c 13268 {
41dbbb37
TS
13269 bool gate = ((flag_cilkplus != 0 || flag_openacc != 0 || flag_openmp != 0
13270 || flag_openmp_simd != 0)
13271 && !seen_error ());
1a3d085c 13272
18751894 13273 /* This pass always runs, to provide PROP_gimple_eomp.
41dbbb37 13274 But often, there is nothing to do. */
18751894
TV
13275 if (!gate)
13276 return 0;
13277
13278 return execute_expand_omp ();
13279 }
27a4cd48
DM
13280
13281}; // class pass_expand_omp
13282
17795822
TS
13283} // anon namespace
13284
27a4cd48
DM
13285gimple_opt_pass *
13286make_pass_expand_omp (gcc::context *ctxt)
13287{
13288 return new pass_expand_omp (ctxt);
13289}
18751894 13290
17795822
TS
13291namespace {
13292
13293const pass_data pass_data_expand_omp_ssa =
18751894
TV
13294{
13295 GIMPLE_PASS, /* type */
13296 "ompexpssa", /* name */
13297 OPTGROUP_NONE, /* optinfo_flags */
13298 TV_NONE, /* tv_id */
13299 PROP_cfg | PROP_ssa, /* properties_required */
13300 PROP_gimple_eomp, /* properties_provided */
13301 0, /* properties_destroyed */
13302 0, /* todo_flags_start */
13303 TODO_cleanup_cfg | TODO_rebuild_alias, /* todo_flags_finish */
13304};
13305
17795822 13306class pass_expand_omp_ssa : public gimple_opt_pass
18751894
TV
13307{
13308public:
13309 pass_expand_omp_ssa (gcc::context *ctxt)
13310 : gimple_opt_pass (pass_data_expand_omp_ssa, ctxt)
13311 {}
13312
13313 /* opt_pass methods: */
13314 virtual bool gate (function *fun)
13315 {
13316 return !(fun->curr_properties & PROP_gimple_eomp);
13317 }
13318 virtual unsigned int execute (function *) { return execute_expand_omp (); }
13319
13320}; // class pass_expand_omp_ssa
13321
17795822
TS
13322} // anon namespace
13323
18751894
TV
13324gimple_opt_pass *
13325make_pass_expand_omp_ssa (gcc::context *ctxt)
13326{
13327 return new pass_expand_omp_ssa (ctxt);
13328}
50674e96 13329\f
41dbbb37
TS
13330/* Routines to lower OMP directives into OMP-GIMPLE. */
13331
acf0174b
JJ
13332/* If ctx is a worksharing context inside of a cancellable parallel
13333 region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
13334 and conditional branch to parallel's cancel_label to handle
13335 cancellation in the implicit barrier. */
13336
13337static void
13338maybe_add_implicit_barrier_cancel (omp_context *ctx, gimple_seq *body)
13339{
355fe088 13340 gimple *omp_return = gimple_seq_last_stmt (*body);
acf0174b
JJ
13341 gcc_assert (gimple_code (omp_return) == GIMPLE_OMP_RETURN);
13342 if (gimple_omp_return_nowait_p (omp_return))
13343 return;
13344 if (ctx->outer
13345 && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_PARALLEL
13346 && ctx->outer->cancellable)
13347 {
dd2fc525
JJ
13348 tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL);
13349 tree c_bool_type = TREE_TYPE (TREE_TYPE (fndecl));
b731b390 13350 tree lhs = create_tmp_var (c_bool_type);
acf0174b
JJ
13351 gimple_omp_return_set_lhs (omp_return, lhs);
13352 tree fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
355fe088 13353 gimple *g = gimple_build_cond (NE_EXPR, lhs,
dd2fc525
JJ
13354 fold_convert (c_bool_type,
13355 boolean_false_node),
acf0174b
JJ
13356 ctx->outer->cancel_label, fallthru_label);
13357 gimple_seq_add_stmt (body, g);
13358 gimple_seq_add_stmt (body, gimple_build_label (fallthru_label));
13359 }
13360}
13361
726a989a
RB
13362/* Lower the OpenMP sections directive in the current statement in GSI_P.
13363 CTX is the enclosing OMP context for the current statement. */
50674e96
DN
13364
13365static void
726a989a 13366lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
50674e96 13367{
726a989a
RB
13368 tree block, control;
13369 gimple_stmt_iterator tgsi;
538dd0b7 13370 gomp_sections *stmt;
355fe088 13371 gimple *t;
538dd0b7 13372 gbind *new_stmt, *bind;
355a7673 13373 gimple_seq ilist, dlist, olist, new_body;
50674e96 13374
538dd0b7 13375 stmt = as_a <gomp_sections *> (gsi_stmt (*gsi_p));
50674e96 13376
45852dcc 13377 push_gimplify_context ();
50674e96
DN
13378
13379 dlist = NULL;
13380 ilist = NULL;
726a989a 13381 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
acf0174b 13382 &ilist, &dlist, ctx, NULL);
50674e96 13383
355a7673
MM
13384 new_body = gimple_omp_body (stmt);
13385 gimple_omp_set_body (stmt, NULL);
13386 tgsi = gsi_start (new_body);
13387 for (; !gsi_end_p (tgsi); gsi_next (&tgsi))
50674e96
DN
13388 {
13389 omp_context *sctx;
355fe088 13390 gimple *sec_start;
50674e96 13391
726a989a 13392 sec_start = gsi_stmt (tgsi);
50674e96
DN
13393 sctx = maybe_lookup_ctx (sec_start);
13394 gcc_assert (sctx);
13395
355a7673
MM
13396 lower_omp (gimple_omp_body_ptr (sec_start), sctx);
13397 gsi_insert_seq_after (&tgsi, gimple_omp_body (sec_start),
13398 GSI_CONTINUE_LINKING);
726a989a 13399 gimple_omp_set_body (sec_start, NULL);
50674e96 13400
355a7673 13401 if (gsi_one_before_end_p (tgsi))
50674e96 13402 {
726a989a
RB
13403 gimple_seq l = NULL;
13404 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
50674e96 13405 &l, ctx);
355a7673 13406 gsi_insert_seq_after (&tgsi, l, GSI_CONTINUE_LINKING);
726a989a 13407 gimple_omp_section_set_last (sec_start);
50674e96 13408 }
b8698a0f 13409
355a7673
MM
13410 gsi_insert_after (&tgsi, gimple_build_omp_return (false),
13411 GSI_CONTINUE_LINKING);
50674e96 13412 }
953ff289
DN
13413
13414 block = make_node (BLOCK);
355a7673 13415 bind = gimple_build_bind (NULL, new_body, block);
953ff289 13416
726a989a
RB
13417 olist = NULL;
13418 lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist, ctx);
50674e96 13419
b357f682 13420 block = make_node (BLOCK);
726a989a 13421 new_stmt = gimple_build_bind (NULL, NULL, block);
355a7673 13422 gsi_replace (gsi_p, new_stmt, true);
50674e96 13423
b357f682 13424 pop_gimplify_context (new_stmt);
726a989a
RB
13425 gimple_bind_append_vars (new_stmt, ctx->block_vars);
13426 BLOCK_VARS (block) = gimple_bind_vars (bind);
b357f682
JJ
13427 if (BLOCK_VARS (block))
13428 TREE_USED (block) = 1;
13429
726a989a
RB
13430 new_body = NULL;
13431 gimple_seq_add_seq (&new_body, ilist);
13432 gimple_seq_add_stmt (&new_body, stmt);
13433 gimple_seq_add_stmt (&new_body, gimple_build_omp_sections_switch ());
13434 gimple_seq_add_stmt (&new_body, bind);
777f7f9a 13435
e5c95afe 13436 control = create_tmp_var (unsigned_type_node, ".section");
726a989a
RB
13437 t = gimple_build_omp_continue (control, control);
13438 gimple_omp_sections_set_control (stmt, control);
13439 gimple_seq_add_stmt (&new_body, t);
777f7f9a 13440
726a989a 13441 gimple_seq_add_seq (&new_body, olist);
acf0174b
JJ
13442 if (ctx->cancellable)
13443 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
726a989a 13444 gimple_seq_add_seq (&new_body, dlist);
50674e96 13445
726a989a 13446 new_body = maybe_catch_exception (new_body);
4a31b7ee 13447
726a989a
RB
13448 t = gimple_build_omp_return
13449 (!!find_omp_clause (gimple_omp_sections_clauses (stmt),
13450 OMP_CLAUSE_NOWAIT));
13451 gimple_seq_add_stmt (&new_body, t);
acf0174b 13452 maybe_add_implicit_barrier_cancel (ctx, &new_body);
777f7f9a 13453
726a989a 13454 gimple_bind_set_body (new_stmt, new_body);
953ff289
DN
13455}
13456
13457
50674e96 13458/* A subroutine of lower_omp_single. Expand the simple form of
726a989a 13459 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
953ff289
DN
13460
13461 if (GOMP_single_start ())
13462 BODY;
13463 [ GOMP_barrier (); ] -> unless 'nowait' is present.
50674e96
DN
13464
13465 FIXME. It may be better to delay expanding the logic of this until
13466 pass_expand_omp. The expanded logic may make the job more difficult
13467 to a synchronization analysis pass. */
953ff289
DN
13468
13469static void
538dd0b7 13470lower_omp_single_simple (gomp_single *single_stmt, gimple_seq *pre_p)
953ff289 13471{
c2255bc4
AH
13472 location_t loc = gimple_location (single_stmt);
13473 tree tlabel = create_artificial_label (loc);
13474 tree flabel = create_artificial_label (loc);
355fe088 13475 gimple *call, *cond;
726a989a
RB
13476 tree lhs, decl;
13477
e79983f4 13478 decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START);
b731b390 13479 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)));
726a989a
RB
13480 call = gimple_build_call (decl, 0);
13481 gimple_call_set_lhs (call, lhs);
13482 gimple_seq_add_stmt (pre_p, call);
13483
13484 cond = gimple_build_cond (EQ_EXPR, lhs,
db3927fb
AH
13485 fold_convert_loc (loc, TREE_TYPE (lhs),
13486 boolean_true_node),
726a989a
RB
13487 tlabel, flabel);
13488 gimple_seq_add_stmt (pre_p, cond);
13489 gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
13490 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
13491 gimple_seq_add_stmt (pre_p, gimple_build_label (flabel));
953ff289
DN
13492}
13493
50674e96
DN
13494
13495/* A subroutine of lower_omp_single. Expand the simple form of
726a989a 13496 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
953ff289
DN
13497
13498 #pragma omp single copyprivate (a, b, c)
13499
13500 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
13501
13502 {
13503 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
13504 {
13505 BODY;
13506 copyout.a = a;
13507 copyout.b = b;
13508 copyout.c = c;
13509 GOMP_single_copy_end (&copyout);
13510 }
13511 else
13512 {
13513 a = copyout_p->a;
13514 b = copyout_p->b;
13515 c = copyout_p->c;
13516 }
13517 GOMP_barrier ();
13518 }
50674e96
DN
13519
13520 FIXME. It may be better to delay expanding the logic of this until
13521 pass_expand_omp. The expanded logic may make the job more difficult
13522 to a synchronization analysis pass. */
953ff289
DN
13523
13524static void
538dd0b7
DM
13525lower_omp_single_copy (gomp_single *single_stmt, gimple_seq *pre_p,
13526 omp_context *ctx)
953ff289 13527{
e79983f4 13528 tree ptr_type, t, l0, l1, l2, bfn_decl;
726a989a 13529 gimple_seq copyin_seq;
c2255bc4 13530 location_t loc = gimple_location (single_stmt);
953ff289
DN
13531
13532 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
13533
13534 ptr_type = build_pointer_type (ctx->record_type);
13535 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
13536
c2255bc4
AH
13537 l0 = create_artificial_label (loc);
13538 l1 = create_artificial_label (loc);
13539 l2 = create_artificial_label (loc);
953ff289 13540
e79983f4
MM
13541 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START);
13542 t = build_call_expr_loc (loc, bfn_decl, 0);
db3927fb 13543 t = fold_convert_loc (loc, ptr_type, t);
726a989a 13544 gimplify_assign (ctx->receiver_decl, t, pre_p);
953ff289
DN
13545
13546 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
13547 build_int_cst (ptr_type, 0));
13548 t = build3 (COND_EXPR, void_type_node, t,
13549 build_and_jump (&l0), build_and_jump (&l1));
13550 gimplify_and_add (t, pre_p);
13551
726a989a 13552 gimple_seq_add_stmt (pre_p, gimple_build_label (l0));
953ff289 13553
726a989a 13554 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
953ff289
DN
13555
13556 copyin_seq = NULL;
726a989a 13557 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
953ff289
DN
13558 &copyin_seq, ctx);
13559
db3927fb 13560 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
e79983f4
MM
13561 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END);
13562 t = build_call_expr_loc (loc, bfn_decl, 1, t);
953ff289
DN
13563 gimplify_and_add (t, pre_p);
13564
13565 t = build_and_jump (&l2);
13566 gimplify_and_add (t, pre_p);
13567
726a989a 13568 gimple_seq_add_stmt (pre_p, gimple_build_label (l1));
953ff289 13569
726a989a 13570 gimple_seq_add_seq (pre_p, copyin_seq);
953ff289 13571
726a989a 13572 gimple_seq_add_stmt (pre_p, gimple_build_label (l2));
953ff289
DN
13573}
13574
50674e96 13575
953ff289
DN
13576/* Expand code for an OpenMP single directive. */
13577
13578static void
726a989a 13579lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
953ff289 13580{
726a989a 13581 tree block;
355fe088 13582 gimple *t;
538dd0b7
DM
13583 gomp_single *single_stmt = as_a <gomp_single *> (gsi_stmt (*gsi_p));
13584 gbind *bind;
acf0174b 13585 gimple_seq bind_body, bind_body_tail = NULL, dlist;
953ff289 13586
45852dcc 13587 push_gimplify_context ();
953ff289 13588
355a7673
MM
13589 block = make_node (BLOCK);
13590 bind = gimple_build_bind (NULL, NULL, block);
13591 gsi_replace (gsi_p, bind, true);
726a989a 13592 bind_body = NULL;
355a7673 13593 dlist = NULL;
726a989a 13594 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt),
acf0174b 13595 &bind_body, &dlist, ctx, NULL);
355a7673 13596 lower_omp (gimple_omp_body_ptr (single_stmt), ctx);
953ff289 13597
726a989a 13598 gimple_seq_add_stmt (&bind_body, single_stmt);
953ff289
DN
13599
13600 if (ctx->record_type)
726a989a 13601 lower_omp_single_copy (single_stmt, &bind_body, ctx);
953ff289 13602 else
726a989a
RB
13603 lower_omp_single_simple (single_stmt, &bind_body);
13604
13605 gimple_omp_set_body (single_stmt, NULL);
953ff289 13606
726a989a 13607 gimple_seq_add_seq (&bind_body, dlist);
777f7f9a 13608
726a989a 13609 bind_body = maybe_catch_exception (bind_body);
777f7f9a 13610
b8698a0f 13611 t = gimple_build_omp_return
726a989a
RB
13612 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt),
13613 OMP_CLAUSE_NOWAIT));
acf0174b
JJ
13614 gimple_seq_add_stmt (&bind_body_tail, t);
13615 maybe_add_implicit_barrier_cancel (ctx, &bind_body_tail);
13616 if (ctx->record_type)
13617 {
13618 gimple_stmt_iterator gsi = gsi_start (bind_body_tail);
13619 tree clobber = build_constructor (ctx->record_type, NULL);
13620 TREE_THIS_VOLATILE (clobber) = 1;
13621 gsi_insert_after (&gsi, gimple_build_assign (ctx->sender_decl,
13622 clobber), GSI_SAME_STMT);
13623 }
13624 gimple_seq_add_seq (&bind_body, bind_body_tail);
355a7673 13625 gimple_bind_set_body (bind, bind_body);
777f7f9a 13626
953ff289 13627 pop_gimplify_context (bind);
50674e96 13628
726a989a
RB
13629 gimple_bind_append_vars (bind, ctx->block_vars);
13630 BLOCK_VARS (block) = ctx->block_vars;
b357f682
JJ
13631 if (BLOCK_VARS (block))
13632 TREE_USED (block) = 1;
953ff289
DN
13633}
13634
50674e96 13635
953ff289
DN
13636/* Expand code for an OpenMP master directive. */
13637
13638static void
726a989a 13639lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
953ff289 13640{
e79983f4 13641 tree block, lab = NULL, x, bfn_decl;
355fe088 13642 gimple *stmt = gsi_stmt (*gsi_p);
538dd0b7 13643 gbind *bind;
db3927fb 13644 location_t loc = gimple_location (stmt);
726a989a 13645 gimple_seq tseq;
953ff289 13646
45852dcc 13647 push_gimplify_context ();
953ff289
DN
13648
13649 block = make_node (BLOCK);
355a7673
MM
13650 bind = gimple_build_bind (NULL, NULL, block);
13651 gsi_replace (gsi_p, bind, true);
13652 gimple_bind_add_stmt (bind, stmt);
777f7f9a 13653
e79983f4
MM
13654 bfn_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
13655 x = build_call_expr_loc (loc, bfn_decl, 0);
953ff289
DN
13656 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
13657 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
726a989a
RB
13658 tseq = NULL;
13659 gimplify_and_add (x, &tseq);
13660 gimple_bind_add_seq (bind, tseq);
953ff289 13661
355a7673 13662 lower_omp (gimple_omp_body_ptr (stmt), ctx);
726a989a
RB
13663 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
13664 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
13665 gimple_omp_set_body (stmt, NULL);
953ff289 13666
726a989a 13667 gimple_bind_add_stmt (bind, gimple_build_label (lab));
777f7f9a 13668
726a989a 13669 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
777f7f9a 13670
953ff289 13671 pop_gimplify_context (bind);
50674e96 13672
726a989a
RB
13673 gimple_bind_append_vars (bind, ctx->block_vars);
13674 BLOCK_VARS (block) = ctx->block_vars;
953ff289
DN
13675}
13676
50674e96 13677
acf0174b
JJ
13678/* Expand code for an OpenMP taskgroup directive. */
13679
13680static void
13681lower_omp_taskgroup (gimple_stmt_iterator *gsi_p, omp_context *ctx)
13682{
355fe088 13683 gimple *stmt = gsi_stmt (*gsi_p);
538dd0b7
DM
13684 gcall *x;
13685 gbind *bind;
acf0174b
JJ
13686 tree block = make_node (BLOCK);
13687
13688 bind = gimple_build_bind (NULL, NULL, block);
13689 gsi_replace (gsi_p, bind, true);
13690 gimple_bind_add_stmt (bind, stmt);
13691
13692 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START),
13693 0);
13694 gimple_bind_add_stmt (bind, x);
13695
13696 lower_omp (gimple_omp_body_ptr (stmt), ctx);
13697 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
13698 gimple_omp_set_body (stmt, NULL);
13699
13700 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
13701
13702 gimple_bind_append_vars (bind, ctx->block_vars);
13703 BLOCK_VARS (block) = ctx->block_vars;
13704}
13705
13706
d9a6bd32
JJ
13707/* Fold the OMP_ORDERED_CLAUSES for the OMP_ORDERED in STMT if possible. */
13708
13709static void
13710lower_omp_ordered_clauses (gimple_stmt_iterator *gsi_p, gomp_ordered *ord_stmt,
13711 omp_context *ctx)
13712{
13713 struct omp_for_data fd;
13714 if (!ctx->outer || gimple_code (ctx->outer->stmt) != GIMPLE_OMP_FOR)
13715 return;
13716
13717 unsigned int len = gimple_omp_for_collapse (ctx->outer->stmt);
13718 struct omp_for_data_loop *loops = XALLOCAVEC (struct omp_for_data_loop, len);
13719 extract_omp_for_data (as_a <gomp_for *> (ctx->outer->stmt), &fd, loops);
13720 if (!fd.ordered)
13721 return;
13722
13723 tree *list_p = gimple_omp_ordered_clauses_ptr (ord_stmt);
13724 tree c = gimple_omp_ordered_clauses (ord_stmt);
13725 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
13726 && OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK)
13727 {
13728 /* Merge depend clauses from multiple adjacent
13729 #pragma omp ordered depend(sink:...) constructs
13730 into one #pragma omp ordered depend(sink:...), so that
13731 we can optimize them together. */
13732 gimple_stmt_iterator gsi = *gsi_p;
13733 gsi_next (&gsi);
13734 while (!gsi_end_p (gsi))
13735 {
13736 gimple *stmt = gsi_stmt (gsi);
13737 if (is_gimple_debug (stmt)
13738 || gimple_code (stmt) == GIMPLE_NOP)
13739 {
13740 gsi_next (&gsi);
13741 continue;
13742 }
13743 if (gimple_code (stmt) != GIMPLE_OMP_ORDERED)
13744 break;
13745 gomp_ordered *ord_stmt2 = as_a <gomp_ordered *> (stmt);
13746 c = gimple_omp_ordered_clauses (ord_stmt2);
13747 if (c == NULL_TREE
13748 || OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND
13749 || OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_SINK)
13750 break;
13751 while (*list_p)
13752 list_p = &OMP_CLAUSE_CHAIN (*list_p);
13753 *list_p = c;
13754 gsi_remove (&gsi, true);
13755 }
13756 }
13757
13758 /* Canonicalize sink dependence clauses into one folded clause if
13759 possible.
13760
13761 The basic algorithm is to create a sink vector whose first
13762 element is the GCD of all the first elements, and whose remaining
13763 elements are the minimum of the subsequent columns.
13764
13765 We ignore dependence vectors whose first element is zero because
13766 such dependencies are known to be executed by the same thread.
13767
13768 We take into account the direction of the loop, so a minimum
13769 becomes a maximum if the loop is iterating forwards. We also
13770 ignore sink clauses where the loop direction is unknown, or where
13771 the offsets are clearly invalid because they are not a multiple
13772 of the loop increment.
13773
13774 For example:
13775
13776 #pragma omp for ordered(2)
13777 for (i=0; i < N; ++i)
13778 for (j=0; j < M; ++j)
13779 {
13780 #pragma omp ordered \
13781 depend(sink:i-8,j-2) \
13782 depend(sink:i,j-1) \ // Completely ignored because i+0.
13783 depend(sink:i-4,j-3) \
13784 depend(sink:i-6,j-4)
13785 #pragma omp ordered depend(source)
13786 }
13787
13788 Folded clause is:
13789
13790 depend(sink:-gcd(8,4,6),-min(2,3,4))
13791 -or-
13792 depend(sink:-2,-2)
13793 */
13794
13795 /* FIXME: Computing GCD's where the first element is zero is
13796 non-trivial in the presence of collapsed loops. Do this later. */
13797 if (fd.collapse > 1)
13798 return;
13799
13800 wide_int *folded_deps = XALLOCAVEC (wide_int, 2 * len - 1);
13801 memset (folded_deps, 0, sizeof (*folded_deps) * (2 * len - 1));
13802 tree folded_dep = NULL_TREE;
13803 /* TRUE if the first dimension's offset is negative. */
13804 bool neg_offset_p = false;
13805
13806 list_p = gimple_omp_ordered_clauses_ptr (ord_stmt);
13807 unsigned int i;
13808 while ((c = *list_p) != NULL)
13809 {
13810 bool remove = false;
13811
13812 gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND);
13813 if (OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_SINK)
13814 goto next_ordered_clause;
13815
13816 tree vec;
13817 for (vec = OMP_CLAUSE_DECL (c), i = 0;
13818 vec && TREE_CODE (vec) == TREE_LIST;
13819 vec = TREE_CHAIN (vec), ++i)
13820 {
13821 gcc_assert (i < len);
13822
13823 /* extract_omp_for_data has canonicalized the condition. */
13824 gcc_assert (fd.loops[i].cond_code == LT_EXPR
13825 || fd.loops[i].cond_code == GT_EXPR);
13826 bool forward = fd.loops[i].cond_code == LT_EXPR;
13827 bool maybe_lexically_later = true;
13828
13829 /* While the committee makes up its mind, bail if we have any
13830 non-constant steps. */
13831 if (TREE_CODE (fd.loops[i].step) != INTEGER_CST)
13832 goto lower_omp_ordered_ret;
13833
13834 tree itype = TREE_TYPE (TREE_VALUE (vec));
13835 if (POINTER_TYPE_P (itype))
13836 itype = sizetype;
13837 wide_int offset = wide_int::from (TREE_PURPOSE (vec),
13838 TYPE_PRECISION (itype),
13839 TYPE_SIGN (itype));
13840
13841 /* Ignore invalid offsets that are not multiples of the step. */
13842 if (!wi::multiple_of_p
13843 (wi::abs (offset), wi::abs ((wide_int) fd.loops[i].step),
13844 UNSIGNED))
13845 {
13846 warning_at (OMP_CLAUSE_LOCATION (c), 0,
13847 "ignoring sink clause with offset that is not "
13848 "a multiple of the loop step");
13849 remove = true;
13850 goto next_ordered_clause;
13851 }
13852
13853 /* Calculate the first dimension. The first dimension of
13854 the folded dependency vector is the GCD of the first
13855 elements, while ignoring any first elements whose offset
13856 is 0. */
13857 if (i == 0)
13858 {
13859 /* Ignore dependence vectors whose first dimension is 0. */
13860 if (offset == 0)
13861 {
13862 remove = true;
13863 goto next_ordered_clause;
13864 }
13865 else
13866 {
13867 if (!TYPE_UNSIGNED (itype) && (forward ^ wi::neg_p (offset)))
13868 {
13869 error_at (OMP_CLAUSE_LOCATION (c),
13870 "first offset must be in opposite direction "
13871 "of loop iterations");
13872 goto lower_omp_ordered_ret;
13873 }
13874 if (forward)
13875 offset = -offset;
13876 neg_offset_p = forward;
13877 /* Initialize the first time around. */
13878 if (folded_dep == NULL_TREE)
13879 {
13880 folded_dep = c;
13881 folded_deps[0] = offset;
13882 }
13883 else
13884 folded_deps[0] = wi::gcd (folded_deps[0],
13885 offset, UNSIGNED);
13886 }
13887 }
13888 /* Calculate minimum for the remaining dimensions. */
13889 else
13890 {
13891 folded_deps[len + i - 1] = offset;
13892 if (folded_dep == c)
13893 folded_deps[i] = offset;
13894 else if (maybe_lexically_later
13895 && !wi::eq_p (folded_deps[i], offset))
13896 {
13897 if (forward ^ wi::gts_p (folded_deps[i], offset))
13898 {
13899 unsigned int j;
13900 folded_dep = c;
13901 for (j = 1; j <= i; j++)
13902 folded_deps[j] = folded_deps[len + j - 1];
13903 }
13904 else
13905 maybe_lexically_later = false;
13906 }
13907 }
13908 }
13909 gcc_assert (i == len);
13910
13911 remove = true;
13912
13913 next_ordered_clause:
13914 if (remove)
13915 *list_p = OMP_CLAUSE_CHAIN (c);
13916 else
13917 list_p = &OMP_CLAUSE_CHAIN (c);
13918 }
13919
13920 if (folded_dep)
13921 {
13922 if (neg_offset_p)
13923 folded_deps[0] = -folded_deps[0];
13924
13925 tree itype = TREE_TYPE (TREE_VALUE (OMP_CLAUSE_DECL (folded_dep)));
13926 if (POINTER_TYPE_P (itype))
13927 itype = sizetype;
13928
13929 TREE_PURPOSE (OMP_CLAUSE_DECL (folded_dep))
13930 = wide_int_to_tree (itype, folded_deps[0]);
13931 OMP_CLAUSE_CHAIN (folded_dep) = gimple_omp_ordered_clauses (ord_stmt);
13932 *gimple_omp_ordered_clauses_ptr (ord_stmt) = folded_dep;
13933 }
13934
13935 lower_omp_ordered_ret:
13936
13937 /* Ordered without clauses is #pragma omp threads, while we want
13938 a nop instead if we remove all clauses. */
13939 if (gimple_omp_ordered_clauses (ord_stmt) == NULL_TREE)
13940 gsi_replace (gsi_p, gimple_build_nop (), true);
13941}
13942
13943
953ff289
DN
13944/* Expand code for an OpenMP ordered directive. */
13945
13946static void
726a989a 13947lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
953ff289 13948{
726a989a 13949 tree block;
355fe088 13950 gimple *stmt = gsi_stmt (*gsi_p);
d9a6bd32 13951 gomp_ordered *ord_stmt = as_a <gomp_ordered *> (stmt);
538dd0b7
DM
13952 gcall *x;
13953 gbind *bind;
e4606348
JJ
13954 bool simd = find_omp_clause (gimple_omp_ordered_clauses (ord_stmt),
13955 OMP_CLAUSE_SIMD);
13956 bool threads = find_omp_clause (gimple_omp_ordered_clauses (ord_stmt),
13957 OMP_CLAUSE_THREADS);
d9a6bd32
JJ
13958
13959 if (find_omp_clause (gimple_omp_ordered_clauses (ord_stmt),
13960 OMP_CLAUSE_DEPEND))
13961 {
13962 /* FIXME: This is needs to be moved to the expansion to verify various
13963 conditions only testable on cfg with dominators computed, and also
13964 all the depend clauses to be merged still might need to be available
13965 for the runtime checks. */
13966 if (0)
13967 lower_omp_ordered_clauses (gsi_p, ord_stmt, ctx);
13968 return;
13969 }
953ff289 13970
45852dcc 13971 push_gimplify_context ();
953ff289
DN
13972
13973 block = make_node (BLOCK);
355a7673
MM
13974 bind = gimple_build_bind (NULL, NULL, block);
13975 gsi_replace (gsi_p, bind, true);
13976 gimple_bind_add_stmt (bind, stmt);
777f7f9a 13977
d9a6bd32
JJ
13978 if (simd)
13979 {
e4606348
JJ
13980 x = gimple_build_call_internal (IFN_GOMP_SIMD_ORDERED_START, 1,
13981 build_int_cst (NULL_TREE, threads));
d9a6bd32
JJ
13982 cfun->has_simduid_loops = true;
13983 }
13984 else
13985 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START),
13986 0);
726a989a 13987 gimple_bind_add_stmt (bind, x);
953ff289 13988
355a7673 13989 lower_omp (gimple_omp_body_ptr (stmt), ctx);
726a989a
RB
13990 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
13991 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
13992 gimple_omp_set_body (stmt, NULL);
953ff289 13993
d9a6bd32 13994 if (simd)
e4606348
JJ
13995 x = gimple_build_call_internal (IFN_GOMP_SIMD_ORDERED_END, 1,
13996 build_int_cst (NULL_TREE, threads));
d9a6bd32
JJ
13997 else
13998 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END),
13999 0);
726a989a 14000 gimple_bind_add_stmt (bind, x);
777f7f9a 14001
726a989a 14002 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
777f7f9a 14003
953ff289 14004 pop_gimplify_context (bind);
50674e96 14005
726a989a
RB
14006 gimple_bind_append_vars (bind, ctx->block_vars);
14007 BLOCK_VARS (block) = gimple_bind_vars (bind);
953ff289
DN
14008}
14009
953ff289 14010
726a989a 14011/* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
953ff289
DN
14012 substitution of a couple of function calls. But in the NAMED case,
14013 requires that languages coordinate a symbol name. It is therefore
14014 best put here in common code. */
14015
de144fb2 14016static GTY(()) hash_map<tree, tree> *critical_name_mutexes;
953ff289
DN
14017
14018static void
726a989a 14019lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
953ff289 14020{
726a989a
RB
14021 tree block;
14022 tree name, lock, unlock;
538dd0b7
DM
14023 gomp_critical *stmt = as_a <gomp_critical *> (gsi_stmt (*gsi_p));
14024 gbind *bind;
db3927fb 14025 location_t loc = gimple_location (stmt);
726a989a 14026 gimple_seq tbody;
953ff289 14027
726a989a 14028 name = gimple_omp_critical_name (stmt);
953ff289
DN
14029 if (name)
14030 {
5039610b 14031 tree decl;
953ff289
DN
14032
14033 if (!critical_name_mutexes)
de144fb2 14034 critical_name_mutexes = hash_map<tree, tree>::create_ggc (10);
953ff289 14035
de144fb2 14036 tree *n = critical_name_mutexes->get (name);
953ff289
DN
14037 if (n == NULL)
14038 {
14039 char *new_str;
14040
b731b390 14041 decl = create_tmp_var_raw (ptr_type_node);
953ff289
DN
14042
14043 new_str = ACONCAT ((".gomp_critical_user_",
14044 IDENTIFIER_POINTER (name), NULL));
14045 DECL_NAME (decl) = get_identifier (new_str);
14046 TREE_PUBLIC (decl) = 1;
14047 TREE_STATIC (decl) = 1;
14048 DECL_COMMON (decl) = 1;
14049 DECL_ARTIFICIAL (decl) = 1;
14050 DECL_IGNORED_P (decl) = 1;
1f6be682 14051
9041d2e6 14052 varpool_node::finalize_decl (decl);
953ff289 14053
de144fb2 14054 critical_name_mutexes->put (name, decl);
953ff289
DN
14055 }
14056 else
de144fb2 14057 decl = *n;
953ff289 14058
41dbbb37 14059 /* If '#pragma omp critical' is inside offloaded region or
476ff787
AT
14060 inside function marked as offloadable, the symbol must be
14061 marked as offloadable too. */
14062 omp_context *octx;
14063 if (cgraph_node::get (current_function_decl)->offloadable)
14064 varpool_node::get_create (decl)->offloadable = 1;
14065 else
14066 for (octx = ctx->outer; octx; octx = octx->outer)
41dbbb37 14067 if (is_gimple_omp_offloaded (octx->stmt))
476ff787
AT
14068 {
14069 varpool_node::get_create (decl)->offloadable = 1;
14070 break;
14071 }
14072
e79983f4 14073 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START);
db3927fb 14074 lock = build_call_expr_loc (loc, lock, 1, build_fold_addr_expr_loc (loc, decl));
953ff289 14075
e79983f4 14076 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END);
db3927fb
AH
14077 unlock = build_call_expr_loc (loc, unlock, 1,
14078 build_fold_addr_expr_loc (loc, decl));
953ff289
DN
14079 }
14080 else
14081 {
e79983f4 14082 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START);
db3927fb 14083 lock = build_call_expr_loc (loc, lock, 0);
953ff289 14084
e79983f4 14085 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END);
db3927fb 14086 unlock = build_call_expr_loc (loc, unlock, 0);
953ff289
DN
14087 }
14088
45852dcc 14089 push_gimplify_context ();
953ff289
DN
14090
14091 block = make_node (BLOCK);
355a7673
MM
14092 bind = gimple_build_bind (NULL, NULL, block);
14093 gsi_replace (gsi_p, bind, true);
14094 gimple_bind_add_stmt (bind, stmt);
777f7f9a 14095
726a989a
RB
14096 tbody = gimple_bind_body (bind);
14097 gimplify_and_add (lock, &tbody);
14098 gimple_bind_set_body (bind, tbody);
953ff289 14099
355a7673 14100 lower_omp (gimple_omp_body_ptr (stmt), ctx);
726a989a
RB
14101 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
14102 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
14103 gimple_omp_set_body (stmt, NULL);
953ff289 14104
726a989a
RB
14105 tbody = gimple_bind_body (bind);
14106 gimplify_and_add (unlock, &tbody);
14107 gimple_bind_set_body (bind, tbody);
777f7f9a 14108
726a989a 14109 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
953ff289
DN
14110
14111 pop_gimplify_context (bind);
726a989a
RB
14112 gimple_bind_append_vars (bind, ctx->block_vars);
14113 BLOCK_VARS (block) = gimple_bind_vars (bind);
50674e96
DN
14114}
14115
14116
14117/* A subroutine of lower_omp_for. Generate code to emit the predicate
14118 for a lastprivate clause. Given a loop control predicate of (V
14119 cond N2), we gate the clause on (!(V cond N2)). The lowered form
3d55c64b
JJ
14120 is appended to *DLIST, iterator initialization is appended to
14121 *BODY_P. */
50674e96
DN
14122
14123static void
726a989a
RB
14124lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
14125 gimple_seq *dlist, struct omp_context *ctx)
50674e96 14126{
726a989a 14127 tree clauses, cond, vinit;
50674e96 14128 enum tree_code cond_code;
726a989a 14129 gimple_seq stmts;
b8698a0f 14130
a68ab351 14131 cond_code = fd->loop.cond_code;
50674e96
DN
14132 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
14133
14134 /* When possible, use a strict equality expression. This can let VRP
14135 type optimizations deduce the value and remove a copy. */
9541ffee 14136 if (tree_fits_shwi_p (fd->loop.step))
50674e96 14137 {
eb1ce453 14138 HOST_WIDE_INT step = tree_to_shwi (fd->loop.step);
50674e96
DN
14139 if (step == 1 || step == -1)
14140 cond_code = EQ_EXPR;
14141 }
14142
41b37d5e
JJ
14143 tree n2 = fd->loop.n2;
14144 if (fd->collapse > 1
14145 && TREE_CODE (n2) != INTEGER_CST
d9a6bd32 14146 && gimple_omp_for_combined_into_p (fd->for_stmt))
41b37d5e 14147 {
e01d41e5 14148 struct omp_context *taskreg_ctx = NULL;
d9a6bd32
JJ
14149 if (gimple_code (ctx->outer->stmt) == GIMPLE_OMP_FOR)
14150 {
14151 gomp_for *gfor = as_a <gomp_for *> (ctx->outer->stmt);
e01d41e5
JJ
14152 if (gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_FOR
14153 || gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_DISTRIBUTE)
d9a6bd32 14154 {
e01d41e5
JJ
14155 if (gimple_omp_for_combined_into_p (gfor))
14156 {
14157 gcc_assert (ctx->outer->outer
14158 && is_parallel_ctx (ctx->outer->outer));
14159 taskreg_ctx = ctx->outer->outer;
14160 }
14161 else
14162 {
14163 struct omp_for_data outer_fd;
14164 extract_omp_for_data (gfor, &outer_fd, NULL);
14165 n2 = fold_convert (TREE_TYPE (n2), outer_fd.loop.n2);
14166 }
d9a6bd32
JJ
14167 }
14168 else if (gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_TASKLOOP)
e01d41e5 14169 taskreg_ctx = ctx->outer->outer;
d9a6bd32 14170 }
e01d41e5
JJ
14171 else if (is_taskreg_ctx (ctx->outer))
14172 taskreg_ctx = ctx->outer;
14173 if (taskreg_ctx)
41b37d5e 14174 {
d9a6bd32
JJ
14175 int i;
14176 tree innerc
e01d41e5 14177 = find_omp_clause (gimple_omp_taskreg_clauses (taskreg_ctx->stmt),
d9a6bd32
JJ
14178 OMP_CLAUSE__LOOPTEMP_);
14179 gcc_assert (innerc);
14180 for (i = 0; i < fd->collapse; i++)
14181 {
14182 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
14183 OMP_CLAUSE__LOOPTEMP_);
14184 gcc_assert (innerc);
14185 }
14186 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
14187 OMP_CLAUSE__LOOPTEMP_);
14188 if (innerc)
14189 n2 = fold_convert (TREE_TYPE (n2),
14190 lookup_decl (OMP_CLAUSE_DECL (innerc),
e01d41e5 14191 taskreg_ctx));
41b37d5e
JJ
14192 }
14193 }
14194 cond = build2 (cond_code, boolean_type_node, fd->loop.v, n2);
50674e96 14195
726a989a 14196 clauses = gimple_omp_for_clauses (fd->for_stmt);
3d55c64b
JJ
14197 stmts = NULL;
14198 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
726a989a 14199 if (!gimple_seq_empty_p (stmts))
3d55c64b 14200 {
726a989a 14201 gimple_seq_add_seq (&stmts, *dlist);
a68ab351 14202 *dlist = stmts;
3d55c64b
JJ
14203
14204 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
a68ab351 14205 vinit = fd->loop.n1;
3d55c64b 14206 if (cond_code == EQ_EXPR
9541ffee 14207 && tree_fits_shwi_p (fd->loop.n2)
a68ab351
JJ
14208 && ! integer_zerop (fd->loop.n2))
14209 vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0);
74bf76ed
JJ
14210 else
14211 vinit = unshare_expr (vinit);
3d55c64b
JJ
14212
14213 /* Initialize the iterator variable, so that threads that don't execute
14214 any iterations don't execute the lastprivate clauses by accident. */
726a989a 14215 gimplify_assign (fd->loop.v, vinit, body_p);
3d55c64b 14216 }
50674e96
DN
14217}
14218
14219
41dbbb37 14220/* Lower code for an OMP loop directive. */
50674e96
DN
14221
14222static void
726a989a 14223lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
50674e96 14224{
726a989a 14225 tree *rhs_p, block;
acf0174b 14226 struct omp_for_data fd, *fdp = NULL;
538dd0b7
DM
14227 gomp_for *stmt = as_a <gomp_for *> (gsi_stmt (*gsi_p));
14228 gbind *new_stmt;
0f900dfa 14229 gimple_seq omp_for_body, body, dlist;
e4834818 14230 gimple_seq oacc_head = NULL, oacc_tail = NULL;
726a989a 14231 size_t i;
50674e96 14232
45852dcc 14233 push_gimplify_context ();
50674e96 14234
355a7673 14235 lower_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
50674e96 14236
b357f682 14237 block = make_node (BLOCK);
726a989a 14238 new_stmt = gimple_build_bind (NULL, NULL, block);
355a7673 14239 /* Replace at gsi right away, so that 'stmt' is no member
026c3cfd 14240 of a sequence anymore as we're going to add to a different
355a7673
MM
14241 one below. */
14242 gsi_replace (gsi_p, new_stmt, true);
b357f682 14243
50674e96
DN
14244 /* Move declaration of temporaries in the loop body before we make
14245 it go away. */
726a989a
RB
14246 omp_for_body = gimple_omp_body (stmt);
14247 if (!gimple_seq_empty_p (omp_for_body)
14248 && gimple_code (gimple_seq_first_stmt (omp_for_body)) == GIMPLE_BIND)
14249 {
538dd0b7
DM
14250 gbind *inner_bind
14251 = as_a <gbind *> (gimple_seq_first_stmt (omp_for_body));
c74559df 14252 tree vars = gimple_bind_vars (inner_bind);
726a989a 14253 gimple_bind_append_vars (new_stmt, vars);
c74559df
JJ
14254 /* bind_vars/BLOCK_VARS are being moved to new_stmt/block, don't
14255 keep them on the inner_bind and it's block. */
14256 gimple_bind_set_vars (inner_bind, NULL_TREE);
14257 if (gimple_bind_block (inner_bind))
14258 BLOCK_VARS (gimple_bind_block (inner_bind)) = NULL_TREE;
726a989a 14259 }
50674e96 14260
acf0174b
JJ
14261 if (gimple_omp_for_combined_into_p (stmt))
14262 {
14263 extract_omp_for_data (stmt, &fd, NULL);
14264 fdp = &fd;
14265
14266 /* We need two temporaries with fd.loop.v type (istart/iend)
14267 and then (fd.collapse - 1) temporaries with the same
14268 type for count2 ... countN-1 vars if not constant. */
14269 size_t count = 2;
14270 tree type = fd.iter_type;
14271 if (fd.collapse > 1
14272 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
14273 count += fd.collapse - 1;
d9a6bd32
JJ
14274 bool taskreg_for
14275 = (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR
14276 || gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_TASKLOOP);
acf0174b
JJ
14277 tree outerc = NULL, *pc = gimple_omp_for_clauses_ptr (stmt);
14278 tree clauses = *pc;
d9a6bd32 14279 if (taskreg_for)
acf0174b 14280 outerc
d9a6bd32 14281 = find_omp_clause (gimple_omp_taskreg_clauses (ctx->outer->stmt),
acf0174b
JJ
14282 OMP_CLAUSE__LOOPTEMP_);
14283 for (i = 0; i < count; i++)
14284 {
14285 tree temp;
d9a6bd32 14286 if (taskreg_for)
acf0174b
JJ
14287 {
14288 gcc_assert (outerc);
14289 temp = lookup_decl (OMP_CLAUSE_DECL (outerc), ctx->outer);
14290 outerc = find_omp_clause (OMP_CLAUSE_CHAIN (outerc),
14291 OMP_CLAUSE__LOOPTEMP_);
14292 }
14293 else
f014c653 14294 {
b731b390 14295 temp = create_tmp_var (type);
f014c653
JJ
14296 insert_decl_map (&ctx->outer->cb, temp, temp);
14297 }
acf0174b
JJ
14298 *pc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
14299 OMP_CLAUSE_DECL (*pc) = temp;
14300 pc = &OMP_CLAUSE_CHAIN (*pc);
14301 }
14302 *pc = clauses;
14303 }
14304
726a989a 14305 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
50674e96 14306 dlist = NULL;
726a989a 14307 body = NULL;
acf0174b
JJ
14308 lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx,
14309 fdp);
726a989a 14310 gimple_seq_add_seq (&body, gimple_omp_for_pre_body (stmt));
50674e96 14311
74bf76ed
JJ
14312 lower_omp (gimple_omp_body_ptr (stmt), ctx);
14313
50674e96
DN
14314 /* Lower the header expressions. At this point, we can assume that
14315 the header is of the form:
14316
14317 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
14318
14319 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
14320 using the .omp_data_s mapping, if needed. */
726a989a 14321 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
a68ab351 14322 {
726a989a 14323 rhs_p = gimple_omp_for_initial_ptr (stmt, i);
a68ab351 14324 if (!is_gimple_min_invariant (*rhs_p))
726a989a 14325 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
a68ab351 14326
726a989a 14327 rhs_p = gimple_omp_for_final_ptr (stmt, i);
a68ab351 14328 if (!is_gimple_min_invariant (*rhs_p))
726a989a 14329 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
a68ab351 14330
726a989a 14331 rhs_p = &TREE_OPERAND (gimple_omp_for_incr (stmt, i), 1);
a68ab351 14332 if (!is_gimple_min_invariant (*rhs_p))
726a989a 14333 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
a68ab351 14334 }
50674e96
DN
14335
14336 /* Once lowered, extract the bounds and clauses. */
a68ab351 14337 extract_omp_for_data (stmt, &fd, NULL);
50674e96 14338
e4834818
NS
14339 if (is_gimple_omp_oacc (ctx->stmt)
14340 && !ctx_in_oacc_kernels_region (ctx))
14341 lower_oacc_head_tail (gimple_location (stmt),
14342 gimple_omp_for_clauses (stmt),
14343 &oacc_head, &oacc_tail, ctx);
14344
374d0225 14345 /* Add OpenACC partitioning and reduction markers just before the loop */
e4834818
NS
14346 if (oacc_head)
14347 gimple_seq_add_seq (&body, oacc_head);
14348
726a989a 14349 lower_omp_for_lastprivate (&fd, &body, &dlist, ctx);
50674e96 14350
d9a6bd32
JJ
14351 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR)
14352 for (tree c = gimple_omp_for_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
14353 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
14354 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
14355 {
14356 OMP_CLAUSE_DECL (c) = lookup_decl (OMP_CLAUSE_DECL (c), ctx);
14357 if (DECL_P (OMP_CLAUSE_LINEAR_STEP (c)))
14358 OMP_CLAUSE_LINEAR_STEP (c)
14359 = maybe_lookup_decl_in_outer_ctx (OMP_CLAUSE_LINEAR_STEP (c),
14360 ctx);
14361 }
14362
726a989a
RB
14363 gimple_seq_add_stmt (&body, stmt);
14364 gimple_seq_add_seq (&body, gimple_omp_body (stmt));
777f7f9a 14365
726a989a
RB
14366 gimple_seq_add_stmt (&body, gimple_build_omp_continue (fd.loop.v,
14367 fd.loop.v));
777f7f9a 14368
50674e96 14369 /* After the loop, add exit clauses. */
726a989a 14370 lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, ctx);
acf0174b
JJ
14371
14372 if (ctx->cancellable)
14373 gimple_seq_add_stmt (&body, gimple_build_label (ctx->cancel_label));
14374
726a989a 14375 gimple_seq_add_seq (&body, dlist);
50674e96 14376
726a989a 14377 body = maybe_catch_exception (body);
4a31b7ee 14378
777f7f9a 14379 /* Region exit marker goes at the end of the loop body. */
726a989a 14380 gimple_seq_add_stmt (&body, gimple_build_omp_return (fd.have_nowait));
acf0174b 14381 maybe_add_implicit_barrier_cancel (ctx, &body);
e4834818
NS
14382
14383 /* Add OpenACC joining and reduction markers just after the loop. */
14384 if (oacc_tail)
14385 gimple_seq_add_seq (&body, oacc_tail);
14386
b357f682 14387 pop_gimplify_context (new_stmt);
726a989a
RB
14388
14389 gimple_bind_append_vars (new_stmt, ctx->block_vars);
14390 BLOCK_VARS (block) = gimple_bind_vars (new_stmt);
b357f682
JJ
14391 if (BLOCK_VARS (block))
14392 TREE_USED (block) = 1;
50674e96 14393
726a989a
RB
14394 gimple_bind_set_body (new_stmt, body);
14395 gimple_omp_set_body (stmt, NULL);
14396 gimple_omp_for_set_pre_body (stmt, NULL);
953ff289
DN
14397}
14398
b8698a0f 14399/* Callback for walk_stmts. Check if the current statement only contains
e0246869 14400 GIMPLE_OMP_FOR or GIMPLE_OMP_SECTIONS. */
69f1837b
JJ
14401
14402static tree
726a989a
RB
14403check_combined_parallel (gimple_stmt_iterator *gsi_p,
14404 bool *handled_ops_p,
14405 struct walk_stmt_info *wi)
69f1837b 14406{
d3bfe4de 14407 int *info = (int *) wi->info;
355fe088 14408 gimple *stmt = gsi_stmt (*gsi_p);
69f1837b 14409
726a989a
RB
14410 *handled_ops_p = true;
14411 switch (gimple_code (stmt))
69f1837b 14412 {
726a989a
RB
14413 WALK_SUBSTMTS;
14414
14415 case GIMPLE_OMP_FOR:
14416 case GIMPLE_OMP_SECTIONS:
69f1837b
JJ
14417 *info = *info == 0 ? 1 : -1;
14418 break;
14419 default:
14420 *info = -1;
14421 break;
14422 }
14423 return NULL;
14424}
50674e96 14425
a68ab351
JJ
14426struct omp_taskcopy_context
14427{
14428 /* This field must be at the beginning, as we do "inheritance": Some
14429 callback functions for tree-inline.c (e.g., omp_copy_decl)
14430 receive a copy_body_data pointer that is up-casted to an
14431 omp_context pointer. */
14432 copy_body_data cb;
14433 omp_context *ctx;
14434};
14435
14436static tree
14437task_copyfn_copy_decl (tree var, copy_body_data *cb)
14438{
14439 struct omp_taskcopy_context *tcctx = (struct omp_taskcopy_context *) cb;
14440
14441 if (splay_tree_lookup (tcctx->ctx->sfield_map, (splay_tree_key) var))
b731b390 14442 return create_tmp_var (TREE_TYPE (var));
a68ab351
JJ
14443
14444 return var;
14445}
14446
14447static tree
14448task_copyfn_remap_type (struct omp_taskcopy_context *tcctx, tree orig_type)
14449{
14450 tree name, new_fields = NULL, type, f;
14451
14452 type = lang_hooks.types.make_type (RECORD_TYPE);
14453 name = DECL_NAME (TYPE_NAME (orig_type));
c2255bc4
AH
14454 name = build_decl (gimple_location (tcctx->ctx->stmt),
14455 TYPE_DECL, name, type);
a68ab351
JJ
14456 TYPE_NAME (type) = name;
14457
14458 for (f = TYPE_FIELDS (orig_type); f ; f = TREE_CHAIN (f))
14459 {
14460 tree new_f = copy_node (f);
14461 DECL_CONTEXT (new_f) = type;
14462 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &tcctx->cb);
14463 TREE_CHAIN (new_f) = new_fields;
726a989a
RB
14464 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &tcctx->cb, NULL);
14465 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r, &tcctx->cb, NULL);
14466 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
14467 &tcctx->cb, NULL);
a68ab351 14468 new_fields = new_f;
b787e7a2 14469 tcctx->cb.decl_map->put (f, new_f);
a68ab351
JJ
14470 }
14471 TYPE_FIELDS (type) = nreverse (new_fields);
14472 layout_type (type);
14473 return type;
14474}
14475
14476/* Create task copyfn. */
14477
14478static void
538dd0b7 14479create_task_copyfn (gomp_task *task_stmt, omp_context *ctx)
a68ab351
JJ
14480{
14481 struct function *child_cfun;
14482 tree child_fn, t, c, src, dst, f, sf, arg, sarg, decl;
14483 tree record_type, srecord_type, bind, list;
14484 bool record_needs_remap = false, srecord_needs_remap = false;
14485 splay_tree_node n;
14486 struct omp_taskcopy_context tcctx;
db3927fb 14487 location_t loc = gimple_location (task_stmt);
a68ab351 14488
726a989a 14489 child_fn = gimple_omp_task_copy_fn (task_stmt);
a68ab351
JJ
14490 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
14491 gcc_assert (child_cfun->cfg == NULL);
a68ab351
JJ
14492 DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
14493
14494 /* Reset DECL_CONTEXT on function arguments. */
910ad8de 14495 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
a68ab351
JJ
14496 DECL_CONTEXT (t) = child_fn;
14497
14498 /* Populate the function. */
45852dcc 14499 push_gimplify_context ();
af16bc76 14500 push_cfun (child_cfun);
a68ab351
JJ
14501
14502 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
14503 TREE_SIDE_EFFECTS (bind) = 1;
14504 list = NULL;
14505 DECL_SAVED_TREE (child_fn) = bind;
726a989a 14506 DECL_SOURCE_LOCATION (child_fn) = gimple_location (task_stmt);
a68ab351
JJ
14507
14508 /* Remap src and dst argument types if needed. */
14509 record_type = ctx->record_type;
14510 srecord_type = ctx->srecord_type;
910ad8de 14511 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
a68ab351
JJ
14512 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
14513 {
14514 record_needs_remap = true;
14515 break;
14516 }
910ad8de 14517 for (f = TYPE_FIELDS (srecord_type); f ; f = DECL_CHAIN (f))
a68ab351
JJ
14518 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
14519 {
14520 srecord_needs_remap = true;
14521 break;
14522 }
14523
14524 if (record_needs_remap || srecord_needs_remap)
14525 {
14526 memset (&tcctx, '\0', sizeof (tcctx));
14527 tcctx.cb.src_fn = ctx->cb.src_fn;
14528 tcctx.cb.dst_fn = child_fn;
d52f5295 14529 tcctx.cb.src_node = cgraph_node::get (tcctx.cb.src_fn);
fe660d7b 14530 gcc_checking_assert (tcctx.cb.src_node);
a68ab351
JJ
14531 tcctx.cb.dst_node = tcctx.cb.src_node;
14532 tcctx.cb.src_cfun = ctx->cb.src_cfun;
14533 tcctx.cb.copy_decl = task_copyfn_copy_decl;
1d65f45c 14534 tcctx.cb.eh_lp_nr = 0;
a68ab351 14535 tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
b787e7a2 14536 tcctx.cb.decl_map = new hash_map<tree, tree>;
a68ab351
JJ
14537 tcctx.ctx = ctx;
14538
14539 if (record_needs_remap)
14540 record_type = task_copyfn_remap_type (&tcctx, record_type);
14541 if (srecord_needs_remap)
14542 srecord_type = task_copyfn_remap_type (&tcctx, srecord_type);
14543 }
14544 else
14545 tcctx.cb.decl_map = NULL;
14546
a68ab351
JJ
14547 arg = DECL_ARGUMENTS (child_fn);
14548 TREE_TYPE (arg) = build_pointer_type (record_type);
910ad8de 14549 sarg = DECL_CHAIN (arg);
a68ab351
JJ
14550 TREE_TYPE (sarg) = build_pointer_type (srecord_type);
14551
14552 /* First pass: initialize temporaries used in record_type and srecord_type
14553 sizes and field offsets. */
14554 if (tcctx.cb.decl_map)
726a989a 14555 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
a68ab351
JJ
14556 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
14557 {
14558 tree *p;
14559
14560 decl = OMP_CLAUSE_DECL (c);
b787e7a2 14561 p = tcctx.cb.decl_map->get (decl);
a68ab351
JJ
14562 if (p == NULL)
14563 continue;
14564 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
14565 sf = (tree) n->value;
b787e7a2 14566 sf = *tcctx.cb.decl_map->get (sf);
70f34814 14567 src = build_simple_mem_ref_loc (loc, sarg);
a9a58711 14568 src = omp_build_component_ref (src, sf);
726a989a 14569 t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
a68ab351
JJ
14570 append_to_statement_list (t, &list);
14571 }
14572
14573 /* Second pass: copy shared var pointers and copy construct non-VLA
14574 firstprivate vars. */
726a989a 14575 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
a68ab351
JJ
14576 switch (OMP_CLAUSE_CODE (c))
14577 {
d9a6bd32 14578 splay_tree_key key;
a68ab351
JJ
14579 case OMP_CLAUSE_SHARED:
14580 decl = OMP_CLAUSE_DECL (c);
d9a6bd32
JJ
14581 key = (splay_tree_key) decl;
14582 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
14583 key = (splay_tree_key) &DECL_UID (decl);
14584 n = splay_tree_lookup (ctx->field_map, key);
a68ab351
JJ
14585 if (n == NULL)
14586 break;
14587 f = (tree) n->value;
14588 if (tcctx.cb.decl_map)
b787e7a2 14589 f = *tcctx.cb.decl_map->get (f);
d9a6bd32 14590 n = splay_tree_lookup (ctx->sfield_map, key);
a68ab351
JJ
14591 sf = (tree) n->value;
14592 if (tcctx.cb.decl_map)
b787e7a2 14593 sf = *tcctx.cb.decl_map->get (sf);
70f34814 14594 src = build_simple_mem_ref_loc (loc, sarg);
a9a58711 14595 src = omp_build_component_ref (src, sf);
70f34814 14596 dst = build_simple_mem_ref_loc (loc, arg);
a9a58711 14597 dst = omp_build_component_ref (dst, f);
726a989a 14598 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
a68ab351
JJ
14599 append_to_statement_list (t, &list);
14600 break;
14601 case OMP_CLAUSE_FIRSTPRIVATE:
14602 decl = OMP_CLAUSE_DECL (c);
14603 if (is_variable_sized (decl))
14604 break;
14605 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
14606 if (n == NULL)
14607 break;
14608 f = (tree) n->value;
14609 if (tcctx.cb.decl_map)
b787e7a2 14610 f = *tcctx.cb.decl_map->get (f);
a68ab351
JJ
14611 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
14612 if (n != NULL)
14613 {
14614 sf = (tree) n->value;
14615 if (tcctx.cb.decl_map)
b787e7a2 14616 sf = *tcctx.cb.decl_map->get (sf);
70f34814 14617 src = build_simple_mem_ref_loc (loc, sarg);
a9a58711 14618 src = omp_build_component_ref (src, sf);
a68ab351 14619 if (use_pointer_for_field (decl, NULL) || is_reference (decl))
70f34814 14620 src = build_simple_mem_ref_loc (loc, src);
a68ab351
JJ
14621 }
14622 else
14623 src = decl;
70f34814 14624 dst = build_simple_mem_ref_loc (loc, arg);
a9a58711 14625 dst = omp_build_component_ref (dst, f);
a68ab351
JJ
14626 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
14627 append_to_statement_list (t, &list);
14628 break;
14629 case OMP_CLAUSE_PRIVATE:
14630 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c))
14631 break;
14632 decl = OMP_CLAUSE_DECL (c);
14633 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
14634 f = (tree) n->value;
14635 if (tcctx.cb.decl_map)
b787e7a2 14636 f = *tcctx.cb.decl_map->get (f);
a68ab351
JJ
14637 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
14638 if (n != NULL)
14639 {
14640 sf = (tree) n->value;
14641 if (tcctx.cb.decl_map)
b787e7a2 14642 sf = *tcctx.cb.decl_map->get (sf);
70f34814 14643 src = build_simple_mem_ref_loc (loc, sarg);
a9a58711 14644 src = omp_build_component_ref (src, sf);
a68ab351 14645 if (use_pointer_for_field (decl, NULL))
70f34814 14646 src = build_simple_mem_ref_loc (loc, src);
a68ab351
JJ
14647 }
14648 else
14649 src = decl;
70f34814 14650 dst = build_simple_mem_ref_loc (loc, arg);
a9a58711 14651 dst = omp_build_component_ref (dst, f);
726a989a 14652 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
a68ab351
JJ
14653 append_to_statement_list (t, &list);
14654 break;
14655 default:
14656 break;
14657 }
14658
14659 /* Last pass: handle VLA firstprivates. */
14660 if (tcctx.cb.decl_map)
726a989a 14661 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
a68ab351
JJ
14662 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
14663 {
14664 tree ind, ptr, df;
14665
14666 decl = OMP_CLAUSE_DECL (c);
14667 if (!is_variable_sized (decl))
14668 continue;
14669 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
14670 if (n == NULL)
14671 continue;
14672 f = (tree) n->value;
b787e7a2 14673 f = *tcctx.cb.decl_map->get (f);
a68ab351
JJ
14674 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
14675 ind = DECL_VALUE_EXPR (decl);
14676 gcc_assert (TREE_CODE (ind) == INDIRECT_REF);
14677 gcc_assert (DECL_P (TREE_OPERAND (ind, 0)));
14678 n = splay_tree_lookup (ctx->sfield_map,
14679 (splay_tree_key) TREE_OPERAND (ind, 0));
14680 sf = (tree) n->value;
b787e7a2 14681 sf = *tcctx.cb.decl_map->get (sf);
70f34814 14682 src = build_simple_mem_ref_loc (loc, sarg);
a9a58711 14683 src = omp_build_component_ref (src, sf);
70f34814
RG
14684 src = build_simple_mem_ref_loc (loc, src);
14685 dst = build_simple_mem_ref_loc (loc, arg);
a9a58711 14686 dst = omp_build_component_ref (dst, f);
a68ab351
JJ
14687 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
14688 append_to_statement_list (t, &list);
14689 n = splay_tree_lookup (ctx->field_map,
14690 (splay_tree_key) TREE_OPERAND (ind, 0));
14691 df = (tree) n->value;
b787e7a2 14692 df = *tcctx.cb.decl_map->get (df);
70f34814 14693 ptr = build_simple_mem_ref_loc (loc, arg);
a9a58711 14694 ptr = omp_build_component_ref (ptr, df);
726a989a 14695 t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
db3927fb 14696 build_fold_addr_expr_loc (loc, dst));
a68ab351
JJ
14697 append_to_statement_list (t, &list);
14698 }
14699
14700 t = build1 (RETURN_EXPR, void_type_node, NULL);
14701 append_to_statement_list (t, &list);
14702
14703 if (tcctx.cb.decl_map)
b787e7a2 14704 delete tcctx.cb.decl_map;
a68ab351
JJ
14705 pop_gimplify_context (NULL);
14706 BIND_EXPR_BODY (bind) = list;
14707 pop_cfun ();
a68ab351
JJ
14708}
14709
acf0174b 14710static void
d9a6bd32 14711lower_depend_clauses (tree *pclauses, gimple_seq *iseq, gimple_seq *oseq)
acf0174b
JJ
14712{
14713 tree c, clauses;
355fe088 14714 gimple *g;
acf0174b
JJ
14715 size_t n_in = 0, n_out = 0, idx = 2, i;
14716
d9a6bd32 14717 clauses = find_omp_clause (*pclauses, OMP_CLAUSE_DEPEND);
acf0174b
JJ
14718 gcc_assert (clauses);
14719 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
14720 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
14721 switch (OMP_CLAUSE_DEPEND_KIND (c))
14722 {
14723 case OMP_CLAUSE_DEPEND_IN:
14724 n_in++;
14725 break;
14726 case OMP_CLAUSE_DEPEND_OUT:
14727 case OMP_CLAUSE_DEPEND_INOUT:
14728 n_out++;
14729 break;
d9a6bd32
JJ
14730 case OMP_CLAUSE_DEPEND_SOURCE:
14731 case OMP_CLAUSE_DEPEND_SINK:
14732 /* FALLTHRU */
acf0174b
JJ
14733 default:
14734 gcc_unreachable ();
14735 }
14736 tree type = build_array_type_nelts (ptr_type_node, n_in + n_out + 2);
b731b390 14737 tree array = create_tmp_var (type);
d9a6bd32 14738 TREE_ADDRESSABLE (array) = 1;
acf0174b
JJ
14739 tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
14740 NULL_TREE);
14741 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_in + n_out));
14742 gimple_seq_add_stmt (iseq, g);
14743 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
14744 NULL_TREE);
14745 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_out));
14746 gimple_seq_add_stmt (iseq, g);
14747 for (i = 0; i < 2; i++)
14748 {
14749 if ((i ? n_in : n_out) == 0)
14750 continue;
14751 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
14752 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
14753 && ((OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_IN) ^ i))
14754 {
14755 tree t = OMP_CLAUSE_DECL (c);
14756 t = fold_convert (ptr_type_node, t);
14757 gimplify_expr (&t, iseq, NULL, is_gimple_val, fb_rvalue);
14758 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (idx++),
14759 NULL_TREE, NULL_TREE);
14760 g = gimple_build_assign (r, t);
14761 gimple_seq_add_stmt (iseq, g);
14762 }
14763 }
acf0174b
JJ
14764 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
14765 OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
d9a6bd32
JJ
14766 OMP_CLAUSE_CHAIN (c) = *pclauses;
14767 *pclauses = c;
acf0174b
JJ
14768 tree clobber = build_constructor (type, NULL);
14769 TREE_THIS_VOLATILE (clobber) = 1;
14770 g = gimple_build_assign (array, clobber);
14771 gimple_seq_add_stmt (oseq, g);
14772}
14773
726a989a
RB
14774/* Lower the OpenMP parallel or task directive in the current statement
14775 in GSI_P. CTX holds context information for the directive. */
50674e96
DN
14776
14777static void
726a989a 14778lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
50674e96 14779{
726a989a
RB
14780 tree clauses;
14781 tree child_fn, t;
355fe088 14782 gimple *stmt = gsi_stmt (*gsi_p);
538dd0b7 14783 gbind *par_bind, *bind, *dep_bind = NULL;
acf0174b 14784 gimple_seq par_body, olist, ilist, par_olist, par_rlist, par_ilist, new_body;
db3927fb 14785 location_t loc = gimple_location (stmt);
50674e96 14786
726a989a 14787 clauses = gimple_omp_taskreg_clauses (stmt);
538dd0b7
DM
14788 par_bind
14789 = as_a <gbind *> (gimple_seq_first_stmt (gimple_omp_body (stmt)));
726a989a 14790 par_body = gimple_bind_body (par_bind);
50674e96 14791 child_fn = ctx->cb.dst_fn;
726a989a
RB
14792 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
14793 && !gimple_omp_parallel_combined_p (stmt))
69f1837b
JJ
14794 {
14795 struct walk_stmt_info wi;
14796 int ws_num = 0;
14797
14798 memset (&wi, 0, sizeof (wi));
69f1837b
JJ
14799 wi.info = &ws_num;
14800 wi.val_only = true;
726a989a 14801 walk_gimple_seq (par_body, check_combined_parallel, NULL, &wi);
69f1837b 14802 if (ws_num == 1)
726a989a 14803 gimple_omp_parallel_set_combined_p (stmt, true);
69f1837b 14804 }
acf0174b
JJ
14805 gimple_seq dep_ilist = NULL;
14806 gimple_seq dep_olist = NULL;
14807 if (gimple_code (stmt) == GIMPLE_OMP_TASK
14808 && find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
14809 {
45852dcc 14810 push_gimplify_context ();
acf0174b 14811 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
d9a6bd32
JJ
14812 lower_depend_clauses (gimple_omp_task_clauses_ptr (stmt),
14813 &dep_ilist, &dep_olist);
acf0174b
JJ
14814 }
14815
a68ab351 14816 if (ctx->srecord_type)
538dd0b7 14817 create_task_copyfn (as_a <gomp_task *> (stmt), ctx);
50674e96 14818
45852dcc 14819 push_gimplify_context ();
50674e96 14820
726a989a
RB
14821 par_olist = NULL;
14822 par_ilist = NULL;
acf0174b
JJ
14823 par_rlist = NULL;
14824 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx, NULL);
355a7673 14825 lower_omp (&par_body, ctx);
726a989a 14826 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL)
acf0174b 14827 lower_reduction_clauses (clauses, &par_rlist, ctx);
50674e96
DN
14828
14829 /* Declare all the variables created by mapping and the variables
14830 declared in the scope of the parallel body. */
14831 record_vars_into (ctx->block_vars, child_fn);
726a989a 14832 record_vars_into (gimple_bind_vars (par_bind), child_fn);
50674e96
DN
14833
14834 if (ctx->record_type)
14835 {
a68ab351
JJ
14836 ctx->sender_decl
14837 = create_tmp_var (ctx->srecord_type ? ctx->srecord_type
14838 : ctx->record_type, ".omp_data_o");
cd3f04c8 14839 DECL_NAMELESS (ctx->sender_decl) = 1;
628c189e 14840 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
726a989a 14841 gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl);
50674e96
DN
14842 }
14843
726a989a
RB
14844 olist = NULL;
14845 ilist = NULL;
50674e96
DN
14846 lower_send_clauses (clauses, &ilist, &olist, ctx);
14847 lower_send_shared_vars (&ilist, &olist, ctx);
14848
acf0174b
JJ
14849 if (ctx->record_type)
14850 {
14851 tree clobber = build_constructor (TREE_TYPE (ctx->sender_decl), NULL);
14852 TREE_THIS_VOLATILE (clobber) = 1;
14853 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
14854 clobber));
14855 }
14856
50674e96 14857 /* Once all the expansions are done, sequence all the different
726a989a 14858 fragments inside gimple_omp_body. */
50674e96 14859
726a989a 14860 new_body = NULL;
50674e96
DN
14861
14862 if (ctx->record_type)
14863 {
db3927fb 14864 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
018b899b 14865 /* fixup_child_record_type might have changed receiver_decl's type. */
db3927fb 14866 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
726a989a
RB
14867 gimple_seq_add_stmt (&new_body,
14868 gimple_build_assign (ctx->receiver_decl, t));
50674e96
DN
14869 }
14870
726a989a
RB
14871 gimple_seq_add_seq (&new_body, par_ilist);
14872 gimple_seq_add_seq (&new_body, par_body);
acf0174b
JJ
14873 gimple_seq_add_seq (&new_body, par_rlist);
14874 if (ctx->cancellable)
14875 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
726a989a
RB
14876 gimple_seq_add_seq (&new_body, par_olist);
14877 new_body = maybe_catch_exception (new_body);
b37dddbc
JJ
14878 if (gimple_code (stmt) == GIMPLE_OMP_TASK)
14879 gimple_seq_add_stmt (&new_body,
14880 gimple_build_omp_continue (integer_zero_node,
14881 integer_zero_node));
726a989a
RB
14882 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
14883 gimple_omp_set_body (stmt, new_body);
50674e96 14884
726a989a 14885 bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
acf0174b
JJ
14886 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
14887 gimple_bind_add_seq (bind, ilist);
14888 gimple_bind_add_stmt (bind, stmt);
14889 gimple_bind_add_seq (bind, olist);
14890
14891 pop_gimplify_context (NULL);
14892
14893 if (dep_bind)
14894 {
14895 gimple_bind_add_seq (dep_bind, dep_ilist);
14896 gimple_bind_add_stmt (dep_bind, bind);
14897 gimple_bind_add_seq (dep_bind, dep_olist);
14898 pop_gimplify_context (dep_bind);
14899 }
14900}
14901
41dbbb37 14902/* Lower the GIMPLE_OMP_TARGET in the current statement
acf0174b
JJ
14903 in GSI_P. CTX holds context information for the directive. */
14904
14905static void
14906lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14907{
14908 tree clauses;
14909 tree child_fn, t, c;
538dd0b7 14910 gomp_target *stmt = as_a <gomp_target *> (gsi_stmt (*gsi_p));
d9a6bd32 14911 gbind *tgt_bind, *bind, *dep_bind = NULL;
182190f2 14912 gimple_seq tgt_body, olist, ilist, fplist, new_body;
acf0174b 14913 location_t loc = gimple_location (stmt);
41dbbb37 14914 bool offloaded, data_region;
acf0174b 14915 unsigned int map_cnt = 0;
d9a6bd32 14916 bool has_depend = false;
acf0174b 14917
41dbbb37
TS
14918 offloaded = is_gimple_omp_offloaded (stmt);
14919 switch (gimple_omp_target_kind (stmt))
14920 {
14921 case GF_OMP_TARGET_KIND_REGION:
14922 case GF_OMP_TARGET_KIND_UPDATE:
d9a6bd32
JJ
14923 case GF_OMP_TARGET_KIND_ENTER_DATA:
14924 case GF_OMP_TARGET_KIND_EXIT_DATA:
41dbbb37
TS
14925 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
14926 case GF_OMP_TARGET_KIND_OACC_KERNELS:
14927 case GF_OMP_TARGET_KIND_OACC_UPDATE:
14928 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
6e232ba4 14929 case GF_OMP_TARGET_KIND_OACC_DECLARE:
41dbbb37
TS
14930 data_region = false;
14931 break;
14932 case GF_OMP_TARGET_KIND_DATA:
14933 case GF_OMP_TARGET_KIND_OACC_DATA:
14934 data_region = true;
14935 break;
14936 default:
14937 gcc_unreachable ();
14938 }
14939
acf0174b 14940 clauses = gimple_omp_target_clauses (stmt);
41dbbb37 14941
d9a6bd32
JJ
14942 gimple_seq dep_ilist = NULL;
14943 gimple_seq dep_olist = NULL;
14944 if (find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
14945 {
14946 push_gimplify_context ();
14947 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
14948 lower_depend_clauses (gimple_omp_target_clauses_ptr (stmt),
14949 &dep_ilist, &dep_olist);
14950 has_depend = true;
14951 }
14952
41dbbb37
TS
14953 tgt_bind = NULL;
14954 tgt_body = NULL;
14955 if (offloaded)
acf0174b 14956 {
538dd0b7 14957 tgt_bind = gimple_seq_first_stmt_as_a_bind (gimple_omp_body (stmt));
acf0174b
JJ
14958 tgt_body = gimple_bind_body (tgt_bind);
14959 }
41dbbb37 14960 else if (data_region)
acf0174b
JJ
14961 tgt_body = gimple_omp_body (stmt);
14962 child_fn = ctx->cb.dst_fn;
14963
45852dcc 14964 push_gimplify_context ();
182190f2 14965 fplist = NULL;
acf0174b
JJ
14966
14967 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
14968 switch (OMP_CLAUSE_CODE (c))
14969 {
14970 tree var, x;
14971
14972 default:
14973 break;
14974 case OMP_CLAUSE_MAP:
b2b29377 14975#if CHECKING_P
41dbbb37
TS
14976 /* First check what we're prepared to handle in the following. */
14977 switch (OMP_CLAUSE_MAP_KIND (c))
14978 {
14979 case GOMP_MAP_ALLOC:
14980 case GOMP_MAP_TO:
14981 case GOMP_MAP_FROM:
14982 case GOMP_MAP_TOFROM:
14983 case GOMP_MAP_POINTER:
14984 case GOMP_MAP_TO_PSET:
d9a6bd32
JJ
14985 case GOMP_MAP_FORCE_DEALLOC:
14986 case GOMP_MAP_RELEASE:
14987 case GOMP_MAP_ALWAYS_TO:
14988 case GOMP_MAP_ALWAYS_FROM:
14989 case GOMP_MAP_ALWAYS_TOFROM:
14990 case GOMP_MAP_FIRSTPRIVATE_POINTER:
e01d41e5 14991 case GOMP_MAP_FIRSTPRIVATE_REFERENCE:
d9a6bd32 14992 case GOMP_MAP_STRUCT:
e01d41e5 14993 case GOMP_MAP_ALWAYS_POINTER:
41dbbb37
TS
14994 break;
14995 case GOMP_MAP_FORCE_ALLOC:
14996 case GOMP_MAP_FORCE_TO:
14997 case GOMP_MAP_FORCE_FROM:
14998 case GOMP_MAP_FORCE_TOFROM:
14999 case GOMP_MAP_FORCE_PRESENT:
41dbbb37 15000 case GOMP_MAP_FORCE_DEVICEPTR:
6e232ba4
JN
15001 case GOMP_MAP_DEVICE_RESIDENT:
15002 case GOMP_MAP_LINK:
41dbbb37
TS
15003 gcc_assert (is_gimple_omp_oacc (stmt));
15004 break;
15005 default:
15006 gcc_unreachable ();
15007 }
15008#endif
15009 /* FALLTHRU */
acf0174b
JJ
15010 case OMP_CLAUSE_TO:
15011 case OMP_CLAUSE_FROM:
182190f2 15012 oacc_firstprivate:
acf0174b
JJ
15013 var = OMP_CLAUSE_DECL (c);
15014 if (!DECL_P (var))
15015 {
15016 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
d9a6bd32
JJ
15017 || (!OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
15018 && (OMP_CLAUSE_MAP_KIND (c)
15019 != GOMP_MAP_FIRSTPRIVATE_POINTER)))
acf0174b
JJ
15020 map_cnt++;
15021 continue;
15022 }
15023
15024 if (DECL_SIZE (var)
15025 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
15026 {
15027 tree var2 = DECL_VALUE_EXPR (var);
15028 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
15029 var2 = TREE_OPERAND (var2, 0);
15030 gcc_assert (DECL_P (var2));
15031 var = var2;
15032 }
15033
d9a6bd32 15034 if (offloaded
182190f2 15035 && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
e01d41e5
JJ
15036 && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
15037 || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_REFERENCE))
d9a6bd32
JJ
15038 {
15039 if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
15040 {
15041 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx))
15042 && varpool_node::get_create (var)->offloadable)
15043 continue;
15044
15045 tree type = build_pointer_type (TREE_TYPE (var));
15046 tree new_var = lookup_decl (var, ctx);
15047 x = create_tmp_var_raw (type, get_name (new_var));
15048 gimple_add_tmp_var (x);
15049 x = build_simple_mem_ref (x);
15050 SET_DECL_VALUE_EXPR (new_var, x);
15051 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15052 }
15053 continue;
15054 }
15055
acf0174b
JJ
15056 if (!maybe_lookup_field (var, ctx))
15057 continue;
15058
41dbbb37 15059 if (offloaded)
acf0174b
JJ
15060 {
15061 x = build_receiver_ref (var, true, ctx);
15062 tree new_var = lookup_decl (var, ctx);
d9a6bd32 15063
182190f2
NS
15064 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
15065 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
acf0174b
JJ
15066 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
15067 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
15068 x = build_simple_mem_ref (x);
182190f2
NS
15069 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
15070 {
15071 gcc_assert (is_gimple_omp_oacc (ctx->stmt));
15072 if (is_reference (new_var))
15073 {
15074 /* Create a local object to hold the instance
15075 value. */
15076 tree type = TREE_TYPE (TREE_TYPE (new_var));
15077 const char *id = IDENTIFIER_POINTER (DECL_NAME (new_var));
15078 tree inst = create_tmp_var (type, id);
15079 gimplify_assign (inst, fold_indirect_ref (x), &fplist);
15080 x = build_fold_addr_expr (inst);
15081 }
15082 gimplify_assign (new_var, x, &fplist);
15083 }
15084 else if (DECL_P (new_var))
15085 {
15086 SET_DECL_VALUE_EXPR (new_var, x);
15087 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15088 }
15089 else
15090 gcc_unreachable ();
acf0174b
JJ
15091 }
15092 map_cnt++;
d9a6bd32
JJ
15093 break;
15094
15095 case OMP_CLAUSE_FIRSTPRIVATE:
182190f2
NS
15096 if (is_oacc_parallel (ctx))
15097 goto oacc_firstprivate;
d9a6bd32
JJ
15098 map_cnt++;
15099 var = OMP_CLAUSE_DECL (c);
15100 if (!is_reference (var)
15101 && !is_gimple_reg_type (TREE_TYPE (var)))
15102 {
15103 tree new_var = lookup_decl (var, ctx);
15104 if (is_variable_sized (var))
15105 {
15106 tree pvar = DECL_VALUE_EXPR (var);
15107 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15108 pvar = TREE_OPERAND (pvar, 0);
15109 gcc_assert (DECL_P (pvar));
15110 tree new_pvar = lookup_decl (pvar, ctx);
15111 x = build_fold_indirect_ref (new_pvar);
15112 TREE_THIS_NOTRAP (x) = 1;
15113 }
15114 else
15115 x = build_receiver_ref (var, true, ctx);
15116 SET_DECL_VALUE_EXPR (new_var, x);
15117 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15118 }
15119 break;
15120
15121 case OMP_CLAUSE_PRIVATE:
182190f2
NS
15122 if (is_gimple_omp_oacc (ctx->stmt))
15123 break;
d9a6bd32
JJ
15124 var = OMP_CLAUSE_DECL (c);
15125 if (is_variable_sized (var))
15126 {
15127 tree new_var = lookup_decl (var, ctx);
15128 tree pvar = DECL_VALUE_EXPR (var);
15129 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15130 pvar = TREE_OPERAND (pvar, 0);
15131 gcc_assert (DECL_P (pvar));
15132 tree new_pvar = lookup_decl (pvar, ctx);
15133 x = build_fold_indirect_ref (new_pvar);
15134 TREE_THIS_NOTRAP (x) = 1;
15135 SET_DECL_VALUE_EXPR (new_var, x);
15136 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15137 }
15138 break;
15139
15140 case OMP_CLAUSE_USE_DEVICE_PTR:
15141 case OMP_CLAUSE_IS_DEVICE_PTR:
15142 var = OMP_CLAUSE_DECL (c);
15143 map_cnt++;
15144 if (is_variable_sized (var))
15145 {
15146 tree new_var = lookup_decl (var, ctx);
15147 tree pvar = DECL_VALUE_EXPR (var);
15148 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15149 pvar = TREE_OPERAND (pvar, 0);
15150 gcc_assert (DECL_P (pvar));
15151 tree new_pvar = lookup_decl (pvar, ctx);
15152 x = build_fold_indirect_ref (new_pvar);
15153 TREE_THIS_NOTRAP (x) = 1;
15154 SET_DECL_VALUE_EXPR (new_var, x);
15155 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15156 }
15157 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
15158 {
15159 tree new_var = lookup_decl (var, ctx);
15160 tree type = build_pointer_type (TREE_TYPE (var));
15161 x = create_tmp_var_raw (type, get_name (new_var));
15162 gimple_add_tmp_var (x);
15163 x = build_simple_mem_ref (x);
15164 SET_DECL_VALUE_EXPR (new_var, x);
15165 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15166 }
15167 break;
acf0174b
JJ
15168 }
15169
41dbbb37 15170 if (offloaded)
acf0174b
JJ
15171 {
15172 target_nesting_level++;
15173 lower_omp (&tgt_body, ctx);
15174 target_nesting_level--;
15175 }
41dbbb37 15176 else if (data_region)
acf0174b
JJ
15177 lower_omp (&tgt_body, ctx);
15178
41dbbb37 15179 if (offloaded)
acf0174b
JJ
15180 {
15181 /* Declare all the variables created by mapping and the variables
15182 declared in the scope of the target body. */
15183 record_vars_into (ctx->block_vars, child_fn);
15184 record_vars_into (gimple_bind_vars (tgt_bind), child_fn);
15185 }
15186
15187 olist = NULL;
15188 ilist = NULL;
15189 if (ctx->record_type)
15190 {
15191 ctx->sender_decl
15192 = create_tmp_var (ctx->record_type, ".omp_data_arr");
15193 DECL_NAMELESS (ctx->sender_decl) = 1;
15194 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
15195 t = make_tree_vec (3);
15196 TREE_VEC_ELT (t, 0) = ctx->sender_decl;
15197 TREE_VEC_ELT (t, 1)
15198 = create_tmp_var (build_array_type_nelts (size_type_node, map_cnt),
15199 ".omp_data_sizes");
15200 DECL_NAMELESS (TREE_VEC_ELT (t, 1)) = 1;
15201 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 1)) = 1;
15202 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 1;
d9a6bd32
JJ
15203 tree tkind_type = short_unsigned_type_node;
15204 int talign_shift = 8;
acf0174b 15205 TREE_VEC_ELT (t, 2)
41dbbb37 15206 = create_tmp_var (build_array_type_nelts (tkind_type, map_cnt),
acf0174b
JJ
15207 ".omp_data_kinds");
15208 DECL_NAMELESS (TREE_VEC_ELT (t, 2)) = 1;
15209 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 2)) = 1;
15210 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 1;
15211 gimple_omp_target_set_data_arg (stmt, t);
15212
15213 vec<constructor_elt, va_gc> *vsize;
15214 vec<constructor_elt, va_gc> *vkind;
15215 vec_alloc (vsize, map_cnt);
15216 vec_alloc (vkind, map_cnt);
15217 unsigned int map_idx = 0;
15218
15219 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
15220 switch (OMP_CLAUSE_CODE (c))
15221 {
d9a6bd32
JJ
15222 tree ovar, nc, s, purpose, var, x, type;
15223 unsigned int talign;
acf0174b
JJ
15224
15225 default:
15226 break;
182190f2 15227
acf0174b
JJ
15228 case OMP_CLAUSE_MAP:
15229 case OMP_CLAUSE_TO:
15230 case OMP_CLAUSE_FROM:
182190f2 15231 oacc_firstprivate_map:
acf0174b
JJ
15232 nc = c;
15233 ovar = OMP_CLAUSE_DECL (c);
d9a6bd32 15234 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
e01d41e5
JJ
15235 && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
15236 || (OMP_CLAUSE_MAP_KIND (c)
15237 == GOMP_MAP_FIRSTPRIVATE_REFERENCE)))
d9a6bd32 15238 break;
acf0174b
JJ
15239 if (!DECL_P (ovar))
15240 {
15241 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
15242 && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
15243 {
15244 gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c))
15245 == get_base_address (ovar));
15246 nc = OMP_CLAUSE_CHAIN (c);
15247 ovar = OMP_CLAUSE_DECL (nc);
15248 }
15249 else
15250 {
15251 tree x = build_sender_ref (ovar, ctx);
15252 tree v
15253 = build_fold_addr_expr_with_type (ovar, ptr_type_node);
15254 gimplify_assign (x, v, &ilist);
15255 nc = NULL_TREE;
15256 }
15257 }
15258 else
15259 {
15260 if (DECL_SIZE (ovar)
15261 && TREE_CODE (DECL_SIZE (ovar)) != INTEGER_CST)
15262 {
15263 tree ovar2 = DECL_VALUE_EXPR (ovar);
15264 gcc_assert (TREE_CODE (ovar2) == INDIRECT_REF);
15265 ovar2 = TREE_OPERAND (ovar2, 0);
15266 gcc_assert (DECL_P (ovar2));
15267 ovar = ovar2;
15268 }
e01d41e5 15269 if (!maybe_lookup_field (ovar, ctx))
acf0174b
JJ
15270 continue;
15271 }
15272
d9a6bd32 15273 talign = TYPE_ALIGN_UNIT (TREE_TYPE (ovar));
0fe81a0f
JJ
15274 if (DECL_P (ovar) && DECL_ALIGN_UNIT (ovar) > talign)
15275 talign = DECL_ALIGN_UNIT (ovar);
acf0174b
JJ
15276 if (nc)
15277 {
d9a6bd32 15278 var = lookup_decl_in_outer_ctx (ovar, ctx);
e01d41e5 15279 x = build_sender_ref (ovar, ctx);
b76e9910
NS
15280
15281 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
182190f2
NS
15282 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
15283 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
15284 && TREE_CODE (TREE_TYPE (ovar)) == ARRAY_TYPE)
acf0174b 15285 {
41dbbb37 15286 gcc_assert (offloaded);
acf0174b 15287 tree avar
b731b390 15288 = create_tmp_var (TREE_TYPE (TREE_TYPE (x)));
acf0174b
JJ
15289 mark_addressable (avar);
15290 gimplify_assign (avar, build_fold_addr_expr (var), &ilist);
0fe81a0f 15291 talign = DECL_ALIGN_UNIT (avar);
acf0174b
JJ
15292 avar = build_fold_addr_expr (avar);
15293 gimplify_assign (x, avar, &ilist);
15294 }
182190f2
NS
15295 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
15296 {
15297 gcc_assert (is_gimple_omp_oacc (ctx->stmt));
15298 if (!is_reference (var))
15299 var = build_fold_addr_expr (var);
15300 else
15301 talign = TYPE_ALIGN_UNIT (TREE_TYPE (TREE_TYPE (ovar)));
15302 gimplify_assign (x, var, &ilist);
15303 }
acf0174b
JJ
15304 else if (is_gimple_reg (var))
15305 {
41dbbb37 15306 gcc_assert (offloaded);
b731b390 15307 tree avar = create_tmp_var (TREE_TYPE (var));
acf0174b 15308 mark_addressable (avar);
41dbbb37
TS
15309 enum gomp_map_kind map_kind = OMP_CLAUSE_MAP_KIND (c);
15310 if (GOMP_MAP_COPY_TO_P (map_kind)
15311 || map_kind == GOMP_MAP_POINTER
15312 || map_kind == GOMP_MAP_TO_PSET
15313 || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
acf0174b
JJ
15314 gimplify_assign (avar, var, &ilist);
15315 avar = build_fold_addr_expr (avar);
15316 gimplify_assign (x, avar, &ilist);
41dbbb37
TS
15317 if ((GOMP_MAP_COPY_FROM_P (map_kind)
15318 || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
acf0174b
JJ
15319 && !TYPE_READONLY (TREE_TYPE (var)))
15320 {
d9a6bd32 15321 x = unshare_expr (x);
acf0174b
JJ
15322 x = build_simple_mem_ref (x);
15323 gimplify_assign (var, x, &olist);
15324 }
15325 }
15326 else
15327 {
15328 var = build_fold_addr_expr (var);
15329 gimplify_assign (x, var, &ilist);
15330 }
15331 }
182190f2
NS
15332 s = NULL_TREE;
15333 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
15334 {
15335 gcc_checking_assert (is_gimple_omp_oacc (ctx->stmt));
15336 s = TREE_TYPE (ovar);
15337 if (TREE_CODE (s) == REFERENCE_TYPE)
15338 s = TREE_TYPE (s);
15339 s = TYPE_SIZE_UNIT (s);
15340 }
15341 else
15342 s = OMP_CLAUSE_SIZE (c);
acf0174b
JJ
15343 if (s == NULL_TREE)
15344 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
15345 s = fold_convert (size_type_node, s);
d9a6bd32 15346 purpose = size_int (map_idx++);
acf0174b
JJ
15347 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
15348 if (TREE_CODE (s) != INTEGER_CST)
15349 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
15350
d9a6bd32 15351 unsigned HOST_WIDE_INT tkind, tkind_zero;
acf0174b
JJ
15352 switch (OMP_CLAUSE_CODE (c))
15353 {
15354 case OMP_CLAUSE_MAP:
15355 tkind = OMP_CLAUSE_MAP_KIND (c);
d9a6bd32
JJ
15356 tkind_zero = tkind;
15357 if (OMP_CLAUSE_MAP_MAYBE_ZERO_LENGTH_ARRAY_SECTION (c))
15358 switch (tkind)
15359 {
15360 case GOMP_MAP_ALLOC:
15361 case GOMP_MAP_TO:
15362 case GOMP_MAP_FROM:
15363 case GOMP_MAP_TOFROM:
15364 case GOMP_MAP_ALWAYS_TO:
15365 case GOMP_MAP_ALWAYS_FROM:
15366 case GOMP_MAP_ALWAYS_TOFROM:
15367 case GOMP_MAP_RELEASE:
15368 tkind_zero = GOMP_MAP_ZERO_LEN_ARRAY_SECTION;
15369 break;
15370 case GOMP_MAP_DELETE:
15371 tkind_zero = GOMP_MAP_DELETE_ZERO_LEN_ARRAY_SECTION;
15372 default:
15373 break;
15374 }
15375 if (tkind_zero != tkind)
15376 {
15377 if (integer_zerop (s))
15378 tkind = tkind_zero;
15379 else if (integer_nonzerop (s))
15380 tkind_zero = tkind;
15381 }
acf0174b 15382 break;
182190f2
NS
15383 case OMP_CLAUSE_FIRSTPRIVATE:
15384 gcc_checking_assert (is_gimple_omp_oacc (ctx->stmt));
15385 tkind = GOMP_MAP_TO;
15386 tkind_zero = tkind;
15387 break;
acf0174b 15388 case OMP_CLAUSE_TO:
41dbbb37 15389 tkind = GOMP_MAP_TO;
d9a6bd32 15390 tkind_zero = tkind;
acf0174b
JJ
15391 break;
15392 case OMP_CLAUSE_FROM:
41dbbb37 15393 tkind = GOMP_MAP_FROM;
d9a6bd32 15394 tkind_zero = tkind;
acf0174b
JJ
15395 break;
15396 default:
15397 gcc_unreachable ();
15398 }
41dbbb37
TS
15399 gcc_checking_assert (tkind
15400 < (HOST_WIDE_INT_C (1U) << talign_shift));
d9a6bd32
JJ
15401 gcc_checking_assert (tkind_zero
15402 < (HOST_WIDE_INT_C (1U) << talign_shift));
acf0174b 15403 talign = ceil_log2 (talign);
41dbbb37 15404 tkind |= talign << talign_shift;
d9a6bd32 15405 tkind_zero |= talign << talign_shift;
41dbbb37
TS
15406 gcc_checking_assert (tkind
15407 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
d9a6bd32
JJ
15408 gcc_checking_assert (tkind_zero
15409 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
15410 if (tkind == tkind_zero)
15411 x = build_int_cstu (tkind_type, tkind);
15412 else
15413 {
15414 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 0;
15415 x = build3 (COND_EXPR, tkind_type,
15416 fold_build2 (EQ_EXPR, boolean_type_node,
15417 unshare_expr (s), size_zero_node),
15418 build_int_cstu (tkind_type, tkind_zero),
15419 build_int_cstu (tkind_type, tkind));
15420 }
15421 CONSTRUCTOR_APPEND_ELT (vkind, purpose, x);
acf0174b
JJ
15422 if (nc && nc != c)
15423 c = nc;
d9a6bd32
JJ
15424 break;
15425
15426 case OMP_CLAUSE_FIRSTPRIVATE:
182190f2
NS
15427 if (is_oacc_parallel (ctx))
15428 goto oacc_firstprivate_map;
d9a6bd32
JJ
15429 ovar = OMP_CLAUSE_DECL (c);
15430 if (is_reference (ovar))
15431 talign = TYPE_ALIGN_UNIT (TREE_TYPE (TREE_TYPE (ovar)));
15432 else
15433 talign = DECL_ALIGN_UNIT (ovar);
15434 var = lookup_decl_in_outer_ctx (ovar, ctx);
15435 x = build_sender_ref (ovar, ctx);
15436 tkind = GOMP_MAP_FIRSTPRIVATE;
15437 type = TREE_TYPE (ovar);
15438 if (is_reference (ovar))
15439 type = TREE_TYPE (type);
15440 bool use_firstprivate_int, force_addr;
15441 use_firstprivate_int = false;
15442 force_addr = false;
15443 if ((INTEGRAL_TYPE_P (type)
15444 && TYPE_PRECISION (type) <= POINTER_SIZE)
15445 || TREE_CODE (type) == POINTER_TYPE)
15446 use_firstprivate_int = true;
15447 if (has_depend)
15448 {
15449 if (is_reference (var))
15450 use_firstprivate_int = false;
15451 else if (is_gimple_reg (var))
15452 {
15453 if (DECL_HAS_VALUE_EXPR_P (var))
15454 {
15455 tree v = get_base_address (var);
15456 if (DECL_P (v) && TREE_ADDRESSABLE (v))
15457 {
15458 use_firstprivate_int = false;
15459 force_addr = true;
15460 }
15461 else
15462 switch (TREE_CODE (v))
15463 {
15464 case INDIRECT_REF:
15465 case MEM_REF:
15466 use_firstprivate_int = false;
15467 force_addr = true;
15468 break;
15469 default:
15470 break;
15471 }
15472 }
15473 }
15474 else
15475 use_firstprivate_int = false;
15476 }
15477 if (use_firstprivate_int)
15478 {
15479 tkind = GOMP_MAP_FIRSTPRIVATE_INT;
15480 tree t = var;
15481 if (is_reference (var))
15482 t = build_simple_mem_ref (var);
15483 if (TREE_CODE (type) != POINTER_TYPE)
15484 t = fold_convert (pointer_sized_int_node, t);
15485 t = fold_convert (TREE_TYPE (x), t);
15486 gimplify_assign (x, t, &ilist);
15487 }
15488 else if (is_reference (var))
15489 gimplify_assign (x, var, &ilist);
15490 else if (!force_addr && is_gimple_reg (var))
15491 {
15492 tree avar = create_tmp_var (TREE_TYPE (var));
15493 mark_addressable (avar);
15494 gimplify_assign (avar, var, &ilist);
15495 avar = build_fold_addr_expr (avar);
15496 gimplify_assign (x, avar, &ilist);
15497 }
15498 else
15499 {
15500 var = build_fold_addr_expr (var);
15501 gimplify_assign (x, var, &ilist);
15502 }
15503 if (tkind == GOMP_MAP_FIRSTPRIVATE_INT)
15504 s = size_int (0);
15505 else if (is_reference (var))
15506 s = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (ovar)));
15507 else
15508 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
15509 s = fold_convert (size_type_node, s);
15510 purpose = size_int (map_idx++);
15511 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
15512 if (TREE_CODE (s) != INTEGER_CST)
15513 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
15514
15515 gcc_checking_assert (tkind
15516 < (HOST_WIDE_INT_C (1U) << talign_shift));
15517 talign = ceil_log2 (talign);
15518 tkind |= talign << talign_shift;
15519 gcc_checking_assert (tkind
15520 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
15521 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
15522 build_int_cstu (tkind_type, tkind));
15523 break;
15524
15525 case OMP_CLAUSE_USE_DEVICE_PTR:
15526 case OMP_CLAUSE_IS_DEVICE_PTR:
15527 ovar = OMP_CLAUSE_DECL (c);
15528 var = lookup_decl_in_outer_ctx (ovar, ctx);
15529 x = build_sender_ref (ovar, ctx);
15530 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_PTR)
15531 tkind = GOMP_MAP_USE_DEVICE_PTR;
15532 else
15533 tkind = GOMP_MAP_FIRSTPRIVATE_INT;
15534 type = TREE_TYPE (ovar);
15535 if (TREE_CODE (type) == ARRAY_TYPE)
15536 var = build_fold_addr_expr (var);
15537 else
15538 {
15539 if (is_reference (ovar))
15540 {
15541 type = TREE_TYPE (type);
15542 if (TREE_CODE (type) != ARRAY_TYPE)
15543 var = build_simple_mem_ref (var);
15544 var = fold_convert (TREE_TYPE (x), var);
15545 }
15546 }
15547 gimplify_assign (x, var, &ilist);
15548 s = size_int (0);
15549 purpose = size_int (map_idx++);
15550 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
15551 gcc_checking_assert (tkind
15552 < (HOST_WIDE_INT_C (1U) << talign_shift));
15553 gcc_checking_assert (tkind
15554 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
15555 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
15556 build_int_cstu (tkind_type, tkind));
15557 break;
acf0174b
JJ
15558 }
15559
15560 gcc_assert (map_idx == map_cnt);
15561
15562 DECL_INITIAL (TREE_VEC_ELT (t, 1))
15563 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)), vsize);
15564 DECL_INITIAL (TREE_VEC_ELT (t, 2))
15565 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 2)), vkind);
d9a6bd32
JJ
15566 for (int i = 1; i <= 2; i++)
15567 if (!TREE_STATIC (TREE_VEC_ELT (t, i)))
15568 {
15569 gimple_seq initlist = NULL;
15570 force_gimple_operand (build1 (DECL_EXPR, void_type_node,
15571 TREE_VEC_ELT (t, i)),
15572 &initlist, true, NULL_TREE);
15573 gimple_seq_add_seq (&ilist, initlist);
15574
15575 tree clobber = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, i)),
15576 NULL);
15577 TREE_THIS_VOLATILE (clobber) = 1;
15578 gimple_seq_add_stmt (&olist,
15579 gimple_build_assign (TREE_VEC_ELT (t, i),
15580 clobber));
15581 }
acf0174b
JJ
15582
15583 tree clobber = build_constructor (ctx->record_type, NULL);
15584 TREE_THIS_VOLATILE (clobber) = 1;
15585 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
15586 clobber));
15587 }
15588
15589 /* Once all the expansions are done, sequence all the different
15590 fragments inside gimple_omp_body. */
15591
15592 new_body = NULL;
15593
41dbbb37
TS
15594 if (offloaded
15595 && ctx->record_type)
acf0174b
JJ
15596 {
15597 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
15598 /* fixup_child_record_type might have changed receiver_decl's type. */
15599 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
15600 gimple_seq_add_stmt (&new_body,
15601 gimple_build_assign (ctx->receiver_decl, t));
15602 }
182190f2 15603 gimple_seq_add_seq (&new_body, fplist);
acf0174b 15604
d9a6bd32 15605 if (offloaded || data_region)
acf0174b 15606 {
d9a6bd32
JJ
15607 tree prev = NULL_TREE;
15608 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
15609 switch (OMP_CLAUSE_CODE (c))
15610 {
15611 tree var, x;
15612 default:
15613 break;
15614 case OMP_CLAUSE_FIRSTPRIVATE:
182190f2
NS
15615 if (is_gimple_omp_oacc (ctx->stmt))
15616 break;
d9a6bd32
JJ
15617 var = OMP_CLAUSE_DECL (c);
15618 if (is_reference (var)
15619 || is_gimple_reg_type (TREE_TYPE (var)))
15620 {
15621 tree new_var = lookup_decl (var, ctx);
15622 tree type;
15623 type = TREE_TYPE (var);
15624 if (is_reference (var))
15625 type = TREE_TYPE (type);
15626 bool use_firstprivate_int;
15627 use_firstprivate_int = false;
15628 if ((INTEGRAL_TYPE_P (type)
15629 && TYPE_PRECISION (type) <= POINTER_SIZE)
15630 || TREE_CODE (type) == POINTER_TYPE)
15631 use_firstprivate_int = true;
15632 if (has_depend)
15633 {
15634 tree v = lookup_decl_in_outer_ctx (var, ctx);
15635 if (is_reference (v))
15636 use_firstprivate_int = false;
15637 else if (is_gimple_reg (v))
15638 {
15639 if (DECL_HAS_VALUE_EXPR_P (v))
15640 {
15641 v = get_base_address (v);
15642 if (DECL_P (v) && TREE_ADDRESSABLE (v))
15643 use_firstprivate_int = false;
15644 else
15645 switch (TREE_CODE (v))
15646 {
15647 case INDIRECT_REF:
15648 case MEM_REF:
15649 use_firstprivate_int = false;
15650 break;
15651 default:
15652 break;
15653 }
15654 }
15655 }
15656 else
15657 use_firstprivate_int = false;
15658 }
15659 if (use_firstprivate_int)
15660 {
15661 x = build_receiver_ref (var, false, ctx);
15662 if (TREE_CODE (type) != POINTER_TYPE)
15663 x = fold_convert (pointer_sized_int_node, x);
15664 x = fold_convert (type, x);
15665 gimplify_expr (&x, &new_body, NULL, is_gimple_val,
15666 fb_rvalue);
15667 if (is_reference (var))
15668 {
15669 tree v = create_tmp_var_raw (type, get_name (var));
15670 gimple_add_tmp_var (v);
15671 TREE_ADDRESSABLE (v) = 1;
15672 gimple_seq_add_stmt (&new_body,
15673 gimple_build_assign (v, x));
15674 x = build_fold_addr_expr (v);
15675 }
15676 gimple_seq_add_stmt (&new_body,
15677 gimple_build_assign (new_var, x));
15678 }
15679 else
15680 {
15681 x = build_receiver_ref (var, !is_reference (var), ctx);
15682 gimplify_expr (&x, &new_body, NULL, is_gimple_val,
15683 fb_rvalue);
15684 gimple_seq_add_stmt (&new_body,
15685 gimple_build_assign (new_var, x));
15686 }
15687 }
15688 else if (is_variable_sized (var))
15689 {
15690 tree pvar = DECL_VALUE_EXPR (var);
15691 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15692 pvar = TREE_OPERAND (pvar, 0);
15693 gcc_assert (DECL_P (pvar));
15694 tree new_var = lookup_decl (pvar, ctx);
15695 x = build_receiver_ref (var, false, ctx);
15696 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
15697 gimple_seq_add_stmt (&new_body,
15698 gimple_build_assign (new_var, x));
15699 }
15700 break;
15701 case OMP_CLAUSE_PRIVATE:
182190f2
NS
15702 if (is_gimple_omp_oacc (ctx->stmt))
15703 break;
d9a6bd32
JJ
15704 var = OMP_CLAUSE_DECL (c);
15705 if (is_reference (var))
15706 {
15707 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
15708 tree new_var = lookup_decl (var, ctx);
15709 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
15710 if (TREE_CONSTANT (x))
15711 {
15712 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
15713 get_name (var));
15714 gimple_add_tmp_var (x);
15715 TREE_ADDRESSABLE (x) = 1;
15716 x = build_fold_addr_expr_loc (clause_loc, x);
15717 }
15718 else
15719 {
15720 tree atmp
15721 = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
15722 tree rtype = TREE_TYPE (TREE_TYPE (new_var));
15723 tree al = size_int (TYPE_ALIGN (rtype));
15724 x = build_call_expr_loc (clause_loc, atmp, 2, x, al);
15725 }
15726
15727 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
15728 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
15729 gimple_seq_add_stmt (&new_body,
15730 gimple_build_assign (new_var, x));
15731 }
15732 break;
15733 case OMP_CLAUSE_USE_DEVICE_PTR:
15734 case OMP_CLAUSE_IS_DEVICE_PTR:
15735 var = OMP_CLAUSE_DECL (c);
15736 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_PTR)
15737 x = build_sender_ref (var, ctx);
15738 else
15739 x = build_receiver_ref (var, false, ctx);
15740 if (is_variable_sized (var))
15741 {
15742 tree pvar = DECL_VALUE_EXPR (var);
15743 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15744 pvar = TREE_OPERAND (pvar, 0);
15745 gcc_assert (DECL_P (pvar));
15746 tree new_var = lookup_decl (pvar, ctx);
15747 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
15748 gimple_seq_add_stmt (&new_body,
15749 gimple_build_assign (new_var, x));
15750 }
15751 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
15752 {
15753 tree new_var = lookup_decl (var, ctx);
15754 new_var = DECL_VALUE_EXPR (new_var);
15755 gcc_assert (TREE_CODE (new_var) == MEM_REF);
15756 new_var = TREE_OPERAND (new_var, 0);
15757 gcc_assert (DECL_P (new_var));
15758 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
15759 gimple_seq_add_stmt (&new_body,
15760 gimple_build_assign (new_var, x));
15761 }
15762 else
15763 {
15764 tree type = TREE_TYPE (var);
15765 tree new_var = lookup_decl (var, ctx);
15766 if (is_reference (var))
15767 {
15768 type = TREE_TYPE (type);
15769 if (TREE_CODE (type) != ARRAY_TYPE)
15770 {
15771 tree v = create_tmp_var_raw (type, get_name (var));
15772 gimple_add_tmp_var (v);
15773 TREE_ADDRESSABLE (v) = 1;
15774 x = fold_convert (type, x);
15775 gimplify_expr (&x, &new_body, NULL, is_gimple_val,
15776 fb_rvalue);
15777 gimple_seq_add_stmt (&new_body,
15778 gimple_build_assign (v, x));
15779 x = build_fold_addr_expr (v);
15780 }
15781 }
15782 x = fold_convert (TREE_TYPE (new_var), x);
15783 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
15784 gimple_seq_add_stmt (&new_body,
15785 gimple_build_assign (new_var, x));
15786 }
15787 break;
15788 }
e01d41e5 15789 /* Handle GOMP_MAP_FIRSTPRIVATE_{POINTER,REFERENCE} in second pass,
d9a6bd32
JJ
15790 so that firstprivate vars holding OMP_CLAUSE_SIZE if needed
15791 are already handled. */
182190f2 15792 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
d9a6bd32
JJ
15793 switch (OMP_CLAUSE_CODE (c))
15794 {
15795 tree var;
15796 default:
15797 break;
15798 case OMP_CLAUSE_MAP:
e01d41e5
JJ
15799 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
15800 || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_REFERENCE)
d9a6bd32
JJ
15801 {
15802 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
15803 HOST_WIDE_INT offset = 0;
15804 gcc_assert (prev);
15805 var = OMP_CLAUSE_DECL (c);
15806 if (DECL_P (var)
15807 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
15808 && is_global_var (maybe_lookup_decl_in_outer_ctx (var,
15809 ctx))
15810 && varpool_node::get_create (var)->offloadable)
15811 break;
15812 if (TREE_CODE (var) == INDIRECT_REF
15813 && TREE_CODE (TREE_OPERAND (var, 0)) == COMPONENT_REF)
15814 var = TREE_OPERAND (var, 0);
15815 if (TREE_CODE (var) == COMPONENT_REF)
15816 {
15817 var = get_addr_base_and_unit_offset (var, &offset);
15818 gcc_assert (var != NULL_TREE && DECL_P (var));
15819 }
15820 else if (DECL_SIZE (var)
15821 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
15822 {
15823 tree var2 = DECL_VALUE_EXPR (var);
15824 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
15825 var2 = TREE_OPERAND (var2, 0);
15826 gcc_assert (DECL_P (var2));
15827 var = var2;
15828 }
15829 tree new_var = lookup_decl (var, ctx), x;
15830 tree type = TREE_TYPE (new_var);
15831 bool is_ref;
15832 if (TREE_CODE (OMP_CLAUSE_DECL (c)) == INDIRECT_REF
15833 && (TREE_CODE (TREE_OPERAND (OMP_CLAUSE_DECL (c), 0))
15834 == COMPONENT_REF))
15835 {
15836 type = TREE_TYPE (TREE_OPERAND (OMP_CLAUSE_DECL (c), 0));
15837 is_ref = true;
15838 new_var = build2 (MEM_REF, type,
15839 build_fold_addr_expr (new_var),
15840 build_int_cst (build_pointer_type (type),
15841 offset));
15842 }
15843 else if (TREE_CODE (OMP_CLAUSE_DECL (c)) == COMPONENT_REF)
15844 {
15845 type = TREE_TYPE (OMP_CLAUSE_DECL (c));
15846 is_ref = TREE_CODE (type) == REFERENCE_TYPE;
15847 new_var = build2 (MEM_REF, type,
15848 build_fold_addr_expr (new_var),
15849 build_int_cst (build_pointer_type (type),
15850 offset));
15851 }
15852 else
15853 is_ref = is_reference (var);
e01d41e5
JJ
15854 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_REFERENCE)
15855 is_ref = false;
d9a6bd32
JJ
15856 bool ref_to_array = false;
15857 if (is_ref)
15858 {
15859 type = TREE_TYPE (type);
15860 if (TREE_CODE (type) == ARRAY_TYPE)
15861 {
15862 type = build_pointer_type (type);
15863 ref_to_array = true;
15864 }
15865 }
15866 else if (TREE_CODE (type) == ARRAY_TYPE)
15867 {
15868 tree decl2 = DECL_VALUE_EXPR (new_var);
15869 gcc_assert (TREE_CODE (decl2) == MEM_REF);
15870 decl2 = TREE_OPERAND (decl2, 0);
15871 gcc_assert (DECL_P (decl2));
15872 new_var = decl2;
15873 type = TREE_TYPE (new_var);
15874 }
15875 x = build_receiver_ref (OMP_CLAUSE_DECL (prev), false, ctx);
15876 x = fold_convert_loc (clause_loc, type, x);
15877 if (!integer_zerop (OMP_CLAUSE_SIZE (c)))
15878 {
15879 tree bias = OMP_CLAUSE_SIZE (c);
15880 if (DECL_P (bias))
15881 bias = lookup_decl (bias, ctx);
15882 bias = fold_convert_loc (clause_loc, sizetype, bias);
15883 bias = fold_build1_loc (clause_loc, NEGATE_EXPR, sizetype,
15884 bias);
15885 x = fold_build2_loc (clause_loc, POINTER_PLUS_EXPR,
15886 TREE_TYPE (x), x, bias);
15887 }
15888 if (ref_to_array)
15889 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
15890 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
15891 if (is_ref && !ref_to_array)
15892 {
15893 tree t = create_tmp_var_raw (type, get_name (var));
15894 gimple_add_tmp_var (t);
15895 TREE_ADDRESSABLE (t) = 1;
15896 gimple_seq_add_stmt (&new_body,
15897 gimple_build_assign (t, x));
15898 x = build_fold_addr_expr_loc (clause_loc, t);
15899 }
15900 gimple_seq_add_stmt (&new_body,
15901 gimple_build_assign (new_var, x));
15902 prev = NULL_TREE;
15903 }
15904 else if (OMP_CLAUSE_CHAIN (c)
15905 && OMP_CLAUSE_CODE (OMP_CLAUSE_CHAIN (c))
15906 == OMP_CLAUSE_MAP
e01d41e5
JJ
15907 && (OMP_CLAUSE_MAP_KIND (OMP_CLAUSE_CHAIN (c))
15908 == GOMP_MAP_FIRSTPRIVATE_POINTER
15909 || (OMP_CLAUSE_MAP_KIND (OMP_CLAUSE_CHAIN (c))
15910 == GOMP_MAP_FIRSTPRIVATE_REFERENCE)))
d9a6bd32
JJ
15911 prev = c;
15912 break;
15913 case OMP_CLAUSE_PRIVATE:
15914 var = OMP_CLAUSE_DECL (c);
15915 if (is_variable_sized (var))
15916 {
15917 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
15918 tree new_var = lookup_decl (var, ctx);
15919 tree pvar = DECL_VALUE_EXPR (var);
15920 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15921 pvar = TREE_OPERAND (pvar, 0);
15922 gcc_assert (DECL_P (pvar));
15923 tree new_pvar = lookup_decl (pvar, ctx);
15924 tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
15925 tree al = size_int (DECL_ALIGN (var));
15926 tree x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
15927 x = build_call_expr_loc (clause_loc, atmp, 2, x, al);
15928 x = fold_convert_loc (clause_loc, TREE_TYPE (new_pvar), x);
15929 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
15930 gimple_seq_add_stmt (&new_body,
15931 gimple_build_assign (new_pvar, x));
15932 }
15933 break;
15934 }
68249442 15935
e5014671
NS
15936 gimple_seq fork_seq = NULL;
15937 gimple_seq join_seq = NULL;
15938
15939 if (is_oacc_parallel (ctx))
15940 {
15941 /* If there are reductions on the offloaded region itself, treat
15942 them as a dummy GANG loop. */
15943 tree level = build_int_cst (integer_type_node, GOMP_DIM_GANG);
15944
15945 lower_oacc_reductions (gimple_location (ctx->stmt), clauses, level,
15946 false, NULL, NULL, &fork_seq, &join_seq, ctx);
15947 }
15948
15949 gimple_seq_add_seq (&new_body, fork_seq);
acf0174b 15950 gimple_seq_add_seq (&new_body, tgt_body);
e5014671 15951 gimple_seq_add_seq (&new_body, join_seq);
68249442 15952
d9a6bd32
JJ
15953 if (offloaded)
15954 new_body = maybe_catch_exception (new_body);
68249442 15955
acf0174b
JJ
15956 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
15957 gimple_omp_set_body (stmt, new_body);
15958 }
15959
15960 bind = gimple_build_bind (NULL, NULL,
15961 tgt_bind ? gimple_bind_block (tgt_bind)
15962 : NULL_TREE);
d9a6bd32 15963 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
355a7673
MM
15964 gimple_bind_add_seq (bind, ilist);
15965 gimple_bind_add_stmt (bind, stmt);
15966 gimple_bind_add_seq (bind, olist);
50674e96 15967
726a989a 15968 pop_gimplify_context (NULL);
d9a6bd32
JJ
15969
15970 if (dep_bind)
15971 {
15972 gimple_bind_add_seq (dep_bind, dep_ilist);
15973 gimple_bind_add_stmt (dep_bind, bind);
15974 gimple_bind_add_seq (dep_bind, dep_olist);
15975 pop_gimplify_context (dep_bind);
15976 }
50674e96
DN
15977}
15978
acf0174b
JJ
15979/* Expand code for an OpenMP teams directive. */
15980
15981static void
15982lower_omp_teams (gimple_stmt_iterator *gsi_p, omp_context *ctx)
15983{
538dd0b7 15984 gomp_teams *teams_stmt = as_a <gomp_teams *> (gsi_stmt (*gsi_p));
45852dcc 15985 push_gimplify_context ();
acf0174b
JJ
15986
15987 tree block = make_node (BLOCK);
538dd0b7 15988 gbind *bind = gimple_build_bind (NULL, NULL, block);
acf0174b
JJ
15989 gsi_replace (gsi_p, bind, true);
15990 gimple_seq bind_body = NULL;
15991 gimple_seq dlist = NULL;
15992 gimple_seq olist = NULL;
15993
15994 tree num_teams = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
15995 OMP_CLAUSE_NUM_TEAMS);
15996 if (num_teams == NULL_TREE)
15997 num_teams = build_int_cst (unsigned_type_node, 0);
15998 else
15999 {
16000 num_teams = OMP_CLAUSE_NUM_TEAMS_EXPR (num_teams);
16001 num_teams = fold_convert (unsigned_type_node, num_teams);
16002 gimplify_expr (&num_teams, &bind_body, NULL, is_gimple_val, fb_rvalue);
16003 }
16004 tree thread_limit = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
16005 OMP_CLAUSE_THREAD_LIMIT);
16006 if (thread_limit == NULL_TREE)
16007 thread_limit = build_int_cst (unsigned_type_node, 0);
16008 else
16009 {
16010 thread_limit = OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit);
16011 thread_limit = fold_convert (unsigned_type_node, thread_limit);
16012 gimplify_expr (&thread_limit, &bind_body, NULL, is_gimple_val,
16013 fb_rvalue);
16014 }
16015
16016 lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt),
16017 &bind_body, &dlist, ctx, NULL);
16018 lower_omp (gimple_omp_body_ptr (teams_stmt), ctx);
16019 lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt), &olist, ctx);
16020 gimple_seq_add_stmt (&bind_body, teams_stmt);
16021
16022 location_t loc = gimple_location (teams_stmt);
16023 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TEAMS);
355fe088 16024 gimple *call = gimple_build_call (decl, 2, num_teams, thread_limit);
acf0174b
JJ
16025 gimple_set_location (call, loc);
16026 gimple_seq_add_stmt (&bind_body, call);
16027
16028 gimple_seq_add_seq (&bind_body, gimple_omp_body (teams_stmt));
16029 gimple_omp_set_body (teams_stmt, NULL);
16030 gimple_seq_add_seq (&bind_body, olist);
16031 gimple_seq_add_seq (&bind_body, dlist);
16032 gimple_seq_add_stmt (&bind_body, gimple_build_omp_return (true));
16033 gimple_bind_set_body (bind, bind_body);
16034
16035 pop_gimplify_context (bind);
16036
16037 gimple_bind_append_vars (bind, ctx->block_vars);
16038 BLOCK_VARS (block) = ctx->block_vars;
16039 if (BLOCK_VARS (block))
16040 TREE_USED (block) = 1;
16041}
16042
16043
d0fb20be 16044/* Callback for lower_omp_1. Return non-NULL if *tp needs to be
726a989a 16045 regimplified. If DATA is non-NULL, lower_omp_1 is outside
41dbbb37 16046 of OMP context, but with task_shared_vars set. */
75a4c3c1
AP
16047
16048static tree
726a989a
RB
16049lower_omp_regimplify_p (tree *tp, int *walk_subtrees,
16050 void *data)
75a4c3c1 16051{
d0fb20be 16052 tree t = *tp;
75a4c3c1 16053
d0fb20be 16054 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
726a989a 16055 if (TREE_CODE (t) == VAR_DECL && data == NULL && DECL_HAS_VALUE_EXPR_P (t))
b826efd9
JJ
16056 return t;
16057
16058 if (task_shared_vars
16059 && DECL_P (t)
16060 && bitmap_bit_p (task_shared_vars, DECL_UID (t)))
d0fb20be 16061 return t;
75a4c3c1 16062
d0fb20be
JJ
16063 /* If a global variable has been privatized, TREE_CONSTANT on
16064 ADDR_EXPR might be wrong. */
726a989a 16065 if (data == NULL && TREE_CODE (t) == ADDR_EXPR)
d0fb20be 16066 recompute_tree_invariant_for_addr_expr (t);
75a4c3c1 16067
d9a6bd32
JJ
16068 *walk_subtrees = !IS_TYPE_OR_DECL_P (t);
16069 return NULL_TREE;
16070}
16071
16072/* Data to be communicated between lower_omp_regimplify_operands and
16073 lower_omp_regimplify_operands_p. */
16074
16075struct lower_omp_regimplify_operands_data
16076{
16077 omp_context *ctx;
16078 vec<tree> *decls;
16079};
16080
16081/* Helper function for lower_omp_regimplify_operands. Find
16082 omp_member_access_dummy_var vars and adjust temporarily their
16083 DECL_VALUE_EXPRs if needed. */
16084
16085static tree
16086lower_omp_regimplify_operands_p (tree *tp, int *walk_subtrees,
16087 void *data)
16088{
16089 tree t = omp_member_access_dummy_var (*tp);
16090 if (t)
16091 {
16092 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
16093 lower_omp_regimplify_operands_data *ldata
16094 = (lower_omp_regimplify_operands_data *) wi->info;
16095 tree o = maybe_lookup_decl (t, ldata->ctx);
16096 if (o != t)
16097 {
16098 ldata->decls->safe_push (DECL_VALUE_EXPR (*tp));
16099 ldata->decls->safe_push (*tp);
16100 tree v = unshare_and_remap (DECL_VALUE_EXPR (*tp), t, o);
16101 SET_DECL_VALUE_EXPR (*tp, v);
16102 }
16103 }
16104 *walk_subtrees = !IS_TYPE_OR_DECL_P (*tp);
d0fb20be 16105 return NULL_TREE;
75a4c3c1 16106}
50674e96 16107
d9a6bd32
JJ
16108/* Wrapper around gimple_regimplify_operands that adjusts DECL_VALUE_EXPRs
16109 of omp_member_access_dummy_var vars during regimplification. */
16110
16111static void
16112lower_omp_regimplify_operands (omp_context *ctx, gimple *stmt,
16113 gimple_stmt_iterator *gsi_p)
16114{
16115 auto_vec<tree, 10> decls;
16116 if (ctx)
16117 {
16118 struct walk_stmt_info wi;
16119 memset (&wi, '\0', sizeof (wi));
16120 struct lower_omp_regimplify_operands_data data;
16121 data.ctx = ctx;
16122 data.decls = &decls;
16123 wi.info = &data;
16124 walk_gimple_op (stmt, lower_omp_regimplify_operands_p, &wi);
16125 }
16126 gimple_regimplify_operands (stmt, gsi_p);
16127 while (!decls.is_empty ())
16128 {
16129 tree t = decls.pop ();
16130 tree v = decls.pop ();
16131 SET_DECL_VALUE_EXPR (t, v);
16132 }
16133}
16134
d0fb20be 16135static void
726a989a 16136lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
953ff289 16137{
355fe088 16138 gimple *stmt = gsi_stmt (*gsi_p);
726a989a 16139 struct walk_stmt_info wi;
538dd0b7 16140 gcall *call_stmt;
953ff289 16141
726a989a
RB
16142 if (gimple_has_location (stmt))
16143 input_location = gimple_location (stmt);
d0fb20be 16144
726a989a
RB
16145 if (task_shared_vars)
16146 memset (&wi, '\0', sizeof (wi));
d0fb20be 16147
50674e96 16148 /* If we have issued syntax errors, avoid doing any heavy lifting.
41dbbb37 16149 Just replace the OMP directives with a NOP to avoid
50674e96 16150 confusing RTL expansion. */
1da2ed5f 16151 if (seen_error () && is_gimple_omp (stmt))
50674e96 16152 {
726a989a 16153 gsi_replace (gsi_p, gimple_build_nop (), true);
d0fb20be 16154 return;
50674e96
DN
16155 }
16156
726a989a 16157 switch (gimple_code (stmt))
953ff289 16158 {
726a989a 16159 case GIMPLE_COND:
538dd0b7
DM
16160 {
16161 gcond *cond_stmt = as_a <gcond *> (stmt);
16162 if ((ctx || task_shared_vars)
16163 && (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
16164 lower_omp_regimplify_p,
16165 ctx ? NULL : &wi, NULL)
16166 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
16167 lower_omp_regimplify_p,
16168 ctx ? NULL : &wi, NULL)))
d9a6bd32 16169 lower_omp_regimplify_operands (ctx, cond_stmt, gsi_p);
538dd0b7 16170 }
d0fb20be 16171 break;
726a989a 16172 case GIMPLE_CATCH:
538dd0b7 16173 lower_omp (gimple_catch_handler_ptr (as_a <gcatch *> (stmt)), ctx);
d0fb20be 16174 break;
726a989a 16175 case GIMPLE_EH_FILTER:
355a7673 16176 lower_omp (gimple_eh_filter_failure_ptr (stmt), ctx);
d0fb20be 16177 break;
726a989a 16178 case GIMPLE_TRY:
355a7673
MM
16179 lower_omp (gimple_try_eval_ptr (stmt), ctx);
16180 lower_omp (gimple_try_cleanup_ptr (stmt), ctx);
d0fb20be 16181 break;
d88513ea 16182 case GIMPLE_TRANSACTION:
538dd0b7
DM
16183 lower_omp (gimple_transaction_body_ptr (
16184 as_a <gtransaction *> (stmt)),
16185 ctx);
d88513ea 16186 break;
726a989a 16187 case GIMPLE_BIND:
538dd0b7 16188 lower_omp (gimple_bind_body_ptr (as_a <gbind *> (stmt)), ctx);
d0fb20be 16189 break;
726a989a
RB
16190 case GIMPLE_OMP_PARALLEL:
16191 case GIMPLE_OMP_TASK:
16192 ctx = maybe_lookup_ctx (stmt);
acf0174b
JJ
16193 gcc_assert (ctx);
16194 if (ctx->cancellable)
16195 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
726a989a 16196 lower_omp_taskreg (gsi_p, ctx);
d0fb20be 16197 break;
726a989a
RB
16198 case GIMPLE_OMP_FOR:
16199 ctx = maybe_lookup_ctx (stmt);
953ff289 16200 gcc_assert (ctx);
acf0174b
JJ
16201 if (ctx->cancellable)
16202 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
726a989a 16203 lower_omp_for (gsi_p, ctx);
953ff289 16204 break;
726a989a
RB
16205 case GIMPLE_OMP_SECTIONS:
16206 ctx = maybe_lookup_ctx (stmt);
953ff289 16207 gcc_assert (ctx);
acf0174b
JJ
16208 if (ctx->cancellable)
16209 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
726a989a 16210 lower_omp_sections (gsi_p, ctx);
953ff289 16211 break;
726a989a
RB
16212 case GIMPLE_OMP_SINGLE:
16213 ctx = maybe_lookup_ctx (stmt);
953ff289 16214 gcc_assert (ctx);
726a989a 16215 lower_omp_single (gsi_p, ctx);
953ff289 16216 break;
726a989a
RB
16217 case GIMPLE_OMP_MASTER:
16218 ctx = maybe_lookup_ctx (stmt);
953ff289 16219 gcc_assert (ctx);
726a989a 16220 lower_omp_master (gsi_p, ctx);
953ff289 16221 break;
acf0174b
JJ
16222 case GIMPLE_OMP_TASKGROUP:
16223 ctx = maybe_lookup_ctx (stmt);
16224 gcc_assert (ctx);
16225 lower_omp_taskgroup (gsi_p, ctx);
16226 break;
726a989a
RB
16227 case GIMPLE_OMP_ORDERED:
16228 ctx = maybe_lookup_ctx (stmt);
953ff289 16229 gcc_assert (ctx);
726a989a 16230 lower_omp_ordered (gsi_p, ctx);
953ff289 16231 break;
726a989a
RB
16232 case GIMPLE_OMP_CRITICAL:
16233 ctx = maybe_lookup_ctx (stmt);
953ff289 16234 gcc_assert (ctx);
726a989a
RB
16235 lower_omp_critical (gsi_p, ctx);
16236 break;
16237 case GIMPLE_OMP_ATOMIC_LOAD:
16238 if ((ctx || task_shared_vars)
538dd0b7
DM
16239 && walk_tree (gimple_omp_atomic_load_rhs_ptr (
16240 as_a <gomp_atomic_load *> (stmt)),
726a989a 16241 lower_omp_regimplify_p, ctx ? NULL : &wi, NULL))
d9a6bd32 16242 lower_omp_regimplify_operands (ctx, stmt, gsi_p);
953ff289 16243 break;
acf0174b
JJ
16244 case GIMPLE_OMP_TARGET:
16245 ctx = maybe_lookup_ctx (stmt);
16246 gcc_assert (ctx);
16247 lower_omp_target (gsi_p, ctx);
16248 break;
16249 case GIMPLE_OMP_TEAMS:
16250 ctx = maybe_lookup_ctx (stmt);
16251 gcc_assert (ctx);
16252 lower_omp_teams (gsi_p, ctx);
16253 break;
16254 case GIMPLE_CALL:
16255 tree fndecl;
538dd0b7
DM
16256 call_stmt = as_a <gcall *> (stmt);
16257 fndecl = gimple_call_fndecl (call_stmt);
acf0174b
JJ
16258 if (fndecl
16259 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
16260 switch (DECL_FUNCTION_CODE (fndecl))
16261 {
16262 case BUILT_IN_GOMP_BARRIER:
16263 if (ctx == NULL)
16264 break;
16265 /* FALLTHRU */
16266 case BUILT_IN_GOMP_CANCEL:
16267 case BUILT_IN_GOMP_CANCELLATION_POINT:
16268 omp_context *cctx;
16269 cctx = ctx;
16270 if (gimple_code (cctx->stmt) == GIMPLE_OMP_SECTION)
16271 cctx = cctx->outer;
538dd0b7 16272 gcc_assert (gimple_call_lhs (call_stmt) == NULL_TREE);
acf0174b
JJ
16273 if (!cctx->cancellable)
16274 {
16275 if (DECL_FUNCTION_CODE (fndecl)
16276 == BUILT_IN_GOMP_CANCELLATION_POINT)
16277 {
16278 stmt = gimple_build_nop ();
16279 gsi_replace (gsi_p, stmt, false);
16280 }
16281 break;
16282 }
acf0174b
JJ
16283 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
16284 {
16285 fndecl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL);
538dd0b7
DM
16286 gimple_call_set_fndecl (call_stmt, fndecl);
16287 gimple_call_set_fntype (call_stmt, TREE_TYPE (fndecl));
acf0174b 16288 }
dd2fc525 16289 tree lhs;
b731b390 16290 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (fndecl)));
538dd0b7 16291 gimple_call_set_lhs (call_stmt, lhs);
acf0174b
JJ
16292 tree fallthru_label;
16293 fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
355fe088 16294 gimple *g;
acf0174b
JJ
16295 g = gimple_build_label (fallthru_label);
16296 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
dd2fc525
JJ
16297 g = gimple_build_cond (NE_EXPR, lhs,
16298 fold_convert (TREE_TYPE (lhs),
16299 boolean_false_node),
acf0174b
JJ
16300 cctx->cancel_label, fallthru_label);
16301 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
16302 break;
16303 default:
16304 break;
16305 }
16306 /* FALLTHRU */
d0fb20be 16307 default:
a68ab351 16308 if ((ctx || task_shared_vars)
726a989a
RB
16309 && walk_gimple_op (stmt, lower_omp_regimplify_p,
16310 ctx ? NULL : &wi))
47519a14
JJ
16311 {
16312 /* Just remove clobbers, this should happen only if we have
16313 "privatized" local addressable variables in SIMD regions,
16314 the clobber isn't needed in that case and gimplifying address
16315 of the ARRAY_REF into a pointer and creating MEM_REF based
16316 clobber would create worse code than we get with the clobber
16317 dropped. */
16318 if (gimple_clobber_p (stmt))
16319 {
16320 gsi_replace (gsi_p, gimple_build_nop (), true);
16321 break;
16322 }
d9a6bd32 16323 lower_omp_regimplify_operands (ctx, stmt, gsi_p);
47519a14 16324 }
953ff289 16325 break;
953ff289 16326 }
953ff289
DN
16327}
16328
16329static void
355a7673 16330lower_omp (gimple_seq *body, omp_context *ctx)
953ff289 16331{
b357f682 16332 location_t saved_location = input_location;
355a7673
MM
16333 gimple_stmt_iterator gsi;
16334 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
726a989a 16335 lower_omp_1 (&gsi, ctx);
41dbbb37 16336 /* During gimplification, we haven't folded statments inside offloading
d26fc979
JJ
16337 or taskreg regions (gimplify.c:maybe_fold_stmt); do that now. */
16338 if (target_nesting_level || taskreg_nesting_level)
acf0174b
JJ
16339 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
16340 fold_stmt (&gsi);
b357f682 16341 input_location = saved_location;
953ff289
DN
16342}
16343\f
16344/* Main entry point. */
16345
c2924966 16346static unsigned int
953ff289
DN
16347execute_lower_omp (void)
16348{
726a989a 16349 gimple_seq body;
5771c391
JJ
16350 int i;
16351 omp_context *ctx;
726a989a 16352
535b544a 16353 /* This pass always runs, to provide PROP_gimple_lomp.
41dbbb37
TS
16354 But often, there is nothing to do. */
16355 if (flag_cilkplus == 0 && flag_openacc == 0 && flag_openmp == 0
16356 && flag_openmp_simd == 0)
535b544a
SB
16357 return 0;
16358
953ff289
DN
16359 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
16360 delete_omp_context);
16361
726a989a 16362 body = gimple_body (current_function_decl);
26127932 16363 scan_omp (&body, NULL);
a68ab351 16364 gcc_assert (taskreg_nesting_level == 0);
5771c391
JJ
16365 FOR_EACH_VEC_ELT (taskreg_contexts, i, ctx)
16366 finish_taskreg_scan (ctx);
16367 taskreg_contexts.release ();
953ff289
DN
16368
16369 if (all_contexts->root)
a68ab351
JJ
16370 {
16371 if (task_shared_vars)
45852dcc 16372 push_gimplify_context ();
355a7673 16373 lower_omp (&body, NULL);
a68ab351
JJ
16374 if (task_shared_vars)
16375 pop_gimplify_context (NULL);
16376 }
953ff289 16377
50674e96
DN
16378 if (all_contexts)
16379 {
16380 splay_tree_delete (all_contexts);
16381 all_contexts = NULL;
16382 }
a68ab351 16383 BITMAP_FREE (task_shared_vars);
c2924966 16384 return 0;
953ff289
DN
16385}
16386
17795822
TS
16387namespace {
16388
16389const pass_data pass_data_lower_omp =
27a4cd48
DM
16390{
16391 GIMPLE_PASS, /* type */
16392 "omplower", /* name */
16393 OPTGROUP_NONE, /* optinfo_flags */
27a4cd48
DM
16394 TV_NONE, /* tv_id */
16395 PROP_gimple_any, /* properties_required */
16396 PROP_gimple_lomp, /* properties_provided */
16397 0, /* properties_destroyed */
16398 0, /* todo_flags_start */
16399 0, /* todo_flags_finish */
953ff289 16400};
27a4cd48 16401
17795822 16402class pass_lower_omp : public gimple_opt_pass
27a4cd48
DM
16403{
16404public:
c3284718
RS
16405 pass_lower_omp (gcc::context *ctxt)
16406 : gimple_opt_pass (pass_data_lower_omp, ctxt)
27a4cd48
DM
16407 {}
16408
16409 /* opt_pass methods: */
be55bfe6 16410 virtual unsigned int execute (function *) { return execute_lower_omp (); }
27a4cd48
DM
16411
16412}; // class pass_lower_omp
16413
17795822
TS
16414} // anon namespace
16415
27a4cd48
DM
16416gimple_opt_pass *
16417make_pass_lower_omp (gcc::context *ctxt)
16418{
16419 return new pass_lower_omp (ctxt);
16420}
953ff289 16421\f
41dbbb37 16422/* The following is a utility to diagnose structured block violations.
777f7f9a
RH
16423 It is not part of the "omplower" pass, as that's invoked too late. It
16424 should be invoked by the respective front ends after gimplification. */
953ff289
DN
16425
16426static splay_tree all_labels;
16427
16428/* Check for mismatched contexts and generate an error if needed. Return
16429 true if an error is detected. */
16430
16431static bool
726a989a 16432diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
355fe088 16433 gimple *branch_ctx, gimple *label_ctx)
953ff289 16434{
41dbbb37
TS
16435 gcc_checking_assert (!branch_ctx || is_gimple_omp (branch_ctx));
16436 gcc_checking_assert (!label_ctx || is_gimple_omp (label_ctx));
16437
726a989a 16438 if (label_ctx == branch_ctx)
953ff289
DN
16439 return false;
16440
41dbbb37
TS
16441 const char* kind = NULL;
16442
16443 if (flag_cilkplus)
16444 {
16445 if ((branch_ctx
16446 && gimple_code (branch_ctx) == GIMPLE_OMP_FOR
16447 && gimple_omp_for_kind (branch_ctx) == GF_OMP_FOR_KIND_CILKSIMD)
16448 || (label_ctx
16449 && gimple_code (label_ctx) == GIMPLE_OMP_FOR
16450 && gimple_omp_for_kind (label_ctx) == GF_OMP_FOR_KIND_CILKSIMD))
16451 kind = "Cilk Plus";
16452 }
16453 if (flag_openacc)
16454 {
16455 if ((branch_ctx && is_gimple_omp_oacc (branch_ctx))
16456 || (label_ctx && is_gimple_omp_oacc (label_ctx)))
16457 {
16458 gcc_checking_assert (kind == NULL);
16459 kind = "OpenACC";
16460 }
16461 }
16462 if (kind == NULL)
16463 {
16464 gcc_checking_assert (flag_openmp);
16465 kind = "OpenMP";
16466 }
b8698a0f 16467
726a989a
RB
16468 /*
16469 Previously we kept track of the label's entire context in diagnose_sb_[12]
16470 so we could traverse it and issue a correct "exit" or "enter" error
16471 message upon a structured block violation.
16472
16473 We built the context by building a list with tree_cons'ing, but there is
16474 no easy counterpart in gimple tuples. It seems like far too much work
16475 for issuing exit/enter error messages. If someone really misses the
16476 distinct error message... patches welcome.
16477 */
b8698a0f 16478
726a989a 16479#if 0
953ff289 16480 /* Try to avoid confusing the user by producing and error message
fa10beec 16481 with correct "exit" or "enter" verbiage. We prefer "exit"
953ff289
DN
16482 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
16483 if (branch_ctx == NULL)
16484 exit_p = false;
16485 else
16486 {
16487 while (label_ctx)
16488 {
16489 if (TREE_VALUE (label_ctx) == branch_ctx)
16490 {
16491 exit_p = false;
16492 break;
16493 }
16494 label_ctx = TREE_CHAIN (label_ctx);
16495 }
16496 }
16497
16498 if (exit_p)
41dbbb37 16499 error ("invalid exit from %s structured block", kind);
953ff289 16500 else
41dbbb37 16501 error ("invalid entry to %s structured block", kind);
726a989a 16502#endif
953ff289 16503
726a989a
RB
16504 /* If it's obvious we have an invalid entry, be specific about the error. */
16505 if (branch_ctx == NULL)
41dbbb37 16506 error ("invalid entry to %s structured block", kind);
726a989a 16507 else
c02065fc
AH
16508 {
16509 /* Otherwise, be vague and lazy, but efficient. */
41dbbb37 16510 error ("invalid branch to/from %s structured block", kind);
c02065fc 16511 }
726a989a
RB
16512
16513 gsi_replace (gsi_p, gimple_build_nop (), false);
953ff289
DN
16514 return true;
16515}
16516
41dbbb37 16517/* Pass 1: Create a minimal tree of structured blocks, and record
726a989a 16518 where each label is found. */
953ff289
DN
16519
16520static tree
726a989a
RB
16521diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
16522 struct walk_stmt_info *wi)
953ff289 16523{
355fe088
TS
16524 gimple *context = (gimple *) wi->info;
16525 gimple *inner_context;
16526 gimple *stmt = gsi_stmt (*gsi_p);
953ff289 16527
726a989a
RB
16528 *handled_ops_p = true;
16529
41dbbb37 16530 switch (gimple_code (stmt))
953ff289 16531 {
726a989a 16532 WALK_SUBSTMTS;
b8698a0f 16533
726a989a
RB
16534 case GIMPLE_OMP_PARALLEL:
16535 case GIMPLE_OMP_TASK:
16536 case GIMPLE_OMP_SECTIONS:
16537 case GIMPLE_OMP_SINGLE:
16538 case GIMPLE_OMP_SECTION:
16539 case GIMPLE_OMP_MASTER:
16540 case GIMPLE_OMP_ORDERED:
16541 case GIMPLE_OMP_CRITICAL:
acf0174b
JJ
16542 case GIMPLE_OMP_TARGET:
16543 case GIMPLE_OMP_TEAMS:
16544 case GIMPLE_OMP_TASKGROUP:
726a989a
RB
16545 /* The minimal context here is just the current OMP construct. */
16546 inner_context = stmt;
953ff289 16547 wi->info = inner_context;
726a989a 16548 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
953ff289
DN
16549 wi->info = context;
16550 break;
16551
726a989a
RB
16552 case GIMPLE_OMP_FOR:
16553 inner_context = stmt;
953ff289 16554 wi->info = inner_context;
726a989a
RB
16555 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
16556 walk them. */
16557 walk_gimple_seq (gimple_omp_for_pre_body (stmt),
16558 diagnose_sb_1, NULL, wi);
16559 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
953ff289
DN
16560 wi->info = context;
16561 break;
16562
726a989a 16563 case GIMPLE_LABEL:
538dd0b7
DM
16564 splay_tree_insert (all_labels,
16565 (splay_tree_key) gimple_label_label (
16566 as_a <glabel *> (stmt)),
953ff289
DN
16567 (splay_tree_value) context);
16568 break;
16569
16570 default:
16571 break;
16572 }
16573
16574 return NULL_TREE;
16575}
16576
16577/* Pass 2: Check each branch and see if its context differs from that of
16578 the destination label's context. */
16579
16580static tree
726a989a
RB
16581diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
16582 struct walk_stmt_info *wi)
953ff289 16583{
355fe088 16584 gimple *context = (gimple *) wi->info;
953ff289 16585 splay_tree_node n;
355fe088 16586 gimple *stmt = gsi_stmt (*gsi_p);
953ff289 16587
726a989a
RB
16588 *handled_ops_p = true;
16589
16590 switch (gimple_code (stmt))
953ff289 16591 {
726a989a
RB
16592 WALK_SUBSTMTS;
16593
16594 case GIMPLE_OMP_PARALLEL:
16595 case GIMPLE_OMP_TASK:
16596 case GIMPLE_OMP_SECTIONS:
16597 case GIMPLE_OMP_SINGLE:
16598 case GIMPLE_OMP_SECTION:
16599 case GIMPLE_OMP_MASTER:
16600 case GIMPLE_OMP_ORDERED:
16601 case GIMPLE_OMP_CRITICAL:
acf0174b
JJ
16602 case GIMPLE_OMP_TARGET:
16603 case GIMPLE_OMP_TEAMS:
16604 case GIMPLE_OMP_TASKGROUP:
726a989a 16605 wi->info = stmt;
355a7673 16606 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
953ff289
DN
16607 wi->info = context;
16608 break;
16609
726a989a
RB
16610 case GIMPLE_OMP_FOR:
16611 wi->info = stmt;
16612 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
16613 walk them. */
355a7673
MM
16614 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt),
16615 diagnose_sb_2, NULL, wi);
16616 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
953ff289
DN
16617 wi->info = context;
16618 break;
16619
ca50f84a
L
16620 case GIMPLE_COND:
16621 {
538dd0b7
DM
16622 gcond *cond_stmt = as_a <gcond *> (stmt);
16623 tree lab = gimple_cond_true_label (cond_stmt);
ca50f84a
L
16624 if (lab)
16625 {
16626 n = splay_tree_lookup (all_labels,
16627 (splay_tree_key) lab);
16628 diagnose_sb_0 (gsi_p, context,
355fe088 16629 n ? (gimple *) n->value : NULL);
ca50f84a 16630 }
538dd0b7 16631 lab = gimple_cond_false_label (cond_stmt);
ca50f84a
L
16632 if (lab)
16633 {
16634 n = splay_tree_lookup (all_labels,
16635 (splay_tree_key) lab);
16636 diagnose_sb_0 (gsi_p, context,
355fe088 16637 n ? (gimple *) n->value : NULL);
ca50f84a
L
16638 }
16639 }
16640 break;
16641
726a989a 16642 case GIMPLE_GOTO:
953ff289 16643 {
726a989a 16644 tree lab = gimple_goto_dest (stmt);
953ff289
DN
16645 if (TREE_CODE (lab) != LABEL_DECL)
16646 break;
16647
16648 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
355fe088 16649 diagnose_sb_0 (gsi_p, context, n ? (gimple *) n->value : NULL);
953ff289
DN
16650 }
16651 break;
16652
726a989a 16653 case GIMPLE_SWITCH:
953ff289 16654 {
538dd0b7 16655 gswitch *switch_stmt = as_a <gswitch *> (stmt);
726a989a 16656 unsigned int i;
538dd0b7 16657 for (i = 0; i < gimple_switch_num_labels (switch_stmt); ++i)
953ff289 16658 {
538dd0b7 16659 tree lab = CASE_LABEL (gimple_switch_label (switch_stmt, i));
953ff289 16660 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
355fe088 16661 if (n && diagnose_sb_0 (gsi_p, context, (gimple *) n->value))
953ff289
DN
16662 break;
16663 }
16664 }
16665 break;
16666
726a989a
RB
16667 case GIMPLE_RETURN:
16668 diagnose_sb_0 (gsi_p, context, NULL);
953ff289
DN
16669 break;
16670
16671 default:
16672 break;
16673 }
16674
16675 return NULL_TREE;
16676}
16677
41dbbb37
TS
16678/* Called from tree-cfg.c::make_edges to create cfg edges for all relevant
16679 GIMPLE_* codes. */
0645c1a2 16680bool
09b22f48
JJ
16681make_gimple_omp_edges (basic_block bb, struct omp_region **region,
16682 int *region_idx)
0645c1a2 16683{
355fe088 16684 gimple *last = last_stmt (bb);
0645c1a2
AM
16685 enum gimple_code code = gimple_code (last);
16686 struct omp_region *cur_region = *region;
16687 bool fallthru = false;
16688
16689 switch (code)
16690 {
16691 case GIMPLE_OMP_PARALLEL:
16692 case GIMPLE_OMP_TASK:
16693 case GIMPLE_OMP_FOR:
16694 case GIMPLE_OMP_SINGLE:
16695 case GIMPLE_OMP_TEAMS:
16696 case GIMPLE_OMP_MASTER:
16697 case GIMPLE_OMP_TASKGROUP:
0645c1a2
AM
16698 case GIMPLE_OMP_CRITICAL:
16699 case GIMPLE_OMP_SECTION:
16700 cur_region = new_omp_region (bb, code, cur_region);
16701 fallthru = true;
16702 break;
16703
d9a6bd32
JJ
16704 case GIMPLE_OMP_ORDERED:
16705 cur_region = new_omp_region (bb, code, cur_region);
16706 fallthru = true;
16707 if (find_omp_clause (gimple_omp_ordered_clauses
16708 (as_a <gomp_ordered *> (last)),
16709 OMP_CLAUSE_DEPEND))
16710 cur_region = cur_region->outer;
16711 break;
16712
0645c1a2
AM
16713 case GIMPLE_OMP_TARGET:
16714 cur_region = new_omp_region (bb, code, cur_region);
16715 fallthru = true;
41dbbb37
TS
16716 switch (gimple_omp_target_kind (last))
16717 {
16718 case GF_OMP_TARGET_KIND_REGION:
16719 case GF_OMP_TARGET_KIND_DATA:
16720 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
16721 case GF_OMP_TARGET_KIND_OACC_KERNELS:
16722 case GF_OMP_TARGET_KIND_OACC_DATA:
16723 break;
16724 case GF_OMP_TARGET_KIND_UPDATE:
d9a6bd32
JJ
16725 case GF_OMP_TARGET_KIND_ENTER_DATA:
16726 case GF_OMP_TARGET_KIND_EXIT_DATA:
41dbbb37
TS
16727 case GF_OMP_TARGET_KIND_OACC_UPDATE:
16728 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
6e232ba4 16729 case GF_OMP_TARGET_KIND_OACC_DECLARE:
41dbbb37
TS
16730 cur_region = cur_region->outer;
16731 break;
16732 default:
16733 gcc_unreachable ();
16734 }
0645c1a2
AM
16735 break;
16736
16737 case GIMPLE_OMP_SECTIONS:
16738 cur_region = new_omp_region (bb, code, cur_region);
16739 fallthru = true;
16740 break;
16741
16742 case GIMPLE_OMP_SECTIONS_SWITCH:
16743 fallthru = false;
16744 break;
16745
16746 case GIMPLE_OMP_ATOMIC_LOAD:
16747 case GIMPLE_OMP_ATOMIC_STORE:
16748 fallthru = true;
16749 break;
16750
16751 case GIMPLE_OMP_RETURN:
16752 /* In the case of a GIMPLE_OMP_SECTION, the edge will go
16753 somewhere other than the next block. This will be
16754 created later. */
16755 cur_region->exit = bb;
b37dddbc
JJ
16756 if (cur_region->type == GIMPLE_OMP_TASK)
16757 /* Add an edge corresponding to not scheduling the task
16758 immediately. */
16759 make_edge (cur_region->entry, bb, EDGE_ABNORMAL);
0645c1a2
AM
16760 fallthru = cur_region->type != GIMPLE_OMP_SECTION;
16761 cur_region = cur_region->outer;
16762 break;
16763
16764 case GIMPLE_OMP_CONTINUE:
16765 cur_region->cont = bb;
16766 switch (cur_region->type)
16767 {
16768 case GIMPLE_OMP_FOR:
16769 /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
16770 succs edges as abnormal to prevent splitting
16771 them. */
16772 single_succ_edge (cur_region->entry)->flags |= EDGE_ABNORMAL;
16773 /* Make the loopback edge. */
16774 make_edge (bb, single_succ (cur_region->entry),
16775 EDGE_ABNORMAL);
16776
16777 /* Create an edge from GIMPLE_OMP_FOR to exit, which
16778 corresponds to the case that the body of the loop
16779 is not executed at all. */
16780 make_edge (cur_region->entry, bb->next_bb, EDGE_ABNORMAL);
16781 make_edge (bb, bb->next_bb, EDGE_FALLTHRU | EDGE_ABNORMAL);
16782 fallthru = false;
16783 break;
16784
16785 case GIMPLE_OMP_SECTIONS:
16786 /* Wire up the edges into and out of the nested sections. */
16787 {
16788 basic_block switch_bb = single_succ (cur_region->entry);
16789
16790 struct omp_region *i;
16791 for (i = cur_region->inner; i ; i = i->next)
16792 {
16793 gcc_assert (i->type == GIMPLE_OMP_SECTION);
16794 make_edge (switch_bb, i->entry, 0);
16795 make_edge (i->exit, bb, EDGE_FALLTHRU);
16796 }
16797
16798 /* Make the loopback edge to the block with
16799 GIMPLE_OMP_SECTIONS_SWITCH. */
16800 make_edge (bb, switch_bb, 0);
16801
16802 /* Make the edge from the switch to exit. */
16803 make_edge (switch_bb, bb->next_bb, 0);
16804 fallthru = false;
16805 }
16806 break;
16807
b37dddbc
JJ
16808 case GIMPLE_OMP_TASK:
16809 fallthru = true;
16810 break;
16811
0645c1a2
AM
16812 default:
16813 gcc_unreachable ();
16814 }
16815 break;
16816
16817 default:
16818 gcc_unreachable ();
16819 }
16820
16821 if (*region != cur_region)
09b22f48
JJ
16822 {
16823 *region = cur_region;
16824 if (cur_region)
16825 *region_idx = cur_region->entry->index;
16826 else
16827 *region_idx = 0;
16828 }
0645c1a2
AM
16829
16830 return fallthru;
16831}
16832
a406865a
RG
16833static unsigned int
16834diagnose_omp_structured_block_errors (void)
953ff289 16835{
953ff289 16836 struct walk_stmt_info wi;
a406865a 16837 gimple_seq body = gimple_body (current_function_decl);
953ff289
DN
16838
16839 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
16840
16841 memset (&wi, 0, sizeof (wi));
726a989a 16842 walk_gimple_seq (body, diagnose_sb_1, NULL, &wi);
953ff289
DN
16843
16844 memset (&wi, 0, sizeof (wi));
953ff289 16845 wi.want_locations = true;
355a7673
MM
16846 walk_gimple_seq_mod (&body, diagnose_sb_2, NULL, &wi);
16847
16848 gimple_set_body (current_function_decl, body);
953ff289
DN
16849
16850 splay_tree_delete (all_labels);
16851 all_labels = NULL;
16852
a406865a 16853 return 0;
953ff289
DN
16854}
16855
17795822
TS
16856namespace {
16857
16858const pass_data pass_data_diagnose_omp_blocks =
27a4cd48
DM
16859{
16860 GIMPLE_PASS, /* type */
16861 "*diagnose_omp_blocks", /* name */
16862 OPTGROUP_NONE, /* optinfo_flags */
27a4cd48
DM
16863 TV_NONE, /* tv_id */
16864 PROP_gimple_any, /* properties_required */
16865 0, /* properties_provided */
16866 0, /* properties_destroyed */
16867 0, /* todo_flags_start */
16868 0, /* todo_flags_finish */
a406865a
RG
16869};
16870
17795822 16871class pass_diagnose_omp_blocks : public gimple_opt_pass
27a4cd48
DM
16872{
16873public:
c3284718
RS
16874 pass_diagnose_omp_blocks (gcc::context *ctxt)
16875 : gimple_opt_pass (pass_data_diagnose_omp_blocks, ctxt)
27a4cd48
DM
16876 {}
16877
16878 /* opt_pass methods: */
41dbbb37
TS
16879 virtual bool gate (function *)
16880 {
16881 return flag_cilkplus || flag_openacc || flag_openmp;
16882 }
be55bfe6
TS
16883 virtual unsigned int execute (function *)
16884 {
16885 return diagnose_omp_structured_block_errors ();
16886 }
27a4cd48
DM
16887
16888}; // class pass_diagnose_omp_blocks
16889
17795822
TS
16890} // anon namespace
16891
27a4cd48
DM
16892gimple_opt_pass *
16893make_pass_diagnose_omp_blocks (gcc::context *ctxt)
16894{
16895 return new pass_diagnose_omp_blocks (ctxt);
16896}
0136f8f0
AH
16897\f
16898/* SIMD clone supporting code. */
16899
16900/* Allocate a fresh `simd_clone' and return it. NARGS is the number
16901 of arguments to reserve space for. */
16902
16903static struct cgraph_simd_clone *
16904simd_clone_struct_alloc (int nargs)
16905{
16906 struct cgraph_simd_clone *clone_info;
16907 size_t len = (sizeof (struct cgraph_simd_clone)
16908 + nargs * sizeof (struct cgraph_simd_clone_arg));
16909 clone_info = (struct cgraph_simd_clone *)
b3bb0eb9 16910 ggc_internal_cleared_alloc (len);
0136f8f0
AH
16911 return clone_info;
16912}
16913
16914/* Make a copy of the `struct cgraph_simd_clone' in FROM to TO. */
16915
16916static inline void
16917simd_clone_struct_copy (struct cgraph_simd_clone *to,
16918 struct cgraph_simd_clone *from)
16919{
16920 memcpy (to, from, (sizeof (struct cgraph_simd_clone)
92d05580
JJ
16921 + ((from->nargs - from->inbranch)
16922 * sizeof (struct cgraph_simd_clone_arg))));
0136f8f0
AH
16923}
16924
16925/* Return vector of parameter types of function FNDECL. This uses
16926 TYPE_ARG_TYPES if available, otherwise falls back to types of
16927 DECL_ARGUMENTS types. */
16928
16929vec<tree>
16930simd_clone_vector_of_formal_parm_types (tree fndecl)
16931{
16932 if (TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
16933 return ipa_get_vector_of_formal_parm_types (TREE_TYPE (fndecl));
16934 vec<tree> args = ipa_get_vector_of_formal_parms (fndecl);
16935 unsigned int i;
16936 tree arg;
16937 FOR_EACH_VEC_ELT (args, i, arg)
16938 args[i] = TREE_TYPE (args[i]);
16939 return args;
16940}
16941
16942/* Given a simd function in NODE, extract the simd specific
16943 information from the OMP clauses passed in CLAUSES, and return
16944 the struct cgraph_simd_clone * if it should be cloned. *INBRANCH_SPECIFIED
16945 is set to TRUE if the `inbranch' or `notinbranch' clause specified,
16946 otherwise set to FALSE. */
16947
16948static struct cgraph_simd_clone *
16949simd_clone_clauses_extract (struct cgraph_node *node, tree clauses,
16950 bool *inbranch_specified)
16951{
16952 vec<tree> args = simd_clone_vector_of_formal_parm_types (node->decl);
16953 tree t;
16954 int n;
16955 *inbranch_specified = false;
16956
16957 n = args.length ();
16958 if (n > 0 && args.last () == void_type_node)
16959 n--;
16960
16961 /* To distinguish from an OpenMP simd clone, Cilk Plus functions to
16962 be cloned have a distinctive artificial label in addition to "omp
16963 declare simd". */
16964 bool cilk_clone
b72271b9 16965 = (flag_cilkplus
41958c28 16966 && lookup_attribute ("cilk simd function",
0136f8f0
AH
16967 DECL_ATTRIBUTES (node->decl)));
16968
16969 /* Allocate one more than needed just in case this is an in-branch
16970 clone which will require a mask argument. */
16971 struct cgraph_simd_clone *clone_info = simd_clone_struct_alloc (n + 1);
16972 clone_info->nargs = n;
16973 clone_info->cilk_elemental = cilk_clone;
16974
16975 if (!clauses)
16976 {
16977 args.release ();
16978 return clone_info;
16979 }
16980 clauses = TREE_VALUE (clauses);
16981 if (!clauses || TREE_CODE (clauses) != OMP_CLAUSE)
16982 return clone_info;
16983
16984 for (t = clauses; t; t = OMP_CLAUSE_CHAIN (t))
16985 {
16986 switch (OMP_CLAUSE_CODE (t))
16987 {
16988 case OMP_CLAUSE_INBRANCH:
16989 clone_info->inbranch = 1;
16990 *inbranch_specified = true;
16991 break;
16992 case OMP_CLAUSE_NOTINBRANCH:
16993 clone_info->inbranch = 0;
16994 *inbranch_specified = true;
16995 break;
16996 case OMP_CLAUSE_SIMDLEN:
16997 clone_info->simdlen
16998 = TREE_INT_CST_LOW (OMP_CLAUSE_SIMDLEN_EXPR (t));
16999 break;
17000 case OMP_CLAUSE_LINEAR:
17001 {
17002 tree decl = OMP_CLAUSE_DECL (t);
17003 tree step = OMP_CLAUSE_LINEAR_STEP (t);
17004 int argno = TREE_INT_CST_LOW (decl);
17005 if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (t))
17006 {
e01d41e5
JJ
17007 enum cgraph_simd_clone_arg_type arg_type;
17008 if (TREE_CODE (args[argno]) == REFERENCE_TYPE)
17009 switch (OMP_CLAUSE_LINEAR_KIND (t))
17010 {
17011 case OMP_CLAUSE_LINEAR_REF:
17012 arg_type
17013 = SIMD_CLONE_ARG_TYPE_LINEAR_REF_VARIABLE_STEP;
17014 break;
17015 case OMP_CLAUSE_LINEAR_UVAL:
17016 arg_type
17017 = SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_VARIABLE_STEP;
17018 break;
17019 case OMP_CLAUSE_LINEAR_VAL:
17020 case OMP_CLAUSE_LINEAR_DEFAULT:
17021 arg_type
17022 = SIMD_CLONE_ARG_TYPE_LINEAR_VAL_VARIABLE_STEP;
17023 break;
17024 default:
17025 gcc_unreachable ();
17026 }
17027 else
17028 arg_type = SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP;
17029 clone_info->args[argno].arg_type = arg_type;
0136f8f0
AH
17030 clone_info->args[argno].linear_step = tree_to_shwi (step);
17031 gcc_assert (clone_info->args[argno].linear_step >= 0
17032 && clone_info->args[argno].linear_step < n);
17033 }
17034 else
17035 {
17036 if (POINTER_TYPE_P (args[argno]))
17037 step = fold_convert (ssizetype, step);
17038 if (!tree_fits_shwi_p (step))
17039 {
17040 warning_at (OMP_CLAUSE_LOCATION (t), 0,
17041 "ignoring large linear step");
17042 args.release ();
17043 return NULL;
17044 }
17045 else if (integer_zerop (step))
17046 {
17047 warning_at (OMP_CLAUSE_LOCATION (t), 0,
17048 "ignoring zero linear step");
17049 args.release ();
17050 return NULL;
17051 }
17052 else
17053 {
d9a6bd32
JJ
17054 enum cgraph_simd_clone_arg_type arg_type;
17055 if (TREE_CODE (args[argno]) == REFERENCE_TYPE)
17056 switch (OMP_CLAUSE_LINEAR_KIND (t))
17057 {
17058 case OMP_CLAUSE_LINEAR_REF:
17059 arg_type
17060 = SIMD_CLONE_ARG_TYPE_LINEAR_REF_CONSTANT_STEP;
17061 break;
17062 case OMP_CLAUSE_LINEAR_UVAL:
17063 arg_type
17064 = SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP;
17065 break;
17066 case OMP_CLAUSE_LINEAR_VAL:
17067 case OMP_CLAUSE_LINEAR_DEFAULT:
17068 arg_type
17069 = SIMD_CLONE_ARG_TYPE_LINEAR_VAL_CONSTANT_STEP;
17070 break;
17071 default:
17072 gcc_unreachable ();
17073 }
17074 else
17075 arg_type = SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP;
17076 clone_info->args[argno].arg_type = arg_type;
0136f8f0
AH
17077 clone_info->args[argno].linear_step = tree_to_shwi (step);
17078 }
17079 }
17080 break;
17081 }
17082 case OMP_CLAUSE_UNIFORM:
17083 {
17084 tree decl = OMP_CLAUSE_DECL (t);
17085 int argno = tree_to_uhwi (decl);
17086 clone_info->args[argno].arg_type
17087 = SIMD_CLONE_ARG_TYPE_UNIFORM;
17088 break;
17089 }
17090 case OMP_CLAUSE_ALIGNED:
17091 {
17092 tree decl = OMP_CLAUSE_DECL (t);
17093 int argno = tree_to_uhwi (decl);
17094 clone_info->args[argno].alignment
17095 = TREE_INT_CST_LOW (OMP_CLAUSE_ALIGNED_ALIGNMENT (t));
17096 break;
17097 }
17098 default:
17099 break;
17100 }
17101 }
17102 args.release ();
17103 return clone_info;
17104}
17105
17106/* Given a SIMD clone in NODE, calculate the characteristic data
17107 type and return the coresponding type. The characteristic data
17108 type is computed as described in the Intel Vector ABI. */
17109
17110static tree
17111simd_clone_compute_base_data_type (struct cgraph_node *node,
17112 struct cgraph_simd_clone *clone_info)
17113{
17114 tree type = integer_type_node;
17115 tree fndecl = node->decl;
17116
17117 /* a) For non-void function, the characteristic data type is the
17118 return type. */
17119 if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) != VOID_TYPE)
17120 type = TREE_TYPE (TREE_TYPE (fndecl));
17121
17122 /* b) If the function has any non-uniform, non-linear parameters,
17123 then the characteristic data type is the type of the first
17124 such parameter. */
17125 else
17126 {
17127 vec<tree> map = simd_clone_vector_of_formal_parm_types (fndecl);
17128 for (unsigned int i = 0; i < clone_info->nargs; ++i)
17129 if (clone_info->args[i].arg_type == SIMD_CLONE_ARG_TYPE_VECTOR)
17130 {
17131 type = map[i];
17132 break;
17133 }
17134 map.release ();
17135 }
17136
17137 /* c) If the characteristic data type determined by a) or b) above
17138 is struct, union, or class type which is pass-by-value (except
17139 for the type that maps to the built-in complex data type), the
17140 characteristic data type is int. */
17141 if (RECORD_OR_UNION_TYPE_P (type)
17142 && !aggregate_value_p (type, NULL)
17143 && TREE_CODE (type) != COMPLEX_TYPE)
17144 return integer_type_node;
17145
17146 /* d) If none of the above three classes is applicable, the
17147 characteristic data type is int. */
17148
17149 return type;
17150
17151 /* e) For Intel Xeon Phi native and offload compilation, if the
17152 resulting characteristic data type is 8-bit or 16-bit integer
17153 data type, the characteristic data type is int. */
17154 /* Well, we don't handle Xeon Phi yet. */
17155}
17156
17157static tree
17158simd_clone_mangle (struct cgraph_node *node,
17159 struct cgraph_simd_clone *clone_info)
17160{
17161 char vecsize_mangle = clone_info->vecsize_mangle;
17162 char mask = clone_info->inbranch ? 'M' : 'N';
17163 unsigned int simdlen = clone_info->simdlen;
17164 unsigned int n;
17165 pretty_printer pp;
17166
17167 gcc_assert (vecsize_mangle && simdlen);
17168
17169 pp_string (&pp, "_ZGV");
17170 pp_character (&pp, vecsize_mangle);
17171 pp_character (&pp, mask);
17172 pp_decimal_int (&pp, simdlen);
17173
17174 for (n = 0; n < clone_info->nargs; ++n)
17175 {
17176 struct cgraph_simd_clone_arg arg = clone_info->args[n];
17177
d9a6bd32 17178 switch (arg.arg_type)
0136f8f0 17179 {
d9a6bd32
JJ
17180 case SIMD_CLONE_ARG_TYPE_UNIFORM:
17181 pp_character (&pp, 'u');
17182 break;
17183 case SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP:
0136f8f0 17184 pp_character (&pp, 'l');
d9a6bd32
JJ
17185 goto mangle_linear;
17186 case SIMD_CLONE_ARG_TYPE_LINEAR_REF_CONSTANT_STEP:
17187 pp_character (&pp, 'R');
17188 goto mangle_linear;
17189 case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_CONSTANT_STEP:
17190 pp_character (&pp, 'L');
17191 goto mangle_linear;
17192 case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP:
17193 pp_character (&pp, 'U');
17194 goto mangle_linear;
17195 mangle_linear:
17196 gcc_assert (arg.linear_step != 0);
0136f8f0
AH
17197 if (arg.linear_step > 1)
17198 pp_unsigned_wide_integer (&pp, arg.linear_step);
17199 else if (arg.linear_step < 0)
17200 {
17201 pp_character (&pp, 'n');
17202 pp_unsigned_wide_integer (&pp, (-(unsigned HOST_WIDE_INT)
17203 arg.linear_step));
17204 }
d9a6bd32
JJ
17205 break;
17206 case SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP:
e01d41e5
JJ
17207 pp_string (&pp, "ls");
17208 pp_unsigned_wide_integer (&pp, arg.linear_step);
17209 break;
17210 case SIMD_CLONE_ARG_TYPE_LINEAR_REF_VARIABLE_STEP:
17211 pp_string (&pp, "Rs");
17212 pp_unsigned_wide_integer (&pp, arg.linear_step);
17213 break;
17214 case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_VARIABLE_STEP:
17215 pp_string (&pp, "Ls");
17216 pp_unsigned_wide_integer (&pp, arg.linear_step);
17217 break;
17218 case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_VARIABLE_STEP:
17219 pp_string (&pp, "Us");
0136f8f0 17220 pp_unsigned_wide_integer (&pp, arg.linear_step);
d9a6bd32
JJ
17221 break;
17222 default:
17223 pp_character (&pp, 'v');
0136f8f0 17224 }
0136f8f0
AH
17225 if (arg.alignment)
17226 {
17227 pp_character (&pp, 'a');
17228 pp_decimal_int (&pp, arg.alignment);
17229 }
17230 }
17231
17232 pp_underscore (&pp);
4cd76837
JJ
17233 const char *str = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl));
17234 if (*str == '*')
17235 ++str;
17236 pp_string (&pp, str);
17237 str = pp_formatted_text (&pp);
0136f8f0
AH
17238
17239 /* If there already is a SIMD clone with the same mangled name, don't
17240 add another one. This can happen e.g. for
17241 #pragma omp declare simd
17242 #pragma omp declare simd simdlen(8)
17243 int foo (int, int);
17244 if the simdlen is assumed to be 8 for the first one, etc. */
17245 for (struct cgraph_node *clone = node->simd_clones; clone;
17246 clone = clone->simdclone->next_clone)
17247 if (strcmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (clone->decl)),
17248 str) == 0)
17249 return NULL_TREE;
17250
17251 return get_identifier (str);
17252}
17253
17254/* Create a simd clone of OLD_NODE and return it. */
17255
17256static struct cgraph_node *
17257simd_clone_create (struct cgraph_node *old_node)
17258{
17259 struct cgraph_node *new_node;
17260 if (old_node->definition)
e06f9964 17261 {
d52f5295 17262 if (!old_node->has_gimple_body_p ())
e06f9964 17263 return NULL;
d52f5295
ML
17264 old_node->get_body ();
17265 new_node = old_node->create_version_clone_with_body (vNULL, NULL, NULL,
17266 false, NULL, NULL,
17267 "simdclone");
e06f9964 17268 }
0136f8f0
AH
17269 else
17270 {
17271 tree old_decl = old_node->decl;
17272 tree new_decl = copy_node (old_node->decl);
17273 DECL_NAME (new_decl) = clone_function_name (old_decl, "simdclone");
17274 SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl));
17275 SET_DECL_RTL (new_decl, NULL);
17276 DECL_STATIC_CONSTRUCTOR (new_decl) = 0;
17277 DECL_STATIC_DESTRUCTOR (new_decl) = 0;
d52f5295 17278 new_node = old_node->create_version_clone (new_decl, vNULL, NULL);
6f9045f4
IE
17279 if (old_node->in_other_partition)
17280 new_node->in_other_partition = 1;
3dafb85c 17281 symtab->call_cgraph_insertion_hooks (new_node);
0136f8f0
AH
17282 }
17283 if (new_node == NULL)
17284 return new_node;
17285
17286 TREE_PUBLIC (new_node->decl) = TREE_PUBLIC (old_node->decl);
17287
17288 /* The function cgraph_function_versioning () will force the new
17289 symbol local. Undo this, and inherit external visability from
17290 the old node. */
17291 new_node->local.local = old_node->local.local;
17292 new_node->externally_visible = old_node->externally_visible;
17293
17294 return new_node;
17295}
17296
17297/* Adjust the return type of the given function to its appropriate
17298 vector counterpart. Returns a simd array to be used throughout the
17299 function as a return value. */
17300
17301static tree
17302simd_clone_adjust_return_type (struct cgraph_node *node)
17303{
17304 tree fndecl = node->decl;
17305 tree orig_rettype = TREE_TYPE (TREE_TYPE (fndecl));
17306 unsigned int veclen;
17307 tree t;
17308
17309 /* Adjust the function return type. */
17310 if (orig_rettype == void_type_node)
17311 return NULL_TREE;
17312 TREE_TYPE (fndecl) = build_distinct_type_copy (TREE_TYPE (fndecl));
1c4967b9
JJ
17313 t = TREE_TYPE (TREE_TYPE (fndecl));
17314 if (INTEGRAL_TYPE_P (t) || POINTER_TYPE_P (t))
0136f8f0
AH
17315 veclen = node->simdclone->vecsize_int;
17316 else
17317 veclen = node->simdclone->vecsize_float;
1c4967b9 17318 veclen /= GET_MODE_BITSIZE (TYPE_MODE (t));
0136f8f0
AH
17319 if (veclen > node->simdclone->simdlen)
17320 veclen = node->simdclone->simdlen;
1c4967b9
JJ
17321 if (POINTER_TYPE_P (t))
17322 t = pointer_sized_int_node;
0136f8f0 17323 if (veclen == node->simdclone->simdlen)
1c4967b9 17324 t = build_vector_type (t, node->simdclone->simdlen);
0136f8f0
AH
17325 else
17326 {
1c4967b9 17327 t = build_vector_type (t, veclen);
0136f8f0 17328 t = build_array_type_nelts (t, node->simdclone->simdlen / veclen);
0136f8f0 17329 }
1c4967b9 17330 TREE_TYPE (TREE_TYPE (fndecl)) = t;
0136f8f0
AH
17331 if (!node->definition)
17332 return NULL_TREE;
17333
17334 t = DECL_RESULT (fndecl);
17335 /* Adjust the DECL_RESULT. */
17336 gcc_assert (TREE_TYPE (t) != void_type_node);
17337 TREE_TYPE (t) = TREE_TYPE (TREE_TYPE (fndecl));
17338 relayout_decl (t);
17339
17340 tree atype = build_array_type_nelts (orig_rettype,
17341 node->simdclone->simdlen);
17342 if (veclen != node->simdclone->simdlen)
17343 return build1 (VIEW_CONVERT_EXPR, atype, t);
17344
17345 /* Set up a SIMD array to use as the return value. */
17346 tree retval = create_tmp_var_raw (atype, "retval");
17347 gimple_add_tmp_var (retval);
17348 return retval;
17349}
17350
17351/* Each vector argument has a corresponding array to be used locally
17352 as part of the eventual loop. Create such temporary array and
17353 return it.
17354
17355 PREFIX is the prefix to be used for the temporary.
17356
17357 TYPE is the inner element type.
17358
17359 SIMDLEN is the number of elements. */
17360
17361static tree
17362create_tmp_simd_array (const char *prefix, tree type, int simdlen)
17363{
17364 tree atype = build_array_type_nelts (type, simdlen);
17365 tree avar = create_tmp_var_raw (atype, prefix);
17366 gimple_add_tmp_var (avar);
17367 return avar;
17368}
17369
17370/* Modify the function argument types to their corresponding vector
17371 counterparts if appropriate. Also, create one array for each simd
17372 argument to be used locally when using the function arguments as
17373 part of the loop.
17374
17375 NODE is the function whose arguments are to be adjusted.
17376
17377 Returns an adjustment vector that will be filled describing how the
17378 argument types will be adjusted. */
17379
17380static ipa_parm_adjustment_vec
17381simd_clone_adjust_argument_types (struct cgraph_node *node)
17382{
17383 vec<tree> args;
17384 ipa_parm_adjustment_vec adjustments;
17385
17386 if (node->definition)
17387 args = ipa_get_vector_of_formal_parms (node->decl);
17388 else
17389 args = simd_clone_vector_of_formal_parm_types (node->decl);
17390 adjustments.create (args.length ());
17391 unsigned i, j, veclen;
17392 struct ipa_parm_adjustment adj;
17393 for (i = 0; i < node->simdclone->nargs; ++i)
17394 {
17395 memset (&adj, 0, sizeof (adj));
17396 tree parm = args[i];
17397 tree parm_type = node->definition ? TREE_TYPE (parm) : parm;
17398 adj.base_index = i;
17399 adj.base = parm;
17400
17401 node->simdclone->args[i].orig_arg = node->definition ? parm : NULL_TREE;
17402 node->simdclone->args[i].orig_type = parm_type;
17403
d9a6bd32 17404 switch (node->simdclone->args[i].arg_type)
0136f8f0 17405 {
d9a6bd32 17406 default:
0136f8f0
AH
17407 /* No adjustment necessary for scalar arguments. */
17408 adj.op = IPA_PARM_OP_COPY;
d9a6bd32
JJ
17409 break;
17410 case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP:
e01d41e5 17411 case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_VARIABLE_STEP:
d9a6bd32
JJ
17412 if (node->definition)
17413 node->simdclone->args[i].simd_array
17414 = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm)),
17415 TREE_TYPE (parm_type),
17416 node->simdclone->simdlen);
17417 adj.op = IPA_PARM_OP_COPY;
17418 break;
17419 case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_CONSTANT_STEP:
e01d41e5 17420 case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_VARIABLE_STEP:
d9a6bd32 17421 case SIMD_CLONE_ARG_TYPE_VECTOR:
0136f8f0
AH
17422 if (INTEGRAL_TYPE_P (parm_type) || POINTER_TYPE_P (parm_type))
17423 veclen = node->simdclone->vecsize_int;
17424 else
17425 veclen = node->simdclone->vecsize_float;
17426 veclen /= GET_MODE_BITSIZE (TYPE_MODE (parm_type));
17427 if (veclen > node->simdclone->simdlen)
17428 veclen = node->simdclone->simdlen;
17429 adj.arg_prefix = "simd";
1c4967b9
JJ
17430 if (POINTER_TYPE_P (parm_type))
17431 adj.type = build_vector_type (pointer_sized_int_node, veclen);
17432 else
17433 adj.type = build_vector_type (parm_type, veclen);
0136f8f0
AH
17434 node->simdclone->args[i].vector_type = adj.type;
17435 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
17436 {
17437 adjustments.safe_push (adj);
17438 if (j == veclen)
17439 {
17440 memset (&adj, 0, sizeof (adj));
17441 adj.op = IPA_PARM_OP_NEW;
17442 adj.arg_prefix = "simd";
17443 adj.base_index = i;
17444 adj.type = node->simdclone->args[i].vector_type;
17445 }
17446 }
17447
17448 if (node->definition)
17449 node->simdclone->args[i].simd_array
17450 = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm)),
17451 parm_type, node->simdclone->simdlen);
17452 }
17453 adjustments.safe_push (adj);
17454 }
17455
17456 if (node->simdclone->inbranch)
17457 {
17458 tree base_type
17459 = simd_clone_compute_base_data_type (node->simdclone->origin,
17460 node->simdclone);
17461
17462 memset (&adj, 0, sizeof (adj));
17463 adj.op = IPA_PARM_OP_NEW;
17464 adj.arg_prefix = "mask";
17465
17466 adj.base_index = i;
17467 if (INTEGRAL_TYPE_P (base_type) || POINTER_TYPE_P (base_type))
17468 veclen = node->simdclone->vecsize_int;
17469 else
17470 veclen = node->simdclone->vecsize_float;
17471 veclen /= GET_MODE_BITSIZE (TYPE_MODE (base_type));
17472 if (veclen > node->simdclone->simdlen)
17473 veclen = node->simdclone->simdlen;
1c4967b9
JJ
17474 if (POINTER_TYPE_P (base_type))
17475 adj.type = build_vector_type (pointer_sized_int_node, veclen);
17476 else
17477 adj.type = build_vector_type (base_type, veclen);
0136f8f0
AH
17478 adjustments.safe_push (adj);
17479
17480 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
17481 adjustments.safe_push (adj);
17482
17483 /* We have previously allocated one extra entry for the mask. Use
17484 it and fill it. */
17485 struct cgraph_simd_clone *sc = node->simdclone;
17486 sc->nargs++;
17487 if (node->definition)
17488 {
17489 sc->args[i].orig_arg
17490 = build_decl (UNKNOWN_LOCATION, PARM_DECL, NULL, base_type);
17491 sc->args[i].simd_array
17492 = create_tmp_simd_array ("mask", base_type, sc->simdlen);
17493 }
17494 sc->args[i].orig_type = base_type;
17495 sc->args[i].arg_type = SIMD_CLONE_ARG_TYPE_MASK;
17496 }
17497
17498 if (node->definition)
17499 ipa_modify_formal_parameters (node->decl, adjustments);
17500 else
17501 {
17502 tree new_arg_types = NULL_TREE, new_reversed;
17503 bool last_parm_void = false;
17504 if (args.length () > 0 && args.last () == void_type_node)
17505 last_parm_void = true;
17506
17507 gcc_assert (TYPE_ARG_TYPES (TREE_TYPE (node->decl)));
17508 j = adjustments.length ();
17509 for (i = 0; i < j; i++)
17510 {
17511 struct ipa_parm_adjustment *adj = &adjustments[i];
17512 tree ptype;
17513 if (adj->op == IPA_PARM_OP_COPY)
17514 ptype = args[adj->base_index];
17515 else
17516 ptype = adj->type;
17517 new_arg_types = tree_cons (NULL_TREE, ptype, new_arg_types);
17518 }
17519 new_reversed = nreverse (new_arg_types);
17520 if (last_parm_void)
17521 {
17522 if (new_reversed)
17523 TREE_CHAIN (new_arg_types) = void_list_node;
17524 else
17525 new_reversed = void_list_node;
17526 }
17527
17528 tree new_type = build_distinct_type_copy (TREE_TYPE (node->decl));
17529 TYPE_ARG_TYPES (new_type) = new_reversed;
17530 TREE_TYPE (node->decl) = new_type;
17531
17532 adjustments.release ();
17533 }
17534 args.release ();
17535 return adjustments;
17536}
17537
17538/* Initialize and copy the function arguments in NODE to their
17539 corresponding local simd arrays. Returns a fresh gimple_seq with
17540 the instruction sequence generated. */
17541
17542static gimple_seq
17543simd_clone_init_simd_arrays (struct cgraph_node *node,
17544 ipa_parm_adjustment_vec adjustments)
17545{
17546 gimple_seq seq = NULL;
17547 unsigned i = 0, j = 0, k;
17548
17549 for (tree arg = DECL_ARGUMENTS (node->decl);
17550 arg;
17551 arg = DECL_CHAIN (arg), i++, j++)
17552 {
d9a6bd32
JJ
17553 if (adjustments[j].op == IPA_PARM_OP_COPY
17554 || POINTER_TYPE_P (TREE_TYPE (arg)))
0136f8f0
AH
17555 continue;
17556
17557 node->simdclone->args[i].vector_arg = arg;
17558
17559 tree array = node->simdclone->args[i].simd_array;
17560 if (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg)) == node->simdclone->simdlen)
17561 {
17562 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
17563 tree ptr = build_fold_addr_expr (array);
17564 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
17565 build_int_cst (ptype, 0));
17566 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
17567 gimplify_and_add (t, &seq);
17568 }
17569 else
17570 {
17571 unsigned int simdlen = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg));
17572 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
17573 for (k = 0; k < node->simdclone->simdlen; k += simdlen)
17574 {
17575 tree ptr = build_fold_addr_expr (array);
17576 int elemsize;
17577 if (k)
17578 {
17579 arg = DECL_CHAIN (arg);
17580 j++;
17581 }
17582 elemsize
17583 = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg))));
17584 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
17585 build_int_cst (ptype, k * elemsize));
17586 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
17587 gimplify_and_add (t, &seq);
17588 }
17589 }
17590 }
17591 return seq;
17592}
17593
17594/* Callback info for ipa_simd_modify_stmt_ops below. */
17595
17596struct modify_stmt_info {
17597 ipa_parm_adjustment_vec adjustments;
355fe088 17598 gimple *stmt;
0136f8f0
AH
17599 /* True if the parent statement was modified by
17600 ipa_simd_modify_stmt_ops. */
17601 bool modified;
17602};
17603
17604/* Callback for walk_gimple_op.
17605
17606 Adjust operands from a given statement as specified in the
17607 adjustments vector in the callback data. */
17608
17609static tree
17610ipa_simd_modify_stmt_ops (tree *tp, int *walk_subtrees, void *data)
17611{
17612 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
2044a4c3
JJ
17613 struct modify_stmt_info *info = (struct modify_stmt_info *) wi->info;
17614 tree *orig_tp = tp;
17615 if (TREE_CODE (*tp) == ADDR_EXPR)
17616 tp = &TREE_OPERAND (*tp, 0);
17617 struct ipa_parm_adjustment *cand = NULL;
17618 if (TREE_CODE (*tp) == PARM_DECL)
17619 cand = ipa_get_adjustment_candidate (&tp, NULL, info->adjustments, true);
17620 else
0136f8f0 17621 {
0136f8f0
AH
17622 if (TYPE_P (*tp))
17623 *walk_subtrees = 0;
0136f8f0 17624 }
0136f8f0 17625
2044a4c3
JJ
17626 tree repl = NULL_TREE;
17627 if (cand)
17628 repl = unshare_expr (cand->new_decl);
17629 else
0136f8f0 17630 {
2044a4c3
JJ
17631 if (tp != orig_tp)
17632 {
17633 *walk_subtrees = 0;
17634 bool modified = info->modified;
17635 info->modified = false;
17636 walk_tree (tp, ipa_simd_modify_stmt_ops, wi, wi->pset);
17637 if (!info->modified)
17638 {
17639 info->modified = modified;
17640 return NULL_TREE;
17641 }
17642 info->modified = modified;
17643 repl = *tp;
17644 }
17645 else
17646 return NULL_TREE;
0136f8f0 17647 }
2044a4c3
JJ
17648
17649 if (tp != orig_tp)
0136f8f0 17650 {
2044a4c3 17651 repl = build_fold_addr_expr (repl);
355fe088 17652 gimple *stmt;
932b6d61
JJ
17653 if (is_gimple_debug (info->stmt))
17654 {
17655 tree vexpr = make_node (DEBUG_EXPR_DECL);
17656 stmt = gimple_build_debug_source_bind (vexpr, repl, NULL);
17657 DECL_ARTIFICIAL (vexpr) = 1;
17658 TREE_TYPE (vexpr) = TREE_TYPE (repl);
17659 DECL_MODE (vexpr) = TYPE_MODE (TREE_TYPE (repl));
17660 repl = vexpr;
17661 }
17662 else
17663 {
b731b390 17664 stmt = gimple_build_assign (make_ssa_name (TREE_TYPE (repl)), repl);
932b6d61
JJ
17665 repl = gimple_assign_lhs (stmt);
17666 }
2044a4c3 17667 gimple_stmt_iterator gsi = gsi_for_stmt (info->stmt);
0136f8f0 17668 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
2044a4c3 17669 *orig_tp = repl;
0136f8f0 17670 }
2044a4c3 17671 else if (!useless_type_conversion_p (TREE_TYPE (*tp), TREE_TYPE (repl)))
0136f8f0
AH
17672 {
17673 tree vce = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (*tp), repl);
17674 *tp = vce;
17675 }
17676 else
17677 *tp = repl;
17678
17679 info->modified = true;
0136f8f0
AH
17680 return NULL_TREE;
17681}
17682
17683/* Traverse the function body and perform all modifications as
17684 described in ADJUSTMENTS. At function return, ADJUSTMENTS will be
17685 modified such that the replacement/reduction value will now be an
17686 offset into the corresponding simd_array.
17687
17688 This function will replace all function argument uses with their
17689 corresponding simd array elements, and ajust the return values
17690 accordingly. */
17691
17692static void
17693ipa_simd_modify_function_body (struct cgraph_node *node,
17694 ipa_parm_adjustment_vec adjustments,
17695 tree retval_array, tree iter)
17696{
17697 basic_block bb;
2044a4c3 17698 unsigned int i, j, l;
0136f8f0
AH
17699
17700 /* Re-use the adjustments array, but this time use it to replace
17701 every function argument use to an offset into the corresponding
17702 simd_array. */
17703 for (i = 0, j = 0; i < node->simdclone->nargs; ++i, ++j)
17704 {
17705 if (!node->simdclone->args[i].vector_arg)
17706 continue;
17707
17708 tree basetype = TREE_TYPE (node->simdclone->args[i].orig_arg);
17709 tree vectype = TREE_TYPE (node->simdclone->args[i].vector_arg);
17710 adjustments[j].new_decl
17711 = build4 (ARRAY_REF,
17712 basetype,
17713 node->simdclone->args[i].simd_array,
17714 iter,
17715 NULL_TREE, NULL_TREE);
17716 if (adjustments[j].op == IPA_PARM_OP_NONE
17717 && TYPE_VECTOR_SUBPARTS (vectype) < node->simdclone->simdlen)
17718 j += node->simdclone->simdlen / TYPE_VECTOR_SUBPARTS (vectype) - 1;
17719 }
17720
2044a4c3
JJ
17721 l = adjustments.length ();
17722 for (i = 1; i < num_ssa_names; i++)
17723 {
17724 tree name = ssa_name (i);
17725 if (name
17726 && SSA_NAME_VAR (name)
17727 && TREE_CODE (SSA_NAME_VAR (name)) == PARM_DECL)
17728 {
17729 for (j = 0; j < l; j++)
17730 if (SSA_NAME_VAR (name) == adjustments[j].base
17731 && adjustments[j].new_decl)
17732 {
17733 tree base_var;
17734 if (adjustments[j].new_ssa_base == NULL_TREE)
17735 {
17736 base_var
17737 = copy_var_decl (adjustments[j].base,
17738 DECL_NAME (adjustments[j].base),
17739 TREE_TYPE (adjustments[j].base));
17740 adjustments[j].new_ssa_base = base_var;
17741 }
17742 else
17743 base_var = adjustments[j].new_ssa_base;
17744 if (SSA_NAME_IS_DEFAULT_DEF (name))
17745 {
17746 bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
17747 gimple_stmt_iterator gsi = gsi_after_labels (bb);
17748 tree new_decl = unshare_expr (adjustments[j].new_decl);
17749 set_ssa_default_def (cfun, adjustments[j].base, NULL_TREE);
17750 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
17751 SSA_NAME_IS_DEFAULT_DEF (name) = 0;
355fe088 17752 gimple *stmt = gimple_build_assign (name, new_decl);
2044a4c3
JJ
17753 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
17754 }
17755 else
17756 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
17757 }
17758 }
17759 }
17760
0136f8f0
AH
17761 struct modify_stmt_info info;
17762 info.adjustments = adjustments;
17763
17764 FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl))
17765 {
17766 gimple_stmt_iterator gsi;
17767
17768 gsi = gsi_start_bb (bb);
17769 while (!gsi_end_p (gsi))
17770 {
355fe088 17771 gimple *stmt = gsi_stmt (gsi);
0136f8f0
AH
17772 info.stmt = stmt;
17773 struct walk_stmt_info wi;
17774
17775 memset (&wi, 0, sizeof (wi));
17776 info.modified = false;
17777 wi.info = &info;
17778 walk_gimple_op (stmt, ipa_simd_modify_stmt_ops, &wi);
17779
538dd0b7 17780 if (greturn *return_stmt = dyn_cast <greturn *> (stmt))
0136f8f0 17781 {
538dd0b7 17782 tree retval = gimple_return_retval (return_stmt);
0136f8f0
AH
17783 if (!retval)
17784 {
17785 gsi_remove (&gsi, true);
17786 continue;
17787 }
17788
17789 /* Replace `return foo' with `retval_array[iter] = foo'. */
17790 tree ref = build4 (ARRAY_REF, TREE_TYPE (retval),
17791 retval_array, iter, NULL, NULL);
17792 stmt = gimple_build_assign (ref, retval);
17793 gsi_replace (&gsi, stmt, true);
17794 info.modified = true;
17795 }
17796
17797 if (info.modified)
17798 {
17799 update_stmt (stmt);
17800 if (maybe_clean_eh_stmt (stmt))
17801 gimple_purge_dead_eh_edges (gimple_bb (stmt));
17802 }
17803 gsi_next (&gsi);
17804 }
17805 }
17806}
17807
e01d41e5
JJ
17808/* Helper function of simd_clone_adjust, return linear step addend
17809 of Ith argument. */
17810
17811static tree
17812simd_clone_linear_addend (struct cgraph_node *node, unsigned int i,
17813 tree addtype, basic_block entry_bb)
17814{
17815 tree ptype = NULL_TREE;
17816 switch (node->simdclone->args[i].arg_type)
17817 {
17818 case SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP:
17819 case SIMD_CLONE_ARG_TYPE_LINEAR_REF_CONSTANT_STEP:
17820 case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_CONSTANT_STEP:
17821 case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP:
17822 return build_int_cst (addtype, node->simdclone->args[i].linear_step);
17823 case SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP:
17824 case SIMD_CLONE_ARG_TYPE_LINEAR_REF_VARIABLE_STEP:
17825 ptype = TREE_TYPE (node->simdclone->args[i].orig_arg);
17826 break;
17827 case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_VARIABLE_STEP:
17828 case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_VARIABLE_STEP:
17829 ptype = TREE_TYPE (TREE_TYPE (node->simdclone->args[i].orig_arg));
17830 break;
17831 default:
17832 gcc_unreachable ();
17833 }
17834
17835 unsigned int idx = node->simdclone->args[i].linear_step;
17836 tree arg = node->simdclone->args[idx].orig_arg;
17837 gcc_assert (is_gimple_reg_type (TREE_TYPE (arg)));
17838 gimple_stmt_iterator gsi = gsi_after_labels (entry_bb);
17839 gimple *g;
17840 tree ret;
17841 if (is_gimple_reg (arg))
17842 ret = get_or_create_ssa_default_def (cfun, arg);
17843 else
17844 {
17845 g = gimple_build_assign (make_ssa_name (TREE_TYPE (arg)), arg);
17846 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
17847 ret = gimple_assign_lhs (g);
17848 }
17849 if (TREE_CODE (TREE_TYPE (arg)) == REFERENCE_TYPE)
17850 {
17851 g = gimple_build_assign (make_ssa_name (TREE_TYPE (TREE_TYPE (arg))),
17852 build_simple_mem_ref (ret));
17853 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
17854 ret = gimple_assign_lhs (g);
17855 }
17856 if (!useless_type_conversion_p (addtype, TREE_TYPE (ret)))
17857 {
17858 g = gimple_build_assign (make_ssa_name (addtype), NOP_EXPR, ret);
17859 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
17860 ret = gimple_assign_lhs (g);
17861 }
17862 if (POINTER_TYPE_P (ptype))
17863 {
17864 tree size = TYPE_SIZE_UNIT (TREE_TYPE (ptype));
17865 if (size && TREE_CODE (size) == INTEGER_CST)
17866 {
17867 g = gimple_build_assign (make_ssa_name (addtype), MULT_EXPR,
17868 ret, fold_convert (addtype, size));
17869 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
17870 ret = gimple_assign_lhs (g);
17871 }
17872 }
17873 return ret;
17874}
17875
0136f8f0
AH
17876/* Adjust the argument types in NODE to their appropriate vector
17877 counterparts. */
17878
17879static void
17880simd_clone_adjust (struct cgraph_node *node)
17881{
17882 push_cfun (DECL_STRUCT_FUNCTION (node->decl));
17883
17884 targetm.simd_clone.adjust (node);
17885
17886 tree retval = simd_clone_adjust_return_type (node);
17887 ipa_parm_adjustment_vec adjustments
17888 = simd_clone_adjust_argument_types (node);
17889
17890 push_gimplify_context ();
17891
17892 gimple_seq seq = simd_clone_init_simd_arrays (node, adjustments);
17893
17894 /* Adjust all uses of vector arguments accordingly. Adjust all
17895 return values accordingly. */
17896 tree iter = create_tmp_var (unsigned_type_node, "iter");
b731b390
JJ
17897 tree iter1 = make_ssa_name (iter);
17898 tree iter2 = make_ssa_name (iter);
0136f8f0
AH
17899 ipa_simd_modify_function_body (node, adjustments, retval, iter1);
17900
17901 /* Initialize the iteration variable. */
17902 basic_block entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
17903 basic_block body_bb = split_block_after_labels (entry_bb)->dest;
17904 gimple_stmt_iterator gsi = gsi_after_labels (entry_bb);
17905 /* Insert the SIMD array and iv initialization at function
17906 entry. */
17907 gsi_insert_seq_before (&gsi, seq, GSI_NEW_STMT);
17908
17909 pop_gimplify_context (NULL);
17910
17911 /* Create a new BB right before the original exit BB, to hold the
17912 iteration increment and the condition/branch. */
17913 basic_block orig_exit = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), 0)->src;
17914 basic_block incr_bb = create_empty_bb (orig_exit);
33d9078a 17915 add_bb_to_loop (incr_bb, body_bb->loop_father);
0136f8f0
AH
17916 /* The succ of orig_exit was EXIT_BLOCK_PTR_FOR_FN (cfun), with an empty
17917 flag. Set it now to be a FALLTHRU_EDGE. */
17918 gcc_assert (EDGE_COUNT (orig_exit->succs) == 1);
17919 EDGE_SUCC (orig_exit, 0)->flags |= EDGE_FALLTHRU;
17920 for (unsigned i = 0;
17921 i < EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds); ++i)
17922 {
17923 edge e = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), i);
17924 redirect_edge_succ (e, incr_bb);
17925 }
17926 edge e = make_edge (incr_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
17927 e->probability = REG_BR_PROB_BASE;
17928 gsi = gsi_last_bb (incr_bb);
355fe088 17929 gimple *g = gimple_build_assign (iter2, PLUS_EXPR, iter1,
0d0e4a03 17930 build_int_cst (unsigned_type_node, 1));
0136f8f0
AH
17931 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
17932
17933 /* Mostly annotate the loop for the vectorizer (the rest is done below). */
17934 struct loop *loop = alloc_loop ();
b15b5979 17935 cfun->has_force_vectorize_loops = true;
0136f8f0 17936 loop->safelen = node->simdclone->simdlen;
b15b5979 17937 loop->force_vectorize = true;
0136f8f0 17938 loop->header = body_bb;
0136f8f0
AH
17939
17940 /* Branch around the body if the mask applies. */
17941 if (node->simdclone->inbranch)
17942 {
17943 gimple_stmt_iterator gsi = gsi_last_bb (loop->header);
17944 tree mask_array
17945 = node->simdclone->args[node->simdclone->nargs - 1].simd_array;
b731b390 17946 tree mask = make_ssa_name (TREE_TYPE (TREE_TYPE (mask_array)));
0136f8f0
AH
17947 tree aref = build4 (ARRAY_REF,
17948 TREE_TYPE (TREE_TYPE (mask_array)),
17949 mask_array, iter1,
17950 NULL, NULL);
17951 g = gimple_build_assign (mask, aref);
17952 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
17953 int bitsize = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (aref)));
17954 if (!INTEGRAL_TYPE_P (TREE_TYPE (aref)))
17955 {
17956 aref = build1 (VIEW_CONVERT_EXPR,
17957 build_nonstandard_integer_type (bitsize, 0), mask);
b731b390 17958 mask = make_ssa_name (TREE_TYPE (aref));
0136f8f0
AH
17959 g = gimple_build_assign (mask, aref);
17960 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
17961 }
17962
17963 g = gimple_build_cond (EQ_EXPR, mask, build_zero_cst (TREE_TYPE (mask)),
17964 NULL, NULL);
17965 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
17966 make_edge (loop->header, incr_bb, EDGE_TRUE_VALUE);
17967 FALLTHRU_EDGE (loop->header)->flags = EDGE_FALSE_VALUE;
17968 }
17969
17970 /* Generate the condition. */
17971 g = gimple_build_cond (LT_EXPR,
17972 iter2,
17973 build_int_cst (unsigned_type_node,
17974 node->simdclone->simdlen),
17975 NULL, NULL);
17976 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
17977 e = split_block (incr_bb, gsi_stmt (gsi));
17978 basic_block latch_bb = e->dest;
33d9078a 17979 basic_block new_exit_bb;
c4d281b2 17980 new_exit_bb = split_block_after_labels (latch_bb)->dest;
0136f8f0
AH
17981 loop->latch = latch_bb;
17982
17983 redirect_edge_succ (FALLTHRU_EDGE (latch_bb), body_bb);
17984
17985 make_edge (incr_bb, new_exit_bb, EDGE_FALSE_VALUE);
17986 /* The successor of incr_bb is already pointing to latch_bb; just
17987 change the flags.
17988 make_edge (incr_bb, latch_bb, EDGE_TRUE_VALUE); */
17989 FALLTHRU_EDGE (incr_bb)->flags = EDGE_TRUE_VALUE;
17990
538dd0b7 17991 gphi *phi = create_phi_node (iter1, body_bb);
0136f8f0
AH
17992 edge preheader_edge = find_edge (entry_bb, body_bb);
17993 edge latch_edge = single_succ_edge (latch_bb);
17994 add_phi_arg (phi, build_zero_cst (unsigned_type_node), preheader_edge,
17995 UNKNOWN_LOCATION);
17996 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
17997
17998 /* Generate the new return. */
17999 gsi = gsi_last_bb (new_exit_bb);
18000 if (retval
18001 && TREE_CODE (retval) == VIEW_CONVERT_EXPR
18002 && TREE_CODE (TREE_OPERAND (retval, 0)) == RESULT_DECL)
18003 retval = TREE_OPERAND (retval, 0);
18004 else if (retval)
18005 {
18006 retval = build1 (VIEW_CONVERT_EXPR,
18007 TREE_TYPE (TREE_TYPE (node->decl)),
18008 retval);
18009 retval = force_gimple_operand_gsi (&gsi, retval, true, NULL,
18010 false, GSI_CONTINUE_LINKING);
18011 }
18012 g = gimple_build_return (retval);
18013 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
18014
18015 /* Handle aligned clauses by replacing default defs of the aligned
18016 uniform args with __builtin_assume_aligned (arg_N(D), alignment)
18017 lhs. Handle linear by adding PHIs. */
18018 for (unsigned i = 0; i < node->simdclone->nargs; i++)
3446fe48
JJ
18019 if (node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
18020 && (TREE_ADDRESSABLE (node->simdclone->args[i].orig_arg)
18021 || !is_gimple_reg_type
18022 (TREE_TYPE (node->simdclone->args[i].orig_arg))))
18023 {
18024 tree orig_arg = node->simdclone->args[i].orig_arg;
18025 if (is_gimple_reg_type (TREE_TYPE (orig_arg)))
18026 iter1 = make_ssa_name (TREE_TYPE (orig_arg));
18027 else
18028 {
18029 iter1 = create_tmp_var_raw (TREE_TYPE (orig_arg));
18030 gimple_add_tmp_var (iter1);
18031 }
18032 gsi = gsi_after_labels (entry_bb);
18033 g = gimple_build_assign (iter1, orig_arg);
18034 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
18035 gsi = gsi_after_labels (body_bb);
18036 g = gimple_build_assign (orig_arg, iter1);
18037 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
18038 }
18039 else if (node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
18040 && DECL_BY_REFERENCE (node->simdclone->args[i].orig_arg)
18041 && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
18042 == REFERENCE_TYPE
18043 && TREE_ADDRESSABLE
18044 (TREE_TYPE (TREE_TYPE (node->simdclone->args[i].orig_arg))))
18045 {
18046 tree orig_arg = node->simdclone->args[i].orig_arg;
18047 tree def = ssa_default_def (cfun, orig_arg);
18048 if (def && !has_zero_uses (def))
18049 {
18050 iter1 = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (orig_arg)));
18051 gimple_add_tmp_var (iter1);
18052 gsi = gsi_after_labels (entry_bb);
18053 g = gimple_build_assign (iter1, build_simple_mem_ref (def));
18054 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
18055 gsi = gsi_after_labels (body_bb);
18056 g = gimple_build_assign (build_simple_mem_ref (def), iter1);
18057 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
18058 }
18059 }
18060 else if (node->simdclone->args[i].alignment
18061 && node->simdclone->args[i].arg_type
18062 == SIMD_CLONE_ARG_TYPE_UNIFORM
18063 && (node->simdclone->args[i].alignment
18064 & (node->simdclone->args[i].alignment - 1)) == 0
18065 && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
18066 == POINTER_TYPE)
0136f8f0
AH
18067 {
18068 unsigned int alignment = node->simdclone->args[i].alignment;
18069 tree orig_arg = node->simdclone->args[i].orig_arg;
18070 tree def = ssa_default_def (cfun, orig_arg);
ab04b46e 18071 if (def && !has_zero_uses (def))
0136f8f0
AH
18072 {
18073 tree fn = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
18074 gimple_seq seq = NULL;
18075 bool need_cvt = false;
538dd0b7 18076 gcall *call
0136f8f0
AH
18077 = gimple_build_call (fn, 2, def, size_int (alignment));
18078 g = call;
18079 if (!useless_type_conversion_p (TREE_TYPE (orig_arg),
18080 ptr_type_node))
18081 need_cvt = true;
b731b390 18082 tree t = make_ssa_name (need_cvt ? ptr_type_node : orig_arg);
0136f8f0
AH
18083 gimple_call_set_lhs (g, t);
18084 gimple_seq_add_stmt_without_update (&seq, g);
18085 if (need_cvt)
18086 {
b731b390 18087 t = make_ssa_name (orig_arg);
0d0e4a03 18088 g = gimple_build_assign (t, NOP_EXPR, gimple_call_lhs (g));
0136f8f0
AH
18089 gimple_seq_add_stmt_without_update (&seq, g);
18090 }
18091 gsi_insert_seq_on_edge_immediate
18092 (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)), seq);
18093
18094 entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
18095 int freq = compute_call_stmt_bb_frequency (current_function_decl,
18096 entry_bb);
d52f5295
ML
18097 node->create_edge (cgraph_node::get_create (fn),
18098 call, entry_bb->count, freq);
0136f8f0
AH
18099
18100 imm_use_iterator iter;
18101 use_operand_p use_p;
355fe088 18102 gimple *use_stmt;
0136f8f0
AH
18103 tree repl = gimple_get_lhs (g);
18104 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
18105 if (is_gimple_debug (use_stmt) || use_stmt == call)
18106 continue;
18107 else
18108 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
18109 SET_USE (use_p, repl);
18110 }
18111 }
d9a6bd32
JJ
18112 else if ((node->simdclone->args[i].arg_type
18113 == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
18114 || (node->simdclone->args[i].arg_type
e01d41e5
JJ
18115 == SIMD_CLONE_ARG_TYPE_LINEAR_REF_CONSTANT_STEP)
18116 || (node->simdclone->args[i].arg_type
18117 == SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP)
18118 || (node->simdclone->args[i].arg_type
18119 == SIMD_CLONE_ARG_TYPE_LINEAR_REF_VARIABLE_STEP))
0136f8f0
AH
18120 {
18121 tree orig_arg = node->simdclone->args[i].orig_arg;
0136f8f0
AH
18122 gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
18123 || POINTER_TYPE_P (TREE_TYPE (orig_arg)));
3446fe48
JJ
18124 tree def = NULL_TREE;
18125 if (TREE_ADDRESSABLE (orig_arg))
18126 {
18127 def = make_ssa_name (TREE_TYPE (orig_arg));
18128 iter1 = make_ssa_name (TREE_TYPE (orig_arg));
18129 iter2 = make_ssa_name (TREE_TYPE (orig_arg));
18130 gsi = gsi_after_labels (entry_bb);
18131 g = gimple_build_assign (def, orig_arg);
18132 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
18133 }
18134 else
18135 {
18136 def = ssa_default_def (cfun, orig_arg);
18137 if (!def || has_zero_uses (def))
18138 def = NULL_TREE;
18139 else
18140 {
18141 iter1 = make_ssa_name (orig_arg);
18142 iter2 = make_ssa_name (orig_arg);
18143 }
18144 }
18145 if (def)
0136f8f0 18146 {
0136f8f0
AH
18147 phi = create_phi_node (iter1, body_bb);
18148 add_phi_arg (phi, def, preheader_edge, UNKNOWN_LOCATION);
18149 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
18150 enum tree_code code = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
18151 ? PLUS_EXPR : POINTER_PLUS_EXPR;
18152 tree addtype = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
18153 ? TREE_TYPE (orig_arg) : sizetype;
e01d41e5
JJ
18154 tree addcst = simd_clone_linear_addend (node, i, addtype,
18155 entry_bb);
0136f8f0 18156 gsi = gsi_last_bb (incr_bb);
e01d41e5 18157 g = gimple_build_assign (iter2, code, iter1, addcst);
0136f8f0
AH
18158 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
18159
18160 imm_use_iterator iter;
18161 use_operand_p use_p;
355fe088 18162 gimple *use_stmt;
3446fe48
JJ
18163 if (TREE_ADDRESSABLE (orig_arg))
18164 {
18165 gsi = gsi_after_labels (body_bb);
18166 g = gimple_build_assign (orig_arg, iter1);
18167 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
18168 }
18169 else
18170 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
18171 if (use_stmt == phi)
18172 continue;
18173 else
18174 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
18175 SET_USE (use_p, iter1);
0136f8f0
AH
18176 }
18177 }
d9a6bd32 18178 else if (node->simdclone->args[i].arg_type
e01d41e5
JJ
18179 == SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP
18180 || (node->simdclone->args[i].arg_type
18181 == SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_VARIABLE_STEP))
d9a6bd32
JJ
18182 {
18183 tree orig_arg = node->simdclone->args[i].orig_arg;
18184 tree def = ssa_default_def (cfun, orig_arg);
18185 gcc_assert (!TREE_ADDRESSABLE (orig_arg)
18186 && TREE_CODE (TREE_TYPE (orig_arg)) == REFERENCE_TYPE);
18187 if (def && !has_zero_uses (def))
18188 {
18189 tree rtype = TREE_TYPE (TREE_TYPE (orig_arg));
18190 iter1 = make_ssa_name (orig_arg);
18191 iter2 = make_ssa_name (orig_arg);
18192 tree iter3 = make_ssa_name (rtype);
18193 tree iter4 = make_ssa_name (rtype);
18194 tree iter5 = make_ssa_name (rtype);
18195 gsi = gsi_after_labels (entry_bb);
18196 gimple *load
18197 = gimple_build_assign (iter3, build_simple_mem_ref (def));
18198 gsi_insert_before (&gsi, load, GSI_NEW_STMT);
18199
18200 tree array = node->simdclone->args[i].simd_array;
18201 TREE_ADDRESSABLE (array) = 1;
18202 tree ptr = build_fold_addr_expr (array);
18203 phi = create_phi_node (iter1, body_bb);
18204 add_phi_arg (phi, ptr, preheader_edge, UNKNOWN_LOCATION);
18205 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
18206 g = gimple_build_assign (iter2, POINTER_PLUS_EXPR, iter1,
18207 TYPE_SIZE_UNIT (TREE_TYPE (iter3)));
18208 gsi = gsi_last_bb (incr_bb);
18209 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
18210
18211 phi = create_phi_node (iter4, body_bb);
18212 add_phi_arg (phi, iter3, preheader_edge, UNKNOWN_LOCATION);
18213 add_phi_arg (phi, iter5, latch_edge, UNKNOWN_LOCATION);
18214 enum tree_code code = INTEGRAL_TYPE_P (TREE_TYPE (iter3))
18215 ? PLUS_EXPR : POINTER_PLUS_EXPR;
18216 tree addtype = INTEGRAL_TYPE_P (TREE_TYPE (iter3))
18217 ? TREE_TYPE (iter3) : sizetype;
e01d41e5
JJ
18218 tree addcst = simd_clone_linear_addend (node, i, addtype,
18219 entry_bb);
d9a6bd32
JJ
18220 g = gimple_build_assign (iter5, code, iter4, addcst);
18221 gsi = gsi_last_bb (incr_bb);
18222 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
18223
18224 g = gimple_build_assign (build_simple_mem_ref (iter1), iter4);
18225 gsi = gsi_after_labels (body_bb);
18226 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
18227
18228 imm_use_iterator iter;
18229 use_operand_p use_p;
18230 gimple *use_stmt;
18231 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
18232 if (use_stmt == load)
18233 continue;
18234 else
18235 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
18236 SET_USE (use_p, iter1);
18237
18238 if (!TYPE_READONLY (rtype))
18239 {
18240 tree v = make_ssa_name (rtype);
18241 tree aref = build4 (ARRAY_REF, rtype, array,
18242 size_zero_node, NULL_TREE,
18243 NULL_TREE);
18244 gsi = gsi_after_labels (new_exit_bb);
18245 g = gimple_build_assign (v, aref);
18246 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
18247 g = gimple_build_assign (build_simple_mem_ref (def), v);
18248 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
18249 }
18250 }
18251 }
0136f8f0
AH
18252
18253 calculate_dominance_info (CDI_DOMINATORS);
18254 add_loop (loop, loop->header->loop_father);
18255 update_ssa (TODO_update_ssa);
18256
18257 pop_cfun ();
18258}
18259
18260/* If the function in NODE is tagged as an elemental SIMD function,
18261 create the appropriate SIMD clones. */
18262
18263static void
18264expand_simd_clones (struct cgraph_node *node)
18265{
0136f8f0
AH
18266 tree attr = lookup_attribute ("omp declare simd",
18267 DECL_ATTRIBUTES (node->decl));
e06f9964
JJ
18268 if (attr == NULL_TREE
18269 || node->global.inlined_to
18270 || lookup_attribute ("noclone", DECL_ATTRIBUTES (node->decl)))
0136f8f0 18271 return;
e06f9964 18272
0136f8f0
AH
18273 /* Ignore
18274 #pragma omp declare simd
18275 extern int foo ();
18276 in C, there we don't know the argument types at all. */
18277 if (!node->definition
18278 && TYPE_ARG_TYPES (TREE_TYPE (node->decl)) == NULL_TREE)
18279 return;
18280
18281 do
18282 {
18283 /* Start with parsing the "omp declare simd" attribute(s). */
18284 bool inbranch_clause_specified;
18285 struct cgraph_simd_clone *clone_info
18286 = simd_clone_clauses_extract (node, TREE_VALUE (attr),
18287 &inbranch_clause_specified);
18288 if (clone_info == NULL)
18289 continue;
18290
18291 int orig_simdlen = clone_info->simdlen;
18292 tree base_type = simd_clone_compute_base_data_type (node, clone_info);
18293 /* The target can return 0 (no simd clones should be created),
18294 1 (just one ISA of simd clones should be created) or higher
18295 count of ISA variants. In that case, clone_info is initialized
18296 for the first ISA variant. */
18297 int count
18298 = targetm.simd_clone.compute_vecsize_and_simdlen (node, clone_info,
18299 base_type, 0);
18300 if (count == 0)
18301 continue;
18302
18303 /* Loop over all COUNT ISA variants, and if !INBRANCH_CLAUSE_SPECIFIED,
18304 also create one inbranch and one !inbranch clone of it. */
18305 for (int i = 0; i < count * 2; i++)
18306 {
18307 struct cgraph_simd_clone *clone = clone_info;
18308 if (inbranch_clause_specified && (i & 1) != 0)
18309 continue;
18310
18311 if (i != 0)
18312 {
18313 clone = simd_clone_struct_alloc (clone_info->nargs
0136f8f0
AH
18314 + ((i & 1) != 0));
18315 simd_clone_struct_copy (clone, clone_info);
18316 /* Undo changes targetm.simd_clone.compute_vecsize_and_simdlen
18317 and simd_clone_adjust_argument_types did to the first
18318 clone's info. */
18319 clone->nargs -= clone_info->inbranch;
18320 clone->simdlen = orig_simdlen;
18321 /* And call the target hook again to get the right ISA. */
18322 targetm.simd_clone.compute_vecsize_and_simdlen (node, clone,
18323 base_type,
18324 i / 2);
18325 if ((i & 1) != 0)
18326 clone->inbranch = 1;
18327 }
18328
18329 /* simd_clone_mangle might fail if such a clone has been created
18330 already. */
18331 tree id = simd_clone_mangle (node, clone);
18332 if (id == NULL_TREE)
18333 continue;
18334
18335 /* Only when we are sure we want to create the clone actually
18336 clone the function (or definitions) or create another
18337 extern FUNCTION_DECL (for prototypes without definitions). */
18338 struct cgraph_node *n = simd_clone_create (node);
18339 if (n == NULL)
18340 continue;
18341
18342 n->simdclone = clone;
18343 clone->origin = node;
18344 clone->next_clone = NULL;
18345 if (node->simd_clones == NULL)
18346 {
18347 clone->prev_clone = n;
18348 node->simd_clones = n;
18349 }
18350 else
18351 {
18352 clone->prev_clone = node->simd_clones->simdclone->prev_clone;
18353 clone->prev_clone->simdclone->next_clone = n;
18354 node->simd_clones->simdclone->prev_clone = n;
18355 }
3dafb85c 18356 symtab->change_decl_assembler_name (n->decl, id);
0136f8f0
AH
18357 /* And finally adjust the return type, parameters and for
18358 definitions also function body. */
18359 if (node->definition)
18360 simd_clone_adjust (n);
18361 else
18362 {
18363 simd_clone_adjust_return_type (n);
18364 simd_clone_adjust_argument_types (n);
18365 }
18366 }
18367 }
18368 while ((attr = lookup_attribute ("omp declare simd", TREE_CHAIN (attr))));
18369}
18370
18371/* Entry point for IPA simd clone creation pass. */
18372
18373static unsigned int
18374ipa_omp_simd_clone (void)
18375{
18376 struct cgraph_node *node;
18377 FOR_EACH_FUNCTION (node)
18378 expand_simd_clones (node);
18379 return 0;
18380}
18381
17795822
TS
18382namespace {
18383
18384const pass_data pass_data_omp_simd_clone =
0136f8f0
AH
18385{
18386 SIMPLE_IPA_PASS, /* type */
18387 "simdclone", /* name */
18388 OPTGROUP_NONE, /* optinfo_flags */
0136f8f0
AH
18389 TV_NONE, /* tv_id */
18390 ( PROP_ssa | PROP_cfg ), /* properties_required */
18391 0, /* properties_provided */
18392 0, /* properties_destroyed */
18393 0, /* todo_flags_start */
18394 0, /* todo_flags_finish */
18395};
18396
17795822 18397class pass_omp_simd_clone : public simple_ipa_opt_pass
0136f8f0
AH
18398{
18399public:
18400 pass_omp_simd_clone(gcc::context *ctxt)
18401 : simple_ipa_opt_pass(pass_data_omp_simd_clone, ctxt)
18402 {}
18403
18404 /* opt_pass methods: */
1a3d085c 18405 virtual bool gate (function *);
be55bfe6 18406 virtual unsigned int execute (function *) { return ipa_omp_simd_clone (); }
0136f8f0
AH
18407};
18408
1a3d085c
TS
18409bool
18410pass_omp_simd_clone::gate (function *)
18411{
18412 return ((flag_openmp || flag_openmp_simd
18413 || flag_cilkplus
18414 || (in_lto_p && !flag_wpa))
18415 && (targetm.simd_clone.compute_vecsize_and_simdlen != NULL));
18416}
18417
17795822
TS
18418} // anon namespace
18419
0136f8f0
AH
18420simple_ipa_opt_pass *
18421make_pass_omp_simd_clone (gcc::context *ctxt)
18422{
18423 return new pass_omp_simd_clone (ctxt);
18424}
27a4cd48 18425
ec6fe917
IV
18426/* Helper function for omp_finish_file routine. Takes decls from V_DECLS and
18427 adds their addresses and sizes to constructor-vector V_CTOR. */
18428static void
18429add_decls_addresses_to_decl_constructor (vec<tree, va_gc> *v_decls,
18430 vec<constructor_elt, va_gc> *v_ctor)
18431{
18432 unsigned len = vec_safe_length (v_decls);
18433 for (unsigned i = 0; i < len; i++)
18434 {
18435 tree it = (*v_decls)[i];
18436 bool is_function = TREE_CODE (it) != VAR_DECL;
18437
18438 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE, build_fold_addr_expr (it));
18439 if (!is_function)
18440 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE,
18441 fold_convert (const_ptr_type_node,
18442 DECL_SIZE_UNIT (it)));
18443 }
18444}
18445
18446/* Create new symbols containing (address, size) pairs for global variables,
18447 marked with "omp declare target" attribute, as well as addresses for the
41dbbb37 18448 functions, which are outlined offloading regions. */
ec6fe917
IV
18449void
18450omp_finish_file (void)
18451{
18452 unsigned num_funcs = vec_safe_length (offload_funcs);
18453 unsigned num_vars = vec_safe_length (offload_vars);
18454
18455 if (num_funcs == 0 && num_vars == 0)
18456 return;
18457
18458 if (targetm_common.have_named_sections)
18459 {
18460 vec<constructor_elt, va_gc> *v_f, *v_v;
18461 vec_alloc (v_f, num_funcs);
18462 vec_alloc (v_v, num_vars * 2);
18463
18464 add_decls_addresses_to_decl_constructor (offload_funcs, v_f);
18465 add_decls_addresses_to_decl_constructor (offload_vars, v_v);
18466
18467 tree vars_decl_type = build_array_type_nelts (pointer_sized_int_node,
18468 num_vars * 2);
18469 tree funcs_decl_type = build_array_type_nelts (pointer_sized_int_node,
18470 num_funcs);
18471 TYPE_ALIGN (vars_decl_type) = TYPE_ALIGN (pointer_sized_int_node);
18472 TYPE_ALIGN (funcs_decl_type) = TYPE_ALIGN (pointer_sized_int_node);
18473 tree ctor_v = build_constructor (vars_decl_type, v_v);
18474 tree ctor_f = build_constructor (funcs_decl_type, v_f);
18475 TREE_CONSTANT (ctor_v) = TREE_CONSTANT (ctor_f) = 1;
18476 TREE_STATIC (ctor_v) = TREE_STATIC (ctor_f) = 1;
18477 tree funcs_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
18478 get_identifier (".offload_func_table"),
18479 funcs_decl_type);
18480 tree vars_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
18481 get_identifier (".offload_var_table"),
18482 vars_decl_type);
18483 TREE_STATIC (funcs_decl) = TREE_STATIC (vars_decl) = 1;
18484 /* Do not align tables more than TYPE_ALIGN (pointer_sized_int_node),
18485 otherwise a joint table in a binary will contain padding between
18486 tables from multiple object files. */
18487 DECL_USER_ALIGN (funcs_decl) = DECL_USER_ALIGN (vars_decl) = 1;
18488 DECL_ALIGN (funcs_decl) = TYPE_ALIGN (funcs_decl_type);
18489 DECL_ALIGN (vars_decl) = TYPE_ALIGN (vars_decl_type);
18490 DECL_INITIAL (funcs_decl) = ctor_f;
18491 DECL_INITIAL (vars_decl) = ctor_v;
18492 set_decl_section_name (funcs_decl, OFFLOAD_FUNC_TABLE_SECTION_NAME);
18493 set_decl_section_name (vars_decl, OFFLOAD_VAR_TABLE_SECTION_NAME);
18494
18495 varpool_node::finalize_decl (vars_decl);
18496 varpool_node::finalize_decl (funcs_decl);
844b0125 18497 }
ec6fe917
IV
18498 else
18499 {
18500 for (unsigned i = 0; i < num_funcs; i++)
18501 {
18502 tree it = (*offload_funcs)[i];
18503 targetm.record_offload_symbol (it);
18504 }
18505 for (unsigned i = 0; i < num_vars; i++)
18506 {
18507 tree it = (*offload_vars)[i];
18508 targetm.record_offload_symbol (it);
18509 }
18510 }
18511}
18512
9bd46bc9
NS
18513/* Find the number of threads (POS = false), or thread number (POS =
18514 true) for an OpenACC region partitioned as MASK. Setup code
18515 required for the calculation is added to SEQ. */
18516
18517static tree
18518oacc_thread_numbers (bool pos, int mask, gimple_seq *seq)
18519{
18520 tree res = pos ? NULL_TREE : build_int_cst (unsigned_type_node, 1);
18521 unsigned ix;
18522
18523 /* Start at gang level, and examine relevant dimension indices. */
18524 for (ix = GOMP_DIM_GANG; ix != GOMP_DIM_MAX; ix++)
18525 if (GOMP_DIM_MASK (ix) & mask)
18526 {
18527 tree arg = build_int_cst (unsigned_type_node, ix);
18528
18529 if (res)
18530 {
18531 /* We had an outer index, so scale that by the size of
18532 this dimension. */
18533 tree n = create_tmp_var (integer_type_node);
18534 gimple *call
18535 = gimple_build_call_internal (IFN_GOACC_DIM_SIZE, 1, arg);
18536
18537 gimple_call_set_lhs (call, n);
18538 gimple_seq_add_stmt (seq, call);
18539 res = fold_build2 (MULT_EXPR, integer_type_node, res, n);
18540 }
18541 if (pos)
18542 {
18543 /* Determine index in this dimension. */
18544 tree id = create_tmp_var (integer_type_node);
18545 gimple *call = gimple_build_call_internal
18546 (IFN_GOACC_DIM_POS, 1, arg);
18547
18548 gimple_call_set_lhs (call, id);
18549 gimple_seq_add_stmt (seq, call);
18550 if (res)
18551 res = fold_build2 (PLUS_EXPR, integer_type_node, res, id);
18552 else
18553 res = id;
18554 }
18555 }
18556
18557 if (res == NULL_TREE)
18558 res = integer_zero_node;
18559
18560 return res;
18561}
18562
18563/* Transform IFN_GOACC_LOOP calls to actual code. See
18564 expand_oacc_for for where these are generated. At the vector
18565 level, we stride loops, such that each member of a warp will
18566 operate on adjacent iterations. At the worker and gang level,
18567 each gang/warp executes a set of contiguous iterations. Chunking
18568 can override this such that each iteration engine executes a
18569 contiguous chunk, and then moves on to stride to the next chunk. */
18570
18571static void
18572oacc_xform_loop (gcall *call)
18573{
18574 gimple_stmt_iterator gsi = gsi_for_stmt (call);
18575 enum ifn_goacc_loop_kind code
18576 = (enum ifn_goacc_loop_kind) TREE_INT_CST_LOW (gimple_call_arg (call, 0));
18577 tree dir = gimple_call_arg (call, 1);
18578 tree range = gimple_call_arg (call, 2);
18579 tree step = gimple_call_arg (call, 3);
18580 tree chunk_size = NULL_TREE;
18581 unsigned mask = (unsigned) TREE_INT_CST_LOW (gimple_call_arg (call, 5));
18582 tree lhs = gimple_call_lhs (call);
18583 tree type = TREE_TYPE (lhs);
18584 tree diff_type = TREE_TYPE (range);
18585 tree r = NULL_TREE;
18586 gimple_seq seq = NULL;
18587 bool chunking = false, striding = true;
18588 unsigned outer_mask = mask & (~mask + 1); // Outermost partitioning
18589 unsigned inner_mask = mask & ~outer_mask; // Inner partitioning (if any)
18590
18591#ifdef ACCEL_COMPILER
18592 chunk_size = gimple_call_arg (call, 4);
18593 if (integer_minus_onep (chunk_size) /* Force static allocation. */
18594 || integer_zerop (chunk_size)) /* Default (also static). */
18595 {
18596 /* If we're at the gang level, we want each to execute a
18597 contiguous run of iterations. Otherwise we want each element
18598 to stride. */
18599 striding = !(outer_mask & GOMP_DIM_MASK (GOMP_DIM_GANG));
18600 chunking = false;
18601 }
18602 else
18603 {
18604 /* Chunk of size 1 is striding. */
18605 striding = integer_onep (chunk_size);
18606 chunking = !striding;
18607 }
18608#endif
18609
18610 /* striding=true, chunking=true
18611 -> invalid.
18612 striding=true, chunking=false
18613 -> chunks=1
18614 striding=false,chunking=true
18615 -> chunks=ceil (range/(chunksize*threads*step))
18616 striding=false,chunking=false
18617 -> chunk_size=ceil(range/(threads*step)),chunks=1 */
18618 push_gimplify_context (true);
18619
18620 switch (code)
18621 {
18622 default: gcc_unreachable ();
18623
18624 case IFN_GOACC_LOOP_CHUNKS:
18625 if (!chunking)
18626 r = build_int_cst (type, 1);
18627 else
18628 {
18629 /* chunk_max
18630 = (range - dir) / (chunks * step * num_threads) + dir */
18631 tree per = oacc_thread_numbers (false, mask, &seq);
18632 per = fold_convert (type, per);
18633 chunk_size = fold_convert (type, chunk_size);
18634 per = fold_build2 (MULT_EXPR, type, per, chunk_size);
18635 per = fold_build2 (MULT_EXPR, type, per, step);
18636 r = build2 (MINUS_EXPR, type, range, dir);
18637 r = build2 (PLUS_EXPR, type, r, per);
18638 r = build2 (TRUNC_DIV_EXPR, type, r, per);
18639 }
18640 break;
18641
18642 case IFN_GOACC_LOOP_STEP:
18643 {
18644 /* If striding, step by the entire compute volume, otherwise
18645 step by the inner volume. */
18646 unsigned volume = striding ? mask : inner_mask;
18647
18648 r = oacc_thread_numbers (false, volume, &seq);
18649 r = build2 (MULT_EXPR, type, fold_convert (type, r), step);
18650 }
18651 break;
18652
18653 case IFN_GOACC_LOOP_OFFSET:
18654 if (striding)
18655 {
18656 r = oacc_thread_numbers (true, mask, &seq);
18657 r = fold_convert (diff_type, r);
18658 }
18659 else
18660 {
18661 tree inner_size = oacc_thread_numbers (false, inner_mask, &seq);
18662 tree outer_size = oacc_thread_numbers (false, outer_mask, &seq);
18663 tree volume = fold_build2 (MULT_EXPR, TREE_TYPE (inner_size),
18664 inner_size, outer_size);
18665
18666 volume = fold_convert (diff_type, volume);
18667 if (chunking)
18668 chunk_size = fold_convert (diff_type, chunk_size);
18669 else
18670 {
18671 tree per = fold_build2 (MULT_EXPR, diff_type, volume, step);
18672
18673 chunk_size = build2 (MINUS_EXPR, diff_type, range, dir);
18674 chunk_size = build2 (PLUS_EXPR, diff_type, chunk_size, per);
18675 chunk_size = build2 (TRUNC_DIV_EXPR, diff_type, chunk_size, per);
18676 }
18677
18678 tree span = build2 (MULT_EXPR, diff_type, chunk_size,
18679 fold_convert (diff_type, inner_size));
18680 r = oacc_thread_numbers (true, outer_mask, &seq);
18681 r = fold_convert (diff_type, r);
18682 r = build2 (MULT_EXPR, diff_type, r, span);
18683
18684 tree inner = oacc_thread_numbers (true, inner_mask, &seq);
18685 inner = fold_convert (diff_type, inner);
18686 r = fold_build2 (PLUS_EXPR, diff_type, r, inner);
18687
18688 if (chunking)
18689 {
18690 tree chunk = fold_convert (diff_type, gimple_call_arg (call, 6));
18691 tree per
18692 = fold_build2 (MULT_EXPR, diff_type, volume, chunk_size);
18693 per = build2 (MULT_EXPR, diff_type, per, chunk);
18694
18695 r = build2 (PLUS_EXPR, diff_type, r, per);
18696 }
18697 }
18698 r = fold_build2 (MULT_EXPR, diff_type, r, step);
18699 if (type != diff_type)
18700 r = fold_convert (type, r);
18701 break;
18702
18703 case IFN_GOACC_LOOP_BOUND:
18704 if (striding)
18705 r = range;
18706 else
18707 {
18708 tree inner_size = oacc_thread_numbers (false, inner_mask, &seq);
18709 tree outer_size = oacc_thread_numbers (false, outer_mask, &seq);
18710 tree volume = fold_build2 (MULT_EXPR, TREE_TYPE (inner_size),
18711 inner_size, outer_size);
18712
18713 volume = fold_convert (diff_type, volume);
18714 if (chunking)
18715 chunk_size = fold_convert (diff_type, chunk_size);
18716 else
18717 {
18718 tree per = fold_build2 (MULT_EXPR, diff_type, volume, step);
18719
18720 chunk_size = build2 (MINUS_EXPR, diff_type, range, dir);
18721 chunk_size = build2 (PLUS_EXPR, diff_type, chunk_size, per);
18722 chunk_size = build2 (TRUNC_DIV_EXPR, diff_type, chunk_size, per);
18723 }
18724
18725 tree span = build2 (MULT_EXPR, diff_type, chunk_size,
18726 fold_convert (diff_type, inner_size));
18727
18728 r = fold_build2 (MULT_EXPR, diff_type, span, step);
18729
18730 tree offset = gimple_call_arg (call, 6);
18731 r = build2 (PLUS_EXPR, diff_type, r,
18732 fold_convert (diff_type, offset));
18733 r = build2 (integer_onep (dir) ? MIN_EXPR : MAX_EXPR,
18734 diff_type, r, range);
18735 }
18736 if (diff_type != type)
18737 r = fold_convert (type, r);
18738 break;
18739 }
18740
18741 gimplify_assign (lhs, r, &seq);
18742
18743 pop_gimplify_context (NULL);
18744
18745 gsi_replace_with_seq (&gsi, seq, true);
18746}
18747
94829f87
NS
18748/* Validate and update the dimensions for offloaded FN. ATTRS is the
18749 raw attribute. DIMS is an array of dimensions, which is returned.
18750 Returns the function level dimensionality -- the level at which an
18751 offload routine wishes to partition a loop. */
18752
18753static int
18754oacc_validate_dims (tree fn, tree attrs, int *dims)
18755{
18756 tree purpose[GOMP_DIM_MAX];
18757 unsigned ix;
18758 tree pos = TREE_VALUE (attrs);
18759 int fn_level = -1;
18760
18761 /* Make sure the attribute creator attached the dimension
18762 information. */
18763 gcc_assert (pos);
18764
18765 for (ix = 0; ix != GOMP_DIM_MAX; ix++)
18766 {
18767 purpose[ix] = TREE_PURPOSE (pos);
18768
18769 if (purpose[ix])
18770 {
18771 if (integer_zerop (purpose[ix]))
18772 fn_level = ix + 1;
18773 else if (fn_level < 0)
18774 fn_level = ix;
18775 }
18776
18777 tree val = TREE_VALUE (pos);
18778 dims[ix] = val ? TREE_INT_CST_LOW (val) : -1;
18779 pos = TREE_CHAIN (pos);
18780 }
18781
18782 bool changed = targetm.goacc.validate_dims (fn, dims, fn_level);
18783
18784 /* Default anything left to 1. */
18785 for (ix = 0; ix != GOMP_DIM_MAX; ix++)
18786 if (dims[ix] < 0)
18787 {
18788 dims[ix] = 1;
18789 changed = true;
18790 }
18791
18792 if (changed)
18793 {
18794 /* Replace the attribute with new values. */
18795 pos = NULL_TREE;
18796 for (ix = GOMP_DIM_MAX; ix--;)
18797 pos = tree_cons (purpose[ix],
18798 build_int_cst (integer_type_node, dims[ix]),
18799 pos);
18800 replace_oacc_fn_attrib (fn, pos);
18801 }
18802
18803 return fn_level;
18804}
18805
9bd46bc9
NS
18806/* Create an empty OpenACC loop structure at LOC. */
18807
18808static oacc_loop *
18809new_oacc_loop_raw (oacc_loop *parent, location_t loc)
18810{
18811 oacc_loop *loop = XCNEW (oacc_loop);
18812
18813 loop->parent = parent;
18814 loop->child = loop->sibling = NULL;
18815
18816 if (parent)
18817 {
18818 loop->sibling = parent->child;
18819 parent->child = loop;
18820 }
18821
18822 loop->loc = loc;
18823 loop->marker = NULL;
18824 memset (loop->heads, 0, sizeof (loop->heads));
18825 memset (loop->tails, 0, sizeof (loop->tails));
18826 loop->routine = NULL_TREE;
18827
18828 loop->mask = loop->flags = 0;
18829 loop->chunk_size = 0;
18830 loop->head_end = NULL;
18831
18832 return loop;
18833}
18834
18835/* Create an outermost, dummy OpenACC loop for offloaded function
18836 DECL. */
18837
18838static oacc_loop *
18839new_oacc_loop_outer (tree decl)
18840{
18841 return new_oacc_loop_raw (NULL, DECL_SOURCE_LOCATION (decl));
18842}
18843
18844/* Start a new OpenACC loop structure beginning at head marker HEAD.
18845 Link into PARENT loop. Return the new loop. */
18846
18847static oacc_loop *
18848new_oacc_loop (oacc_loop *parent, gcall *marker)
18849{
18850 oacc_loop *loop = new_oacc_loop_raw (parent, gimple_location (marker));
18851
18852 loop->marker = marker;
18853
18854 /* TODO: This is where device_type flattening would occur for the loop
18855 flags. */
18856
18857 loop->flags = TREE_INT_CST_LOW (gimple_call_arg (marker, 3));
18858
18859 tree chunk_size = integer_zero_node;
18860 if (loop->flags & OLF_GANG_STATIC)
18861 chunk_size = gimple_call_arg (marker, 4);
18862 loop->chunk_size = chunk_size;
18863
18864 return loop;
18865}
18866
18867/* Create a dummy loop encompassing a call to a openACC routine.
18868 Extract the routine's partitioning requirements. */
18869
18870static void
18871new_oacc_loop_routine (oacc_loop *parent, gcall *call, tree decl, tree attrs)
18872{
18873 oacc_loop *loop = new_oacc_loop_raw (parent, gimple_location (call));
18874 int dims[GOMP_DIM_MAX];
18875 int level = oacc_validate_dims (decl, attrs, dims);
18876
18877 gcc_assert (level >= 0);
18878
18879 loop->marker = call;
18880 loop->routine = decl;
18881 loop->mask = ((GOMP_DIM_MASK (GOMP_DIM_MAX) - 1)
18882 ^ (GOMP_DIM_MASK (level) - 1));
18883}
18884
18885/* Finish off the current OpenACC loop ending at tail marker TAIL.
18886 Return the parent loop. */
18887
18888static oacc_loop *
18889finish_oacc_loop (oacc_loop *loop)
18890{
18891 return loop->parent;
18892}
18893
18894/* Free all OpenACC loop structures within LOOP (inclusive). */
18895
18896static void
18897free_oacc_loop (oacc_loop *loop)
18898{
18899 if (loop->sibling)
18900 free_oacc_loop (loop->sibling);
18901 if (loop->child)
18902 free_oacc_loop (loop->child);
18903
18904 free (loop);
18905}
18906
18907/* Dump out the OpenACC loop head or tail beginning at FROM. */
18908
18909static void
18910dump_oacc_loop_part (FILE *file, gcall *from, int depth,
18911 const char *title, int level)
18912{
18913 enum ifn_unique_kind kind
18914 = (enum ifn_unique_kind) TREE_INT_CST_LOW (gimple_call_arg (from, 0));
18915
18916 fprintf (file, "%*s%s-%d:\n", depth * 2, "", title, level);
18917 for (gimple_stmt_iterator gsi = gsi_for_stmt (from);;)
18918 {
18919 gimple *stmt = gsi_stmt (gsi);
18920
18921 if (is_gimple_call (stmt)
18922 && gimple_call_internal_p (stmt)
18923 && gimple_call_internal_fn (stmt) == IFN_UNIQUE)
18924 {
18925 enum ifn_unique_kind k
18926 = ((enum ifn_unique_kind) TREE_INT_CST_LOW
18927 (gimple_call_arg (stmt, 0)));
18928
18929 if (k == kind && stmt != from)
18930 break;
18931 }
18932 print_gimple_stmt (file, stmt, depth * 2 + 2, 0);
18933
18934 gsi_next (&gsi);
18935 while (gsi_end_p (gsi))
18936 gsi = gsi_start_bb (single_succ (gsi_bb (gsi)));
18937 }
18938}
18939
18940/* Dump OpenACC loops LOOP, its siblings and its children. */
18941
18942static void
18943dump_oacc_loop (FILE *file, oacc_loop *loop, int depth)
18944{
18945 int ix;
18946
18947 fprintf (file, "%*sLoop %x(%x) %s:%u\n", depth * 2, "",
18948 loop->flags, loop->mask,
18949 LOCATION_FILE (loop->loc), LOCATION_LINE (loop->loc));
18950
18951 if (loop->marker)
18952 print_gimple_stmt (file, loop->marker, depth * 2, 0);
18953
18954 if (loop->routine)
18955 fprintf (file, "%*sRoutine %s:%u:%s\n",
18956 depth * 2, "", DECL_SOURCE_FILE (loop->routine),
18957 DECL_SOURCE_LINE (loop->routine),
18958 IDENTIFIER_POINTER (DECL_NAME (loop->routine)));
18959
18960 for (ix = GOMP_DIM_GANG; ix != GOMP_DIM_MAX; ix++)
18961 if (loop->heads[ix])
18962 dump_oacc_loop_part (file, loop->heads[ix], depth, "Head", ix);
18963 for (ix = GOMP_DIM_MAX; ix--;)
18964 if (loop->tails[ix])
18965 dump_oacc_loop_part (file, loop->tails[ix], depth, "Tail", ix);
18966
18967 if (loop->child)
18968 dump_oacc_loop (file, loop->child, depth + 1);
18969 if (loop->sibling)
18970 dump_oacc_loop (file, loop->sibling, depth);
18971}
18972
18973void debug_oacc_loop (oacc_loop *);
18974
18975/* Dump loops to stderr. */
18976
18977DEBUG_FUNCTION void
18978debug_oacc_loop (oacc_loop *loop)
18979{
18980 dump_oacc_loop (stderr, loop, 0);
18981}
18982
18983/* DFS walk of basic blocks BB onwards, creating OpenACC loop
18984 structures as we go. By construction these loops are properly
18985 nested. */
18986
18987static void
18988oacc_loop_discover_walk (oacc_loop *loop, basic_block bb)
18989{
18990 int marker = 0;
18991 int remaining = 0;
18992
18993 if (bb->flags & BB_VISITED)
18994 return;
18995
18996 follow:
18997 bb->flags |= BB_VISITED;
18998
18999 /* Scan for loop markers. */
19000 for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);
19001 gsi_next (&gsi))
19002 {
19003 gimple *stmt = gsi_stmt (gsi);
19004
19005 if (!is_gimple_call (stmt))
19006 continue;
19007
19008 gcall *call = as_a <gcall *> (stmt);
19009
19010 /* If this is a routine, make a dummy loop for it. */
19011 if (tree decl = gimple_call_fndecl (call))
19012 if (tree attrs = get_oacc_fn_attrib (decl))
19013 {
19014 gcc_assert (!marker);
19015 new_oacc_loop_routine (loop, call, decl, attrs);
19016 }
19017
19018 if (!gimple_call_internal_p (call))
19019 continue;
19020
19021 if (gimple_call_internal_fn (call) != IFN_UNIQUE)
19022 continue;
19023
19024 enum ifn_unique_kind kind
19025 = (enum ifn_unique_kind) TREE_INT_CST_LOW (gimple_call_arg (call, 0));
19026 if (kind == IFN_UNIQUE_OACC_HEAD_MARK
19027 || kind == IFN_UNIQUE_OACC_TAIL_MARK)
19028 {
19029 if (gimple_call_num_args (call) == 2)
19030 {
19031 gcc_assert (marker && !remaining);
19032 marker = 0;
19033 if (kind == IFN_UNIQUE_OACC_TAIL_MARK)
19034 loop = finish_oacc_loop (loop);
19035 else
19036 loop->head_end = call;
19037 }
19038 else
19039 {
19040 int count = TREE_INT_CST_LOW (gimple_call_arg (call, 2));
19041
19042 if (!marker)
19043 {
19044 if (kind == IFN_UNIQUE_OACC_HEAD_MARK)
19045 loop = new_oacc_loop (loop, call);
19046 remaining = count;
19047 }
19048 gcc_assert (count == remaining);
19049 if (remaining)
19050 {
19051 remaining--;
19052 if (kind == IFN_UNIQUE_OACC_HEAD_MARK)
19053 loop->heads[marker] = call;
19054 else
19055 loop->tails[remaining] = call;
19056 }
19057 marker++;
19058 }
19059 }
19060 }
19061 if (remaining || marker)
19062 {
19063 bb = single_succ (bb);
19064 gcc_assert (single_pred_p (bb) && !(bb->flags & BB_VISITED));
19065 goto follow;
19066 }
19067
19068 /* Walk successor blocks. */
19069 edge e;
19070 edge_iterator ei;
19071
19072 FOR_EACH_EDGE (e, ei, bb->succs)
19073 oacc_loop_discover_walk (loop, e->dest);
19074}
19075
19076/* LOOP is the first sibling. Reverse the order in place and return
19077 the new first sibling. Recurse to child loops. */
19078
19079static oacc_loop *
19080oacc_loop_sibling_nreverse (oacc_loop *loop)
19081{
19082 oacc_loop *last = NULL;
19083 do
19084 {
19085 if (loop->child)
19086 loop->child = oacc_loop_sibling_nreverse (loop->child);
19087
19088 oacc_loop *next = loop->sibling;
19089 loop->sibling = last;
19090 last = loop;
19091 loop = next;
19092 }
19093 while (loop);
19094
19095 return last;
19096}
19097
19098/* Discover the OpenACC loops marked up by HEAD and TAIL markers for
19099 the current function. */
19100
19101static oacc_loop *
19102oacc_loop_discovery ()
19103{
19104 basic_block bb;
19105
19106 oacc_loop *top = new_oacc_loop_outer (current_function_decl);
19107 oacc_loop_discover_walk (top, ENTRY_BLOCK_PTR_FOR_FN (cfun));
19108
19109 /* The siblings were constructed in reverse order, reverse them so
19110 that diagnostics come out in an unsurprising order. */
19111 top = oacc_loop_sibling_nreverse (top);
19112
19113 /* Reset the visited flags. */
19114 FOR_ALL_BB_FN (bb, cfun)
19115 bb->flags &= ~BB_VISITED;
19116
19117 return top;
19118}
19119
19120/* Transform the abstract internal function markers starting at FROM
19121 to be for partitioning level LEVEL. Stop when we meet another HEAD
19122 or TAIL marker. */
19123
19124static void
19125oacc_loop_xform_head_tail (gcall *from, int level)
19126{
19127 enum ifn_unique_kind kind
19128 = (enum ifn_unique_kind) TREE_INT_CST_LOW (gimple_call_arg (from, 0));
19129 tree replacement = build_int_cst (unsigned_type_node, level);
19130
19131 for (gimple_stmt_iterator gsi = gsi_for_stmt (from);;)
19132 {
19133 gimple *stmt = gsi_stmt (gsi);
19134
19135 if (is_gimple_call (stmt)
19136 && gimple_call_internal_p (stmt)
19137 && gimple_call_internal_fn (stmt) == IFN_UNIQUE)
19138 {
19139 enum ifn_unique_kind k
19140 = ((enum ifn_unique_kind)
19141 TREE_INT_CST_LOW (gimple_call_arg (stmt, 0)));
19142
19143 if (k == IFN_UNIQUE_OACC_FORK || k == IFN_UNIQUE_OACC_JOIN)
19144 *gimple_call_arg_ptr (stmt, 2) = replacement;
19145 else if (k == kind && stmt != from)
19146 break;
19147 }
e5014671
NS
19148 else if (is_gimple_call (stmt)
19149 && gimple_call_internal_p (stmt)
19150 && gimple_call_internal_fn (stmt) == IFN_GOACC_REDUCTION)
19151 *gimple_call_arg_ptr (stmt, 3) = replacement;
19152
9bd46bc9
NS
19153 gsi_next (&gsi);
19154 while (gsi_end_p (gsi))
19155 gsi = gsi_start_bb (single_succ (gsi_bb (gsi)));
19156 }
19157}
19158
19159/* Transform the IFN_GOACC_LOOP internal functions by providing the
19160 determined partitioning mask and chunking argument. */
19161
19162static void
19163oacc_loop_xform_loop (gcall *end_marker, tree mask_arg, tree chunk_arg)
19164{
19165 gimple_stmt_iterator gsi = gsi_for_stmt (end_marker);
19166
19167 for (;;)
19168 {
19169 for (; !gsi_end_p (gsi); gsi_next (&gsi))
19170 {
19171 gimple *stmt = gsi_stmt (gsi);
19172
19173 if (!is_gimple_call (stmt))
19174 continue;
19175
19176 gcall *call = as_a <gcall *> (stmt);
19177
19178 if (!gimple_call_internal_p (call))
19179 continue;
19180
19181 if (gimple_call_internal_fn (call) != IFN_GOACC_LOOP)
19182 continue;
19183
19184 *gimple_call_arg_ptr (call, 5) = mask_arg;
19185 *gimple_call_arg_ptr (call, 4) = chunk_arg;
19186 if (TREE_INT_CST_LOW (gimple_call_arg (call, 0))
19187 == IFN_GOACC_LOOP_BOUND)
19188 return;
19189 }
19190
19191 /* If we didn't see LOOP_BOUND, it should be in the single
19192 successor block. */
19193 basic_block bb = single_succ (gsi_bb (gsi));
19194 gsi = gsi_start_bb (bb);
19195 }
19196}
19197
19198/* Process the discovered OpenACC loops, setting the correct
19199 partitioning level etc. */
19200
19201static void
19202oacc_loop_process (oacc_loop *loop)
19203{
19204 if (loop->child)
19205 oacc_loop_process (loop->child);
19206
19207 if (loop->mask && !loop->routine)
19208 {
19209 int ix;
19210 unsigned mask = loop->mask;
19211 unsigned dim = GOMP_DIM_GANG;
19212 tree mask_arg = build_int_cst (unsigned_type_node, mask);
19213 tree chunk_arg = loop->chunk_size;
19214
19215 oacc_loop_xform_loop (loop->head_end, mask_arg, chunk_arg);
19216
19217 for (ix = 0; ix != GOMP_DIM_MAX && loop->heads[ix]; ix++)
19218 {
19219 gcc_assert (mask);
19220
19221 while (!(GOMP_DIM_MASK (dim) & mask))
19222 dim++;
19223
19224 oacc_loop_xform_head_tail (loop->heads[ix], dim);
19225 oacc_loop_xform_head_tail (loop->tails[ix], dim);
19226
19227 mask ^= GOMP_DIM_MASK (dim);
19228 }
19229 }
19230
19231 if (loop->sibling)
19232 oacc_loop_process (loop->sibling);
19233}
19234
19235/* Walk the OpenACC loop heirarchy checking and assigning the
19236 programmer-specified partitionings. OUTER_MASK is the partitioning
c5a64cfe
NS
19237 this loop is contained within. Return true if we contain an
19238 auto-partitionable loop. */
9bd46bc9 19239
c5a64cfe 19240static bool
9bd46bc9
NS
19241oacc_loop_fixed_partitions (oacc_loop *loop, unsigned outer_mask)
19242{
19243 unsigned this_mask = loop->mask;
19244 bool has_auto = false;
19245 bool noisy = true;
19246
19247#ifdef ACCEL_COMPILER
19248 /* When device_type is supported, we want the device compiler to be
19249 noisy, if the loop parameters are device_type-specific. */
19250 noisy = false;
19251#endif
19252
19253 if (!loop->routine)
19254 {
19255 bool auto_par = (loop->flags & OLF_AUTO) != 0;
19256 bool seq_par = (loop->flags & OLF_SEQ) != 0;
19257
19258 this_mask = ((loop->flags >> OLF_DIM_BASE)
19259 & (GOMP_DIM_MASK (GOMP_DIM_MAX) - 1));
19260
19261 if ((this_mask != 0) + auto_par + seq_par > 1)
19262 {
19263 if (noisy)
19264 error_at (loop->loc,
19265 seq_par
19266 ? "%<seq%> overrides other OpenACC loop specifiers"
19267 : "%<auto%> conflicts with other OpenACC loop specifiers");
19268 auto_par = false;
19269 loop->flags &= ~OLF_AUTO;
19270 if (seq_par)
19271 {
19272 loop->flags &=
19273 ~((GOMP_DIM_MASK (GOMP_DIM_MAX) - 1) << OLF_DIM_BASE);
19274 this_mask = 0;
19275 }
19276 }
19277 if (auto_par && (loop->flags & OLF_INDEPENDENT))
19278 has_auto = true;
19279 }
19280
19281 if (this_mask & outer_mask)
19282 {
19283 const oacc_loop *outer;
19284 for (outer = loop->parent; outer; outer = outer->parent)
19285 if (outer->mask & this_mask)
19286 break;
19287
19288 if (noisy)
19289 {
19290 if (outer)
19291 {
19292 error_at (loop->loc,
19293 "%s uses same OpenACC parallelism as containing loop",
19294 loop->routine ? "routine call" : "inner loop");
19295 inform (outer->loc, "containing loop here");
19296 }
19297 else
19298 error_at (loop->loc,
19299 "%s uses OpenACC parallelism disallowed by containing routine",
19300 loop->routine ? "routine call" : "loop");
19301
19302 if (loop->routine)
19303 inform (DECL_SOURCE_LOCATION (loop->routine),
19304 "routine %qD declared here", loop->routine);
19305 }
19306 this_mask &= ~outer_mask;
19307 }
19308 else
19309 {
19310 unsigned outermost = this_mask & -this_mask;
19311
19312 if (outermost && outermost <= outer_mask)
19313 {
19314 if (noisy)
19315 {
19316 error_at (loop->loc,
19317 "incorrectly nested OpenACC loop parallelism");
19318
19319 const oacc_loop *outer;
19320 for (outer = loop->parent;
19321 outer->flags && outer->flags < outermost;
19322 outer = outer->parent)
19323 continue;
19324 inform (outer->loc, "containing loop here");
19325 }
19326
19327 this_mask &= ~outermost;
19328 }
19329 }
19330
19331 loop->mask = this_mask;
19332
19333 if (loop->child
19334 && oacc_loop_fixed_partitions (loop->child, outer_mask | this_mask))
19335 has_auto = true;
19336
19337 if (loop->sibling
19338 && oacc_loop_fixed_partitions (loop->sibling, outer_mask))
19339 has_auto = true;
19340
19341 return has_auto;
19342}
19343
c5a64cfe
NS
19344/* Walk the OpenACC loop heirarchy to assign auto-partitioned loops.
19345 OUTER_MASK is the partitioning this loop is contained within.
19346 Return the cumulative partitioning used by this loop, siblings and
19347 children. */
19348
19349static unsigned
19350oacc_loop_auto_partitions (oacc_loop *loop, unsigned outer_mask)
19351{
19352 unsigned inner_mask = 0;
19353 bool noisy = true;
19354
19355#ifdef ACCEL_COMPILER
19356 /* When device_type is supported, we want the device compiler to be
19357 noisy, if the loop parameters are device_type-specific. */
19358 noisy = false;
19359#endif
19360
19361 if (loop->child)
19362 inner_mask |= oacc_loop_auto_partitions (loop->child,
19363 outer_mask | loop->mask);
19364
19365 if ((loop->flags & OLF_AUTO) && (loop->flags & OLF_INDEPENDENT))
19366 {
19367 unsigned this_mask = 0;
19368
19369 /* Determine the outermost partitioning used within this loop. */
19370 this_mask = inner_mask | GOMP_DIM_MASK (GOMP_DIM_MAX);
19371 this_mask = (this_mask & -this_mask);
19372
19373 /* Pick the partitioning just inside that one. */
19374 this_mask >>= 1;
19375
19376 /* And avoid picking one use by an outer loop. */
19377 this_mask &= ~outer_mask;
19378
19379 if (!this_mask && noisy)
19380 warning_at (loop->loc, 0,
19381 "insufficient partitioning available to parallelize loop");
19382
19383 loop->mask = this_mask;
19384 }
19385 inner_mask |= loop->mask;
19386
19387 if (loop->sibling)
19388 inner_mask |= oacc_loop_auto_partitions (loop->sibling, outer_mask);
19389
19390 return inner_mask;
19391}
19392
9bd46bc9
NS
19393/* Walk the OpenACC loop heirarchy to check and assign partitioning
19394 axes. */
19395
19396static void
c5a64cfe 19397oacc_loop_partition (oacc_loop *loop, unsigned outer_mask)
9bd46bc9 19398{
c5a64cfe
NS
19399 if (oacc_loop_fixed_partitions (loop, outer_mask))
19400 oacc_loop_auto_partitions (loop, outer_mask);
9bd46bc9
NS
19401}
19402
6e91acf8
NS
19403/* Default fork/join early expander. Delete the function calls if
19404 there is no RTL expander. */
19405
19406bool
19407default_goacc_fork_join (gcall *ARG_UNUSED (call),
19408 const int *ARG_UNUSED (dims), bool is_fork)
19409{
19410 if (is_fork)
19411 return targetm.have_oacc_fork ();
19412 else
19413 return targetm.have_oacc_join ();
19414}
19415
e5014671
NS
19416/* Default goacc.reduction early expander.
19417
19418 LHS-opt = IFN_REDUCTION (KIND, RES_PTR, VAR, LEVEL, OP, OFFSET)
19419 If RES_PTR is not integer-zerop:
19420 SETUP - emit 'LHS = *RES_PTR', LHS = NULL
19421 TEARDOWN - emit '*RES_PTR = VAR'
19422 If LHS is not NULL
19423 emit 'LHS = VAR' */
19424
19425void
19426default_goacc_reduction (gcall *call)
19427{
19428 unsigned code = (unsigned)TREE_INT_CST_LOW (gimple_call_arg (call, 0));
19429 gimple_stmt_iterator gsi = gsi_for_stmt (call);
19430 tree lhs = gimple_call_lhs (call);
19431 tree var = gimple_call_arg (call, 2);
19432 gimple_seq seq = NULL;
19433
19434 if (code == IFN_GOACC_REDUCTION_SETUP
19435 || code == IFN_GOACC_REDUCTION_TEARDOWN)
19436 {
19437 /* Setup and Teardown need to copy from/to the receiver object,
19438 if there is one. */
19439 tree ref_to_res = gimple_call_arg (call, 1);
19440
19441 if (!integer_zerop (ref_to_res))
19442 {
19443 tree dst = build_simple_mem_ref (ref_to_res);
19444 tree src = var;
19445
19446 if (code == IFN_GOACC_REDUCTION_SETUP)
19447 {
19448 src = dst;
19449 dst = lhs;
19450 lhs = NULL;
19451 }
19452 gimple_seq_add_stmt (&seq, gimple_build_assign (dst, src));
19453 }
19454 }
19455
19456 /* Copy VAR to LHS, if there is an LHS. */
19457 if (lhs)
19458 gimple_seq_add_stmt (&seq, gimple_build_assign (lhs, var));
19459
19460 gsi_replace_with_seq (&gsi, seq, true);
19461}
19462
94829f87
NS
19463/* Main entry point for oacc transformations which run on the device
19464 compiler after LTO, so we know what the target device is at this
19465 point (including the host fallback). */
19466
19467static unsigned int
19468execute_oacc_device_lower ()
19469{
19470 tree attrs = get_oacc_fn_attrib (current_function_decl);
19471 int dims[GOMP_DIM_MAX];
19472
19473 if (!attrs)
19474 /* Not an offloaded function. */
19475 return 0;
19476
9bd46bc9
NS
19477 int fn_level = oacc_validate_dims (current_function_decl, attrs, dims);
19478
19479 /* Discover, partition and process the loops. */
19480 oacc_loop *loops = oacc_loop_discovery ();
c5a64cfe
NS
19481 unsigned outer_mask = fn_level >= 0 ? GOMP_DIM_MASK (fn_level) - 1 : 0;
19482 oacc_loop_partition (loops, outer_mask);
9bd46bc9
NS
19483 oacc_loop_process (loops);
19484 if (dump_file)
19485 {
19486 fprintf (dump_file, "OpenACC loops\n");
19487 dump_oacc_loop (dump_file, loops, 0);
19488 fprintf (dump_file, "\n");
19489 }
19490
e5014671
NS
19491 /* Offloaded targets may introduce new basic blocks, which require
19492 dominance information to update SSA. */
19493 calculate_dominance_info (CDI_DOMINATORS);
19494
9bd46bc9
NS
19495 /* Now lower internal loop functions to target-specific code
19496 sequences. */
19497 basic_block bb;
19498 FOR_ALL_BB_FN (bb, cfun)
19499 for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);)
19500 {
19501 gimple *stmt = gsi_stmt (gsi);
19502 if (!is_gimple_call (stmt))
19503 {
19504 gsi_next (&gsi);
19505 continue;
19506 }
19507
19508 gcall *call = as_a <gcall *> (stmt);
19509 if (!gimple_call_internal_p (call))
19510 {
19511 gsi_next (&gsi);
19512 continue;
19513 }
19514
19515 /* Rewind to allow rescan. */
19516 gsi_prev (&gsi);
19517 bool rescan = false, remove = false;
19518 enum internal_fn ifn_code = gimple_call_internal_fn (call);
19519
19520 switch (ifn_code)
19521 {
19522 default: break;
19523
19524 case IFN_GOACC_LOOP:
19525 oacc_xform_loop (call);
19526 rescan = true;
19527 break;
19528
e5014671
NS
19529 case IFN_GOACC_REDUCTION:
19530 /* Mark the function for SSA renaming. */
19531 mark_virtual_operands_for_renaming (cfun);
19532
19533 /* If the level is -1, this ended up being an unused
19534 axis. Handle as a default. */
19535 if (integer_minus_onep (gimple_call_arg (call, 3)))
19536 default_goacc_reduction (call);
19537 else
19538 targetm.goacc.reduction (call);
19539 rescan = true;
19540 break;
19541
9bd46bc9
NS
19542 case IFN_UNIQUE:
19543 {
19544 enum ifn_unique_kind kind
19545 = ((enum ifn_unique_kind)
19546 TREE_INT_CST_LOW (gimple_call_arg (call, 0)));
19547
19548 switch (kind)
19549 {
19550 default:
19551 gcc_unreachable ();
19552
19553 case IFN_UNIQUE_OACC_FORK:
19554 case IFN_UNIQUE_OACC_JOIN:
19555 if (integer_minus_onep (gimple_call_arg (call, 2)))
19556 remove = true;
19557 else if (!targetm.goacc.fork_join
19558 (call, dims, kind == IFN_UNIQUE_OACC_FORK))
19559 remove = true;
19560 break;
19561
19562 case IFN_UNIQUE_OACC_HEAD_MARK:
19563 case IFN_UNIQUE_OACC_TAIL_MARK:
19564 remove = true;
19565 break;
19566 }
19567 break;
19568 }
19569 }
19570
19571 if (gsi_end_p (gsi))
19572 /* We rewound past the beginning of the BB. */
19573 gsi = gsi_start_bb (bb);
19574 else
19575 /* Undo the rewind. */
19576 gsi_next (&gsi);
19577
19578 if (remove)
19579 {
19580 if (gimple_vdef (call))
19581 replace_uses_by (gimple_vdef (call), gimple_vuse (call));
19582 if (gimple_call_lhs (call))
19583 {
19584 /* Propagate the data dependency var. */
19585 gimple *ass = gimple_build_assign (gimple_call_lhs (call),
19586 gimple_call_arg (call, 1));
19587 gsi_replace (&gsi, ass, false);
19588 }
19589 else
19590 gsi_remove (&gsi, true);
19591 }
19592 else if (!rescan)
19593 /* If not rescanning, advance over the call. */
19594 gsi_next (&gsi);
19595 }
19596
19597 free_oacc_loop (loops);
19598
94829f87
NS
19599 return 0;
19600}
19601
19602/* Default launch dimension validator. Force everything to 1. A
19603 backend that wants to provide larger dimensions must override this
19604 hook. */
19605
19606bool
19607default_goacc_validate_dims (tree ARG_UNUSED (decl), int *dims,
19608 int ARG_UNUSED (fn_level))
19609{
19610 bool changed = false;
19611
19612 for (unsigned ix = 0; ix != GOMP_DIM_MAX; ix++)
19613 {
19614 if (dims[ix] != 1)
19615 {
19616 dims[ix] = 1;
19617 changed = true;
19618 }
19619 }
19620
19621 return changed;
19622}
19623
bd751975
NS
19624/* Default dimension bound is unknown on accelerator and 1 on host. */
19625
19626int
19627default_goacc_dim_limit (int ARG_UNUSED (axis))
19628{
19629#ifdef ACCEL_COMPILER
19630 return 0;
19631#else
19632 return 1;
19633#endif
19634}
19635
94829f87
NS
19636namespace {
19637
19638const pass_data pass_data_oacc_device_lower =
19639{
19640 GIMPLE_PASS, /* type */
19641 "oaccdevlow", /* name */
19642 OPTGROUP_NONE, /* optinfo_flags */
19643 TV_NONE, /* tv_id */
19644 PROP_cfg, /* properties_required */
19645 0 /* Possibly PROP_gimple_eomp. */, /* properties_provided */
19646 0, /* properties_destroyed */
19647 0, /* todo_flags_start */
19648 TODO_update_ssa | TODO_cleanup_cfg, /* todo_flags_finish */
19649};
19650
19651class pass_oacc_device_lower : public gimple_opt_pass
19652{
19653public:
19654 pass_oacc_device_lower (gcc::context *ctxt)
19655 : gimple_opt_pass (pass_data_oacc_device_lower, ctxt)
19656 {}
19657
19658 /* opt_pass methods: */
19659 virtual unsigned int execute (function *)
19660 {
adc2b4d7 19661 bool gate = flag_openacc != 0;
94829f87
NS
19662
19663 if (!gate)
19664 return 0;
19665
19666 return execute_oacc_device_lower ();
19667 }
19668
374d0225 19669}; // class pass_oacc_device_lower
94829f87
NS
19670
19671} // anon namespace
19672
19673gimple_opt_pass *
19674make_pass_oacc_device_lower (gcc::context *ctxt)
19675{
19676 return new pass_oacc_device_lower (ctxt);
19677}
19678
953ff289 19679#include "gt-omp-low.h"