]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/omp-low.c
Mark omp thread functions as parallelized
[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"
28#include "tm.h"
40e23961
MC
29#include "hash-set.h"
30#include "machmode.h"
31#include "vec.h"
32#include "double-int.h"
33#include "input.h"
34#include "alias.h"
35#include "symtab.h"
36#include "wide-int.h"
37#include "inchash.h"
953ff289 38#include "tree.h"
40e23961 39#include "fold-const.h"
d8a2d370
DN
40#include "stringpool.h"
41#include "stor-layout.h"
953ff289 42#include "rtl.h"
60393bbc 43#include "predict.h"
60393bbc 44#include "hard-reg-set.h"
60393bbc
AM
45#include "function.h"
46#include "dominance.h"
47#include "cfg.h"
48#include "cfganal.h"
2fb9a547
AM
49#include "basic-block.h"
50#include "tree-ssa-alias.h"
51#include "internal-fn.h"
52#include "gimple-fold.h"
53#include "gimple-expr.h"
54#include "is-a.h"
18f429e2 55#include "gimple.h"
45b0be94 56#include "gimplify.h"
5be5c238 57#include "gimple-iterator.h"
18f429e2 58#include "gimplify-me.h"
5be5c238 59#include "gimple-walk.h"
726a989a 60#include "tree-iterator.h"
953ff289
DN
61#include "tree-inline.h"
62#include "langhooks.h"
1da2ed5f 63#include "diagnostic-core.h"
442b4905 64#include "gimple-ssa.h"
c582198b
AM
65#include "hash-map.h"
66#include "plugin-api.h"
67#include "ipa-ref.h"
442b4905
AM
68#include "cgraph.h"
69#include "tree-cfg.h"
70#include "tree-phinodes.h"
71#include "ssa-iterators.h"
72#include "tree-ssanames.h"
73#include "tree-into-ssa.h"
36566b39
PK
74#include "hashtab.h"
75#include "flags.h"
76#include "statistics.h"
77#include "real.h"
78#include "fixed-value.h"
79#include "insn-config.h"
80#include "expmed.h"
81#include "dojump.h"
82#include "explow.h"
83#include "calls.h"
84#include "emit-rtl.h"
85#include "varasm.h"
86#include "stmt.h"
d8a2d370 87#include "expr.h"
442b4905 88#include "tree-dfa.h"
7a300452 89#include "tree-ssa.h"
953ff289 90#include "tree-pass.h"
953ff289 91#include "except.h"
6be42dd4 92#include "splay-tree.h"
b0710fe1 93#include "insn-codes.h"
a509ebb5
RL
94#include "optabs.h"
95#include "cfgloop.h"
74bf76ed 96#include "target.h"
ec6fe917 97#include "common/common-target.h"
0645c1a2 98#include "omp-low.h"
4484a35a
AM
99#include "gimple-low.h"
100#include "tree-cfgcleanup.h"
0136f8f0 101#include "pretty-print.h"
c582198b 102#include "alloc-pool.h"
dd912cb8 103#include "symbol-summary.h"
0136f8f0 104#include "ipa-prop.h"
1fe37220 105#include "tree-nested.h"
0136f8f0 106#include "tree-eh.h"
9a771876 107#include "cilk.h"
1f6be682 108#include "context.h"
ec6fe917 109#include "lto-section-names.h"
41dbbb37 110#include "gomp-constants.h"
953ff289 111
726a989a 112
41dbbb37 113/* Lowering of OMP parallel and workshare constructs proceeds in two
953ff289
DN
114 phases. The first phase scans the function looking for OMP statements
115 and then for variables that must be replaced to satisfy data sharing
116 clauses. The second phase expands code for the constructs, as well as
c0220ea4 117 re-gimplifying things when variables have been replaced with complex
953ff289
DN
118 expressions.
119
7ebaeab5 120 Final code generation is done by pass_expand_omp. The flowgraph is
41dbbb37
TS
121 scanned for regions which are then moved to a new
122 function, to be invoked by the thread library, or offloaded. */
953ff289 123
41dbbb37 124/* OMP region information. Every parallel and workshare
0645c1a2
AM
125 directive is enclosed between two markers, the OMP_* directive
126 and a corresponding OMP_RETURN statement. */
127
128struct omp_region
129{
130 /* The enclosing region. */
131 struct omp_region *outer;
132
133 /* First child region. */
134 struct omp_region *inner;
135
136 /* Next peer region. */
137 struct omp_region *next;
138
139 /* Block containing the omp directive as its last stmt. */
140 basic_block entry;
141
142 /* Block containing the OMP_RETURN as its last stmt. */
143 basic_block exit;
144
145 /* Block containing the OMP_CONTINUE as its last stmt. */
146 basic_block cont;
147
148 /* If this is a combined parallel+workshare region, this is a list
149 of additional arguments needed by the combined parallel+workshare
150 library call. */
151 vec<tree, va_gc> *ws_args;
152
153 /* The code for the omp directive of this region. */
154 enum gimple_code type;
155
156 /* Schedule kind, only used for OMP_FOR type regions. */
157 enum omp_clause_schedule_kind sched_kind;
158
159 /* True if this is a combined parallel+workshare region. */
160 bool is_combined_parallel;
161};
162
41dbbb37
TS
163/* Levels of parallelism as defined by OpenACC. Increasing numbers
164 correspond to deeper loop nesting levels. */
165#define MASK_GANG 1
166#define MASK_WORKER 2
167#define MASK_VECTOR 4
168
953ff289
DN
169/* Context structure. Used to store information about each parallel
170 directive in the code. */
171
172typedef struct omp_context
173{
174 /* This field must be at the beginning, as we do "inheritance": Some
175 callback functions for tree-inline.c (e.g., omp_copy_decl)
176 receive a copy_body_data pointer that is up-casted to an
177 omp_context pointer. */
178 copy_body_data cb;
179
180 /* The tree of contexts corresponding to the encountered constructs. */
181 struct omp_context *outer;
726a989a 182 gimple stmt;
953ff289 183
b8698a0f 184 /* Map variables to fields in a structure that allows communication
953ff289
DN
185 between sending and receiving threads. */
186 splay_tree field_map;
187 tree record_type;
188 tree sender_decl;
189 tree receiver_decl;
190
a68ab351
JJ
191 /* These are used just by task contexts, if task firstprivate fn is
192 needed. srecord_type is used to communicate from the thread
193 that encountered the task construct to task firstprivate fn,
194 record_type is allocated by GOMP_task, initialized by task firstprivate
195 fn and passed to the task body fn. */
196 splay_tree sfield_map;
197 tree srecord_type;
198
953ff289
DN
199 /* A chain of variables to add to the top-level block surrounding the
200 construct. In the case of a parallel, this is in the child function. */
201 tree block_vars;
202
41dbbb37
TS
203 /* A map of reduction pointer variables. For accelerators, each
204 reduction variable is replaced with an array. Each thread, in turn,
205 is assigned to a slot on that array. */
206 splay_tree reduction_map;
207
acf0174b
JJ
208 /* Label to which GOMP_cancel{,llation_point} and explicit and implicit
209 barriers should jump to during omplower pass. */
210 tree cancel_label;
211
953ff289
DN
212 /* What to do with variables with implicitly determined sharing
213 attributes. */
214 enum omp_clause_default_kind default_kind;
215
216 /* Nesting depth of this context. Used to beautify error messages re
217 invalid gotos. The outermost ctx is depth 1, with depth 0 being
218 reserved for the main body of the function. */
219 int depth;
220
953ff289
DN
221 /* True if this parallel directive is nested within another. */
222 bool is_nested;
acf0174b
JJ
223
224 /* True if this construct can be cancelled. */
225 bool cancellable;
41dbbb37
TS
226
227 /* For OpenACC loops, a mask of gang, worker and vector used at
228 levels below this one. */
229 int gwv_below;
230 /* For OpenACC loops, a mask of gang, worker and vector used at
231 this level and above. For parallel and kernels clauses, a mask
232 indicating which of num_gangs/num_workers/num_vectors was used. */
233 int gwv_this;
953ff289
DN
234} omp_context;
235
41dbbb37
TS
236/* A structure holding the elements of:
237 for (V = N1; V cond N2; V += STEP) [...] */
953ff289 238
a68ab351
JJ
239struct omp_for_data_loop
240{
241 tree v, n1, n2, step;
242 enum tree_code cond_code;
243};
244
50674e96 245/* A structure describing the main elements of a parallel loop. */
953ff289 246
50674e96 247struct omp_for_data
953ff289 248{
a68ab351 249 struct omp_for_data_loop loop;
726a989a 250 tree chunk_size;
538dd0b7 251 gomp_for *for_stmt;
a68ab351
JJ
252 tree pre, iter_type;
253 int collapse;
953ff289
DN
254 bool have_nowait, have_ordered;
255 enum omp_clause_schedule_kind sched_kind;
a68ab351 256 struct omp_for_data_loop *loops;
953ff289
DN
257};
258
50674e96 259
953ff289 260static splay_tree all_contexts;
a68ab351 261static int taskreg_nesting_level;
acf0174b 262static int target_nesting_level;
0645c1a2 263static struct omp_region *root_omp_region;
a68ab351 264static bitmap task_shared_vars;
5771c391 265static vec<omp_context *> taskreg_contexts;
953ff289 266
26127932 267static void scan_omp (gimple_seq *, omp_context *);
726a989a
RB
268static tree scan_omp_1_op (tree *, int *, void *);
269
270#define WALK_SUBSTMTS \
271 case GIMPLE_BIND: \
272 case GIMPLE_TRY: \
273 case GIMPLE_CATCH: \
274 case GIMPLE_EH_FILTER: \
0a35513e 275 case GIMPLE_TRANSACTION: \
726a989a
RB
276 /* The sub-statements for these should be walked. */ \
277 *handled_ops_p = false; \
278 break;
279
41dbbb37
TS
280/* Helper function to get the name of the array containing the partial
281 reductions for OpenACC reductions. */
282static const char *
283oacc_get_reduction_array_id (tree node)
284{
285 const char *id = IDENTIFIER_POINTER (DECL_NAME (node));
286 int len = strlen ("OACC") + strlen (id);
287 char *temp_name = XALLOCAVEC (char, len + 1);
288 snprintf (temp_name, len + 1, "OACC%s", id);
289 return IDENTIFIER_POINTER (get_identifier (temp_name));
290}
291
292/* Determine the number of threads OpenACC threads used to determine the
293 size of the array of partial reductions. Currently, this is num_gangs
294 * vector_length. This value may be different than GOACC_GET_NUM_THREADS,
295 because it is independed of the device used. */
296
297static tree
298oacc_max_threads (omp_context *ctx)
299{
300 tree nthreads, vector_length, gangs, clauses;
301
302 gangs = fold_convert (sizetype, integer_one_node);
303 vector_length = gangs;
304
305 /* The reduction clause may be nested inside a loop directive.
306 Scan for the innermost vector_length clause. */
307 for (omp_context *oc = ctx; oc; oc = oc->outer)
308 {
309 if (gimple_code (oc->stmt) != GIMPLE_OMP_TARGET
310 || (gimple_omp_target_kind (oc->stmt)
311 != GF_OMP_TARGET_KIND_OACC_PARALLEL))
312 continue;
313
314 clauses = gimple_omp_target_clauses (oc->stmt);
315
316 vector_length = find_omp_clause (clauses, OMP_CLAUSE_VECTOR_LENGTH);
317 if (vector_length)
318 vector_length = fold_convert_loc (OMP_CLAUSE_LOCATION (vector_length),
319 sizetype,
320 OMP_CLAUSE_VECTOR_LENGTH_EXPR
321 (vector_length));
322 else
323 vector_length = fold_convert (sizetype, integer_one_node);
324
325 gangs = find_omp_clause (clauses, OMP_CLAUSE_NUM_GANGS);
326 if (gangs)
327 gangs = fold_convert_loc (OMP_CLAUSE_LOCATION (gangs), sizetype,
328 OMP_CLAUSE_NUM_GANGS_EXPR (gangs));
329 else
330 gangs = fold_convert (sizetype, integer_one_node);
331
332 break;
333 }
334
335 nthreads = fold_build2 (MULT_EXPR, sizetype, gangs, vector_length);
336
337 return nthreads;
338}
339
ec6fe917
IV
340/* Holds offload tables with decls. */
341vec<tree, va_gc> *offload_funcs, *offload_vars;
342
726a989a
RB
343/* Convenience function for calling scan_omp_1_op on tree operands. */
344
345static inline tree
346scan_omp_op (tree *tp, omp_context *ctx)
347{
348 struct walk_stmt_info wi;
349
350 memset (&wi, 0, sizeof (wi));
351 wi.info = ctx;
352 wi.want_locations = true;
353
354 return walk_tree (tp, scan_omp_1_op, &wi, NULL);
355}
356
355a7673 357static void lower_omp (gimple_seq *, omp_context *);
8ca5b2a2
JJ
358static tree lookup_decl_in_outer_ctx (tree, omp_context *);
359static tree maybe_lookup_decl_in_outer_ctx (tree, omp_context *);
953ff289 360
41dbbb37 361/* Find an OMP clause of type KIND within CLAUSES. */
953ff289 362
917948d3 363tree
e0c68ce9 364find_omp_clause (tree clauses, enum omp_clause_code kind)
953ff289
DN
365{
366 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
aaf46ef9 367 if (OMP_CLAUSE_CODE (clauses) == kind)
953ff289
DN
368 return clauses;
369
370 return NULL_TREE;
371}
372
373/* Return true if CTX is for an omp parallel. */
374
375static inline bool
376is_parallel_ctx (omp_context *ctx)
377{
726a989a 378 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL;
953ff289
DN
379}
380
50674e96 381
a68ab351
JJ
382/* Return true if CTX is for an omp task. */
383
384static inline bool
385is_task_ctx (omp_context *ctx)
386{
726a989a 387 return gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
a68ab351
JJ
388}
389
390
391/* Return true if CTX is for an omp parallel or omp task. */
392
393static inline bool
394is_taskreg_ctx (omp_context *ctx)
395{
726a989a
RB
396 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL
397 || gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
a68ab351
JJ
398}
399
400
50674e96 401/* Return true if REGION is a combined parallel+workshare region. */
953ff289
DN
402
403static inline bool
50674e96
DN
404is_combined_parallel (struct omp_region *region)
405{
406 return region->is_combined_parallel;
407}
408
409
410/* Extract the header elements of parallel loop FOR_STMT and store
411 them into *FD. */
412
413static void
538dd0b7 414extract_omp_for_data (gomp_for *for_stmt, struct omp_for_data *fd,
a68ab351 415 struct omp_for_data_loop *loops)
50674e96 416{
a68ab351
JJ
417 tree t, var, *collapse_iter, *collapse_count;
418 tree count = NULL_TREE, iter_type = long_integer_type_node;
419 struct omp_for_data_loop *loop;
420 int i;
421 struct omp_for_data_loop dummy_loop;
db3927fb 422 location_t loc = gimple_location (for_stmt);
0aadce73 423 bool simd = gimple_omp_for_kind (for_stmt) & GF_OMP_FOR_SIMD;
acf0174b
JJ
424 bool distribute = gimple_omp_for_kind (for_stmt)
425 == GF_OMP_FOR_KIND_DISTRIBUTE;
50674e96
DN
426
427 fd->for_stmt = for_stmt;
428 fd->pre = NULL;
726a989a 429 fd->collapse = gimple_omp_for_collapse (for_stmt);
a68ab351
JJ
430 if (fd->collapse > 1)
431 fd->loops = loops;
432 else
433 fd->loops = &fd->loop;
50674e96 434
acf0174b
JJ
435 fd->have_nowait = distribute || simd;
436 fd->have_ordered = false;
50674e96
DN
437 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
438 fd->chunk_size = NULL_TREE;
9a771876
JJ
439 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
440 fd->sched_kind = OMP_CLAUSE_SCHEDULE_CILKFOR;
a68ab351
JJ
441 collapse_iter = NULL;
442 collapse_count = NULL;
50674e96 443
726a989a 444 for (t = gimple_omp_for_clauses (for_stmt); t ; t = OMP_CLAUSE_CHAIN (t))
aaf46ef9 445 switch (OMP_CLAUSE_CODE (t))
50674e96
DN
446 {
447 case OMP_CLAUSE_NOWAIT:
448 fd->have_nowait = true;
449 break;
450 case OMP_CLAUSE_ORDERED:
451 fd->have_ordered = true;
452 break;
453 case OMP_CLAUSE_SCHEDULE:
acf0174b 454 gcc_assert (!distribute);
50674e96
DN
455 fd->sched_kind = OMP_CLAUSE_SCHEDULE_KIND (t);
456 fd->chunk_size = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t);
457 break;
acf0174b
JJ
458 case OMP_CLAUSE_DIST_SCHEDULE:
459 gcc_assert (distribute);
460 fd->chunk_size = OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (t);
461 break;
a68ab351
JJ
462 case OMP_CLAUSE_COLLAPSE:
463 if (fd->collapse > 1)
464 {
465 collapse_iter = &OMP_CLAUSE_COLLAPSE_ITERVAR (t);
466 collapse_count = &OMP_CLAUSE_COLLAPSE_COUNT (t);
467 }
34f2124e 468 break;
50674e96
DN
469 default:
470 break;
471 }
472
a68ab351
JJ
473 /* FIXME: for now map schedule(auto) to schedule(static).
474 There should be analysis to determine whether all iterations
475 are approximately the same amount of work (then schedule(static)
1cbc62c0 476 is best) or if it varies (then schedule(dynamic,N) is better). */
a68ab351
JJ
477 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_AUTO)
478 {
479 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
480 gcc_assert (fd->chunk_size == NULL);
481 }
482 gcc_assert (fd->collapse == 1 || collapse_iter != NULL);
50674e96
DN
483 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
484 gcc_assert (fd->chunk_size == NULL);
485 else if (fd->chunk_size == NULL)
486 {
487 /* We only need to compute a default chunk size for ordered
488 static loops and dynamic loops. */
a68ab351 489 if (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
acf0174b 490 || fd->have_ordered)
50674e96
DN
491 fd->chunk_size = (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
492 ? integer_zero_node : integer_one_node;
493 }
a68ab351
JJ
494
495 for (i = 0; i < fd->collapse; i++)
496 {
497 if (fd->collapse == 1)
498 loop = &fd->loop;
499 else if (loops != NULL)
500 loop = loops + i;
501 else
502 loop = &dummy_loop;
503
726a989a 504 loop->v = gimple_omp_for_index (for_stmt, i);
a68ab351
JJ
505 gcc_assert (SSA_VAR_P (loop->v));
506 gcc_assert (TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
507 || TREE_CODE (TREE_TYPE (loop->v)) == POINTER_TYPE);
508 var = TREE_CODE (loop->v) == SSA_NAME ? SSA_NAME_VAR (loop->v) : loop->v;
726a989a 509 loop->n1 = gimple_omp_for_initial (for_stmt, i);
a68ab351 510
726a989a
RB
511 loop->cond_code = gimple_omp_for_cond (for_stmt, i);
512 loop->n2 = gimple_omp_for_final (for_stmt, i);
a68ab351
JJ
513 switch (loop->cond_code)
514 {
515 case LT_EXPR:
516 case GT_EXPR:
517 break;
c02065fc
AH
518 case NE_EXPR:
519 gcc_assert (gimple_omp_for_kind (for_stmt)
9a771876
JJ
520 == GF_OMP_FOR_KIND_CILKSIMD
521 || (gimple_omp_for_kind (for_stmt)
522 == GF_OMP_FOR_KIND_CILKFOR));
c02065fc 523 break;
a68ab351
JJ
524 case LE_EXPR:
525 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
5d49b6a7 526 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, 1);
a68ab351 527 else
db3927fb
AH
528 loop->n2 = fold_build2_loc (loc,
529 PLUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
a68ab351
JJ
530 build_int_cst (TREE_TYPE (loop->n2), 1));
531 loop->cond_code = LT_EXPR;
532 break;
533 case GE_EXPR:
534 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
5d49b6a7 535 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, -1);
a68ab351 536 else
db3927fb
AH
537 loop->n2 = fold_build2_loc (loc,
538 MINUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
a68ab351
JJ
539 build_int_cst (TREE_TYPE (loop->n2), 1));
540 loop->cond_code = GT_EXPR;
541 break;
542 default:
543 gcc_unreachable ();
544 }
545
726a989a 546 t = gimple_omp_for_incr (for_stmt, i);
a68ab351
JJ
547 gcc_assert (TREE_OPERAND (t, 0) == var);
548 switch (TREE_CODE (t))
549 {
550 case PLUS_EXPR:
a68ab351
JJ
551 loop->step = TREE_OPERAND (t, 1);
552 break;
56099f00
RG
553 case POINTER_PLUS_EXPR:
554 loop->step = fold_convert (ssizetype, TREE_OPERAND (t, 1));
555 break;
a68ab351
JJ
556 case MINUS_EXPR:
557 loop->step = TREE_OPERAND (t, 1);
db3927fb
AH
558 loop->step = fold_build1_loc (loc,
559 NEGATE_EXPR, TREE_TYPE (loop->step),
a68ab351
JJ
560 loop->step);
561 break;
562 default:
563 gcc_unreachable ();
564 }
565
acf0174b
JJ
566 if (simd
567 || (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
568 && !fd->have_ordered))
74bf76ed
JJ
569 {
570 if (fd->collapse == 1)
571 iter_type = TREE_TYPE (loop->v);
572 else if (i == 0
573 || TYPE_PRECISION (iter_type)
574 < TYPE_PRECISION (TREE_TYPE (loop->v)))
575 iter_type
576 = build_nonstandard_integer_type
acf0174b 577 (TYPE_PRECISION (TREE_TYPE (loop->v)), 1);
74bf76ed
JJ
578 }
579 else if (iter_type != long_long_unsigned_type_node)
a68ab351
JJ
580 {
581 if (POINTER_TYPE_P (TREE_TYPE (loop->v)))
582 iter_type = long_long_unsigned_type_node;
583 else if (TYPE_UNSIGNED (TREE_TYPE (loop->v))
584 && TYPE_PRECISION (TREE_TYPE (loop->v))
585 >= TYPE_PRECISION (iter_type))
586 {
587 tree n;
588
589 if (loop->cond_code == LT_EXPR)
db3927fb
AH
590 n = fold_build2_loc (loc,
591 PLUS_EXPR, TREE_TYPE (loop->v),
a68ab351
JJ
592 loop->n2, loop->step);
593 else
594 n = loop->n1;
595 if (TREE_CODE (n) != INTEGER_CST
596 || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type), n))
597 iter_type = long_long_unsigned_type_node;
598 }
599 else if (TYPE_PRECISION (TREE_TYPE (loop->v))
600 > TYPE_PRECISION (iter_type))
601 {
602 tree n1, n2;
603
604 if (loop->cond_code == LT_EXPR)
605 {
606 n1 = loop->n1;
db3927fb
AH
607 n2 = fold_build2_loc (loc,
608 PLUS_EXPR, TREE_TYPE (loop->v),
a68ab351
JJ
609 loop->n2, loop->step);
610 }
611 else
612 {
db3927fb
AH
613 n1 = fold_build2_loc (loc,
614 MINUS_EXPR, TREE_TYPE (loop->v),
a68ab351
JJ
615 loop->n2, loop->step);
616 n2 = loop->n1;
617 }
618 if (TREE_CODE (n1) != INTEGER_CST
619 || TREE_CODE (n2) != INTEGER_CST
620 || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type), n1)
621 || !tree_int_cst_lt (n2, TYPE_MAX_VALUE (iter_type)))
622 iter_type = long_long_unsigned_type_node;
623 }
624 }
625
626 if (collapse_count && *collapse_count == NULL)
627 {
5a0f4dd3
JJ
628 t = fold_binary (loop->cond_code, boolean_type_node,
629 fold_convert (TREE_TYPE (loop->v), loop->n1),
630 fold_convert (TREE_TYPE (loop->v), loop->n2));
631 if (t && integer_zerop (t))
632 count = build_zero_cst (long_long_unsigned_type_node);
633 else if ((i == 0 || count != NULL_TREE)
634 && TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
635 && TREE_CONSTANT (loop->n1)
636 && TREE_CONSTANT (loop->n2)
637 && TREE_CODE (loop->step) == INTEGER_CST)
a68ab351
JJ
638 {
639 tree itype = TREE_TYPE (loop->v);
640
641 if (POINTER_TYPE_P (itype))
96f9265a 642 itype = signed_type_for (itype);
a68ab351 643 t = build_int_cst (itype, (loop->cond_code == LT_EXPR ? -1 : 1));
db3927fb
AH
644 t = fold_build2_loc (loc,
645 PLUS_EXPR, itype,
646 fold_convert_loc (loc, itype, loop->step), t);
647 t = fold_build2_loc (loc, PLUS_EXPR, itype, t,
648 fold_convert_loc (loc, itype, loop->n2));
649 t = fold_build2_loc (loc, MINUS_EXPR, itype, t,
650 fold_convert_loc (loc, itype, loop->n1));
a68ab351 651 if (TYPE_UNSIGNED (itype) && loop->cond_code == GT_EXPR)
db3927fb
AH
652 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype,
653 fold_build1_loc (loc, NEGATE_EXPR, itype, t),
654 fold_build1_loc (loc, NEGATE_EXPR, itype,
655 fold_convert_loc (loc, itype,
656 loop->step)));
a68ab351 657 else
db3927fb
AH
658 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, t,
659 fold_convert_loc (loc, itype, loop->step));
660 t = fold_convert_loc (loc, long_long_unsigned_type_node, t);
a68ab351 661 if (count != NULL_TREE)
db3927fb
AH
662 count = fold_build2_loc (loc,
663 MULT_EXPR, long_long_unsigned_type_node,
a68ab351
JJ
664 count, t);
665 else
666 count = t;
667 if (TREE_CODE (count) != INTEGER_CST)
668 count = NULL_TREE;
669 }
5a0f4dd3 670 else if (count && !integer_zerop (count))
a68ab351
JJ
671 count = NULL_TREE;
672 }
673 }
674
74bf76ed 675 if (count
acf0174b
JJ
676 && !simd
677 && (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
678 || fd->have_ordered))
a68ab351
JJ
679 {
680 if (!tree_int_cst_lt (count, TYPE_MAX_VALUE (long_integer_type_node)))
681 iter_type = long_long_unsigned_type_node;
682 else
683 iter_type = long_integer_type_node;
684 }
685 else if (collapse_iter && *collapse_iter != NULL)
686 iter_type = TREE_TYPE (*collapse_iter);
687 fd->iter_type = iter_type;
688 if (collapse_iter && *collapse_iter == NULL)
689 *collapse_iter = create_tmp_var (iter_type, ".iter");
690 if (collapse_count && *collapse_count == NULL)
691 {
692 if (count)
db3927fb 693 *collapse_count = fold_convert_loc (loc, iter_type, count);
a68ab351
JJ
694 else
695 *collapse_count = create_tmp_var (iter_type, ".count");
696 }
697
698 if (fd->collapse > 1)
699 {
700 fd->loop.v = *collapse_iter;
701 fd->loop.n1 = build_int_cst (TREE_TYPE (fd->loop.v), 0);
702 fd->loop.n2 = *collapse_count;
703 fd->loop.step = build_int_cst (TREE_TYPE (fd->loop.v), 1);
704 fd->loop.cond_code = LT_EXPR;
705 }
41dbbb37
TS
706
707 /* For OpenACC loops, force a chunk size of one, as this avoids the default
708 scheduling where several subsequent iterations are being executed by the
709 same thread. */
710 if (gimple_omp_for_kind (for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
711 {
712 gcc_assert (fd->chunk_size == NULL_TREE);
713 fd->chunk_size = build_int_cst (TREE_TYPE (fd->loop.v), 1);
714 }
50674e96
DN
715}
716
717
718/* Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB
719 is the immediate dominator of PAR_ENTRY_BB, return true if there
720 are no data dependencies that would prevent expanding the parallel
721 directive at PAR_ENTRY_BB as a combined parallel+workshare region.
722
723 When expanding a combined parallel+workshare region, the call to
724 the child function may need additional arguments in the case of
726a989a
RB
725 GIMPLE_OMP_FOR regions. In some cases, these arguments are
726 computed out of variables passed in from the parent to the child
727 via 'struct .omp_data_s'. For instance:
50674e96
DN
728
729 #pragma omp parallel for schedule (guided, i * 4)
730 for (j ...)
731
732 Is lowered into:
733
734 # BLOCK 2 (PAR_ENTRY_BB)
735 .omp_data_o.i = i;
736 #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
b8698a0f 737
50674e96
DN
738 # BLOCK 3 (WS_ENTRY_BB)
739 .omp_data_i = &.omp_data_o;
740 D.1667 = .omp_data_i->i;
741 D.1598 = D.1667 * 4;
742 #pragma omp for schedule (guided, D.1598)
743
744 When we outline the parallel region, the call to the child function
745 'bar.omp_fn.0' will need the value D.1598 in its argument list, but
746 that value is computed *after* the call site. So, in principle we
747 cannot do the transformation.
748
749 To see whether the code in WS_ENTRY_BB blocks the combined
750 parallel+workshare call, we collect all the variables used in the
726a989a 751 GIMPLE_OMP_FOR header check whether they appear on the LHS of any
50674e96
DN
752 statement in WS_ENTRY_BB. If so, then we cannot emit the combined
753 call.
754
755 FIXME. If we had the SSA form built at this point, we could merely
756 hoist the code in block 3 into block 2 and be done with it. But at
757 this point we don't have dataflow information and though we could
758 hack something up here, it is really not worth the aggravation. */
759
760static bool
0f900dfa 761workshare_safe_to_combine_p (basic_block ws_entry_bb)
50674e96
DN
762{
763 struct omp_for_data fd;
0f900dfa 764 gimple ws_stmt = last_stmt (ws_entry_bb);
50674e96 765
726a989a 766 if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
50674e96
DN
767 return true;
768
726a989a 769 gcc_assert (gimple_code (ws_stmt) == GIMPLE_OMP_FOR);
50674e96 770
538dd0b7 771 extract_omp_for_data (as_a <gomp_for *> (ws_stmt), &fd, NULL);
a68ab351
JJ
772
773 if (fd.collapse > 1 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
774 return false;
775 if (fd.iter_type != long_integer_type_node)
776 return false;
50674e96
DN
777
778 /* FIXME. We give up too easily here. If any of these arguments
779 are not constants, they will likely involve variables that have
780 been mapped into fields of .omp_data_s for sharing with the child
781 function. With appropriate data flow, it would be possible to
782 see through this. */
a68ab351
JJ
783 if (!is_gimple_min_invariant (fd.loop.n1)
784 || !is_gimple_min_invariant (fd.loop.n2)
785 || !is_gimple_min_invariant (fd.loop.step)
50674e96
DN
786 || (fd.chunk_size && !is_gimple_min_invariant (fd.chunk_size)))
787 return false;
788
789 return true;
790}
791
792
793/* Collect additional arguments needed to emit a combined
794 parallel+workshare call. WS_STMT is the workshare directive being
795 expanded. */
796
9771b263 797static vec<tree, va_gc> *
acf0174b 798get_ws_args_for (gimple par_stmt, gimple ws_stmt)
50674e96
DN
799{
800 tree t;
db3927fb 801 location_t loc = gimple_location (ws_stmt);
9771b263 802 vec<tree, va_gc> *ws_args;
50674e96 803
538dd0b7 804 if (gomp_for *for_stmt = dyn_cast <gomp_for *> (ws_stmt))
50674e96
DN
805 {
806 struct omp_for_data fd;
acf0174b 807 tree n1, n2;
50674e96 808
538dd0b7 809 extract_omp_for_data (for_stmt, &fd, NULL);
acf0174b
JJ
810 n1 = fd.loop.n1;
811 n2 = fd.loop.n2;
812
538dd0b7 813 if (gimple_omp_for_combined_into_p (for_stmt))
acf0174b
JJ
814 {
815 tree innerc
816 = find_omp_clause (gimple_omp_parallel_clauses (par_stmt),
817 OMP_CLAUSE__LOOPTEMP_);
818 gcc_assert (innerc);
819 n1 = OMP_CLAUSE_DECL (innerc);
820 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
821 OMP_CLAUSE__LOOPTEMP_);
822 gcc_assert (innerc);
823 n2 = OMP_CLAUSE_DECL (innerc);
824 }
50674e96 825
9771b263 826 vec_alloc (ws_args, 3 + (fd.chunk_size != 0));
50674e96 827
acf0174b 828 t = fold_convert_loc (loc, long_integer_type_node, n1);
9771b263 829 ws_args->quick_push (t);
50674e96 830
acf0174b 831 t = fold_convert_loc (loc, long_integer_type_node, n2);
9771b263 832 ws_args->quick_push (t);
50674e96 833
3bb06db4 834 t = fold_convert_loc (loc, long_integer_type_node, fd.loop.step);
9771b263 835 ws_args->quick_push (t);
3bb06db4
NF
836
837 if (fd.chunk_size)
838 {
839 t = fold_convert_loc (loc, long_integer_type_node, fd.chunk_size);
9771b263 840 ws_args->quick_push (t);
3bb06db4 841 }
50674e96
DN
842
843 return ws_args;
844 }
726a989a 845 else if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
50674e96 846 {
e5c95afe 847 /* Number of sections is equal to the number of edges from the
726a989a
RB
848 GIMPLE_OMP_SECTIONS_SWITCH statement, except for the one to
849 the exit of the sections region. */
850 basic_block bb = single_succ (gimple_bb (ws_stmt));
e5c95afe 851 t = build_int_cst (unsigned_type_node, EDGE_COUNT (bb->succs) - 1);
9771b263
DN
852 vec_alloc (ws_args, 1);
853 ws_args->quick_push (t);
3bb06db4 854 return ws_args;
50674e96
DN
855 }
856
857 gcc_unreachable ();
858}
859
860
861/* Discover whether REGION is a combined parallel+workshare region. */
862
863static void
864determine_parallel_type (struct omp_region *region)
953ff289 865{
50674e96
DN
866 basic_block par_entry_bb, par_exit_bb;
867 basic_block ws_entry_bb, ws_exit_bb;
868
d3c673c7 869 if (region == NULL || region->inner == NULL
e5c95afe
ZD
870 || region->exit == NULL || region->inner->exit == NULL
871 || region->inner->cont == NULL)
50674e96
DN
872 return;
873
874 /* We only support parallel+for and parallel+sections. */
726a989a
RB
875 if (region->type != GIMPLE_OMP_PARALLEL
876 || (region->inner->type != GIMPLE_OMP_FOR
877 && region->inner->type != GIMPLE_OMP_SECTIONS))
50674e96
DN
878 return;
879
880 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
881 WS_EXIT_BB -> PAR_EXIT_BB. */
777f7f9a
RH
882 par_entry_bb = region->entry;
883 par_exit_bb = region->exit;
884 ws_entry_bb = region->inner->entry;
885 ws_exit_bb = region->inner->exit;
50674e96
DN
886
887 if (single_succ (par_entry_bb) == ws_entry_bb
888 && single_succ (ws_exit_bb) == par_exit_bb
0f900dfa 889 && workshare_safe_to_combine_p (ws_entry_bb)
726a989a 890 && (gimple_omp_parallel_combined_p (last_stmt (par_entry_bb))
69f1837b
JJ
891 || (last_and_only_stmt (ws_entry_bb)
892 && last_and_only_stmt (par_exit_bb))))
50674e96 893 {
acf0174b 894 gimple par_stmt = last_stmt (par_entry_bb);
726a989a 895 gimple ws_stmt = last_stmt (ws_entry_bb);
777f7f9a 896
726a989a 897 if (region->inner->type == GIMPLE_OMP_FOR)
50674e96
DN
898 {
899 /* If this is a combined parallel loop, we need to determine
900 whether or not to use the combined library calls. There
901 are two cases where we do not apply the transformation:
902 static loops and any kind of ordered loop. In the first
903 case, we already open code the loop so there is no need
904 to do anything else. In the latter case, the combined
905 parallel loop call would still need extra synchronization
906 to implement ordered semantics, so there would not be any
907 gain in using the combined call. */
726a989a 908 tree clauses = gimple_omp_for_clauses (ws_stmt);
50674e96
DN
909 tree c = find_omp_clause (clauses, OMP_CLAUSE_SCHEDULE);
910 if (c == NULL
911 || OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_STATIC
912 || find_omp_clause (clauses, OMP_CLAUSE_ORDERED))
913 {
914 region->is_combined_parallel = false;
915 region->inner->is_combined_parallel = false;
916 return;
917 }
918 }
919
920 region->is_combined_parallel = true;
921 region->inner->is_combined_parallel = true;
acf0174b 922 region->ws_args = get_ws_args_for (par_stmt, ws_stmt);
50674e96 923 }
953ff289
DN
924}
925
50674e96 926
953ff289
DN
927/* Return true if EXPR is variable sized. */
928
929static inline bool
22ea9ec0 930is_variable_sized (const_tree expr)
953ff289
DN
931{
932 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr)));
933}
934
935/* Return true if DECL is a reference type. */
936
937static inline bool
938is_reference (tree decl)
939{
940 return lang_hooks.decls.omp_privatize_by_reference (decl);
941}
942
41dbbb37
TS
943/* Return the type of a decl. If the decl is reference type,
944 return its base type. */
945static inline tree
946get_base_type (tree decl)
947{
948 tree type = TREE_TYPE (decl);
949 if (is_reference (decl))
950 type = TREE_TYPE (type);
951 return type;
952}
953
954/* Lookup variables. The "maybe" form
953ff289
DN
955 allows for the variable form to not have been entered, otherwise we
956 assert that the variable must have been entered. */
957
958static inline tree
959lookup_decl (tree var, omp_context *ctx)
960{
b787e7a2 961 tree *n = ctx->cb.decl_map->get (var);
6be42dd4 962 return *n;
953ff289
DN
963}
964
965static inline tree
7c8f7639 966maybe_lookup_decl (const_tree var, omp_context *ctx)
953ff289 967{
b787e7a2 968 tree *n = ctx->cb.decl_map->get (const_cast<tree> (var));
6be42dd4 969 return n ? *n : NULL_TREE;
953ff289
DN
970}
971
972static inline tree
973lookup_field (tree var, omp_context *ctx)
974{
975 splay_tree_node n;
976 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
977 return (tree) n->value;
978}
979
a68ab351
JJ
980static inline tree
981lookup_sfield (tree var, omp_context *ctx)
982{
983 splay_tree_node n;
984 n = splay_tree_lookup (ctx->sfield_map
985 ? ctx->sfield_map : ctx->field_map,
986 (splay_tree_key) var);
987 return (tree) n->value;
988}
989
953ff289
DN
990static inline tree
991maybe_lookup_field (tree var, omp_context *ctx)
992{
993 splay_tree_node n;
994 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
995 return n ? (tree) n->value : NULL_TREE;
996}
997
41dbbb37
TS
998static inline tree
999lookup_oacc_reduction (const char *id, omp_context *ctx)
1000{
1001 splay_tree_node n;
1002 n = splay_tree_lookup (ctx->reduction_map, (splay_tree_key) id);
1003 return (tree) n->value;
1004}
1005
1006static inline tree
1007maybe_lookup_oacc_reduction (tree var, omp_context *ctx)
1008{
1009 splay_tree_node n = NULL;
1010 if (ctx->reduction_map)
1011 n = splay_tree_lookup (ctx->reduction_map, (splay_tree_key) var);
1012 return n ? (tree) n->value : NULL_TREE;
1013}
1014
7c8f7639
JJ
1015/* Return true if DECL should be copied by pointer. SHARED_CTX is
1016 the parallel context if DECL is to be shared. */
953ff289
DN
1017
1018static bool
a68ab351 1019use_pointer_for_field (tree decl, omp_context *shared_ctx)
953ff289
DN
1020{
1021 if (AGGREGATE_TYPE_P (TREE_TYPE (decl)))
1022 return true;
1023
6fc0bb99 1024 /* We can only use copy-in/copy-out semantics for shared variables
953ff289 1025 when we know the value is not accessible from an outer scope. */
7c8f7639 1026 if (shared_ctx)
953ff289 1027 {
41dbbb37
TS
1028 gcc_assert (!is_gimple_omp_oacc (shared_ctx->stmt));
1029
953ff289
DN
1030 /* ??? Trivially accessible from anywhere. But why would we even
1031 be passing an address in this case? Should we simply assert
1032 this to be false, or should we have a cleanup pass that removes
1033 these from the list of mappings? */
1034 if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
1035 return true;
1036
1037 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
1038 without analyzing the expression whether or not its location
1039 is accessible to anyone else. In the case of nested parallel
1040 regions it certainly may be. */
077b0dfb 1041 if (TREE_CODE (decl) != RESULT_DECL && DECL_HAS_VALUE_EXPR_P (decl))
953ff289
DN
1042 return true;
1043
1044 /* Do not use copy-in/copy-out for variables that have their
1045 address taken. */
1046 if (TREE_ADDRESSABLE (decl))
1047 return true;
7c8f7639 1048
6d840d99
JJ
1049 /* lower_send_shared_vars only uses copy-in, but not copy-out
1050 for these. */
1051 if (TREE_READONLY (decl)
1052 || ((TREE_CODE (decl) == RESULT_DECL
1053 || TREE_CODE (decl) == PARM_DECL)
1054 && DECL_BY_REFERENCE (decl)))
1055 return false;
1056
7c8f7639
JJ
1057 /* Disallow copy-in/out in nested parallel if
1058 decl is shared in outer parallel, otherwise
1059 each thread could store the shared variable
1060 in its own copy-in location, making the
1061 variable no longer really shared. */
6d840d99 1062 if (shared_ctx->is_nested)
7c8f7639
JJ
1063 {
1064 omp_context *up;
1065
1066 for (up = shared_ctx->outer; up; up = up->outer)
d9c194cb 1067 if (is_taskreg_ctx (up) && maybe_lookup_decl (decl, up))
7c8f7639
JJ
1068 break;
1069
d9c194cb 1070 if (up)
7c8f7639
JJ
1071 {
1072 tree c;
1073
726a989a 1074 for (c = gimple_omp_taskreg_clauses (up->stmt);
7c8f7639
JJ
1075 c; c = OMP_CLAUSE_CHAIN (c))
1076 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
1077 && OMP_CLAUSE_DECL (c) == decl)
1078 break;
1079
1080 if (c)
25142650 1081 goto maybe_mark_addressable_and_ret;
7c8f7639
JJ
1082 }
1083 }
a68ab351 1084
6d840d99 1085 /* For tasks avoid using copy-in/out. As tasks can be
a68ab351
JJ
1086 deferred or executed in different thread, when GOMP_task
1087 returns, the task hasn't necessarily terminated. */
6d840d99 1088 if (is_task_ctx (shared_ctx))
a68ab351 1089 {
25142650
JJ
1090 tree outer;
1091 maybe_mark_addressable_and_ret:
1092 outer = maybe_lookup_decl_in_outer_ctx (decl, shared_ctx);
a68ab351
JJ
1093 if (is_gimple_reg (outer))
1094 {
1095 /* Taking address of OUTER in lower_send_shared_vars
1096 might need regimplification of everything that uses the
1097 variable. */
1098 if (!task_shared_vars)
1099 task_shared_vars = BITMAP_ALLOC (NULL);
1100 bitmap_set_bit (task_shared_vars, DECL_UID (outer));
1101 TREE_ADDRESSABLE (outer) = 1;
1102 }
1103 return true;
1104 }
953ff289
DN
1105 }
1106
1107 return false;
1108}
1109
917948d3
ZD
1110/* Construct a new automatic decl similar to VAR. */
1111
1112static tree
1113omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx)
1114{
1115 tree copy = copy_var_decl (var, name, type);
1116
1117 DECL_CONTEXT (copy) = current_function_decl;
910ad8de 1118 DECL_CHAIN (copy) = ctx->block_vars;
953ff289
DN
1119 ctx->block_vars = copy;
1120
1121 return copy;
1122}
1123
1124static tree
1125omp_copy_decl_1 (tree var, omp_context *ctx)
1126{
1127 return omp_copy_decl_2 (var, DECL_NAME (var), TREE_TYPE (var), ctx);
1128}
1129
a9a58711
JJ
1130/* Build COMPONENT_REF and set TREE_THIS_VOLATILE and TREE_READONLY on it
1131 as appropriate. */
1132static tree
1133omp_build_component_ref (tree obj, tree field)
1134{
1135 tree ret = build3 (COMPONENT_REF, TREE_TYPE (field), obj, field, NULL);
1136 if (TREE_THIS_VOLATILE (field))
1137 TREE_THIS_VOLATILE (ret) |= 1;
1138 if (TREE_READONLY (field))
1139 TREE_READONLY (ret) |= 1;
1140 return ret;
1141}
1142
953ff289
DN
1143/* Build tree nodes to access the field for VAR on the receiver side. */
1144
1145static tree
1146build_receiver_ref (tree var, bool by_ref, omp_context *ctx)
1147{
1148 tree x, field = lookup_field (var, ctx);
1149
1150 /* If the receiver record type was remapped in the child function,
1151 remap the field into the new record type. */
1152 x = maybe_lookup_field (field, ctx);
1153 if (x != NULL)
1154 field = x;
1155
70f34814 1156 x = build_simple_mem_ref (ctx->receiver_decl);
a9a58711 1157 x = omp_build_component_ref (x, field);
953ff289 1158 if (by_ref)
70f34814 1159 x = build_simple_mem_ref (x);
953ff289
DN
1160
1161 return x;
1162}
1163
1164/* Build tree nodes to access VAR in the scope outer to CTX. In the case
1165 of a parallel, this is a component reference; for workshare constructs
1166 this is some variable. */
1167
1168static tree
1169build_outer_var_ref (tree var, omp_context *ctx)
1170{
1171 tree x;
1172
8ca5b2a2 1173 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx)))
953ff289
DN
1174 x = var;
1175 else if (is_variable_sized (var))
1176 {
1177 x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
1178 x = build_outer_var_ref (x, ctx);
70f34814 1179 x = build_simple_mem_ref (x);
953ff289 1180 }
a68ab351 1181 else if (is_taskreg_ctx (ctx))
953ff289 1182 {
7c8f7639 1183 bool by_ref = use_pointer_for_field (var, NULL);
953ff289
DN
1184 x = build_receiver_ref (var, by_ref, ctx);
1185 }
74bf76ed 1186 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
0aadce73 1187 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
74bf76ed
JJ
1188 {
1189 /* #pragma omp simd isn't a worksharing construct, and can reference even
1190 private vars in its linear etc. clauses. */
1191 x = NULL_TREE;
1192 if (ctx->outer && is_taskreg_ctx (ctx))
1193 x = lookup_decl (var, ctx->outer);
1194 else if (ctx->outer)
f3b331d1 1195 x = maybe_lookup_decl_in_outer_ctx (var, ctx);
74bf76ed
JJ
1196 if (x == NULL_TREE)
1197 x = var;
1198 }
953ff289
DN
1199 else if (ctx->outer)
1200 x = lookup_decl (var, ctx->outer);
eeb1d9e0
JJ
1201 else if (is_reference (var))
1202 /* This can happen with orphaned constructs. If var is reference, it is
1203 possible it is shared and as such valid. */
1204 x = var;
953ff289
DN
1205 else
1206 gcc_unreachable ();
1207
1208 if (is_reference (var))
70f34814 1209 x = build_simple_mem_ref (x);
953ff289
DN
1210
1211 return x;
1212}
1213
1214/* Build tree nodes to access the field for VAR on the sender side. */
1215
1216static tree
1217build_sender_ref (tree var, omp_context *ctx)
1218{
a68ab351 1219 tree field = lookup_sfield (var, ctx);
a9a58711 1220 return omp_build_component_ref (ctx->sender_decl, field);
953ff289
DN
1221}
1222
1223/* Add a new field for VAR inside the structure CTX->SENDER_DECL. */
1224
1225static void
a68ab351 1226install_var_field (tree var, bool by_ref, int mask, omp_context *ctx)
953ff289 1227{
a68ab351 1228 tree field, type, sfield = NULL_TREE;
953ff289 1229
a68ab351
JJ
1230 gcc_assert ((mask & 1) == 0
1231 || !splay_tree_lookup (ctx->field_map, (splay_tree_key) var));
1232 gcc_assert ((mask & 2) == 0 || !ctx->sfield_map
1233 || !splay_tree_lookup (ctx->sfield_map, (splay_tree_key) var));
41dbbb37
TS
1234 gcc_assert ((mask & 3) == 3
1235 || !is_gimple_omp_oacc (ctx->stmt));
953ff289
DN
1236
1237 type = TREE_TYPE (var);
acf0174b
JJ
1238 if (mask & 4)
1239 {
1240 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
1241 type = build_pointer_type (build_pointer_type (type));
1242 }
1243 else if (by_ref)
953ff289 1244 type = build_pointer_type (type);
a68ab351
JJ
1245 else if ((mask & 3) == 1 && is_reference (var))
1246 type = TREE_TYPE (type);
953ff289 1247
c2255bc4
AH
1248 field = build_decl (DECL_SOURCE_LOCATION (var),
1249 FIELD_DECL, DECL_NAME (var), type);
953ff289
DN
1250
1251 /* Remember what variable this field was created for. This does have a
1252 side effect of making dwarf2out ignore this member, so for helpful
1253 debugging we clear it later in delete_omp_context. */
1254 DECL_ABSTRACT_ORIGIN (field) = var;
a68ab351
JJ
1255 if (type == TREE_TYPE (var))
1256 {
1257 DECL_ALIGN (field) = DECL_ALIGN (var);
1258 DECL_USER_ALIGN (field) = DECL_USER_ALIGN (var);
1259 TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (var);
1260 }
1261 else
1262 DECL_ALIGN (field) = TYPE_ALIGN (type);
953ff289 1263
a68ab351
JJ
1264 if ((mask & 3) == 3)
1265 {
1266 insert_field_into_struct (ctx->record_type, field);
1267 if (ctx->srecord_type)
1268 {
c2255bc4
AH
1269 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1270 FIELD_DECL, DECL_NAME (var), type);
a68ab351
JJ
1271 DECL_ABSTRACT_ORIGIN (sfield) = var;
1272 DECL_ALIGN (sfield) = DECL_ALIGN (field);
1273 DECL_USER_ALIGN (sfield) = DECL_USER_ALIGN (field);
1274 TREE_THIS_VOLATILE (sfield) = TREE_THIS_VOLATILE (field);
1275 insert_field_into_struct (ctx->srecord_type, sfield);
1276 }
1277 }
1278 else
1279 {
1280 if (ctx->srecord_type == NULL_TREE)
1281 {
1282 tree t;
1283
1284 ctx->srecord_type = lang_hooks.types.make_type (RECORD_TYPE);
1285 ctx->sfield_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1286 for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
1287 {
c2255bc4
AH
1288 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1289 FIELD_DECL, DECL_NAME (t), TREE_TYPE (t));
a68ab351
JJ
1290 DECL_ABSTRACT_ORIGIN (sfield) = DECL_ABSTRACT_ORIGIN (t);
1291 insert_field_into_struct (ctx->srecord_type, sfield);
1292 splay_tree_insert (ctx->sfield_map,
1293 (splay_tree_key) DECL_ABSTRACT_ORIGIN (t),
1294 (splay_tree_value) sfield);
1295 }
1296 }
1297 sfield = field;
1298 insert_field_into_struct ((mask & 1) ? ctx->record_type
1299 : ctx->srecord_type, field);
1300 }
953ff289 1301
a68ab351
JJ
1302 if (mask & 1)
1303 splay_tree_insert (ctx->field_map, (splay_tree_key) var,
1304 (splay_tree_value) field);
1305 if ((mask & 2) && ctx->sfield_map)
1306 splay_tree_insert (ctx->sfield_map, (splay_tree_key) var,
1307 (splay_tree_value) sfield);
953ff289
DN
1308}
1309
1310static tree
1311install_var_local (tree var, omp_context *ctx)
1312{
1313 tree new_var = omp_copy_decl_1 (var, ctx);
1314 insert_decl_map (&ctx->cb, var, new_var);
1315 return new_var;
1316}
1317
1318/* Adjust the replacement for DECL in CTX for the new context. This means
1319 copying the DECL_VALUE_EXPR, and fixing up the type. */
1320
1321static void
1322fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug)
1323{
1324 tree new_decl, size;
1325
1326 new_decl = lookup_decl (decl, ctx);
1327
1328 TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb);
1329
1330 if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug)
1331 && DECL_HAS_VALUE_EXPR_P (decl))
1332 {
1333 tree ve = DECL_VALUE_EXPR (decl);
726a989a 1334 walk_tree (&ve, copy_tree_body_r, &ctx->cb, NULL);
953ff289
DN
1335 SET_DECL_VALUE_EXPR (new_decl, ve);
1336 DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
1337 }
1338
1339 if (!TREE_CONSTANT (DECL_SIZE (new_decl)))
1340 {
1341 size = remap_decl (DECL_SIZE (decl), &ctx->cb);
1342 if (size == error_mark_node)
1343 size = TYPE_SIZE (TREE_TYPE (new_decl));
1344 DECL_SIZE (new_decl) = size;
1345
1346 size = remap_decl (DECL_SIZE_UNIT (decl), &ctx->cb);
1347 if (size == error_mark_node)
1348 size = TYPE_SIZE_UNIT (TREE_TYPE (new_decl));
1349 DECL_SIZE_UNIT (new_decl) = size;
1350 }
1351}
1352
1353/* The callback for remap_decl. Search all containing contexts for a
1354 mapping of the variable; this avoids having to duplicate the splay
1355 tree ahead of time. We know a mapping doesn't already exist in the
1356 given context. Create new mappings to implement default semantics. */
1357
1358static tree
1359omp_copy_decl (tree var, copy_body_data *cb)
1360{
1361 omp_context *ctx = (omp_context *) cb;
1362 tree new_var;
1363
953ff289
DN
1364 if (TREE_CODE (var) == LABEL_DECL)
1365 {
c2255bc4 1366 new_var = create_artificial_label (DECL_SOURCE_LOCATION (var));
50674e96 1367 DECL_CONTEXT (new_var) = current_function_decl;
953ff289
DN
1368 insert_decl_map (&ctx->cb, var, new_var);
1369 return new_var;
1370 }
1371
a68ab351 1372 while (!is_taskreg_ctx (ctx))
953ff289
DN
1373 {
1374 ctx = ctx->outer;
1375 if (ctx == NULL)
1376 return var;
1377 new_var = maybe_lookup_decl (var, ctx);
1378 if (new_var)
1379 return new_var;
1380 }
1381
8ca5b2a2
JJ
1382 if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn)
1383 return var;
1384
953ff289
DN
1385 return error_mark_node;
1386}
1387
50674e96 1388
50674e96
DN
1389/* Debugging dumps for parallel regions. */
1390void dump_omp_region (FILE *, struct omp_region *, int);
1391void debug_omp_region (struct omp_region *);
1392void debug_all_omp_regions (void);
1393
1394/* Dump the parallel region tree rooted at REGION. */
1395
1396void
1397dump_omp_region (FILE *file, struct omp_region *region, int indent)
1398{
777f7f9a 1399 fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index,
726a989a 1400 gimple_code_name[region->type]);
50674e96
DN
1401
1402 if (region->inner)
1403 dump_omp_region (file, region->inner, indent + 4);
1404
777f7f9a
RH
1405 if (region->cont)
1406 {
726a989a 1407 fprintf (file, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent, "",
777f7f9a
RH
1408 region->cont->index);
1409 }
b8698a0f 1410
50674e96 1411 if (region->exit)
726a989a 1412 fprintf (file, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent, "",
777f7f9a 1413 region->exit->index);
50674e96 1414 else
777f7f9a 1415 fprintf (file, "%*s[no exit marker]\n", indent, "");
50674e96
DN
1416
1417 if (region->next)
777f7f9a 1418 dump_omp_region (file, region->next, indent);
50674e96
DN
1419}
1420
24e47c76 1421DEBUG_FUNCTION void
50674e96
DN
1422debug_omp_region (struct omp_region *region)
1423{
1424 dump_omp_region (stderr, region, 0);
1425}
1426
24e47c76 1427DEBUG_FUNCTION void
50674e96
DN
1428debug_all_omp_regions (void)
1429{
1430 dump_omp_region (stderr, root_omp_region, 0);
1431}
1432
1433
1434/* Create a new parallel region starting at STMT inside region PARENT. */
1435
0645c1a2 1436static struct omp_region *
726a989a
RB
1437new_omp_region (basic_block bb, enum gimple_code type,
1438 struct omp_region *parent)
50674e96 1439{
d3bfe4de 1440 struct omp_region *region = XCNEW (struct omp_region);
50674e96
DN
1441
1442 region->outer = parent;
777f7f9a
RH
1443 region->entry = bb;
1444 region->type = type;
50674e96
DN
1445
1446 if (parent)
1447 {
1448 /* This is a nested region. Add it to the list of inner
1449 regions in PARENT. */
1450 region->next = parent->inner;
1451 parent->inner = region;
1452 }
777f7f9a 1453 else
50674e96
DN
1454 {
1455 /* This is a toplevel region. Add it to the list of toplevel
1456 regions in ROOT_OMP_REGION. */
1457 region->next = root_omp_region;
1458 root_omp_region = region;
1459 }
777f7f9a
RH
1460
1461 return region;
1462}
1463
1464/* Release the memory associated with the region tree rooted at REGION. */
1465
1466static void
1467free_omp_region_1 (struct omp_region *region)
1468{
1469 struct omp_region *i, *n;
1470
1471 for (i = region->inner; i ; i = n)
50674e96 1472 {
777f7f9a
RH
1473 n = i->next;
1474 free_omp_region_1 (i);
50674e96
DN
1475 }
1476
777f7f9a
RH
1477 free (region);
1478}
50674e96 1479
777f7f9a
RH
1480/* Release the memory for the entire omp region tree. */
1481
1482void
1483free_omp_regions (void)
1484{
1485 struct omp_region *r, *n;
1486 for (r = root_omp_region; r ; r = n)
1487 {
1488 n = r->next;
1489 free_omp_region_1 (r);
1490 }
1491 root_omp_region = NULL;
50674e96
DN
1492}
1493
1494
953ff289
DN
1495/* Create a new context, with OUTER_CTX being the surrounding context. */
1496
1497static omp_context *
726a989a 1498new_omp_context (gimple stmt, omp_context *outer_ctx)
953ff289
DN
1499{
1500 omp_context *ctx = XCNEW (omp_context);
1501
1502 splay_tree_insert (all_contexts, (splay_tree_key) stmt,
1503 (splay_tree_value) ctx);
1504 ctx->stmt = stmt;
1505
1506 if (outer_ctx)
1507 {
1508 ctx->outer = outer_ctx;
1509 ctx->cb = outer_ctx->cb;
1510 ctx->cb.block = NULL;
1511 ctx->depth = outer_ctx->depth + 1;
41dbbb37 1512 ctx->reduction_map = outer_ctx->reduction_map;
953ff289
DN
1513 }
1514 else
1515 {
1516 ctx->cb.src_fn = current_function_decl;
1517 ctx->cb.dst_fn = current_function_decl;
d52f5295 1518 ctx->cb.src_node = cgraph_node::get (current_function_decl);
fe660d7b 1519 gcc_checking_assert (ctx->cb.src_node);
953ff289
DN
1520 ctx->cb.dst_node = ctx->cb.src_node;
1521 ctx->cb.src_cfun = cfun;
1522 ctx->cb.copy_decl = omp_copy_decl;
1d65f45c 1523 ctx->cb.eh_lp_nr = 0;
953ff289
DN
1524 ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
1525 ctx->depth = 1;
1526 }
1527
b787e7a2 1528 ctx->cb.decl_map = new hash_map<tree, tree>;
953ff289
DN
1529
1530 return ctx;
1531}
1532
726a989a 1533static gimple_seq maybe_catch_exception (gimple_seq);
2368a460
JJ
1534
1535/* Finalize task copyfn. */
1536
1537static void
538dd0b7 1538finalize_task_copyfn (gomp_task *task_stmt)
2368a460
JJ
1539{
1540 struct function *child_cfun;
af16bc76 1541 tree child_fn;
355a7673 1542 gimple_seq seq = NULL, new_seq;
538dd0b7 1543 gbind *bind;
2368a460 1544
726a989a 1545 child_fn = gimple_omp_task_copy_fn (task_stmt);
2368a460
JJ
1546 if (child_fn == NULL_TREE)
1547 return;
1548
1549 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
d7ed20db 1550 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
2368a460 1551
2368a460 1552 push_cfun (child_cfun);
3ad065ef 1553 bind = gimplify_body (child_fn, false);
726a989a
RB
1554 gimple_seq_add_stmt (&seq, bind);
1555 new_seq = maybe_catch_exception (seq);
1556 if (new_seq != seq)
1557 {
1558 bind = gimple_build_bind (NULL, new_seq, NULL);
355a7673 1559 seq = NULL;
726a989a
RB
1560 gimple_seq_add_stmt (&seq, bind);
1561 }
1562 gimple_set_body (child_fn, seq);
2368a460 1563 pop_cfun ();
2368a460 1564
d7ed20db 1565 /* Inform the callgraph about the new function. */
d52f5295 1566 cgraph_node::add_new_function (child_fn, false);
a79b7ec5 1567 cgraph_node::get (child_fn)->parallelized_function = 1;
2368a460
JJ
1568}
1569
953ff289
DN
1570/* Destroy a omp_context data structures. Called through the splay tree
1571 value delete callback. */
1572
1573static void
1574delete_omp_context (splay_tree_value value)
1575{
1576 omp_context *ctx = (omp_context *) value;
1577
b787e7a2 1578 delete ctx->cb.decl_map;
953ff289
DN
1579
1580 if (ctx->field_map)
1581 splay_tree_delete (ctx->field_map);
a68ab351
JJ
1582 if (ctx->sfield_map)
1583 splay_tree_delete (ctx->sfield_map);
3713412b
JJ
1584 /* Reduction map is copied to nested contexts, so only delete it in the
1585 owner. */
41dbbb37 1586 if (ctx->reduction_map
3713412b
JJ
1587 && gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET
1588 && is_gimple_omp_offloaded (ctx->stmt)
1589 && is_gimple_omp_oacc (ctx->stmt))
41dbbb37 1590 splay_tree_delete (ctx->reduction_map);
953ff289
DN
1591
1592 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
1593 it produces corrupt debug information. */
1594 if (ctx->record_type)
1595 {
1596 tree t;
910ad8de 1597 for (t = TYPE_FIELDS (ctx->record_type); t ; t = DECL_CHAIN (t))
953ff289
DN
1598 DECL_ABSTRACT_ORIGIN (t) = NULL;
1599 }
a68ab351
JJ
1600 if (ctx->srecord_type)
1601 {
1602 tree t;
910ad8de 1603 for (t = TYPE_FIELDS (ctx->srecord_type); t ; t = DECL_CHAIN (t))
a68ab351
JJ
1604 DECL_ABSTRACT_ORIGIN (t) = NULL;
1605 }
953ff289 1606
2368a460 1607 if (is_task_ctx (ctx))
538dd0b7 1608 finalize_task_copyfn (as_a <gomp_task *> (ctx->stmt));
2368a460 1609
953ff289
DN
1610 XDELETE (ctx);
1611}
1612
1613/* Fix up RECEIVER_DECL with a type that has been remapped to the child
1614 context. */
1615
1616static void
1617fixup_child_record_type (omp_context *ctx)
1618{
1619 tree f, type = ctx->record_type;
1620
1621 /* ??? It isn't sufficient to just call remap_type here, because
1622 variably_modified_type_p doesn't work the way we expect for
1623 record types. Testing each field for whether it needs remapping
1624 and creating a new record by hand works, however. */
910ad8de 1625 for (f = TYPE_FIELDS (type); f ; f = DECL_CHAIN (f))
953ff289
DN
1626 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
1627 break;
1628 if (f)
1629 {
1630 tree name, new_fields = NULL;
1631
1632 type = lang_hooks.types.make_type (RECORD_TYPE);
1633 name = DECL_NAME (TYPE_NAME (ctx->record_type));
c2255bc4
AH
1634 name = build_decl (DECL_SOURCE_LOCATION (ctx->receiver_decl),
1635 TYPE_DECL, name, type);
953ff289
DN
1636 TYPE_NAME (type) = name;
1637
910ad8de 1638 for (f = TYPE_FIELDS (ctx->record_type); f ; f = DECL_CHAIN (f))
953ff289
DN
1639 {
1640 tree new_f = copy_node (f);
1641 DECL_CONTEXT (new_f) = type;
1642 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
910ad8de 1643 DECL_CHAIN (new_f) = new_fields;
726a989a
RB
1644 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &ctx->cb, NULL);
1645 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r,
1646 &ctx->cb, NULL);
1647 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
1648 &ctx->cb, NULL);
953ff289
DN
1649 new_fields = new_f;
1650
1651 /* Arrange to be able to look up the receiver field
1652 given the sender field. */
1653 splay_tree_insert (ctx->field_map, (splay_tree_key) f,
1654 (splay_tree_value) new_f);
1655 }
1656 TYPE_FIELDS (type) = nreverse (new_fields);
1657 layout_type (type);
1658 }
1659
a2a2fe4b
RB
1660 TREE_TYPE (ctx->receiver_decl)
1661 = build_qualified_type (build_reference_type (type), TYPE_QUAL_RESTRICT);
953ff289
DN
1662}
1663
1664/* Instantiate decls as necessary in CTX to satisfy the data sharing
1665 specified by CLAUSES. */
1666
1667static void
1668scan_sharing_clauses (tree clauses, omp_context *ctx)
1669{
1670 tree c, decl;
1671 bool scan_array_reductions = false;
1672
1673 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1674 {
1675 bool by_ref;
1676
aaf46ef9 1677 switch (OMP_CLAUSE_CODE (c))
953ff289
DN
1678 {
1679 case OMP_CLAUSE_PRIVATE:
1680 decl = OMP_CLAUSE_DECL (c);
a68ab351
JJ
1681 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
1682 goto do_private;
1683 else if (!is_variable_sized (decl))
953ff289
DN
1684 install_var_local (decl, ctx);
1685 break;
1686
1687 case OMP_CLAUSE_SHARED:
9cf32741 1688 decl = OMP_CLAUSE_DECL (c);
acf0174b
JJ
1689 /* Ignore shared directives in teams construct. */
1690 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
9cf32741
JJ
1691 {
1692 /* Global variables don't need to be copied,
1693 the receiver side will use them directly. */
1694 tree odecl = maybe_lookup_decl_in_outer_ctx (decl, ctx);
1695 if (is_global_var (odecl))
1696 break;
1697 insert_decl_map (&ctx->cb, decl, odecl);
1698 break;
1699 }
a68ab351 1700 gcc_assert (is_taskreg_ctx (ctx));
5da250fc
JJ
1701 gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl))
1702 || !is_variable_sized (decl));
8ca5b2a2
JJ
1703 /* Global variables don't need to be copied,
1704 the receiver side will use them directly. */
1705 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1706 break;
a68ab351 1707 by_ref = use_pointer_for_field (decl, ctx);
953ff289
DN
1708 if (! TREE_READONLY (decl)
1709 || TREE_ADDRESSABLE (decl)
1710 || by_ref
1711 || is_reference (decl))
1712 {
a68ab351 1713 install_var_field (decl, by_ref, 3, ctx);
953ff289
DN
1714 install_var_local (decl, ctx);
1715 break;
1716 }
1717 /* We don't need to copy const scalar vars back. */
aaf46ef9 1718 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
953ff289
DN
1719 goto do_private;
1720
1721 case OMP_CLAUSE_LASTPRIVATE:
1722 /* Let the corresponding firstprivate clause create
1723 the variable. */
1724 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1725 break;
1726 /* FALLTHRU */
1727
1728 case OMP_CLAUSE_FIRSTPRIVATE:
41dbbb37
TS
1729 if (is_gimple_omp_oacc (ctx->stmt))
1730 {
1731 sorry ("clause not supported yet");
1732 break;
1733 }
1734 /* FALLTHRU */
953ff289 1735 case OMP_CLAUSE_REDUCTION:
74bf76ed 1736 case OMP_CLAUSE_LINEAR:
953ff289
DN
1737 decl = OMP_CLAUSE_DECL (c);
1738 do_private:
1739 if (is_variable_sized (decl))
953ff289 1740 {
a68ab351
JJ
1741 if (is_task_ctx (ctx))
1742 install_var_field (decl, false, 1, ctx);
1743 break;
1744 }
1745 else if (is_taskreg_ctx (ctx))
1746 {
1747 bool global
1748 = is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx));
7c8f7639 1749 by_ref = use_pointer_for_field (decl, NULL);
a68ab351
JJ
1750
1751 if (is_task_ctx (ctx)
1752 && (global || by_ref || is_reference (decl)))
1753 {
1754 install_var_field (decl, false, 1, ctx);
1755 if (!global)
1756 install_var_field (decl, by_ref, 2, ctx);
1757 }
1758 else if (!global)
1759 install_var_field (decl, by_ref, 3, ctx);
953ff289
DN
1760 }
1761 install_var_local (decl, ctx);
41dbbb37
TS
1762 if (is_gimple_omp_oacc (ctx->stmt)
1763 && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
1764 {
1765 /* Create a decl for the reduction array. */
1766 tree var = OMP_CLAUSE_DECL (c);
1767 tree type = get_base_type (var);
1768 tree ptype = build_pointer_type (type);
1769 tree array = create_tmp_var (ptype,
1770 oacc_get_reduction_array_id (var));
1771 omp_context *c = (ctx->field_map ? ctx : ctx->outer);
1772 install_var_field (array, true, 3, c);
1773 install_var_local (array, c);
1774
1775 /* Insert it into the current context. */
1776 splay_tree_insert (ctx->reduction_map, (splay_tree_key)
1777 oacc_get_reduction_array_id (var),
1778 (splay_tree_value) array);
1779 splay_tree_insert (ctx->reduction_map,
1780 (splay_tree_key) array,
1781 (splay_tree_value) array);
1782 }
953ff289
DN
1783 break;
1784
acf0174b
JJ
1785 case OMP_CLAUSE__LOOPTEMP_:
1786 gcc_assert (is_parallel_ctx (ctx));
1787 decl = OMP_CLAUSE_DECL (c);
1788 install_var_field (decl, false, 3, ctx);
1789 install_var_local (decl, ctx);
1790 break;
1791
953ff289 1792 case OMP_CLAUSE_COPYPRIVATE:
953ff289
DN
1793 case OMP_CLAUSE_COPYIN:
1794 decl = OMP_CLAUSE_DECL (c);
7c8f7639 1795 by_ref = use_pointer_for_field (decl, NULL);
a68ab351 1796 install_var_field (decl, by_ref, 3, ctx);
953ff289
DN
1797 break;
1798
1799 case OMP_CLAUSE_DEFAULT:
1800 ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
1801 break;
1802
20906c66 1803 case OMP_CLAUSE_FINAL:
953ff289
DN
1804 case OMP_CLAUSE_IF:
1805 case OMP_CLAUSE_NUM_THREADS:
acf0174b
JJ
1806 case OMP_CLAUSE_NUM_TEAMS:
1807 case OMP_CLAUSE_THREAD_LIMIT:
1808 case OMP_CLAUSE_DEVICE:
953ff289 1809 case OMP_CLAUSE_SCHEDULE:
acf0174b
JJ
1810 case OMP_CLAUSE_DIST_SCHEDULE:
1811 case OMP_CLAUSE_DEPEND:
9a771876 1812 case OMP_CLAUSE__CILK_FOR_COUNT_:
41dbbb37
TS
1813 case OMP_CLAUSE_NUM_GANGS:
1814 case OMP_CLAUSE_NUM_WORKERS:
1815 case OMP_CLAUSE_VECTOR_LENGTH:
953ff289 1816 if (ctx->outer)
726a989a 1817 scan_omp_op (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
953ff289
DN
1818 break;
1819
acf0174b
JJ
1820 case OMP_CLAUSE_TO:
1821 case OMP_CLAUSE_FROM:
1822 case OMP_CLAUSE_MAP:
1823 if (ctx->outer)
1824 scan_omp_op (&OMP_CLAUSE_SIZE (c), ctx->outer);
1825 decl = OMP_CLAUSE_DECL (c);
1826 /* Global variables with "omp declare target" attribute
1827 don't need to be copied, the receiver side will use them
1828 directly. */
1829 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1830 && DECL_P (decl)
1831 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
1f6be682 1832 && varpool_node::get_create (decl)->offloadable)
acf0174b
JJ
1833 break;
1834 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
41dbbb37 1835 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER)
acf0174b 1836 {
41dbbb37
TS
1837 /* Ignore GOMP_MAP_POINTER kind for arrays in regions that are
1838 not offloaded; there is nothing to map for those. */
1839 if (!is_gimple_omp_offloaded (ctx->stmt)
b8910447
JJ
1840 && !POINTER_TYPE_P (TREE_TYPE (decl))
1841 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
acf0174b
JJ
1842 break;
1843 }
1844 if (DECL_P (decl))
1845 {
1846 if (DECL_SIZE (decl)
1847 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1848 {
1849 tree decl2 = DECL_VALUE_EXPR (decl);
1850 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1851 decl2 = TREE_OPERAND (decl2, 0);
1852 gcc_assert (DECL_P (decl2));
1853 install_var_field (decl2, true, 3, ctx);
1854 install_var_local (decl2, ctx);
1855 install_var_local (decl, ctx);
1856 }
1857 else
1858 {
1859 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
41dbbb37 1860 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
acf0174b
JJ
1861 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
1862 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1863 install_var_field (decl, true, 7, ctx);
1864 else
1865 install_var_field (decl, true, 3, ctx);
41dbbb37 1866 if (is_gimple_omp_offloaded (ctx->stmt))
acf0174b
JJ
1867 install_var_local (decl, ctx);
1868 }
1869 }
1870 else
1871 {
1872 tree base = get_base_address (decl);
1873 tree nc = OMP_CLAUSE_CHAIN (c);
1874 if (DECL_P (base)
1875 && nc != NULL_TREE
1876 && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
1877 && OMP_CLAUSE_DECL (nc) == base
41dbbb37 1878 && OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_POINTER
acf0174b
JJ
1879 && integer_zerop (OMP_CLAUSE_SIZE (nc)))
1880 {
1881 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c) = 1;
1882 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (nc) = 1;
1883 }
1884 else
1885 {
f014c653
JJ
1886 if (ctx->outer)
1887 {
1888 scan_omp_op (&OMP_CLAUSE_DECL (c), ctx->outer);
1889 decl = OMP_CLAUSE_DECL (c);
1890 }
acf0174b
JJ
1891 gcc_assert (!splay_tree_lookup (ctx->field_map,
1892 (splay_tree_key) decl));
1893 tree field
1894 = build_decl (OMP_CLAUSE_LOCATION (c),
1895 FIELD_DECL, NULL_TREE, ptr_type_node);
1896 DECL_ALIGN (field) = TYPE_ALIGN (ptr_type_node);
1897 insert_field_into_struct (ctx->record_type, field);
1898 splay_tree_insert (ctx->field_map, (splay_tree_key) decl,
1899 (splay_tree_value) field);
1900 }
1901 }
1902 break;
1903
953ff289
DN
1904 case OMP_CLAUSE_NOWAIT:
1905 case OMP_CLAUSE_ORDERED:
a68ab351
JJ
1906 case OMP_CLAUSE_COLLAPSE:
1907 case OMP_CLAUSE_UNTIED:
20906c66 1908 case OMP_CLAUSE_MERGEABLE:
acf0174b 1909 case OMP_CLAUSE_PROC_BIND:
74bf76ed 1910 case OMP_CLAUSE_SAFELEN:
41dbbb37
TS
1911 case OMP_CLAUSE_ASYNC:
1912 case OMP_CLAUSE_WAIT:
1913 case OMP_CLAUSE_GANG:
1914 case OMP_CLAUSE_WORKER:
1915 case OMP_CLAUSE_VECTOR:
953ff289
DN
1916 break;
1917
acf0174b
JJ
1918 case OMP_CLAUSE_ALIGNED:
1919 decl = OMP_CLAUSE_DECL (c);
1920 if (is_global_var (decl)
1921 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1922 install_var_local (decl, ctx);
1923 break;
1924
41dbbb37
TS
1925 case OMP_CLAUSE_DEVICE_RESIDENT:
1926 case OMP_CLAUSE_USE_DEVICE:
1927 case OMP_CLAUSE__CACHE_:
1928 case OMP_CLAUSE_INDEPENDENT:
1929 case OMP_CLAUSE_AUTO:
1930 case OMP_CLAUSE_SEQ:
1931 sorry ("Clause not supported yet");
1932 break;
1933
953ff289
DN
1934 default:
1935 gcc_unreachable ();
1936 }
1937 }
1938
1939 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1940 {
aaf46ef9 1941 switch (OMP_CLAUSE_CODE (c))
953ff289
DN
1942 {
1943 case OMP_CLAUSE_LASTPRIVATE:
1944 /* Let the corresponding firstprivate clause create
1945 the variable. */
726a989a 1946 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
a68ab351 1947 scan_array_reductions = true;
953ff289
DN
1948 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1949 break;
1950 /* FALLTHRU */
1951
953ff289 1952 case OMP_CLAUSE_FIRSTPRIVATE:
41dbbb37
TS
1953 if (is_gimple_omp_oacc (ctx->stmt))
1954 {
1955 sorry ("clause not supported yet");
1956 break;
1957 }
1958 /* FALLTHRU */
1959 case OMP_CLAUSE_PRIVATE:
953ff289 1960 case OMP_CLAUSE_REDUCTION:
74bf76ed 1961 case OMP_CLAUSE_LINEAR:
953ff289
DN
1962 decl = OMP_CLAUSE_DECL (c);
1963 if (is_variable_sized (decl))
1964 install_var_local (decl, ctx);
1965 fixup_remapped_decl (decl, ctx,
aaf46ef9 1966 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
953ff289 1967 && OMP_CLAUSE_PRIVATE_DEBUG (c));
aaf46ef9 1968 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
953ff289
DN
1969 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1970 scan_array_reductions = true;
f7468577
JJ
1971 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
1972 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
1973 scan_array_reductions = true;
953ff289
DN
1974 break;
1975
1976 case OMP_CLAUSE_SHARED:
acf0174b
JJ
1977 /* Ignore shared directives in teams construct. */
1978 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1979 break;
953ff289 1980 decl = OMP_CLAUSE_DECL (c);
8ca5b2a2
JJ
1981 if (! is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1982 fixup_remapped_decl (decl, ctx, false);
953ff289
DN
1983 break;
1984
acf0174b 1985 case OMP_CLAUSE_MAP:
41dbbb37 1986 if (!is_gimple_omp_offloaded (ctx->stmt))
acf0174b
JJ
1987 break;
1988 decl = OMP_CLAUSE_DECL (c);
1989 if (DECL_P (decl)
1990 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
1f6be682 1991 && varpool_node::get_create (decl)->offloadable)
acf0174b
JJ
1992 break;
1993 if (DECL_P (decl))
1994 {
41dbbb37 1995 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
acf0174b
JJ
1996 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
1997 && !COMPLETE_TYPE_P (TREE_TYPE (decl)))
1998 {
1999 tree new_decl = lookup_decl (decl, ctx);
2000 TREE_TYPE (new_decl)
2001 = remap_type (TREE_TYPE (decl), &ctx->cb);
2002 }
2003 else if (DECL_SIZE (decl)
2004 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
2005 {
2006 tree decl2 = DECL_VALUE_EXPR (decl);
2007 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2008 decl2 = TREE_OPERAND (decl2, 0);
2009 gcc_assert (DECL_P (decl2));
2010 fixup_remapped_decl (decl2, ctx, false);
2011 fixup_remapped_decl (decl, ctx, true);
2012 }
2013 else
2014 fixup_remapped_decl (decl, ctx, false);
2015 }
2016 break;
2017
953ff289
DN
2018 case OMP_CLAUSE_COPYPRIVATE:
2019 case OMP_CLAUSE_COPYIN:
2020 case OMP_CLAUSE_DEFAULT:
2021 case OMP_CLAUSE_IF:
2022 case OMP_CLAUSE_NUM_THREADS:
acf0174b
JJ
2023 case OMP_CLAUSE_NUM_TEAMS:
2024 case OMP_CLAUSE_THREAD_LIMIT:
2025 case OMP_CLAUSE_DEVICE:
953ff289 2026 case OMP_CLAUSE_SCHEDULE:
acf0174b 2027 case OMP_CLAUSE_DIST_SCHEDULE:
953ff289
DN
2028 case OMP_CLAUSE_NOWAIT:
2029 case OMP_CLAUSE_ORDERED:
a68ab351
JJ
2030 case OMP_CLAUSE_COLLAPSE:
2031 case OMP_CLAUSE_UNTIED:
20906c66
JJ
2032 case OMP_CLAUSE_FINAL:
2033 case OMP_CLAUSE_MERGEABLE:
acf0174b 2034 case OMP_CLAUSE_PROC_BIND:
74bf76ed 2035 case OMP_CLAUSE_SAFELEN:
acf0174b
JJ
2036 case OMP_CLAUSE_ALIGNED:
2037 case OMP_CLAUSE_DEPEND:
2038 case OMP_CLAUSE__LOOPTEMP_:
2039 case OMP_CLAUSE_TO:
2040 case OMP_CLAUSE_FROM:
9a771876 2041 case OMP_CLAUSE__CILK_FOR_COUNT_:
41dbbb37
TS
2042 case OMP_CLAUSE_ASYNC:
2043 case OMP_CLAUSE_WAIT:
2044 case OMP_CLAUSE_NUM_GANGS:
2045 case OMP_CLAUSE_NUM_WORKERS:
2046 case OMP_CLAUSE_VECTOR_LENGTH:
2047 case OMP_CLAUSE_GANG:
2048 case OMP_CLAUSE_WORKER:
2049 case OMP_CLAUSE_VECTOR:
2050 break;
2051
2052 case OMP_CLAUSE_DEVICE_RESIDENT:
2053 case OMP_CLAUSE_USE_DEVICE:
2054 case OMP_CLAUSE__CACHE_:
2055 case OMP_CLAUSE_INDEPENDENT:
2056 case OMP_CLAUSE_AUTO:
2057 case OMP_CLAUSE_SEQ:
2058 sorry ("Clause not supported yet");
953ff289
DN
2059 break;
2060
2061 default:
2062 gcc_unreachable ();
2063 }
2064 }
2065
41dbbb37
TS
2066 gcc_checking_assert (!scan_array_reductions
2067 || !is_gimple_omp_oacc (ctx->stmt));
953ff289
DN
2068 if (scan_array_reductions)
2069 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
aaf46ef9 2070 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
953ff289
DN
2071 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2072 {
26127932
JJ
2073 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
2074 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
953ff289 2075 }
a68ab351 2076 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
726a989a 2077 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
26127932 2078 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
f7468577
JJ
2079 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
2080 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
2081 scan_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
953ff289
DN
2082}
2083
9a771876
JJ
2084/* Create a new name for omp child function. Returns an identifier. If
2085 IS_CILK_FOR is true then the suffix for the child function is
2086 "_cilk_for_fn." */
953ff289 2087
953ff289 2088static tree
9a771876 2089create_omp_child_function_name (bool task_copy, bool is_cilk_for)
953ff289 2090{
9a771876
JJ
2091 if (is_cilk_for)
2092 return clone_function_name (current_function_decl, "_cilk_for_fn");
2093 return clone_function_name (current_function_decl,
2094 task_copy ? "_omp_cpyfn" : "_omp_fn");
2095}
2096
2097/* Returns the type of the induction variable for the child function for
2098 _Cilk_for and the types for _high and _low variables based on TYPE. */
2099
2100static tree
2101cilk_for_check_loop_diff_type (tree type)
2102{
2103 if (TYPE_PRECISION (type) <= TYPE_PRECISION (uint32_type_node))
2104 {
2105 if (TYPE_UNSIGNED (type))
2106 return uint32_type_node;
2107 else
2108 return integer_type_node;
2109 }
2110 else
2111 {
2112 if (TYPE_UNSIGNED (type))
2113 return uint64_type_node;
2114 else
2115 return long_long_integer_type_node;
2116 }
953ff289
DN
2117}
2118
2119/* Build a decl for the omp child function. It'll not contain a body
2120 yet, just the bare decl. */
2121
2122static void
a68ab351 2123create_omp_child_function (omp_context *ctx, bool task_copy)
953ff289
DN
2124{
2125 tree decl, type, name, t;
2126
9a771876
JJ
2127 tree cilk_for_count
2128 = (flag_cilkplus && gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2129 ? find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
2130 OMP_CLAUSE__CILK_FOR_COUNT_) : NULL_TREE;
2131 tree cilk_var_type = NULL_TREE;
2132
2133 name = create_omp_child_function_name (task_copy,
2134 cilk_for_count != NULL_TREE);
a68ab351
JJ
2135 if (task_copy)
2136 type = build_function_type_list (void_type_node, ptr_type_node,
2137 ptr_type_node, NULL_TREE);
9a771876
JJ
2138 else if (cilk_for_count)
2139 {
2140 type = TREE_TYPE (OMP_CLAUSE_OPERAND (cilk_for_count, 0));
2141 cilk_var_type = cilk_for_check_loop_diff_type (type);
2142 type = build_function_type_list (void_type_node, ptr_type_node,
2143 cilk_var_type, cilk_var_type, NULL_TREE);
2144 }
a68ab351
JJ
2145 else
2146 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
953ff289 2147
9a771876 2148 decl = build_decl (gimple_location (ctx->stmt), FUNCTION_DECL, name, type);
953ff289 2149
41dbbb37
TS
2150 gcc_checking_assert (!is_gimple_omp_oacc (ctx->stmt)
2151 || !task_copy);
a68ab351
JJ
2152 if (!task_copy)
2153 ctx->cb.dst_fn = decl;
2154 else
726a989a 2155 gimple_omp_task_set_copy_fn (ctx->stmt, decl);
953ff289
DN
2156
2157 TREE_STATIC (decl) = 1;
2158 TREE_USED (decl) = 1;
2159 DECL_ARTIFICIAL (decl) = 1;
2160 DECL_IGNORED_P (decl) = 0;
2161 TREE_PUBLIC (decl) = 0;
2162 DECL_UNINLINABLE (decl) = 1;
2163 DECL_EXTERNAL (decl) = 0;
2164 DECL_CONTEXT (decl) = NULL_TREE;
50674e96 2165 DECL_INITIAL (decl) = make_node (BLOCK);
1f6be682
IV
2166 if (cgraph_node::get (current_function_decl)->offloadable)
2167 cgraph_node::get_create (decl)->offloadable = 1;
acf0174b
JJ
2168 else
2169 {
2170 omp_context *octx;
2171 for (octx = ctx; octx; octx = octx->outer)
41dbbb37 2172 if (is_gimple_omp_offloaded (octx->stmt))
acf0174b 2173 {
1f6be682 2174 cgraph_node::get_create (decl)->offloadable = 1;
844b0125 2175#ifdef ENABLE_OFFLOADING
1f6be682 2176 g->have_offload = true;
844b0125 2177#endif
acf0174b
JJ
2178 break;
2179 }
2180 }
953ff289 2181
d7823208
BS
2182 if (cgraph_node::get_create (decl)->offloadable
2183 && !lookup_attribute ("omp declare target",
2184 DECL_ATTRIBUTES (current_function_decl)))
2185 DECL_ATTRIBUTES (decl)
2186 = tree_cons (get_identifier ("omp target entrypoint"),
2187 NULL_TREE, DECL_ATTRIBUTES (decl));
2188
c2255bc4
AH
2189 t = build_decl (DECL_SOURCE_LOCATION (decl),
2190 RESULT_DECL, NULL_TREE, void_type_node);
953ff289
DN
2191 DECL_ARTIFICIAL (t) = 1;
2192 DECL_IGNORED_P (t) = 1;
07485407 2193 DECL_CONTEXT (t) = decl;
953ff289
DN
2194 DECL_RESULT (decl) = t;
2195
9a771876
JJ
2196 /* _Cilk_for's child function requires two extra parameters called
2197 __low and __high that are set the by Cilk runtime when it calls this
2198 function. */
2199 if (cilk_for_count)
2200 {
2201 t = build_decl (DECL_SOURCE_LOCATION (decl),
2202 PARM_DECL, get_identifier ("__high"), cilk_var_type);
2203 DECL_ARTIFICIAL (t) = 1;
2204 DECL_NAMELESS (t) = 1;
2205 DECL_ARG_TYPE (t) = ptr_type_node;
2206 DECL_CONTEXT (t) = current_function_decl;
2207 TREE_USED (t) = 1;
2208 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2209 DECL_ARGUMENTS (decl) = t;
2210
2211 t = build_decl (DECL_SOURCE_LOCATION (decl),
2212 PARM_DECL, get_identifier ("__low"), cilk_var_type);
2213 DECL_ARTIFICIAL (t) = 1;
2214 DECL_NAMELESS (t) = 1;
2215 DECL_ARG_TYPE (t) = ptr_type_node;
2216 DECL_CONTEXT (t) = current_function_decl;
2217 TREE_USED (t) = 1;
2218 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2219 DECL_ARGUMENTS (decl) = t;
2220 }
2221
2222 tree data_name = get_identifier (".omp_data_i");
2223 t = build_decl (DECL_SOURCE_LOCATION (decl), PARM_DECL, data_name,
2224 ptr_type_node);
953ff289 2225 DECL_ARTIFICIAL (t) = 1;
cd3f04c8 2226 DECL_NAMELESS (t) = 1;
953ff289 2227 DECL_ARG_TYPE (t) = ptr_type_node;
50674e96 2228 DECL_CONTEXT (t) = current_function_decl;
953ff289 2229 TREE_USED (t) = 1;
9a771876
JJ
2230 if (cilk_for_count)
2231 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
953ff289 2232 DECL_ARGUMENTS (decl) = t;
a68ab351
JJ
2233 if (!task_copy)
2234 ctx->receiver_decl = t;
2235 else
2236 {
c2255bc4
AH
2237 t = build_decl (DECL_SOURCE_LOCATION (decl),
2238 PARM_DECL, get_identifier (".omp_data_o"),
a68ab351
JJ
2239 ptr_type_node);
2240 DECL_ARTIFICIAL (t) = 1;
cd3f04c8 2241 DECL_NAMELESS (t) = 1;
a68ab351
JJ
2242 DECL_ARG_TYPE (t) = ptr_type_node;
2243 DECL_CONTEXT (t) = current_function_decl;
2244 TREE_USED (t) = 1;
628c189e 2245 TREE_ADDRESSABLE (t) = 1;
910ad8de 2246 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
a68ab351
JJ
2247 DECL_ARGUMENTS (decl) = t;
2248 }
953ff289 2249
b8698a0f 2250 /* Allocate memory for the function structure. The call to
50674e96 2251 allocate_struct_function clobbers CFUN, so we need to restore
953ff289 2252 it afterward. */
db2960f4 2253 push_struct_function (decl);
726a989a 2254 cfun->function_end_locus = gimple_location (ctx->stmt);
db2960f4 2255 pop_cfun ();
953ff289
DN
2256}
2257
acf0174b
JJ
2258/* Callback for walk_gimple_seq. Check if combined parallel
2259 contains gimple_omp_for_combined_into_p OMP_FOR. */
2260
2261static tree
2262find_combined_for (gimple_stmt_iterator *gsi_p,
2263 bool *handled_ops_p,
2264 struct walk_stmt_info *wi)
2265{
2266 gimple stmt = gsi_stmt (*gsi_p);
2267
2268 *handled_ops_p = true;
2269 switch (gimple_code (stmt))
2270 {
2271 WALK_SUBSTMTS;
2272
2273 case GIMPLE_OMP_FOR:
2274 if (gimple_omp_for_combined_into_p (stmt)
2275 && gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR)
2276 {
2277 wi->info = stmt;
2278 return integer_zero_node;
2279 }
2280 break;
2281 default:
2282 break;
2283 }
2284 return NULL;
2285}
2286
953ff289
DN
2287/* Scan an OpenMP parallel directive. */
2288
2289static void
726a989a 2290scan_omp_parallel (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
953ff289
DN
2291{
2292 omp_context *ctx;
2293 tree name;
538dd0b7 2294 gomp_parallel *stmt = as_a <gomp_parallel *> (gsi_stmt (*gsi));
953ff289
DN
2295
2296 /* Ignore parallel directives with empty bodies, unless there
2297 are copyin clauses. */
2298 if (optimize > 0
726a989a
RB
2299 && empty_body_p (gimple_omp_body (stmt))
2300 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
2301 OMP_CLAUSE_COPYIN) == NULL)
953ff289 2302 {
726a989a 2303 gsi_replace (gsi, gimple_build_nop (), false);
953ff289
DN
2304 return;
2305 }
2306
acf0174b
JJ
2307 if (gimple_omp_parallel_combined_p (stmt))
2308 {
acf0174b
JJ
2309 struct walk_stmt_info wi;
2310
2311 memset (&wi, 0, sizeof (wi));
2312 wi.val_only = true;
2313 walk_gimple_seq (gimple_omp_body (stmt),
2314 find_combined_for, NULL, &wi);
538dd0b7 2315 if (wi.info)
acf0174b 2316 {
538dd0b7 2317 gomp_for *for_stmt = as_a <gomp_for *> ((gimple) wi.info);
acf0174b
JJ
2318 struct omp_for_data fd;
2319 extract_omp_for_data (for_stmt, &fd, NULL);
2320 /* We need two temporaries with fd.loop.v type (istart/iend)
2321 and then (fd.collapse - 1) temporaries with the same
2322 type for count2 ... countN-1 vars if not constant. */
2323 size_t count = 2, i;
2324 tree type = fd.iter_type;
2325 if (fd.collapse > 1
2326 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
2327 count += fd.collapse - 1;
2328 for (i = 0; i < count; i++)
2329 {
b731b390 2330 tree temp = create_tmp_var (type);
acf0174b
JJ
2331 tree c = build_omp_clause (UNKNOWN_LOCATION,
2332 OMP_CLAUSE__LOOPTEMP_);
f014c653 2333 insert_decl_map (&outer_ctx->cb, temp, temp);
acf0174b
JJ
2334 OMP_CLAUSE_DECL (c) = temp;
2335 OMP_CLAUSE_CHAIN (c) = gimple_omp_parallel_clauses (stmt);
2336 gimple_omp_parallel_set_clauses (stmt, c);
2337 }
2338 }
2339 }
2340
726a989a 2341 ctx = new_omp_context (stmt, outer_ctx);
5771c391 2342 taskreg_contexts.safe_push (ctx);
a68ab351 2343 if (taskreg_nesting_level > 1)
50674e96 2344 ctx->is_nested = true;
953ff289 2345 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
953ff289
DN
2346 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2347 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
953ff289 2348 name = create_tmp_var_name (".omp_data_s");
c2255bc4
AH
2349 name = build_decl (gimple_location (stmt),
2350 TYPE_DECL, name, ctx->record_type);
cd3f04c8
JJ
2351 DECL_ARTIFICIAL (name) = 1;
2352 DECL_NAMELESS (name) = 1;
953ff289 2353 TYPE_NAME (ctx->record_type) = name;
a68ab351 2354 create_omp_child_function (ctx, false);
726a989a 2355 gimple_omp_parallel_set_child_fn (stmt, ctx->cb.dst_fn);
953ff289 2356
726a989a 2357 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt), ctx);
26127932 2358 scan_omp (gimple_omp_body_ptr (stmt), ctx);
953ff289
DN
2359
2360 if (TYPE_FIELDS (ctx->record_type) == NULL)
2361 ctx->record_type = ctx->receiver_decl = NULL;
953ff289
DN
2362}
2363
a68ab351
JJ
2364/* Scan an OpenMP task directive. */
2365
2366static void
726a989a 2367scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
a68ab351
JJ
2368{
2369 omp_context *ctx;
726a989a 2370 tree name, t;
538dd0b7 2371 gomp_task *stmt = as_a <gomp_task *> (gsi_stmt (*gsi));
a68ab351
JJ
2372
2373 /* Ignore task directives with empty bodies. */
2374 if (optimize > 0
726a989a 2375 && empty_body_p (gimple_omp_body (stmt)))
a68ab351 2376 {
726a989a 2377 gsi_replace (gsi, gimple_build_nop (), false);
a68ab351
JJ
2378 return;
2379 }
2380
726a989a 2381 ctx = new_omp_context (stmt, outer_ctx);
5771c391 2382 taskreg_contexts.safe_push (ctx);
a68ab351
JJ
2383 if (taskreg_nesting_level > 1)
2384 ctx->is_nested = true;
2385 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2386 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2387 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2388 name = create_tmp_var_name (".omp_data_s");
c2255bc4
AH
2389 name = build_decl (gimple_location (stmt),
2390 TYPE_DECL, name, ctx->record_type);
cd3f04c8
JJ
2391 DECL_ARTIFICIAL (name) = 1;
2392 DECL_NAMELESS (name) = 1;
a68ab351
JJ
2393 TYPE_NAME (ctx->record_type) = name;
2394 create_omp_child_function (ctx, false);
726a989a 2395 gimple_omp_task_set_child_fn (stmt, ctx->cb.dst_fn);
a68ab351 2396
726a989a 2397 scan_sharing_clauses (gimple_omp_task_clauses (stmt), ctx);
a68ab351
JJ
2398
2399 if (ctx->srecord_type)
2400 {
2401 name = create_tmp_var_name (".omp_data_a");
c2255bc4
AH
2402 name = build_decl (gimple_location (stmt),
2403 TYPE_DECL, name, ctx->srecord_type);
cd3f04c8
JJ
2404 DECL_ARTIFICIAL (name) = 1;
2405 DECL_NAMELESS (name) = 1;
a68ab351
JJ
2406 TYPE_NAME (ctx->srecord_type) = name;
2407 create_omp_child_function (ctx, true);
2408 }
2409
26127932 2410 scan_omp (gimple_omp_body_ptr (stmt), ctx);
a68ab351
JJ
2411
2412 if (TYPE_FIELDS (ctx->record_type) == NULL)
2413 {
2414 ctx->record_type = ctx->receiver_decl = NULL;
726a989a
RB
2415 t = build_int_cst (long_integer_type_node, 0);
2416 gimple_omp_task_set_arg_size (stmt, t);
2417 t = build_int_cst (long_integer_type_node, 1);
2418 gimple_omp_task_set_arg_align (stmt, t);
a68ab351 2419 }
5771c391
JJ
2420}
2421
2422
2423/* If any decls have been made addressable during scan_omp,
2424 adjust their fields if needed, and layout record types
2425 of parallel/task constructs. */
2426
2427static void
2428finish_taskreg_scan (omp_context *ctx)
2429{
2430 if (ctx->record_type == NULL_TREE)
2431 return;
2432
2433 /* If any task_shared_vars were needed, verify all
2434 OMP_CLAUSE_SHARED clauses on GIMPLE_OMP_{PARALLEL,TASK}
2435 statements if use_pointer_for_field hasn't changed
2436 because of that. If it did, update field types now. */
2437 if (task_shared_vars)
2438 {
2439 tree c;
2440
2441 for (c = gimple_omp_taskreg_clauses (ctx->stmt);
2442 c; c = OMP_CLAUSE_CHAIN (c))
2443 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED)
2444 {
2445 tree decl = OMP_CLAUSE_DECL (c);
2446
2447 /* Global variables don't need to be copied,
2448 the receiver side will use them directly. */
2449 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
2450 continue;
2451 if (!bitmap_bit_p (task_shared_vars, DECL_UID (decl))
2452 || !use_pointer_for_field (decl, ctx))
2453 continue;
2454 tree field = lookup_field (decl, ctx);
2455 if (TREE_CODE (TREE_TYPE (field)) == POINTER_TYPE
2456 && TREE_TYPE (TREE_TYPE (field)) == TREE_TYPE (decl))
2457 continue;
2458 TREE_TYPE (field) = build_pointer_type (TREE_TYPE (decl));
2459 TREE_THIS_VOLATILE (field) = 0;
2460 DECL_USER_ALIGN (field) = 0;
2461 DECL_ALIGN (field) = TYPE_ALIGN (TREE_TYPE (field));
2462 if (TYPE_ALIGN (ctx->record_type) < DECL_ALIGN (field))
2463 TYPE_ALIGN (ctx->record_type) = DECL_ALIGN (field);
2464 if (ctx->srecord_type)
2465 {
2466 tree sfield = lookup_sfield (decl, ctx);
2467 TREE_TYPE (sfield) = TREE_TYPE (field);
2468 TREE_THIS_VOLATILE (sfield) = 0;
2469 DECL_USER_ALIGN (sfield) = 0;
2470 DECL_ALIGN (sfield) = DECL_ALIGN (field);
2471 if (TYPE_ALIGN (ctx->srecord_type) < DECL_ALIGN (sfield))
2472 TYPE_ALIGN (ctx->srecord_type) = DECL_ALIGN (sfield);
2473 }
2474 }
2475 }
2476
2477 if (gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2478 {
2479 layout_type (ctx->record_type);
2480 fixup_child_record_type (ctx);
2481 }
a68ab351
JJ
2482 else
2483 {
5771c391 2484 location_t loc = gimple_location (ctx->stmt);
a68ab351
JJ
2485 tree *p, vla_fields = NULL_TREE, *q = &vla_fields;
2486 /* Move VLA fields to the end. */
2487 p = &TYPE_FIELDS (ctx->record_type);
2488 while (*p)
2489 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p))
2490 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p))))
2491 {
2492 *q = *p;
2493 *p = TREE_CHAIN (*p);
2494 TREE_CHAIN (*q) = NULL_TREE;
2495 q = &TREE_CHAIN (*q);
2496 }
2497 else
910ad8de 2498 p = &DECL_CHAIN (*p);
a68ab351
JJ
2499 *p = vla_fields;
2500 layout_type (ctx->record_type);
2501 fixup_child_record_type (ctx);
2502 if (ctx->srecord_type)
2503 layout_type (ctx->srecord_type);
5771c391
JJ
2504 tree t = fold_convert_loc (loc, long_integer_type_node,
2505 TYPE_SIZE_UNIT (ctx->record_type));
2506 gimple_omp_task_set_arg_size (ctx->stmt, t);
726a989a 2507 t = build_int_cst (long_integer_type_node,
a68ab351 2508 TYPE_ALIGN_UNIT (ctx->record_type));
5771c391 2509 gimple_omp_task_set_arg_align (ctx->stmt, t);
a68ab351
JJ
2510 }
2511}
2512
953ff289 2513
41dbbb37
TS
2514static omp_context *
2515enclosing_target_ctx (omp_context *ctx)
2516{
2517 while (ctx != NULL
2518 && gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET)
2519 ctx = ctx->outer;
2520 gcc_assert (ctx != NULL);
2521 return ctx;
2522}
2523
2524static bool
2525oacc_loop_or_target_p (gimple stmt)
2526{
2527 enum gimple_code outer_type = gimple_code (stmt);
2528 return ((outer_type == GIMPLE_OMP_TARGET
2529 && ((gimple_omp_target_kind (stmt)
2530 == GF_OMP_TARGET_KIND_OACC_PARALLEL)
2531 || (gimple_omp_target_kind (stmt)
2532 == GF_OMP_TARGET_KIND_OACC_KERNELS)))
2533 || (outer_type == GIMPLE_OMP_FOR
2534 && gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_OACC_LOOP));
2535}
2536
2537/* Scan a GIMPLE_OMP_FOR. */
953ff289
DN
2538
2539static void
538dd0b7 2540scan_omp_for (gomp_for *stmt, omp_context *outer_ctx)
953ff289 2541{
41dbbb37 2542 enum gimple_code outer_type = GIMPLE_ERROR_MARK;
50674e96 2543 omp_context *ctx;
726a989a 2544 size_t i;
41dbbb37
TS
2545 tree clauses = gimple_omp_for_clauses (stmt);
2546
2547 if (outer_ctx)
2548 outer_type = gimple_code (outer_ctx->stmt);
953ff289 2549
50674e96 2550 ctx = new_omp_context (stmt, outer_ctx);
953ff289 2551
41dbbb37
TS
2552 if (is_gimple_omp_oacc (stmt))
2553 {
2554 if (outer_ctx && outer_type == GIMPLE_OMP_FOR)
2555 ctx->gwv_this = outer_ctx->gwv_this;
2556 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2557 {
2558 int val;
2559 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_GANG)
2560 val = MASK_GANG;
2561 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_WORKER)
2562 val = MASK_WORKER;
2563 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_VECTOR)
2564 val = MASK_VECTOR;
2565 else
2566 continue;
2567 ctx->gwv_this |= val;
2568 if (!outer_ctx)
2569 {
2570 /* Skip; not nested inside a region. */
2571 continue;
2572 }
2573 if (!oacc_loop_or_target_p (outer_ctx->stmt))
2574 {
2575 /* Skip; not nested inside an OpenACC region. */
2576 continue;
2577 }
2578 if (outer_type == GIMPLE_OMP_FOR)
2579 outer_ctx->gwv_below |= val;
2580 if (OMP_CLAUSE_OPERAND (c, 0) != NULL_TREE)
2581 {
2582 omp_context *enclosing = enclosing_target_ctx (outer_ctx);
2583 if (gimple_omp_target_kind (enclosing->stmt)
2584 == GF_OMP_TARGET_KIND_OACC_PARALLEL)
2585 error_at (gimple_location (stmt),
2586 "no arguments allowed to gang, worker and vector clauses inside parallel");
2587 }
2588 }
2589 }
2590
2591 scan_sharing_clauses (clauses, ctx);
953ff289 2592
26127932 2593 scan_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
726a989a 2594 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
a68ab351 2595 {
726a989a
RB
2596 scan_omp_op (gimple_omp_for_index_ptr (stmt, i), ctx);
2597 scan_omp_op (gimple_omp_for_initial_ptr (stmt, i), ctx);
2598 scan_omp_op (gimple_omp_for_final_ptr (stmt, i), ctx);
2599 scan_omp_op (gimple_omp_for_incr_ptr (stmt, i), ctx);
a68ab351 2600 }
26127932 2601 scan_omp (gimple_omp_body_ptr (stmt), ctx);
41dbbb37
TS
2602
2603 if (is_gimple_omp_oacc (stmt))
2604 {
2605 if (ctx->gwv_this & ctx->gwv_below)
2606 error_at (gimple_location (stmt),
2607 "gang, worker and vector may occur only once in a loop nest");
2608 else if (ctx->gwv_below != 0
2609 && ctx->gwv_this > ctx->gwv_below)
2610 error_at (gimple_location (stmt),
2611 "gang, worker and vector must occur in this order in a loop nest");
2612 if (outer_ctx && outer_type == GIMPLE_OMP_FOR)
2613 outer_ctx->gwv_below |= ctx->gwv_below;
2614 }
953ff289
DN
2615}
2616
2617/* Scan an OpenMP sections directive. */
2618
2619static void
538dd0b7 2620scan_omp_sections (gomp_sections *stmt, omp_context *outer_ctx)
953ff289 2621{
953ff289
DN
2622 omp_context *ctx;
2623
2624 ctx = new_omp_context (stmt, outer_ctx);
726a989a 2625 scan_sharing_clauses (gimple_omp_sections_clauses (stmt), ctx);
26127932 2626 scan_omp (gimple_omp_body_ptr (stmt), ctx);
953ff289
DN
2627}
2628
2629/* Scan an OpenMP single directive. */
2630
2631static void
538dd0b7 2632scan_omp_single (gomp_single *stmt, omp_context *outer_ctx)
953ff289 2633{
953ff289
DN
2634 omp_context *ctx;
2635 tree name;
2636
2637 ctx = new_omp_context (stmt, outer_ctx);
2638 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2639 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2640 name = create_tmp_var_name (".omp_copy_s");
c2255bc4
AH
2641 name = build_decl (gimple_location (stmt),
2642 TYPE_DECL, name, ctx->record_type);
953ff289
DN
2643 TYPE_NAME (ctx->record_type) = name;
2644
726a989a 2645 scan_sharing_clauses (gimple_omp_single_clauses (stmt), ctx);
26127932 2646 scan_omp (gimple_omp_body_ptr (stmt), ctx);
953ff289
DN
2647
2648 if (TYPE_FIELDS (ctx->record_type) == NULL)
2649 ctx->record_type = NULL;
2650 else
2651 layout_type (ctx->record_type);
2652}
2653
41dbbb37 2654/* Scan a GIMPLE_OMP_TARGET. */
acf0174b
JJ
2655
2656static void
538dd0b7 2657scan_omp_target (gomp_target *stmt, omp_context *outer_ctx)
acf0174b
JJ
2658{
2659 omp_context *ctx;
2660 tree name;
41dbbb37
TS
2661 bool offloaded = is_gimple_omp_offloaded (stmt);
2662 tree clauses = gimple_omp_target_clauses (stmt);
acf0174b
JJ
2663
2664 ctx = new_omp_context (stmt, outer_ctx);
2665 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2666 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2667 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2668 name = create_tmp_var_name (".omp_data_t");
2669 name = build_decl (gimple_location (stmt),
2670 TYPE_DECL, name, ctx->record_type);
2671 DECL_ARTIFICIAL (name) = 1;
2672 DECL_NAMELESS (name) = 1;
2673 TYPE_NAME (ctx->record_type) = name;
41dbbb37 2674 if (offloaded)
acf0174b 2675 {
41dbbb37
TS
2676 if (is_gimple_omp_oacc (stmt))
2677 ctx->reduction_map = splay_tree_new (splay_tree_compare_pointers,
2678 0, 0);
2679
acf0174b
JJ
2680 create_omp_child_function (ctx, false);
2681 gimple_omp_target_set_child_fn (stmt, ctx->cb.dst_fn);
2682 }
2683
41dbbb37
TS
2684 if (is_gimple_omp_oacc (stmt))
2685 {
2686 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2687 {
2688 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NUM_GANGS)
2689 ctx->gwv_this |= MASK_GANG;
2690 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NUM_WORKERS)
2691 ctx->gwv_this |= MASK_WORKER;
2692 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_VECTOR_LENGTH)
2693 ctx->gwv_this |= MASK_VECTOR;
2694 }
2695 }
2696
2697 scan_sharing_clauses (clauses, ctx);
acf0174b
JJ
2698 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2699
2700 if (TYPE_FIELDS (ctx->record_type) == NULL)
2701 ctx->record_type = ctx->receiver_decl = NULL;
2702 else
2703 {
2704 TYPE_FIELDS (ctx->record_type)
2705 = nreverse (TYPE_FIELDS (ctx->record_type));
2706#ifdef ENABLE_CHECKING
2707 tree field;
2708 unsigned int align = DECL_ALIGN (TYPE_FIELDS (ctx->record_type));
2709 for (field = TYPE_FIELDS (ctx->record_type);
2710 field;
2711 field = DECL_CHAIN (field))
2712 gcc_assert (DECL_ALIGN (field) == align);
2713#endif
2714 layout_type (ctx->record_type);
41dbbb37 2715 if (offloaded)
acf0174b
JJ
2716 fixup_child_record_type (ctx);
2717 }
2718}
2719
2720/* Scan an OpenMP teams directive. */
2721
2722static void
538dd0b7 2723scan_omp_teams (gomp_teams *stmt, omp_context *outer_ctx)
acf0174b
JJ
2724{
2725 omp_context *ctx = new_omp_context (stmt, outer_ctx);
2726 scan_sharing_clauses (gimple_omp_teams_clauses (stmt), ctx);
2727 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2728}
953ff289 2729
41dbbb37 2730/* Check nesting restrictions. */
26127932
JJ
2731static bool
2732check_omp_nesting_restrictions (gimple stmt, omp_context *ctx)
a6fc8e21 2733{
41dbbb37
TS
2734 /* No nesting of non-OpenACC STMT (that is, an OpenMP one, or a GOMP builtin)
2735 inside an OpenACC CTX. */
2736 if (!(is_gimple_omp (stmt)
2737 && is_gimple_omp_oacc (stmt)))
2738 {
2739 for (omp_context *ctx_ = ctx; ctx_ != NULL; ctx_ = ctx_->outer)
2740 if (is_gimple_omp (ctx_->stmt)
2741 && is_gimple_omp_oacc (ctx_->stmt))
2742 {
2743 error_at (gimple_location (stmt),
2744 "non-OpenACC construct inside of OpenACC region");
2745 return false;
2746 }
2747 }
2748
74bf76ed
JJ
2749 if (ctx != NULL)
2750 {
2751 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
0aadce73 2752 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
74bf76ed
JJ
2753 {
2754 error_at (gimple_location (stmt),
2755 "OpenMP constructs may not be nested inside simd region");
2756 return false;
2757 }
acf0174b
JJ
2758 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
2759 {
2760 if ((gimple_code (stmt) != GIMPLE_OMP_FOR
2761 || (gimple_omp_for_kind (stmt)
2762 != GF_OMP_FOR_KIND_DISTRIBUTE))
2763 && gimple_code (stmt) != GIMPLE_OMP_PARALLEL)
2764 {
2765 error_at (gimple_location (stmt),
2766 "only distribute or parallel constructs are allowed to "
2767 "be closely nested inside teams construct");
2768 return false;
2769 }
2770 }
74bf76ed 2771 }
726a989a 2772 switch (gimple_code (stmt))
a6fc8e21 2773 {
726a989a 2774 case GIMPLE_OMP_FOR:
0aadce73 2775 if (gimple_omp_for_kind (stmt) & GF_OMP_FOR_SIMD)
74bf76ed 2776 return true;
acf0174b
JJ
2777 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
2778 {
2779 if (ctx != NULL && gimple_code (ctx->stmt) != GIMPLE_OMP_TEAMS)
2780 {
2781 error_at (gimple_location (stmt),
2782 "distribute construct must be closely nested inside "
2783 "teams construct");
2784 return false;
2785 }
2786 return true;
2787 }
2788 /* FALLTHRU */
2789 case GIMPLE_CALL:
2790 if (is_gimple_call (stmt)
2791 && (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2792 == BUILT_IN_GOMP_CANCEL
2793 || DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2794 == BUILT_IN_GOMP_CANCELLATION_POINT))
2795 {
2796 const char *bad = NULL;
2797 const char *kind = NULL;
2798 if (ctx == NULL)
2799 {
2800 error_at (gimple_location (stmt), "orphaned %qs construct",
2801 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2802 == BUILT_IN_GOMP_CANCEL
2803 ? "#pragma omp cancel"
2804 : "#pragma omp cancellation point");
2805 return false;
2806 }
9541ffee 2807 switch (tree_fits_shwi_p (gimple_call_arg (stmt, 0))
9439e9a1 2808 ? tree_to_shwi (gimple_call_arg (stmt, 0))
acf0174b
JJ
2809 : 0)
2810 {
2811 case 1:
2812 if (gimple_code (ctx->stmt) != GIMPLE_OMP_PARALLEL)
2813 bad = "#pragma omp parallel";
2814 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2815 == BUILT_IN_GOMP_CANCEL
2816 && !integer_zerop (gimple_call_arg (stmt, 1)))
2817 ctx->cancellable = true;
2818 kind = "parallel";
2819 break;
2820 case 2:
2821 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
2822 || gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR)
2823 bad = "#pragma omp for";
2824 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2825 == BUILT_IN_GOMP_CANCEL
2826 && !integer_zerop (gimple_call_arg (stmt, 1)))
2827 {
2828 ctx->cancellable = true;
2829 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2830 OMP_CLAUSE_NOWAIT))
2831 warning_at (gimple_location (stmt), 0,
2832 "%<#pragma omp cancel for%> inside "
2833 "%<nowait%> for construct");
2834 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2835 OMP_CLAUSE_ORDERED))
2836 warning_at (gimple_location (stmt), 0,
2837 "%<#pragma omp cancel for%> inside "
2838 "%<ordered%> for construct");
2839 }
2840 kind = "for";
2841 break;
2842 case 4:
2843 if (gimple_code (ctx->stmt) != GIMPLE_OMP_SECTIONS
2844 && gimple_code (ctx->stmt) != GIMPLE_OMP_SECTION)
2845 bad = "#pragma omp sections";
2846 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2847 == BUILT_IN_GOMP_CANCEL
2848 && !integer_zerop (gimple_call_arg (stmt, 1)))
2849 {
2850 if (gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS)
2851 {
2852 ctx->cancellable = true;
2853 if (find_omp_clause (gimple_omp_sections_clauses
2854 (ctx->stmt),
2855 OMP_CLAUSE_NOWAIT))
2856 warning_at (gimple_location (stmt), 0,
2857 "%<#pragma omp cancel sections%> inside "
2858 "%<nowait%> sections construct");
2859 }
2860 else
2861 {
2862 gcc_assert (ctx->outer
2863 && gimple_code (ctx->outer->stmt)
2864 == GIMPLE_OMP_SECTIONS);
2865 ctx->outer->cancellable = true;
2866 if (find_omp_clause (gimple_omp_sections_clauses
2867 (ctx->outer->stmt),
2868 OMP_CLAUSE_NOWAIT))
2869 warning_at (gimple_location (stmt), 0,
2870 "%<#pragma omp cancel sections%> inside "
2871 "%<nowait%> sections construct");
2872 }
2873 }
2874 kind = "sections";
2875 break;
2876 case 8:
2877 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TASK)
2878 bad = "#pragma omp task";
2879 else
2880 ctx->cancellable = true;
2881 kind = "taskgroup";
2882 break;
2883 default:
2884 error_at (gimple_location (stmt), "invalid arguments");
2885 return false;
2886 }
2887 if (bad)
2888 {
2889 error_at (gimple_location (stmt),
2890 "%<%s %s%> construct not closely nested inside of %qs",
2891 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2892 == BUILT_IN_GOMP_CANCEL
2893 ? "#pragma omp cancel"
2894 : "#pragma omp cancellation point", kind, bad);
2895 return false;
2896 }
2897 }
74bf76ed 2898 /* FALLTHRU */
726a989a
RB
2899 case GIMPLE_OMP_SECTIONS:
2900 case GIMPLE_OMP_SINGLE:
a6fc8e21 2901 for (; ctx != NULL; ctx = ctx->outer)
726a989a 2902 switch (gimple_code (ctx->stmt))
a6fc8e21 2903 {
726a989a
RB
2904 case GIMPLE_OMP_FOR:
2905 case GIMPLE_OMP_SECTIONS:
2906 case GIMPLE_OMP_SINGLE:
2907 case GIMPLE_OMP_ORDERED:
2908 case GIMPLE_OMP_MASTER:
2909 case GIMPLE_OMP_TASK:
acf0174b 2910 case GIMPLE_OMP_CRITICAL:
726a989a 2911 if (is_gimple_call (stmt))
a68ab351 2912 {
acf0174b
JJ
2913 if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2914 != BUILT_IN_GOMP_BARRIER)
2915 return true;
26127932
JJ
2916 error_at (gimple_location (stmt),
2917 "barrier region may not be closely nested inside "
2918 "of work-sharing, critical, ordered, master or "
2919 "explicit task region");
2920 return false;
a68ab351 2921 }
26127932
JJ
2922 error_at (gimple_location (stmt),
2923 "work-sharing region may not be closely nested inside "
2924 "of work-sharing, critical, ordered, master or explicit "
2925 "task region");
2926 return false;
726a989a 2927 case GIMPLE_OMP_PARALLEL:
26127932 2928 return true;
a6fc8e21
JJ
2929 default:
2930 break;
2931 }
2932 break;
726a989a 2933 case GIMPLE_OMP_MASTER:
a6fc8e21 2934 for (; ctx != NULL; ctx = ctx->outer)
726a989a 2935 switch (gimple_code (ctx->stmt))
a6fc8e21 2936 {
726a989a
RB
2937 case GIMPLE_OMP_FOR:
2938 case GIMPLE_OMP_SECTIONS:
2939 case GIMPLE_OMP_SINGLE:
2940 case GIMPLE_OMP_TASK:
26127932
JJ
2941 error_at (gimple_location (stmt),
2942 "master region may not be closely nested inside "
2943 "of work-sharing or explicit task region");
2944 return false;
726a989a 2945 case GIMPLE_OMP_PARALLEL:
26127932 2946 return true;
a6fc8e21
JJ
2947 default:
2948 break;
2949 }
2950 break;
726a989a 2951 case GIMPLE_OMP_ORDERED:
a6fc8e21 2952 for (; ctx != NULL; ctx = ctx->outer)
726a989a 2953 switch (gimple_code (ctx->stmt))
a6fc8e21 2954 {
726a989a
RB
2955 case GIMPLE_OMP_CRITICAL:
2956 case GIMPLE_OMP_TASK:
26127932
JJ
2957 error_at (gimple_location (stmt),
2958 "ordered region may not be closely nested inside "
2959 "of critical or explicit task region");
2960 return false;
726a989a
RB
2961 case GIMPLE_OMP_FOR:
2962 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
a6fc8e21 2963 OMP_CLAUSE_ORDERED) == NULL)
26127932
JJ
2964 {
2965 error_at (gimple_location (stmt),
2966 "ordered region must be closely nested inside "
a6fc8e21 2967 "a loop region with an ordered clause");
26127932
JJ
2968 return false;
2969 }
2970 return true;
726a989a 2971 case GIMPLE_OMP_PARALLEL:
acf0174b
JJ
2972 error_at (gimple_location (stmt),
2973 "ordered region must be closely nested inside "
2974 "a loop region with an ordered clause");
2975 return false;
a6fc8e21
JJ
2976 default:
2977 break;
2978 }
2979 break;
726a989a 2980 case GIMPLE_OMP_CRITICAL:
538dd0b7
DM
2981 {
2982 tree this_stmt_name
2983 = gimple_omp_critical_name (as_a <gomp_critical *> (stmt));
2984 for (; ctx != NULL; ctx = ctx->outer)
2985 if (gomp_critical *other_crit
2986 = dyn_cast <gomp_critical *> (ctx->stmt))
2987 if (this_stmt_name == gimple_omp_critical_name (other_crit))
2988 {
2989 error_at (gimple_location (stmt),
2990 "critical region may not be nested inside a critical "
2991 "region with the same name");
2992 return false;
2993 }
2994 }
a6fc8e21 2995 break;
acf0174b
JJ
2996 case GIMPLE_OMP_TEAMS:
2997 if (ctx == NULL
2998 || gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET
2999 || gimple_omp_target_kind (ctx->stmt) != GF_OMP_TARGET_KIND_REGION)
3000 {
3001 error_at (gimple_location (stmt),
3002 "teams construct not closely nested inside of target "
3003 "region");
3004 return false;
3005 }
3006 break;
f014c653
JJ
3007 case GIMPLE_OMP_TARGET:
3008 for (; ctx != NULL; ctx = ctx->outer)
41dbbb37
TS
3009 {
3010 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET)
3011 {
3012 if (is_gimple_omp (stmt)
3013 && is_gimple_omp_oacc (stmt)
3014 && is_gimple_omp (ctx->stmt))
3015 {
3016 error_at (gimple_location (stmt),
3017 "OpenACC construct inside of non-OpenACC region");
3018 return false;
3019 }
3020 continue;
3021 }
3022
3023 const char *stmt_name, *ctx_stmt_name;
3024 switch (gimple_omp_target_kind (stmt))
3025 {
3026 case GF_OMP_TARGET_KIND_REGION: stmt_name = "target"; break;
3027 case GF_OMP_TARGET_KIND_DATA: stmt_name = "target data"; break;
3028 case GF_OMP_TARGET_KIND_UPDATE: stmt_name = "target update"; break;
3029 case GF_OMP_TARGET_KIND_OACC_PARALLEL: stmt_name = "parallel"; break;
3030 case GF_OMP_TARGET_KIND_OACC_KERNELS: stmt_name = "kernels"; break;
3031 case GF_OMP_TARGET_KIND_OACC_DATA: stmt_name = "data"; break;
3032 case GF_OMP_TARGET_KIND_OACC_UPDATE: stmt_name = "update"; break;
3033 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA: stmt_name = "enter/exit data"; break;
3034 default: gcc_unreachable ();
3035 }
3036 switch (gimple_omp_target_kind (ctx->stmt))
3037 {
3038 case GF_OMP_TARGET_KIND_REGION: ctx_stmt_name = "target"; break;
3039 case GF_OMP_TARGET_KIND_DATA: ctx_stmt_name = "target data"; break;
3040 case GF_OMP_TARGET_KIND_OACC_PARALLEL: ctx_stmt_name = "parallel"; break;
3041 case GF_OMP_TARGET_KIND_OACC_KERNELS: ctx_stmt_name = "kernels"; break;
3042 case GF_OMP_TARGET_KIND_OACC_DATA: ctx_stmt_name = "data"; break;
3043 default: gcc_unreachable ();
3044 }
3045
3046 /* OpenACC/OpenMP mismatch? */
3047 if (is_gimple_omp_oacc (stmt)
3048 != is_gimple_omp_oacc (ctx->stmt))
3049 {
3050 error_at (gimple_location (stmt),
3051 "%s %s construct inside of %s %s region",
3052 (is_gimple_omp_oacc (stmt)
3053 ? "OpenACC" : "OpenMP"), stmt_name,
3054 (is_gimple_omp_oacc (ctx->stmt)
3055 ? "OpenACC" : "OpenMP"), ctx_stmt_name);
3056 return false;
3057 }
3058 if (is_gimple_omp_offloaded (ctx->stmt))
3059 {
3060 /* No GIMPLE_OMP_TARGET inside offloaded OpenACC CTX. */
3061 if (is_gimple_omp_oacc (ctx->stmt))
3062 {
3063 error_at (gimple_location (stmt),
3064 "%s construct inside of %s region",
3065 stmt_name, ctx_stmt_name);
3066 return false;
3067 }
3068 else
3069 {
3070 gcc_checking_assert (!is_gimple_omp_oacc (stmt));
3071 warning_at (gimple_location (stmt), 0,
3072 "%s construct inside of %s region",
3073 stmt_name, ctx_stmt_name);
3074 }
3075 }
3076 }
f014c653 3077 break;
a6fc8e21
JJ
3078 default:
3079 break;
3080 }
26127932 3081 return true;
a6fc8e21
JJ
3082}
3083
3084
726a989a
RB
3085/* Helper function scan_omp.
3086
3087 Callback for walk_tree or operators in walk_gimple_stmt used to
41dbbb37 3088 scan for OMP directives in TP. */
953ff289
DN
3089
3090static tree
726a989a 3091scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
953ff289 3092{
d3bfe4de
KG
3093 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
3094 omp_context *ctx = (omp_context *) wi->info;
953ff289
DN
3095 tree t = *tp;
3096
726a989a
RB
3097 switch (TREE_CODE (t))
3098 {
3099 case VAR_DECL:
3100 case PARM_DECL:
3101 case LABEL_DECL:
3102 case RESULT_DECL:
3103 if (ctx)
3104 *tp = remap_decl (t, &ctx->cb);
3105 break;
3106
3107 default:
3108 if (ctx && TYPE_P (t))
3109 *tp = remap_type (t, &ctx->cb);
3110 else if (!DECL_P (t))
a900ae6b
JJ
3111 {
3112 *walk_subtrees = 1;
3113 if (ctx)
70f34814
RG
3114 {
3115 tree tem = remap_type (TREE_TYPE (t), &ctx->cb);
3116 if (tem != TREE_TYPE (t))
3117 {
3118 if (TREE_CODE (t) == INTEGER_CST)
807e902e 3119 *tp = wide_int_to_tree (tem, t);
70f34814
RG
3120 else
3121 TREE_TYPE (t) = tem;
3122 }
3123 }
a900ae6b 3124 }
726a989a
RB
3125 break;
3126 }
3127
3128 return NULL_TREE;
3129}
3130
c02065fc
AH
3131/* Return true if FNDECL is a setjmp or a longjmp. */
3132
3133static bool
3134setjmp_or_longjmp_p (const_tree fndecl)
3135{
3136 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
3137 && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_SETJMP
3138 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LONGJMP))
3139 return true;
3140
3141 tree declname = DECL_NAME (fndecl);
3142 if (!declname)
3143 return false;
3144 const char *name = IDENTIFIER_POINTER (declname);
3145 return !strcmp (name, "setjmp") || !strcmp (name, "longjmp");
3146}
3147
726a989a
RB
3148
3149/* Helper function for scan_omp.
3150
41dbbb37 3151 Callback for walk_gimple_stmt used to scan for OMP directives in
726a989a
RB
3152 the current statement in GSI. */
3153
3154static tree
3155scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
3156 struct walk_stmt_info *wi)
3157{
3158 gimple stmt = gsi_stmt (*gsi);
3159 omp_context *ctx = (omp_context *) wi->info;
3160
3161 if (gimple_has_location (stmt))
3162 input_location = gimple_location (stmt);
953ff289 3163
41dbbb37 3164 /* Check the nesting restrictions. */
acf0174b
JJ
3165 bool remove = false;
3166 if (is_gimple_omp (stmt))
3167 remove = !check_omp_nesting_restrictions (stmt, ctx);
3168 else if (is_gimple_call (stmt))
3169 {
3170 tree fndecl = gimple_call_fndecl (stmt);
c02065fc
AH
3171 if (fndecl)
3172 {
3173 if (setjmp_or_longjmp_p (fndecl)
3174 && ctx
3175 && gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
0aadce73 3176 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
c02065fc
AH
3177 {
3178 remove = true;
3179 error_at (gimple_location (stmt),
3180 "setjmp/longjmp inside simd construct");
3181 }
3182 else if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
3183 switch (DECL_FUNCTION_CODE (fndecl))
3184 {
3185 case BUILT_IN_GOMP_BARRIER:
3186 case BUILT_IN_GOMP_CANCEL:
3187 case BUILT_IN_GOMP_CANCELLATION_POINT:
3188 case BUILT_IN_GOMP_TASKYIELD:
3189 case BUILT_IN_GOMP_TASKWAIT:
3190 case BUILT_IN_GOMP_TASKGROUP_START:
3191 case BUILT_IN_GOMP_TASKGROUP_END:
3192 remove = !check_omp_nesting_restrictions (stmt, ctx);
3193 break;
3194 default:
3195 break;
3196 }
3197 }
acf0174b
JJ
3198 }
3199 if (remove)
3200 {
3201 stmt = gimple_build_nop ();
3202 gsi_replace (gsi, stmt, false);
a68ab351 3203 }
a6fc8e21 3204
726a989a
RB
3205 *handled_ops_p = true;
3206
3207 switch (gimple_code (stmt))
953ff289 3208 {
726a989a 3209 case GIMPLE_OMP_PARALLEL:
a68ab351 3210 taskreg_nesting_level++;
726a989a 3211 scan_omp_parallel (gsi, ctx);
a68ab351
JJ
3212 taskreg_nesting_level--;
3213 break;
3214
726a989a 3215 case GIMPLE_OMP_TASK:
a68ab351 3216 taskreg_nesting_level++;
726a989a 3217 scan_omp_task (gsi, ctx);
a68ab351 3218 taskreg_nesting_level--;
953ff289
DN
3219 break;
3220
726a989a 3221 case GIMPLE_OMP_FOR:
538dd0b7 3222 scan_omp_for (as_a <gomp_for *> (stmt), ctx);
953ff289
DN
3223 break;
3224
726a989a 3225 case GIMPLE_OMP_SECTIONS:
538dd0b7 3226 scan_omp_sections (as_a <gomp_sections *> (stmt), ctx);
953ff289
DN
3227 break;
3228
726a989a 3229 case GIMPLE_OMP_SINGLE:
538dd0b7 3230 scan_omp_single (as_a <gomp_single *> (stmt), ctx);
953ff289
DN
3231 break;
3232
726a989a
RB
3233 case GIMPLE_OMP_SECTION:
3234 case GIMPLE_OMP_MASTER:
acf0174b 3235 case GIMPLE_OMP_TASKGROUP:
726a989a
RB
3236 case GIMPLE_OMP_ORDERED:
3237 case GIMPLE_OMP_CRITICAL:
3238 ctx = new_omp_context (stmt, ctx);
26127932 3239 scan_omp (gimple_omp_body_ptr (stmt), ctx);
953ff289
DN
3240 break;
3241
acf0174b 3242 case GIMPLE_OMP_TARGET:
538dd0b7 3243 scan_omp_target (as_a <gomp_target *> (stmt), ctx);
acf0174b
JJ
3244 break;
3245
3246 case GIMPLE_OMP_TEAMS:
538dd0b7 3247 scan_omp_teams (as_a <gomp_teams *> (stmt), ctx);
acf0174b
JJ
3248 break;
3249
726a989a 3250 case GIMPLE_BIND:
953ff289
DN
3251 {
3252 tree var;
953ff289 3253
726a989a
RB
3254 *handled_ops_p = false;
3255 if (ctx)
538dd0b7
DM
3256 for (var = gimple_bind_vars (as_a <gbind *> (stmt));
3257 var ;
3258 var = DECL_CHAIN (var))
726a989a 3259 insert_decl_map (&ctx->cb, var, var);
953ff289
DN
3260 }
3261 break;
953ff289 3262 default:
726a989a 3263 *handled_ops_p = false;
953ff289
DN
3264 break;
3265 }
3266
3267 return NULL_TREE;
3268}
3269
3270
726a989a 3271/* Scan all the statements starting at the current statement. CTX
41dbbb37 3272 contains context information about the OMP directives and
726a989a 3273 clauses found during the scan. */
953ff289
DN
3274
3275static void
26127932 3276scan_omp (gimple_seq *body_p, omp_context *ctx)
953ff289
DN
3277{
3278 location_t saved_location;
3279 struct walk_stmt_info wi;
3280
3281 memset (&wi, 0, sizeof (wi));
953ff289 3282 wi.info = ctx;
953ff289
DN
3283 wi.want_locations = true;
3284
3285 saved_location = input_location;
26127932 3286 walk_gimple_seq_mod (body_p, scan_omp_1_stmt, scan_omp_1_op, &wi);
953ff289
DN
3287 input_location = saved_location;
3288}
3289\f
3290/* Re-gimplification and code generation routines. */
3291
3292/* Build a call to GOMP_barrier. */
3293
acf0174b
JJ
3294static gimple
3295build_omp_barrier (tree lhs)
3296{
3297 tree fndecl = builtin_decl_explicit (lhs ? BUILT_IN_GOMP_BARRIER_CANCEL
3298 : BUILT_IN_GOMP_BARRIER);
538dd0b7 3299 gcall *g = gimple_build_call (fndecl, 0);
acf0174b
JJ
3300 if (lhs)
3301 gimple_call_set_lhs (g, lhs);
3302 return g;
953ff289
DN
3303}
3304
3305/* If a context was created for STMT when it was scanned, return it. */
3306
3307static omp_context *
726a989a 3308maybe_lookup_ctx (gimple stmt)
953ff289
DN
3309{
3310 splay_tree_node n;
3311 n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
3312 return n ? (omp_context *) n->value : NULL;
3313}
3314
50674e96
DN
3315
3316/* Find the mapping for DECL in CTX or the immediately enclosing
3317 context that has a mapping for DECL.
3318
3319 If CTX is a nested parallel directive, we may have to use the decl
3320 mappings created in CTX's parent context. Suppose that we have the
3321 following parallel nesting (variable UIDs showed for clarity):
3322
3323 iD.1562 = 0;
3324 #omp parallel shared(iD.1562) -> outer parallel
3325 iD.1562 = iD.1562 + 1;
3326
3327 #omp parallel shared (iD.1562) -> inner parallel
3328 iD.1562 = iD.1562 - 1;
3329
3330 Each parallel structure will create a distinct .omp_data_s structure
3331 for copying iD.1562 in/out of the directive:
3332
3333 outer parallel .omp_data_s.1.i -> iD.1562
3334 inner parallel .omp_data_s.2.i -> iD.1562
3335
3336 A shared variable mapping will produce a copy-out operation before
3337 the parallel directive and a copy-in operation after it. So, in
3338 this case we would have:
3339
3340 iD.1562 = 0;
3341 .omp_data_o.1.i = iD.1562;
3342 #omp parallel shared(iD.1562) -> outer parallel
3343 .omp_data_i.1 = &.omp_data_o.1
3344 .omp_data_i.1->i = .omp_data_i.1->i + 1;
3345
3346 .omp_data_o.2.i = iD.1562; -> **
3347 #omp parallel shared(iD.1562) -> inner parallel
3348 .omp_data_i.2 = &.omp_data_o.2
3349 .omp_data_i.2->i = .omp_data_i.2->i - 1;
3350
3351
3352 ** This is a problem. The symbol iD.1562 cannot be referenced
3353 inside the body of the outer parallel region. But since we are
3354 emitting this copy operation while expanding the inner parallel
3355 directive, we need to access the CTX structure of the outer
3356 parallel directive to get the correct mapping:
3357
3358 .omp_data_o.2.i = .omp_data_i.1->i
3359
3360 Since there may be other workshare or parallel directives enclosing
3361 the parallel directive, it may be necessary to walk up the context
3362 parent chain. This is not a problem in general because nested
3363 parallelism happens only rarely. */
3364
3365static tree
3366lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
3367{
3368 tree t;
3369 omp_context *up;
3370
50674e96
DN
3371 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
3372 t = maybe_lookup_decl (decl, up);
3373
d2dda7fe 3374 gcc_assert (!ctx->is_nested || t || is_global_var (decl));
50674e96 3375
64964499 3376 return t ? t : decl;
50674e96
DN
3377}
3378
3379
8ca5b2a2
JJ
3380/* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
3381 in outer contexts. */
3382
3383static tree
3384maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
3385{
3386 tree t = NULL;
3387 omp_context *up;
3388
d2dda7fe
JJ
3389 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
3390 t = maybe_lookup_decl (decl, up);
8ca5b2a2
JJ
3391
3392 return t ? t : decl;
3393}
3394
3395
953ff289
DN
3396/* Construct the initialization value for reduction CLAUSE. */
3397
3398tree
3399omp_reduction_init (tree clause, tree type)
3400{
db3927fb 3401 location_t loc = OMP_CLAUSE_LOCATION (clause);
953ff289
DN
3402 switch (OMP_CLAUSE_REDUCTION_CODE (clause))
3403 {
3404 case PLUS_EXPR:
3405 case MINUS_EXPR:
3406 case BIT_IOR_EXPR:
3407 case BIT_XOR_EXPR:
3408 case TRUTH_OR_EXPR:
3409 case TRUTH_ORIF_EXPR:
3410 case TRUTH_XOR_EXPR:
3411 case NE_EXPR:
e8160c9a 3412 return build_zero_cst (type);
953ff289
DN
3413
3414 case MULT_EXPR:
3415 case TRUTH_AND_EXPR:
3416 case TRUTH_ANDIF_EXPR:
3417 case EQ_EXPR:
db3927fb 3418 return fold_convert_loc (loc, type, integer_one_node);
953ff289
DN
3419
3420 case BIT_AND_EXPR:
db3927fb 3421 return fold_convert_loc (loc, type, integer_minus_one_node);
953ff289
DN
3422
3423 case MAX_EXPR:
3424 if (SCALAR_FLOAT_TYPE_P (type))
3425 {
3426 REAL_VALUE_TYPE max, min;
3d3dbadd 3427 if (HONOR_INFINITIES (type))
953ff289
DN
3428 {
3429 real_inf (&max);
3430 real_arithmetic (&min, NEGATE_EXPR, &max, NULL);
3431 }
3432 else
3433 real_maxval (&min, 1, TYPE_MODE (type));
3434 return build_real (type, min);
3435 }
3436 else
3437 {
3438 gcc_assert (INTEGRAL_TYPE_P (type));
3439 return TYPE_MIN_VALUE (type);
3440 }
3441
3442 case MIN_EXPR:
3443 if (SCALAR_FLOAT_TYPE_P (type))
3444 {
3445 REAL_VALUE_TYPE max;
3d3dbadd 3446 if (HONOR_INFINITIES (type))
953ff289
DN
3447 real_inf (&max);
3448 else
3449 real_maxval (&max, 0, TYPE_MODE (type));
3450 return build_real (type, max);
3451 }
3452 else
3453 {
3454 gcc_assert (INTEGRAL_TYPE_P (type));
3455 return TYPE_MAX_VALUE (type);
3456 }
3457
3458 default:
3459 gcc_unreachable ();
3460 }
3461}
3462
acf0174b
JJ
3463/* Return alignment to be assumed for var in CLAUSE, which should be
3464 OMP_CLAUSE_ALIGNED. */
3465
3466static tree
3467omp_clause_aligned_alignment (tree clause)
3468{
3469 if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause))
3470 return OMP_CLAUSE_ALIGNED_ALIGNMENT (clause);
3471
3472 /* Otherwise return implementation defined alignment. */
3473 unsigned int al = 1;
ef4bddc2 3474 machine_mode mode, vmode;
acf0174b
JJ
3475 int vs = targetm.vectorize.autovectorize_vector_sizes ();
3476 if (vs)
3477 vs = 1 << floor_log2 (vs);
3478 static enum mode_class classes[]
3479 = { MODE_INT, MODE_VECTOR_INT, MODE_FLOAT, MODE_VECTOR_FLOAT };
3480 for (int i = 0; i < 4; i += 2)
3481 for (mode = GET_CLASS_NARROWEST_MODE (classes[i]);
3482 mode != VOIDmode;
3483 mode = GET_MODE_WIDER_MODE (mode))
3484 {
3485 vmode = targetm.vectorize.preferred_simd_mode (mode);
3486 if (GET_MODE_CLASS (vmode) != classes[i + 1])
3487 continue;
3488 while (vs
3489 && GET_MODE_SIZE (vmode) < vs
3490 && GET_MODE_2XWIDER_MODE (vmode) != VOIDmode)
3491 vmode = GET_MODE_2XWIDER_MODE (vmode);
3492
3493 tree type = lang_hooks.types.type_for_mode (mode, 1);
3494 if (type == NULL_TREE || TYPE_MODE (type) != mode)
3495 continue;
3496 type = build_vector_type (type, GET_MODE_SIZE (vmode)
3497 / GET_MODE_SIZE (mode));
3498 if (TYPE_MODE (type) != vmode)
3499 continue;
3500 if (TYPE_ALIGN_UNIT (type) > al)
3501 al = TYPE_ALIGN_UNIT (type);
3502 }
3503 return build_int_cst (integer_type_node, al);
3504}
3505
74bf76ed
JJ
3506/* Return maximum possible vectorization factor for the target. */
3507
3508static int
3509omp_max_vf (void)
3510{
3511 if (!optimize
3512 || optimize_debug
ab2ffbeb 3513 || !flag_tree_loop_optimize
ea0f3e87
XDL
3514 || (!flag_tree_loop_vectorize
3515 && (global_options_set.x_flag_tree_loop_vectorize
3516 || global_options_set.x_flag_tree_vectorize)))
74bf76ed
JJ
3517 return 1;
3518
3519 int vs = targetm.vectorize.autovectorize_vector_sizes ();
3520 if (vs)
3521 {
3522 vs = 1 << floor_log2 (vs);
3523 return vs;
3524 }
ef4bddc2 3525 machine_mode vqimode = targetm.vectorize.preferred_simd_mode (QImode);
74bf76ed
JJ
3526 if (GET_MODE_CLASS (vqimode) == MODE_VECTOR_INT)
3527 return GET_MODE_NUNITS (vqimode);
3528 return 1;
3529}
3530
3531/* Helper function of lower_rec_input_clauses, used for #pragma omp simd
3532 privatization. */
3533
3534static bool
3535lower_rec_simd_input_clauses (tree new_var, omp_context *ctx, int &max_vf,
3536 tree &idx, tree &lane, tree &ivar, tree &lvar)
3537{
3538 if (max_vf == 0)
3539 {
3540 max_vf = omp_max_vf ();
3541 if (max_vf > 1)
3542 {
3543 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3544 OMP_CLAUSE_SAFELEN);
b46ebd6c
JJ
3545 if (c && TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) != INTEGER_CST)
3546 max_vf = 1;
3547 else if (c && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
3548 max_vf) == -1)
9439e9a1 3549 max_vf = tree_to_shwi (OMP_CLAUSE_SAFELEN_EXPR (c));
74bf76ed
JJ
3550 }
3551 if (max_vf > 1)
3552 {
b731b390
JJ
3553 idx = create_tmp_var (unsigned_type_node);
3554 lane = create_tmp_var (unsigned_type_node);
74bf76ed
JJ
3555 }
3556 }
3557 if (max_vf == 1)
3558 return false;
3559
3560 tree atype = build_array_type_nelts (TREE_TYPE (new_var), max_vf);
b731b390 3561 tree avar = create_tmp_var_raw (atype);
74bf76ed
JJ
3562 if (TREE_ADDRESSABLE (new_var))
3563 TREE_ADDRESSABLE (avar) = 1;
3564 DECL_ATTRIBUTES (avar)
3565 = tree_cons (get_identifier ("omp simd array"), NULL,
3566 DECL_ATTRIBUTES (avar));
3567 gimple_add_tmp_var (avar);
3568 ivar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, idx,
3569 NULL_TREE, NULL_TREE);
3570 lvar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, lane,
3571 NULL_TREE, NULL_TREE);
acf0174b
JJ
3572 if (DECL_P (new_var))
3573 {
3574 SET_DECL_VALUE_EXPR (new_var, lvar);
3575 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3576 }
74bf76ed
JJ
3577 return true;
3578}
3579
decaaec8
JJ
3580/* Helper function of lower_rec_input_clauses. For a reference
3581 in simd reduction, add an underlying variable it will reference. */
3582
3583static void
3584handle_simd_reference (location_t loc, tree new_vard, gimple_seq *ilist)
3585{
3586 tree z = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard)));
3587 if (TREE_CONSTANT (z))
3588 {
3589 const char *name = NULL;
3590 if (DECL_NAME (new_vard))
3591 name = IDENTIFIER_POINTER (DECL_NAME (new_vard));
3592
3593 z = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_vard)), name);
3594 gimple_add_tmp_var (z);
3595 TREE_ADDRESSABLE (z) = 1;
3596 z = build_fold_addr_expr_loc (loc, z);
3597 gimplify_assign (new_vard, z, ilist);
3598 }
3599}
3600
953ff289
DN
3601/* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
3602 from the receiver (aka child) side and initializers for REFERENCE_TYPE
3603 private variables. Initialization statements go in ILIST, while calls
3604 to destructors go in DLIST. */
3605
3606static void
726a989a 3607lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
acf0174b 3608 omp_context *ctx, struct omp_for_data *fd)
953ff289 3609{
5039610b 3610 tree c, dtor, copyin_seq, x, ptr;
953ff289 3611 bool copyin_by_ref = false;
8ca5b2a2 3612 bool lastprivate_firstprivate = false;
acf0174b 3613 bool reduction_omp_orig_ref = false;
953ff289 3614 int pass;
74bf76ed 3615 bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
0aadce73 3616 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD);
74bf76ed
JJ
3617 int max_vf = 0;
3618 tree lane = NULL_TREE, idx = NULL_TREE;
3619 tree ivar = NULL_TREE, lvar = NULL_TREE;
3620 gimple_seq llist[2] = { NULL, NULL };
953ff289 3621
953ff289
DN
3622 copyin_seq = NULL;
3623
74bf76ed
JJ
3624 /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
3625 with data sharing clauses referencing variable sized vars. That
3626 is unnecessarily hard to support and very unlikely to result in
3627 vectorized code anyway. */
3628 if (is_simd)
3629 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3630 switch (OMP_CLAUSE_CODE (c))
3631 {
da6f124d
JJ
3632 case OMP_CLAUSE_LINEAR:
3633 if (OMP_CLAUSE_LINEAR_ARRAY (c))
3634 max_vf = 1;
3635 /* FALLTHRU */
74bf76ed 3636 case OMP_CLAUSE_REDUCTION:
74bf76ed
JJ
3637 case OMP_CLAUSE_PRIVATE:
3638 case OMP_CLAUSE_FIRSTPRIVATE:
3639 case OMP_CLAUSE_LASTPRIVATE:
74bf76ed
JJ
3640 if (is_variable_sized (OMP_CLAUSE_DECL (c)))
3641 max_vf = 1;
3642 break;
3643 default:
3644 continue;
3645 }
3646
953ff289
DN
3647 /* Do all the fixed sized types in the first pass, and the variable sized
3648 types in the second pass. This makes sure that the scalar arguments to
b8698a0f 3649 the variable sized types are processed before we use them in the
953ff289
DN
3650 variable sized operations. */
3651 for (pass = 0; pass < 2; ++pass)
3652 {
3653 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3654 {
aaf46ef9 3655 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
953ff289
DN
3656 tree var, new_var;
3657 bool by_ref;
db3927fb 3658 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
953ff289
DN
3659
3660 switch (c_kind)
3661 {
3662 case OMP_CLAUSE_PRIVATE:
3663 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
3664 continue;
3665 break;
3666 case OMP_CLAUSE_SHARED:
acf0174b
JJ
3667 /* Ignore shared directives in teams construct. */
3668 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3669 continue;
8ca5b2a2
JJ
3670 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
3671 {
3672 gcc_assert (is_global_var (OMP_CLAUSE_DECL (c)));
3673 continue;
3674 }
953ff289 3675 case OMP_CLAUSE_FIRSTPRIVATE:
953ff289 3676 case OMP_CLAUSE_COPYIN:
acf0174b
JJ
3677 case OMP_CLAUSE_LINEAR:
3678 break;
953ff289 3679 case OMP_CLAUSE_REDUCTION:
acf0174b
JJ
3680 if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
3681 reduction_omp_orig_ref = true;
953ff289 3682 break;
acf0174b
JJ
3683 case OMP_CLAUSE__LOOPTEMP_:
3684 /* Handle _looptemp_ clauses only on parallel. */
3685 if (fd)
3686 continue;
74bf76ed 3687 break;
077b0dfb 3688 case OMP_CLAUSE_LASTPRIVATE:
8ca5b2a2
JJ
3689 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3690 {
3691 lastprivate_firstprivate = true;
3692 if (pass != 0)
3693 continue;
3694 }
92d28cbb
JJ
3695 /* Even without corresponding firstprivate, if
3696 decl is Fortran allocatable, it needs outer var
3697 reference. */
3698 else if (pass == 0
3699 && lang_hooks.decls.omp_private_outer_ref
3700 (OMP_CLAUSE_DECL (c)))
3701 lastprivate_firstprivate = true;
077b0dfb 3702 break;
acf0174b
JJ
3703 case OMP_CLAUSE_ALIGNED:
3704 if (pass == 0)
3705 continue;
3706 var = OMP_CLAUSE_DECL (c);
3707 if (TREE_CODE (TREE_TYPE (var)) == POINTER_TYPE
3708 && !is_global_var (var))
3709 {
3710 new_var = maybe_lookup_decl (var, ctx);
3711 if (new_var == NULL_TREE)
3712 new_var = maybe_lookup_decl_in_outer_ctx (var, ctx);
3713 x = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3714 x = build_call_expr_loc (clause_loc, x, 2, new_var,
3715 omp_clause_aligned_alignment (c));
3716 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3717 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
3718 gimplify_and_add (x, ilist);
3719 }
3720 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
3721 && is_global_var (var))
3722 {
3723 tree ptype = build_pointer_type (TREE_TYPE (var)), t, t2;
3724 new_var = lookup_decl (var, ctx);
3725 t = maybe_lookup_decl_in_outer_ctx (var, ctx);
3726 t = build_fold_addr_expr_loc (clause_loc, t);
3727 t2 = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3728 t = build_call_expr_loc (clause_loc, t2, 2, t,
3729 omp_clause_aligned_alignment (c));
3730 t = fold_convert_loc (clause_loc, ptype, t);
b731b390 3731 x = create_tmp_var (ptype);
acf0174b
JJ
3732 t = build2 (MODIFY_EXPR, ptype, x, t);
3733 gimplify_and_add (t, ilist);
3734 t = build_simple_mem_ref_loc (clause_loc, x);
3735 SET_DECL_VALUE_EXPR (new_var, t);
3736 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3737 }
3738 continue;
953ff289
DN
3739 default:
3740 continue;
3741 }
3742
3743 new_var = var = OMP_CLAUSE_DECL (c);
3744 if (c_kind != OMP_CLAUSE_COPYIN)
3745 new_var = lookup_decl (var, ctx);
3746
3747 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
3748 {
3749 if (pass != 0)
3750 continue;
3751 }
953ff289
DN
3752 else if (is_variable_sized (var))
3753 {
50674e96
DN
3754 /* For variable sized types, we need to allocate the
3755 actual storage here. Call alloca and store the
3756 result in the pointer decl that we created elsewhere. */
953ff289
DN
3757 if (pass == 0)
3758 continue;
3759
a68ab351
JJ
3760 if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
3761 {
538dd0b7 3762 gcall *stmt;
e79983f4 3763 tree tmp, atmp;
726a989a 3764
a68ab351
JJ
3765 ptr = DECL_VALUE_EXPR (new_var);
3766 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
3767 ptr = TREE_OPERAND (ptr, 0);
3768 gcc_assert (DECL_P (ptr));
3769 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
726a989a
RB
3770
3771 /* void *tmp = __builtin_alloca */
e79983f4
MM
3772 atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3773 stmt = gimple_build_call (atmp, 1, x);
b731b390 3774 tmp = create_tmp_var_raw (ptr_type_node);
726a989a
RB
3775 gimple_add_tmp_var (tmp);
3776 gimple_call_set_lhs (stmt, tmp);
3777
3778 gimple_seq_add_stmt (ilist, stmt);
3779
db3927fb 3780 x = fold_convert_loc (clause_loc, TREE_TYPE (ptr), tmp);
726a989a 3781 gimplify_assign (ptr, x, ilist);
a68ab351 3782 }
953ff289 3783 }
953ff289
DN
3784 else if (is_reference (var))
3785 {
50674e96
DN
3786 /* For references that are being privatized for Fortran,
3787 allocate new backing storage for the new pointer
3788 variable. This allows us to avoid changing all the
3789 code that expects a pointer to something that expects
acf0174b 3790 a direct variable. */
953ff289
DN
3791 if (pass == 0)
3792 continue;
3793
3794 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
a68ab351
JJ
3795 if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx))
3796 {
3797 x = build_receiver_ref (var, false, ctx);
db3927fb 3798 x = build_fold_addr_expr_loc (clause_loc, x);
a68ab351
JJ
3799 }
3800 else if (TREE_CONSTANT (x))
953ff289 3801 {
decaaec8
JJ
3802 /* For reduction in SIMD loop, defer adding the
3803 initialization of the reference, because if we decide
3804 to use SIMD array for it, the initilization could cause
3805 expansion ICE. */
3806 if (c_kind == OMP_CLAUSE_REDUCTION && is_simd)
4ceffa27
JJ
3807 x = NULL_TREE;
3808 else
3809 {
3810 const char *name = NULL;
3811 if (DECL_NAME (var))
3812 name = IDENTIFIER_POINTER (DECL_NAME (new_var));
3813
3814 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
3815 name);
3816 gimple_add_tmp_var (x);
3817 TREE_ADDRESSABLE (x) = 1;
3818 x = build_fold_addr_expr_loc (clause_loc, x);
3819 }
953ff289
DN
3820 }
3821 else
3822 {
e79983f4
MM
3823 tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3824 x = build_call_expr_loc (clause_loc, atmp, 1, x);
953ff289
DN
3825 }
3826
4ceffa27
JJ
3827 if (x)
3828 {
3829 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3830 gimplify_assign (new_var, x, ilist);
3831 }
953ff289 3832
70f34814 3833 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
953ff289
DN
3834 }
3835 else if (c_kind == OMP_CLAUSE_REDUCTION
3836 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3837 {
3838 if (pass == 0)
3839 continue;
3840 }
3841 else if (pass != 0)
3842 continue;
3843
aaf46ef9 3844 switch (OMP_CLAUSE_CODE (c))
953ff289
DN
3845 {
3846 case OMP_CLAUSE_SHARED:
acf0174b
JJ
3847 /* Ignore shared directives in teams construct. */
3848 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3849 continue;
8ca5b2a2
JJ
3850 /* Shared global vars are just accessed directly. */
3851 if (is_global_var (new_var))
3852 break;
953ff289
DN
3853 /* Set up the DECL_VALUE_EXPR for shared variables now. This
3854 needs to be delayed until after fixup_child_record_type so
3855 that we get the correct type during the dereference. */
7c8f7639 3856 by_ref = use_pointer_for_field (var, ctx);
953ff289
DN
3857 x = build_receiver_ref (var, by_ref, ctx);
3858 SET_DECL_VALUE_EXPR (new_var, x);
3859 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3860
3861 /* ??? If VAR is not passed by reference, and the variable
3862 hasn't been initialized yet, then we'll get a warning for
3863 the store into the omp_data_s structure. Ideally, we'd be
b8698a0f 3864 able to notice this and not store anything at all, but
953ff289
DN
3865 we're generating code too early. Suppress the warning. */
3866 if (!by_ref)
3867 TREE_NO_WARNING (var) = 1;
3868 break;
3869
3870 case OMP_CLAUSE_LASTPRIVATE:
3871 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3872 break;
3873 /* FALLTHRU */
3874
3875 case OMP_CLAUSE_PRIVATE:
a68ab351
JJ
3876 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE)
3877 x = build_outer_var_ref (var, ctx);
3878 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
3879 {
3880 if (is_task_ctx (ctx))
3881 x = build_receiver_ref (var, false, ctx);
3882 else
3883 x = build_outer_var_ref (var, ctx);
3884 }
3885 else
3886 x = NULL;
74bf76ed 3887 do_private:
acf0174b
JJ
3888 tree nx;
3889 nx = lang_hooks.decls.omp_clause_default_ctor (c, new_var, x);
74bf76ed
JJ
3890 if (is_simd)
3891 {
3892 tree y = lang_hooks.decls.omp_clause_dtor (c, new_var);
acf0174b 3893 if ((TREE_ADDRESSABLE (new_var) || nx || y
74bf76ed
JJ
3894 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
3895 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3896 idx, lane, ivar, lvar))
3897 {
acf0174b 3898 if (nx)
74bf76ed
JJ
3899 x = lang_hooks.decls.omp_clause_default_ctor
3900 (c, unshare_expr (ivar), x);
acf0174b 3901 if (nx && x)
74bf76ed
JJ
3902 gimplify_and_add (x, &llist[0]);
3903 if (y)
3904 {
3905 y = lang_hooks.decls.omp_clause_dtor (c, ivar);
3906 if (y)
3907 {
3908 gimple_seq tseq = NULL;
3909
3910 dtor = y;
3911 gimplify_stmt (&dtor, &tseq);
3912 gimple_seq_add_seq (&llist[1], tseq);
3913 }
3914 }
3915 break;
3916 }
3917 }
acf0174b
JJ
3918 if (nx)
3919 gimplify_and_add (nx, ilist);
953ff289
DN
3920 /* FALLTHRU */
3921
3922 do_dtor:
3923 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
3924 if (x)
3925 {
726a989a
RB
3926 gimple_seq tseq = NULL;
3927
953ff289 3928 dtor = x;
726a989a 3929 gimplify_stmt (&dtor, &tseq);
355a7673 3930 gimple_seq_add_seq (dlist, tseq);
953ff289
DN
3931 }
3932 break;
3933
74bf76ed
JJ
3934 case OMP_CLAUSE_LINEAR:
3935 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c))
3936 goto do_firstprivate;
3937 if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
3938 x = NULL;
3939 else
3940 x = build_outer_var_ref (var, ctx);
3941 goto do_private;
3942
953ff289 3943 case OMP_CLAUSE_FIRSTPRIVATE:
a68ab351
JJ
3944 if (is_task_ctx (ctx))
3945 {
3946 if (is_reference (var) || is_variable_sized (var))
3947 goto do_dtor;
3948 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var,
3949 ctx))
3950 || use_pointer_for_field (var, NULL))
3951 {
3952 x = build_receiver_ref (var, false, ctx);
3953 SET_DECL_VALUE_EXPR (new_var, x);
3954 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3955 goto do_dtor;
3956 }
3957 }
74bf76ed 3958 do_firstprivate:
953ff289 3959 x = build_outer_var_ref (var, ctx);
74bf76ed
JJ
3960 if (is_simd)
3961 {
acf0174b
JJ
3962 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3963 && gimple_omp_for_combined_into_p (ctx->stmt))
3964 {
da6f124d
JJ
3965 tree t = OMP_CLAUSE_LINEAR_STEP (c);
3966 tree stept = TREE_TYPE (t);
3967 tree ct = find_omp_clause (clauses,
3968 OMP_CLAUSE__LOOPTEMP_);
3969 gcc_assert (ct);
3970 tree l = OMP_CLAUSE_DECL (ct);
56ad0e38
JJ
3971 tree n1 = fd->loop.n1;
3972 tree step = fd->loop.step;
3973 tree itype = TREE_TYPE (l);
3974 if (POINTER_TYPE_P (itype))
3975 itype = signed_type_for (itype);
3976 l = fold_build2 (MINUS_EXPR, itype, l, n1);
3977 if (TYPE_UNSIGNED (itype)
3978 && fd->loop.cond_code == GT_EXPR)
3979 l = fold_build2 (TRUNC_DIV_EXPR, itype,
3980 fold_build1 (NEGATE_EXPR, itype, l),
3981 fold_build1 (NEGATE_EXPR,
3982 itype, step));
3983 else
3984 l = fold_build2 (TRUNC_DIV_EXPR, itype, l, step);
acf0174b
JJ
3985 t = fold_build2 (MULT_EXPR, stept,
3986 fold_convert (stept, l), t);
da6f124d
JJ
3987
3988 if (OMP_CLAUSE_LINEAR_ARRAY (c))
3989 {
3990 x = lang_hooks.decls.omp_clause_linear_ctor
3991 (c, new_var, x, t);
3992 gimplify_and_add (x, ilist);
3993 goto do_dtor;
3994 }
3995
acf0174b
JJ
3996 if (POINTER_TYPE_P (TREE_TYPE (x)))
3997 x = fold_build2 (POINTER_PLUS_EXPR,
3998 TREE_TYPE (x), x, t);
3999 else
4000 x = fold_build2 (PLUS_EXPR, TREE_TYPE (x), x, t);
4001 }
4002
74bf76ed
JJ
4003 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
4004 || TREE_ADDRESSABLE (new_var))
4005 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4006 idx, lane, ivar, lvar))
4007 {
4008 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR)
4009 {
b731b390 4010 tree iv = create_tmp_var (TREE_TYPE (new_var));
74bf76ed
JJ
4011 x = lang_hooks.decls.omp_clause_copy_ctor (c, iv, x);
4012 gimplify_and_add (x, ilist);
4013 gimple_stmt_iterator gsi
4014 = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
538dd0b7 4015 gassign *g
74bf76ed
JJ
4016 = gimple_build_assign (unshare_expr (lvar), iv);
4017 gsi_insert_before_without_update (&gsi, g,
4018 GSI_SAME_STMT);
da6f124d 4019 tree t = OMP_CLAUSE_LINEAR_STEP (c);
74bf76ed
JJ
4020 enum tree_code code = PLUS_EXPR;
4021 if (POINTER_TYPE_P (TREE_TYPE (new_var)))
4022 code = POINTER_PLUS_EXPR;
0d0e4a03 4023 g = gimple_build_assign (iv, code, iv, t);
74bf76ed
JJ
4024 gsi_insert_before_without_update (&gsi, g,
4025 GSI_SAME_STMT);
4026 break;
4027 }
4028 x = lang_hooks.decls.omp_clause_copy_ctor
4029 (c, unshare_expr (ivar), x);
4030 gimplify_and_add (x, &llist[0]);
4031 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
4032 if (x)
4033 {
4034 gimple_seq tseq = NULL;
4035
4036 dtor = x;
4037 gimplify_stmt (&dtor, &tseq);
4038 gimple_seq_add_seq (&llist[1], tseq);
4039 }
4040 break;
4041 }
4042 }
953ff289
DN
4043 x = lang_hooks.decls.omp_clause_copy_ctor (c, new_var, x);
4044 gimplify_and_add (x, ilist);
4045 goto do_dtor;
953ff289 4046
acf0174b
JJ
4047 case OMP_CLAUSE__LOOPTEMP_:
4048 gcc_assert (is_parallel_ctx (ctx));
4049 x = build_outer_var_ref (var, ctx);
4050 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
4051 gimplify_and_add (x, ilist);
4052 break;
4053
953ff289 4054 case OMP_CLAUSE_COPYIN:
7c8f7639 4055 by_ref = use_pointer_for_field (var, NULL);
953ff289
DN
4056 x = build_receiver_ref (var, by_ref, ctx);
4057 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
4058 append_to_statement_list (x, &copyin_seq);
4059 copyin_by_ref |= by_ref;
4060 break;
4061
4062 case OMP_CLAUSE_REDUCTION:
4063 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4064 {
a68ab351 4065 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
acf0174b 4066 gimple tseq;
a68ab351
JJ
4067 x = build_outer_var_ref (var, ctx);
4068
acf0174b
JJ
4069 if (is_reference (var)
4070 && !useless_type_conversion_p (TREE_TYPE (placeholder),
4071 TREE_TYPE (x)))
db3927fb 4072 x = build_fold_addr_expr_loc (clause_loc, x);
a68ab351
JJ
4073 SET_DECL_VALUE_EXPR (placeholder, x);
4074 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
acf0174b
JJ
4075 tree new_vard = new_var;
4076 if (is_reference (var))
4077 {
4078 gcc_assert (TREE_CODE (new_var) == MEM_REF);
4079 new_vard = TREE_OPERAND (new_var, 0);
4080 gcc_assert (DECL_P (new_vard));
4081 }
74bf76ed
JJ
4082 if (is_simd
4083 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4084 idx, lane, ivar, lvar))
4085 {
acf0174b
JJ
4086 if (new_vard == new_var)
4087 {
4088 gcc_assert (DECL_VALUE_EXPR (new_var) == lvar);
4089 SET_DECL_VALUE_EXPR (new_var, ivar);
4090 }
4091 else
4092 {
4093 SET_DECL_VALUE_EXPR (new_vard,
4094 build_fold_addr_expr (ivar));
4095 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
4096 }
4097 x = lang_hooks.decls.omp_clause_default_ctor
4098 (c, unshare_expr (ivar),
4099 build_outer_var_ref (var, ctx));
4100 if (x)
4101 gimplify_and_add (x, &llist[0]);
4102 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
4103 {
4104 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
4105 lower_omp (&tseq, ctx);
4106 gimple_seq_add_seq (&llist[0], tseq);
4107 }
4108 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
4109 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
4110 lower_omp (&tseq, ctx);
4111 gimple_seq_add_seq (&llist[1], tseq);
4112 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4113 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
4114 if (new_vard == new_var)
4115 SET_DECL_VALUE_EXPR (new_var, lvar);
4116 else
4117 SET_DECL_VALUE_EXPR (new_vard,
4118 build_fold_addr_expr (lvar));
4119 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
4120 if (x)
4121 {
4122 tseq = NULL;
4123 dtor = x;
4124 gimplify_stmt (&dtor, &tseq);
4125 gimple_seq_add_seq (&llist[1], tseq);
4126 }
4127 break;
4128 }
4ceffa27
JJ
4129 /* If this is a reference to constant size reduction var
4130 with placeholder, we haven't emitted the initializer
4131 for it because it is undesirable if SIMD arrays are used.
4132 But if they aren't used, we need to emit the deferred
4133 initialization now. */
4134 else if (is_reference (var) && is_simd)
decaaec8 4135 handle_simd_reference (clause_loc, new_vard, ilist);
acf0174b 4136 x = lang_hooks.decls.omp_clause_default_ctor
92d28cbb
JJ
4137 (c, unshare_expr (new_var),
4138 build_outer_var_ref (var, ctx));
acf0174b
JJ
4139 if (x)
4140 gimplify_and_add (x, ilist);
4141 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
4142 {
4143 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
4144 lower_omp (&tseq, ctx);
4145 gimple_seq_add_seq (ilist, tseq);
4146 }
4147 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
4148 if (is_simd)
4149 {
4150 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
4151 lower_omp (&tseq, ctx);
4152 gimple_seq_add_seq (dlist, tseq);
4153 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4154 }
4155 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
4156 goto do_dtor;
4157 }
4158 else
4159 {
4160 x = omp_reduction_init (c, TREE_TYPE (new_var));
4161 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
e9792e1d
JJ
4162 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
4163
4164 /* reduction(-:var) sums up the partial results, so it
4165 acts identically to reduction(+:var). */
4166 if (code == MINUS_EXPR)
4167 code = PLUS_EXPR;
4168
decaaec8
JJ
4169 tree new_vard = new_var;
4170 if (is_simd && is_reference (var))
4171 {
4172 gcc_assert (TREE_CODE (new_var) == MEM_REF);
4173 new_vard = TREE_OPERAND (new_var, 0);
4174 gcc_assert (DECL_P (new_vard));
4175 }
acf0174b
JJ
4176 if (is_simd
4177 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4178 idx, lane, ivar, lvar))
4179 {
acf0174b
JJ
4180 tree ref = build_outer_var_ref (var, ctx);
4181
4182 gimplify_assign (unshare_expr (ivar), x, &llist[0]);
4183
acf0174b 4184 x = build2 (code, TREE_TYPE (ref), ref, ivar);
74bf76ed
JJ
4185 ref = build_outer_var_ref (var, ctx);
4186 gimplify_assign (ref, x, &llist[1]);
decaaec8
JJ
4187
4188 if (new_vard != new_var)
4189 {
4190 SET_DECL_VALUE_EXPR (new_vard,
4191 build_fold_addr_expr (lvar));
4192 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
4193 }
74bf76ed
JJ
4194 }
4195 else
4196 {
decaaec8
JJ
4197 if (is_reference (var) && is_simd)
4198 handle_simd_reference (clause_loc, new_vard, ilist);
74bf76ed
JJ
4199 gimplify_assign (new_var, x, ilist);
4200 if (is_simd)
e9792e1d
JJ
4201 {
4202 tree ref = build_outer_var_ref (var, ctx);
4203
4204 x = build2 (code, TREE_TYPE (ref), ref, new_var);
4205 ref = build_outer_var_ref (var, ctx);
4206 gimplify_assign (ref, x, dlist);
4207 }
74bf76ed 4208 }
953ff289
DN
4209 }
4210 break;
4211
4212 default:
4213 gcc_unreachable ();
4214 }
4215 }
4216 }
4217
74bf76ed
JJ
4218 if (lane)
4219 {
4220 tree uid = create_tmp_var (ptr_type_node, "simduid");
8928eff3
JJ
4221 /* Don't want uninit warnings on simduid, it is always uninitialized,
4222 but we use it not for the value, but for the DECL_UID only. */
4223 TREE_NO_WARNING (uid) = 1;
74bf76ed
JJ
4224 gimple g
4225 = gimple_build_call_internal (IFN_GOMP_SIMD_LANE, 1, uid);
4226 gimple_call_set_lhs (g, lane);
4227 gimple_stmt_iterator gsi = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
4228 gsi_insert_before_without_update (&gsi, g, GSI_SAME_STMT);
4229 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SIMDUID_);
4230 OMP_CLAUSE__SIMDUID__DECL (c) = uid;
4231 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
4232 gimple_omp_for_set_clauses (ctx->stmt, c);
0d0e4a03
JJ
4233 g = gimple_build_assign (lane, INTEGER_CST,
4234 build_int_cst (unsigned_type_node, 0));
74bf76ed
JJ
4235 gimple_seq_add_stmt (ilist, g);
4236 for (int i = 0; i < 2; i++)
4237 if (llist[i])
4238 {
b731b390 4239 tree vf = create_tmp_var (unsigned_type_node);
74bf76ed
JJ
4240 g = gimple_build_call_internal (IFN_GOMP_SIMD_VF, 1, uid);
4241 gimple_call_set_lhs (g, vf);
4242 gimple_seq *seq = i == 0 ? ilist : dlist;
4243 gimple_seq_add_stmt (seq, g);
4244 tree t = build_int_cst (unsigned_type_node, 0);
0d0e4a03 4245 g = gimple_build_assign (idx, INTEGER_CST, t);
74bf76ed
JJ
4246 gimple_seq_add_stmt (seq, g);
4247 tree body = create_artificial_label (UNKNOWN_LOCATION);
4248 tree header = create_artificial_label (UNKNOWN_LOCATION);
4249 tree end = create_artificial_label (UNKNOWN_LOCATION);
4250 gimple_seq_add_stmt (seq, gimple_build_goto (header));
4251 gimple_seq_add_stmt (seq, gimple_build_label (body));
4252 gimple_seq_add_seq (seq, llist[i]);
4253 t = build_int_cst (unsigned_type_node, 1);
0d0e4a03 4254 g = gimple_build_assign (idx, PLUS_EXPR, idx, t);
74bf76ed
JJ
4255 gimple_seq_add_stmt (seq, g);
4256 gimple_seq_add_stmt (seq, gimple_build_label (header));
4257 g = gimple_build_cond (LT_EXPR, idx, vf, body, end);
4258 gimple_seq_add_stmt (seq, g);
4259 gimple_seq_add_stmt (seq, gimple_build_label (end));
4260 }
4261 }
4262
953ff289
DN
4263 /* The copyin sequence is not to be executed by the main thread, since
4264 that would result in self-copies. Perhaps not visible to scalars,
4265 but it certainly is to C++ operator=. */
4266 if (copyin_seq)
4267 {
e79983f4
MM
4268 x = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM),
4269 0);
953ff289
DN
4270 x = build2 (NE_EXPR, boolean_type_node, x,
4271 build_int_cst (TREE_TYPE (x), 0));
4272 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
4273 gimplify_and_add (x, ilist);
4274 }
4275
4276 /* If any copyin variable is passed by reference, we must ensure the
4277 master thread doesn't modify it before it is copied over in all
8ca5b2a2
JJ
4278 threads. Similarly for variables in both firstprivate and
4279 lastprivate clauses we need to ensure the lastprivate copying
acf0174b
JJ
4280 happens after firstprivate copying in all threads. And similarly
4281 for UDRs if initializer expression refers to omp_orig. */
4282 if (copyin_by_ref || lastprivate_firstprivate || reduction_omp_orig_ref)
74bf76ed
JJ
4283 {
4284 /* Don't add any barrier for #pragma omp simd or
4285 #pragma omp distribute. */
4286 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
e2110f8f 4287 || gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_FOR)
acf0174b 4288 gimple_seq_add_stmt (ilist, build_omp_barrier (NULL_TREE));
74bf76ed
JJ
4289 }
4290
4291 /* If max_vf is non-zero, then we can use only a vectorization factor
4292 up to the max_vf we chose. So stick it into the safelen clause. */
4293 if (max_vf)
4294 {
4295 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
4296 OMP_CLAUSE_SAFELEN);
4297 if (c == NULL_TREE
b46ebd6c
JJ
4298 || (TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) == INTEGER_CST
4299 && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
4300 max_vf) == 1))
74bf76ed
JJ
4301 {
4302 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_SAFELEN);
4303 OMP_CLAUSE_SAFELEN_EXPR (c) = build_int_cst (integer_type_node,
4304 max_vf);
4305 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
4306 gimple_omp_for_set_clauses (ctx->stmt, c);
4307 }
4308 }
953ff289
DN
4309}
4310
50674e96 4311
953ff289
DN
4312/* Generate code to implement the LASTPRIVATE clauses. This is used for
4313 both parallel and workshare constructs. PREDICATE may be NULL if it's
4314 always true. */
4315
4316static void
726a989a 4317lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
acf0174b 4318 omp_context *ctx)
953ff289 4319{
74bf76ed 4320 tree x, c, label = NULL, orig_clauses = clauses;
a68ab351 4321 bool par_clauses = false;
74bf76ed 4322 tree simduid = NULL, lastlane = NULL;
953ff289 4323
74bf76ed
JJ
4324 /* Early exit if there are no lastprivate or linear clauses. */
4325 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
4326 if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LASTPRIVATE
4327 || (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LINEAR
4328 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses)))
4329 break;
953ff289
DN
4330 if (clauses == NULL)
4331 {
4332 /* If this was a workshare clause, see if it had been combined
4333 with its parallel. In that case, look for the clauses on the
4334 parallel statement itself. */
4335 if (is_parallel_ctx (ctx))
4336 return;
4337
4338 ctx = ctx->outer;
4339 if (ctx == NULL || !is_parallel_ctx (ctx))
4340 return;
4341
726a989a 4342 clauses = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
953ff289
DN
4343 OMP_CLAUSE_LASTPRIVATE);
4344 if (clauses == NULL)
4345 return;
a68ab351 4346 par_clauses = true;
953ff289
DN
4347 }
4348
726a989a
RB
4349 if (predicate)
4350 {
538dd0b7 4351 gcond *stmt;
726a989a
RB
4352 tree label_true, arm1, arm2;
4353
c2255bc4
AH
4354 label = create_artificial_label (UNKNOWN_LOCATION);
4355 label_true = create_artificial_label (UNKNOWN_LOCATION);
726a989a
RB
4356 arm1 = TREE_OPERAND (predicate, 0);
4357 arm2 = TREE_OPERAND (predicate, 1);
4358 gimplify_expr (&arm1, stmt_list, NULL, is_gimple_val, fb_rvalue);
4359 gimplify_expr (&arm2, stmt_list, NULL, is_gimple_val, fb_rvalue);
4360 stmt = gimple_build_cond (TREE_CODE (predicate), arm1, arm2,
4361 label_true, label);
4362 gimple_seq_add_stmt (stmt_list, stmt);
4363 gimple_seq_add_stmt (stmt_list, gimple_build_label (label_true));
4364 }
953ff289 4365
74bf76ed 4366 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
0aadce73 4367 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
74bf76ed
JJ
4368 {
4369 simduid = find_omp_clause (orig_clauses, OMP_CLAUSE__SIMDUID_);
4370 if (simduid)
4371 simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
4372 }
4373
a68ab351 4374 for (c = clauses; c ;)
953ff289
DN
4375 {
4376 tree var, new_var;
db3927fb 4377 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
953ff289 4378
74bf76ed
JJ
4379 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
4380 || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
4381 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
a68ab351
JJ
4382 {
4383 var = OMP_CLAUSE_DECL (c);
4384 new_var = lookup_decl (var, ctx);
953ff289 4385
74bf76ed
JJ
4386 if (simduid && DECL_HAS_VALUE_EXPR_P (new_var))
4387 {
4388 tree val = DECL_VALUE_EXPR (new_var);
4389 if (TREE_CODE (val) == ARRAY_REF
4390 && VAR_P (TREE_OPERAND (val, 0))
4391 && lookup_attribute ("omp simd array",
4392 DECL_ATTRIBUTES (TREE_OPERAND (val,
4393 0))))
4394 {
4395 if (lastlane == NULL)
4396 {
b731b390 4397 lastlane = create_tmp_var (unsigned_type_node);
538dd0b7 4398 gcall *g
74bf76ed
JJ
4399 = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE,
4400 2, simduid,
4401 TREE_OPERAND (val, 1));
4402 gimple_call_set_lhs (g, lastlane);
4403 gimple_seq_add_stmt (stmt_list, g);
4404 }
4405 new_var = build4 (ARRAY_REF, TREE_TYPE (val),
4406 TREE_OPERAND (val, 0), lastlane,
4407 NULL_TREE, NULL_TREE);
4408 }
4409 }
4410
4411 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
4412 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
726a989a 4413 {
355a7673 4414 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
726a989a
RB
4415 gimple_seq_add_seq (stmt_list,
4416 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
74bf76ed 4417 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) = NULL;
726a989a 4418 }
f7468577
JJ
4419 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
4420 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
4421 {
4422 lower_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
4423 gimple_seq_add_seq (stmt_list,
4424 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c));
4425 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c) = NULL;
4426 }
953ff289 4427
a68ab351
JJ
4428 x = build_outer_var_ref (var, ctx);
4429 if (is_reference (var))
70f34814 4430 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
a68ab351 4431 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
726a989a 4432 gimplify_and_add (x, stmt_list);
a68ab351
JJ
4433 }
4434 c = OMP_CLAUSE_CHAIN (c);
4435 if (c == NULL && !par_clauses)
4436 {
4437 /* If this was a workshare clause, see if it had been combined
4438 with its parallel. In that case, continue looking for the
4439 clauses also on the parallel statement itself. */
4440 if (is_parallel_ctx (ctx))
4441 break;
4442
4443 ctx = ctx->outer;
4444 if (ctx == NULL || !is_parallel_ctx (ctx))
4445 break;
4446
726a989a 4447 c = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
a68ab351
JJ
4448 OMP_CLAUSE_LASTPRIVATE);
4449 par_clauses = true;
4450 }
953ff289
DN
4451 }
4452
726a989a
RB
4453 if (label)
4454 gimple_seq_add_stmt (stmt_list, gimple_build_label (label));
953ff289
DN
4455}
4456
41dbbb37
TS
4457static void
4458oacc_lower_reduction_var_helper (gimple_seq *stmt_seqp, omp_context *ctx,
4459 tree tid, tree var, tree new_var)
4460{
4461 /* The atomic add at the end of the sum creates unnecessary
4462 write contention on accelerators. To work around this,
4463 create an array to store the partial reductions. Later, in
4464 lower_omp_for (for openacc), the values of array will be
4465 combined. */
4466
4467 tree t = NULL_TREE, array, x;
4468 tree type = get_base_type (var);
4469 gimple stmt;
4470
4471 /* Now insert the partial reductions into the array. */
4472
4473 /* Find the reduction array. */
4474
4475 tree ptype = build_pointer_type (type);
4476
4477 t = lookup_oacc_reduction (oacc_get_reduction_array_id (var), ctx);
4478 t = build_receiver_ref (t, false, ctx->outer);
4479
4480 array = create_tmp_var (ptype);
4481 gimplify_assign (array, t, stmt_seqp);
4482
4483 tree ptr = create_tmp_var (TREE_TYPE (array));
4484
4485 /* Find the reduction array. */
4486
4487 /* testing a unary conversion. */
4488 tree offset = create_tmp_var (sizetype);
4489 gimplify_assign (offset, TYPE_SIZE_UNIT (type),
4490 stmt_seqp);
4491 t = create_tmp_var (sizetype);
4492 gimplify_assign (t, unshare_expr (fold_build1 (NOP_EXPR, sizetype, tid)),
4493 stmt_seqp);
4494 stmt = gimple_build_assign (offset, MULT_EXPR, offset, t);
4495 gimple_seq_add_stmt (stmt_seqp, stmt);
4496
4497 /* Offset expression. Does the POINTER_PLUS_EXPR take care
4498 of adding sizeof(var) to the array? */
4499 ptr = create_tmp_var (ptype);
4500 stmt = gimple_build_assign (unshare_expr (ptr), POINTER_PLUS_EXPR, array,
4501 offset);
4502 gimple_seq_add_stmt (stmt_seqp, stmt);
4503
4504 /* Move the local sum to gfc$sum[i]. */
4505 x = unshare_expr (build_simple_mem_ref (ptr));
4506 stmt = gimplify_assign (x, new_var, stmt_seqp);
4507}
50674e96 4508
953ff289
DN
4509/* Generate code to implement the REDUCTION clauses. */
4510
4511static void
726a989a 4512lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
953ff289 4513{
726a989a
RB
4514 gimple_seq sub_seq = NULL;
4515 gimple stmt;
41dbbb37 4516 tree x, c, tid = NULL_TREE;
953ff289
DN
4517 int count = 0;
4518
74bf76ed
JJ
4519 /* SIMD reductions are handled in lower_rec_input_clauses. */
4520 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
0aadce73 4521 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
74bf76ed
JJ
4522 return;
4523
953ff289
DN
4524 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
4525 update in that case, otherwise use a lock. */
4526 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
aaf46ef9 4527 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
953ff289
DN
4528 {
4529 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4530 {
acf0174b 4531 /* Never use OMP_ATOMIC for array reductions or UDRs. */
953ff289
DN
4532 count = -1;
4533 break;
4534 }
4535 count++;
4536 }
4537
4538 if (count == 0)
4539 return;
4540
41dbbb37
TS
4541 /* Initialize thread info for OpenACC. */
4542 if (is_gimple_omp_oacc (ctx->stmt))
4543 {
4544 /* Get the current thread id. */
4545 tree call = builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM);
4546 tid = create_tmp_var (TREE_TYPE (TREE_TYPE (call)));
4547 gimple stmt = gimple_build_call (call, 0);
4548 gimple_call_set_lhs (stmt, tid);
4549 gimple_seq_add_stmt (stmt_seqp, stmt);
4550 }
4551
953ff289
DN
4552 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4553 {
4554 tree var, ref, new_var;
4555 enum tree_code code;
db3927fb 4556 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
953ff289 4557
aaf46ef9 4558 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
953ff289
DN
4559 continue;
4560
4561 var = OMP_CLAUSE_DECL (c);
4562 new_var = lookup_decl (var, ctx);
4563 if (is_reference (var))
70f34814 4564 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
953ff289
DN
4565 ref = build_outer_var_ref (var, ctx);
4566 code = OMP_CLAUSE_REDUCTION_CODE (c);
50674e96
DN
4567
4568 /* reduction(-:var) sums up the partial results, so it acts
4569 identically to reduction(+:var). */
953ff289
DN
4570 if (code == MINUS_EXPR)
4571 code = PLUS_EXPR;
4572
41dbbb37
TS
4573 if (is_gimple_omp_oacc (ctx->stmt))
4574 {
4575 gcc_checking_assert (!OMP_CLAUSE_REDUCTION_PLACEHOLDER (c));
4576
4577 oacc_lower_reduction_var_helper (stmt_seqp, ctx, tid, var, new_var);
4578 }
4579 else if (count == 1)
953ff289 4580 {
db3927fb 4581 tree addr = build_fold_addr_expr_loc (clause_loc, ref);
953ff289
DN
4582
4583 addr = save_expr (addr);
4584 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
db3927fb 4585 x = fold_build2_loc (clause_loc, code, TREE_TYPE (ref), ref, new_var);
953ff289 4586 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
726a989a 4587 gimplify_and_add (x, stmt_seqp);
953ff289
DN
4588 return;
4589 }
41dbbb37 4590 else if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
953ff289
DN
4591 {
4592 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
4593
acf0174b
JJ
4594 if (is_reference (var)
4595 && !useless_type_conversion_p (TREE_TYPE (placeholder),
4596 TREE_TYPE (ref)))
db3927fb 4597 ref = build_fold_addr_expr_loc (clause_loc, ref);
953ff289
DN
4598 SET_DECL_VALUE_EXPR (placeholder, ref);
4599 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
355a7673 4600 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
726a989a
RB
4601 gimple_seq_add_seq (&sub_seq, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
4602 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
953ff289
DN
4603 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
4604 }
4605 else
4606 {
4607 x = build2 (code, TREE_TYPE (ref), ref, new_var);
4608 ref = build_outer_var_ref (var, ctx);
726a989a 4609 gimplify_assign (ref, x, &sub_seq);
953ff289
DN
4610 }
4611 }
4612
41dbbb37
TS
4613 if (is_gimple_omp_oacc (ctx->stmt))
4614 return;
4615
e79983f4
MM
4616 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START),
4617 0);
726a989a 4618 gimple_seq_add_stmt (stmt_seqp, stmt);
953ff289 4619
726a989a 4620 gimple_seq_add_seq (stmt_seqp, sub_seq);
953ff289 4621
e79983f4
MM
4622 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END),
4623 0);
726a989a 4624 gimple_seq_add_stmt (stmt_seqp, stmt);
953ff289
DN
4625}
4626
50674e96 4627
953ff289
DN
4628/* Generate code to implement the COPYPRIVATE clauses. */
4629
4630static void
726a989a 4631lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist,
953ff289
DN
4632 omp_context *ctx)
4633{
4634 tree c;
4635
4636 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4637 {
78db7d92 4638 tree var, new_var, ref, x;
953ff289 4639 bool by_ref;
db3927fb 4640 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
953ff289 4641
aaf46ef9 4642 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
953ff289
DN
4643 continue;
4644
4645 var = OMP_CLAUSE_DECL (c);
7c8f7639 4646 by_ref = use_pointer_for_field (var, NULL);
953ff289
DN
4647
4648 ref = build_sender_ref (var, ctx);
78db7d92
JJ
4649 x = new_var = lookup_decl_in_outer_ctx (var, ctx);
4650 if (by_ref)
4651 {
4652 x = build_fold_addr_expr_loc (clause_loc, new_var);
4653 x = fold_convert_loc (clause_loc, TREE_TYPE (ref), x);
4654 }
726a989a 4655 gimplify_assign (ref, x, slist);
953ff289 4656
78db7d92
JJ
4657 ref = build_receiver_ref (var, false, ctx);
4658 if (by_ref)
4659 {
4660 ref = fold_convert_loc (clause_loc,
4661 build_pointer_type (TREE_TYPE (new_var)),
4662 ref);
4663 ref = build_fold_indirect_ref_loc (clause_loc, ref);
4664 }
953ff289
DN
4665 if (is_reference (var))
4666 {
78db7d92 4667 ref = fold_convert_loc (clause_loc, TREE_TYPE (new_var), ref);
70f34814
RG
4668 ref = build_simple_mem_ref_loc (clause_loc, ref);
4669 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
953ff289 4670 }
78db7d92 4671 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, ref);
953ff289
DN
4672 gimplify_and_add (x, rlist);
4673 }
4674}
4675
50674e96 4676
953ff289
DN
4677/* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
4678 and REDUCTION from the sender (aka parent) side. */
4679
4680static void
726a989a
RB
4681lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
4682 omp_context *ctx)
953ff289
DN
4683{
4684 tree c;
4685
4686 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4687 {
50674e96 4688 tree val, ref, x, var;
953ff289 4689 bool by_ref, do_in = false, do_out = false;
db3927fb 4690 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
953ff289 4691
aaf46ef9 4692 switch (OMP_CLAUSE_CODE (c))
953ff289 4693 {
a68ab351
JJ
4694 case OMP_CLAUSE_PRIVATE:
4695 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
4696 break;
4697 continue;
953ff289
DN
4698 case OMP_CLAUSE_FIRSTPRIVATE:
4699 case OMP_CLAUSE_COPYIN:
4700 case OMP_CLAUSE_LASTPRIVATE:
4701 case OMP_CLAUSE_REDUCTION:
acf0174b 4702 case OMP_CLAUSE__LOOPTEMP_:
953ff289
DN
4703 break;
4704 default:
4705 continue;
4706 }
4707
d2dda7fe
JJ
4708 val = OMP_CLAUSE_DECL (c);
4709 var = lookup_decl_in_outer_ctx (val, ctx);
50674e96 4710
8ca5b2a2
JJ
4711 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
4712 && is_global_var (var))
4713 continue;
953ff289
DN
4714 if (is_variable_sized (val))
4715 continue;
7c8f7639 4716 by_ref = use_pointer_for_field (val, NULL);
953ff289 4717
aaf46ef9 4718 switch (OMP_CLAUSE_CODE (c))
953ff289 4719 {
a68ab351 4720 case OMP_CLAUSE_PRIVATE:
953ff289
DN
4721 case OMP_CLAUSE_FIRSTPRIVATE:
4722 case OMP_CLAUSE_COPYIN:
acf0174b 4723 case OMP_CLAUSE__LOOPTEMP_:
953ff289
DN
4724 do_in = true;
4725 break;
4726
4727 case OMP_CLAUSE_LASTPRIVATE:
4728 if (by_ref || is_reference (val))
4729 {
4730 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4731 continue;
4732 do_in = true;
4733 }
4734 else
a68ab351
JJ
4735 {
4736 do_out = true;
4737 if (lang_hooks.decls.omp_private_outer_ref (val))
4738 do_in = true;
4739 }
953ff289
DN
4740 break;
4741
4742 case OMP_CLAUSE_REDUCTION:
4743 do_in = true;
4744 do_out = !(by_ref || is_reference (val));
4745 break;
4746
4747 default:
4748 gcc_unreachable ();
4749 }
4750
4751 if (do_in)
4752 {
4753 ref = build_sender_ref (val, ctx);
db3927fb 4754 x = by_ref ? build_fold_addr_expr_loc (clause_loc, var) : var;
726a989a 4755 gimplify_assign (ref, x, ilist);
a68ab351
JJ
4756 if (is_task_ctx (ctx))
4757 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref, 1)) = NULL;
953ff289 4758 }
50674e96 4759
953ff289
DN
4760 if (do_out)
4761 {
4762 ref = build_sender_ref (val, ctx);
726a989a 4763 gimplify_assign (var, ref, olist);
953ff289
DN
4764 }
4765 }
4766}
4767
726a989a
RB
4768/* Generate code to implement SHARED from the sender (aka parent)
4769 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
4770 list things that got automatically shared. */
953ff289
DN
4771
4772static void
726a989a 4773lower_send_shared_vars (gimple_seq *ilist, gimple_seq *olist, omp_context *ctx)
953ff289 4774{
a68ab351 4775 tree var, ovar, nvar, f, x, record_type;
953ff289
DN
4776
4777 if (ctx->record_type == NULL)
4778 return;
50674e96 4779
a68ab351 4780 record_type = ctx->srecord_type ? ctx->srecord_type : ctx->record_type;
910ad8de 4781 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
953ff289
DN
4782 {
4783 ovar = DECL_ABSTRACT_ORIGIN (f);
4784 nvar = maybe_lookup_decl (ovar, ctx);
4785 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
4786 continue;
4787
50674e96
DN
4788 /* If CTX is a nested parallel directive. Find the immediately
4789 enclosing parallel or workshare construct that contains a
4790 mapping for OVAR. */
d2dda7fe 4791 var = lookup_decl_in_outer_ctx (ovar, ctx);
50674e96 4792
7c8f7639 4793 if (use_pointer_for_field (ovar, ctx))
953ff289
DN
4794 {
4795 x = build_sender_ref (ovar, ctx);
50674e96 4796 var = build_fold_addr_expr (var);
726a989a 4797 gimplify_assign (x, var, ilist);
953ff289
DN
4798 }
4799 else
4800 {
4801 x = build_sender_ref (ovar, ctx);
726a989a 4802 gimplify_assign (x, var, ilist);
953ff289 4803
14e5b285
RG
4804 if (!TREE_READONLY (var)
4805 /* We don't need to receive a new reference to a result
4806 or parm decl. In fact we may not store to it as we will
4807 invalidate any pending RSO and generate wrong gimple
4808 during inlining. */
4809 && !((TREE_CODE (var) == RESULT_DECL
4810 || TREE_CODE (var) == PARM_DECL)
4811 && DECL_BY_REFERENCE (var)))
a68ab351
JJ
4812 {
4813 x = build_sender_ref (ovar, ctx);
726a989a 4814 gimplify_assign (var, x, olist);
a68ab351 4815 }
953ff289
DN
4816 }
4817 }
4818}
4819
726a989a
RB
4820
4821/* A convenience function to build an empty GIMPLE_COND with just the
4822 condition. */
4823
538dd0b7 4824static gcond *
726a989a
RB
4825gimple_build_cond_empty (tree cond)
4826{
4827 enum tree_code pred_code;
4828 tree lhs, rhs;
4829
4830 gimple_cond_get_ops_from_tree (cond, &pred_code, &lhs, &rhs);
4831 return gimple_build_cond (pred_code, lhs, rhs, NULL_TREE, NULL_TREE);
4832}
4833
4834
b8698a0f 4835/* Build the function calls to GOMP_parallel_start etc to actually
50674e96
DN
4836 generate the parallel operation. REGION is the parallel region
4837 being expanded. BB is the block where to insert the code. WS_ARGS
4838 will be set if this is a call to a combined parallel+workshare
4839 construct, it contains the list of additional arguments needed by
4840 the workshare construct. */
953ff289
DN
4841
4842static void
777f7f9a 4843expand_parallel_call (struct omp_region *region, basic_block bb,
538dd0b7
DM
4844 gomp_parallel *entry_stmt,
4845 vec<tree, va_gc> *ws_args)
953ff289 4846{
acf0174b 4847 tree t, t1, t2, val, cond, c, clauses, flags;
726a989a
RB
4848 gimple_stmt_iterator gsi;
4849 gimple stmt;
e79983f4
MM
4850 enum built_in_function start_ix;
4851 int start_ix2;
db3927fb 4852 location_t clause_loc;
9771b263 4853 vec<tree, va_gc> *args;
50674e96 4854
726a989a 4855 clauses = gimple_omp_parallel_clauses (entry_stmt);
50674e96 4856
acf0174b 4857 /* Determine what flavor of GOMP_parallel we will be
50674e96 4858 emitting. */
acf0174b 4859 start_ix = BUILT_IN_GOMP_PARALLEL;
50674e96
DN
4860 if (is_combined_parallel (region))
4861 {
777f7f9a 4862 switch (region->inner->type)
50674e96 4863 {
726a989a 4864 case GIMPLE_OMP_FOR:
a68ab351 4865 gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
acf0174b 4866 start_ix2 = ((int)BUILT_IN_GOMP_PARALLEL_LOOP_STATIC
e79983f4
MM
4867 + (region->inner->sched_kind
4868 == OMP_CLAUSE_SCHEDULE_RUNTIME
4869 ? 3 : region->inner->sched_kind));
4870 start_ix = (enum built_in_function)start_ix2;
777f7f9a 4871 break;
726a989a 4872 case GIMPLE_OMP_SECTIONS:
acf0174b 4873 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS;
777f7f9a
RH
4874 break;
4875 default:
4876 gcc_unreachable ();
50674e96 4877 }
50674e96 4878 }
953ff289
DN
4879
4880 /* By default, the value of NUM_THREADS is zero (selected at run time)
4881 and there is no conditional. */
4882 cond = NULL_TREE;
4883 val = build_int_cst (unsigned_type_node, 0);
acf0174b 4884 flags = build_int_cst (unsigned_type_node, 0);
953ff289
DN
4885
4886 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
4887 if (c)
4888 cond = OMP_CLAUSE_IF_EXPR (c);
4889
4890 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
4891 if (c)
db3927fb
AH
4892 {
4893 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
4894 clause_loc = OMP_CLAUSE_LOCATION (c);
4895 }
4896 else
4897 clause_loc = gimple_location (entry_stmt);
953ff289 4898
acf0174b
JJ
4899 c = find_omp_clause (clauses, OMP_CLAUSE_PROC_BIND);
4900 if (c)
4901 flags = build_int_cst (unsigned_type_node, OMP_CLAUSE_PROC_BIND_KIND (c));
4902
953ff289 4903 /* Ensure 'val' is of the correct type. */
db3927fb 4904 val = fold_convert_loc (clause_loc, unsigned_type_node, val);
953ff289
DN
4905
4906 /* If we found the clause 'if (cond)', build either
4907 (cond != 0) or (cond ? val : 1u). */
4908 if (cond)
4909 {
50674e96
DN
4910 cond = gimple_boolify (cond);
4911
953ff289 4912 if (integer_zerop (val))
db3927fb
AH
4913 val = fold_build2_loc (clause_loc,
4914 EQ_EXPR, unsigned_type_node, cond,
917948d3 4915 build_int_cst (TREE_TYPE (cond), 0));
953ff289 4916 else
50674e96
DN
4917 {
4918 basic_block cond_bb, then_bb, else_bb;
917948d3 4919 edge e, e_then, e_else;
726a989a 4920 tree tmp_then, tmp_else, tmp_join, tmp_var;
917948d3 4921
b731b390 4922 tmp_var = create_tmp_var (TREE_TYPE (val));
917948d3
ZD
4923 if (gimple_in_ssa_p (cfun))
4924 {
b731b390
JJ
4925 tmp_then = make_ssa_name (tmp_var);
4926 tmp_else = make_ssa_name (tmp_var);
4927 tmp_join = make_ssa_name (tmp_var);
917948d3
ZD
4928 }
4929 else
4930 {
4931 tmp_then = tmp_var;
4932 tmp_else = tmp_var;
4933 tmp_join = tmp_var;
4934 }
50674e96 4935
50674e96
DN
4936 e = split_block (bb, NULL);
4937 cond_bb = e->src;
4938 bb = e->dest;
4939 remove_edge (e);
4940
4941 then_bb = create_empty_bb (cond_bb);
4942 else_bb = create_empty_bb (then_bb);
917948d3
ZD
4943 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
4944 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
50674e96 4945
726a989a
RB
4946 stmt = gimple_build_cond_empty (cond);
4947 gsi = gsi_start_bb (cond_bb);
4948 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
50674e96 4949
726a989a
RB
4950 gsi = gsi_start_bb (then_bb);
4951 stmt = gimple_build_assign (tmp_then, val);
4952 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
50674e96 4953
726a989a
RB
4954 gsi = gsi_start_bb (else_bb);
4955 stmt = gimple_build_assign
4956 (tmp_else, build_int_cst (unsigned_type_node, 1));
4957 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
50674e96
DN
4958
4959 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
4960 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
726338f4
RB
4961 add_bb_to_loop (then_bb, cond_bb->loop_father);
4962 add_bb_to_loop (else_bb, cond_bb->loop_father);
917948d3
ZD
4963 e_then = make_edge (then_bb, bb, EDGE_FALLTHRU);
4964 e_else = make_edge (else_bb, bb, EDGE_FALLTHRU);
50674e96 4965
917948d3
ZD
4966 if (gimple_in_ssa_p (cfun))
4967 {
538dd0b7 4968 gphi *phi = create_phi_node (tmp_join, bb);
9e227d60
DC
4969 add_phi_arg (phi, tmp_then, e_then, UNKNOWN_LOCATION);
4970 add_phi_arg (phi, tmp_else, e_else, UNKNOWN_LOCATION);
917948d3
ZD
4971 }
4972
4973 val = tmp_join;
50674e96
DN
4974 }
4975
726a989a
RB
4976 gsi = gsi_start_bb (bb);
4977 val = force_gimple_operand_gsi (&gsi, val, true, NULL_TREE,
4978 false, GSI_CONTINUE_LINKING);
953ff289
DN
4979 }
4980
726a989a
RB
4981 gsi = gsi_last_bb (bb);
4982 t = gimple_omp_parallel_data_arg (entry_stmt);
953ff289 4983 if (t == NULL)
5039610b 4984 t1 = null_pointer_node;
953ff289 4985 else
5039610b 4986 t1 = build_fold_addr_expr (t);
726a989a 4987 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
50674e96 4988
acf0174b 4989 vec_alloc (args, 4 + vec_safe_length (ws_args));
9771b263
DN
4990 args->quick_push (t2);
4991 args->quick_push (t1);
4992 args->quick_push (val);
4993 if (ws_args)
4994 args->splice (*ws_args);
acf0174b 4995 args->quick_push (flags);
3bb06db4
NF
4996
4997 t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
e79983f4 4998 builtin_decl_explicit (start_ix), args);
50674e96 4999
726a989a
RB
5000 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5001 false, GSI_CONTINUE_LINKING);
953ff289
DN
5002}
5003
9a771876
JJ
5004/* Insert a function call whose name is FUNC_NAME with the information from
5005 ENTRY_STMT into the basic_block BB. */
5006
5007static void
538dd0b7 5008expand_cilk_for_call (basic_block bb, gomp_parallel *entry_stmt,
9a771876
JJ
5009 vec <tree, va_gc> *ws_args)
5010{
5011 tree t, t1, t2;
5012 gimple_stmt_iterator gsi;
5013 vec <tree, va_gc> *args;
5014
5015 gcc_assert (vec_safe_length (ws_args) == 2);
5016 tree func_name = (*ws_args)[0];
5017 tree grain = (*ws_args)[1];
5018
5019 tree clauses = gimple_omp_parallel_clauses (entry_stmt);
5020 tree count = find_omp_clause (clauses, OMP_CLAUSE__CILK_FOR_COUNT_);
5021 gcc_assert (count != NULL_TREE);
5022 count = OMP_CLAUSE_OPERAND (count, 0);
5023
5024 gsi = gsi_last_bb (bb);
5025 t = gimple_omp_parallel_data_arg (entry_stmt);
5026 if (t == NULL)
5027 t1 = null_pointer_node;
5028 else
5029 t1 = build_fold_addr_expr (t);
5030 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
5031
5032 vec_alloc (args, 4);
5033 args->quick_push (t2);
5034 args->quick_push (t1);
5035 args->quick_push (count);
5036 args->quick_push (grain);
5037 t = build_call_expr_loc_vec (UNKNOWN_LOCATION, func_name, args);
5038
5039 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, false,
5040 GSI_CONTINUE_LINKING);
5041}
50674e96 5042
a68ab351
JJ
5043/* Build the function call to GOMP_task to actually
5044 generate the task operation. BB is the block where to insert the code. */
5045
5046static void
538dd0b7 5047expand_task_call (basic_block bb, gomp_task *entry_stmt)
a68ab351 5048{
acf0174b 5049 tree t, t1, t2, t3, flags, cond, c, c2, clauses, depend;
726a989a 5050 gimple_stmt_iterator gsi;
db3927fb 5051 location_t loc = gimple_location (entry_stmt);
a68ab351 5052
726a989a 5053 clauses = gimple_omp_task_clauses (entry_stmt);
a68ab351 5054
a68ab351
JJ
5055 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
5056 if (c)
5057 cond = gimple_boolify (OMP_CLAUSE_IF_EXPR (c));
5058 else
5059 cond = boolean_true_node;
5060
5061 c = find_omp_clause (clauses, OMP_CLAUSE_UNTIED);
20906c66 5062 c2 = find_omp_clause (clauses, OMP_CLAUSE_MERGEABLE);
acf0174b 5063 depend = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
20906c66 5064 flags = build_int_cst (unsigned_type_node,
acf0174b 5065 (c ? 1 : 0) + (c2 ? 4 : 0) + (depend ? 8 : 0));
20906c66
JJ
5066
5067 c = find_omp_clause (clauses, OMP_CLAUSE_FINAL);
5068 if (c)
5069 {
5070 c = gimple_boolify (OMP_CLAUSE_FINAL_EXPR (c));
5071 c = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, c,
5072 build_int_cst (unsigned_type_node, 2),
5073 build_int_cst (unsigned_type_node, 0));
5074 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node, flags, c);
5075 }
acf0174b
JJ
5076 if (depend)
5077 depend = OMP_CLAUSE_DECL (depend);
5078 else
5079 depend = build_int_cst (ptr_type_node, 0);
a68ab351 5080
726a989a
RB
5081 gsi = gsi_last_bb (bb);
5082 t = gimple_omp_task_data_arg (entry_stmt);
a68ab351
JJ
5083 if (t == NULL)
5084 t2 = null_pointer_node;
5085 else
db3927fb
AH
5086 t2 = build_fold_addr_expr_loc (loc, t);
5087 t1 = build_fold_addr_expr_loc (loc, gimple_omp_task_child_fn (entry_stmt));
726a989a 5088 t = gimple_omp_task_copy_fn (entry_stmt);
a68ab351
JJ
5089 if (t == NULL)
5090 t3 = null_pointer_node;
5091 else
db3927fb 5092 t3 = build_fold_addr_expr_loc (loc, t);
a68ab351 5093
e79983f4 5094 t = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK),
acf0174b 5095 8, t1, t2, t3,
726a989a 5096 gimple_omp_task_arg_size (entry_stmt),
acf0174b
JJ
5097 gimple_omp_task_arg_align (entry_stmt), cond, flags,
5098 depend);
a68ab351 5099
726a989a
RB
5100 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5101 false, GSI_CONTINUE_LINKING);
a68ab351
JJ
5102}
5103
5104
726a989a
RB
5105/* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
5106 catch handler and return it. This prevents programs from violating the
5107 structured block semantics with throws. */
953ff289 5108
726a989a
RB
5109static gimple_seq
5110maybe_catch_exception (gimple_seq body)
953ff289 5111{
1d65f45c
RH
5112 gimple g;
5113 tree decl;
953ff289
DN
5114
5115 if (!flag_exceptions)
726a989a 5116 return body;
953ff289 5117
3b06d379
SB
5118 if (lang_hooks.eh_protect_cleanup_actions != NULL)
5119 decl = lang_hooks.eh_protect_cleanup_actions ();
953ff289 5120 else
e79983f4 5121 decl = builtin_decl_explicit (BUILT_IN_TRAP);
726a989a 5122
1d65f45c
RH
5123 g = gimple_build_eh_must_not_throw (decl);
5124 g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g),
726a989a 5125 GIMPLE_TRY_CATCH);
953ff289 5126
1d65f45c 5127 return gimple_seq_alloc_with_stmt (g);
953ff289
DN
5128}
5129
50674e96 5130/* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
953ff289 5131
50674e96 5132static tree
9771b263 5133vec2chain (vec<tree, va_gc> *v)
953ff289 5134{
c021f10b
NF
5135 tree chain = NULL_TREE, t;
5136 unsigned ix;
953ff289 5137
9771b263 5138 FOR_EACH_VEC_SAFE_ELT_REVERSE (v, ix, t)
50674e96 5139 {
910ad8de 5140 DECL_CHAIN (t) = chain;
c021f10b 5141 chain = t;
50674e96 5142 }
953ff289 5143
c021f10b 5144 return chain;
50674e96 5145}
953ff289 5146
953ff289 5147
50674e96 5148/* Remove barriers in REGION->EXIT's block. Note that this is only
726a989a
RB
5149 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
5150 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
5151 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
50674e96 5152 removed. */
953ff289 5153
50674e96
DN
5154static void
5155remove_exit_barrier (struct omp_region *region)
5156{
726a989a 5157 gimple_stmt_iterator gsi;
50674e96 5158 basic_block exit_bb;
777f7f9a
RH
5159 edge_iterator ei;
5160 edge e;
726a989a 5161 gimple stmt;
03742a9b 5162 int any_addressable_vars = -1;
953ff289 5163
777f7f9a 5164 exit_bb = region->exit;
953ff289 5165
2aee3e57
JJ
5166 /* If the parallel region doesn't return, we don't have REGION->EXIT
5167 block at all. */
5168 if (! exit_bb)
5169 return;
5170
726a989a
RB
5171 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
5172 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
777f7f9a
RH
5173 statements that can appear in between are extremely limited -- no
5174 memory operations at all. Here, we allow nothing at all, so the
726a989a
RB
5175 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
5176 gsi = gsi_last_bb (exit_bb);
5177 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
5178 gsi_prev (&gsi);
5179 if (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
50674e96 5180 return;
953ff289 5181
777f7f9a
RH
5182 FOR_EACH_EDGE (e, ei, exit_bb->preds)
5183 {
726a989a
RB
5184 gsi = gsi_last_bb (e->src);
5185 if (gsi_end_p (gsi))
777f7f9a 5186 continue;
726a989a 5187 stmt = gsi_stmt (gsi);
03742a9b
JJ
5188 if (gimple_code (stmt) == GIMPLE_OMP_RETURN
5189 && !gimple_omp_return_nowait_p (stmt))
5190 {
5191 /* OpenMP 3.0 tasks unfortunately prevent this optimization
5192 in many cases. If there could be tasks queued, the barrier
5193 might be needed to let the tasks run before some local
5194 variable of the parallel that the task uses as shared
5195 runs out of scope. The task can be spawned either
5196 from within current function (this would be easy to check)
5197 or from some function it calls and gets passed an address
5198 of such a variable. */
5199 if (any_addressable_vars < 0)
5200 {
538dd0b7
DM
5201 gomp_parallel *parallel_stmt
5202 = as_a <gomp_parallel *> (last_stmt (region->entry));
03742a9b 5203 tree child_fun = gimple_omp_parallel_child_fn (parallel_stmt);
c021f10b
NF
5204 tree local_decls, block, decl;
5205 unsigned ix;
03742a9b
JJ
5206
5207 any_addressable_vars = 0;
c021f10b
NF
5208 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun), ix, decl)
5209 if (TREE_ADDRESSABLE (decl))
03742a9b
JJ
5210 {
5211 any_addressable_vars = 1;
5212 break;
5213 }
5214 for (block = gimple_block (stmt);
5215 !any_addressable_vars
5216 && block
5217 && TREE_CODE (block) == BLOCK;
5218 block = BLOCK_SUPERCONTEXT (block))
5219 {
5220 for (local_decls = BLOCK_VARS (block);
5221 local_decls;
910ad8de 5222 local_decls = DECL_CHAIN (local_decls))
03742a9b
JJ
5223 if (TREE_ADDRESSABLE (local_decls))
5224 {
5225 any_addressable_vars = 1;
5226 break;
5227 }
5228 if (block == gimple_block (parallel_stmt))
5229 break;
5230 }
5231 }
5232 if (!any_addressable_vars)
5233 gimple_omp_return_set_nowait (stmt);
5234 }
777f7f9a 5235 }
953ff289
DN
5236}
5237
777f7f9a
RH
5238static void
5239remove_exit_barriers (struct omp_region *region)
5240{
726a989a 5241 if (region->type == GIMPLE_OMP_PARALLEL)
777f7f9a
RH
5242 remove_exit_barrier (region);
5243
5244 if (region->inner)
5245 {
5246 region = region->inner;
5247 remove_exit_barriers (region);
5248 while (region->next)
5249 {
5250 region = region->next;
5251 remove_exit_barriers (region);
5252 }
5253 }
5254}
50674e96 5255
2b4cf991
JJ
5256/* Optimize omp_get_thread_num () and omp_get_num_threads ()
5257 calls. These can't be declared as const functions, but
5258 within one parallel body they are constant, so they can be
5259 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
a68ab351
JJ
5260 which are declared const. Similarly for task body, except
5261 that in untied task omp_get_thread_num () can change at any task
5262 scheduling point. */
2b4cf991
JJ
5263
5264static void
726a989a 5265optimize_omp_library_calls (gimple entry_stmt)
2b4cf991
JJ
5266{
5267 basic_block bb;
726a989a 5268 gimple_stmt_iterator gsi;
e79983f4
MM
5269 tree thr_num_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
5270 tree thr_num_id = DECL_ASSEMBLER_NAME (thr_num_tree);
5271 tree num_thr_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
5272 tree num_thr_id = DECL_ASSEMBLER_NAME (num_thr_tree);
726a989a
RB
5273 bool untied_task = (gimple_code (entry_stmt) == GIMPLE_OMP_TASK
5274 && find_omp_clause (gimple_omp_task_clauses (entry_stmt),
a68ab351 5275 OMP_CLAUSE_UNTIED) != NULL);
2b4cf991 5276
11cd3bed 5277 FOR_EACH_BB_FN (bb, cfun)
726a989a 5278 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
2b4cf991 5279 {
726a989a 5280 gimple call = gsi_stmt (gsi);
2b4cf991
JJ
5281 tree decl;
5282
726a989a
RB
5283 if (is_gimple_call (call)
5284 && (decl = gimple_call_fndecl (call))
2b4cf991
JJ
5285 && DECL_EXTERNAL (decl)
5286 && TREE_PUBLIC (decl)
5287 && DECL_INITIAL (decl) == NULL)
5288 {
5289 tree built_in;
5290
5291 if (DECL_NAME (decl) == thr_num_id)
a68ab351
JJ
5292 {
5293 /* In #pragma omp task untied omp_get_thread_num () can change
5294 during the execution of the task region. */
5295 if (untied_task)
5296 continue;
e79983f4 5297 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
a68ab351 5298 }
2b4cf991 5299 else if (DECL_NAME (decl) == num_thr_id)
e79983f4 5300 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
2b4cf991
JJ
5301 else
5302 continue;
5303
5304 if (DECL_ASSEMBLER_NAME (decl) != DECL_ASSEMBLER_NAME (built_in)
726a989a 5305 || gimple_call_num_args (call) != 0)
2b4cf991
JJ
5306 continue;
5307
5308 if (flag_exceptions && !TREE_NOTHROW (decl))
5309 continue;
5310
5311 if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
9600efe1
MM
5312 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl)),
5313 TREE_TYPE (TREE_TYPE (built_in))))
2b4cf991
JJ
5314 continue;
5315
7c9577be 5316 gimple_call_set_fndecl (call, built_in);
2b4cf991
JJ
5317 }
5318 }
5319}
5320
5a0f4dd3
JJ
5321/* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
5322 regimplified. */
5323
5324static tree
5325expand_omp_regimplify_p (tree *tp, int *walk_subtrees, void *)
5326{
5327 tree t = *tp;
5328
5329 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
5330 if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t))
5331 return t;
5332
5333 if (TREE_CODE (t) == ADDR_EXPR)
5334 recompute_tree_invariant_for_addr_expr (t);
5335
5336 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
5337 return NULL_TREE;
5338}
5339
74bf76ed
JJ
5340/* Prepend TO = FROM assignment before *GSI_P. */
5341
5342static void
5343expand_omp_build_assign (gimple_stmt_iterator *gsi_p, tree to, tree from)
5344{
5345 bool simple_p = DECL_P (to) && TREE_ADDRESSABLE (to);
5346 from = force_gimple_operand_gsi (gsi_p, from, simple_p, NULL_TREE,
5347 true, GSI_SAME_STMT);
5348 gimple stmt = gimple_build_assign (to, from);
5349 gsi_insert_before (gsi_p, stmt, GSI_SAME_STMT);
5350 if (walk_tree (&from, expand_omp_regimplify_p, NULL, NULL)
5351 || walk_tree (&to, expand_omp_regimplify_p, NULL, NULL))
5352 {
5353 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
5354 gimple_regimplify_operands (stmt, &gsi);
5355 }
5356}
5357
a68ab351 5358/* Expand the OpenMP parallel or task directive starting at REGION. */
953ff289
DN
5359
5360static void
a68ab351 5361expand_omp_taskreg (struct omp_region *region)
953ff289 5362{
50674e96 5363 basic_block entry_bb, exit_bb, new_bb;
db2960f4 5364 struct function *child_cfun;
3bb06db4 5365 tree child_fn, block, t;
726a989a
RB
5366 gimple_stmt_iterator gsi;
5367 gimple entry_stmt, stmt;
50674e96 5368 edge e;
9771b263 5369 vec<tree, va_gc> *ws_args;
50674e96 5370
777f7f9a 5371 entry_stmt = last_stmt (region->entry);
726a989a 5372 child_fn = gimple_omp_taskreg_child_fn (entry_stmt);
50674e96 5373 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
50674e96 5374
777f7f9a
RH
5375 entry_bb = region->entry;
5376 exit_bb = region->exit;
50674e96 5377
9a771876
JJ
5378 bool is_cilk_for
5379 = (flag_cilkplus
5380 && gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL
5381 && find_omp_clause (gimple_omp_parallel_clauses (entry_stmt),
5382 OMP_CLAUSE__CILK_FOR_COUNT_) != NULL_TREE);
5383
5384 if (is_cilk_for)
5385 /* If it is a _Cilk_for statement, it is modelled *like* a parallel for,
5386 and the inner statement contains the name of the built-in function
5387 and grain. */
5388 ws_args = region->inner->ws_args;
5389 else if (is_combined_parallel (region))
777f7f9a 5390 ws_args = region->ws_args;
50674e96 5391 else
3bb06db4 5392 ws_args = NULL;
953ff289 5393
777f7f9a 5394 if (child_cfun->cfg)
953ff289 5395 {
50674e96
DN
5396 /* Due to inlining, it may happen that we have already outlined
5397 the region, in which case all we need to do is make the
5398 sub-graph unreachable and emit the parallel call. */
5399 edge entry_succ_e, exit_succ_e;
50674e96
DN
5400
5401 entry_succ_e = single_succ_edge (entry_bb);
50674e96 5402
726a989a
RB
5403 gsi = gsi_last_bb (entry_bb);
5404 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_PARALLEL
5405 || gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_TASK);
5406 gsi_remove (&gsi, true);
50674e96
DN
5407
5408 new_bb = entry_bb;
d3c673c7
JJ
5409 if (exit_bb)
5410 {
5411 exit_succ_e = single_succ_edge (exit_bb);
5412 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
5413 }
917948d3 5414 remove_edge_and_dominated_blocks (entry_succ_e);
953ff289 5415 }
50674e96
DN
5416 else
5417 {
2fed2012 5418 unsigned srcidx, dstidx, num;
c021f10b 5419
50674e96 5420 /* If the parallel region needs data sent from the parent
b570947c
JJ
5421 function, then the very first statement (except possible
5422 tree profile counter updates) of the parallel body
50674e96
DN
5423 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
5424 &.OMP_DATA_O is passed as an argument to the child function,
5425 we need to replace it with the argument as seen by the child
5426 function.
5427
5428 In most cases, this will end up being the identity assignment
5429 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
5430 a function call that has been inlined, the original PARM_DECL
5431 .OMP_DATA_I may have been converted into a different local
5432 variable. In which case, we need to keep the assignment. */
726a989a 5433 if (gimple_omp_taskreg_data_arg (entry_stmt))
50674e96
DN
5434 {
5435 basic_block entry_succ_bb = single_succ (entry_bb);
726a989a
RB
5436 tree arg, narg;
5437 gimple parcopy_stmt = NULL;
953ff289 5438
726a989a 5439 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
b570947c 5440 {
726a989a 5441 gimple stmt;
b570947c 5442
726a989a
RB
5443 gcc_assert (!gsi_end_p (gsi));
5444 stmt = gsi_stmt (gsi);
5445 if (gimple_code (stmt) != GIMPLE_ASSIGN)
018b899b
JJ
5446 continue;
5447
726a989a 5448 if (gimple_num_ops (stmt) == 2)
b570947c 5449 {
726a989a
RB
5450 tree arg = gimple_assign_rhs1 (stmt);
5451
5452 /* We're ignore the subcode because we're
5453 effectively doing a STRIP_NOPS. */
5454
5455 if (TREE_CODE (arg) == ADDR_EXPR
5456 && TREE_OPERAND (arg, 0)
5457 == gimple_omp_taskreg_data_arg (entry_stmt))
5458 {
5459 parcopy_stmt = stmt;
5460 break;
5461 }
b570947c
JJ
5462 }
5463 }
917948d3 5464
726a989a 5465 gcc_assert (parcopy_stmt != NULL);
917948d3
ZD
5466 arg = DECL_ARGUMENTS (child_fn);
5467
5468 if (!gimple_in_ssa_p (cfun))
5469 {
726a989a
RB
5470 if (gimple_assign_lhs (parcopy_stmt) == arg)
5471 gsi_remove (&gsi, true);
917948d3 5472 else
726a989a
RB
5473 {
5474 /* ?? Is setting the subcode really necessary ?? */
5475 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (arg));
5476 gimple_assign_set_rhs1 (parcopy_stmt, arg);
5477 }
917948d3
ZD
5478 }
5479 else
5480 {
5481 /* If we are in ssa form, we must load the value from the default
5482 definition of the argument. That should not be defined now,
5483 since the argument is not used uninitialized. */
32244553 5484 gcc_assert (ssa_default_def (cfun, arg) == NULL);
726a989a 5485 narg = make_ssa_name (arg, gimple_build_nop ());
32244553 5486 set_ssa_default_def (cfun, arg, narg);
726a989a
RB
5487 /* ?? Is setting the subcode really necessary ?? */
5488 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (narg));
5489 gimple_assign_set_rhs1 (parcopy_stmt, narg);
917948d3
ZD
5490 update_stmt (parcopy_stmt);
5491 }
50674e96
DN
5492 }
5493
5494 /* Declare local variables needed in CHILD_CFUN. */
5495 block = DECL_INITIAL (child_fn);
c021f10b 5496 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
4f0ae266
JJ
5497 /* The gimplifier could record temporaries in parallel/task block
5498 rather than in containing function's local_decls chain,
5499 which would mean cgraph missed finalizing them. Do it now. */
910ad8de 5500 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
4f0ae266
JJ
5501 if (TREE_CODE (t) == VAR_DECL
5502 && TREE_STATIC (t)
5503 && !DECL_EXTERNAL (t))
9041d2e6 5504 varpool_node::finalize_decl (t);
726a989a 5505 DECL_SAVED_TREE (child_fn) = NULL;
355a7673
MM
5506 /* We'll create a CFG for child_fn, so no gimple body is needed. */
5507 gimple_set_body (child_fn, NULL);
b357f682 5508 TREE_USED (block) = 1;
50674e96 5509
917948d3 5510 /* Reset DECL_CONTEXT on function arguments. */
910ad8de 5511 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
50674e96
DN
5512 DECL_CONTEXT (t) = child_fn;
5513
726a989a
RB
5514 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
5515 so that it can be moved to the child function. */
5516 gsi = gsi_last_bb (entry_bb);
5517 stmt = gsi_stmt (gsi);
5518 gcc_assert (stmt && (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
5519 || gimple_code (stmt) == GIMPLE_OMP_TASK));
726a989a 5520 e = split_block (entry_bb, stmt);
b13c907a 5521 gsi_remove (&gsi, true);
50674e96
DN
5522 entry_bb = e->dest;
5523 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
5524
726a989a 5525 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
2aee3e57
JJ
5526 if (exit_bb)
5527 {
726a989a
RB
5528 gsi = gsi_last_bb (exit_bb);
5529 gcc_assert (!gsi_end_p (gsi)
5530 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
5531 stmt = gimple_build_return (NULL);
5532 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
5533 gsi_remove (&gsi, true);
2aee3e57 5534 }
917948d3
ZD
5535
5536 /* Move the parallel region into CHILD_CFUN. */
b8698a0f 5537
917948d3
ZD
5538 if (gimple_in_ssa_p (cfun))
5539 {
5db9ba0c 5540 init_tree_ssa (child_cfun);
3828719a
RG
5541 init_ssa_operands (child_cfun);
5542 child_cfun->gimple_df->in_ssa_p = true;
b357f682 5543 block = NULL_TREE;
917948d3 5544 }
b357f682 5545 else
726a989a 5546 block = gimple_block (entry_stmt);
b357f682
JJ
5547
5548 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
917948d3
ZD
5549 if (exit_bb)
5550 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
6093bc06
RB
5551 /* When the OMP expansion process cannot guarantee an up-to-date
5552 loop tree arrange for the child function to fixup loops. */
5553 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
5554 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
917948d3 5555
b357f682 5556 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
9771b263 5557 num = vec_safe_length (child_cfun->local_decls);
2fed2012
JJ
5558 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
5559 {
9771b263 5560 t = (*child_cfun->local_decls)[srcidx];
2fed2012
JJ
5561 if (DECL_CONTEXT (t) == cfun->decl)
5562 continue;
5563 if (srcidx != dstidx)
9771b263 5564 (*child_cfun->local_decls)[dstidx] = t;
2fed2012
JJ
5565 dstidx++;
5566 }
5567 if (dstidx != num)
9771b263 5568 vec_safe_truncate (child_cfun->local_decls, dstidx);
b357f682 5569
917948d3 5570 /* Inform the callgraph about the new function. */
d7ed20db 5571 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
d52f5295 5572 cgraph_node::add_new_function (child_fn, true);
a79b7ec5 5573 cgraph_node::get (child_fn)->parallelized_function = 1;
917948d3
ZD
5574
5575 /* Fix the callgraph edges for child_cfun. Those for cfun will be
5576 fixed in a following pass. */
5577 push_cfun (child_cfun);
2b4cf991 5578 if (optimize)
a68ab351 5579 optimize_omp_library_calls (entry_stmt);
3dafb85c 5580 cgraph_edge::rebuild_edges ();
99819c63
JJ
5581
5582 /* Some EH regions might become dead, see PR34608. If
5583 pass_cleanup_cfg isn't the first pass to happen with the
5584 new child, these dead EH edges might cause problems.
5585 Clean them up now. */
5586 if (flag_exceptions)
5587 {
5588 basic_block bb;
99819c63
JJ
5589 bool changed = false;
5590
11cd3bed 5591 FOR_EACH_BB_FN (bb, cfun)
726a989a 5592 changed |= gimple_purge_dead_eh_edges (bb);
99819c63
JJ
5593 if (changed)
5594 cleanup_tree_cfg ();
99819c63 5595 }
5006671f
RG
5596 if (gimple_in_ssa_p (cfun))
5597 update_ssa (TODO_update_ssa);
917948d3 5598 pop_cfun ();
50674e96 5599 }
b8698a0f 5600
50674e96 5601 /* Emit a library call to launch the children threads. */
9a771876 5602 if (is_cilk_for)
538dd0b7
DM
5603 expand_cilk_for_call (new_bb,
5604 as_a <gomp_parallel *> (entry_stmt), ws_args);
9a771876 5605 else if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
538dd0b7
DM
5606 expand_parallel_call (region, new_bb,
5607 as_a <gomp_parallel *> (entry_stmt), ws_args);
a68ab351 5608 else
538dd0b7 5609 expand_task_call (new_bb, as_a <gomp_task *> (entry_stmt));
a5efada7
RG
5610 if (gimple_in_ssa_p (cfun))
5611 update_ssa (TODO_update_ssa_only_virtuals);
953ff289
DN
5612}
5613
50674e96 5614
74bf76ed
JJ
5615/* Helper function for expand_omp_{for_*,simd}. If this is the outermost
5616 of the combined collapse > 1 loop constructs, generate code like:
5617 if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
5618 if (cond3 is <)
5619 adj = STEP3 - 1;
5620 else
5621 adj = STEP3 + 1;
5622 count3 = (adj + N32 - N31) / STEP3;
5623 if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
5624 if (cond2 is <)
5625 adj = STEP2 - 1;
5626 else
5627 adj = STEP2 + 1;
5628 count2 = (adj + N22 - N21) / STEP2;
5629 if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
5630 if (cond1 is <)
5631 adj = STEP1 - 1;
5632 else
5633 adj = STEP1 + 1;
5634 count1 = (adj + N12 - N11) / STEP1;
5635 count = count1 * count2 * count3;
5636 Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
5637 count = 0;
acf0174b
JJ
5638 and set ZERO_ITER_BB to that bb. If this isn't the outermost
5639 of the combined loop constructs, just initialize COUNTS array
5640 from the _looptemp_ clauses. */
74bf76ed
JJ
5641
5642/* NOTE: It *could* be better to moosh all of the BBs together,
5643 creating one larger BB with all the computation and the unexpected
5644 jump at the end. I.e.
5645
5646 bool zero3, zero2, zero1, zero;
5647
5648 zero3 = N32 c3 N31;
5649 count3 = (N32 - N31) /[cl] STEP3;
5650 zero2 = N22 c2 N21;
5651 count2 = (N22 - N21) /[cl] STEP2;
5652 zero1 = N12 c1 N11;
5653 count1 = (N12 - N11) /[cl] STEP1;
5654 zero = zero3 || zero2 || zero1;
5655 count = count1 * count2 * count3;
5656 if (__builtin_expect(zero, false)) goto zero_iter_bb;
5657
5658 After all, we expect the zero=false, and thus we expect to have to
5659 evaluate all of the comparison expressions, so short-circuiting
5660 oughtn't be a win. Since the condition isn't protecting a
5661 denominator, we're not concerned about divide-by-zero, so we can
5662 fully evaluate count even if a numerator turned out to be wrong.
5663
5664 It seems like putting this all together would create much better
5665 scheduling opportunities, and less pressure on the chip's branch
5666 predictor. */
5667
5668static void
5669expand_omp_for_init_counts (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
5670 basic_block &entry_bb, tree *counts,
5671 basic_block &zero_iter_bb, int &first_zero_iter,
5672 basic_block &l2_dom_bb)
5673{
5674 tree t, type = TREE_TYPE (fd->loop.v);
74bf76ed
JJ
5675 edge e, ne;
5676 int i;
5677
5678 /* Collapsed loops need work for expansion into SSA form. */
5679 gcc_assert (!gimple_in_ssa_p (cfun));
5680
acf0174b
JJ
5681 if (gimple_omp_for_combined_into_p (fd->for_stmt)
5682 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
5683 {
5684 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5685 isn't supposed to be handled, as the inner loop doesn't
5686 use it. */
5687 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
5688 OMP_CLAUSE__LOOPTEMP_);
5689 gcc_assert (innerc);
5690 for (i = 0; i < fd->collapse; i++)
5691 {
5692 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5693 OMP_CLAUSE__LOOPTEMP_);
5694 gcc_assert (innerc);
5695 if (i)
5696 counts[i] = OMP_CLAUSE_DECL (innerc);
5697 else
5698 counts[0] = NULL_TREE;
5699 }
5700 return;
5701 }
5702
74bf76ed
JJ
5703 for (i = 0; i < fd->collapse; i++)
5704 {
5705 tree itype = TREE_TYPE (fd->loops[i].v);
5706
5707 if (SSA_VAR_P (fd->loop.n2)
5708 && ((t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
5709 fold_convert (itype, fd->loops[i].n1),
5710 fold_convert (itype, fd->loops[i].n2)))
5711 == NULL_TREE || !integer_onep (t)))
5712 {
538dd0b7 5713 gcond *cond_stmt;
74bf76ed
JJ
5714 tree n1, n2;
5715 n1 = fold_convert (itype, unshare_expr (fd->loops[i].n1));
5716 n1 = force_gimple_operand_gsi (gsi, n1, true, NULL_TREE,
5717 true, GSI_SAME_STMT);
5718 n2 = fold_convert (itype, unshare_expr (fd->loops[i].n2));
5719 n2 = force_gimple_operand_gsi (gsi, n2, true, NULL_TREE,
5720 true, GSI_SAME_STMT);
538dd0b7
DM
5721 cond_stmt = gimple_build_cond (fd->loops[i].cond_code, n1, n2,
5722 NULL_TREE, NULL_TREE);
5723 gsi_insert_before (gsi, cond_stmt, GSI_SAME_STMT);
5724 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
74bf76ed 5725 expand_omp_regimplify_p, NULL, NULL)
538dd0b7 5726 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
74bf76ed
JJ
5727 expand_omp_regimplify_p, NULL, NULL))
5728 {
538dd0b7
DM
5729 *gsi = gsi_for_stmt (cond_stmt);
5730 gimple_regimplify_operands (cond_stmt, gsi);
74bf76ed 5731 }
538dd0b7 5732 e = split_block (entry_bb, cond_stmt);
74bf76ed
JJ
5733 if (zero_iter_bb == NULL)
5734 {
538dd0b7 5735 gassign *assign_stmt;
74bf76ed
JJ
5736 first_zero_iter = i;
5737 zero_iter_bb = create_empty_bb (entry_bb);
726338f4 5738 add_bb_to_loop (zero_iter_bb, entry_bb->loop_father);
74bf76ed 5739 *gsi = gsi_after_labels (zero_iter_bb);
538dd0b7
DM
5740 assign_stmt = gimple_build_assign (fd->loop.n2,
5741 build_zero_cst (type));
5742 gsi_insert_before (gsi, assign_stmt, GSI_SAME_STMT);
74bf76ed
JJ
5743 set_immediate_dominator (CDI_DOMINATORS, zero_iter_bb,
5744 entry_bb);
5745 }
5746 ne = make_edge (entry_bb, zero_iter_bb, EDGE_FALSE_VALUE);
5747 ne->probability = REG_BR_PROB_BASE / 2000 - 1;
5748 e->flags = EDGE_TRUE_VALUE;
5749 e->probability = REG_BR_PROB_BASE - ne->probability;
5750 if (l2_dom_bb == NULL)
5751 l2_dom_bb = entry_bb;
5752 entry_bb = e->dest;
5753 *gsi = gsi_last_bb (entry_bb);
5754 }
5755
5756 if (POINTER_TYPE_P (itype))
5757 itype = signed_type_for (itype);
5758 t = build_int_cst (itype, (fd->loops[i].cond_code == LT_EXPR
5759 ? -1 : 1));
5760 t = fold_build2 (PLUS_EXPR, itype,
5761 fold_convert (itype, fd->loops[i].step), t);
5762 t = fold_build2 (PLUS_EXPR, itype, t,
5763 fold_convert (itype, fd->loops[i].n2));
5764 t = fold_build2 (MINUS_EXPR, itype, t,
5765 fold_convert (itype, fd->loops[i].n1));
5766 /* ?? We could probably use CEIL_DIV_EXPR instead of
5767 TRUNC_DIV_EXPR and adjusting by hand. Unless we can't
5768 generate the same code in the end because generically we
5769 don't know that the values involved must be negative for
5770 GT?? */
5771 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
5772 t = fold_build2 (TRUNC_DIV_EXPR, itype,
5773 fold_build1 (NEGATE_EXPR, itype, t),
5774 fold_build1 (NEGATE_EXPR, itype,
5775 fold_convert (itype,
5776 fd->loops[i].step)));
5777 else
5778 t = fold_build2 (TRUNC_DIV_EXPR, itype, t,
5779 fold_convert (itype, fd->loops[i].step));
5780 t = fold_convert (type, t);
5781 if (TREE_CODE (t) == INTEGER_CST)
5782 counts[i] = t;
5783 else
5784 {
5785 counts[i] = create_tmp_reg (type, ".count");
5786 expand_omp_build_assign (gsi, counts[i], t);
5787 }
5788 if (SSA_VAR_P (fd->loop.n2))
5789 {
5790 if (i == 0)
5791 t = counts[0];
5792 else
5793 t = fold_build2 (MULT_EXPR, type, fd->loop.n2, counts[i]);
5794 expand_omp_build_assign (gsi, fd->loop.n2, t);
5795 }
5796 }
5797}
5798
5799
5800/* Helper function for expand_omp_{for_*,simd}. Generate code like:
5801 T = V;
5802 V3 = N31 + (T % count3) * STEP3;
5803 T = T / count3;
5804 V2 = N21 + (T % count2) * STEP2;
5805 T = T / count2;
5806 V1 = N11 + T * STEP1;
acf0174b
JJ
5807 if this loop doesn't have an inner loop construct combined with it.
5808 If it does have an inner loop construct combined with it and the
5809 iteration count isn't known constant, store values from counts array
5810 into its _looptemp_ temporaries instead. */
74bf76ed
JJ
5811
5812static void
5813expand_omp_for_init_vars (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
acf0174b 5814 tree *counts, gimple inner_stmt, tree startvar)
74bf76ed
JJ
5815{
5816 int i;
acf0174b
JJ
5817 if (gimple_omp_for_combined_p (fd->for_stmt))
5818 {
5819 /* If fd->loop.n2 is constant, then no propagation of the counts
5820 is needed, they are constant. */
5821 if (TREE_CODE (fd->loop.n2) == INTEGER_CST)
5822 return;
5823
5824 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
5825 ? gimple_omp_parallel_clauses (inner_stmt)
5826 : gimple_omp_for_clauses (inner_stmt);
5827 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5828 isn't supposed to be handled, as the inner loop doesn't
5829 use it. */
5830 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
5831 gcc_assert (innerc);
5832 for (i = 0; i < fd->collapse; i++)
5833 {
5834 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5835 OMP_CLAUSE__LOOPTEMP_);
5836 gcc_assert (innerc);
5837 if (i)
5838 {
5839 tree tem = OMP_CLAUSE_DECL (innerc);
5840 tree t = fold_convert (TREE_TYPE (tem), counts[i]);
5841 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5842 false, GSI_CONTINUE_LINKING);
538dd0b7 5843 gassign *stmt = gimple_build_assign (tem, t);
acf0174b
JJ
5844 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5845 }
5846 }
5847 return;
5848 }
5849
74bf76ed
JJ
5850 tree type = TREE_TYPE (fd->loop.v);
5851 tree tem = create_tmp_reg (type, ".tem");
538dd0b7 5852 gassign *stmt = gimple_build_assign (tem, startvar);
74bf76ed
JJ
5853 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5854
5855 for (i = fd->collapse - 1; i >= 0; i--)
5856 {
5857 tree vtype = TREE_TYPE (fd->loops[i].v), itype, t;
5858 itype = vtype;
5859 if (POINTER_TYPE_P (vtype))
5860 itype = signed_type_for (vtype);
5861 if (i != 0)
5862 t = fold_build2 (TRUNC_MOD_EXPR, type, tem, counts[i]);
5863 else
5864 t = tem;
5865 t = fold_convert (itype, t);
5866 t = fold_build2 (MULT_EXPR, itype, t,
5867 fold_convert (itype, fd->loops[i].step));
5868 if (POINTER_TYPE_P (vtype))
5869 t = fold_build_pointer_plus (fd->loops[i].n1, t);
5870 else
5871 t = fold_build2 (PLUS_EXPR, itype, fd->loops[i].n1, t);
5872 t = force_gimple_operand_gsi (gsi, t,
5873 DECL_P (fd->loops[i].v)
5874 && TREE_ADDRESSABLE (fd->loops[i].v),
5875 NULL_TREE, false,
5876 GSI_CONTINUE_LINKING);
5877 stmt = gimple_build_assign (fd->loops[i].v, t);
5878 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5879 if (i != 0)
5880 {
5881 t = fold_build2 (TRUNC_DIV_EXPR, type, tem, counts[i]);
5882 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5883 false, GSI_CONTINUE_LINKING);
5884 stmt = gimple_build_assign (tem, t);
5885 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5886 }
5887 }
5888}
5889
5890
5891/* Helper function for expand_omp_for_*. Generate code like:
5892 L10:
5893 V3 += STEP3;
5894 if (V3 cond3 N32) goto BODY_BB; else goto L11;
5895 L11:
5896 V3 = N31;
5897 V2 += STEP2;
5898 if (V2 cond2 N22) goto BODY_BB; else goto L12;
5899 L12:
5900 V2 = N21;
5901 V1 += STEP1;
5902 goto BODY_BB; */
5903
5904static basic_block
5905extract_omp_for_update_vars (struct omp_for_data *fd, basic_block cont_bb,
5906 basic_block body_bb)
5907{
5908 basic_block last_bb, bb, collapse_bb = NULL;
5909 int i;
5910 gimple_stmt_iterator gsi;
5911 edge e;
5912 tree t;
5913 gimple stmt;
5914
5915 last_bb = cont_bb;
5916 for (i = fd->collapse - 1; i >= 0; i--)
5917 {
5918 tree vtype = TREE_TYPE (fd->loops[i].v);
5919
5920 bb = create_empty_bb (last_bb);
726338f4 5921 add_bb_to_loop (bb, last_bb->loop_father);
74bf76ed
JJ
5922 gsi = gsi_start_bb (bb);
5923
5924 if (i < fd->collapse - 1)
5925 {
5926 e = make_edge (last_bb, bb, EDGE_FALSE_VALUE);
5927 e->probability = REG_BR_PROB_BASE / 8;
5928
5929 t = fd->loops[i + 1].n1;
5930 t = force_gimple_operand_gsi (&gsi, t,
5931 DECL_P (fd->loops[i + 1].v)
5932 && TREE_ADDRESSABLE (fd->loops[i
5933 + 1].v),
5934 NULL_TREE, false,
5935 GSI_CONTINUE_LINKING);
5936 stmt = gimple_build_assign (fd->loops[i + 1].v, t);
5937 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5938 }
5939 else
5940 collapse_bb = bb;
5941
5942 set_immediate_dominator (CDI_DOMINATORS, bb, last_bb);
5943
5944 if (POINTER_TYPE_P (vtype))
5945 t = fold_build_pointer_plus (fd->loops[i].v, fd->loops[i].step);
5946 else
5947 t = fold_build2 (PLUS_EXPR, vtype, fd->loops[i].v, fd->loops[i].step);
5948 t = force_gimple_operand_gsi (&gsi, t,
5949 DECL_P (fd->loops[i].v)
5950 && TREE_ADDRESSABLE (fd->loops[i].v),
5951 NULL_TREE, false, GSI_CONTINUE_LINKING);
5952 stmt = gimple_build_assign (fd->loops[i].v, t);
5953 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5954
5955 if (i > 0)
5956 {
5957 t = fd->loops[i].n2;
5958 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5959 false, GSI_CONTINUE_LINKING);
5960 tree v = fd->loops[i].v;
5961 if (DECL_P (v) && TREE_ADDRESSABLE (v))
5962 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
5963 false, GSI_CONTINUE_LINKING);
5964 t = fold_build2 (fd->loops[i].cond_code, boolean_type_node, v, t);
5965 stmt = gimple_build_cond_empty (t);
5966 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5967 e = make_edge (bb, body_bb, EDGE_TRUE_VALUE);
5968 e->probability = REG_BR_PROB_BASE * 7 / 8;
5969 }
5970 else
5971 make_edge (bb, body_bb, EDGE_FALLTHRU);
5972 last_bb = bb;
5973 }
5974
5975 return collapse_bb;
5976}
5977
5978
50674e96 5979/* A subroutine of expand_omp_for. Generate code for a parallel
953ff289
DN
5980 loop with any schedule. Given parameters:
5981
5982 for (V = N1; V cond N2; V += STEP) BODY;
5983
5984 where COND is "<" or ">", we generate pseudocode
5985
5986 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
50674e96 5987 if (more) goto L0; else goto L3;
953ff289
DN
5988 L0:
5989 V = istart0;
5990 iend = iend0;
5991 L1:
5992 BODY;
5993 V += STEP;
50674e96 5994 if (V cond iend) goto L1; else goto L2;
953ff289 5995 L2:
50674e96
DN
5996 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
5997 L3:
953ff289 5998
50674e96 5999 If this is a combined omp parallel loop, instead of the call to
a68ab351 6000 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
acf0174b
JJ
6001 If this is gimple_omp_for_combined_p loop, then instead of assigning
6002 V and iend in L0 we assign the first two _looptemp_ clause decls of the
6003 inner GIMPLE_OMP_FOR and V += STEP; and
6004 if (V cond iend) goto L1; else goto L2; are removed.
a68ab351
JJ
6005
6006 For collapsed loops, given parameters:
6007 collapse(3)
6008 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
6009 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
6010 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
6011 BODY;
6012
6013 we generate pseudocode
6014
5a0f4dd3 6015 if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
a68ab351
JJ
6016 if (cond3 is <)
6017 adj = STEP3 - 1;
6018 else
6019 adj = STEP3 + 1;
6020 count3 = (adj + N32 - N31) / STEP3;
5a0f4dd3 6021 if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
a68ab351
JJ
6022 if (cond2 is <)
6023 adj = STEP2 - 1;
6024 else
6025 adj = STEP2 + 1;
6026 count2 = (adj + N22 - N21) / STEP2;
5a0f4dd3 6027 if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
a68ab351
JJ
6028 if (cond1 is <)
6029 adj = STEP1 - 1;
6030 else
6031 adj = STEP1 + 1;
6032 count1 = (adj + N12 - N11) / STEP1;
6033 count = count1 * count2 * count3;
5a0f4dd3
JJ
6034 goto Z1;
6035 Z0:
6036 count = 0;
6037 Z1:
a68ab351
JJ
6038 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
6039 if (more) goto L0; else goto L3;
6040 L0:
6041 V = istart0;
6042 T = V;
6043 V3 = N31 + (T % count3) * STEP3;
6044 T = T / count3;
6045 V2 = N21 + (T % count2) * STEP2;
6046 T = T / count2;
6047 V1 = N11 + T * STEP1;
6048 iend = iend0;
6049 L1:
6050 BODY;
6051 V += 1;
6052 if (V < iend) goto L10; else goto L2;
6053 L10:
6054 V3 += STEP3;
6055 if (V3 cond3 N32) goto L1; else goto L11;
6056 L11:
6057 V3 = N31;
6058 V2 += STEP2;
6059 if (V2 cond2 N22) goto L1; else goto L12;
6060 L12:
6061 V2 = N21;
6062 V1 += STEP1;
6063 goto L1;
6064 L2:
6065 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
6066 L3:
6067
6068 */
953ff289 6069
777f7f9a 6070static void
50674e96
DN
6071expand_omp_for_generic (struct omp_region *region,
6072 struct omp_for_data *fd,
953ff289 6073 enum built_in_function start_fn,
acf0174b
JJ
6074 enum built_in_function next_fn,
6075 gimple inner_stmt)
953ff289 6076{
726a989a 6077 tree type, istart0, iend0, iend;
a68ab351
JJ
6078 tree t, vmain, vback, bias = NULL_TREE;
6079 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, collapse_bb;
d3c673c7 6080 basic_block l2_bb = NULL, l3_bb = NULL;
726a989a 6081 gimple_stmt_iterator gsi;
538dd0b7 6082 gassign *assign_stmt;
50674e96 6083 bool in_combined_parallel = is_combined_parallel (region);
e5c95afe 6084 bool broken_loop = region->cont == NULL;
917948d3 6085 edge e, ne;
a68ab351
JJ
6086 tree *counts = NULL;
6087 int i;
e5c95afe
ZD
6088
6089 gcc_assert (!broken_loop || !in_combined_parallel);
a68ab351
JJ
6090 gcc_assert (fd->iter_type == long_integer_type_node
6091 || !in_combined_parallel);
953ff289 6092
a68ab351
JJ
6093 type = TREE_TYPE (fd->loop.v);
6094 istart0 = create_tmp_var (fd->iter_type, ".istart0");
6095 iend0 = create_tmp_var (fd->iter_type, ".iend0");
5b4fc8fb
JJ
6096 TREE_ADDRESSABLE (istart0) = 1;
6097 TREE_ADDRESSABLE (iend0) = 1;
953ff289 6098
a68ab351
JJ
6099 /* See if we need to bias by LLONG_MIN. */
6100 if (fd->iter_type == long_long_unsigned_type_node
6101 && TREE_CODE (type) == INTEGER_TYPE
6102 && !TYPE_UNSIGNED (type))
6103 {
6104 tree n1, n2;
6105
6106 if (fd->loop.cond_code == LT_EXPR)
6107 {
6108 n1 = fd->loop.n1;
6109 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
6110 }
6111 else
6112 {
6113 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
6114 n2 = fd->loop.n1;
6115 }
6116 if (TREE_CODE (n1) != INTEGER_CST
6117 || TREE_CODE (n2) != INTEGER_CST
6118 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
6119 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
6120 }
6121
777f7f9a 6122 entry_bb = region->entry;
d3c673c7 6123 cont_bb = region->cont;
a68ab351 6124 collapse_bb = NULL;
e5c95afe
ZD
6125 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
6126 gcc_assert (broken_loop
6127 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
6128 l0_bb = split_edge (FALLTHRU_EDGE (entry_bb));
6129 l1_bb = single_succ (l0_bb);
6130 if (!broken_loop)
d3c673c7
JJ
6131 {
6132 l2_bb = create_empty_bb (cont_bb);
e5c95afe
ZD
6133 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb);
6134 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
d3c673c7 6135 }
e5c95afe
ZD
6136 else
6137 l2_bb = NULL;
6138 l3_bb = BRANCH_EDGE (entry_bb)->dest;
6139 exit_bb = region->exit;
50674e96 6140
726a989a 6141 gsi = gsi_last_bb (entry_bb);
a68ab351 6142
726a989a 6143 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
a68ab351
JJ
6144 if (fd->collapse > 1)
6145 {
5a0f4dd3 6146 int first_zero_iter = -1;
74bf76ed 6147 basic_block zero_iter_bb = NULL, l2_dom_bb = NULL;
5a0f4dd3 6148
74bf76ed
JJ
6149 counts = XALLOCAVEC (tree, fd->collapse);
6150 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6151 zero_iter_bb, first_zero_iter,
6152 l2_dom_bb);
a68ab351 6153
5a0f4dd3
JJ
6154 if (zero_iter_bb)
6155 {
6156 /* Some counts[i] vars might be uninitialized if
6157 some loop has zero iterations. But the body shouldn't
6158 be executed in that case, so just avoid uninit warnings. */
6159 for (i = first_zero_iter; i < fd->collapse; i++)
6160 if (SSA_VAR_P (counts[i]))
6161 TREE_NO_WARNING (counts[i]) = 1;
6162 gsi_prev (&gsi);
6163 e = split_block (entry_bb, gsi_stmt (gsi));
6164 entry_bb = e->dest;
6165 make_edge (zero_iter_bb, entry_bb, EDGE_FALLTHRU);
6166 gsi = gsi_last_bb (entry_bb);
6167 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
6168 get_immediate_dominator (CDI_DOMINATORS,
6169 zero_iter_bb));
6170 }
a68ab351 6171 }
917948d3
ZD
6172 if (in_combined_parallel)
6173 {
6174 /* In a combined parallel loop, emit a call to
6175 GOMP_loop_foo_next. */
e79983f4 6176 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
917948d3
ZD
6177 build_fold_addr_expr (istart0),
6178 build_fold_addr_expr (iend0));
6179 }
6180 else
953ff289 6181 {
5039610b 6182 tree t0, t1, t2, t3, t4;
50674e96
DN
6183 /* If this is not a combined parallel loop, emit a call to
6184 GOMP_loop_foo_start in ENTRY_BB. */
5039610b
SL
6185 t4 = build_fold_addr_expr (iend0);
6186 t3 = build_fold_addr_expr (istart0);
a68ab351 6187 t2 = fold_convert (fd->iter_type, fd->loop.step);
74bf76ed
JJ
6188 t1 = fd->loop.n2;
6189 t0 = fd->loop.n1;
acf0174b
JJ
6190 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6191 {
6192 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6193 OMP_CLAUSE__LOOPTEMP_);
6194 gcc_assert (innerc);
6195 t0 = OMP_CLAUSE_DECL (innerc);
6196 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6197 OMP_CLAUSE__LOOPTEMP_);
6198 gcc_assert (innerc);
6199 t1 = OMP_CLAUSE_DECL (innerc);
6200 }
74bf76ed
JJ
6201 if (POINTER_TYPE_P (TREE_TYPE (t0))
6202 && TYPE_PRECISION (TREE_TYPE (t0))
6203 != TYPE_PRECISION (fd->iter_type))
c6ff4493
SE
6204 {
6205 /* Avoid casting pointers to integer of a different size. */
96f9265a 6206 tree itype = signed_type_for (type);
74bf76ed
JJ
6207 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
6208 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
c6ff4493
SE
6209 }
6210 else
6211 {
74bf76ed
JJ
6212 t1 = fold_convert (fd->iter_type, t1);
6213 t0 = fold_convert (fd->iter_type, t0);
c6ff4493 6214 }
a68ab351 6215 if (bias)
953ff289 6216 {
a68ab351
JJ
6217 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
6218 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
6219 }
6220 if (fd->iter_type == long_integer_type_node)
6221 {
6222 if (fd->chunk_size)
6223 {
6224 t = fold_convert (fd->iter_type, fd->chunk_size);
e79983f4
MM
6225 t = build_call_expr (builtin_decl_explicit (start_fn),
6226 6, t0, t1, t2, t, t3, t4);
a68ab351
JJ
6227 }
6228 else
e79983f4
MM
6229 t = build_call_expr (builtin_decl_explicit (start_fn),
6230 5, t0, t1, t2, t3, t4);
953ff289 6231 }
5039610b 6232 else
a68ab351
JJ
6233 {
6234 tree t5;
6235 tree c_bool_type;
e79983f4 6236 tree bfn_decl;
a68ab351
JJ
6237
6238 /* The GOMP_loop_ull_*start functions have additional boolean
6239 argument, true for < loops and false for > loops.
6240 In Fortran, the C bool type can be different from
6241 boolean_type_node. */
e79983f4
MM
6242 bfn_decl = builtin_decl_explicit (start_fn);
6243 c_bool_type = TREE_TYPE (TREE_TYPE (bfn_decl));
a68ab351
JJ
6244 t5 = build_int_cst (c_bool_type,
6245 fd->loop.cond_code == LT_EXPR ? 1 : 0);
6246 if (fd->chunk_size)
6247 {
e79983f4 6248 tree bfn_decl = builtin_decl_explicit (start_fn);
a68ab351 6249 t = fold_convert (fd->iter_type, fd->chunk_size);
e79983f4 6250 t = build_call_expr (bfn_decl, 7, t5, t0, t1, t2, t, t3, t4);
a68ab351
JJ
6251 }
6252 else
e79983f4
MM
6253 t = build_call_expr (builtin_decl_explicit (start_fn),
6254 6, t5, t0, t1, t2, t3, t4);
a68ab351 6255 }
953ff289 6256 }
a68ab351
JJ
6257 if (TREE_TYPE (t) != boolean_type_node)
6258 t = fold_build2 (NE_EXPR, boolean_type_node,
6259 t, build_int_cst (TREE_TYPE (t), 0));
726a989a
RB
6260 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6261 true, GSI_SAME_STMT);
6262 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
917948d3 6263
726a989a
RB
6264 /* Remove the GIMPLE_OMP_FOR statement. */
6265 gsi_remove (&gsi, true);
953ff289 6266
50674e96 6267 /* Iteration setup for sequential loop goes in L0_BB. */
74bf76ed
JJ
6268 tree startvar = fd->loop.v;
6269 tree endvar = NULL_TREE;
6270
acf0174b
JJ
6271 if (gimple_omp_for_combined_p (fd->for_stmt))
6272 {
6273 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_FOR
6274 && gimple_omp_for_kind (inner_stmt)
6275 == GF_OMP_FOR_KIND_SIMD);
6276 tree innerc = find_omp_clause (gimple_omp_for_clauses (inner_stmt),
6277 OMP_CLAUSE__LOOPTEMP_);
6278 gcc_assert (innerc);
6279 startvar = OMP_CLAUSE_DECL (innerc);
6280 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6281 OMP_CLAUSE__LOOPTEMP_);
6282 gcc_assert (innerc);
6283 endvar = OMP_CLAUSE_DECL (innerc);
6284 }
6285
726a989a 6286 gsi = gsi_start_bb (l0_bb);
550918ca 6287 t = istart0;
a68ab351 6288 if (bias)
550918ca 6289 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
74bf76ed
JJ
6290 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
6291 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
6292 t = fold_convert (TREE_TYPE (startvar), t);
ea3a0fde 6293 t = force_gimple_operand_gsi (&gsi, t,
74bf76ed
JJ
6294 DECL_P (startvar)
6295 && TREE_ADDRESSABLE (startvar),
ea3a0fde 6296 NULL_TREE, false, GSI_CONTINUE_LINKING);
538dd0b7
DM
6297 assign_stmt = gimple_build_assign (startvar, t);
6298 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
953ff289 6299
550918ca 6300 t = iend0;
a68ab351 6301 if (bias)
550918ca 6302 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
74bf76ed
JJ
6303 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
6304 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
6305 t = fold_convert (TREE_TYPE (startvar), t);
726a989a
RB
6306 iend = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6307 false, GSI_CONTINUE_LINKING);
74bf76ed 6308 if (endvar)
a68ab351 6309 {
538dd0b7
DM
6310 assign_stmt = gimple_build_assign (endvar, iend);
6311 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
95782571 6312 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (iend)))
538dd0b7 6313 assign_stmt = gimple_build_assign (fd->loop.v, iend);
95782571 6314 else
0d0e4a03 6315 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, iend);
538dd0b7 6316 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
a68ab351 6317 }
74bf76ed 6318 if (fd->collapse > 1)
acf0174b 6319 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
50674e96 6320
e5c95afe 6321 if (!broken_loop)
d3c673c7 6322 {
e5c95afe
ZD
6323 /* Code to control the increment and predicate for the sequential
6324 loop goes in the CONT_BB. */
726a989a 6325 gsi = gsi_last_bb (cont_bb);
538dd0b7
DM
6326 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
6327 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
6328 vmain = gimple_omp_continue_control_use (cont_stmt);
6329 vback = gimple_omp_continue_control_def (cont_stmt);
917948d3 6330
acf0174b 6331 if (!gimple_omp_for_combined_p (fd->for_stmt))
74bf76ed
JJ
6332 {
6333 if (POINTER_TYPE_P (type))
6334 t = fold_build_pointer_plus (vmain, fd->loop.step);
6335 else
6336 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
6337 t = force_gimple_operand_gsi (&gsi, t,
6338 DECL_P (vback)
6339 && TREE_ADDRESSABLE (vback),
6340 NULL_TREE, true, GSI_SAME_STMT);
538dd0b7
DM
6341 assign_stmt = gimple_build_assign (vback, t);
6342 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
74bf76ed
JJ
6343
6344 t = build2 (fd->loop.cond_code, boolean_type_node,
6345 DECL_P (vback) && TREE_ADDRESSABLE (vback) ? t : vback,
6346 iend);
538dd0b7
DM
6347 gcond *cond_stmt = gimple_build_cond_empty (t);
6348 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
74bf76ed 6349 }
50674e96 6350
726a989a
RB
6351 /* Remove GIMPLE_OMP_CONTINUE. */
6352 gsi_remove (&gsi, true);
50674e96 6353
acf0174b 6354 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
74bf76ed 6355 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, l1_bb);
a68ab351 6356
e5c95afe 6357 /* Emit code to get the next parallel iteration in L2_BB. */
726a989a 6358 gsi = gsi_start_bb (l2_bb);
50674e96 6359
e79983f4 6360 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
e5c95afe
ZD
6361 build_fold_addr_expr (istart0),
6362 build_fold_addr_expr (iend0));
726a989a
RB
6363 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6364 false, GSI_CONTINUE_LINKING);
a68ab351
JJ
6365 if (TREE_TYPE (t) != boolean_type_node)
6366 t = fold_build2 (NE_EXPR, boolean_type_node,
6367 t, build_int_cst (TREE_TYPE (t), 0));
538dd0b7
DM
6368 gcond *cond_stmt = gimple_build_cond_empty (t);
6369 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
e5c95afe 6370 }
953ff289 6371
777f7f9a 6372 /* Add the loop cleanup function. */
726a989a
RB
6373 gsi = gsi_last_bb (exit_bb);
6374 if (gimple_omp_return_nowait_p (gsi_stmt (gsi)))
e79983f4 6375 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
acf0174b
JJ
6376 else if (gimple_omp_return_lhs (gsi_stmt (gsi)))
6377 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL);
777f7f9a 6378 else
e79983f4 6379 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END);
538dd0b7 6380 gcall *call_stmt = gimple_build_call (t, 0);
acf0174b 6381 if (gimple_omp_return_lhs (gsi_stmt (gsi)))
538dd0b7
DM
6382 gimple_call_set_lhs (call_stmt, gimple_omp_return_lhs (gsi_stmt (gsi)));
6383 gsi_insert_after (&gsi, call_stmt, GSI_SAME_STMT);
726a989a 6384 gsi_remove (&gsi, true);
50674e96
DN
6385
6386 /* Connect the new blocks. */
917948d3
ZD
6387 find_edge (entry_bb, l0_bb)->flags = EDGE_TRUE_VALUE;
6388 find_edge (entry_bb, l3_bb)->flags = EDGE_FALSE_VALUE;
953ff289 6389
e5c95afe
ZD
6390 if (!broken_loop)
6391 {
726a989a
RB
6392 gimple_seq phis;
6393
917948d3
ZD
6394 e = find_edge (cont_bb, l3_bb);
6395 ne = make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
6396
726a989a
RB
6397 phis = phi_nodes (l3_bb);
6398 for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi))
6399 {
6400 gimple phi = gsi_stmt (gsi);
6401 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, ne),
6402 PHI_ARG_DEF_FROM_EDGE (phi, e));
6403 }
917948d3
ZD
6404 remove_edge (e);
6405
e5c95afe 6406 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
726338f4 6407 add_bb_to_loop (l2_bb, cont_bb->loop_father);
74bf76ed 6408 e = find_edge (cont_bb, l1_bb);
acf0174b
JJ
6409 if (gimple_omp_for_combined_p (fd->for_stmt))
6410 {
6411 remove_edge (e);
6412 e = NULL;
6413 }
74bf76ed 6414 else if (fd->collapse > 1)
a68ab351 6415 {
a68ab351
JJ
6416 remove_edge (e);
6417 e = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6418 }
6419 else
74bf76ed
JJ
6420 e->flags = EDGE_TRUE_VALUE;
6421 if (e)
a68ab351 6422 {
74bf76ed
JJ
6423 e->probability = REG_BR_PROB_BASE * 7 / 8;
6424 find_edge (cont_bb, l2_bb)->probability = REG_BR_PROB_BASE / 8;
6425 }
6426 else
6427 {
6428 e = find_edge (cont_bb, l2_bb);
6429 e->flags = EDGE_FALLTHRU;
a68ab351 6430 }
e5c95afe 6431 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
917948d3
ZD
6432
6433 set_immediate_dominator (CDI_DOMINATORS, l2_bb,
6434 recompute_dominator (CDI_DOMINATORS, l2_bb));
6435 set_immediate_dominator (CDI_DOMINATORS, l3_bb,
6436 recompute_dominator (CDI_DOMINATORS, l3_bb));
6437 set_immediate_dominator (CDI_DOMINATORS, l0_bb,
6438 recompute_dominator (CDI_DOMINATORS, l0_bb));
6439 set_immediate_dominator (CDI_DOMINATORS, l1_bb,
6440 recompute_dominator (CDI_DOMINATORS, l1_bb));
6093bc06
RB
6441
6442 struct loop *outer_loop = alloc_loop ();
6443 outer_loop->header = l0_bb;
6444 outer_loop->latch = l2_bb;
6445 add_loop (outer_loop, l0_bb->loop_father);
6446
acf0174b 6447 if (!gimple_omp_for_combined_p (fd->for_stmt))
74bf76ed
JJ
6448 {
6449 struct loop *loop = alloc_loop ();
6450 loop->header = l1_bb;
6451 /* The loop may have multiple latches. */
6452 add_loop (loop, outer_loop);
6453 }
e5c95afe 6454 }
953ff289
DN
6455}
6456
6457
50674e96
DN
6458/* A subroutine of expand_omp_for. Generate code for a parallel
6459 loop with static schedule and no specified chunk size. Given
6460 parameters:
953ff289
DN
6461
6462 for (V = N1; V cond N2; V += STEP) BODY;
6463
6464 where COND is "<" or ">", we generate pseudocode
6465
5a0f4dd3 6466 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
953ff289
DN
6467 if (cond is <)
6468 adj = STEP - 1;
6469 else
6470 adj = STEP + 1;
a68ab351
JJ
6471 if ((__typeof (V)) -1 > 0 && cond is >)
6472 n = -(adj + N2 - N1) / -STEP;
6473 else
6474 n = (adj + N2 - N1) / STEP;
953ff289 6475 q = n / nthreads;
fb79f500
JJ
6476 tt = n % nthreads;
6477 if (threadid < tt) goto L3; else goto L4;
6478 L3:
6479 tt = 0;
6480 q = q + 1;
6481 L4:
6482 s0 = q * threadid + tt;
6483 e0 = s0 + q;
917948d3 6484 V = s0 * STEP + N1;
953ff289
DN
6485 if (s0 >= e0) goto L2; else goto L0;
6486 L0:
953ff289
DN
6487 e = e0 * STEP + N1;
6488 L1:
6489 BODY;
6490 V += STEP;
6491 if (V cond e) goto L1;
953ff289
DN
6492 L2:
6493*/
6494
777f7f9a 6495static void
50674e96 6496expand_omp_for_static_nochunk (struct omp_region *region,
acf0174b
JJ
6497 struct omp_for_data *fd,
6498 gimple inner_stmt)
953ff289 6499{
fb79f500 6500 tree n, q, s0, e0, e, t, tt, nthreads, threadid;
a68ab351 6501 tree type, itype, vmain, vback;
fb79f500 6502 basic_block entry_bb, second_bb, third_bb, exit_bb, seq_start_bb;
acf0174b 6503 basic_block body_bb, cont_bb, collapse_bb = NULL;
777f7f9a 6504 basic_block fin_bb;
726a989a 6505 gimple_stmt_iterator gsi;
fb79f500 6506 edge ep;
acf0174b
JJ
6507 bool broken_loop = region->cont == NULL;
6508 tree *counts = NULL;
6509 tree n1, n2, step;
953ff289 6510
41dbbb37
TS
6511 gcc_checking_assert ((gimple_omp_for_kind (fd->for_stmt)
6512 != GF_OMP_FOR_KIND_OACC_LOOP)
6513 || !inner_stmt);
6514
a68ab351
JJ
6515 itype = type = TREE_TYPE (fd->loop.v);
6516 if (POINTER_TYPE_P (type))
96f9265a 6517 itype = signed_type_for (type);
953ff289 6518
777f7f9a 6519 entry_bb = region->entry;
777f7f9a 6520 cont_bb = region->cont;
e5c95afe 6521 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
acf0174b
JJ
6522 fin_bb = BRANCH_EDGE (entry_bb)->dest;
6523 gcc_assert (broken_loop
6524 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
e5c95afe
ZD
6525 seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb));
6526 body_bb = single_succ (seq_start_bb);
acf0174b
JJ
6527 if (!broken_loop)
6528 {
6529 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
6530 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6531 }
777f7f9a
RH
6532 exit_bb = region->exit;
6533
50674e96 6534 /* Iteration space partitioning goes in ENTRY_BB. */
726a989a
RB
6535 gsi = gsi_last_bb (entry_bb);
6536 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
777f7f9a 6537
acf0174b
JJ
6538 if (fd->collapse > 1)
6539 {
6540 int first_zero_iter = -1;
6541 basic_block l2_dom_bb = NULL;
6542
6543 counts = XALLOCAVEC (tree, fd->collapse);
6544 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6545 fin_bb, first_zero_iter,
6546 l2_dom_bb);
6547 t = NULL_TREE;
6548 }
6549 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
6550 t = integer_one_node;
6551 else
6552 t = fold_binary (fd->loop.cond_code, boolean_type_node,
6553 fold_convert (type, fd->loop.n1),
6554 fold_convert (type, fd->loop.n2));
6555 if (fd->collapse == 1
6556 && TYPE_UNSIGNED (type)
5a0f4dd3
JJ
6557 && (t == NULL_TREE || !integer_onep (t)))
6558 {
5a0f4dd3
JJ
6559 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
6560 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
6561 true, GSI_SAME_STMT);
6562 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
6563 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
6564 true, GSI_SAME_STMT);
538dd0b7
DM
6565 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
6566 NULL_TREE, NULL_TREE);
6567 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
6568 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
5a0f4dd3 6569 expand_omp_regimplify_p, NULL, NULL)
538dd0b7 6570 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
5a0f4dd3
JJ
6571 expand_omp_regimplify_p, NULL, NULL))
6572 {
538dd0b7
DM
6573 gsi = gsi_for_stmt (cond_stmt);
6574 gimple_regimplify_operands (cond_stmt, &gsi);
5a0f4dd3 6575 }
538dd0b7 6576 ep = split_block (entry_bb, cond_stmt);
5a0f4dd3
JJ
6577 ep->flags = EDGE_TRUE_VALUE;
6578 entry_bb = ep->dest;
6579 ep->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
6580 ep = make_edge (ep->src, fin_bb, EDGE_FALSE_VALUE);
6581 ep->probability = REG_BR_PROB_BASE / 2000 - 1;
6582 if (gimple_in_ssa_p (cfun))
6583 {
6584 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
538dd0b7
DM
6585 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
6586 !gsi_end_p (gpi); gsi_next (&gpi))
5a0f4dd3 6587 {
538dd0b7 6588 gphi *phi = gpi.phi ();
5a0f4dd3
JJ
6589 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
6590 ep, UNKNOWN_LOCATION);
6591 }
6592 }
6593 gsi = gsi_last_bb (entry_bb);
6594 }
6595
41dbbb37
TS
6596 switch (gimple_omp_for_kind (fd->for_stmt))
6597 {
6598 case GF_OMP_FOR_KIND_FOR:
6599 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
6600 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
6601 break;
6602 case GF_OMP_FOR_KIND_DISTRIBUTE:
6603 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
6604 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
6605 break;
6606 case GF_OMP_FOR_KIND_OACC_LOOP:
6607 nthreads = builtin_decl_explicit (BUILT_IN_GOACC_GET_NUM_THREADS);
6608 threadid = builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM);
6609 break;
6610 default:
6611 gcc_unreachable ();
6612 }
6613 nthreads = build_call_expr (nthreads, 0);
6614 nthreads = fold_convert (itype, nthreads);
6615 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
726a989a 6616 true, GSI_SAME_STMT);
41dbbb37
TS
6617 threadid = build_call_expr (threadid, 0);
6618 threadid = fold_convert (itype, threadid);
6619 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
726a989a 6620 true, GSI_SAME_STMT);
953ff289 6621
acf0174b
JJ
6622 n1 = fd->loop.n1;
6623 n2 = fd->loop.n2;
6624 step = fd->loop.step;
6625 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6626 {
6627 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6628 OMP_CLAUSE__LOOPTEMP_);
6629 gcc_assert (innerc);
6630 n1 = OMP_CLAUSE_DECL (innerc);
6631 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6632 OMP_CLAUSE__LOOPTEMP_);
6633 gcc_assert (innerc);
6634 n2 = OMP_CLAUSE_DECL (innerc);
6635 }
6636 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
6637 true, NULL_TREE, true, GSI_SAME_STMT);
6638 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
6639 true, NULL_TREE, true, GSI_SAME_STMT);
6640 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
6641 true, NULL_TREE, true, GSI_SAME_STMT);
a68ab351
JJ
6642
6643 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
acf0174b
JJ
6644 t = fold_build2 (PLUS_EXPR, itype, step, t);
6645 t = fold_build2 (PLUS_EXPR, itype, t, n2);
6646 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
a68ab351
JJ
6647 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
6648 t = fold_build2 (TRUNC_DIV_EXPR, itype,
6649 fold_build1 (NEGATE_EXPR, itype, t),
acf0174b 6650 fold_build1 (NEGATE_EXPR, itype, step));
a68ab351 6651 else
acf0174b 6652 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
a68ab351 6653 t = fold_convert (itype, t);
726a989a 6654 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
953ff289 6655
7cc434a3 6656 q = create_tmp_reg (itype, "q");
a68ab351 6657 t = fold_build2 (TRUNC_DIV_EXPR, itype, n, nthreads);
fb79f500
JJ
6658 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
6659 gsi_insert_before (&gsi, gimple_build_assign (q, t), GSI_SAME_STMT);
6660
7cc434a3 6661 tt = create_tmp_reg (itype, "tt");
fb79f500
JJ
6662 t = fold_build2 (TRUNC_MOD_EXPR, itype, n, nthreads);
6663 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
6664 gsi_insert_before (&gsi, gimple_build_assign (tt, t), GSI_SAME_STMT);
953ff289 6665
fb79f500 6666 t = build2 (LT_EXPR, boolean_type_node, threadid, tt);
538dd0b7
DM
6667 gcond *cond_stmt = gimple_build_cond_empty (t);
6668 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
fb79f500 6669
538dd0b7 6670 second_bb = split_block (entry_bb, cond_stmt)->dest;
fb79f500
JJ
6671 gsi = gsi_last_bb (second_bb);
6672 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6673
6674 gsi_insert_before (&gsi, gimple_build_assign (tt, build_int_cst (itype, 0)),
6675 GSI_SAME_STMT);
538dd0b7 6676 gassign *assign_stmt
0d0e4a03 6677 = gimple_build_assign (q, PLUS_EXPR, q, build_int_cst (itype, 1));
538dd0b7 6678 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
fb79f500 6679
538dd0b7 6680 third_bb = split_block (second_bb, assign_stmt)->dest;
fb79f500
JJ
6681 gsi = gsi_last_bb (third_bb);
6682 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
953ff289 6683
a68ab351 6684 t = build2 (MULT_EXPR, itype, q, threadid);
fb79f500 6685 t = build2 (PLUS_EXPR, itype, t, tt);
726a989a 6686 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
953ff289 6687
a68ab351 6688 t = fold_build2 (PLUS_EXPR, itype, s0, q);
726a989a 6689 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
917948d3 6690
953ff289 6691 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
726a989a 6692 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
50674e96 6693
726a989a
RB
6694 /* Remove the GIMPLE_OMP_FOR statement. */
6695 gsi_remove (&gsi, true);
50674e96
DN
6696
6697 /* Setup code for sequential iteration goes in SEQ_START_BB. */
726a989a 6698 gsi = gsi_start_bb (seq_start_bb);
953ff289 6699
acf0174b
JJ
6700 tree startvar = fd->loop.v;
6701 tree endvar = NULL_TREE;
6702
6703 if (gimple_omp_for_combined_p (fd->for_stmt))
6704 {
6705 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
6706 ? gimple_omp_parallel_clauses (inner_stmt)
6707 : gimple_omp_for_clauses (inner_stmt);
6708 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
6709 gcc_assert (innerc);
6710 startvar = OMP_CLAUSE_DECL (innerc);
6711 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6712 OMP_CLAUSE__LOOPTEMP_);
6713 gcc_assert (innerc);
6714 endvar = OMP_CLAUSE_DECL (innerc);
6715 }
a68ab351 6716 t = fold_convert (itype, s0);
acf0174b 6717 t = fold_build2 (MULT_EXPR, itype, t, step);
a68ab351 6718 if (POINTER_TYPE_P (type))
acf0174b 6719 t = fold_build_pointer_plus (n1, t);
a68ab351 6720 else
acf0174b
JJ
6721 t = fold_build2 (PLUS_EXPR, type, t, n1);
6722 t = fold_convert (TREE_TYPE (startvar), t);
ea3a0fde 6723 t = force_gimple_operand_gsi (&gsi, t,
acf0174b
JJ
6724 DECL_P (startvar)
6725 && TREE_ADDRESSABLE (startvar),
ea3a0fde 6726 NULL_TREE, false, GSI_CONTINUE_LINKING);
538dd0b7
DM
6727 assign_stmt = gimple_build_assign (startvar, t);
6728 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
b8698a0f 6729
a68ab351 6730 t = fold_convert (itype, e0);
acf0174b 6731 t = fold_build2 (MULT_EXPR, itype, t, step);
a68ab351 6732 if (POINTER_TYPE_P (type))
acf0174b 6733 t = fold_build_pointer_plus (n1, t);
a68ab351 6734 else
acf0174b
JJ
6735 t = fold_build2 (PLUS_EXPR, type, t, n1);
6736 t = fold_convert (TREE_TYPE (startvar), t);
726a989a
RB
6737 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6738 false, GSI_CONTINUE_LINKING);
acf0174b
JJ
6739 if (endvar)
6740 {
538dd0b7
DM
6741 assign_stmt = gimple_build_assign (endvar, e);
6742 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
95782571 6743 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
538dd0b7 6744 assign_stmt = gimple_build_assign (fd->loop.v, e);
95782571 6745 else
0d0e4a03 6746 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
538dd0b7 6747 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
acf0174b
JJ
6748 }
6749 if (fd->collapse > 1)
6750 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
953ff289 6751
acf0174b
JJ
6752 if (!broken_loop)
6753 {
6754 /* The code controlling the sequential loop replaces the
6755 GIMPLE_OMP_CONTINUE. */
6756 gsi = gsi_last_bb (cont_bb);
538dd0b7
DM
6757 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
6758 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
6759 vmain = gimple_omp_continue_control_use (cont_stmt);
6760 vback = gimple_omp_continue_control_def (cont_stmt);
917948d3 6761
acf0174b
JJ
6762 if (!gimple_omp_for_combined_p (fd->for_stmt))
6763 {
6764 if (POINTER_TYPE_P (type))
6765 t = fold_build_pointer_plus (vmain, step);
6766 else
6767 t = fold_build2 (PLUS_EXPR, type, vmain, step);
6768 t = force_gimple_operand_gsi (&gsi, t,
6769 DECL_P (vback)
6770 && TREE_ADDRESSABLE (vback),
6771 NULL_TREE, true, GSI_SAME_STMT);
538dd0b7
DM
6772 assign_stmt = gimple_build_assign (vback, t);
6773 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
917948d3 6774
acf0174b
JJ
6775 t = build2 (fd->loop.cond_code, boolean_type_node,
6776 DECL_P (vback) && TREE_ADDRESSABLE (vback)
6777 ? t : vback, e);
6778 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6779 }
953ff289 6780
acf0174b
JJ
6781 /* Remove the GIMPLE_OMP_CONTINUE statement. */
6782 gsi_remove (&gsi, true);
6783
6784 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
6785 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
6786 }
50674e96 6787
726a989a
RB
6788 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
6789 gsi = gsi_last_bb (exit_bb);
6790 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
acf0174b
JJ
6791 {
6792 t = gimple_omp_return_lhs (gsi_stmt (gsi));
41dbbb37
TS
6793 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
6794 gcc_checking_assert (t == NULL_TREE);
6795 else
6796 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
acf0174b 6797 }
726a989a 6798 gsi_remove (&gsi, true);
50674e96
DN
6799
6800 /* Connect all the blocks. */
fb79f500
JJ
6801 ep = make_edge (entry_bb, third_bb, EDGE_FALSE_VALUE);
6802 ep->probability = REG_BR_PROB_BASE / 4 * 3;
6803 ep = find_edge (entry_bb, second_bb);
6804 ep->flags = EDGE_TRUE_VALUE;
6805 ep->probability = REG_BR_PROB_BASE / 4;
6806 find_edge (third_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
6807 find_edge (third_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
917948d3 6808
acf0174b
JJ
6809 if (!broken_loop)
6810 {
6811 ep = find_edge (cont_bb, body_bb);
6812 if (gimple_omp_for_combined_p (fd->for_stmt))
6813 {
6814 remove_edge (ep);
6815 ep = NULL;
6816 }
6817 else if (fd->collapse > 1)
6818 {
6819 remove_edge (ep);
6820 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6821 }
6822 else
6823 ep->flags = EDGE_TRUE_VALUE;
6824 find_edge (cont_bb, fin_bb)->flags
6825 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
6826 }
b8698a0f 6827
fb79f500
JJ
6828 set_immediate_dominator (CDI_DOMINATORS, second_bb, entry_bb);
6829 set_immediate_dominator (CDI_DOMINATORS, third_bb, entry_bb);
6830 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, third_bb);
acf0174b 6831
917948d3
ZD
6832 set_immediate_dominator (CDI_DOMINATORS, body_bb,
6833 recompute_dominator (CDI_DOMINATORS, body_bb));
6834 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
6835 recompute_dominator (CDI_DOMINATORS, fin_bb));
6093bc06 6836
acf0174b
JJ
6837 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
6838 {
6839 struct loop *loop = alloc_loop ();
6840 loop->header = body_bb;
6841 if (collapse_bb == NULL)
6842 loop->latch = cont_bb;
6843 add_loop (loop, body_bb->loop_father);
6844 }
953ff289
DN
6845}
6846
50674e96
DN
6847
6848/* A subroutine of expand_omp_for. Generate code for a parallel
6849 loop with static schedule and a specified chunk size. Given
6850 parameters:
953ff289
DN
6851
6852 for (V = N1; V cond N2; V += STEP) BODY;
6853
6854 where COND is "<" or ">", we generate pseudocode
6855
5a0f4dd3 6856 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
953ff289
DN
6857 if (cond is <)
6858 adj = STEP - 1;
6859 else
6860 adj = STEP + 1;
a68ab351
JJ
6861 if ((__typeof (V)) -1 > 0 && cond is >)
6862 n = -(adj + N2 - N1) / -STEP;
6863 else
6864 n = (adj + N2 - N1) / STEP;
953ff289 6865 trip = 0;
917948d3
ZD
6866 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
6867 here so that V is defined
6868 if the loop is not entered
953ff289
DN
6869 L0:
6870 s0 = (trip * nthreads + threadid) * CHUNK;
6871 e0 = min(s0 + CHUNK, n);
6872 if (s0 < n) goto L1; else goto L4;
6873 L1:
6874 V = s0 * STEP + N1;
6875 e = e0 * STEP + N1;
6876 L2:
6877 BODY;
6878 V += STEP;
6879 if (V cond e) goto L2; else goto L3;
6880 L3:
6881 trip += 1;
6882 goto L0;
6883 L4:
953ff289
DN
6884*/
6885
777f7f9a 6886static void
acf0174b
JJ
6887expand_omp_for_static_chunk (struct omp_region *region,
6888 struct omp_for_data *fd, gimple inner_stmt)
953ff289 6889{
726a989a 6890 tree n, s0, e0, e, t;
917948d3 6891 tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
ed20ae98 6892 tree type, itype, vmain, vback, vextra;
50674e96 6893 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
acf0174b 6894 basic_block trip_update_bb = NULL, cont_bb, collapse_bb = NULL, fin_bb;
ed20ae98 6895 gimple_stmt_iterator gsi;
726a989a 6896 edge se;
acf0174b
JJ
6897 bool broken_loop = region->cont == NULL;
6898 tree *counts = NULL;
6899 tree n1, n2, step;
953ff289 6900
41dbbb37
TS
6901 gcc_checking_assert ((gimple_omp_for_kind (fd->for_stmt)
6902 != GF_OMP_FOR_KIND_OACC_LOOP)
6903 || !inner_stmt);
6904
a68ab351
JJ
6905 itype = type = TREE_TYPE (fd->loop.v);
6906 if (POINTER_TYPE_P (type))
96f9265a 6907 itype = signed_type_for (type);
953ff289 6908
777f7f9a 6909 entry_bb = region->entry;
e5c95afe
ZD
6910 se = split_block (entry_bb, last_stmt (entry_bb));
6911 entry_bb = se->src;
6912 iter_part_bb = se->dest;
777f7f9a 6913 cont_bb = region->cont;
e5c95afe 6914 gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
acf0174b
JJ
6915 fin_bb = BRANCH_EDGE (iter_part_bb)->dest;
6916 gcc_assert (broken_loop
6917 || fin_bb == FALLTHRU_EDGE (cont_bb)->dest);
e5c95afe
ZD
6918 seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
6919 body_bb = single_succ (seq_start_bb);
acf0174b
JJ
6920 if (!broken_loop)
6921 {
6922 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
6923 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6924 trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
6925 }
777f7f9a 6926 exit_bb = region->exit;
50674e96 6927
50674e96 6928 /* Trip and adjustment setup goes in ENTRY_BB. */
ed20ae98
TS
6929 gsi = gsi_last_bb (entry_bb);
6930 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
50674e96 6931
acf0174b
JJ
6932 if (fd->collapse > 1)
6933 {
6934 int first_zero_iter = -1;
6935 basic_block l2_dom_bb = NULL;
6936
6937 counts = XALLOCAVEC (tree, fd->collapse);
ed20ae98 6938 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
acf0174b
JJ
6939 fin_bb, first_zero_iter,
6940 l2_dom_bb);
6941 t = NULL_TREE;
6942 }
6943 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
6944 t = integer_one_node;
6945 else
6946 t = fold_binary (fd->loop.cond_code, boolean_type_node,
6947 fold_convert (type, fd->loop.n1),
6948 fold_convert (type, fd->loop.n2));
6949 if (fd->collapse == 1
6950 && TYPE_UNSIGNED (type)
5a0f4dd3
JJ
6951 && (t == NULL_TREE || !integer_onep (t)))
6952 {
5a0f4dd3 6953 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
ed20ae98 6954 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
5a0f4dd3
JJ
6955 true, GSI_SAME_STMT);
6956 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
ed20ae98 6957 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
5a0f4dd3 6958 true, GSI_SAME_STMT);
538dd0b7
DM
6959 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
6960 NULL_TREE, NULL_TREE);
6961 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
6962 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
5a0f4dd3 6963 expand_omp_regimplify_p, NULL, NULL)
538dd0b7 6964 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
5a0f4dd3
JJ
6965 expand_omp_regimplify_p, NULL, NULL))
6966 {
538dd0b7
DM
6967 gsi = gsi_for_stmt (cond_stmt);
6968 gimple_regimplify_operands (cond_stmt, &gsi);
5a0f4dd3 6969 }
538dd0b7 6970 se = split_block (entry_bb, cond_stmt);
5a0f4dd3
JJ
6971 se->flags = EDGE_TRUE_VALUE;
6972 entry_bb = se->dest;
6973 se->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
6974 se = make_edge (se->src, fin_bb, EDGE_FALSE_VALUE);
6975 se->probability = REG_BR_PROB_BASE / 2000 - 1;
6976 if (gimple_in_ssa_p (cfun))
6977 {
6978 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
538dd0b7
DM
6979 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
6980 !gsi_end_p (gpi); gsi_next (&gpi))
5a0f4dd3 6981 {
538dd0b7 6982 gphi *phi = gpi.phi ();
5a0f4dd3
JJ
6983 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
6984 se, UNKNOWN_LOCATION);
6985 }
6986 }
ed20ae98 6987 gsi = gsi_last_bb (entry_bb);
5a0f4dd3
JJ
6988 }
6989
41dbbb37
TS
6990 switch (gimple_omp_for_kind (fd->for_stmt))
6991 {
6992 case GF_OMP_FOR_KIND_FOR:
6993 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
6994 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
6995 break;
6996 case GF_OMP_FOR_KIND_DISTRIBUTE:
6997 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
6998 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
6999 break;
7000 case GF_OMP_FOR_KIND_OACC_LOOP:
7001 nthreads = builtin_decl_explicit (BUILT_IN_GOACC_GET_NUM_THREADS);
7002 threadid = builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM);
7003 break;
7004 default:
7005 gcc_unreachable ();
7006 }
7007 nthreads = build_call_expr (nthreads, 0);
7008 nthreads = fold_convert (itype, nthreads);
7009 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
726a989a 7010 true, GSI_SAME_STMT);
41dbbb37
TS
7011 threadid = build_call_expr (threadid, 0);
7012 threadid = fold_convert (itype, threadid);
7013 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
726a989a 7014 true, GSI_SAME_STMT);
917948d3 7015
acf0174b
JJ
7016 n1 = fd->loop.n1;
7017 n2 = fd->loop.n2;
7018 step = fd->loop.step;
7019 if (gimple_omp_for_combined_into_p (fd->for_stmt))
7020 {
7021 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7022 OMP_CLAUSE__LOOPTEMP_);
7023 gcc_assert (innerc);
7024 n1 = OMP_CLAUSE_DECL (innerc);
7025 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7026 OMP_CLAUSE__LOOPTEMP_);
7027 gcc_assert (innerc);
7028 n2 = OMP_CLAUSE_DECL (innerc);
7029 }
ed20ae98 7030 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
acf0174b 7031 true, NULL_TREE, true, GSI_SAME_STMT);
ed20ae98 7032 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
acf0174b 7033 true, NULL_TREE, true, GSI_SAME_STMT);
ed20ae98 7034 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
acf0174b 7035 true, NULL_TREE, true, GSI_SAME_STMT);
917948d3 7036 fd->chunk_size
ed20ae98 7037 = force_gimple_operand_gsi (&gsi, fold_convert (itype, fd->chunk_size),
726a989a 7038 true, NULL_TREE, true, GSI_SAME_STMT);
a68ab351
JJ
7039
7040 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
acf0174b
JJ
7041 t = fold_build2 (PLUS_EXPR, itype, step, t);
7042 t = fold_build2 (PLUS_EXPR, itype, t, n2);
7043 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
a68ab351
JJ
7044 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
7045 t = fold_build2 (TRUNC_DIV_EXPR, itype,
7046 fold_build1 (NEGATE_EXPR, itype, t),
acf0174b 7047 fold_build1 (NEGATE_EXPR, itype, step));
a68ab351 7048 else
acf0174b 7049 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
a68ab351 7050 t = fold_convert (itype, t);
ed20ae98 7051 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
726a989a 7052 true, GSI_SAME_STMT);
917948d3 7053
a5efada7 7054 trip_var = create_tmp_reg (itype, ".trip");
917948d3
ZD
7055 if (gimple_in_ssa_p (cfun))
7056 {
b731b390
JJ
7057 trip_init = make_ssa_name (trip_var);
7058 trip_main = make_ssa_name (trip_var);
7059 trip_back = make_ssa_name (trip_var);
917948d3 7060 }
953ff289 7061 else
917948d3
ZD
7062 {
7063 trip_init = trip_var;
7064 trip_main = trip_var;
7065 trip_back = trip_var;
7066 }
953ff289 7067
538dd0b7
DM
7068 gassign *assign_stmt
7069 = gimple_build_assign (trip_init, build_int_cst (itype, 0));
7070 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
50674e96 7071
a68ab351 7072 t = fold_build2 (MULT_EXPR, itype, threadid, fd->chunk_size);
acf0174b 7073 t = fold_build2 (MULT_EXPR, itype, t, step);
a68ab351 7074 if (POINTER_TYPE_P (type))
acf0174b 7075 t = fold_build_pointer_plus (n1, t);
a68ab351 7076 else
acf0174b 7077 t = fold_build2 (PLUS_EXPR, type, t, n1);
ed20ae98
TS
7078 vextra = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7079 true, GSI_SAME_STMT);
917948d3 7080
726a989a 7081 /* Remove the GIMPLE_OMP_FOR. */
ed20ae98 7082 gsi_remove (&gsi, true);
50674e96
DN
7083
7084 /* Iteration space partitioning goes in ITER_PART_BB. */
ed20ae98 7085 gsi = gsi_last_bb (iter_part_bb);
953ff289 7086
a68ab351
JJ
7087 t = fold_build2 (MULT_EXPR, itype, trip_main, nthreads);
7088 t = fold_build2 (PLUS_EXPR, itype, t, threadid);
7089 t = fold_build2 (MULT_EXPR, itype, t, fd->chunk_size);
ed20ae98 7090 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
726a989a 7091 false, GSI_CONTINUE_LINKING);
953ff289 7092
a68ab351
JJ
7093 t = fold_build2 (PLUS_EXPR, itype, s0, fd->chunk_size);
7094 t = fold_build2 (MIN_EXPR, itype, t, n);
ed20ae98 7095 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
726a989a 7096 false, GSI_CONTINUE_LINKING);
953ff289
DN
7097
7098 t = build2 (LT_EXPR, boolean_type_node, s0, n);
ed20ae98 7099 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_CONTINUE_LINKING);
50674e96
DN
7100
7101 /* Setup code for sequential iteration goes in SEQ_START_BB. */
ed20ae98 7102 gsi = gsi_start_bb (seq_start_bb);
953ff289 7103
acf0174b
JJ
7104 tree startvar = fd->loop.v;
7105 tree endvar = NULL_TREE;
7106
7107 if (gimple_omp_for_combined_p (fd->for_stmt))
7108 {
7109 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
7110 ? gimple_omp_parallel_clauses (inner_stmt)
7111 : gimple_omp_for_clauses (inner_stmt);
7112 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
7113 gcc_assert (innerc);
7114 startvar = OMP_CLAUSE_DECL (innerc);
7115 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7116 OMP_CLAUSE__LOOPTEMP_);
7117 gcc_assert (innerc);
7118 endvar = OMP_CLAUSE_DECL (innerc);
7119 }
7120
a68ab351 7121 t = fold_convert (itype, s0);
acf0174b 7122 t = fold_build2 (MULT_EXPR, itype, t, step);
a68ab351 7123 if (POINTER_TYPE_P (type))
acf0174b 7124 t = fold_build_pointer_plus (n1, t);
a68ab351 7125 else
acf0174b
JJ
7126 t = fold_build2 (PLUS_EXPR, type, t, n1);
7127 t = fold_convert (TREE_TYPE (startvar), t);
ed20ae98 7128 t = force_gimple_operand_gsi (&gsi, t,
acf0174b
JJ
7129 DECL_P (startvar)
7130 && TREE_ADDRESSABLE (startvar),
ea3a0fde 7131 NULL_TREE, false, GSI_CONTINUE_LINKING);
538dd0b7
DM
7132 assign_stmt = gimple_build_assign (startvar, t);
7133 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
953ff289 7134
a68ab351 7135 t = fold_convert (itype, e0);
acf0174b 7136 t = fold_build2 (MULT_EXPR, itype, t, step);
a68ab351 7137 if (POINTER_TYPE_P (type))
acf0174b 7138 t = fold_build_pointer_plus (n1, t);
a68ab351 7139 else
acf0174b
JJ
7140 t = fold_build2 (PLUS_EXPR, type, t, n1);
7141 t = fold_convert (TREE_TYPE (startvar), t);
ed20ae98 7142 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
726a989a 7143 false, GSI_CONTINUE_LINKING);
acf0174b
JJ
7144 if (endvar)
7145 {
538dd0b7
DM
7146 assign_stmt = gimple_build_assign (endvar, e);
7147 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
95782571 7148 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
538dd0b7 7149 assign_stmt = gimple_build_assign (fd->loop.v, e);
95782571 7150 else
0d0e4a03 7151 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
538dd0b7 7152 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
acf0174b
JJ
7153 }
7154 if (fd->collapse > 1)
ed20ae98 7155 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
acf0174b
JJ
7156
7157 if (!broken_loop)
7158 {
7159 /* The code controlling the sequential loop goes in CONT_BB,
7160 replacing the GIMPLE_OMP_CONTINUE. */
ed20ae98 7161 gsi = gsi_last_bb (cont_bb);
538dd0b7
DM
7162 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
7163 vmain = gimple_omp_continue_control_use (cont_stmt);
7164 vback = gimple_omp_continue_control_def (cont_stmt);
953ff289 7165
acf0174b
JJ
7166 if (!gimple_omp_for_combined_p (fd->for_stmt))
7167 {
7168 if (POINTER_TYPE_P (type))
ed20ae98 7169 t = fold_build_pointer_plus (vmain, step);
acf0174b 7170 else
ed20ae98
TS
7171 t = fold_build2 (PLUS_EXPR, type, vmain, step);
7172 if (DECL_P (vback) && TREE_ADDRESSABLE (vback))
7173 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
acf0174b 7174 true, GSI_SAME_STMT);
538dd0b7
DM
7175 assign_stmt = gimple_build_assign (vback, t);
7176 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
917948d3 7177
acf0174b 7178 t = build2 (fd->loop.cond_code, boolean_type_node,
ed20ae98
TS
7179 DECL_P (vback) && TREE_ADDRESSABLE (vback)
7180 ? t : vback, e);
7181 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
acf0174b 7182 }
917948d3 7183
acf0174b 7184 /* Remove GIMPLE_OMP_CONTINUE. */
ed20ae98 7185 gsi_remove (&gsi, true);
b8698a0f 7186
acf0174b
JJ
7187 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
7188 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
50674e96 7189
acf0174b 7190 /* Trip update code goes into TRIP_UPDATE_BB. */
ed20ae98 7191 gsi = gsi_start_bb (trip_update_bb);
953ff289 7192
acf0174b
JJ
7193 t = build_int_cst (itype, 1);
7194 t = build2 (PLUS_EXPR, itype, trip_main, t);
538dd0b7
DM
7195 assign_stmt = gimple_build_assign (trip_back, t);
7196 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
acf0174b 7197 }
953ff289 7198
726a989a 7199 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
ed20ae98
TS
7200 gsi = gsi_last_bb (exit_bb);
7201 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
acf0174b 7202 {
ed20ae98 7203 t = gimple_omp_return_lhs (gsi_stmt (gsi));
41dbbb37
TS
7204 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
7205 gcc_checking_assert (t == NULL_TREE);
7206 else
7207 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
acf0174b 7208 }
ed20ae98 7209 gsi_remove (&gsi, true);
953ff289 7210
50674e96 7211 /* Connect the new blocks. */
e5c95afe
ZD
7212 find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
7213 find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
917948d3 7214
acf0174b
JJ
7215 if (!broken_loop)
7216 {
7217 se = find_edge (cont_bb, body_bb);
7218 if (gimple_omp_for_combined_p (fd->for_stmt))
7219 {
7220 remove_edge (se);
7221 se = NULL;
7222 }
7223 else if (fd->collapse > 1)
7224 {
7225 remove_edge (se);
7226 se = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
7227 }
7228 else
7229 se->flags = EDGE_TRUE_VALUE;
7230 find_edge (cont_bb, trip_update_bb)->flags
7231 = se ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
917948d3 7232
acf0174b
JJ
7233 redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb);
7234 }
917948d3
ZD
7235
7236 if (gimple_in_ssa_p (cfun))
7237 {
538dd0b7
DM
7238 gphi_iterator psi;
7239 gphi *phi;
726a989a 7240 edge re, ene;
726a989a
RB
7241 edge_var_map *vm;
7242 size_t i;
7243
acf0174b
JJ
7244 gcc_assert (fd->collapse == 1 && !broken_loop);
7245
917948d3
ZD
7246 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
7247 remove arguments of the phi nodes in fin_bb. We need to create
7248 appropriate phi nodes in iter_part_bb instead. */
7249 se = single_pred_edge (fin_bb);
7250 re = single_succ_edge (trip_update_bb);
b787e7a2 7251 vec<edge_var_map> *head = redirect_edge_var_map_vector (re);
917948d3
ZD
7252 ene = single_succ_edge (entry_bb);
7253
726a989a 7254 psi = gsi_start_phis (fin_bb);
9771b263 7255 for (i = 0; !gsi_end_p (psi) && head->iterate (i, &vm);
726a989a 7256 gsi_next (&psi), ++i)
917948d3 7257 {
538dd0b7 7258 gphi *nphi;
f5045c96 7259 source_location locus;
726a989a 7260
538dd0b7 7261 phi = psi.phi ();
726a989a
RB
7262 t = gimple_phi_result (phi);
7263 gcc_assert (t == redirect_edge_var_map_result (vm));
917948d3 7264 nphi = create_phi_node (t, iter_part_bb);
917948d3
ZD
7265
7266 t = PHI_ARG_DEF_FROM_EDGE (phi, se);
f5045c96
AM
7267 locus = gimple_phi_arg_location_from_edge (phi, se);
7268
a68ab351 7269 /* A special case -- fd->loop.v is not yet computed in
ed20ae98 7270 iter_part_bb, we need to use vextra instead. */
a68ab351 7271 if (t == fd->loop.v)
ed20ae98 7272 t = vextra;
9e227d60 7273 add_phi_arg (nphi, t, ene, locus);
f5045c96 7274 locus = redirect_edge_var_map_location (vm);
9e227d60 7275 add_phi_arg (nphi, redirect_edge_var_map_def (vm), re, locus);
726a989a 7276 }
56f6033d 7277 gcc_assert (gsi_end_p (psi) && i == head->length ());
726a989a
RB
7278 redirect_edge_var_map_clear (re);
7279 while (1)
7280 {
7281 psi = gsi_start_phis (fin_bb);
7282 if (gsi_end_p (psi))
7283 break;
7284 remove_phi_node (&psi, false);
917948d3 7285 }
917948d3
ZD
7286
7287 /* Make phi node for trip. */
7288 phi = create_phi_node (trip_main, iter_part_bb);
f5045c96 7289 add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb),
9e227d60 7290 UNKNOWN_LOCATION);
f5045c96 7291 add_phi_arg (phi, trip_init, single_succ_edge (entry_bb),
9e227d60 7292 UNKNOWN_LOCATION);
917948d3
ZD
7293 }
7294
acf0174b
JJ
7295 if (!broken_loop)
7296 set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
917948d3
ZD
7297 set_immediate_dominator (CDI_DOMINATORS, iter_part_bb,
7298 recompute_dominator (CDI_DOMINATORS, iter_part_bb));
7299 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
7300 recompute_dominator (CDI_DOMINATORS, fin_bb));
7301 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb,
7302 recompute_dominator (CDI_DOMINATORS, seq_start_bb));
7303 set_immediate_dominator (CDI_DOMINATORS, body_bb,
7304 recompute_dominator (CDI_DOMINATORS, body_bb));
6093bc06 7305
acf0174b
JJ
7306 if (!broken_loop)
7307 {
7308 struct loop *trip_loop = alloc_loop ();
7309 trip_loop->header = iter_part_bb;
7310 trip_loop->latch = trip_update_bb;
7311 add_loop (trip_loop, iter_part_bb->loop_father);
6093bc06 7312
acf0174b
JJ
7313 if (!gimple_omp_for_combined_p (fd->for_stmt))
7314 {
7315 struct loop *loop = alloc_loop ();
7316 loop->header = body_bb;
01dde9b0
JJ
7317 if (collapse_bb == NULL)
7318 loop->latch = cont_bb;
acf0174b
JJ
7319 add_loop (loop, trip_loop);
7320 }
7321 }
953ff289
DN
7322}
7323
9a771876
JJ
7324/* A subroutine of expand_omp_for. Generate code for _Cilk_for loop.
7325 Given parameters:
7326 for (V = N1; V cond N2; V += STEP) BODY;
7327
7328 where COND is "<" or ">" or "!=", we generate pseudocode
7329
7330 for (ind_var = low; ind_var < high; ind_var++)
7331 {
7332 V = n1 + (ind_var * STEP)
7333
7334 <BODY>
7335 }
7336
7337 In the above pseudocode, low and high are function parameters of the
7338 child function. In the function below, we are inserting a temp.
7339 variable that will be making a call to two OMP functions that will not be
7340 found in the body of _Cilk_for (since OMP_FOR cannot be mixed
7341 with _Cilk_for). These functions are replaced with low and high
7342 by the function that handles taskreg. */
7343
7344
7345static void
7346expand_cilk_for (struct omp_region *region, struct omp_for_data *fd)
7347{
7348 bool broken_loop = region->cont == NULL;
7349 basic_block entry_bb = region->entry;
7350 basic_block cont_bb = region->cont;
7351
7352 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
7353 gcc_assert (broken_loop
7354 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
7355 basic_block l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
7356 basic_block l1_bb, l2_bb;
7357
7358 if (!broken_loop)
7359 {
7360 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
7361 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
7362 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
7363 l2_bb = BRANCH_EDGE (entry_bb)->dest;
7364 }
7365 else
7366 {
7367 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
7368 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
7369 l2_bb = single_succ (l1_bb);
7370 }
7371 basic_block exit_bb = region->exit;
7372 basic_block l2_dom_bb = NULL;
7373
7374 gimple_stmt_iterator gsi = gsi_last_bb (entry_bb);
7375
7376 /* Below statements until the "tree high_val = ..." are pseudo statements
7377 used to pass information to be used by expand_omp_taskreg.
7378 low_val and high_val will be replaced by the __low and __high
7379 parameter from the child function.
7380
7381 The call_exprs part is a place-holder, it is mainly used
7382 to distinctly identify to the top-level part that this is
7383 where we should put low and high (reasoning given in header
7384 comment). */
7385
7386 tree child_fndecl
538dd0b7
DM
7387 = gimple_omp_parallel_child_fn (
7388 as_a <gomp_parallel *> (last_stmt (region->outer->entry)));
9a771876
JJ
7389 tree t, low_val = NULL_TREE, high_val = NULL_TREE;
7390 for (t = DECL_ARGUMENTS (child_fndecl); t; t = TREE_CHAIN (t))
7391 {
7392 if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__high"))
7393 high_val = t;
7394 else if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__low"))
7395 low_val = t;
7396 }
7397 gcc_assert (low_val && high_val);
7398
7399 tree type = TREE_TYPE (low_val);
7400 tree ind_var = create_tmp_reg (type, "__cilk_ind_var");
7401 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
7402
7403 /* Not needed in SSA form right now. */
7404 gcc_assert (!gimple_in_ssa_p (cfun));
7405 if (l2_dom_bb == NULL)
7406 l2_dom_bb = l1_bb;
7407
7408 tree n1 = low_val;
7409 tree n2 = high_val;
7410
7411 gimple stmt = gimple_build_assign (ind_var, n1);
7412
7413 /* Replace the GIMPLE_OMP_FOR statement. */
7414 gsi_replace (&gsi, stmt, true);
7415
7416 if (!broken_loop)
7417 {
7418 /* Code to control the increment goes in the CONT_BB. */
7419 gsi = gsi_last_bb (cont_bb);
7420 stmt = gsi_stmt (gsi);
7421 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
0d0e4a03
JJ
7422 stmt = gimple_build_assign (ind_var, PLUS_EXPR, ind_var,
7423 build_one_cst (type));
9a771876
JJ
7424
7425 /* Replace GIMPLE_OMP_CONTINUE. */
7426 gsi_replace (&gsi, stmt, true);
7427 }
7428
7429 /* Emit the condition in L1_BB. */
7430 gsi = gsi_after_labels (l1_bb);
7431 t = fold_build2 (MULT_EXPR, TREE_TYPE (fd->loop.step),
7432 fold_convert (TREE_TYPE (fd->loop.step), ind_var),
7433 fd->loop.step);
7434 if (POINTER_TYPE_P (TREE_TYPE (fd->loop.n1)))
7435 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (fd->loop.n1),
7436 fd->loop.n1, fold_convert (sizetype, t));
7437 else
7438 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loop.n1),
7439 fd->loop.n1, fold_convert (TREE_TYPE (fd->loop.n1), t));
7440 t = fold_convert (TREE_TYPE (fd->loop.v), t);
7441 expand_omp_build_assign (&gsi, fd->loop.v, t);
7442
7443 /* The condition is always '<' since the runtime will fill in the low
7444 and high values. */
7445 stmt = gimple_build_cond (LT_EXPR, ind_var, n2, NULL_TREE, NULL_TREE);
7446 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
7447
7448 /* Remove GIMPLE_OMP_RETURN. */
7449 gsi = gsi_last_bb (exit_bb);
7450 gsi_remove (&gsi, true);
7451
7452 /* Connect the new blocks. */
7453 remove_edge (FALLTHRU_EDGE (entry_bb));
7454
7455 edge e, ne;
7456 if (!broken_loop)
7457 {
7458 remove_edge (BRANCH_EDGE (entry_bb));
7459 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
7460
7461 e = BRANCH_EDGE (l1_bb);
7462 ne = FALLTHRU_EDGE (l1_bb);
7463 e->flags = EDGE_TRUE_VALUE;
7464 }
7465 else
7466 {
7467 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7468
7469 ne = single_succ_edge (l1_bb);
7470 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
7471
7472 }
7473 ne->flags = EDGE_FALSE_VALUE;
7474 e->probability = REG_BR_PROB_BASE * 7 / 8;
7475 ne->probability = REG_BR_PROB_BASE / 8;
7476
7477 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
7478 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
7479 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
7480
7481 if (!broken_loop)
7482 {
7483 struct loop *loop = alloc_loop ();
7484 loop->header = l1_bb;
7485 loop->latch = cont_bb;
7486 add_loop (loop, l1_bb->loop_father);
7487 loop->safelen = INT_MAX;
7488 }
7489
7490 /* Pick the correct library function based on the precision of the
7491 induction variable type. */
7492 tree lib_fun = NULL_TREE;
7493 if (TYPE_PRECISION (type) == 32)
7494 lib_fun = cilk_for_32_fndecl;
7495 else if (TYPE_PRECISION (type) == 64)
7496 lib_fun = cilk_for_64_fndecl;
7497 else
7498 gcc_unreachable ();
7499
7500 gcc_assert (fd->sched_kind == OMP_CLAUSE_SCHEDULE_CILKFOR);
7501
7502 /* WS_ARGS contains the library function flavor to call:
7503 __libcilkrts_cilk_for_64 or __libcilkrts_cilk_for_32), and the
7504 user-defined grain value. If the user does not define one, then zero
7505 is passed in by the parser. */
7506 vec_alloc (region->ws_args, 2);
7507 region->ws_args->quick_push (lib_fun);
7508 region->ws_args->quick_push (fd->chunk_size);
7509}
acf0174b 7510
74bf76ed
JJ
7511/* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
7512 loop. Given parameters:
7513
7514 for (V = N1; V cond N2; V += STEP) BODY;
7515
7516 where COND is "<" or ">", we generate pseudocode
7517
7518 V = N1;
7519 goto L1;
7520 L0:
7521 BODY;
7522 V += STEP;
7523 L1:
7524 if (V cond N2) goto L0; else goto L2;
7525 L2:
7526
7527 For collapsed loops, given parameters:
7528 collapse(3)
7529 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
7530 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
7531 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
7532 BODY;
7533
7534 we generate pseudocode
7535
7536 if (cond3 is <)
7537 adj = STEP3 - 1;
7538 else
7539 adj = STEP3 + 1;
7540 count3 = (adj + N32 - N31) / STEP3;
7541 if (cond2 is <)
7542 adj = STEP2 - 1;
7543 else
7544 adj = STEP2 + 1;
7545 count2 = (adj + N22 - N21) / STEP2;
7546 if (cond1 is <)
7547 adj = STEP1 - 1;
7548 else
7549 adj = STEP1 + 1;
7550 count1 = (adj + N12 - N11) / STEP1;
7551 count = count1 * count2 * count3;
7552 V = 0;
7553 V1 = N11;
7554 V2 = N21;
7555 V3 = N31;
7556 goto L1;
7557 L0:
7558 BODY;
7559 V += 1;
7560 V3 += STEP3;
7561 V2 += (V3 cond3 N32) ? 0 : STEP2;
7562 V3 = (V3 cond3 N32) ? V3 : N31;
7563 V1 += (V2 cond2 N22) ? 0 : STEP1;
7564 V2 = (V2 cond2 N22) ? V2 : N21;
7565 L1:
7566 if (V < count) goto L0; else goto L2;
7567 L2:
7568
7569 */
7570
7571static void
7572expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
7573{
7574 tree type, t;
7575 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, l2_bb, l2_dom_bb;
7576 gimple_stmt_iterator gsi;
7577 gimple stmt;
538dd0b7 7578 gcond *cond_stmt;
74bf76ed
JJ
7579 bool broken_loop = region->cont == NULL;
7580 edge e, ne;
7581 tree *counts = NULL;
7582 int i;
7583 tree safelen = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7584 OMP_CLAUSE_SAFELEN);
7585 tree simduid = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7586 OMP_CLAUSE__SIMDUID_);
acf0174b 7587 tree n1, n2;
74bf76ed
JJ
7588
7589 type = TREE_TYPE (fd->loop.v);
7590 entry_bb = region->entry;
7591 cont_bb = region->cont;
7592 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
7593 gcc_assert (broken_loop
7594 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
7595 l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
7596 if (!broken_loop)
7597 {
7598 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
7599 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
7600 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
7601 l2_bb = BRANCH_EDGE (entry_bb)->dest;
7602 }
7603 else
7604 {
7605 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
7606 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
7607 l2_bb = single_succ (l1_bb);
7608 }
7609 exit_bb = region->exit;
7610 l2_dom_bb = NULL;
7611
7612 gsi = gsi_last_bb (entry_bb);
7613
7614 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
7615 /* Not needed in SSA form right now. */
7616 gcc_assert (!gimple_in_ssa_p (cfun));
7617 if (fd->collapse > 1)
7618 {
7619 int first_zero_iter = -1;
7620 basic_block zero_iter_bb = l2_bb;
7621
7622 counts = XALLOCAVEC (tree, fd->collapse);
7623 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
7624 zero_iter_bb, first_zero_iter,
7625 l2_dom_bb);
7626 }
7627 if (l2_dom_bb == NULL)
7628 l2_dom_bb = l1_bb;
7629
acf0174b 7630 n1 = fd->loop.n1;
74bf76ed 7631 n2 = fd->loop.n2;
acf0174b
JJ
7632 if (gimple_omp_for_combined_into_p (fd->for_stmt))
7633 {
7634 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7635 OMP_CLAUSE__LOOPTEMP_);
7636 gcc_assert (innerc);
7637 n1 = OMP_CLAUSE_DECL (innerc);
7638 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7639 OMP_CLAUSE__LOOPTEMP_);
7640 gcc_assert (innerc);
7641 n2 = OMP_CLAUSE_DECL (innerc);
7642 expand_omp_build_assign (&gsi, fd->loop.v,
7643 fold_convert (type, n1));
7644 if (fd->collapse > 1)
7645 {
7646 gsi_prev (&gsi);
7647 expand_omp_for_init_vars (fd, &gsi, counts, NULL, n1);
7648 gsi_next (&gsi);
7649 }
7650 }
74bf76ed
JJ
7651 else
7652 {
7653 expand_omp_build_assign (&gsi, fd->loop.v,
7654 fold_convert (type, fd->loop.n1));
7655 if (fd->collapse > 1)
7656 for (i = 0; i < fd->collapse; i++)
7657 {
7658 tree itype = TREE_TYPE (fd->loops[i].v);
7659 if (POINTER_TYPE_P (itype))
7660 itype = signed_type_for (itype);
7661 t = fold_convert (TREE_TYPE (fd->loops[i].v), fd->loops[i].n1);
7662 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7663 }
7664 }
7665
7666 /* Remove the GIMPLE_OMP_FOR statement. */
7667 gsi_remove (&gsi, true);
7668
7669 if (!broken_loop)
7670 {
7671 /* Code to control the increment goes in the CONT_BB. */
7672 gsi = gsi_last_bb (cont_bb);
7673 stmt = gsi_stmt (gsi);
7674 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
7675
7676 if (POINTER_TYPE_P (type))
7677 t = fold_build_pointer_plus (fd->loop.v, fd->loop.step);
7678 else
7679 t = fold_build2 (PLUS_EXPR, type, fd->loop.v, fd->loop.step);
7680 expand_omp_build_assign (&gsi, fd->loop.v, t);
7681
7682 if (fd->collapse > 1)
7683 {
7684 i = fd->collapse - 1;
7685 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
7686 {
7687 t = fold_convert (sizetype, fd->loops[i].step);
7688 t = fold_build_pointer_plus (fd->loops[i].v, t);
7689 }
7690 else
7691 {
7692 t = fold_convert (TREE_TYPE (fd->loops[i].v),
7693 fd->loops[i].step);
7694 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
7695 fd->loops[i].v, t);
7696 }
7697 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7698
7699 for (i = fd->collapse - 1; i > 0; i--)
7700 {
7701 tree itype = TREE_TYPE (fd->loops[i].v);
7702 tree itype2 = TREE_TYPE (fd->loops[i - 1].v);
7703 if (POINTER_TYPE_P (itype2))
7704 itype2 = signed_type_for (itype2);
7705 t = build3 (COND_EXPR, itype2,
7706 build2 (fd->loops[i].cond_code, boolean_type_node,
7707 fd->loops[i].v,
7708 fold_convert (itype, fd->loops[i].n2)),
7709 build_int_cst (itype2, 0),
7710 fold_convert (itype2, fd->loops[i - 1].step));
7711 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i - 1].v)))
7712 t = fold_build_pointer_plus (fd->loops[i - 1].v, t);
7713 else
7714 t = fold_build2 (PLUS_EXPR, itype2, fd->loops[i - 1].v, t);
7715 expand_omp_build_assign (&gsi, fd->loops[i - 1].v, t);
7716
7717 t = build3 (COND_EXPR, itype,
7718 build2 (fd->loops[i].cond_code, boolean_type_node,
7719 fd->loops[i].v,
7720 fold_convert (itype, fd->loops[i].n2)),
7721 fd->loops[i].v,
7722 fold_convert (itype, fd->loops[i].n1));
7723 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7724 }
7725 }
7726
7727 /* Remove GIMPLE_OMP_CONTINUE. */
7728 gsi_remove (&gsi, true);
7729 }
7730
7731 /* Emit the condition in L1_BB. */
7732 gsi = gsi_start_bb (l1_bb);
7733
7734 t = fold_convert (type, n2);
7735 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7736 false, GSI_CONTINUE_LINKING);
7737 t = build2 (fd->loop.cond_code, boolean_type_node, fd->loop.v, t);
538dd0b7
DM
7738 cond_stmt = gimple_build_cond_empty (t);
7739 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
7740 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt), expand_omp_regimplify_p,
74bf76ed 7741 NULL, NULL)
538dd0b7 7742 || walk_tree (gimple_cond_rhs_ptr (cond_stmt), expand_omp_regimplify_p,
74bf76ed
JJ
7743 NULL, NULL))
7744 {
538dd0b7
DM
7745 gsi = gsi_for_stmt (cond_stmt);
7746 gimple_regimplify_operands (cond_stmt, &gsi);
74bf76ed
JJ
7747 }
7748
7749 /* Remove GIMPLE_OMP_RETURN. */
7750 gsi = gsi_last_bb (exit_bb);
7751 gsi_remove (&gsi, true);
7752
7753 /* Connect the new blocks. */
7754 remove_edge (FALLTHRU_EDGE (entry_bb));
7755
7756 if (!broken_loop)
7757 {
7758 remove_edge (BRANCH_EDGE (entry_bb));
7759 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
7760
7761 e = BRANCH_EDGE (l1_bb);
7762 ne = FALLTHRU_EDGE (l1_bb);
7763 e->flags = EDGE_TRUE_VALUE;
7764 }
7765 else
7766 {
7767 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7768
7769 ne = single_succ_edge (l1_bb);
7770 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
7771
7772 }
7773 ne->flags = EDGE_FALSE_VALUE;
7774 e->probability = REG_BR_PROB_BASE * 7 / 8;
7775 ne->probability = REG_BR_PROB_BASE / 8;
7776
7777 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
7778 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
7779 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
7780
7781 if (!broken_loop)
7782 {
7783 struct loop *loop = alloc_loop ();
7784 loop->header = l1_bb;
01dde9b0 7785 loop->latch = cont_bb;
74bf76ed
JJ
7786 add_loop (loop, l1_bb->loop_father);
7787 if (safelen == NULL_TREE)
7788 loop->safelen = INT_MAX;
7789 else
7790 {
7791 safelen = OMP_CLAUSE_SAFELEN_EXPR (safelen);
b46ebd6c
JJ
7792 if (TREE_CODE (safelen) != INTEGER_CST)
7793 loop->safelen = 0;
7794 else if (!tree_fits_uhwi_p (safelen)
7795 || tree_to_uhwi (safelen) > INT_MAX)
74bf76ed
JJ
7796 loop->safelen = INT_MAX;
7797 else
ae7e9ddd 7798 loop->safelen = tree_to_uhwi (safelen);
74bf76ed
JJ
7799 if (loop->safelen == 1)
7800 loop->safelen = 0;
7801 }
7802 if (simduid)
7803 {
7804 loop->simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
7805 cfun->has_simduid_loops = true;
7806 }
ea0f3e87 7807 /* If not -fno-tree-loop-vectorize, hint that we want to vectorize
74bf76ed 7808 the loop. */
ea0f3e87
XDL
7809 if ((flag_tree_loop_vectorize
7810 || (!global_options_set.x_flag_tree_loop_vectorize
7811 && !global_options_set.x_flag_tree_vectorize))
ab2ffbeb 7812 && flag_tree_loop_optimize
74bf76ed
JJ
7813 && loop->safelen > 1)
7814 {
b15b5979
EB
7815 loop->force_vectorize = true;
7816 cfun->has_force_vectorize_loops = true;
74bf76ed
JJ
7817 }
7818 }
7819}
7820
953ff289 7821
41dbbb37 7822/* Expand the OMP loop defined by REGION. */
953ff289 7823
50674e96 7824static void
acf0174b 7825expand_omp_for (struct omp_region *region, gimple inner_stmt)
50674e96
DN
7826{
7827 struct omp_for_data fd;
a68ab351 7828 struct omp_for_data_loop *loops;
953ff289 7829
a68ab351
JJ
7830 loops
7831 = (struct omp_for_data_loop *)
726a989a 7832 alloca (gimple_omp_for_collapse (last_stmt (region->entry))
a68ab351 7833 * sizeof (struct omp_for_data_loop));
538dd0b7
DM
7834 extract_omp_for_data (as_a <gomp_for *> (last_stmt (region->entry)),
7835 &fd, loops);
21a66e91 7836 region->sched_kind = fd.sched_kind;
953ff289 7837
135a171d
JJ
7838 gcc_assert (EDGE_COUNT (region->entry->succs) == 2);
7839 BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
7840 FALLTHRU_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
7841 if (region->cont)
7842 {
7843 gcc_assert (EDGE_COUNT (region->cont->succs) == 2);
7844 BRANCH_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
7845 FALLTHRU_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
7846 }
6093bc06 7847 else
1aa95df7 7848 /* If there isn't a continue then this is a degerate case where
6093bc06
RB
7849 the introduction of abnormal edges during lowering will prevent
7850 original loops from being detected. Fix that up. */
7851 loops_state_set (LOOPS_NEED_FIXUP);
135a171d 7852
0aadce73 7853 if (gimple_omp_for_kind (fd.for_stmt) & GF_OMP_FOR_SIMD)
74bf76ed 7854 expand_omp_simd (region, &fd);
9a771876
JJ
7855 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
7856 expand_cilk_for (region, &fd);
74bf76ed 7857 else if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
acf0174b 7858 && !fd.have_ordered)
953ff289
DN
7859 {
7860 if (fd.chunk_size == NULL)
acf0174b 7861 expand_omp_for_static_nochunk (region, &fd, inner_stmt);
953ff289 7862 else
acf0174b 7863 expand_omp_for_static_chunk (region, &fd, inner_stmt);
953ff289
DN
7864 }
7865 else
7866 {
a68ab351
JJ
7867 int fn_index, start_ix, next_ix;
7868
74bf76ed
JJ
7869 gcc_assert (gimple_omp_for_kind (fd.for_stmt)
7870 == GF_OMP_FOR_KIND_FOR);
9abd5ed9
JJ
7871 if (fd.chunk_size == NULL
7872 && fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
7873 fd.chunk_size = integer_zero_node;
a68ab351
JJ
7874 gcc_assert (fd.sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
7875 fn_index = (fd.sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
726a989a 7876 ? 3 : fd.sched_kind;
a68ab351 7877 fn_index += fd.have_ordered * 4;
e79983f4
MM
7878 start_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_START) + fn_index;
7879 next_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT) + fn_index;
a68ab351
JJ
7880 if (fd.iter_type == long_long_unsigned_type_node)
7881 {
e79983f4
MM
7882 start_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
7883 - (int)BUILT_IN_GOMP_LOOP_STATIC_START);
7884 next_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
7885 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT);
a68ab351 7886 }
bbbbb16a 7887 expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
acf0174b 7888 (enum built_in_function) next_ix, inner_stmt);
953ff289 7889 }
5f40b3cb 7890
a5efada7
RG
7891 if (gimple_in_ssa_p (cfun))
7892 update_ssa (TODO_update_ssa_only_virtuals);
953ff289
DN
7893}
7894
953ff289
DN
7895
7896/* Expand code for an OpenMP sections directive. In pseudo code, we generate
7897
953ff289
DN
7898 v = GOMP_sections_start (n);
7899 L0:
7900 switch (v)
7901 {
7902 case 0:
7903 goto L2;
7904 case 1:
7905 section 1;
7906 goto L1;
7907 case 2:
7908 ...
7909 case n:
7910 ...
953ff289
DN
7911 default:
7912 abort ();
7913 }
7914 L1:
7915 v = GOMP_sections_next ();
7916 goto L0;
7917 L2:
7918 reduction;
7919
50674e96 7920 If this is a combined parallel sections, replace the call to
917948d3 7921 GOMP_sections_start with call to GOMP_sections_next. */
953ff289
DN
7922
7923static void
50674e96 7924expand_omp_sections (struct omp_region *region)
953ff289 7925{
0f900dfa 7926 tree t, u, vin = NULL, vmain, vnext, l2;
726a989a 7927 unsigned len;
e5c95afe 7928 basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
726a989a 7929 gimple_stmt_iterator si, switch_si;
538dd0b7
DM
7930 gomp_sections *sections_stmt;
7931 gimple stmt;
7932 gomp_continue *cont;
c34938a8
JJ
7933 edge_iterator ei;
7934 edge e;
777f7f9a 7935 struct omp_region *inner;
726a989a 7936 unsigned i, casei;
e5c95afe 7937 bool exit_reachable = region->cont != NULL;
953ff289 7938
65e7bfe3 7939 gcc_assert (region->exit != NULL);
777f7f9a 7940 entry_bb = region->entry;
e5c95afe 7941 l0_bb = single_succ (entry_bb);
777f7f9a 7942 l1_bb = region->cont;
e5c95afe 7943 l2_bb = region->exit;
65e7bfe3
JJ
7944 if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
7945 l2 = gimple_block_label (l2_bb);
7946 else
d3c673c7 7947 {
65e7bfe3
JJ
7948 /* This can happen if there are reductions. */
7949 len = EDGE_COUNT (l0_bb->succs);
7950 gcc_assert (len > 0);
7951 e = EDGE_SUCC (l0_bb, len - 1);
7952 si = gsi_last_bb (e->dest);
7953 l2 = NULL_TREE;
7954 if (gsi_end_p (si)
7955 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
7956 l2 = gimple_block_label (e->dest);
c34938a8 7957 else
65e7bfe3
JJ
7958 FOR_EACH_EDGE (e, ei, l0_bb->succs)
7959 {
7960 si = gsi_last_bb (e->dest);
7961 if (gsi_end_p (si)
7962 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
c34938a8 7963 {
65e7bfe3
JJ
7964 l2 = gimple_block_label (e->dest);
7965 break;
c34938a8 7966 }
65e7bfe3 7967 }
d3c673c7 7968 }
65e7bfe3
JJ
7969 if (exit_reachable)
7970 default_bb = create_empty_bb (l1_bb->prev_bb);
d3c673c7 7971 else
65e7bfe3 7972 default_bb = create_empty_bb (l0_bb);
50674e96
DN
7973
7974 /* We will build a switch() with enough cases for all the
726a989a 7975 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
50674e96 7976 and a default case to abort if something goes wrong. */
e5c95afe 7977 len = EDGE_COUNT (l0_bb->succs);
726a989a 7978
9771b263 7979 /* Use vec::quick_push on label_vec throughout, since we know the size
726a989a 7980 in advance. */
ef062b13 7981 auto_vec<tree> label_vec (len);
953ff289 7982
777f7f9a 7983 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
726a989a
RB
7984 GIMPLE_OMP_SECTIONS statement. */
7985 si = gsi_last_bb (entry_bb);
538dd0b7 7986 sections_stmt = as_a <gomp_sections *> (gsi_stmt (si));
726a989a
RB
7987 gcc_assert (gimple_code (sections_stmt) == GIMPLE_OMP_SECTIONS);
7988 vin = gimple_omp_sections_control (sections_stmt);
50674e96 7989 if (!is_combined_parallel (region))
953ff289 7990 {
50674e96
DN
7991 /* If we are not inside a combined parallel+sections region,
7992 call GOMP_sections_start. */
4befd127 7993 t = build_int_cst (unsigned_type_node, len - 1);
e79983f4 7994 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START);
726a989a 7995 stmt = gimple_build_call (u, 1, t);
953ff289 7996 }
917948d3
ZD
7997 else
7998 {
7999 /* Otherwise, call GOMP_sections_next. */
e79983f4 8000 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
726a989a 8001 stmt = gimple_build_call (u, 0);
917948d3 8002 }
726a989a
RB
8003 gimple_call_set_lhs (stmt, vin);
8004 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
8005 gsi_remove (&si, true);
8006
8007 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
8008 L0_BB. */
8009 switch_si = gsi_last_bb (l0_bb);
8010 gcc_assert (gimple_code (gsi_stmt (switch_si)) == GIMPLE_OMP_SECTIONS_SWITCH);
917948d3
ZD
8011 if (exit_reachable)
8012 {
538dd0b7 8013 cont = as_a <gomp_continue *> (last_stmt (l1_bb));
726a989a
RB
8014 gcc_assert (gimple_code (cont) == GIMPLE_OMP_CONTINUE);
8015 vmain = gimple_omp_continue_control_use (cont);
8016 vnext = gimple_omp_continue_control_def (cont);
917948d3
ZD
8017 }
8018 else
8019 {
8020 vmain = vin;
8021 vnext = NULL_TREE;
8022 }
953ff289 8023
65e7bfe3 8024 t = build_case_label (build_int_cst (unsigned_type_node, 0), NULL, l2);
9771b263 8025 label_vec.quick_push (t);
65e7bfe3 8026 i = 1;
d3c673c7 8027
726a989a 8028 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
e5c95afe
ZD
8029 for (inner = region->inner, casei = 1;
8030 inner;
8031 inner = inner->next, i++, casei++)
953ff289 8032 {
50674e96
DN
8033 basic_block s_entry_bb, s_exit_bb;
8034
c34938a8 8035 /* Skip optional reduction region. */
726a989a 8036 if (inner->type == GIMPLE_OMP_ATOMIC_LOAD)
c34938a8
JJ
8037 {
8038 --i;
8039 --casei;
8040 continue;
8041 }
8042
777f7f9a
RH
8043 s_entry_bb = inner->entry;
8044 s_exit_bb = inner->exit;
953ff289 8045
726a989a 8046 t = gimple_block_label (s_entry_bb);
e5c95afe 8047 u = build_int_cst (unsigned_type_node, casei);
3d528853 8048 u = build_case_label (u, NULL, t);
9771b263 8049 label_vec.quick_push (u);
777f7f9a 8050
726a989a
RB
8051 si = gsi_last_bb (s_entry_bb);
8052 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SECTION);
8053 gcc_assert (i < len || gimple_omp_section_last_p (gsi_stmt (si)));
8054 gsi_remove (&si, true);
777f7f9a 8055 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
d3c673c7
JJ
8056
8057 if (s_exit_bb == NULL)
8058 continue;
8059
726a989a
RB
8060 si = gsi_last_bb (s_exit_bb);
8061 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
8062 gsi_remove (&si, true);
d3c673c7 8063
50674e96 8064 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
953ff289
DN
8065 }
8066
50674e96 8067 /* Error handling code goes in DEFAULT_BB. */
726a989a 8068 t = gimple_block_label (default_bb);
3d528853 8069 u = build_case_label (NULL, NULL, t);
777f7f9a 8070 make_edge (l0_bb, default_bb, 0);
726338f4 8071 add_bb_to_loop (default_bb, current_loops->tree_root);
953ff289 8072
fd8d363e 8073 stmt = gimple_build_switch (vmain, u, label_vec);
726a989a
RB
8074 gsi_insert_after (&switch_si, stmt, GSI_SAME_STMT);
8075 gsi_remove (&switch_si, true);
726a989a
RB
8076
8077 si = gsi_start_bb (default_bb);
e79983f4 8078 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
726a989a 8079 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
50674e96 8080
e5c95afe 8081 if (exit_reachable)
d3c673c7 8082 {
e79983f4
MM
8083 tree bfn_decl;
8084
e5c95afe 8085 /* Code to get the next section goes in L1_BB. */
726a989a
RB
8086 si = gsi_last_bb (l1_bb);
8087 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
953ff289 8088
e79983f4
MM
8089 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
8090 stmt = gimple_build_call (bfn_decl, 0);
726a989a
RB
8091 gimple_call_set_lhs (stmt, vnext);
8092 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
8093 gsi_remove (&si, true);
50674e96 8094
e5c95afe 8095 single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
d3c673c7 8096 }
50674e96 8097
65e7bfe3
JJ
8098 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
8099 si = gsi_last_bb (l2_bb);
8100 if (gimple_omp_return_nowait_p (gsi_stmt (si)))
8101 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
acf0174b
JJ
8102 else if (gimple_omp_return_lhs (gsi_stmt (si)))
8103 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL);
65e7bfe3
JJ
8104 else
8105 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
8106 stmt = gimple_build_call (t, 0);
acf0174b
JJ
8107 if (gimple_omp_return_lhs (gsi_stmt (si)))
8108 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (si)));
65e7bfe3
JJ
8109 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
8110 gsi_remove (&si, true);
8111
917948d3 8112 set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
50674e96 8113}
953ff289 8114
953ff289 8115
777f7f9a
RH
8116/* Expand code for an OpenMP single directive. We've already expanded
8117 much of the code, here we simply place the GOMP_barrier call. */
8118
8119static void
8120expand_omp_single (struct omp_region *region)
8121{
8122 basic_block entry_bb, exit_bb;
726a989a 8123 gimple_stmt_iterator si;
777f7f9a
RH
8124
8125 entry_bb = region->entry;
8126 exit_bb = region->exit;
8127
726a989a 8128 si = gsi_last_bb (entry_bb);
726a989a
RB
8129 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE);
8130 gsi_remove (&si, true);
777f7f9a
RH
8131 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
8132
726a989a 8133 si = gsi_last_bb (exit_bb);
acf0174b
JJ
8134 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
8135 {
8136 tree t = gimple_omp_return_lhs (gsi_stmt (si));
8137 gsi_insert_after (&si, build_omp_barrier (t), GSI_SAME_STMT);
8138 }
726a989a 8139 gsi_remove (&si, true);
777f7f9a
RH
8140 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
8141}
8142
8143
8144/* Generic expansion for OpenMP synchronization directives: master,
8145 ordered and critical. All we need to do here is remove the entry
8146 and exit markers for REGION. */
50674e96
DN
8147
8148static void
8149expand_omp_synch (struct omp_region *region)
8150{
8151 basic_block entry_bb, exit_bb;
726a989a 8152 gimple_stmt_iterator si;
50674e96 8153
777f7f9a
RH
8154 entry_bb = region->entry;
8155 exit_bb = region->exit;
50674e96 8156
726a989a
RB
8157 si = gsi_last_bb (entry_bb);
8158 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE
8159 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASTER
acf0174b 8160 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TASKGROUP
726a989a 8161 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ORDERED
acf0174b
JJ
8162 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CRITICAL
8163 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TEAMS);
726a989a 8164 gsi_remove (&si, true);
50674e96
DN
8165 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
8166
d3c673c7
JJ
8167 if (exit_bb)
8168 {
726a989a
RB
8169 si = gsi_last_bb (exit_bb);
8170 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
8171 gsi_remove (&si, true);
d3c673c7
JJ
8172 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
8173 }
50674e96 8174}
953ff289 8175
20906c66
JJ
8176/* A subroutine of expand_omp_atomic. Attempt to implement the atomic
8177 operation as a normal volatile load. */
8178
8179static bool
05409788
RH
8180expand_omp_atomic_load (basic_block load_bb, tree addr,
8181 tree loaded_val, int index)
20906c66 8182{
05409788
RH
8183 enum built_in_function tmpbase;
8184 gimple_stmt_iterator gsi;
8185 basic_block store_bb;
8186 location_t loc;
8187 gimple stmt;
8188 tree decl, call, type, itype;
8189
8190 gsi = gsi_last_bb (load_bb);
8191 stmt = gsi_stmt (gsi);
8192 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
8193 loc = gimple_location (stmt);
8194
8195 /* ??? If the target does not implement atomic_load_optab[mode], and mode
8196 is smaller than word size, then expand_atomic_load assumes that the load
8197 is atomic. We could avoid the builtin entirely in this case. */
8198
8199 tmpbase = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
8200 decl = builtin_decl_explicit (tmpbase);
8201 if (decl == NULL_TREE)
8202 return false;
8203
8204 type = TREE_TYPE (loaded_val);
8205 itype = TREE_TYPE (TREE_TYPE (decl));
8206
8207 call = build_call_expr_loc (loc, decl, 2, addr,
acf0174b
JJ
8208 build_int_cst (NULL,
8209 gimple_omp_atomic_seq_cst_p (stmt)
8210 ? MEMMODEL_SEQ_CST
8211 : MEMMODEL_RELAXED));
05409788
RH
8212 if (!useless_type_conversion_p (type, itype))
8213 call = fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
8214 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
8215
8216 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
8217 gsi_remove (&gsi, true);
8218
8219 store_bb = single_succ (load_bb);
8220 gsi = gsi_last_bb (store_bb);
8221 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
8222 gsi_remove (&gsi, true);
8223
8224 if (gimple_in_ssa_p (cfun))
8225 update_ssa (TODO_update_ssa_no_phi);
8226
8227 return true;
20906c66
JJ
8228}
8229
8230/* A subroutine of expand_omp_atomic. Attempt to implement the atomic
8231 operation as a normal volatile store. */
8232
8233static bool
05409788
RH
8234expand_omp_atomic_store (basic_block load_bb, tree addr,
8235 tree loaded_val, tree stored_val, int index)
20906c66 8236{
05409788
RH
8237 enum built_in_function tmpbase;
8238 gimple_stmt_iterator gsi;
8239 basic_block store_bb = single_succ (load_bb);
8240 location_t loc;
8241 gimple stmt;
8242 tree decl, call, type, itype;
ef4bddc2 8243 machine_mode imode;
05409788
RH
8244 bool exchange;
8245
8246 gsi = gsi_last_bb (load_bb);
8247 stmt = gsi_stmt (gsi);
8248 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
8249
8250 /* If the load value is needed, then this isn't a store but an exchange. */
8251 exchange = gimple_omp_atomic_need_value_p (stmt);
8252
8253 gsi = gsi_last_bb (store_bb);
8254 stmt = gsi_stmt (gsi);
8255 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE);
8256 loc = gimple_location (stmt);
8257
8258 /* ??? If the target does not implement atomic_store_optab[mode], and mode
8259 is smaller than word size, then expand_atomic_store assumes that the store
8260 is atomic. We could avoid the builtin entirely in this case. */
8261
8262 tmpbase = (exchange ? BUILT_IN_ATOMIC_EXCHANGE_N : BUILT_IN_ATOMIC_STORE_N);
8263 tmpbase = (enum built_in_function) ((int) tmpbase + index + 1);
8264 decl = builtin_decl_explicit (tmpbase);
8265 if (decl == NULL_TREE)
8266 return false;
8267
8268 type = TREE_TYPE (stored_val);
8269
8270 /* Dig out the type of the function's second argument. */
8271 itype = TREE_TYPE (decl);
8272 itype = TYPE_ARG_TYPES (itype);
8273 itype = TREE_CHAIN (itype);
8274 itype = TREE_VALUE (itype);
8275 imode = TYPE_MODE (itype);
8276
8277 if (exchange && !can_atomic_exchange_p (imode, true))
8278 return false;
8279
8280 if (!useless_type_conversion_p (itype, type))
8281 stored_val = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, stored_val);
8282 call = build_call_expr_loc (loc, decl, 3, addr, stored_val,
acf0174b
JJ
8283 build_int_cst (NULL,
8284 gimple_omp_atomic_seq_cst_p (stmt)
8285 ? MEMMODEL_SEQ_CST
8286 : MEMMODEL_RELAXED));
05409788
RH
8287 if (exchange)
8288 {
8289 if (!useless_type_conversion_p (type, itype))
8290 call = build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
8291 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
8292 }
8293
8294 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
8295 gsi_remove (&gsi, true);
8296
8297 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
8298 gsi = gsi_last_bb (load_bb);
8299 gsi_remove (&gsi, true);
8300
8301 if (gimple_in_ssa_p (cfun))
8302 update_ssa (TODO_update_ssa_no_phi);
8303
8304 return true;
20906c66
JJ
8305}
8306
a509ebb5 8307/* A subroutine of expand_omp_atomic. Attempt to implement the atomic
86951993 8308 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
a509ebb5
RL
8309 size of the data type, and thus usable to find the index of the builtin
8310 decl. Returns false if the expression is not of the proper form. */
8311
8312static bool
8313expand_omp_atomic_fetch_op (basic_block load_bb,
8314 tree addr, tree loaded_val,
8315 tree stored_val, int index)
8316{
e79983f4 8317 enum built_in_function oldbase, newbase, tmpbase;
a509ebb5 8318 tree decl, itype, call;
20906c66 8319 tree lhs, rhs;
a509ebb5 8320 basic_block store_bb = single_succ (load_bb);
726a989a
RB
8321 gimple_stmt_iterator gsi;
8322 gimple stmt;
db3927fb 8323 location_t loc;
86951993 8324 enum tree_code code;
20906c66 8325 bool need_old, need_new;
ef4bddc2 8326 machine_mode imode;
acf0174b 8327 bool seq_cst;
a509ebb5
RL
8328
8329 /* We expect to find the following sequences:
b8698a0f 8330
a509ebb5 8331 load_bb:
726a989a 8332 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
a509ebb5
RL
8333
8334 store_bb:
8335 val = tmp OP something; (or: something OP tmp)
b8698a0f 8336 GIMPLE_OMP_STORE (val)
a509ebb5 8337
b8698a0f 8338 ???FIXME: Allow a more flexible sequence.
a509ebb5 8339 Perhaps use data flow to pick the statements.
b8698a0f 8340
a509ebb5
RL
8341 */
8342
726a989a
RB
8343 gsi = gsi_after_labels (store_bb);
8344 stmt = gsi_stmt (gsi);
db3927fb 8345 loc = gimple_location (stmt);
726a989a 8346 if (!is_gimple_assign (stmt))
a509ebb5 8347 return false;
726a989a
RB
8348 gsi_next (&gsi);
8349 if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE)
a509ebb5 8350 return false;
20906c66
JJ
8351 need_new = gimple_omp_atomic_need_value_p (gsi_stmt (gsi));
8352 need_old = gimple_omp_atomic_need_value_p (last_stmt (load_bb));
acf0174b 8353 seq_cst = gimple_omp_atomic_seq_cst_p (last_stmt (load_bb));
20906c66 8354 gcc_checking_assert (!need_old || !need_new);
a509ebb5 8355
726a989a 8356 if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
a509ebb5
RL
8357 return false;
8358
a509ebb5 8359 /* Check for one of the supported fetch-op operations. */
86951993
AM
8360 code = gimple_assign_rhs_code (stmt);
8361 switch (code)
a509ebb5
RL
8362 {
8363 case PLUS_EXPR:
8364 case POINTER_PLUS_EXPR:
86951993
AM
8365 oldbase = BUILT_IN_ATOMIC_FETCH_ADD_N;
8366 newbase = BUILT_IN_ATOMIC_ADD_FETCH_N;
a509ebb5
RL
8367 break;
8368 case MINUS_EXPR:
86951993
AM
8369 oldbase = BUILT_IN_ATOMIC_FETCH_SUB_N;
8370 newbase = BUILT_IN_ATOMIC_SUB_FETCH_N;
a509ebb5
RL
8371 break;
8372 case BIT_AND_EXPR:
86951993
AM
8373 oldbase = BUILT_IN_ATOMIC_FETCH_AND_N;
8374 newbase = BUILT_IN_ATOMIC_AND_FETCH_N;
a509ebb5
RL
8375 break;
8376 case BIT_IOR_EXPR:
86951993
AM
8377 oldbase = BUILT_IN_ATOMIC_FETCH_OR_N;
8378 newbase = BUILT_IN_ATOMIC_OR_FETCH_N;
a509ebb5
RL
8379 break;
8380 case BIT_XOR_EXPR:
86951993
AM
8381 oldbase = BUILT_IN_ATOMIC_FETCH_XOR_N;
8382 newbase = BUILT_IN_ATOMIC_XOR_FETCH_N;
a509ebb5
RL
8383 break;
8384 default:
8385 return false;
8386 }
86951993 8387
a509ebb5 8388 /* Make sure the expression is of the proper form. */
726a989a
RB
8389 if (operand_equal_p (gimple_assign_rhs1 (stmt), loaded_val, 0))
8390 rhs = gimple_assign_rhs2 (stmt);
8391 else if (commutative_tree_code (gimple_assign_rhs_code (stmt))
8392 && operand_equal_p (gimple_assign_rhs2 (stmt), loaded_val, 0))
8393 rhs = gimple_assign_rhs1 (stmt);
a509ebb5
RL
8394 else
8395 return false;
8396
e79983f4
MM
8397 tmpbase = ((enum built_in_function)
8398 ((need_new ? newbase : oldbase) + index + 1));
8399 decl = builtin_decl_explicit (tmpbase);
20790697
JJ
8400 if (decl == NULL_TREE)
8401 return false;
a509ebb5 8402 itype = TREE_TYPE (TREE_TYPE (decl));
86951993 8403 imode = TYPE_MODE (itype);
a509ebb5 8404
86951993
AM
8405 /* We could test all of the various optabs involved, but the fact of the
8406 matter is that (with the exception of i486 vs i586 and xadd) all targets
8407 that support any atomic operaton optab also implements compare-and-swap.
8408 Let optabs.c take care of expanding any compare-and-swap loop. */
cedb4a1a 8409 if (!can_compare_and_swap_p (imode, true))
a509ebb5
RL
8410 return false;
8411
726a989a
RB
8412 gsi = gsi_last_bb (load_bb);
8413 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
86951993
AM
8414
8415 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
8416 It only requires that the operation happen atomically. Thus we can
8417 use the RELAXED memory model. */
8418 call = build_call_expr_loc (loc, decl, 3, addr,
8419 fold_convert_loc (loc, itype, rhs),
acf0174b
JJ
8420 build_int_cst (NULL,
8421 seq_cst ? MEMMODEL_SEQ_CST
8422 : MEMMODEL_RELAXED));
86951993 8423
20906c66
JJ
8424 if (need_old || need_new)
8425 {
8426 lhs = need_old ? loaded_val : stored_val;
8427 call = fold_convert_loc (loc, TREE_TYPE (lhs), call);
8428 call = build2_loc (loc, MODIFY_EXPR, void_type_node, lhs, call);
8429 }
8430 else
8431 call = fold_convert_loc (loc, void_type_node, call);
726a989a
RB
8432 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
8433 gsi_remove (&gsi, true);
a509ebb5 8434
726a989a
RB
8435 gsi = gsi_last_bb (store_bb);
8436 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
8437 gsi_remove (&gsi, true);
8438 gsi = gsi_last_bb (store_bb);
8439 gsi_remove (&gsi, true);
a509ebb5
RL
8440
8441 if (gimple_in_ssa_p (cfun))
8442 update_ssa (TODO_update_ssa_no_phi);
8443
8444 return true;
8445}
8446
8447/* A subroutine of expand_omp_atomic. Implement the atomic operation as:
8448
8449 oldval = *addr;
8450 repeat:
8451 newval = rhs; // with oldval replacing *addr in rhs
8452 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
8453 if (oldval != newval)
8454 goto repeat;
8455
8456 INDEX is log2 of the size of the data type, and thus usable to find the
8457 index of the builtin decl. */
8458
8459static bool
8460expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
8461 tree addr, tree loaded_val, tree stored_val,
8462 int index)
8463{
c18c98c0 8464 tree loadedi, storedi, initial, new_storedi, old_vali;
a509ebb5 8465 tree type, itype, cmpxchg, iaddr;
726a989a 8466 gimple_stmt_iterator si;
a509ebb5 8467 basic_block loop_header = single_succ (load_bb);
726a989a 8468 gimple phi, stmt;
a509ebb5 8469 edge e;
e79983f4 8470 enum built_in_function fncode;
a509ebb5 8471
86951993
AM
8472 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
8473 order to use the RELAXED memory model effectively. */
e79983f4
MM
8474 fncode = (enum built_in_function)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
8475 + index + 1);
8476 cmpxchg = builtin_decl_explicit (fncode);
20790697
JJ
8477 if (cmpxchg == NULL_TREE)
8478 return false;
a509ebb5
RL
8479 type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
8480 itype = TREE_TYPE (TREE_TYPE (cmpxchg));
8481
cedb4a1a 8482 if (!can_compare_and_swap_p (TYPE_MODE (itype), true))
a509ebb5
RL
8483 return false;
8484
726a989a
RB
8485 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
8486 si = gsi_last_bb (load_bb);
8487 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
8488
c18c98c0
JJ
8489 /* For floating-point values, we'll need to view-convert them to integers
8490 so that we can perform the atomic compare and swap. Simplify the
8491 following code by always setting up the "i"ntegral variables. */
8492 if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
8493 {
726a989a
RB
8494 tree iaddr_val;
8495
7cc434a3 8496 iaddr = create_tmp_reg (build_pointer_type_for_mode (itype, ptr_mode,
b731b390 8497 true));
726a989a
RB
8498 iaddr_val
8499 = force_gimple_operand_gsi (&si,
8500 fold_convert (TREE_TYPE (iaddr), addr),
8501 false, NULL_TREE, true, GSI_SAME_STMT);
8502 stmt = gimple_build_assign (iaddr, iaddr_val);
8503 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
b731b390 8504 loadedi = create_tmp_var (itype);
c18c98c0 8505 if (gimple_in_ssa_p (cfun))
b731b390 8506 loadedi = make_ssa_name (loadedi);
c18c98c0
JJ
8507 }
8508 else
8509 {
8510 iaddr = addr;
8511 loadedi = loaded_val;
8512 }
726a989a 8513
8175be9a
JJ
8514 fncode = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
8515 tree loaddecl = builtin_decl_explicit (fncode);
8516 if (loaddecl)
8517 initial
8518 = fold_convert (TREE_TYPE (TREE_TYPE (iaddr)),
8519 build_call_expr (loaddecl, 2, iaddr,
8520 build_int_cst (NULL_TREE,
8521 MEMMODEL_RELAXED)));
8522 else
8523 initial = build2 (MEM_REF, TREE_TYPE (TREE_TYPE (iaddr)), iaddr,
8524 build_int_cst (TREE_TYPE (iaddr), 0));
8525
70f34814 8526 initial
8175be9a
JJ
8527 = force_gimple_operand_gsi (&si, initial, true, NULL_TREE, true,
8528 GSI_SAME_STMT);
c18c98c0
JJ
8529
8530 /* Move the value to the LOADEDI temporary. */
a509ebb5
RL
8531 if (gimple_in_ssa_p (cfun))
8532 {
726a989a 8533 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header)));
c18c98c0 8534 phi = create_phi_node (loadedi, loop_header);
a509ebb5
RL
8535 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)),
8536 initial);
8537 }
8538 else
726a989a
RB
8539 gsi_insert_before (&si,
8540 gimple_build_assign (loadedi, initial),
8541 GSI_SAME_STMT);
c18c98c0
JJ
8542 if (loadedi != loaded_val)
8543 {
726a989a
RB
8544 gimple_stmt_iterator gsi2;
8545 tree x;
c18c98c0
JJ
8546
8547 x = build1 (VIEW_CONVERT_EXPR, type, loadedi);
726a989a 8548 gsi2 = gsi_start_bb (loop_header);
c18c98c0
JJ
8549 if (gimple_in_ssa_p (cfun))
8550 {
538dd0b7 8551 gassign *stmt;
726a989a
RB
8552 x = force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
8553 true, GSI_SAME_STMT);
8554 stmt = gimple_build_assign (loaded_val, x);
8555 gsi_insert_before (&gsi2, stmt, GSI_SAME_STMT);
c18c98c0
JJ
8556 }
8557 else
8558 {
726a989a
RB
8559 x = build2 (MODIFY_EXPR, TREE_TYPE (loaded_val), loaded_val, x);
8560 force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
8561 true, GSI_SAME_STMT);
c18c98c0
JJ
8562 }
8563 }
726a989a 8564 gsi_remove (&si, true);
a509ebb5 8565
726a989a
RB
8566 si = gsi_last_bb (store_bb);
8567 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
a509ebb5 8568
c18c98c0
JJ
8569 if (iaddr == addr)
8570 storedi = stored_val;
a509ebb5 8571 else
c18c98c0 8572 storedi =
726a989a 8573 force_gimple_operand_gsi (&si,
c18c98c0
JJ
8574 build1 (VIEW_CONVERT_EXPR, itype,
8575 stored_val), true, NULL_TREE, true,
726a989a 8576 GSI_SAME_STMT);
a509ebb5
RL
8577
8578 /* Build the compare&swap statement. */
8579 new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi);
726a989a 8580 new_storedi = force_gimple_operand_gsi (&si,
587aa063
RG
8581 fold_convert (TREE_TYPE (loadedi),
8582 new_storedi),
a509ebb5 8583 true, NULL_TREE,
726a989a 8584 true, GSI_SAME_STMT);
a509ebb5
RL
8585
8586 if (gimple_in_ssa_p (cfun))
8587 old_vali = loadedi;
8588 else
8589 {
b731b390 8590 old_vali = create_tmp_var (TREE_TYPE (loadedi));
726a989a
RB
8591 stmt = gimple_build_assign (old_vali, loadedi);
8592 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
a509ebb5 8593
726a989a
RB
8594 stmt = gimple_build_assign (loadedi, new_storedi);
8595 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
a509ebb5
RL
8596 }
8597
8598 /* Note that we always perform the comparison as an integer, even for
b8698a0f 8599 floating point. This allows the atomic operation to properly
a509ebb5 8600 succeed even with NaNs and -0.0. */
726a989a
RB
8601 stmt = gimple_build_cond_empty
8602 (build2 (NE_EXPR, boolean_type_node,
8603 new_storedi, old_vali));
8604 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
a509ebb5
RL
8605
8606 /* Update cfg. */
8607 e = single_succ_edge (store_bb);
8608 e->flags &= ~EDGE_FALLTHRU;
8609 e->flags |= EDGE_FALSE_VALUE;
8610
8611 e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE);
8612
c18c98c0 8613 /* Copy the new value to loadedi (we already did that before the condition
a509ebb5
RL
8614 if we are not in SSA). */
8615 if (gimple_in_ssa_p (cfun))
8616 {
726a989a 8617 phi = gimple_seq_first_stmt (phi_nodes (loop_header));
c18c98c0 8618 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), new_storedi);
a509ebb5
RL
8619 }
8620
726a989a
RB
8621 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
8622 gsi_remove (&si, true);
a509ebb5 8623
6093bc06
RB
8624 struct loop *loop = alloc_loop ();
8625 loop->header = loop_header;
a1756c0a 8626 loop->latch = store_bb;
6093bc06
RB
8627 add_loop (loop, loop_header->loop_father);
8628
a509ebb5
RL
8629 if (gimple_in_ssa_p (cfun))
8630 update_ssa (TODO_update_ssa_no_phi);
8631
8632 return true;
8633}
8634
8635/* A subroutine of expand_omp_atomic. Implement the atomic operation as:
8636
8637 GOMP_atomic_start ();
8638 *addr = rhs;
8639 GOMP_atomic_end ();
8640
8641 The result is not globally atomic, but works so long as all parallel
8642 references are within #pragma omp atomic directives. According to
8643 responses received from omp@openmp.org, appears to be within spec.
8644 Which makes sense, since that's how several other compilers handle
b8698a0f 8645 this situation as well.
726a989a
RB
8646 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
8647 expanding. STORED_VAL is the operand of the matching
8648 GIMPLE_OMP_ATOMIC_STORE.
a509ebb5 8649
b8698a0f
L
8650 We replace
8651 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
a509ebb5
RL
8652 loaded_val = *addr;
8653
8654 and replace
05409788 8655 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
b8698a0f 8656 *addr = stored_val;
a509ebb5
RL
8657*/
8658
8659static bool
8660expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
8661 tree addr, tree loaded_val, tree stored_val)
8662{
726a989a 8663 gimple_stmt_iterator si;
538dd0b7 8664 gassign *stmt;
a509ebb5
RL
8665 tree t;
8666
726a989a
RB
8667 si = gsi_last_bb (load_bb);
8668 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
a509ebb5 8669
e79983f4 8670 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
3bb06db4 8671 t = build_call_expr (t, 0);
726a989a 8672 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
a509ebb5 8673
70f34814 8674 stmt = gimple_build_assign (loaded_val, build_simple_mem_ref (addr));
726a989a
RB
8675 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8676 gsi_remove (&si, true);
a509ebb5 8677
726a989a
RB
8678 si = gsi_last_bb (store_bb);
8679 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
a509ebb5 8680
70f34814
RG
8681 stmt = gimple_build_assign (build_simple_mem_ref (unshare_expr (addr)),
8682 stored_val);
726a989a 8683 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
a509ebb5 8684
e79983f4 8685 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
3bb06db4 8686 t = build_call_expr (t, 0);
726a989a
RB
8687 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
8688 gsi_remove (&si, true);
a509ebb5
RL
8689
8690 if (gimple_in_ssa_p (cfun))
8691 update_ssa (TODO_update_ssa_no_phi);
8692 return true;
8693}
8694
b8698a0f
L
8695/* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
8696 using expand_omp_atomic_fetch_op. If it failed, we try to
a509ebb5
RL
8697 call expand_omp_atomic_pipeline, and if it fails too, the
8698 ultimate fallback is wrapping the operation in a mutex
b8698a0f
L
8699 (expand_omp_atomic_mutex). REGION is the atomic region built
8700 by build_omp_regions_1(). */
a509ebb5
RL
8701
8702static void
8703expand_omp_atomic (struct omp_region *region)
8704{
8705 basic_block load_bb = region->entry, store_bb = region->exit;
538dd0b7
DM
8706 gomp_atomic_load *load = as_a <gomp_atomic_load *> (last_stmt (load_bb));
8707 gomp_atomic_store *store = as_a <gomp_atomic_store *> (last_stmt (store_bb));
726a989a
RB
8708 tree loaded_val = gimple_omp_atomic_load_lhs (load);
8709 tree addr = gimple_omp_atomic_load_rhs (load);
8710 tree stored_val = gimple_omp_atomic_store_val (store);
a509ebb5
RL
8711 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
8712 HOST_WIDE_INT index;
8713
8714 /* Make sure the type is one of the supported sizes. */
ae7e9ddd 8715 index = tree_to_uhwi (TYPE_SIZE_UNIT (type));
a509ebb5
RL
8716 index = exact_log2 (index);
8717 if (index >= 0 && index <= 4)
8718 {
8719 unsigned int align = TYPE_ALIGN_UNIT (type);
8720
8721 /* __sync builtins require strict data alignment. */
4999c62c 8722 if (exact_log2 (align) >= index)
a509ebb5 8723 {
05409788 8724 /* Atomic load. */
20906c66
JJ
8725 if (loaded_val == stored_val
8726 && (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
8727 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
8728 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
05409788 8729 && expand_omp_atomic_load (load_bb, addr, loaded_val, index))
20906c66
JJ
8730 return;
8731
05409788 8732 /* Atomic store. */
20906c66
JJ
8733 if ((GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
8734 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
8735 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
8736 && store_bb == single_succ (load_bb)
8737 && first_stmt (store_bb) == store
05409788
RH
8738 && expand_omp_atomic_store (load_bb, addr, loaded_val,
8739 stored_val, index))
20906c66
JJ
8740 return;
8741
a509ebb5
RL
8742 /* When possible, use specialized atomic update functions. */
8743 if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
05409788
RH
8744 && store_bb == single_succ (load_bb)
8745 && expand_omp_atomic_fetch_op (load_bb, addr,
8746 loaded_val, stored_val, index))
8747 return;
a509ebb5
RL
8748
8749 /* If we don't have specialized __sync builtins, try and implement
8750 as a compare and swap loop. */
8751 if (expand_omp_atomic_pipeline (load_bb, store_bb, addr,
8752 loaded_val, stored_val, index))
8753 return;
8754 }
8755 }
8756
8757 /* The ultimate fallback is wrapping the operation in a mutex. */
8758 expand_omp_atomic_mutex (load_bb, store_bb, addr, loaded_val, stored_val);
8759}
8760
953ff289 8761
41dbbb37 8762/* Expand the GIMPLE_OMP_TARGET starting at REGION. */
acf0174b
JJ
8763
8764static void
8765expand_omp_target (struct omp_region *region)
8766{
8767 basic_block entry_bb, exit_bb, new_bb;
41dbbb37
TS
8768 struct function *child_cfun;
8769 tree child_fn, block, t;
acf0174b 8770 gimple_stmt_iterator gsi;
538dd0b7
DM
8771 gomp_target *entry_stmt;
8772 gimple stmt;
acf0174b 8773 edge e;
41dbbb37 8774 bool offloaded, data_region;
acf0174b 8775
538dd0b7 8776 entry_stmt = as_a <gomp_target *> (last_stmt (region->entry));
acf0174b 8777 new_bb = region->entry;
41dbbb37
TS
8778
8779 offloaded = is_gimple_omp_offloaded (entry_stmt);
8780 switch (gimple_omp_target_kind (entry_stmt))
8781 {
8782 case GF_OMP_TARGET_KIND_REGION:
8783 case GF_OMP_TARGET_KIND_UPDATE:
8784 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
8785 case GF_OMP_TARGET_KIND_OACC_KERNELS:
8786 case GF_OMP_TARGET_KIND_OACC_UPDATE:
8787 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
8788 data_region = false;
8789 break;
8790 case GF_OMP_TARGET_KIND_DATA:
8791 case GF_OMP_TARGET_KIND_OACC_DATA:
8792 data_region = true;
8793 break;
8794 default:
8795 gcc_unreachable ();
8796 }
8797
8798 child_fn = NULL_TREE;
8799 child_cfun = NULL;
8800 if (offloaded)
acf0174b
JJ
8801 {
8802 child_fn = gimple_omp_target_child_fn (entry_stmt);
8803 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
8804 }
8805
41dbbb37
TS
8806 /* Supported by expand_omp_taskreg, but not here. */
8807 if (child_cfun != NULL)
8808 gcc_checking_assert (!child_cfun->cfg);
8809 gcc_checking_assert (!gimple_in_ssa_p (cfun));
8810
acf0174b
JJ
8811 entry_bb = region->entry;
8812 exit_bb = region->exit;
8813
41dbbb37 8814 if (offloaded)
acf0174b
JJ
8815 {
8816 unsigned srcidx, dstidx, num;
8817
41dbbb37 8818 /* If the offloading region needs data sent from the parent
acf0174b 8819 function, then the very first statement (except possible
41dbbb37 8820 tree profile counter updates) of the offloading body
acf0174b
JJ
8821 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
8822 &.OMP_DATA_O is passed as an argument to the child function,
8823 we need to replace it with the argument as seen by the child
8824 function.
8825
8826 In most cases, this will end up being the identity assignment
41dbbb37 8827 .OMP_DATA_I = .OMP_DATA_I. However, if the offloading body had
acf0174b
JJ
8828 a function call that has been inlined, the original PARM_DECL
8829 .OMP_DATA_I may have been converted into a different local
8830 variable. In which case, we need to keep the assignment. */
41dbbb37
TS
8831 tree data_arg = gimple_omp_target_data_arg (entry_stmt);
8832 if (data_arg)
acf0174b
JJ
8833 {
8834 basic_block entry_succ_bb = single_succ (entry_bb);
8835 gimple_stmt_iterator gsi;
8836 tree arg;
8837 gimple tgtcopy_stmt = NULL;
41dbbb37 8838 tree sender = TREE_VEC_ELT (data_arg, 0);
acf0174b
JJ
8839
8840 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
8841 {
8842 gcc_assert (!gsi_end_p (gsi));
8843 stmt = gsi_stmt (gsi);
8844 if (gimple_code (stmt) != GIMPLE_ASSIGN)
8845 continue;
8846
8847 if (gimple_num_ops (stmt) == 2)
8848 {
8849 tree arg = gimple_assign_rhs1 (stmt);
8850
8851 /* We're ignoring the subcode because we're
8852 effectively doing a STRIP_NOPS. */
8853
8854 if (TREE_CODE (arg) == ADDR_EXPR
8855 && TREE_OPERAND (arg, 0) == sender)
8856 {
8857 tgtcopy_stmt = stmt;
8858 break;
8859 }
8860 }
8861 }
8862
8863 gcc_assert (tgtcopy_stmt != NULL);
8864 arg = DECL_ARGUMENTS (child_fn);
8865
8866 gcc_assert (gimple_assign_lhs (tgtcopy_stmt) == arg);
8867 gsi_remove (&gsi, true);
8868 }
8869
8870 /* Declare local variables needed in CHILD_CFUN. */
8871 block = DECL_INITIAL (child_fn);
8872 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
41dbbb37 8873 /* The gimplifier could record temporaries in the offloading block
acf0174b
JJ
8874 rather than in containing function's local_decls chain,
8875 which would mean cgraph missed finalizing them. Do it now. */
8876 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
8877 if (TREE_CODE (t) == VAR_DECL
8878 && TREE_STATIC (t)
8879 && !DECL_EXTERNAL (t))
9041d2e6 8880 varpool_node::finalize_decl (t);
acf0174b
JJ
8881 DECL_SAVED_TREE (child_fn) = NULL;
8882 /* We'll create a CFG for child_fn, so no gimple body is needed. */
8883 gimple_set_body (child_fn, NULL);
8884 TREE_USED (block) = 1;
8885
8886 /* Reset DECL_CONTEXT on function arguments. */
8887 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
8888 DECL_CONTEXT (t) = child_fn;
8889
41dbbb37 8890 /* Split ENTRY_BB at GIMPLE_*,
acf0174b
JJ
8891 so that it can be moved to the child function. */
8892 gsi = gsi_last_bb (entry_bb);
8893 stmt = gsi_stmt (gsi);
41dbbb37
TS
8894 gcc_assert (stmt
8895 && gimple_code (stmt) == gimple_code (entry_stmt));
acf0174b 8896 e = split_block (entry_bb, stmt);
b13c907a 8897 gsi_remove (&gsi, true);
acf0174b
JJ
8898 entry_bb = e->dest;
8899 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
8900
8901 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
8902 if (exit_bb)
8903 {
8904 gsi = gsi_last_bb (exit_bb);
8905 gcc_assert (!gsi_end_p (gsi)
8906 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
8907 stmt = gimple_build_return (NULL);
8908 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
8909 gsi_remove (&gsi, true);
8910 }
8911
41dbbb37 8912 /* Move the offloading region into CHILD_CFUN. */
acf0174b
JJ
8913
8914 block = gimple_block (entry_stmt);
8915
8916 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
8917 if (exit_bb)
8918 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
8919 /* When the OMP expansion process cannot guarantee an up-to-date
8920 loop tree arrange for the child function to fixup loops. */
8921 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
8922 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
8923
8924 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
8925 num = vec_safe_length (child_cfun->local_decls);
8926 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
8927 {
8928 t = (*child_cfun->local_decls)[srcidx];
8929 if (DECL_CONTEXT (t) == cfun->decl)
8930 continue;
8931 if (srcidx != dstidx)
8932 (*child_cfun->local_decls)[dstidx] = t;
8933 dstidx++;
8934 }
8935 if (dstidx != num)
8936 vec_safe_truncate (child_cfun->local_decls, dstidx);
8937
8938 /* Inform the callgraph about the new function. */
8939 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
d52f5295 8940 cgraph_node::add_new_function (child_fn, true);
acf0174b 8941
844b0125 8942#ifdef ENABLE_OFFLOADING
ec6fe917
IV
8943 /* Add the new function to the offload table. */
8944 vec_safe_push (offload_funcs, child_fn);
844b0125 8945#endif
ec6fe917 8946
acf0174b
JJ
8947 /* Fix the callgraph edges for child_cfun. Those for cfun will be
8948 fixed in a following pass. */
8949 push_cfun (child_cfun);
3dafb85c 8950 cgraph_edge::rebuild_edges ();
acf0174b 8951
844b0125 8952#ifdef ENABLE_OFFLOADING
1f6be682
IV
8953 /* Prevent IPA from removing child_fn as unreachable, since there are no
8954 refs from the parent function to child_fn in offload LTO mode. */
844b0125 8955 struct cgraph_node *node = cgraph_node::get (child_fn);
1f6be682 8956 node->mark_force_output ();
844b0125 8957#endif
1f6be682 8958
acf0174b
JJ
8959 /* Some EH regions might become dead, see PR34608. If
8960 pass_cleanup_cfg isn't the first pass to happen with the
8961 new child, these dead EH edges might cause problems.
8962 Clean them up now. */
8963 if (flag_exceptions)
8964 {
8965 basic_block bb;
8966 bool changed = false;
8967
11cd3bed 8968 FOR_EACH_BB_FN (bb, cfun)
acf0174b
JJ
8969 changed |= gimple_purge_dead_eh_edges (bb);
8970 if (changed)
8971 cleanup_tree_cfg ();
8972 }
8973 pop_cfun ();
8974 }
8975
41dbbb37 8976 /* Emit a library call to launch the offloading region, or do data
acf0174b
JJ
8977 transfers. */
8978 tree t1, t2, t3, t4, device, cond, c, clauses;
8979 enum built_in_function start_ix;
8980 location_t clause_loc;
8981
41dbbb37
TS
8982 switch (gimple_omp_target_kind (entry_stmt))
8983 {
8984 case GF_OMP_TARGET_KIND_REGION:
8985 start_ix = BUILT_IN_GOMP_TARGET;
8986 break;
8987 case GF_OMP_TARGET_KIND_DATA:
8988 start_ix = BUILT_IN_GOMP_TARGET_DATA;
8989 break;
8990 case GF_OMP_TARGET_KIND_UPDATE:
8991 start_ix = BUILT_IN_GOMP_TARGET_UPDATE;
8992 break;
8993 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
8994 case GF_OMP_TARGET_KIND_OACC_KERNELS:
8995 start_ix = BUILT_IN_GOACC_PARALLEL;
8996 break;
8997 case GF_OMP_TARGET_KIND_OACC_DATA:
8998 start_ix = BUILT_IN_GOACC_DATA_START;
8999 break;
9000 case GF_OMP_TARGET_KIND_OACC_UPDATE:
9001 start_ix = BUILT_IN_GOACC_UPDATE;
9002 break;
9003 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
9004 start_ix = BUILT_IN_GOACC_ENTER_EXIT_DATA;
9005 break;
9006 default:
9007 gcc_unreachable ();
9008 }
acf0174b 9009
41dbbb37 9010 clauses = gimple_omp_target_clauses (entry_stmt);
acf0174b 9011
41dbbb37
TS
9012 /* By default, the value of DEVICE is GOMP_DEVICE_ICV (let runtime
9013 library choose) and there is no conditional. */
acf0174b 9014 cond = NULL_TREE;
41dbbb37 9015 device = build_int_cst (integer_type_node, GOMP_DEVICE_ICV);
acf0174b
JJ
9016
9017 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
9018 if (c)
9019 cond = OMP_CLAUSE_IF_EXPR (c);
9020
9021 c = find_omp_clause (clauses, OMP_CLAUSE_DEVICE);
9022 if (c)
9023 {
41dbbb37
TS
9024 /* Even if we pass it to all library function calls, it is currently only
9025 defined/used for the OpenMP target ones. */
9026 gcc_checking_assert (start_ix == BUILT_IN_GOMP_TARGET
9027 || start_ix == BUILT_IN_GOMP_TARGET_DATA
9028 || start_ix == BUILT_IN_GOMP_TARGET_UPDATE);
9029
acf0174b
JJ
9030 device = OMP_CLAUSE_DEVICE_ID (c);
9031 clause_loc = OMP_CLAUSE_LOCATION (c);
9032 }
9033 else
9034 clause_loc = gimple_location (entry_stmt);
9035
9036 /* Ensure 'device' is of the correct type. */
9037 device = fold_convert_loc (clause_loc, integer_type_node, device);
9038
9039 /* If we found the clause 'if (cond)', build
41dbbb37 9040 (cond ? device : GOMP_DEVICE_HOST_FALLBACK). */
acf0174b
JJ
9041 if (cond)
9042 {
9043 cond = gimple_boolify (cond);
9044
9045 basic_block cond_bb, then_bb, else_bb;
9046 edge e;
9047 tree tmp_var;
9048
b731b390 9049 tmp_var = create_tmp_var (TREE_TYPE (device));
41dbbb37
TS
9050 if (offloaded)
9051 e = split_block (new_bb, NULL);
9052 else
acf0174b
JJ
9053 {
9054 gsi = gsi_last_bb (new_bb);
9055 gsi_prev (&gsi);
9056 e = split_block (new_bb, gsi_stmt (gsi));
9057 }
acf0174b
JJ
9058 cond_bb = e->src;
9059 new_bb = e->dest;
9060 remove_edge (e);
9061
9062 then_bb = create_empty_bb (cond_bb);
9063 else_bb = create_empty_bb (then_bb);
9064 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
9065 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
9066
9067 stmt = gimple_build_cond_empty (cond);
9068 gsi = gsi_last_bb (cond_bb);
9069 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
9070
9071 gsi = gsi_start_bb (then_bb);
9072 stmt = gimple_build_assign (tmp_var, device);
9073 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
9074
9075 gsi = gsi_start_bb (else_bb);
9076 stmt = gimple_build_assign (tmp_var,
41dbbb37
TS
9077 build_int_cst (integer_type_node,
9078 GOMP_DEVICE_HOST_FALLBACK));
acf0174b
JJ
9079 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
9080
9081 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
9082 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
726338f4
RB
9083 add_bb_to_loop (then_bb, cond_bb->loop_father);
9084 add_bb_to_loop (else_bb, cond_bb->loop_father);
acf0174b
JJ
9085 make_edge (then_bb, new_bb, EDGE_FALLTHRU);
9086 make_edge (else_bb, new_bb, EDGE_FALLTHRU);
9087
9088 device = tmp_var;
9089 }
9090
9091 gsi = gsi_last_bb (new_bb);
9092 t = gimple_omp_target_data_arg (entry_stmt);
9093 if (t == NULL)
9094 {
9095 t1 = size_zero_node;
9096 t2 = build_zero_cst (ptr_type_node);
9097 t3 = t2;
9098 t4 = t2;
9099 }
9100 else
9101 {
9102 t1 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t, 1))));
9103 t1 = size_binop (PLUS_EXPR, t1, size_int (1));
9104 t2 = build_fold_addr_expr (TREE_VEC_ELT (t, 0));
9105 t3 = build_fold_addr_expr (TREE_VEC_ELT (t, 1));
9106 t4 = build_fold_addr_expr (TREE_VEC_ELT (t, 2));
9107 }
9108
9109 gimple g;
41dbbb37 9110 /* The maximum number used by any start_ix, without varargs. */
9410d9b2
JJ
9111 auto_vec<tree, 11> args;
9112 args.quick_push (device);
41dbbb37 9113 if (offloaded)
9410d9b2 9114 args.quick_push (build_fold_addr_expr (child_fn));
128b26dc
TS
9115 switch (start_ix)
9116 {
9117 case BUILT_IN_GOMP_TARGET:
9118 case BUILT_IN_GOMP_TARGET_DATA:
9119 case BUILT_IN_GOMP_TARGET_UPDATE:
9120 /* This const void * is part of the current ABI, but we're not actually
9121 using it. */
9410d9b2 9122 args.quick_push (build_zero_cst (ptr_type_node));
128b26dc
TS
9123 break;
9124 case BUILT_IN_GOACC_DATA_START:
9125 case BUILT_IN_GOACC_ENTER_EXIT_DATA:
9126 case BUILT_IN_GOACC_PARALLEL:
9127 case BUILT_IN_GOACC_UPDATE:
9128 break;
9129 default:
9130 gcc_unreachable ();
9131 }
9410d9b2
JJ
9132 args.quick_push (t1);
9133 args.quick_push (t2);
9134 args.quick_push (t3);
9135 args.quick_push (t4);
41dbbb37
TS
9136 switch (start_ix)
9137 {
9138 case BUILT_IN_GOACC_DATA_START:
9139 case BUILT_IN_GOMP_TARGET:
9140 case BUILT_IN_GOMP_TARGET_DATA:
9141 case BUILT_IN_GOMP_TARGET_UPDATE:
9142 break;
9143 case BUILT_IN_GOACC_PARALLEL:
9144 {
9145 tree t_num_gangs, t_num_workers, t_vector_length;
9146
9147 /* Default values for num_gangs, num_workers, and vector_length. */
9148 t_num_gangs = t_num_workers = t_vector_length
9149 = fold_convert_loc (gimple_location (entry_stmt),
9150 integer_type_node, integer_one_node);
9151 /* ..., but if present, use the value specified by the respective
9152 clause, making sure that are of the correct type. */
9153 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_GANGS);
9154 if (c)
9155 t_num_gangs = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9156 integer_type_node,
9157 OMP_CLAUSE_NUM_GANGS_EXPR (c));
9158 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_WORKERS);
9159 if (c)
9160 t_num_workers = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9161 integer_type_node,
9162 OMP_CLAUSE_NUM_WORKERS_EXPR (c));
9163 c = find_omp_clause (clauses, OMP_CLAUSE_VECTOR_LENGTH);
9164 if (c)
9165 t_vector_length = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9166 integer_type_node,
9167 OMP_CLAUSE_VECTOR_LENGTH_EXPR (c));
9410d9b2
JJ
9168 args.quick_push (t_num_gangs);
9169 args.quick_push (t_num_workers);
9170 args.quick_push (t_vector_length);
41dbbb37
TS
9171 }
9172 /* FALLTHRU */
9173 case BUILT_IN_GOACC_ENTER_EXIT_DATA:
9174 case BUILT_IN_GOACC_UPDATE:
9175 {
9176 tree t_async;
9177 int t_wait_idx;
9178
9179 /* Default values for t_async. */
9180 t_async = fold_convert_loc (gimple_location (entry_stmt),
9181 integer_type_node,
9182 build_int_cst (integer_type_node,
9183 GOMP_ASYNC_SYNC));
9184 /* ..., but if present, use the value specified by the respective
9185 clause, making sure that is of the correct type. */
9186 c = find_omp_clause (clauses, OMP_CLAUSE_ASYNC);
9187 if (c)
9188 t_async = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9189 integer_type_node,
9190 OMP_CLAUSE_ASYNC_EXPR (c));
9191
9410d9b2 9192 args.quick_push (t_async);
41dbbb37 9193 /* Save the index, and... */
9410d9b2 9194 t_wait_idx = args.length ();
41dbbb37 9195 /* ... push a default value. */
9410d9b2
JJ
9196 args.quick_push (fold_convert_loc (gimple_location (entry_stmt),
9197 integer_type_node,
9198 integer_zero_node));
41dbbb37
TS
9199 c = find_omp_clause (clauses, OMP_CLAUSE_WAIT);
9200 if (c)
9201 {
9202 int n = 0;
9203
9204 for (; c; c = OMP_CLAUSE_CHAIN (c))
9205 {
9206 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_WAIT)
9207 {
9410d9b2
JJ
9208 args.safe_push (fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9209 integer_type_node,
9210 OMP_CLAUSE_WAIT_EXPR (c)));
41dbbb37
TS
9211 n++;
9212 }
9213 }
9214
9215 /* Now that we know the number, replace the default value. */
9410d9b2
JJ
9216 args.ordered_remove (t_wait_idx);
9217 args.quick_insert (t_wait_idx,
9218 fold_convert_loc (gimple_location (entry_stmt),
9219 integer_type_node,
9220 build_int_cst (integer_type_node, n)));
41dbbb37
TS
9221 }
9222 }
9223 break;
9224 default:
9225 gcc_unreachable ();
acf0174b 9226 }
41dbbb37 9227
9410d9b2 9228 g = gimple_build_call_vec (builtin_decl_explicit (start_ix), args);
acf0174b
JJ
9229 gimple_set_location (g, gimple_location (entry_stmt));
9230 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
41dbbb37 9231 if (!offloaded)
acf0174b
JJ
9232 {
9233 g = gsi_stmt (gsi);
9234 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_TARGET);
9235 gsi_remove (&gsi, true);
9236 }
41dbbb37
TS
9237 if (data_region
9238 && region->exit)
acf0174b
JJ
9239 {
9240 gsi = gsi_last_bb (region->exit);
9241 g = gsi_stmt (gsi);
9242 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_RETURN);
9243 gsi_remove (&gsi, true);
9244 }
9245}
9246
9247
9248/* Expand the parallel region tree rooted at REGION. Expansion
9249 proceeds in depth-first order. Innermost regions are expanded
9250 first. This way, parallel regions that require a new function to
726a989a 9251 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
50674e96
DN
9252 internal dependencies in their body. */
9253
9254static void
9255expand_omp (struct omp_region *region)
9256{
9257 while (region)
9258 {
b357f682 9259 location_t saved_location;
acf0174b 9260 gimple inner_stmt = NULL;
b357f682 9261
068e1875
ZD
9262 /* First, determine whether this is a combined parallel+workshare
9263 region. */
726a989a 9264 if (region->type == GIMPLE_OMP_PARALLEL)
068e1875
ZD
9265 determine_parallel_type (region);
9266
acf0174b
JJ
9267 if (region->type == GIMPLE_OMP_FOR
9268 && gimple_omp_for_combined_p (last_stmt (region->entry)))
9269 inner_stmt = last_stmt (region->inner->entry);
9270
50674e96
DN
9271 if (region->inner)
9272 expand_omp (region->inner);
9273
b357f682 9274 saved_location = input_location;
726a989a
RB
9275 if (gimple_has_location (last_stmt (region->entry)))
9276 input_location = gimple_location (last_stmt (region->entry));
b357f682 9277
777f7f9a 9278 switch (region->type)
50674e96 9279 {
726a989a
RB
9280 case GIMPLE_OMP_PARALLEL:
9281 case GIMPLE_OMP_TASK:
a68ab351
JJ
9282 expand_omp_taskreg (region);
9283 break;
9284
726a989a 9285 case GIMPLE_OMP_FOR:
acf0174b 9286 expand_omp_for (region, inner_stmt);
777f7f9a 9287 break;
50674e96 9288
726a989a 9289 case GIMPLE_OMP_SECTIONS:
777f7f9a
RH
9290 expand_omp_sections (region);
9291 break;
50674e96 9292
726a989a 9293 case GIMPLE_OMP_SECTION:
777f7f9a 9294 /* Individual omp sections are handled together with their
726a989a 9295 parent GIMPLE_OMP_SECTIONS region. */
777f7f9a 9296 break;
50674e96 9297
726a989a 9298 case GIMPLE_OMP_SINGLE:
777f7f9a
RH
9299 expand_omp_single (region);
9300 break;
50674e96 9301
726a989a 9302 case GIMPLE_OMP_MASTER:
acf0174b 9303 case GIMPLE_OMP_TASKGROUP:
726a989a
RB
9304 case GIMPLE_OMP_ORDERED:
9305 case GIMPLE_OMP_CRITICAL:
acf0174b 9306 case GIMPLE_OMP_TEAMS:
777f7f9a
RH
9307 expand_omp_synch (region);
9308 break;
50674e96 9309
726a989a 9310 case GIMPLE_OMP_ATOMIC_LOAD:
a509ebb5
RL
9311 expand_omp_atomic (region);
9312 break;
9313
acf0174b
JJ
9314 case GIMPLE_OMP_TARGET:
9315 expand_omp_target (region);
9316 break;
9317
777f7f9a
RH
9318 default:
9319 gcc_unreachable ();
9320 }
8d9c1aec 9321
b357f682 9322 input_location = saved_location;
50674e96
DN
9323 region = region->next;
9324 }
9325}
9326
9327
9328/* Helper for build_omp_regions. Scan the dominator tree starting at
5f40b3cb
ZD
9329 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
9330 true, the function ends once a single tree is built (otherwise, whole
9331 forest of OMP constructs may be built). */
50674e96
DN
9332
9333static void
5f40b3cb
ZD
9334build_omp_regions_1 (basic_block bb, struct omp_region *parent,
9335 bool single_tree)
50674e96 9336{
726a989a
RB
9337 gimple_stmt_iterator gsi;
9338 gimple stmt;
50674e96
DN
9339 basic_block son;
9340
726a989a
RB
9341 gsi = gsi_last_bb (bb);
9342 if (!gsi_end_p (gsi) && is_gimple_omp (gsi_stmt (gsi)))
50674e96
DN
9343 {
9344 struct omp_region *region;
726a989a 9345 enum gimple_code code;
50674e96 9346
726a989a
RB
9347 stmt = gsi_stmt (gsi);
9348 code = gimple_code (stmt);
9349 if (code == GIMPLE_OMP_RETURN)
50674e96
DN
9350 {
9351 /* STMT is the return point out of region PARENT. Mark it
9352 as the exit point and make PARENT the immediately
9353 enclosing region. */
9354 gcc_assert (parent);
9355 region = parent;
777f7f9a 9356 region->exit = bb;
50674e96 9357 parent = parent->outer;
50674e96 9358 }
726a989a 9359 else if (code == GIMPLE_OMP_ATOMIC_STORE)
a509ebb5 9360 {
726a989a
RB
9361 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
9362 GIMPLE_OMP_RETURN, but matches with
9363 GIMPLE_OMP_ATOMIC_LOAD. */
a509ebb5 9364 gcc_assert (parent);
726a989a 9365 gcc_assert (parent->type == GIMPLE_OMP_ATOMIC_LOAD);
a509ebb5
RL
9366 region = parent;
9367 region->exit = bb;
9368 parent = parent->outer;
9369 }
726a989a 9370 else if (code == GIMPLE_OMP_CONTINUE)
777f7f9a
RH
9371 {
9372 gcc_assert (parent);
9373 parent->cont = bb;
9374 }
726a989a 9375 else if (code == GIMPLE_OMP_SECTIONS_SWITCH)
e5c95afe 9376 {
726a989a
RB
9377 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
9378 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
e5c95afe 9379 }
50674e96
DN
9380 else
9381 {
777f7f9a 9382 region = new_omp_region (bb, code, parent);
41dbbb37
TS
9383 /* Otherwise... */
9384 if (code == GIMPLE_OMP_TARGET)
9385 {
9386 switch (gimple_omp_target_kind (stmt))
9387 {
9388 case GF_OMP_TARGET_KIND_REGION:
9389 case GF_OMP_TARGET_KIND_DATA:
9390 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
9391 case GF_OMP_TARGET_KIND_OACC_KERNELS:
9392 case GF_OMP_TARGET_KIND_OACC_DATA:
9393 break;
9394 case GF_OMP_TARGET_KIND_UPDATE:
9395 case GF_OMP_TARGET_KIND_OACC_UPDATE:
9396 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
9397 /* ..., other than for those stand-alone directives... */
9398 region = NULL;
9399 break;
9400 default:
9401 gcc_unreachable ();
9402 }
9403 }
9404 /* ..., this directive becomes the parent for a new region. */
9405 if (region)
9406 parent = region;
50674e96 9407 }
50674e96
DN
9408 }
9409
5f40b3cb
ZD
9410 if (single_tree && !parent)
9411 return;
9412
50674e96
DN
9413 for (son = first_dom_son (CDI_DOMINATORS, bb);
9414 son;
9415 son = next_dom_son (CDI_DOMINATORS, son))
5f40b3cb
ZD
9416 build_omp_regions_1 (son, parent, single_tree);
9417}
9418
9419/* Builds the tree of OMP regions rooted at ROOT, storing it to
9420 root_omp_region. */
9421
9422static void
9423build_omp_regions_root (basic_block root)
9424{
9425 gcc_assert (root_omp_region == NULL);
9426 build_omp_regions_1 (root, NULL, true);
9427 gcc_assert (root_omp_region != NULL);
50674e96
DN
9428}
9429
5f40b3cb
ZD
9430/* Expands omp construct (and its subconstructs) starting in HEAD. */
9431
9432void
9433omp_expand_local (basic_block head)
9434{
9435 build_omp_regions_root (head);
9436 if (dump_file && (dump_flags & TDF_DETAILS))
9437 {
9438 fprintf (dump_file, "\nOMP region tree\n\n");
9439 dump_omp_region (dump_file, root_omp_region, 0);
9440 fprintf (dump_file, "\n");
9441 }
9442
9443 remove_exit_barriers (root_omp_region);
9444 expand_omp (root_omp_region);
9445
9446 free_omp_regions ();
9447}
50674e96
DN
9448
9449/* Scan the CFG and build a tree of OMP regions. Return the root of
9450 the OMP region tree. */
9451
9452static void
9453build_omp_regions (void)
9454{
777f7f9a 9455 gcc_assert (root_omp_region == NULL);
50674e96 9456 calculate_dominance_info (CDI_DOMINATORS);
fefa31b5 9457 build_omp_regions_1 (ENTRY_BLOCK_PTR_FOR_FN (cfun), NULL, false);
50674e96
DN
9458}
9459
50674e96
DN
9460/* Main entry point for expanding OMP-GIMPLE into runtime calls. */
9461
c2924966 9462static unsigned int
50674e96
DN
9463execute_expand_omp (void)
9464{
9465 build_omp_regions ();
9466
777f7f9a
RH
9467 if (!root_omp_region)
9468 return 0;
50674e96 9469
777f7f9a
RH
9470 if (dump_file)
9471 {
9472 fprintf (dump_file, "\nOMP region tree\n\n");
9473 dump_omp_region (dump_file, root_omp_region, 0);
9474 fprintf (dump_file, "\n");
50674e96 9475 }
777f7f9a
RH
9476
9477 remove_exit_barriers (root_omp_region);
9478
9479 expand_omp (root_omp_region);
9480
777f7f9a
RH
9481 cleanup_tree_cfg ();
9482
9483 free_omp_regions ();
9484
c2924966 9485 return 0;
50674e96
DN
9486}
9487
917948d3
ZD
9488/* OMP expansion -- the default pass, run before creation of SSA form. */
9489
27a4cd48
DM
9490namespace {
9491
9492const pass_data pass_data_expand_omp =
9493{
9494 GIMPLE_PASS, /* type */
9495 "ompexp", /* name */
9496 OPTGROUP_NONE, /* optinfo_flags */
27a4cd48
DM
9497 TV_NONE, /* tv_id */
9498 PROP_gimple_any, /* properties_required */
18751894 9499 PROP_gimple_eomp, /* properties_provided */
27a4cd48
DM
9500 0, /* properties_destroyed */
9501 0, /* todo_flags_start */
9502 0, /* todo_flags_finish */
50674e96 9503};
27a4cd48
DM
9504
9505class pass_expand_omp : public gimple_opt_pass
9506{
9507public:
c3284718
RS
9508 pass_expand_omp (gcc::context *ctxt)
9509 : gimple_opt_pass (pass_data_expand_omp, ctxt)
27a4cd48
DM
9510 {}
9511
9512 /* opt_pass methods: */
18751894 9513 virtual unsigned int execute (function *)
1a3d085c 9514 {
41dbbb37
TS
9515 bool gate = ((flag_cilkplus != 0 || flag_openacc != 0 || flag_openmp != 0
9516 || flag_openmp_simd != 0)
9517 && !seen_error ());
1a3d085c 9518
18751894 9519 /* This pass always runs, to provide PROP_gimple_eomp.
41dbbb37 9520 But often, there is nothing to do. */
18751894
TV
9521 if (!gate)
9522 return 0;
9523
9524 return execute_expand_omp ();
9525 }
27a4cd48
DM
9526
9527}; // class pass_expand_omp
9528
9529} // anon namespace
9530
9531gimple_opt_pass *
9532make_pass_expand_omp (gcc::context *ctxt)
9533{
9534 return new pass_expand_omp (ctxt);
9535}
18751894
TV
9536
9537namespace {
9538
9539const pass_data pass_data_expand_omp_ssa =
9540{
9541 GIMPLE_PASS, /* type */
9542 "ompexpssa", /* name */
9543 OPTGROUP_NONE, /* optinfo_flags */
9544 TV_NONE, /* tv_id */
9545 PROP_cfg | PROP_ssa, /* properties_required */
9546 PROP_gimple_eomp, /* properties_provided */
9547 0, /* properties_destroyed */
9548 0, /* todo_flags_start */
9549 TODO_cleanup_cfg | TODO_rebuild_alias, /* todo_flags_finish */
9550};
9551
9552class pass_expand_omp_ssa : public gimple_opt_pass
9553{
9554public:
9555 pass_expand_omp_ssa (gcc::context *ctxt)
9556 : gimple_opt_pass (pass_data_expand_omp_ssa, ctxt)
9557 {}
9558
9559 /* opt_pass methods: */
9560 virtual bool gate (function *fun)
9561 {
9562 return !(fun->curr_properties & PROP_gimple_eomp);
9563 }
9564 virtual unsigned int execute (function *) { return execute_expand_omp (); }
9565
9566}; // class pass_expand_omp_ssa
9567
9568} // anon namespace
9569
9570gimple_opt_pass *
9571make_pass_expand_omp_ssa (gcc::context *ctxt)
9572{
9573 return new pass_expand_omp_ssa (ctxt);
9574}
50674e96 9575\f
41dbbb37
TS
9576/* Routines to lower OMP directives into OMP-GIMPLE. */
9577
9578/* Helper function to preform, potentially COMPLEX_TYPE, operation and
9579 convert it to gimple. */
9580static void
9581oacc_gimple_assign (tree dest, tree_code op, tree src, gimple_seq *seq)
9582{
9583 gimple stmt;
9584
9585 if (TREE_CODE (TREE_TYPE (dest)) != COMPLEX_TYPE)
9586 {
9587 stmt = gimple_build_assign (dest, op, dest, src);
9588 gimple_seq_add_stmt (seq, stmt);
9589 return;
9590 }
9591
9592 tree t = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9593 tree rdest = fold_build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (dest)), dest);
9594 gimplify_assign (t, rdest, seq);
9595 rdest = t;
9596
9597 t = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9598 tree idest = fold_build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (dest)), dest);
9599 gimplify_assign (t, idest, seq);
9600 idest = t;
9601
9602 t = create_tmp_var (TREE_TYPE (TREE_TYPE (src)));
9603 tree rsrc = fold_build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (src)), src);
9604 gimplify_assign (t, rsrc, seq);
9605 rsrc = t;
9606
9607 t = create_tmp_var (TREE_TYPE (TREE_TYPE (src)));
9608 tree isrc = fold_build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (src)), src);
9609 gimplify_assign (t, isrc, seq);
9610 isrc = t;
9611
9612 tree r = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9613 tree i = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9614 tree result;
9615
9616 if (op == PLUS_EXPR)
9617 {
9618 stmt = gimple_build_assign (r, op, rdest, rsrc);
9619 gimple_seq_add_stmt (seq, stmt);
9620
9621 stmt = gimple_build_assign (i, op, idest, isrc);
9622 gimple_seq_add_stmt (seq, stmt);
9623 }
9624 else if (op == MULT_EXPR)
9625 {
9626 /* Let x = a + ib = dest, y = c + id = src.
9627 x * y = (ac - bd) + i(ad + bc) */
9628 tree ac = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9629 tree bd = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9630 tree ad = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9631 tree bc = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9632
9633 stmt = gimple_build_assign (ac, MULT_EXPR, rdest, rsrc);
9634 gimple_seq_add_stmt (seq, stmt);
9635
9636 stmt = gimple_build_assign (bd, MULT_EXPR, idest, isrc);
9637 gimple_seq_add_stmt (seq, stmt);
9638
9639 stmt = gimple_build_assign (r, MINUS_EXPR, ac, bd);
9640 gimple_seq_add_stmt (seq, stmt);
9641
9642 stmt = gimple_build_assign (ad, MULT_EXPR, rdest, isrc);
9643 gimple_seq_add_stmt (seq, stmt);
9644
9645 stmt = gimple_build_assign (bd, MULT_EXPR, idest, rsrc);
9646 gimple_seq_add_stmt (seq, stmt);
9647
9648 stmt = gimple_build_assign (i, PLUS_EXPR, ad, bc);
9649 gimple_seq_add_stmt (seq, stmt);
9650 }
9651 else
9652 gcc_unreachable ();
9653
9654 result = build2 (COMPLEX_EXPR, TREE_TYPE (dest), r, i);
9655 gimplify_assign (dest, result, seq);
9656}
9657
9658/* Helper function to initialize local data for the reduction arrays.
9659 The reduction arrays need to be placed inside the calling function
9660 for accelerators, or else the host won't be able to preform the final
9661 reduction. */
9662
9663static void
9664oacc_initialize_reduction_data (tree clauses, tree nthreads,
9665 gimple_seq *stmt_seqp, omp_context *ctx)
9666{
9667 tree c, t, oc;
9668 gimple stmt;
9669 omp_context *octx;
9670
9671 /* Find the innermost OpenACC parallel context. */
9672 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET
9673 && (gimple_omp_target_kind (ctx->stmt)
9674 == GF_OMP_TARGET_KIND_OACC_PARALLEL))
9675 octx = ctx;
9676 else
9677 octx = ctx->outer;
9678 gcc_checking_assert (gimple_code (octx->stmt) == GIMPLE_OMP_TARGET
9679 && (gimple_omp_target_kind (octx->stmt)
9680 == GF_OMP_TARGET_KIND_OACC_PARALLEL));
9681
9682 /* Extract the clauses. */
9683 oc = gimple_omp_target_clauses (octx->stmt);
9684
9685 /* Find the last outer clause. */
9686 for (; oc && OMP_CLAUSE_CHAIN (oc); oc = OMP_CLAUSE_CHAIN (oc))
9687 ;
9688
9689 /* Allocate arrays for each reduction variable. */
9690 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9691 {
9692 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
9693 continue;
9694
9695 tree var = OMP_CLAUSE_DECL (c);
9696 tree type = get_base_type (var);
9697 tree array = lookup_oacc_reduction (oacc_get_reduction_array_id (var),
9698 ctx);
9699 tree size, call;
9700
9701 /* Calculate size of the reduction array. */
9702 t = create_tmp_var (TREE_TYPE (nthreads));
9703 stmt = gimple_build_assign (t, MULT_EXPR, nthreads,
9704 fold_convert (TREE_TYPE (nthreads),
9705 TYPE_SIZE_UNIT (type)));
9706 gimple_seq_add_stmt (stmt_seqp, stmt);
9707
9708 size = create_tmp_var (sizetype);
9709 gimplify_assign (size, fold_build1 (NOP_EXPR, sizetype, t), stmt_seqp);
9710
9711 /* Now allocate memory for it. */
9712 call = unshare_expr (builtin_decl_explicit (BUILT_IN_ALLOCA));
9713 stmt = gimple_build_call (call, 1, size);
9714 gimple_call_set_lhs (stmt, array);
9715 gimple_seq_add_stmt (stmt_seqp, stmt);
9716
9717 /* Map this array into the accelerator. */
9718
9719 /* Add the reduction array to the list of clauses. */
9720 tree x = array;
9721 t = build_omp_clause (gimple_location (ctx->stmt), OMP_CLAUSE_MAP);
9722 OMP_CLAUSE_SET_MAP_KIND (t, GOMP_MAP_FORCE_FROM);
9723 OMP_CLAUSE_DECL (t) = x;
9724 OMP_CLAUSE_CHAIN (t) = NULL;
9725 if (oc)
9726 OMP_CLAUSE_CHAIN (oc) = t;
9727 else
9728 gimple_omp_target_set_clauses (as_a <gomp_target *> (octx->stmt), t);
9729 OMP_CLAUSE_SIZE (t) = size;
9730 oc = t;
9731 }
9732}
9733
9734/* Helper function to process the array of partial reductions. Nthreads
9735 indicates the number of threads. Unfortunately, GOACC_GET_NUM_THREADS
9736 cannot be used here, because nthreads on the host may be different than
9737 on the accelerator. */
9738
9739static void
9740oacc_finalize_reduction_data (tree clauses, tree nthreads,
9741 gimple_seq *stmt_seqp, omp_context *ctx)
9742{
9743 tree c, x, var, array, loop_header, loop_body, loop_exit, type;
9744 gimple stmt;
9745
9746 /* Create for loop.
9747
9748 let var = the original reduction variable
9749 let array = reduction variable array
9750
9751 for (i = 0; i < nthreads; i++)
9752 var op= array[i]
9753 */
9754
9755 loop_header = create_artificial_label (UNKNOWN_LOCATION);
9756 loop_body = create_artificial_label (UNKNOWN_LOCATION);
9757 loop_exit = create_artificial_label (UNKNOWN_LOCATION);
9758
9759 /* Create and initialize an index variable. */
9760 tree ix = create_tmp_var (sizetype);
9761 gimplify_assign (ix, fold_build1 (NOP_EXPR, sizetype, integer_zero_node),
9762 stmt_seqp);
9763
9764 /* Insert the loop header label here. */
9765 gimple_seq_add_stmt (stmt_seqp, gimple_build_label (loop_header));
9766
9767 /* Exit loop if ix >= nthreads. */
9768 x = create_tmp_var (sizetype);
9769 gimplify_assign (x, fold_build1 (NOP_EXPR, sizetype, nthreads), stmt_seqp);
9770 stmt = gimple_build_cond (GE_EXPR, ix, x, loop_exit, loop_body);
9771 gimple_seq_add_stmt (stmt_seqp, stmt);
9772
9773 /* Insert the loop body label here. */
9774 gimple_seq_add_stmt (stmt_seqp, gimple_build_label (loop_body));
9775
9776 /* Collapse each reduction array, one element at a time. */
9777 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9778 {
9779 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
9780 continue;
9781
9782 tree_code reduction_code = OMP_CLAUSE_REDUCTION_CODE (c);
9783
9784 /* reduction(-:var) sums up the partial results, so it acts
9785 identically to reduction(+:var). */
9786 if (reduction_code == MINUS_EXPR)
9787 reduction_code = PLUS_EXPR;
9788
9789 /* Set up reduction variable var. */
9790 var = OMP_CLAUSE_DECL (c);
9791 type = get_base_type (var);
9792 array = lookup_oacc_reduction (oacc_get_reduction_array_id
9793 (OMP_CLAUSE_DECL (c)), ctx);
9794
9795 /* Calculate the array offset. */
9796 tree offset = create_tmp_var (sizetype);
9797 gimplify_assign (offset, TYPE_SIZE_UNIT (type), stmt_seqp);
9798 stmt = gimple_build_assign (offset, MULT_EXPR, offset, ix);
9799 gimple_seq_add_stmt (stmt_seqp, stmt);
9800
9801 tree ptr = create_tmp_var (TREE_TYPE (array));
9802 stmt = gimple_build_assign (ptr, POINTER_PLUS_EXPR, array, offset);
9803 gimple_seq_add_stmt (stmt_seqp, stmt);
9804
9805 /* Extract array[ix] into mem. */
9806 tree mem = create_tmp_var (type);
9807 gimplify_assign (mem, build_simple_mem_ref (ptr), stmt_seqp);
9808
9809 /* Find the original reduction variable. */
9810 if (is_reference (var))
9811 var = build_simple_mem_ref (var);
9812
9813 tree t = create_tmp_var (type);
9814
9815 x = lang_hooks.decls.omp_clause_assign_op (c, t, var);
9816 gimplify_and_add (unshare_expr(x), stmt_seqp);
9817
9818 /* var = var op mem */
9819 switch (OMP_CLAUSE_REDUCTION_CODE (c))
9820 {
9821 case TRUTH_ANDIF_EXPR:
9822 case TRUTH_ORIF_EXPR:
9823 t = fold_build2 (OMP_CLAUSE_REDUCTION_CODE (c), integer_type_node,
9824 t, mem);
9825 gimplify_and_add (t, stmt_seqp);
9826 break;
9827 default:
9828 /* The lhs isn't a gimple_reg when var is COMPLEX_TYPE. */
9829 oacc_gimple_assign (t, OMP_CLAUSE_REDUCTION_CODE (c), mem,
9830 stmt_seqp);
9831 }
9832
9833 t = fold_build1 (NOP_EXPR, TREE_TYPE (var), t);
9834 x = lang_hooks.decls.omp_clause_assign_op (c, var, t);
9835 gimplify_and_add (unshare_expr(x), stmt_seqp);
9836 }
9837
9838 /* Increment the induction variable. */
9839 tree one = fold_build1 (NOP_EXPR, sizetype, integer_one_node);
9840 stmt = gimple_build_assign (ix, PLUS_EXPR, ix, one);
9841 gimple_seq_add_stmt (stmt_seqp, stmt);
9842
9843 /* Go back to the top of the loop. */
9844 gimple_seq_add_stmt (stmt_seqp, gimple_build_goto (loop_header));
9845
9846 /* Place the loop exit label here. */
9847 gimple_seq_add_stmt (stmt_seqp, gimple_build_label (loop_exit));
9848}
9849
9850/* Scan through all of the gimple stmts searching for an OMP_FOR_EXPR, and
9851 scan that for reductions. */
9852
9853static void
9854oacc_process_reduction_data (gimple_seq *body, gimple_seq *in_stmt_seqp,
9855 gimple_seq *out_stmt_seqp, omp_context *ctx)
9856{
9857 gimple_stmt_iterator gsi;
9858 gimple_seq inner = NULL;
9859
9860 /* A collapse clause may have inserted a new bind block. */
9861 gsi = gsi_start (*body);
9862 while (!gsi_end_p (gsi))
9863 {
9864 gimple stmt = gsi_stmt (gsi);
9865 if (gbind *bind_stmt = dyn_cast <gbind *> (stmt))
9866 {
9867 inner = gimple_bind_body (bind_stmt);
9868 body = &inner;
9869 gsi = gsi_start (*body);
9870 }
9871 else if (dyn_cast <gomp_for *> (stmt))
9872 break;
9873 else
9874 gsi_next (&gsi);
9875 }
9876
9877 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
9878 {
9879 tree clauses, nthreads, t, c, acc_device, acc_device_host, call,
9880 enter, exit;
9881 bool reduction_found = false;
9882
9883 gimple stmt = gsi_stmt (gsi);
9884
9885 switch (gimple_code (stmt))
9886 {
9887 case GIMPLE_OMP_FOR:
9888 clauses = gimple_omp_for_clauses (stmt);
9889
9890 /* Search for a reduction clause. */
9891 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9892 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
9893 {
9894 reduction_found = true;
9895 break;
9896 }
9897
9898 if (!reduction_found)
9899 break;
9900
9901 ctx = maybe_lookup_ctx (stmt);
9902 t = NULL_TREE;
9903
9904 /* Extract the number of threads. */
9905 nthreads = create_tmp_var (sizetype);
9906 t = oacc_max_threads (ctx);
9907 gimplify_assign (nthreads, t, in_stmt_seqp);
9908
9909 /* Determine if this is kernel will be executed on the host. */
9910 call = builtin_decl_explicit (BUILT_IN_ACC_GET_DEVICE_TYPE);
9911 acc_device = create_tmp_var (integer_type_node, ".acc_device_type");
9912 stmt = gimple_build_call (call, 0);
9913 gimple_call_set_lhs (stmt, acc_device);
9914 gimple_seq_add_stmt (in_stmt_seqp, stmt);
9915
9916 /* Set nthreads = 1 for ACC_DEVICE_TYPE=host. */
9917 acc_device_host = create_tmp_var (integer_type_node,
9918 ".acc_device_host");
9919 gimplify_assign (acc_device_host,
9920 build_int_cst (integer_type_node,
9921 GOMP_DEVICE_HOST),
9922 in_stmt_seqp);
9923
9924 enter = create_artificial_label (UNKNOWN_LOCATION);
9925 exit = create_artificial_label (UNKNOWN_LOCATION);
9926
9927 stmt = gimple_build_cond (EQ_EXPR, acc_device, acc_device_host,
9928 enter, exit);
9929 gimple_seq_add_stmt (in_stmt_seqp, stmt);
9930 gimple_seq_add_stmt (in_stmt_seqp, gimple_build_label (enter));
9931 gimplify_assign (nthreads, fold_build1 (NOP_EXPR, sizetype,
9932 integer_one_node),
9933 in_stmt_seqp);
9934 gimple_seq_add_stmt (in_stmt_seqp, gimple_build_label (exit));
9935
9936 /* Also, set nthreads = 1 for ACC_DEVICE_TYPE=host_nonshm. */
9937 gimplify_assign (acc_device_host,
9938 build_int_cst (integer_type_node,
9939 GOMP_DEVICE_HOST_NONSHM),
9940 in_stmt_seqp);
9941
9942 enter = create_artificial_label (UNKNOWN_LOCATION);
9943 exit = create_artificial_label (UNKNOWN_LOCATION);
9944
9945 stmt = gimple_build_cond (EQ_EXPR, acc_device, acc_device_host,
9946 enter, exit);
9947 gimple_seq_add_stmt (in_stmt_seqp, stmt);
9948 gimple_seq_add_stmt (in_stmt_seqp, gimple_build_label (enter));
9949 gimplify_assign (nthreads, fold_build1 (NOP_EXPR, sizetype,
9950 integer_one_node),
9951 in_stmt_seqp);
9952 gimple_seq_add_stmt (in_stmt_seqp, gimple_build_label (exit));
9953
9954 oacc_initialize_reduction_data (clauses, nthreads, in_stmt_seqp,
9955 ctx);
9956 oacc_finalize_reduction_data (clauses, nthreads, out_stmt_seqp, ctx);
9957 break;
9958 default:
9959 // Scan for other directives which support reduction here.
9960 break;
9961 }
9962 }
9963}
50674e96 9964
acf0174b
JJ
9965/* If ctx is a worksharing context inside of a cancellable parallel
9966 region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
9967 and conditional branch to parallel's cancel_label to handle
9968 cancellation in the implicit barrier. */
9969
9970static void
9971maybe_add_implicit_barrier_cancel (omp_context *ctx, gimple_seq *body)
9972{
9973 gimple omp_return = gimple_seq_last_stmt (*body);
9974 gcc_assert (gimple_code (omp_return) == GIMPLE_OMP_RETURN);
9975 if (gimple_omp_return_nowait_p (omp_return))
9976 return;
9977 if (ctx->outer
9978 && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_PARALLEL
9979 && ctx->outer->cancellable)
9980 {
dd2fc525
JJ
9981 tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL);
9982 tree c_bool_type = TREE_TYPE (TREE_TYPE (fndecl));
b731b390 9983 tree lhs = create_tmp_var (c_bool_type);
acf0174b
JJ
9984 gimple_omp_return_set_lhs (omp_return, lhs);
9985 tree fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
dd2fc525
JJ
9986 gimple g = gimple_build_cond (NE_EXPR, lhs,
9987 fold_convert (c_bool_type,
9988 boolean_false_node),
acf0174b
JJ
9989 ctx->outer->cancel_label, fallthru_label);
9990 gimple_seq_add_stmt (body, g);
9991 gimple_seq_add_stmt (body, gimple_build_label (fallthru_label));
9992 }
9993}
9994
726a989a
RB
9995/* Lower the OpenMP sections directive in the current statement in GSI_P.
9996 CTX is the enclosing OMP context for the current statement. */
50674e96
DN
9997
9998static void
726a989a 9999lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
50674e96 10000{
726a989a
RB
10001 tree block, control;
10002 gimple_stmt_iterator tgsi;
538dd0b7
DM
10003 gomp_sections *stmt;
10004 gimple t;
10005 gbind *new_stmt, *bind;
355a7673 10006 gimple_seq ilist, dlist, olist, new_body;
50674e96 10007
538dd0b7 10008 stmt = as_a <gomp_sections *> (gsi_stmt (*gsi_p));
50674e96 10009
45852dcc 10010 push_gimplify_context ();
50674e96
DN
10011
10012 dlist = NULL;
10013 ilist = NULL;
726a989a 10014 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
acf0174b 10015 &ilist, &dlist, ctx, NULL);
50674e96 10016
355a7673
MM
10017 new_body = gimple_omp_body (stmt);
10018 gimple_omp_set_body (stmt, NULL);
10019 tgsi = gsi_start (new_body);
10020 for (; !gsi_end_p (tgsi); gsi_next (&tgsi))
50674e96
DN
10021 {
10022 omp_context *sctx;
726a989a 10023 gimple sec_start;
50674e96 10024
726a989a 10025 sec_start = gsi_stmt (tgsi);
50674e96
DN
10026 sctx = maybe_lookup_ctx (sec_start);
10027 gcc_assert (sctx);
10028
355a7673
MM
10029 lower_omp (gimple_omp_body_ptr (sec_start), sctx);
10030 gsi_insert_seq_after (&tgsi, gimple_omp_body (sec_start),
10031 GSI_CONTINUE_LINKING);
726a989a 10032 gimple_omp_set_body (sec_start, NULL);
50674e96 10033
355a7673 10034 if (gsi_one_before_end_p (tgsi))
50674e96 10035 {
726a989a
RB
10036 gimple_seq l = NULL;
10037 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
50674e96 10038 &l, ctx);
355a7673 10039 gsi_insert_seq_after (&tgsi, l, GSI_CONTINUE_LINKING);
726a989a 10040 gimple_omp_section_set_last (sec_start);
50674e96 10041 }
b8698a0f 10042
355a7673
MM
10043 gsi_insert_after (&tgsi, gimple_build_omp_return (false),
10044 GSI_CONTINUE_LINKING);
50674e96 10045 }
953ff289
DN
10046
10047 block = make_node (BLOCK);
355a7673 10048 bind = gimple_build_bind (NULL, new_body, block);
953ff289 10049
726a989a
RB
10050 olist = NULL;
10051 lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist, ctx);
50674e96 10052
b357f682 10053 block = make_node (BLOCK);
726a989a 10054 new_stmt = gimple_build_bind (NULL, NULL, block);
355a7673 10055 gsi_replace (gsi_p, new_stmt, true);
50674e96 10056
b357f682 10057 pop_gimplify_context (new_stmt);
726a989a
RB
10058 gimple_bind_append_vars (new_stmt, ctx->block_vars);
10059 BLOCK_VARS (block) = gimple_bind_vars (bind);
b357f682
JJ
10060 if (BLOCK_VARS (block))
10061 TREE_USED (block) = 1;
10062
726a989a
RB
10063 new_body = NULL;
10064 gimple_seq_add_seq (&new_body, ilist);
10065 gimple_seq_add_stmt (&new_body, stmt);
10066 gimple_seq_add_stmt (&new_body, gimple_build_omp_sections_switch ());
10067 gimple_seq_add_stmt (&new_body, bind);
777f7f9a 10068
e5c95afe 10069 control = create_tmp_var (unsigned_type_node, ".section");
726a989a
RB
10070 t = gimple_build_omp_continue (control, control);
10071 gimple_omp_sections_set_control (stmt, control);
10072 gimple_seq_add_stmt (&new_body, t);
777f7f9a 10073
726a989a 10074 gimple_seq_add_seq (&new_body, olist);
acf0174b
JJ
10075 if (ctx->cancellable)
10076 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
726a989a 10077 gimple_seq_add_seq (&new_body, dlist);
50674e96 10078
726a989a 10079 new_body = maybe_catch_exception (new_body);
4a31b7ee 10080
726a989a
RB
10081 t = gimple_build_omp_return
10082 (!!find_omp_clause (gimple_omp_sections_clauses (stmt),
10083 OMP_CLAUSE_NOWAIT));
10084 gimple_seq_add_stmt (&new_body, t);
acf0174b 10085 maybe_add_implicit_barrier_cancel (ctx, &new_body);
777f7f9a 10086
726a989a 10087 gimple_bind_set_body (new_stmt, new_body);
953ff289
DN
10088}
10089
10090
50674e96 10091/* A subroutine of lower_omp_single. Expand the simple form of
726a989a 10092 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
953ff289
DN
10093
10094 if (GOMP_single_start ())
10095 BODY;
10096 [ GOMP_barrier (); ] -> unless 'nowait' is present.
50674e96
DN
10097
10098 FIXME. It may be better to delay expanding the logic of this until
10099 pass_expand_omp. The expanded logic may make the job more difficult
10100 to a synchronization analysis pass. */
953ff289
DN
10101
10102static void
538dd0b7 10103lower_omp_single_simple (gomp_single *single_stmt, gimple_seq *pre_p)
953ff289 10104{
c2255bc4
AH
10105 location_t loc = gimple_location (single_stmt);
10106 tree tlabel = create_artificial_label (loc);
10107 tree flabel = create_artificial_label (loc);
726a989a
RB
10108 gimple call, cond;
10109 tree lhs, decl;
10110
e79983f4 10111 decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START);
b731b390 10112 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)));
726a989a
RB
10113 call = gimple_build_call (decl, 0);
10114 gimple_call_set_lhs (call, lhs);
10115 gimple_seq_add_stmt (pre_p, call);
10116
10117 cond = gimple_build_cond (EQ_EXPR, lhs,
db3927fb
AH
10118 fold_convert_loc (loc, TREE_TYPE (lhs),
10119 boolean_true_node),
726a989a
RB
10120 tlabel, flabel);
10121 gimple_seq_add_stmt (pre_p, cond);
10122 gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
10123 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
10124 gimple_seq_add_stmt (pre_p, gimple_build_label (flabel));
953ff289
DN
10125}
10126
50674e96
DN
10127
10128/* A subroutine of lower_omp_single. Expand the simple form of
726a989a 10129 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
953ff289
DN
10130
10131 #pragma omp single copyprivate (a, b, c)
10132
10133 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
10134
10135 {
10136 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
10137 {
10138 BODY;
10139 copyout.a = a;
10140 copyout.b = b;
10141 copyout.c = c;
10142 GOMP_single_copy_end (&copyout);
10143 }
10144 else
10145 {
10146 a = copyout_p->a;
10147 b = copyout_p->b;
10148 c = copyout_p->c;
10149 }
10150 GOMP_barrier ();
10151 }
50674e96
DN
10152
10153 FIXME. It may be better to delay expanding the logic of this until
10154 pass_expand_omp. The expanded logic may make the job more difficult
10155 to a synchronization analysis pass. */
953ff289
DN
10156
10157static void
538dd0b7
DM
10158lower_omp_single_copy (gomp_single *single_stmt, gimple_seq *pre_p,
10159 omp_context *ctx)
953ff289 10160{
e79983f4 10161 tree ptr_type, t, l0, l1, l2, bfn_decl;
726a989a 10162 gimple_seq copyin_seq;
c2255bc4 10163 location_t loc = gimple_location (single_stmt);
953ff289
DN
10164
10165 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
10166
10167 ptr_type = build_pointer_type (ctx->record_type);
10168 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
10169
c2255bc4
AH
10170 l0 = create_artificial_label (loc);
10171 l1 = create_artificial_label (loc);
10172 l2 = create_artificial_label (loc);
953ff289 10173
e79983f4
MM
10174 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START);
10175 t = build_call_expr_loc (loc, bfn_decl, 0);
db3927fb 10176 t = fold_convert_loc (loc, ptr_type, t);
726a989a 10177 gimplify_assign (ctx->receiver_decl, t, pre_p);
953ff289
DN
10178
10179 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
10180 build_int_cst (ptr_type, 0));
10181 t = build3 (COND_EXPR, void_type_node, t,
10182 build_and_jump (&l0), build_and_jump (&l1));
10183 gimplify_and_add (t, pre_p);
10184
726a989a 10185 gimple_seq_add_stmt (pre_p, gimple_build_label (l0));
953ff289 10186
726a989a 10187 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
953ff289
DN
10188
10189 copyin_seq = NULL;
726a989a 10190 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
953ff289
DN
10191 &copyin_seq, ctx);
10192
db3927fb 10193 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
e79983f4
MM
10194 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END);
10195 t = build_call_expr_loc (loc, bfn_decl, 1, t);
953ff289
DN
10196 gimplify_and_add (t, pre_p);
10197
10198 t = build_and_jump (&l2);
10199 gimplify_and_add (t, pre_p);
10200
726a989a 10201 gimple_seq_add_stmt (pre_p, gimple_build_label (l1));
953ff289 10202
726a989a 10203 gimple_seq_add_seq (pre_p, copyin_seq);
953ff289 10204
726a989a 10205 gimple_seq_add_stmt (pre_p, gimple_build_label (l2));
953ff289
DN
10206}
10207
50674e96 10208
953ff289
DN
10209/* Expand code for an OpenMP single directive. */
10210
10211static void
726a989a 10212lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
953ff289 10213{
726a989a 10214 tree block;
538dd0b7
DM
10215 gimple t;
10216 gomp_single *single_stmt = as_a <gomp_single *> (gsi_stmt (*gsi_p));
10217 gbind *bind;
acf0174b 10218 gimple_seq bind_body, bind_body_tail = NULL, dlist;
953ff289 10219
45852dcc 10220 push_gimplify_context ();
953ff289 10221
355a7673
MM
10222 block = make_node (BLOCK);
10223 bind = gimple_build_bind (NULL, NULL, block);
10224 gsi_replace (gsi_p, bind, true);
726a989a 10225 bind_body = NULL;
355a7673 10226 dlist = NULL;
726a989a 10227 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt),
acf0174b 10228 &bind_body, &dlist, ctx, NULL);
355a7673 10229 lower_omp (gimple_omp_body_ptr (single_stmt), ctx);
953ff289 10230
726a989a 10231 gimple_seq_add_stmt (&bind_body, single_stmt);
953ff289
DN
10232
10233 if (ctx->record_type)
726a989a 10234 lower_omp_single_copy (single_stmt, &bind_body, ctx);
953ff289 10235 else
726a989a
RB
10236 lower_omp_single_simple (single_stmt, &bind_body);
10237
10238 gimple_omp_set_body (single_stmt, NULL);
953ff289 10239
726a989a 10240 gimple_seq_add_seq (&bind_body, dlist);
777f7f9a 10241
726a989a 10242 bind_body = maybe_catch_exception (bind_body);
777f7f9a 10243
b8698a0f 10244 t = gimple_build_omp_return
726a989a
RB
10245 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt),
10246 OMP_CLAUSE_NOWAIT));
acf0174b
JJ
10247 gimple_seq_add_stmt (&bind_body_tail, t);
10248 maybe_add_implicit_barrier_cancel (ctx, &bind_body_tail);
10249 if (ctx->record_type)
10250 {
10251 gimple_stmt_iterator gsi = gsi_start (bind_body_tail);
10252 tree clobber = build_constructor (ctx->record_type, NULL);
10253 TREE_THIS_VOLATILE (clobber) = 1;
10254 gsi_insert_after (&gsi, gimple_build_assign (ctx->sender_decl,
10255 clobber), GSI_SAME_STMT);
10256 }
10257 gimple_seq_add_seq (&bind_body, bind_body_tail);
355a7673 10258 gimple_bind_set_body (bind, bind_body);
777f7f9a 10259
953ff289 10260 pop_gimplify_context (bind);
50674e96 10261
726a989a
RB
10262 gimple_bind_append_vars (bind, ctx->block_vars);
10263 BLOCK_VARS (block) = ctx->block_vars;
b357f682
JJ
10264 if (BLOCK_VARS (block))
10265 TREE_USED (block) = 1;
953ff289
DN
10266}
10267
50674e96 10268
953ff289
DN
10269/* Expand code for an OpenMP master directive. */
10270
10271static void
726a989a 10272lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
953ff289 10273{
e79983f4 10274 tree block, lab = NULL, x, bfn_decl;
538dd0b7
DM
10275 gimple stmt = gsi_stmt (*gsi_p);
10276 gbind *bind;
db3927fb 10277 location_t loc = gimple_location (stmt);
726a989a 10278 gimple_seq tseq;
953ff289 10279
45852dcc 10280 push_gimplify_context ();
953ff289
DN
10281
10282 block = make_node (BLOCK);
355a7673
MM
10283 bind = gimple_build_bind (NULL, NULL, block);
10284 gsi_replace (gsi_p, bind, true);
10285 gimple_bind_add_stmt (bind, stmt);
777f7f9a 10286
e79983f4
MM
10287 bfn_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
10288 x = build_call_expr_loc (loc, bfn_decl, 0);
953ff289
DN
10289 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
10290 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
726a989a
RB
10291 tseq = NULL;
10292 gimplify_and_add (x, &tseq);
10293 gimple_bind_add_seq (bind, tseq);
953ff289 10294
355a7673 10295 lower_omp (gimple_omp_body_ptr (stmt), ctx);
726a989a
RB
10296 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
10297 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10298 gimple_omp_set_body (stmt, NULL);
953ff289 10299
726a989a 10300 gimple_bind_add_stmt (bind, gimple_build_label (lab));
777f7f9a 10301
726a989a 10302 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
777f7f9a 10303
953ff289 10304 pop_gimplify_context (bind);
50674e96 10305
726a989a
RB
10306 gimple_bind_append_vars (bind, ctx->block_vars);
10307 BLOCK_VARS (block) = ctx->block_vars;
953ff289
DN
10308}
10309
50674e96 10310
acf0174b
JJ
10311/* Expand code for an OpenMP taskgroup directive. */
10312
10313static void
10314lower_omp_taskgroup (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10315{
538dd0b7
DM
10316 gimple stmt = gsi_stmt (*gsi_p);
10317 gcall *x;
10318 gbind *bind;
acf0174b
JJ
10319 tree block = make_node (BLOCK);
10320
10321 bind = gimple_build_bind (NULL, NULL, block);
10322 gsi_replace (gsi_p, bind, true);
10323 gimple_bind_add_stmt (bind, stmt);
10324
10325 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START),
10326 0);
10327 gimple_bind_add_stmt (bind, x);
10328
10329 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10330 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10331 gimple_omp_set_body (stmt, NULL);
10332
10333 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
10334
10335 gimple_bind_append_vars (bind, ctx->block_vars);
10336 BLOCK_VARS (block) = ctx->block_vars;
10337}
10338
10339
953ff289
DN
10340/* Expand code for an OpenMP ordered directive. */
10341
10342static void
726a989a 10343lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
953ff289 10344{
726a989a 10345 tree block;
538dd0b7
DM
10346 gimple stmt = gsi_stmt (*gsi_p);
10347 gcall *x;
10348 gbind *bind;
953ff289 10349
45852dcc 10350 push_gimplify_context ();
953ff289
DN
10351
10352 block = make_node (BLOCK);
355a7673
MM
10353 bind = gimple_build_bind (NULL, NULL, block);
10354 gsi_replace (gsi_p, bind, true);
10355 gimple_bind_add_stmt (bind, stmt);
777f7f9a 10356
e79983f4
MM
10357 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START),
10358 0);
726a989a 10359 gimple_bind_add_stmt (bind, x);
953ff289 10360
355a7673 10361 lower_omp (gimple_omp_body_ptr (stmt), ctx);
726a989a
RB
10362 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
10363 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10364 gimple_omp_set_body (stmt, NULL);
953ff289 10365
e79983f4 10366 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END), 0);
726a989a 10367 gimple_bind_add_stmt (bind, x);
777f7f9a 10368
726a989a 10369 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
777f7f9a 10370
953ff289 10371 pop_gimplify_context (bind);
50674e96 10372
726a989a
RB
10373 gimple_bind_append_vars (bind, ctx->block_vars);
10374 BLOCK_VARS (block) = gimple_bind_vars (bind);
953ff289
DN
10375}
10376
953ff289 10377
726a989a 10378/* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
953ff289
DN
10379 substitution of a couple of function calls. But in the NAMED case,
10380 requires that languages coordinate a symbol name. It is therefore
10381 best put here in common code. */
10382
de144fb2 10383static GTY(()) hash_map<tree, tree> *critical_name_mutexes;
953ff289
DN
10384
10385static void
726a989a 10386lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
953ff289 10387{
726a989a
RB
10388 tree block;
10389 tree name, lock, unlock;
538dd0b7
DM
10390 gomp_critical *stmt = as_a <gomp_critical *> (gsi_stmt (*gsi_p));
10391 gbind *bind;
db3927fb 10392 location_t loc = gimple_location (stmt);
726a989a 10393 gimple_seq tbody;
953ff289 10394
726a989a 10395 name = gimple_omp_critical_name (stmt);
953ff289
DN
10396 if (name)
10397 {
5039610b 10398 tree decl;
953ff289
DN
10399
10400 if (!critical_name_mutexes)
de144fb2 10401 critical_name_mutexes = hash_map<tree, tree>::create_ggc (10);
953ff289 10402
de144fb2 10403 tree *n = critical_name_mutexes->get (name);
953ff289
DN
10404 if (n == NULL)
10405 {
10406 char *new_str;
10407
b731b390 10408 decl = create_tmp_var_raw (ptr_type_node);
953ff289
DN
10409
10410 new_str = ACONCAT ((".gomp_critical_user_",
10411 IDENTIFIER_POINTER (name), NULL));
10412 DECL_NAME (decl) = get_identifier (new_str);
10413 TREE_PUBLIC (decl) = 1;
10414 TREE_STATIC (decl) = 1;
10415 DECL_COMMON (decl) = 1;
10416 DECL_ARTIFICIAL (decl) = 1;
10417 DECL_IGNORED_P (decl) = 1;
1f6be682 10418
9041d2e6 10419 varpool_node::finalize_decl (decl);
953ff289 10420
de144fb2 10421 critical_name_mutexes->put (name, decl);
953ff289
DN
10422 }
10423 else
de144fb2 10424 decl = *n;
953ff289 10425
41dbbb37 10426 /* If '#pragma omp critical' is inside offloaded region or
476ff787
AT
10427 inside function marked as offloadable, the symbol must be
10428 marked as offloadable too. */
10429 omp_context *octx;
10430 if (cgraph_node::get (current_function_decl)->offloadable)
10431 varpool_node::get_create (decl)->offloadable = 1;
10432 else
10433 for (octx = ctx->outer; octx; octx = octx->outer)
41dbbb37 10434 if (is_gimple_omp_offloaded (octx->stmt))
476ff787
AT
10435 {
10436 varpool_node::get_create (decl)->offloadable = 1;
10437 break;
10438 }
10439
e79983f4 10440 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START);
db3927fb 10441 lock = build_call_expr_loc (loc, lock, 1, build_fold_addr_expr_loc (loc, decl));
953ff289 10442
e79983f4 10443 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END);
db3927fb
AH
10444 unlock = build_call_expr_loc (loc, unlock, 1,
10445 build_fold_addr_expr_loc (loc, decl));
953ff289
DN
10446 }
10447 else
10448 {
e79983f4 10449 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START);
db3927fb 10450 lock = build_call_expr_loc (loc, lock, 0);
953ff289 10451
e79983f4 10452 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END);
db3927fb 10453 unlock = build_call_expr_loc (loc, unlock, 0);
953ff289
DN
10454 }
10455
45852dcc 10456 push_gimplify_context ();
953ff289
DN
10457
10458 block = make_node (BLOCK);
355a7673
MM
10459 bind = gimple_build_bind (NULL, NULL, block);
10460 gsi_replace (gsi_p, bind, true);
10461 gimple_bind_add_stmt (bind, stmt);
777f7f9a 10462
726a989a
RB
10463 tbody = gimple_bind_body (bind);
10464 gimplify_and_add (lock, &tbody);
10465 gimple_bind_set_body (bind, tbody);
953ff289 10466
355a7673 10467 lower_omp (gimple_omp_body_ptr (stmt), ctx);
726a989a
RB
10468 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
10469 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10470 gimple_omp_set_body (stmt, NULL);
953ff289 10471
726a989a
RB
10472 tbody = gimple_bind_body (bind);
10473 gimplify_and_add (unlock, &tbody);
10474 gimple_bind_set_body (bind, tbody);
777f7f9a 10475
726a989a 10476 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
953ff289
DN
10477
10478 pop_gimplify_context (bind);
726a989a
RB
10479 gimple_bind_append_vars (bind, ctx->block_vars);
10480 BLOCK_VARS (block) = gimple_bind_vars (bind);
50674e96
DN
10481}
10482
10483
10484/* A subroutine of lower_omp_for. Generate code to emit the predicate
10485 for a lastprivate clause. Given a loop control predicate of (V
10486 cond N2), we gate the clause on (!(V cond N2)). The lowered form
3d55c64b
JJ
10487 is appended to *DLIST, iterator initialization is appended to
10488 *BODY_P. */
50674e96
DN
10489
10490static void
726a989a
RB
10491lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
10492 gimple_seq *dlist, struct omp_context *ctx)
50674e96 10493{
726a989a 10494 tree clauses, cond, vinit;
50674e96 10495 enum tree_code cond_code;
726a989a 10496 gimple_seq stmts;
b8698a0f 10497
a68ab351 10498 cond_code = fd->loop.cond_code;
50674e96
DN
10499 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
10500
10501 /* When possible, use a strict equality expression. This can let VRP
10502 type optimizations deduce the value and remove a copy. */
9541ffee 10503 if (tree_fits_shwi_p (fd->loop.step))
50674e96 10504 {
eb1ce453 10505 HOST_WIDE_INT step = tree_to_shwi (fd->loop.step);
50674e96
DN
10506 if (step == 1 || step == -1)
10507 cond_code = EQ_EXPR;
10508 }
10509
a68ab351 10510 cond = build2 (cond_code, boolean_type_node, fd->loop.v, fd->loop.n2);
50674e96 10511
726a989a 10512 clauses = gimple_omp_for_clauses (fd->for_stmt);
3d55c64b
JJ
10513 stmts = NULL;
10514 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
726a989a 10515 if (!gimple_seq_empty_p (stmts))
3d55c64b 10516 {
726a989a 10517 gimple_seq_add_seq (&stmts, *dlist);
a68ab351 10518 *dlist = stmts;
3d55c64b
JJ
10519
10520 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
a68ab351 10521 vinit = fd->loop.n1;
3d55c64b 10522 if (cond_code == EQ_EXPR
9541ffee 10523 && tree_fits_shwi_p (fd->loop.n2)
a68ab351
JJ
10524 && ! integer_zerop (fd->loop.n2))
10525 vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0);
74bf76ed
JJ
10526 else
10527 vinit = unshare_expr (vinit);
3d55c64b
JJ
10528
10529 /* Initialize the iterator variable, so that threads that don't execute
10530 any iterations don't execute the lastprivate clauses by accident. */
726a989a 10531 gimplify_assign (fd->loop.v, vinit, body_p);
3d55c64b 10532 }
50674e96
DN
10533}
10534
10535
41dbbb37 10536/* Lower code for an OMP loop directive. */
50674e96
DN
10537
10538static void
726a989a 10539lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
50674e96 10540{
726a989a 10541 tree *rhs_p, block;
acf0174b 10542 struct omp_for_data fd, *fdp = NULL;
538dd0b7
DM
10543 gomp_for *stmt = as_a <gomp_for *> (gsi_stmt (*gsi_p));
10544 gbind *new_stmt;
0f900dfa 10545 gimple_seq omp_for_body, body, dlist;
726a989a 10546 size_t i;
50674e96 10547
45852dcc 10548 push_gimplify_context ();
50674e96 10549
355a7673 10550 lower_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
50674e96 10551
b357f682 10552 block = make_node (BLOCK);
726a989a 10553 new_stmt = gimple_build_bind (NULL, NULL, block);
355a7673
MM
10554 /* Replace at gsi right away, so that 'stmt' is no member
10555 of a sequence anymore as we're going to add to to a different
10556 one below. */
10557 gsi_replace (gsi_p, new_stmt, true);
b357f682 10558
50674e96
DN
10559 /* Move declaration of temporaries in the loop body before we make
10560 it go away. */
726a989a
RB
10561 omp_for_body = gimple_omp_body (stmt);
10562 if (!gimple_seq_empty_p (omp_for_body)
10563 && gimple_code (gimple_seq_first_stmt (omp_for_body)) == GIMPLE_BIND)
10564 {
538dd0b7
DM
10565 gbind *inner_bind
10566 = as_a <gbind *> (gimple_seq_first_stmt (omp_for_body));
c74559df 10567 tree vars = gimple_bind_vars (inner_bind);
726a989a 10568 gimple_bind_append_vars (new_stmt, vars);
c74559df
JJ
10569 /* bind_vars/BLOCK_VARS are being moved to new_stmt/block, don't
10570 keep them on the inner_bind and it's block. */
10571 gimple_bind_set_vars (inner_bind, NULL_TREE);
10572 if (gimple_bind_block (inner_bind))
10573 BLOCK_VARS (gimple_bind_block (inner_bind)) = NULL_TREE;
726a989a 10574 }
50674e96 10575
acf0174b
JJ
10576 if (gimple_omp_for_combined_into_p (stmt))
10577 {
10578 extract_omp_for_data (stmt, &fd, NULL);
10579 fdp = &fd;
10580
10581 /* We need two temporaries with fd.loop.v type (istart/iend)
10582 and then (fd.collapse - 1) temporaries with the same
10583 type for count2 ... countN-1 vars if not constant. */
10584 size_t count = 2;
10585 tree type = fd.iter_type;
10586 if (fd.collapse > 1
10587 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
10588 count += fd.collapse - 1;
10589 bool parallel_for = gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR;
10590 tree outerc = NULL, *pc = gimple_omp_for_clauses_ptr (stmt);
10591 tree clauses = *pc;
10592 if (parallel_for)
10593 outerc
10594 = find_omp_clause (gimple_omp_parallel_clauses (ctx->outer->stmt),
10595 OMP_CLAUSE__LOOPTEMP_);
10596 for (i = 0; i < count; i++)
10597 {
10598 tree temp;
10599 if (parallel_for)
10600 {
10601 gcc_assert (outerc);
10602 temp = lookup_decl (OMP_CLAUSE_DECL (outerc), ctx->outer);
10603 outerc = find_omp_clause (OMP_CLAUSE_CHAIN (outerc),
10604 OMP_CLAUSE__LOOPTEMP_);
10605 }
10606 else
f014c653 10607 {
b731b390 10608 temp = create_tmp_var (type);
f014c653
JJ
10609 insert_decl_map (&ctx->outer->cb, temp, temp);
10610 }
acf0174b
JJ
10611 *pc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
10612 OMP_CLAUSE_DECL (*pc) = temp;
10613 pc = &OMP_CLAUSE_CHAIN (*pc);
10614 }
10615 *pc = clauses;
10616 }
10617
726a989a 10618 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
50674e96 10619 dlist = NULL;
726a989a 10620 body = NULL;
acf0174b
JJ
10621 lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx,
10622 fdp);
726a989a 10623 gimple_seq_add_seq (&body, gimple_omp_for_pre_body (stmt));
50674e96 10624
74bf76ed
JJ
10625 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10626
50674e96
DN
10627 /* Lower the header expressions. At this point, we can assume that
10628 the header is of the form:
10629
10630 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
10631
10632 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
10633 using the .omp_data_s mapping, if needed. */
726a989a 10634 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
a68ab351 10635 {
726a989a 10636 rhs_p = gimple_omp_for_initial_ptr (stmt, i);
a68ab351 10637 if (!is_gimple_min_invariant (*rhs_p))
726a989a 10638 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
a68ab351 10639
726a989a 10640 rhs_p = gimple_omp_for_final_ptr (stmt, i);
a68ab351 10641 if (!is_gimple_min_invariant (*rhs_p))
726a989a 10642 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
a68ab351 10643
726a989a 10644 rhs_p = &TREE_OPERAND (gimple_omp_for_incr (stmt, i), 1);
a68ab351 10645 if (!is_gimple_min_invariant (*rhs_p))
726a989a 10646 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
a68ab351 10647 }
50674e96
DN
10648
10649 /* Once lowered, extract the bounds and clauses. */
a68ab351 10650 extract_omp_for_data (stmt, &fd, NULL);
50674e96 10651
726a989a 10652 lower_omp_for_lastprivate (&fd, &body, &dlist, ctx);
50674e96 10653
726a989a
RB
10654 gimple_seq_add_stmt (&body, stmt);
10655 gimple_seq_add_seq (&body, gimple_omp_body (stmt));
777f7f9a 10656
726a989a
RB
10657 gimple_seq_add_stmt (&body, gimple_build_omp_continue (fd.loop.v,
10658 fd.loop.v));
777f7f9a 10659
50674e96 10660 /* After the loop, add exit clauses. */
726a989a 10661 lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, ctx);
acf0174b
JJ
10662
10663 if (ctx->cancellable)
10664 gimple_seq_add_stmt (&body, gimple_build_label (ctx->cancel_label));
10665
726a989a 10666 gimple_seq_add_seq (&body, dlist);
50674e96 10667
726a989a 10668 body = maybe_catch_exception (body);
4a31b7ee 10669
777f7f9a 10670 /* Region exit marker goes at the end of the loop body. */
726a989a 10671 gimple_seq_add_stmt (&body, gimple_build_omp_return (fd.have_nowait));
acf0174b 10672 maybe_add_implicit_barrier_cancel (ctx, &body);
b357f682 10673 pop_gimplify_context (new_stmt);
726a989a
RB
10674
10675 gimple_bind_append_vars (new_stmt, ctx->block_vars);
10676 BLOCK_VARS (block) = gimple_bind_vars (new_stmt);
b357f682
JJ
10677 if (BLOCK_VARS (block))
10678 TREE_USED (block) = 1;
50674e96 10679
726a989a
RB
10680 gimple_bind_set_body (new_stmt, body);
10681 gimple_omp_set_body (stmt, NULL);
10682 gimple_omp_for_set_pre_body (stmt, NULL);
953ff289
DN
10683}
10684
b8698a0f 10685/* Callback for walk_stmts. Check if the current statement only contains
e0246869 10686 GIMPLE_OMP_FOR or GIMPLE_OMP_SECTIONS. */
69f1837b
JJ
10687
10688static tree
726a989a
RB
10689check_combined_parallel (gimple_stmt_iterator *gsi_p,
10690 bool *handled_ops_p,
10691 struct walk_stmt_info *wi)
69f1837b 10692{
d3bfe4de 10693 int *info = (int *) wi->info;
726a989a 10694 gimple stmt = gsi_stmt (*gsi_p);
69f1837b 10695
726a989a
RB
10696 *handled_ops_p = true;
10697 switch (gimple_code (stmt))
69f1837b 10698 {
726a989a
RB
10699 WALK_SUBSTMTS;
10700
10701 case GIMPLE_OMP_FOR:
10702 case GIMPLE_OMP_SECTIONS:
69f1837b
JJ
10703 *info = *info == 0 ? 1 : -1;
10704 break;
10705 default:
10706 *info = -1;
10707 break;
10708 }
10709 return NULL;
10710}
50674e96 10711
a68ab351
JJ
10712struct omp_taskcopy_context
10713{
10714 /* This field must be at the beginning, as we do "inheritance": Some
10715 callback functions for tree-inline.c (e.g., omp_copy_decl)
10716 receive a copy_body_data pointer that is up-casted to an
10717 omp_context pointer. */
10718 copy_body_data cb;
10719 omp_context *ctx;
10720};
10721
10722static tree
10723task_copyfn_copy_decl (tree var, copy_body_data *cb)
10724{
10725 struct omp_taskcopy_context *tcctx = (struct omp_taskcopy_context *) cb;
10726
10727 if (splay_tree_lookup (tcctx->ctx->sfield_map, (splay_tree_key) var))
b731b390 10728 return create_tmp_var (TREE_TYPE (var));
a68ab351
JJ
10729
10730 return var;
10731}
10732
10733static tree
10734task_copyfn_remap_type (struct omp_taskcopy_context *tcctx, tree orig_type)
10735{
10736 tree name, new_fields = NULL, type, f;
10737
10738 type = lang_hooks.types.make_type (RECORD_TYPE);
10739 name = DECL_NAME (TYPE_NAME (orig_type));
c2255bc4
AH
10740 name = build_decl (gimple_location (tcctx->ctx->stmt),
10741 TYPE_DECL, name, type);
a68ab351
JJ
10742 TYPE_NAME (type) = name;
10743
10744 for (f = TYPE_FIELDS (orig_type); f ; f = TREE_CHAIN (f))
10745 {
10746 tree new_f = copy_node (f);
10747 DECL_CONTEXT (new_f) = type;
10748 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &tcctx->cb);
10749 TREE_CHAIN (new_f) = new_fields;
726a989a
RB
10750 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &tcctx->cb, NULL);
10751 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r, &tcctx->cb, NULL);
10752 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
10753 &tcctx->cb, NULL);
a68ab351 10754 new_fields = new_f;
b787e7a2 10755 tcctx->cb.decl_map->put (f, new_f);
a68ab351
JJ
10756 }
10757 TYPE_FIELDS (type) = nreverse (new_fields);
10758 layout_type (type);
10759 return type;
10760}
10761
10762/* Create task copyfn. */
10763
10764static void
538dd0b7 10765create_task_copyfn (gomp_task *task_stmt, omp_context *ctx)
a68ab351
JJ
10766{
10767 struct function *child_cfun;
10768 tree child_fn, t, c, src, dst, f, sf, arg, sarg, decl;
10769 tree record_type, srecord_type, bind, list;
10770 bool record_needs_remap = false, srecord_needs_remap = false;
10771 splay_tree_node n;
10772 struct omp_taskcopy_context tcctx;
db3927fb 10773 location_t loc = gimple_location (task_stmt);
a68ab351 10774
726a989a 10775 child_fn = gimple_omp_task_copy_fn (task_stmt);
a68ab351
JJ
10776 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
10777 gcc_assert (child_cfun->cfg == NULL);
a68ab351
JJ
10778 DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
10779
10780 /* Reset DECL_CONTEXT on function arguments. */
910ad8de 10781 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
a68ab351
JJ
10782 DECL_CONTEXT (t) = child_fn;
10783
10784 /* Populate the function. */
45852dcc 10785 push_gimplify_context ();
af16bc76 10786 push_cfun (child_cfun);
a68ab351
JJ
10787
10788 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
10789 TREE_SIDE_EFFECTS (bind) = 1;
10790 list = NULL;
10791 DECL_SAVED_TREE (child_fn) = bind;
726a989a 10792 DECL_SOURCE_LOCATION (child_fn) = gimple_location (task_stmt);
a68ab351
JJ
10793
10794 /* Remap src and dst argument types if needed. */
10795 record_type = ctx->record_type;
10796 srecord_type = ctx->srecord_type;
910ad8de 10797 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
a68ab351
JJ
10798 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
10799 {
10800 record_needs_remap = true;
10801 break;
10802 }
910ad8de 10803 for (f = TYPE_FIELDS (srecord_type); f ; f = DECL_CHAIN (f))
a68ab351
JJ
10804 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
10805 {
10806 srecord_needs_remap = true;
10807 break;
10808 }
10809
10810 if (record_needs_remap || srecord_needs_remap)
10811 {
10812 memset (&tcctx, '\0', sizeof (tcctx));
10813 tcctx.cb.src_fn = ctx->cb.src_fn;
10814 tcctx.cb.dst_fn = child_fn;
d52f5295 10815 tcctx.cb.src_node = cgraph_node::get (tcctx.cb.src_fn);
fe660d7b 10816 gcc_checking_assert (tcctx.cb.src_node);
a68ab351
JJ
10817 tcctx.cb.dst_node = tcctx.cb.src_node;
10818 tcctx.cb.src_cfun = ctx->cb.src_cfun;
10819 tcctx.cb.copy_decl = task_copyfn_copy_decl;
1d65f45c 10820 tcctx.cb.eh_lp_nr = 0;
a68ab351 10821 tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
b787e7a2 10822 tcctx.cb.decl_map = new hash_map<tree, tree>;
a68ab351
JJ
10823 tcctx.ctx = ctx;
10824
10825 if (record_needs_remap)
10826 record_type = task_copyfn_remap_type (&tcctx, record_type);
10827 if (srecord_needs_remap)
10828 srecord_type = task_copyfn_remap_type (&tcctx, srecord_type);
10829 }
10830 else
10831 tcctx.cb.decl_map = NULL;
10832
a68ab351
JJ
10833 arg = DECL_ARGUMENTS (child_fn);
10834 TREE_TYPE (arg) = build_pointer_type (record_type);
910ad8de 10835 sarg = DECL_CHAIN (arg);
a68ab351
JJ
10836 TREE_TYPE (sarg) = build_pointer_type (srecord_type);
10837
10838 /* First pass: initialize temporaries used in record_type and srecord_type
10839 sizes and field offsets. */
10840 if (tcctx.cb.decl_map)
726a989a 10841 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
a68ab351
JJ
10842 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
10843 {
10844 tree *p;
10845
10846 decl = OMP_CLAUSE_DECL (c);
b787e7a2 10847 p = tcctx.cb.decl_map->get (decl);
a68ab351
JJ
10848 if (p == NULL)
10849 continue;
10850 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
10851 sf = (tree) n->value;
b787e7a2 10852 sf = *tcctx.cb.decl_map->get (sf);
70f34814 10853 src = build_simple_mem_ref_loc (loc, sarg);
a9a58711 10854 src = omp_build_component_ref (src, sf);
726a989a 10855 t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
a68ab351
JJ
10856 append_to_statement_list (t, &list);
10857 }
10858
10859 /* Second pass: copy shared var pointers and copy construct non-VLA
10860 firstprivate vars. */
726a989a 10861 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
a68ab351
JJ
10862 switch (OMP_CLAUSE_CODE (c))
10863 {
10864 case OMP_CLAUSE_SHARED:
10865 decl = OMP_CLAUSE_DECL (c);
10866 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
10867 if (n == NULL)
10868 break;
10869 f = (tree) n->value;
10870 if (tcctx.cb.decl_map)
b787e7a2 10871 f = *tcctx.cb.decl_map->get (f);
a68ab351
JJ
10872 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
10873 sf = (tree) n->value;
10874 if (tcctx.cb.decl_map)
b787e7a2 10875 sf = *tcctx.cb.decl_map->get (sf);
70f34814 10876 src = build_simple_mem_ref_loc (loc, sarg);
a9a58711 10877 src = omp_build_component_ref (src, sf);
70f34814 10878 dst = build_simple_mem_ref_loc (loc, arg);
a9a58711 10879 dst = omp_build_component_ref (dst, f);
726a989a 10880 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
a68ab351
JJ
10881 append_to_statement_list (t, &list);
10882 break;
10883 case OMP_CLAUSE_FIRSTPRIVATE:
10884 decl = OMP_CLAUSE_DECL (c);
10885 if (is_variable_sized (decl))
10886 break;
10887 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
10888 if (n == NULL)
10889 break;
10890 f = (tree) n->value;
10891 if (tcctx.cb.decl_map)
b787e7a2 10892 f = *tcctx.cb.decl_map->get (f);
a68ab351
JJ
10893 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
10894 if (n != NULL)
10895 {
10896 sf = (tree) n->value;
10897 if (tcctx.cb.decl_map)
b787e7a2 10898 sf = *tcctx.cb.decl_map->get (sf);
70f34814 10899 src = build_simple_mem_ref_loc (loc, sarg);
a9a58711 10900 src = omp_build_component_ref (src, sf);
a68ab351 10901 if (use_pointer_for_field (decl, NULL) || is_reference (decl))
70f34814 10902 src = build_simple_mem_ref_loc (loc, src);
a68ab351
JJ
10903 }
10904 else
10905 src = decl;
70f34814 10906 dst = build_simple_mem_ref_loc (loc, arg);
a9a58711 10907 dst = omp_build_component_ref (dst, f);
a68ab351
JJ
10908 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
10909 append_to_statement_list (t, &list);
10910 break;
10911 case OMP_CLAUSE_PRIVATE:
10912 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c))
10913 break;
10914 decl = OMP_CLAUSE_DECL (c);
10915 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
10916 f = (tree) n->value;
10917 if (tcctx.cb.decl_map)
b787e7a2 10918 f = *tcctx.cb.decl_map->get (f);
a68ab351
JJ
10919 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
10920 if (n != NULL)
10921 {
10922 sf = (tree) n->value;
10923 if (tcctx.cb.decl_map)
b787e7a2 10924 sf = *tcctx.cb.decl_map->get (sf);
70f34814 10925 src = build_simple_mem_ref_loc (loc, sarg);
a9a58711 10926 src = omp_build_component_ref (src, sf);
a68ab351 10927 if (use_pointer_for_field (decl, NULL))
70f34814 10928 src = build_simple_mem_ref_loc (loc, src);
a68ab351
JJ
10929 }
10930 else
10931 src = decl;
70f34814 10932 dst = build_simple_mem_ref_loc (loc, arg);
a9a58711 10933 dst = omp_build_component_ref (dst, f);
726a989a 10934 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
a68ab351
JJ
10935 append_to_statement_list (t, &list);
10936 break;
10937 default:
10938 break;
10939 }
10940
10941 /* Last pass: handle VLA firstprivates. */
10942 if (tcctx.cb.decl_map)
726a989a 10943 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
a68ab351
JJ
10944 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
10945 {
10946 tree ind, ptr, df;
10947
10948 decl = OMP_CLAUSE_DECL (c);
10949 if (!is_variable_sized (decl))
10950 continue;
10951 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
10952 if (n == NULL)
10953 continue;
10954 f = (tree) n->value;
b787e7a2 10955 f = *tcctx.cb.decl_map->get (f);
a68ab351
JJ
10956 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
10957 ind = DECL_VALUE_EXPR (decl);
10958 gcc_assert (TREE_CODE (ind) == INDIRECT_REF);
10959 gcc_assert (DECL_P (TREE_OPERAND (ind, 0)));
10960 n = splay_tree_lookup (ctx->sfield_map,
10961 (splay_tree_key) TREE_OPERAND (ind, 0));
10962 sf = (tree) n->value;
b787e7a2 10963 sf = *tcctx.cb.decl_map->get (sf);
70f34814 10964 src = build_simple_mem_ref_loc (loc, sarg);
a9a58711 10965 src = omp_build_component_ref (src, sf);
70f34814
RG
10966 src = build_simple_mem_ref_loc (loc, src);
10967 dst = build_simple_mem_ref_loc (loc, arg);
a9a58711 10968 dst = omp_build_component_ref (dst, f);
a68ab351
JJ
10969 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
10970 append_to_statement_list (t, &list);
10971 n = splay_tree_lookup (ctx->field_map,
10972 (splay_tree_key) TREE_OPERAND (ind, 0));
10973 df = (tree) n->value;
b787e7a2 10974 df = *tcctx.cb.decl_map->get (df);
70f34814 10975 ptr = build_simple_mem_ref_loc (loc, arg);
a9a58711 10976 ptr = omp_build_component_ref (ptr, df);
726a989a 10977 t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
db3927fb 10978 build_fold_addr_expr_loc (loc, dst));
a68ab351
JJ
10979 append_to_statement_list (t, &list);
10980 }
10981
10982 t = build1 (RETURN_EXPR, void_type_node, NULL);
10983 append_to_statement_list (t, &list);
10984
10985 if (tcctx.cb.decl_map)
b787e7a2 10986 delete tcctx.cb.decl_map;
a68ab351
JJ
10987 pop_gimplify_context (NULL);
10988 BIND_EXPR_BODY (bind) = list;
10989 pop_cfun ();
a68ab351
JJ
10990}
10991
acf0174b
JJ
10992static void
10993lower_depend_clauses (gimple stmt, gimple_seq *iseq, gimple_seq *oseq)
10994{
10995 tree c, clauses;
10996 gimple g;
10997 size_t n_in = 0, n_out = 0, idx = 2, i;
10998
10999 clauses = find_omp_clause (gimple_omp_task_clauses (stmt),
11000 OMP_CLAUSE_DEPEND);
11001 gcc_assert (clauses);
11002 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
11003 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
11004 switch (OMP_CLAUSE_DEPEND_KIND (c))
11005 {
11006 case OMP_CLAUSE_DEPEND_IN:
11007 n_in++;
11008 break;
11009 case OMP_CLAUSE_DEPEND_OUT:
11010 case OMP_CLAUSE_DEPEND_INOUT:
11011 n_out++;
11012 break;
11013 default:
11014 gcc_unreachable ();
11015 }
11016 tree type = build_array_type_nelts (ptr_type_node, n_in + n_out + 2);
b731b390 11017 tree array = create_tmp_var (type);
acf0174b
JJ
11018 tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
11019 NULL_TREE);
11020 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_in + n_out));
11021 gimple_seq_add_stmt (iseq, g);
11022 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
11023 NULL_TREE);
11024 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_out));
11025 gimple_seq_add_stmt (iseq, g);
11026 for (i = 0; i < 2; i++)
11027 {
11028 if ((i ? n_in : n_out) == 0)
11029 continue;
11030 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
11031 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
11032 && ((OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_IN) ^ i))
11033 {
11034 tree t = OMP_CLAUSE_DECL (c);
11035 t = fold_convert (ptr_type_node, t);
11036 gimplify_expr (&t, iseq, NULL, is_gimple_val, fb_rvalue);
11037 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (idx++),
11038 NULL_TREE, NULL_TREE);
11039 g = gimple_build_assign (r, t);
11040 gimple_seq_add_stmt (iseq, g);
11041 }
11042 }
11043 tree *p = gimple_omp_task_clauses_ptr (stmt);
11044 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
11045 OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
11046 OMP_CLAUSE_CHAIN (c) = *p;
11047 *p = c;
11048 tree clobber = build_constructor (type, NULL);
11049 TREE_THIS_VOLATILE (clobber) = 1;
11050 g = gimple_build_assign (array, clobber);
11051 gimple_seq_add_stmt (oseq, g);
11052}
11053
726a989a
RB
11054/* Lower the OpenMP parallel or task directive in the current statement
11055 in GSI_P. CTX holds context information for the directive. */
50674e96
DN
11056
11057static void
726a989a 11058lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
50674e96 11059{
726a989a
RB
11060 tree clauses;
11061 tree child_fn, t;
11062 gimple stmt = gsi_stmt (*gsi_p);
538dd0b7 11063 gbind *par_bind, *bind, *dep_bind = NULL;
acf0174b 11064 gimple_seq par_body, olist, ilist, par_olist, par_rlist, par_ilist, new_body;
db3927fb 11065 location_t loc = gimple_location (stmt);
50674e96 11066
726a989a 11067 clauses = gimple_omp_taskreg_clauses (stmt);
538dd0b7
DM
11068 par_bind
11069 = as_a <gbind *> (gimple_seq_first_stmt (gimple_omp_body (stmt)));
726a989a 11070 par_body = gimple_bind_body (par_bind);
50674e96 11071 child_fn = ctx->cb.dst_fn;
726a989a
RB
11072 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
11073 && !gimple_omp_parallel_combined_p (stmt))
69f1837b
JJ
11074 {
11075 struct walk_stmt_info wi;
11076 int ws_num = 0;
11077
11078 memset (&wi, 0, sizeof (wi));
69f1837b
JJ
11079 wi.info = &ws_num;
11080 wi.val_only = true;
726a989a 11081 walk_gimple_seq (par_body, check_combined_parallel, NULL, &wi);
69f1837b 11082 if (ws_num == 1)
726a989a 11083 gimple_omp_parallel_set_combined_p (stmt, true);
69f1837b 11084 }
acf0174b
JJ
11085 gimple_seq dep_ilist = NULL;
11086 gimple_seq dep_olist = NULL;
11087 if (gimple_code (stmt) == GIMPLE_OMP_TASK
11088 && find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
11089 {
45852dcc 11090 push_gimplify_context ();
acf0174b
JJ
11091 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
11092 lower_depend_clauses (stmt, &dep_ilist, &dep_olist);
11093 }
11094
a68ab351 11095 if (ctx->srecord_type)
538dd0b7 11096 create_task_copyfn (as_a <gomp_task *> (stmt), ctx);
50674e96 11097
45852dcc 11098 push_gimplify_context ();
50674e96 11099
726a989a
RB
11100 par_olist = NULL;
11101 par_ilist = NULL;
acf0174b
JJ
11102 par_rlist = NULL;
11103 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx, NULL);
355a7673 11104 lower_omp (&par_body, ctx);
726a989a 11105 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL)
acf0174b 11106 lower_reduction_clauses (clauses, &par_rlist, ctx);
50674e96
DN
11107
11108 /* Declare all the variables created by mapping and the variables
11109 declared in the scope of the parallel body. */
11110 record_vars_into (ctx->block_vars, child_fn);
726a989a 11111 record_vars_into (gimple_bind_vars (par_bind), child_fn);
50674e96
DN
11112
11113 if (ctx->record_type)
11114 {
a68ab351
JJ
11115 ctx->sender_decl
11116 = create_tmp_var (ctx->srecord_type ? ctx->srecord_type
11117 : ctx->record_type, ".omp_data_o");
cd3f04c8 11118 DECL_NAMELESS (ctx->sender_decl) = 1;
628c189e 11119 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
726a989a 11120 gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl);
50674e96
DN
11121 }
11122
726a989a
RB
11123 olist = NULL;
11124 ilist = NULL;
50674e96
DN
11125 lower_send_clauses (clauses, &ilist, &olist, ctx);
11126 lower_send_shared_vars (&ilist, &olist, ctx);
11127
acf0174b
JJ
11128 if (ctx->record_type)
11129 {
11130 tree clobber = build_constructor (TREE_TYPE (ctx->sender_decl), NULL);
11131 TREE_THIS_VOLATILE (clobber) = 1;
11132 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
11133 clobber));
11134 }
11135
50674e96 11136 /* Once all the expansions are done, sequence all the different
726a989a 11137 fragments inside gimple_omp_body. */
50674e96 11138
726a989a 11139 new_body = NULL;
50674e96
DN
11140
11141 if (ctx->record_type)
11142 {
db3927fb 11143 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
018b899b 11144 /* fixup_child_record_type might have changed receiver_decl's type. */
db3927fb 11145 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
726a989a
RB
11146 gimple_seq_add_stmt (&new_body,
11147 gimple_build_assign (ctx->receiver_decl, t));
50674e96
DN
11148 }
11149
726a989a
RB
11150 gimple_seq_add_seq (&new_body, par_ilist);
11151 gimple_seq_add_seq (&new_body, par_body);
acf0174b
JJ
11152 gimple_seq_add_seq (&new_body, par_rlist);
11153 if (ctx->cancellable)
11154 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
726a989a
RB
11155 gimple_seq_add_seq (&new_body, par_olist);
11156 new_body = maybe_catch_exception (new_body);
11157 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
11158 gimple_omp_set_body (stmt, new_body);
50674e96 11159
726a989a 11160 bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
acf0174b
JJ
11161 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
11162 gimple_bind_add_seq (bind, ilist);
11163 gimple_bind_add_stmt (bind, stmt);
11164 gimple_bind_add_seq (bind, olist);
11165
11166 pop_gimplify_context (NULL);
11167
11168 if (dep_bind)
11169 {
11170 gimple_bind_add_seq (dep_bind, dep_ilist);
11171 gimple_bind_add_stmt (dep_bind, bind);
11172 gimple_bind_add_seq (dep_bind, dep_olist);
11173 pop_gimplify_context (dep_bind);
11174 }
11175}
11176
41dbbb37 11177/* Lower the GIMPLE_OMP_TARGET in the current statement
acf0174b
JJ
11178 in GSI_P. CTX holds context information for the directive. */
11179
11180static void
11181lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
11182{
11183 tree clauses;
11184 tree child_fn, t, c;
538dd0b7 11185 gomp_target *stmt = as_a <gomp_target *> (gsi_stmt (*gsi_p));
41dbbb37
TS
11186 gbind *tgt_bind, *bind;
11187 gimple_seq tgt_body, olist, ilist, orlist, irlist, new_body;
acf0174b 11188 location_t loc = gimple_location (stmt);
41dbbb37 11189 bool offloaded, data_region;
acf0174b
JJ
11190 unsigned int map_cnt = 0;
11191
41dbbb37
TS
11192 offloaded = is_gimple_omp_offloaded (stmt);
11193 switch (gimple_omp_target_kind (stmt))
11194 {
11195 case GF_OMP_TARGET_KIND_REGION:
11196 case GF_OMP_TARGET_KIND_UPDATE:
11197 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
11198 case GF_OMP_TARGET_KIND_OACC_KERNELS:
11199 case GF_OMP_TARGET_KIND_OACC_UPDATE:
11200 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
11201 data_region = false;
11202 break;
11203 case GF_OMP_TARGET_KIND_DATA:
11204 case GF_OMP_TARGET_KIND_OACC_DATA:
11205 data_region = true;
11206 break;
11207 default:
11208 gcc_unreachable ();
11209 }
11210
acf0174b 11211 clauses = gimple_omp_target_clauses (stmt);
41dbbb37
TS
11212
11213 tgt_bind = NULL;
11214 tgt_body = NULL;
11215 if (offloaded)
acf0174b 11216 {
538dd0b7 11217 tgt_bind = gimple_seq_first_stmt_as_a_bind (gimple_omp_body (stmt));
acf0174b
JJ
11218 tgt_body = gimple_bind_body (tgt_bind);
11219 }
41dbbb37 11220 else if (data_region)
acf0174b
JJ
11221 tgt_body = gimple_omp_body (stmt);
11222 child_fn = ctx->cb.dst_fn;
11223
45852dcc 11224 push_gimplify_context ();
acf0174b 11225
41dbbb37
TS
11226 irlist = NULL;
11227 orlist = NULL;
11228 if (offloaded
11229 && is_gimple_omp_oacc (stmt))
11230 oacc_process_reduction_data (&tgt_body, &irlist, &orlist, ctx);
11231
acf0174b
JJ
11232 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
11233 switch (OMP_CLAUSE_CODE (c))
11234 {
11235 tree var, x;
11236
11237 default:
11238 break;
11239 case OMP_CLAUSE_MAP:
41dbbb37
TS
11240#ifdef ENABLE_CHECKING
11241 /* First check what we're prepared to handle in the following. */
11242 switch (OMP_CLAUSE_MAP_KIND (c))
11243 {
11244 case GOMP_MAP_ALLOC:
11245 case GOMP_MAP_TO:
11246 case GOMP_MAP_FROM:
11247 case GOMP_MAP_TOFROM:
11248 case GOMP_MAP_POINTER:
11249 case GOMP_MAP_TO_PSET:
11250 break;
11251 case GOMP_MAP_FORCE_ALLOC:
11252 case GOMP_MAP_FORCE_TO:
11253 case GOMP_MAP_FORCE_FROM:
11254 case GOMP_MAP_FORCE_TOFROM:
11255 case GOMP_MAP_FORCE_PRESENT:
11256 case GOMP_MAP_FORCE_DEALLOC:
11257 case GOMP_MAP_FORCE_DEVICEPTR:
11258 gcc_assert (is_gimple_omp_oacc (stmt));
11259 break;
11260 default:
11261 gcc_unreachable ();
11262 }
11263#endif
11264 /* FALLTHRU */
acf0174b
JJ
11265 case OMP_CLAUSE_TO:
11266 case OMP_CLAUSE_FROM:
11267 var = OMP_CLAUSE_DECL (c);
11268 if (!DECL_P (var))
11269 {
11270 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
11271 || !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
11272 map_cnt++;
11273 continue;
11274 }
11275
11276 if (DECL_SIZE (var)
11277 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
11278 {
11279 tree var2 = DECL_VALUE_EXPR (var);
11280 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
11281 var2 = TREE_OPERAND (var2, 0);
11282 gcc_assert (DECL_P (var2));
11283 var = var2;
11284 }
11285
11286 if (!maybe_lookup_field (var, ctx))
11287 continue;
11288
41dbbb37 11289 if (offloaded)
acf0174b
JJ
11290 {
11291 x = build_receiver_ref (var, true, ctx);
11292 tree new_var = lookup_decl (var, ctx);
41dbbb37 11293 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
acf0174b
JJ
11294 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
11295 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
11296 x = build_simple_mem_ref (x);
11297 SET_DECL_VALUE_EXPR (new_var, x);
11298 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
11299 }
11300 map_cnt++;
11301 }
11302
41dbbb37 11303 if (offloaded)
acf0174b
JJ
11304 {
11305 target_nesting_level++;
11306 lower_omp (&tgt_body, ctx);
11307 target_nesting_level--;
11308 }
41dbbb37 11309 else if (data_region)
acf0174b
JJ
11310 lower_omp (&tgt_body, ctx);
11311
41dbbb37 11312 if (offloaded)
acf0174b
JJ
11313 {
11314 /* Declare all the variables created by mapping and the variables
11315 declared in the scope of the target body. */
11316 record_vars_into (ctx->block_vars, child_fn);
11317 record_vars_into (gimple_bind_vars (tgt_bind), child_fn);
11318 }
11319
11320 olist = NULL;
11321 ilist = NULL;
11322 if (ctx->record_type)
11323 {
11324 ctx->sender_decl
11325 = create_tmp_var (ctx->record_type, ".omp_data_arr");
11326 DECL_NAMELESS (ctx->sender_decl) = 1;
11327 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
11328 t = make_tree_vec (3);
11329 TREE_VEC_ELT (t, 0) = ctx->sender_decl;
11330 TREE_VEC_ELT (t, 1)
11331 = create_tmp_var (build_array_type_nelts (size_type_node, map_cnt),
11332 ".omp_data_sizes");
11333 DECL_NAMELESS (TREE_VEC_ELT (t, 1)) = 1;
11334 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 1)) = 1;
11335 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 1;
41dbbb37
TS
11336 tree tkind_type;
11337 int talign_shift;
11338 if (is_gimple_omp_oacc (stmt))
11339 {
11340 tkind_type = short_unsigned_type_node;
11341 talign_shift = 8;
11342 }
11343 else
11344 {
11345 tkind_type = unsigned_char_type_node;
11346 talign_shift = 3;
11347 }
acf0174b 11348 TREE_VEC_ELT (t, 2)
41dbbb37 11349 = create_tmp_var (build_array_type_nelts (tkind_type, map_cnt),
acf0174b
JJ
11350 ".omp_data_kinds");
11351 DECL_NAMELESS (TREE_VEC_ELT (t, 2)) = 1;
11352 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 2)) = 1;
11353 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 1;
11354 gimple_omp_target_set_data_arg (stmt, t);
11355
11356 vec<constructor_elt, va_gc> *vsize;
11357 vec<constructor_elt, va_gc> *vkind;
11358 vec_alloc (vsize, map_cnt);
11359 vec_alloc (vkind, map_cnt);
11360 unsigned int map_idx = 0;
11361
11362 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
11363 switch (OMP_CLAUSE_CODE (c))
11364 {
11365 tree ovar, nc;
11366
11367 default:
11368 break;
11369 case OMP_CLAUSE_MAP:
11370 case OMP_CLAUSE_TO:
11371 case OMP_CLAUSE_FROM:
11372 nc = c;
11373 ovar = OMP_CLAUSE_DECL (c);
11374 if (!DECL_P (ovar))
11375 {
11376 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
11377 && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
11378 {
11379 gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c))
11380 == get_base_address (ovar));
11381 nc = OMP_CLAUSE_CHAIN (c);
11382 ovar = OMP_CLAUSE_DECL (nc);
11383 }
11384 else
11385 {
11386 tree x = build_sender_ref (ovar, ctx);
11387 tree v
11388 = build_fold_addr_expr_with_type (ovar, ptr_type_node);
11389 gimplify_assign (x, v, &ilist);
11390 nc = NULL_TREE;
11391 }
11392 }
11393 else
11394 {
11395 if (DECL_SIZE (ovar)
11396 && TREE_CODE (DECL_SIZE (ovar)) != INTEGER_CST)
11397 {
11398 tree ovar2 = DECL_VALUE_EXPR (ovar);
11399 gcc_assert (TREE_CODE (ovar2) == INDIRECT_REF);
11400 ovar2 = TREE_OPERAND (ovar2, 0);
11401 gcc_assert (DECL_P (ovar2));
11402 ovar = ovar2;
11403 }
11404 if (!maybe_lookup_field (ovar, ctx))
11405 continue;
11406 }
11407
0fe81a0f
JJ
11408 unsigned int talign = TYPE_ALIGN_UNIT (TREE_TYPE (ovar));
11409 if (DECL_P (ovar) && DECL_ALIGN_UNIT (ovar) > talign)
11410 talign = DECL_ALIGN_UNIT (ovar);
acf0174b
JJ
11411 if (nc)
11412 {
11413 tree var = lookup_decl_in_outer_ctx (ovar, ctx);
11414 tree x = build_sender_ref (ovar, ctx);
41dbbb37
TS
11415 if (maybe_lookup_oacc_reduction (var, ctx))
11416 {
11417 gcc_checking_assert (offloaded
11418 && is_gimple_omp_oacc (stmt));
11419 gimplify_assign (x, var, &ilist);
11420 }
11421 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
11422 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
11423 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
11424 && TREE_CODE (TREE_TYPE (ovar)) == ARRAY_TYPE)
acf0174b 11425 {
41dbbb37 11426 gcc_assert (offloaded);
acf0174b 11427 tree avar
b731b390 11428 = create_tmp_var (TREE_TYPE (TREE_TYPE (x)));
acf0174b
JJ
11429 mark_addressable (avar);
11430 gimplify_assign (avar, build_fold_addr_expr (var), &ilist);
0fe81a0f 11431 talign = DECL_ALIGN_UNIT (avar);
acf0174b
JJ
11432 avar = build_fold_addr_expr (avar);
11433 gimplify_assign (x, avar, &ilist);
11434 }
11435 else if (is_gimple_reg (var))
11436 {
41dbbb37 11437 gcc_assert (offloaded);
b731b390 11438 tree avar = create_tmp_var (TREE_TYPE (var));
acf0174b 11439 mark_addressable (avar);
41dbbb37
TS
11440 enum gomp_map_kind map_kind = OMP_CLAUSE_MAP_KIND (c);
11441 if (GOMP_MAP_COPY_TO_P (map_kind)
11442 || map_kind == GOMP_MAP_POINTER
11443 || map_kind == GOMP_MAP_TO_PSET
11444 || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
acf0174b
JJ
11445 gimplify_assign (avar, var, &ilist);
11446 avar = build_fold_addr_expr (avar);
11447 gimplify_assign (x, avar, &ilist);
41dbbb37
TS
11448 if ((GOMP_MAP_COPY_FROM_P (map_kind)
11449 || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
acf0174b
JJ
11450 && !TYPE_READONLY (TREE_TYPE (var)))
11451 {
11452 x = build_sender_ref (ovar, ctx);
11453 x = build_simple_mem_ref (x);
11454 gimplify_assign (var, x, &olist);
11455 }
11456 }
11457 else
11458 {
11459 var = build_fold_addr_expr (var);
11460 gimplify_assign (x, var, &ilist);
11461 }
11462 }
11463 tree s = OMP_CLAUSE_SIZE (c);
11464 if (s == NULL_TREE)
11465 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
11466 s = fold_convert (size_type_node, s);
11467 tree purpose = size_int (map_idx++);
11468 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
11469 if (TREE_CODE (s) != INTEGER_CST)
11470 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
11471
41dbbb37 11472 unsigned HOST_WIDE_INT tkind;
acf0174b
JJ
11473 switch (OMP_CLAUSE_CODE (c))
11474 {
11475 case OMP_CLAUSE_MAP:
11476 tkind = OMP_CLAUSE_MAP_KIND (c);
11477 break;
11478 case OMP_CLAUSE_TO:
41dbbb37 11479 tkind = GOMP_MAP_TO;
acf0174b
JJ
11480 break;
11481 case OMP_CLAUSE_FROM:
41dbbb37 11482 tkind = GOMP_MAP_FROM;
acf0174b
JJ
11483 break;
11484 default:
11485 gcc_unreachable ();
11486 }
41dbbb37
TS
11487 gcc_checking_assert (tkind
11488 < (HOST_WIDE_INT_C (1U) << talign_shift));
acf0174b 11489 talign = ceil_log2 (talign);
41dbbb37
TS
11490 tkind |= talign << talign_shift;
11491 gcc_checking_assert (tkind
11492 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
acf0174b 11493 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
41dbbb37 11494 build_int_cstu (tkind_type, tkind));
acf0174b
JJ
11495 if (nc && nc != c)
11496 c = nc;
11497 }
11498
11499 gcc_assert (map_idx == map_cnt);
11500
11501 DECL_INITIAL (TREE_VEC_ELT (t, 1))
11502 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)), vsize);
11503 DECL_INITIAL (TREE_VEC_ELT (t, 2))
11504 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 2)), vkind);
11505 if (!TREE_STATIC (TREE_VEC_ELT (t, 1)))
11506 {
11507 gimple_seq initlist = NULL;
11508 force_gimple_operand (build1 (DECL_EXPR, void_type_node,
11509 TREE_VEC_ELT (t, 1)),
11510 &initlist, true, NULL_TREE);
11511 gimple_seq_add_seq (&ilist, initlist);
bae729a2
TS
11512
11513 tree clobber = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)),
11514 NULL);
11515 TREE_THIS_VOLATILE (clobber) = 1;
11516 gimple_seq_add_stmt (&olist,
11517 gimple_build_assign (TREE_VEC_ELT (t, 1),
11518 clobber));
acf0174b
JJ
11519 }
11520
11521 tree clobber = build_constructor (ctx->record_type, NULL);
11522 TREE_THIS_VOLATILE (clobber) = 1;
11523 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
11524 clobber));
11525 }
11526
11527 /* Once all the expansions are done, sequence all the different
11528 fragments inside gimple_omp_body. */
11529
11530 new_body = NULL;
11531
41dbbb37
TS
11532 if (offloaded
11533 && ctx->record_type)
acf0174b
JJ
11534 {
11535 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
11536 /* fixup_child_record_type might have changed receiver_decl's type. */
11537 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
11538 gimple_seq_add_stmt (&new_body,
11539 gimple_build_assign (ctx->receiver_decl, t));
11540 }
11541
41dbbb37 11542 if (offloaded)
acf0174b
JJ
11543 {
11544 gimple_seq_add_seq (&new_body, tgt_body);
11545 new_body = maybe_catch_exception (new_body);
11546 }
41dbbb37 11547 else if (data_region)
acf0174b 11548 new_body = tgt_body;
41dbbb37 11549 if (offloaded || data_region)
acf0174b
JJ
11550 {
11551 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
11552 gimple_omp_set_body (stmt, new_body);
11553 }
11554
11555 bind = gimple_build_bind (NULL, NULL,
11556 tgt_bind ? gimple_bind_block (tgt_bind)
11557 : NULL_TREE);
726a989a 11558 gsi_replace (gsi_p, bind, true);
41dbbb37 11559 gimple_bind_add_seq (bind, irlist);
355a7673
MM
11560 gimple_bind_add_seq (bind, ilist);
11561 gimple_bind_add_stmt (bind, stmt);
11562 gimple_bind_add_seq (bind, olist);
41dbbb37 11563 gimple_bind_add_seq (bind, orlist);
50674e96 11564
726a989a 11565 pop_gimplify_context (NULL);
50674e96
DN
11566}
11567
acf0174b
JJ
11568/* Expand code for an OpenMP teams directive. */
11569
11570static void
11571lower_omp_teams (gimple_stmt_iterator *gsi_p, omp_context *ctx)
11572{
538dd0b7 11573 gomp_teams *teams_stmt = as_a <gomp_teams *> (gsi_stmt (*gsi_p));
45852dcc 11574 push_gimplify_context ();
acf0174b
JJ
11575
11576 tree block = make_node (BLOCK);
538dd0b7 11577 gbind *bind = gimple_build_bind (NULL, NULL, block);
acf0174b
JJ
11578 gsi_replace (gsi_p, bind, true);
11579 gimple_seq bind_body = NULL;
11580 gimple_seq dlist = NULL;
11581 gimple_seq olist = NULL;
11582
11583 tree num_teams = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
11584 OMP_CLAUSE_NUM_TEAMS);
11585 if (num_teams == NULL_TREE)
11586 num_teams = build_int_cst (unsigned_type_node, 0);
11587 else
11588 {
11589 num_teams = OMP_CLAUSE_NUM_TEAMS_EXPR (num_teams);
11590 num_teams = fold_convert (unsigned_type_node, num_teams);
11591 gimplify_expr (&num_teams, &bind_body, NULL, is_gimple_val, fb_rvalue);
11592 }
11593 tree thread_limit = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
11594 OMP_CLAUSE_THREAD_LIMIT);
11595 if (thread_limit == NULL_TREE)
11596 thread_limit = build_int_cst (unsigned_type_node, 0);
11597 else
11598 {
11599 thread_limit = OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit);
11600 thread_limit = fold_convert (unsigned_type_node, thread_limit);
11601 gimplify_expr (&thread_limit, &bind_body, NULL, is_gimple_val,
11602 fb_rvalue);
11603 }
11604
11605 lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt),
11606 &bind_body, &dlist, ctx, NULL);
11607 lower_omp (gimple_omp_body_ptr (teams_stmt), ctx);
11608 lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt), &olist, ctx);
11609 gimple_seq_add_stmt (&bind_body, teams_stmt);
11610
11611 location_t loc = gimple_location (teams_stmt);
11612 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TEAMS);
11613 gimple call = gimple_build_call (decl, 2, num_teams, thread_limit);
11614 gimple_set_location (call, loc);
11615 gimple_seq_add_stmt (&bind_body, call);
11616
11617 gimple_seq_add_seq (&bind_body, gimple_omp_body (teams_stmt));
11618 gimple_omp_set_body (teams_stmt, NULL);
11619 gimple_seq_add_seq (&bind_body, olist);
11620 gimple_seq_add_seq (&bind_body, dlist);
11621 gimple_seq_add_stmt (&bind_body, gimple_build_omp_return (true));
11622 gimple_bind_set_body (bind, bind_body);
11623
11624 pop_gimplify_context (bind);
11625
11626 gimple_bind_append_vars (bind, ctx->block_vars);
11627 BLOCK_VARS (block) = ctx->block_vars;
11628 if (BLOCK_VARS (block))
11629 TREE_USED (block) = 1;
11630}
11631
11632
d0fb20be 11633/* Callback for lower_omp_1. Return non-NULL if *tp needs to be
726a989a 11634 regimplified. If DATA is non-NULL, lower_omp_1 is outside
41dbbb37 11635 of OMP context, but with task_shared_vars set. */
75a4c3c1
AP
11636
11637static tree
726a989a
RB
11638lower_omp_regimplify_p (tree *tp, int *walk_subtrees,
11639 void *data)
75a4c3c1 11640{
d0fb20be 11641 tree t = *tp;
75a4c3c1 11642
d0fb20be 11643 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
726a989a 11644 if (TREE_CODE (t) == VAR_DECL && data == NULL && DECL_HAS_VALUE_EXPR_P (t))
b826efd9
JJ
11645 return t;
11646
11647 if (task_shared_vars
11648 && DECL_P (t)
11649 && bitmap_bit_p (task_shared_vars, DECL_UID (t)))
d0fb20be 11650 return t;
75a4c3c1 11651
d0fb20be
JJ
11652 /* If a global variable has been privatized, TREE_CONSTANT on
11653 ADDR_EXPR might be wrong. */
726a989a 11654 if (data == NULL && TREE_CODE (t) == ADDR_EXPR)
d0fb20be 11655 recompute_tree_invariant_for_addr_expr (t);
75a4c3c1 11656
d0fb20be
JJ
11657 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
11658 return NULL_TREE;
75a4c3c1 11659}
50674e96 11660
d0fb20be 11661static void
726a989a 11662lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
953ff289 11663{
726a989a
RB
11664 gimple stmt = gsi_stmt (*gsi_p);
11665 struct walk_stmt_info wi;
538dd0b7 11666 gcall *call_stmt;
953ff289 11667
726a989a
RB
11668 if (gimple_has_location (stmt))
11669 input_location = gimple_location (stmt);
d0fb20be 11670
726a989a
RB
11671 if (task_shared_vars)
11672 memset (&wi, '\0', sizeof (wi));
d0fb20be 11673
50674e96 11674 /* If we have issued syntax errors, avoid doing any heavy lifting.
41dbbb37 11675 Just replace the OMP directives with a NOP to avoid
50674e96 11676 confusing RTL expansion. */
1da2ed5f 11677 if (seen_error () && is_gimple_omp (stmt))
50674e96 11678 {
726a989a 11679 gsi_replace (gsi_p, gimple_build_nop (), true);
d0fb20be 11680 return;
50674e96
DN
11681 }
11682
726a989a 11683 switch (gimple_code (stmt))
953ff289 11684 {
726a989a 11685 case GIMPLE_COND:
538dd0b7
DM
11686 {
11687 gcond *cond_stmt = as_a <gcond *> (stmt);
11688 if ((ctx || task_shared_vars)
11689 && (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
11690 lower_omp_regimplify_p,
11691 ctx ? NULL : &wi, NULL)
11692 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
11693 lower_omp_regimplify_p,
11694 ctx ? NULL : &wi, NULL)))
11695 gimple_regimplify_operands (cond_stmt, gsi_p);
11696 }
d0fb20be 11697 break;
726a989a 11698 case GIMPLE_CATCH:
538dd0b7 11699 lower_omp (gimple_catch_handler_ptr (as_a <gcatch *> (stmt)), ctx);
d0fb20be 11700 break;
726a989a 11701 case GIMPLE_EH_FILTER:
355a7673 11702 lower_omp (gimple_eh_filter_failure_ptr (stmt), ctx);
d0fb20be 11703 break;
726a989a 11704 case GIMPLE_TRY:
355a7673
MM
11705 lower_omp (gimple_try_eval_ptr (stmt), ctx);
11706 lower_omp (gimple_try_cleanup_ptr (stmt), ctx);
d0fb20be 11707 break;
d88513ea 11708 case GIMPLE_TRANSACTION:
538dd0b7
DM
11709 lower_omp (gimple_transaction_body_ptr (
11710 as_a <gtransaction *> (stmt)),
11711 ctx);
d88513ea 11712 break;
726a989a 11713 case GIMPLE_BIND:
538dd0b7 11714 lower_omp (gimple_bind_body_ptr (as_a <gbind *> (stmt)), ctx);
d0fb20be 11715 break;
726a989a
RB
11716 case GIMPLE_OMP_PARALLEL:
11717 case GIMPLE_OMP_TASK:
11718 ctx = maybe_lookup_ctx (stmt);
acf0174b
JJ
11719 gcc_assert (ctx);
11720 if (ctx->cancellable)
11721 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
726a989a 11722 lower_omp_taskreg (gsi_p, ctx);
d0fb20be 11723 break;
726a989a
RB
11724 case GIMPLE_OMP_FOR:
11725 ctx = maybe_lookup_ctx (stmt);
953ff289 11726 gcc_assert (ctx);
acf0174b
JJ
11727 if (ctx->cancellable)
11728 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
726a989a 11729 lower_omp_for (gsi_p, ctx);
953ff289 11730 break;
726a989a
RB
11731 case GIMPLE_OMP_SECTIONS:
11732 ctx = maybe_lookup_ctx (stmt);
953ff289 11733 gcc_assert (ctx);
acf0174b
JJ
11734 if (ctx->cancellable)
11735 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
726a989a 11736 lower_omp_sections (gsi_p, ctx);
953ff289 11737 break;
726a989a
RB
11738 case GIMPLE_OMP_SINGLE:
11739 ctx = maybe_lookup_ctx (stmt);
953ff289 11740 gcc_assert (ctx);
726a989a 11741 lower_omp_single (gsi_p, ctx);
953ff289 11742 break;
726a989a
RB
11743 case GIMPLE_OMP_MASTER:
11744 ctx = maybe_lookup_ctx (stmt);
953ff289 11745 gcc_assert (ctx);
726a989a 11746 lower_omp_master (gsi_p, ctx);
953ff289 11747 break;
acf0174b
JJ
11748 case GIMPLE_OMP_TASKGROUP:
11749 ctx = maybe_lookup_ctx (stmt);
11750 gcc_assert (ctx);
11751 lower_omp_taskgroup (gsi_p, ctx);
11752 break;
726a989a
RB
11753 case GIMPLE_OMP_ORDERED:
11754 ctx = maybe_lookup_ctx (stmt);
953ff289 11755 gcc_assert (ctx);
726a989a 11756 lower_omp_ordered (gsi_p, ctx);
953ff289 11757 break;
726a989a
RB
11758 case GIMPLE_OMP_CRITICAL:
11759 ctx = maybe_lookup_ctx (stmt);
953ff289 11760 gcc_assert (ctx);
726a989a
RB
11761 lower_omp_critical (gsi_p, ctx);
11762 break;
11763 case GIMPLE_OMP_ATOMIC_LOAD:
11764 if ((ctx || task_shared_vars)
538dd0b7
DM
11765 && walk_tree (gimple_omp_atomic_load_rhs_ptr (
11766 as_a <gomp_atomic_load *> (stmt)),
726a989a
RB
11767 lower_omp_regimplify_p, ctx ? NULL : &wi, NULL))
11768 gimple_regimplify_operands (stmt, gsi_p);
953ff289 11769 break;
acf0174b
JJ
11770 case GIMPLE_OMP_TARGET:
11771 ctx = maybe_lookup_ctx (stmt);
11772 gcc_assert (ctx);
11773 lower_omp_target (gsi_p, ctx);
11774 break;
11775 case GIMPLE_OMP_TEAMS:
11776 ctx = maybe_lookup_ctx (stmt);
11777 gcc_assert (ctx);
11778 lower_omp_teams (gsi_p, ctx);
11779 break;
11780 case GIMPLE_CALL:
11781 tree fndecl;
538dd0b7
DM
11782 call_stmt = as_a <gcall *> (stmt);
11783 fndecl = gimple_call_fndecl (call_stmt);
acf0174b
JJ
11784 if (fndecl
11785 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
11786 switch (DECL_FUNCTION_CODE (fndecl))
11787 {
11788 case BUILT_IN_GOMP_BARRIER:
11789 if (ctx == NULL)
11790 break;
11791 /* FALLTHRU */
11792 case BUILT_IN_GOMP_CANCEL:
11793 case BUILT_IN_GOMP_CANCELLATION_POINT:
11794 omp_context *cctx;
11795 cctx = ctx;
11796 if (gimple_code (cctx->stmt) == GIMPLE_OMP_SECTION)
11797 cctx = cctx->outer;
538dd0b7 11798 gcc_assert (gimple_call_lhs (call_stmt) == NULL_TREE);
acf0174b
JJ
11799 if (!cctx->cancellable)
11800 {
11801 if (DECL_FUNCTION_CODE (fndecl)
11802 == BUILT_IN_GOMP_CANCELLATION_POINT)
11803 {
11804 stmt = gimple_build_nop ();
11805 gsi_replace (gsi_p, stmt, false);
11806 }
11807 break;
11808 }
acf0174b
JJ
11809 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
11810 {
11811 fndecl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL);
538dd0b7
DM
11812 gimple_call_set_fndecl (call_stmt, fndecl);
11813 gimple_call_set_fntype (call_stmt, TREE_TYPE (fndecl));
acf0174b 11814 }
dd2fc525 11815 tree lhs;
b731b390 11816 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (fndecl)));
538dd0b7 11817 gimple_call_set_lhs (call_stmt, lhs);
acf0174b
JJ
11818 tree fallthru_label;
11819 fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
11820 gimple g;
11821 g = gimple_build_label (fallthru_label);
11822 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
dd2fc525
JJ
11823 g = gimple_build_cond (NE_EXPR, lhs,
11824 fold_convert (TREE_TYPE (lhs),
11825 boolean_false_node),
acf0174b
JJ
11826 cctx->cancel_label, fallthru_label);
11827 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
11828 break;
11829 default:
11830 break;
11831 }
11832 /* FALLTHRU */
d0fb20be 11833 default:
a68ab351 11834 if ((ctx || task_shared_vars)
726a989a
RB
11835 && walk_gimple_op (stmt, lower_omp_regimplify_p,
11836 ctx ? NULL : &wi))
47519a14
JJ
11837 {
11838 /* Just remove clobbers, this should happen only if we have
11839 "privatized" local addressable variables in SIMD regions,
11840 the clobber isn't needed in that case and gimplifying address
11841 of the ARRAY_REF into a pointer and creating MEM_REF based
11842 clobber would create worse code than we get with the clobber
11843 dropped. */
11844 if (gimple_clobber_p (stmt))
11845 {
11846 gsi_replace (gsi_p, gimple_build_nop (), true);
11847 break;
11848 }
11849 gimple_regimplify_operands (stmt, gsi_p);
11850 }
953ff289 11851 break;
953ff289 11852 }
953ff289
DN
11853}
11854
11855static void
355a7673 11856lower_omp (gimple_seq *body, omp_context *ctx)
953ff289 11857{
b357f682 11858 location_t saved_location = input_location;
355a7673
MM
11859 gimple_stmt_iterator gsi;
11860 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
726a989a 11861 lower_omp_1 (&gsi, ctx);
41dbbb37
TS
11862 /* During gimplification, we haven't folded statments inside offloading
11863 regions (gimplify.c:maybe_fold_stmt); do that now. */
acf0174b
JJ
11864 if (target_nesting_level)
11865 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
11866 fold_stmt (&gsi);
b357f682 11867 input_location = saved_location;
953ff289
DN
11868}
11869\f
11870/* Main entry point. */
11871
c2924966 11872static unsigned int
953ff289
DN
11873execute_lower_omp (void)
11874{
726a989a 11875 gimple_seq body;
5771c391
JJ
11876 int i;
11877 omp_context *ctx;
726a989a 11878
535b544a 11879 /* This pass always runs, to provide PROP_gimple_lomp.
41dbbb37
TS
11880 But often, there is nothing to do. */
11881 if (flag_cilkplus == 0 && flag_openacc == 0 && flag_openmp == 0
11882 && flag_openmp_simd == 0)
535b544a
SB
11883 return 0;
11884
953ff289
DN
11885 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
11886 delete_omp_context);
11887
726a989a 11888 body = gimple_body (current_function_decl);
26127932 11889 scan_omp (&body, NULL);
a68ab351 11890 gcc_assert (taskreg_nesting_level == 0);
5771c391
JJ
11891 FOR_EACH_VEC_ELT (taskreg_contexts, i, ctx)
11892 finish_taskreg_scan (ctx);
11893 taskreg_contexts.release ();
953ff289
DN
11894
11895 if (all_contexts->root)
a68ab351
JJ
11896 {
11897 if (task_shared_vars)
45852dcc 11898 push_gimplify_context ();
355a7673 11899 lower_omp (&body, NULL);
a68ab351
JJ
11900 if (task_shared_vars)
11901 pop_gimplify_context (NULL);
11902 }
953ff289 11903
50674e96
DN
11904 if (all_contexts)
11905 {
11906 splay_tree_delete (all_contexts);
11907 all_contexts = NULL;
11908 }
a68ab351 11909 BITMAP_FREE (task_shared_vars);
c2924966 11910 return 0;
953ff289
DN
11911}
11912
27a4cd48
DM
11913namespace {
11914
11915const pass_data pass_data_lower_omp =
11916{
11917 GIMPLE_PASS, /* type */
11918 "omplower", /* name */
11919 OPTGROUP_NONE, /* optinfo_flags */
27a4cd48
DM
11920 TV_NONE, /* tv_id */
11921 PROP_gimple_any, /* properties_required */
11922 PROP_gimple_lomp, /* properties_provided */
11923 0, /* properties_destroyed */
11924 0, /* todo_flags_start */
11925 0, /* todo_flags_finish */
953ff289 11926};
27a4cd48
DM
11927
11928class pass_lower_omp : public gimple_opt_pass
11929{
11930public:
c3284718
RS
11931 pass_lower_omp (gcc::context *ctxt)
11932 : gimple_opt_pass (pass_data_lower_omp, ctxt)
27a4cd48
DM
11933 {}
11934
11935 /* opt_pass methods: */
be55bfe6 11936 virtual unsigned int execute (function *) { return execute_lower_omp (); }
27a4cd48
DM
11937
11938}; // class pass_lower_omp
11939
11940} // anon namespace
11941
11942gimple_opt_pass *
11943make_pass_lower_omp (gcc::context *ctxt)
11944{
11945 return new pass_lower_omp (ctxt);
11946}
953ff289 11947\f
41dbbb37 11948/* The following is a utility to diagnose structured block violations.
777f7f9a
RH
11949 It is not part of the "omplower" pass, as that's invoked too late. It
11950 should be invoked by the respective front ends after gimplification. */
953ff289
DN
11951
11952static splay_tree all_labels;
11953
11954/* Check for mismatched contexts and generate an error if needed. Return
11955 true if an error is detected. */
11956
11957static bool
726a989a
RB
11958diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
11959 gimple branch_ctx, gimple label_ctx)
953ff289 11960{
41dbbb37
TS
11961 gcc_checking_assert (!branch_ctx || is_gimple_omp (branch_ctx));
11962 gcc_checking_assert (!label_ctx || is_gimple_omp (label_ctx));
11963
726a989a 11964 if (label_ctx == branch_ctx)
953ff289
DN
11965 return false;
11966
41dbbb37
TS
11967 const char* kind = NULL;
11968
11969 if (flag_cilkplus)
11970 {
11971 if ((branch_ctx
11972 && gimple_code (branch_ctx) == GIMPLE_OMP_FOR
11973 && gimple_omp_for_kind (branch_ctx) == GF_OMP_FOR_KIND_CILKSIMD)
11974 || (label_ctx
11975 && gimple_code (label_ctx) == GIMPLE_OMP_FOR
11976 && gimple_omp_for_kind (label_ctx) == GF_OMP_FOR_KIND_CILKSIMD))
11977 kind = "Cilk Plus";
11978 }
11979 if (flag_openacc)
11980 {
11981 if ((branch_ctx && is_gimple_omp_oacc (branch_ctx))
11982 || (label_ctx && is_gimple_omp_oacc (label_ctx)))
11983 {
11984 gcc_checking_assert (kind == NULL);
11985 kind = "OpenACC";
11986 }
11987 }
11988 if (kind == NULL)
11989 {
11990 gcc_checking_assert (flag_openmp);
11991 kind = "OpenMP";
11992 }
b8698a0f 11993
726a989a
RB
11994 /*
11995 Previously we kept track of the label's entire context in diagnose_sb_[12]
11996 so we could traverse it and issue a correct "exit" or "enter" error
11997 message upon a structured block violation.
11998
11999 We built the context by building a list with tree_cons'ing, but there is
12000 no easy counterpart in gimple tuples. It seems like far too much work
12001 for issuing exit/enter error messages. If someone really misses the
12002 distinct error message... patches welcome.
12003 */
b8698a0f 12004
726a989a 12005#if 0
953ff289 12006 /* Try to avoid confusing the user by producing and error message
fa10beec 12007 with correct "exit" or "enter" verbiage. We prefer "exit"
953ff289
DN
12008 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
12009 if (branch_ctx == NULL)
12010 exit_p = false;
12011 else
12012 {
12013 while (label_ctx)
12014 {
12015 if (TREE_VALUE (label_ctx) == branch_ctx)
12016 {
12017 exit_p = false;
12018 break;
12019 }
12020 label_ctx = TREE_CHAIN (label_ctx);
12021 }
12022 }
12023
12024 if (exit_p)
41dbbb37 12025 error ("invalid exit from %s structured block", kind);
953ff289 12026 else
41dbbb37 12027 error ("invalid entry to %s structured block", kind);
726a989a 12028#endif
953ff289 12029
726a989a
RB
12030 /* If it's obvious we have an invalid entry, be specific about the error. */
12031 if (branch_ctx == NULL)
41dbbb37 12032 error ("invalid entry to %s structured block", kind);
726a989a 12033 else
c02065fc
AH
12034 {
12035 /* Otherwise, be vague and lazy, but efficient. */
41dbbb37 12036 error ("invalid branch to/from %s structured block", kind);
c02065fc 12037 }
726a989a
RB
12038
12039 gsi_replace (gsi_p, gimple_build_nop (), false);
953ff289
DN
12040 return true;
12041}
12042
41dbbb37 12043/* Pass 1: Create a minimal tree of structured blocks, and record
726a989a 12044 where each label is found. */
953ff289
DN
12045
12046static tree
726a989a
RB
12047diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
12048 struct walk_stmt_info *wi)
953ff289 12049{
726a989a
RB
12050 gimple context = (gimple) wi->info;
12051 gimple inner_context;
12052 gimple stmt = gsi_stmt (*gsi_p);
953ff289 12053
726a989a
RB
12054 *handled_ops_p = true;
12055
41dbbb37 12056 switch (gimple_code (stmt))
953ff289 12057 {
726a989a 12058 WALK_SUBSTMTS;
b8698a0f 12059
726a989a
RB
12060 case GIMPLE_OMP_PARALLEL:
12061 case GIMPLE_OMP_TASK:
12062 case GIMPLE_OMP_SECTIONS:
12063 case GIMPLE_OMP_SINGLE:
12064 case GIMPLE_OMP_SECTION:
12065 case GIMPLE_OMP_MASTER:
12066 case GIMPLE_OMP_ORDERED:
12067 case GIMPLE_OMP_CRITICAL:
acf0174b
JJ
12068 case GIMPLE_OMP_TARGET:
12069 case GIMPLE_OMP_TEAMS:
12070 case GIMPLE_OMP_TASKGROUP:
726a989a
RB
12071 /* The minimal context here is just the current OMP construct. */
12072 inner_context = stmt;
953ff289 12073 wi->info = inner_context;
726a989a 12074 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
953ff289
DN
12075 wi->info = context;
12076 break;
12077
726a989a
RB
12078 case GIMPLE_OMP_FOR:
12079 inner_context = stmt;
953ff289 12080 wi->info = inner_context;
726a989a
RB
12081 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
12082 walk them. */
12083 walk_gimple_seq (gimple_omp_for_pre_body (stmt),
12084 diagnose_sb_1, NULL, wi);
12085 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
953ff289
DN
12086 wi->info = context;
12087 break;
12088
726a989a 12089 case GIMPLE_LABEL:
538dd0b7
DM
12090 splay_tree_insert (all_labels,
12091 (splay_tree_key) gimple_label_label (
12092 as_a <glabel *> (stmt)),
953ff289
DN
12093 (splay_tree_value) context);
12094 break;
12095
12096 default:
12097 break;
12098 }
12099
12100 return NULL_TREE;
12101}
12102
12103/* Pass 2: Check each branch and see if its context differs from that of
12104 the destination label's context. */
12105
12106static tree
726a989a
RB
12107diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
12108 struct walk_stmt_info *wi)
953ff289 12109{
726a989a 12110 gimple context = (gimple) wi->info;
953ff289 12111 splay_tree_node n;
726a989a 12112 gimple stmt = gsi_stmt (*gsi_p);
953ff289 12113
726a989a
RB
12114 *handled_ops_p = true;
12115
12116 switch (gimple_code (stmt))
953ff289 12117 {
726a989a
RB
12118 WALK_SUBSTMTS;
12119
12120 case GIMPLE_OMP_PARALLEL:
12121 case GIMPLE_OMP_TASK:
12122 case GIMPLE_OMP_SECTIONS:
12123 case GIMPLE_OMP_SINGLE:
12124 case GIMPLE_OMP_SECTION:
12125 case GIMPLE_OMP_MASTER:
12126 case GIMPLE_OMP_ORDERED:
12127 case GIMPLE_OMP_CRITICAL:
acf0174b
JJ
12128 case GIMPLE_OMP_TARGET:
12129 case GIMPLE_OMP_TEAMS:
12130 case GIMPLE_OMP_TASKGROUP:
726a989a 12131 wi->info = stmt;
355a7673 12132 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
953ff289
DN
12133 wi->info = context;
12134 break;
12135
726a989a
RB
12136 case GIMPLE_OMP_FOR:
12137 wi->info = stmt;
12138 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
12139 walk them. */
355a7673
MM
12140 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt),
12141 diagnose_sb_2, NULL, wi);
12142 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
953ff289
DN
12143 wi->info = context;
12144 break;
12145
ca50f84a
L
12146 case GIMPLE_COND:
12147 {
538dd0b7
DM
12148 gcond *cond_stmt = as_a <gcond *> (stmt);
12149 tree lab = gimple_cond_true_label (cond_stmt);
ca50f84a
L
12150 if (lab)
12151 {
12152 n = splay_tree_lookup (all_labels,
12153 (splay_tree_key) lab);
12154 diagnose_sb_0 (gsi_p, context,
12155 n ? (gimple) n->value : NULL);
12156 }
538dd0b7 12157 lab = gimple_cond_false_label (cond_stmt);
ca50f84a
L
12158 if (lab)
12159 {
12160 n = splay_tree_lookup (all_labels,
12161 (splay_tree_key) lab);
12162 diagnose_sb_0 (gsi_p, context,
12163 n ? (gimple) n->value : NULL);
12164 }
12165 }
12166 break;
12167
726a989a 12168 case GIMPLE_GOTO:
953ff289 12169 {
726a989a 12170 tree lab = gimple_goto_dest (stmt);
953ff289
DN
12171 if (TREE_CODE (lab) != LABEL_DECL)
12172 break;
12173
12174 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
726a989a 12175 diagnose_sb_0 (gsi_p, context, n ? (gimple) n->value : NULL);
953ff289
DN
12176 }
12177 break;
12178
726a989a 12179 case GIMPLE_SWITCH:
953ff289 12180 {
538dd0b7 12181 gswitch *switch_stmt = as_a <gswitch *> (stmt);
726a989a 12182 unsigned int i;
538dd0b7 12183 for (i = 0; i < gimple_switch_num_labels (switch_stmt); ++i)
953ff289 12184 {
538dd0b7 12185 tree lab = CASE_LABEL (gimple_switch_label (switch_stmt, i));
953ff289 12186 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
726a989a 12187 if (n && diagnose_sb_0 (gsi_p, context, (gimple) n->value))
953ff289
DN
12188 break;
12189 }
12190 }
12191 break;
12192
726a989a
RB
12193 case GIMPLE_RETURN:
12194 diagnose_sb_0 (gsi_p, context, NULL);
953ff289
DN
12195 break;
12196
12197 default:
12198 break;
12199 }
12200
12201 return NULL_TREE;
12202}
12203
41dbbb37
TS
12204/* Called from tree-cfg.c::make_edges to create cfg edges for all relevant
12205 GIMPLE_* codes. */
0645c1a2 12206bool
09b22f48
JJ
12207make_gimple_omp_edges (basic_block bb, struct omp_region **region,
12208 int *region_idx)
0645c1a2
AM
12209{
12210 gimple last = last_stmt (bb);
12211 enum gimple_code code = gimple_code (last);
12212 struct omp_region *cur_region = *region;
12213 bool fallthru = false;
12214
12215 switch (code)
12216 {
12217 case GIMPLE_OMP_PARALLEL:
12218 case GIMPLE_OMP_TASK:
12219 case GIMPLE_OMP_FOR:
12220 case GIMPLE_OMP_SINGLE:
12221 case GIMPLE_OMP_TEAMS:
12222 case GIMPLE_OMP_MASTER:
12223 case GIMPLE_OMP_TASKGROUP:
12224 case GIMPLE_OMP_ORDERED:
12225 case GIMPLE_OMP_CRITICAL:
12226 case GIMPLE_OMP_SECTION:
12227 cur_region = new_omp_region (bb, code, cur_region);
12228 fallthru = true;
12229 break;
12230
12231 case GIMPLE_OMP_TARGET:
12232 cur_region = new_omp_region (bb, code, cur_region);
12233 fallthru = true;
41dbbb37
TS
12234 switch (gimple_omp_target_kind (last))
12235 {
12236 case GF_OMP_TARGET_KIND_REGION:
12237 case GF_OMP_TARGET_KIND_DATA:
12238 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
12239 case GF_OMP_TARGET_KIND_OACC_KERNELS:
12240 case GF_OMP_TARGET_KIND_OACC_DATA:
12241 break;
12242 case GF_OMP_TARGET_KIND_UPDATE:
12243 case GF_OMP_TARGET_KIND_OACC_UPDATE:
12244 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
12245 cur_region = cur_region->outer;
12246 break;
12247 default:
12248 gcc_unreachable ();
12249 }
0645c1a2
AM
12250 break;
12251
12252 case GIMPLE_OMP_SECTIONS:
12253 cur_region = new_omp_region (bb, code, cur_region);
12254 fallthru = true;
12255 break;
12256
12257 case GIMPLE_OMP_SECTIONS_SWITCH:
12258 fallthru = false;
12259 break;
12260
12261 case GIMPLE_OMP_ATOMIC_LOAD:
12262 case GIMPLE_OMP_ATOMIC_STORE:
12263 fallthru = true;
12264 break;
12265
12266 case GIMPLE_OMP_RETURN:
12267 /* In the case of a GIMPLE_OMP_SECTION, the edge will go
12268 somewhere other than the next block. This will be
12269 created later. */
12270 cur_region->exit = bb;
12271 fallthru = cur_region->type != GIMPLE_OMP_SECTION;
12272 cur_region = cur_region->outer;
12273 break;
12274
12275 case GIMPLE_OMP_CONTINUE:
12276 cur_region->cont = bb;
12277 switch (cur_region->type)
12278 {
12279 case GIMPLE_OMP_FOR:
12280 /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
12281 succs edges as abnormal to prevent splitting
12282 them. */
12283 single_succ_edge (cur_region->entry)->flags |= EDGE_ABNORMAL;
12284 /* Make the loopback edge. */
12285 make_edge (bb, single_succ (cur_region->entry),
12286 EDGE_ABNORMAL);
12287
12288 /* Create an edge from GIMPLE_OMP_FOR to exit, which
12289 corresponds to the case that the body of the loop
12290 is not executed at all. */
12291 make_edge (cur_region->entry, bb->next_bb, EDGE_ABNORMAL);
12292 make_edge (bb, bb->next_bb, EDGE_FALLTHRU | EDGE_ABNORMAL);
12293 fallthru = false;
12294 break;
12295
12296 case GIMPLE_OMP_SECTIONS:
12297 /* Wire up the edges into and out of the nested sections. */
12298 {
12299 basic_block switch_bb = single_succ (cur_region->entry);
12300
12301 struct omp_region *i;
12302 for (i = cur_region->inner; i ; i = i->next)
12303 {
12304 gcc_assert (i->type == GIMPLE_OMP_SECTION);
12305 make_edge (switch_bb, i->entry, 0);
12306 make_edge (i->exit, bb, EDGE_FALLTHRU);
12307 }
12308
12309 /* Make the loopback edge to the block with
12310 GIMPLE_OMP_SECTIONS_SWITCH. */
12311 make_edge (bb, switch_bb, 0);
12312
12313 /* Make the edge from the switch to exit. */
12314 make_edge (switch_bb, bb->next_bb, 0);
12315 fallthru = false;
12316 }
12317 break;
12318
12319 default:
12320 gcc_unreachable ();
12321 }
12322 break;
12323
12324 default:
12325 gcc_unreachable ();
12326 }
12327
12328 if (*region != cur_region)
09b22f48
JJ
12329 {
12330 *region = cur_region;
12331 if (cur_region)
12332 *region_idx = cur_region->entry->index;
12333 else
12334 *region_idx = 0;
12335 }
0645c1a2
AM
12336
12337 return fallthru;
12338}
12339
a406865a
RG
12340static unsigned int
12341diagnose_omp_structured_block_errors (void)
953ff289 12342{
953ff289 12343 struct walk_stmt_info wi;
a406865a 12344 gimple_seq body = gimple_body (current_function_decl);
953ff289
DN
12345
12346 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
12347
12348 memset (&wi, 0, sizeof (wi));
726a989a 12349 walk_gimple_seq (body, diagnose_sb_1, NULL, &wi);
953ff289
DN
12350
12351 memset (&wi, 0, sizeof (wi));
953ff289 12352 wi.want_locations = true;
355a7673
MM
12353 walk_gimple_seq_mod (&body, diagnose_sb_2, NULL, &wi);
12354
12355 gimple_set_body (current_function_decl, body);
953ff289
DN
12356
12357 splay_tree_delete (all_labels);
12358 all_labels = NULL;
12359
a406865a 12360 return 0;
953ff289
DN
12361}
12362
27a4cd48
DM
12363namespace {
12364
12365const pass_data pass_data_diagnose_omp_blocks =
12366{
12367 GIMPLE_PASS, /* type */
12368 "*diagnose_omp_blocks", /* name */
12369 OPTGROUP_NONE, /* optinfo_flags */
27a4cd48
DM
12370 TV_NONE, /* tv_id */
12371 PROP_gimple_any, /* properties_required */
12372 0, /* properties_provided */
12373 0, /* properties_destroyed */
12374 0, /* todo_flags_start */
12375 0, /* todo_flags_finish */
a406865a
RG
12376};
12377
27a4cd48
DM
12378class pass_diagnose_omp_blocks : public gimple_opt_pass
12379{
12380public:
c3284718
RS
12381 pass_diagnose_omp_blocks (gcc::context *ctxt)
12382 : gimple_opt_pass (pass_data_diagnose_omp_blocks, ctxt)
27a4cd48
DM
12383 {}
12384
12385 /* opt_pass methods: */
41dbbb37
TS
12386 virtual bool gate (function *)
12387 {
12388 return flag_cilkplus || flag_openacc || flag_openmp;
12389 }
be55bfe6
TS
12390 virtual unsigned int execute (function *)
12391 {
12392 return diagnose_omp_structured_block_errors ();
12393 }
27a4cd48
DM
12394
12395}; // class pass_diagnose_omp_blocks
12396
12397} // anon namespace
12398
12399gimple_opt_pass *
12400make_pass_diagnose_omp_blocks (gcc::context *ctxt)
12401{
12402 return new pass_diagnose_omp_blocks (ctxt);
12403}
0136f8f0
AH
12404\f
12405/* SIMD clone supporting code. */
12406
12407/* Allocate a fresh `simd_clone' and return it. NARGS is the number
12408 of arguments to reserve space for. */
12409
12410static struct cgraph_simd_clone *
12411simd_clone_struct_alloc (int nargs)
12412{
12413 struct cgraph_simd_clone *clone_info;
12414 size_t len = (sizeof (struct cgraph_simd_clone)
12415 + nargs * sizeof (struct cgraph_simd_clone_arg));
12416 clone_info = (struct cgraph_simd_clone *)
b3bb0eb9 12417 ggc_internal_cleared_alloc (len);
0136f8f0
AH
12418 return clone_info;
12419}
12420
12421/* Make a copy of the `struct cgraph_simd_clone' in FROM to TO. */
12422
12423static inline void
12424simd_clone_struct_copy (struct cgraph_simd_clone *to,
12425 struct cgraph_simd_clone *from)
12426{
12427 memcpy (to, from, (sizeof (struct cgraph_simd_clone)
92d05580
JJ
12428 + ((from->nargs - from->inbranch)
12429 * sizeof (struct cgraph_simd_clone_arg))));
0136f8f0
AH
12430}
12431
12432/* Return vector of parameter types of function FNDECL. This uses
12433 TYPE_ARG_TYPES if available, otherwise falls back to types of
12434 DECL_ARGUMENTS types. */
12435
12436vec<tree>
12437simd_clone_vector_of_formal_parm_types (tree fndecl)
12438{
12439 if (TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
12440 return ipa_get_vector_of_formal_parm_types (TREE_TYPE (fndecl));
12441 vec<tree> args = ipa_get_vector_of_formal_parms (fndecl);
12442 unsigned int i;
12443 tree arg;
12444 FOR_EACH_VEC_ELT (args, i, arg)
12445 args[i] = TREE_TYPE (args[i]);
12446 return args;
12447}
12448
12449/* Given a simd function in NODE, extract the simd specific
12450 information from the OMP clauses passed in CLAUSES, and return
12451 the struct cgraph_simd_clone * if it should be cloned. *INBRANCH_SPECIFIED
12452 is set to TRUE if the `inbranch' or `notinbranch' clause specified,
12453 otherwise set to FALSE. */
12454
12455static struct cgraph_simd_clone *
12456simd_clone_clauses_extract (struct cgraph_node *node, tree clauses,
12457 bool *inbranch_specified)
12458{
12459 vec<tree> args = simd_clone_vector_of_formal_parm_types (node->decl);
12460 tree t;
12461 int n;
12462 *inbranch_specified = false;
12463
12464 n = args.length ();
12465 if (n > 0 && args.last () == void_type_node)
12466 n--;
12467
12468 /* To distinguish from an OpenMP simd clone, Cilk Plus functions to
12469 be cloned have a distinctive artificial label in addition to "omp
12470 declare simd". */
12471 bool cilk_clone
b72271b9 12472 = (flag_cilkplus
41958c28 12473 && lookup_attribute ("cilk simd function",
0136f8f0
AH
12474 DECL_ATTRIBUTES (node->decl)));
12475
12476 /* Allocate one more than needed just in case this is an in-branch
12477 clone which will require a mask argument. */
12478 struct cgraph_simd_clone *clone_info = simd_clone_struct_alloc (n + 1);
12479 clone_info->nargs = n;
12480 clone_info->cilk_elemental = cilk_clone;
12481
12482 if (!clauses)
12483 {
12484 args.release ();
12485 return clone_info;
12486 }
12487 clauses = TREE_VALUE (clauses);
12488 if (!clauses || TREE_CODE (clauses) != OMP_CLAUSE)
12489 return clone_info;
12490
12491 for (t = clauses; t; t = OMP_CLAUSE_CHAIN (t))
12492 {
12493 switch (OMP_CLAUSE_CODE (t))
12494 {
12495 case OMP_CLAUSE_INBRANCH:
12496 clone_info->inbranch = 1;
12497 *inbranch_specified = true;
12498 break;
12499 case OMP_CLAUSE_NOTINBRANCH:
12500 clone_info->inbranch = 0;
12501 *inbranch_specified = true;
12502 break;
12503 case OMP_CLAUSE_SIMDLEN:
12504 clone_info->simdlen
12505 = TREE_INT_CST_LOW (OMP_CLAUSE_SIMDLEN_EXPR (t));
12506 break;
12507 case OMP_CLAUSE_LINEAR:
12508 {
12509 tree decl = OMP_CLAUSE_DECL (t);
12510 tree step = OMP_CLAUSE_LINEAR_STEP (t);
12511 int argno = TREE_INT_CST_LOW (decl);
12512 if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (t))
12513 {
12514 clone_info->args[argno].arg_type
12515 = SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP;
12516 clone_info->args[argno].linear_step = tree_to_shwi (step);
12517 gcc_assert (clone_info->args[argno].linear_step >= 0
12518 && clone_info->args[argno].linear_step < n);
12519 }
12520 else
12521 {
12522 if (POINTER_TYPE_P (args[argno]))
12523 step = fold_convert (ssizetype, step);
12524 if (!tree_fits_shwi_p (step))
12525 {
12526 warning_at (OMP_CLAUSE_LOCATION (t), 0,
12527 "ignoring large linear step");
12528 args.release ();
12529 return NULL;
12530 }
12531 else if (integer_zerop (step))
12532 {
12533 warning_at (OMP_CLAUSE_LOCATION (t), 0,
12534 "ignoring zero linear step");
12535 args.release ();
12536 return NULL;
12537 }
12538 else
12539 {
12540 clone_info->args[argno].arg_type
12541 = SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP;
12542 clone_info->args[argno].linear_step = tree_to_shwi (step);
12543 }
12544 }
12545 break;
12546 }
12547 case OMP_CLAUSE_UNIFORM:
12548 {
12549 tree decl = OMP_CLAUSE_DECL (t);
12550 int argno = tree_to_uhwi (decl);
12551 clone_info->args[argno].arg_type
12552 = SIMD_CLONE_ARG_TYPE_UNIFORM;
12553 break;
12554 }
12555 case OMP_CLAUSE_ALIGNED:
12556 {
12557 tree decl = OMP_CLAUSE_DECL (t);
12558 int argno = tree_to_uhwi (decl);
12559 clone_info->args[argno].alignment
12560 = TREE_INT_CST_LOW (OMP_CLAUSE_ALIGNED_ALIGNMENT (t));
12561 break;
12562 }
12563 default:
12564 break;
12565 }
12566 }
12567 args.release ();
12568 return clone_info;
12569}
12570
12571/* Given a SIMD clone in NODE, calculate the characteristic data
12572 type and return the coresponding type. The characteristic data
12573 type is computed as described in the Intel Vector ABI. */
12574
12575static tree
12576simd_clone_compute_base_data_type (struct cgraph_node *node,
12577 struct cgraph_simd_clone *clone_info)
12578{
12579 tree type = integer_type_node;
12580 tree fndecl = node->decl;
12581
12582 /* a) For non-void function, the characteristic data type is the
12583 return type. */
12584 if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) != VOID_TYPE)
12585 type = TREE_TYPE (TREE_TYPE (fndecl));
12586
12587 /* b) If the function has any non-uniform, non-linear parameters,
12588 then the characteristic data type is the type of the first
12589 such parameter. */
12590 else
12591 {
12592 vec<tree> map = simd_clone_vector_of_formal_parm_types (fndecl);
12593 for (unsigned int i = 0; i < clone_info->nargs; ++i)
12594 if (clone_info->args[i].arg_type == SIMD_CLONE_ARG_TYPE_VECTOR)
12595 {
12596 type = map[i];
12597 break;
12598 }
12599 map.release ();
12600 }
12601
12602 /* c) If the characteristic data type determined by a) or b) above
12603 is struct, union, or class type which is pass-by-value (except
12604 for the type that maps to the built-in complex data type), the
12605 characteristic data type is int. */
12606 if (RECORD_OR_UNION_TYPE_P (type)
12607 && !aggregate_value_p (type, NULL)
12608 && TREE_CODE (type) != COMPLEX_TYPE)
12609 return integer_type_node;
12610
12611 /* d) If none of the above three classes is applicable, the
12612 characteristic data type is int. */
12613
12614 return type;
12615
12616 /* e) For Intel Xeon Phi native and offload compilation, if the
12617 resulting characteristic data type is 8-bit or 16-bit integer
12618 data type, the characteristic data type is int. */
12619 /* Well, we don't handle Xeon Phi yet. */
12620}
12621
12622static tree
12623simd_clone_mangle (struct cgraph_node *node,
12624 struct cgraph_simd_clone *clone_info)
12625{
12626 char vecsize_mangle = clone_info->vecsize_mangle;
12627 char mask = clone_info->inbranch ? 'M' : 'N';
12628 unsigned int simdlen = clone_info->simdlen;
12629 unsigned int n;
12630 pretty_printer pp;
12631
12632 gcc_assert (vecsize_mangle && simdlen);
12633
12634 pp_string (&pp, "_ZGV");
12635 pp_character (&pp, vecsize_mangle);
12636 pp_character (&pp, mask);
12637 pp_decimal_int (&pp, simdlen);
12638
12639 for (n = 0; n < clone_info->nargs; ++n)
12640 {
12641 struct cgraph_simd_clone_arg arg = clone_info->args[n];
12642
12643 if (arg.arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM)
12644 pp_character (&pp, 'u');
12645 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
12646 {
12647 gcc_assert (arg.linear_step != 0);
12648 pp_character (&pp, 'l');
12649 if (arg.linear_step > 1)
12650 pp_unsigned_wide_integer (&pp, arg.linear_step);
12651 else if (arg.linear_step < 0)
12652 {
12653 pp_character (&pp, 'n');
12654 pp_unsigned_wide_integer (&pp, (-(unsigned HOST_WIDE_INT)
12655 arg.linear_step));
12656 }
12657 }
12658 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP)
12659 {
12660 pp_character (&pp, 's');
12661 pp_unsigned_wide_integer (&pp, arg.linear_step);
12662 }
12663 else
12664 pp_character (&pp, 'v');
12665 if (arg.alignment)
12666 {
12667 pp_character (&pp, 'a');
12668 pp_decimal_int (&pp, arg.alignment);
12669 }
12670 }
12671
12672 pp_underscore (&pp);
4cd76837
JJ
12673 const char *str = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl));
12674 if (*str == '*')
12675 ++str;
12676 pp_string (&pp, str);
12677 str = pp_formatted_text (&pp);
0136f8f0
AH
12678
12679 /* If there already is a SIMD clone with the same mangled name, don't
12680 add another one. This can happen e.g. for
12681 #pragma omp declare simd
12682 #pragma omp declare simd simdlen(8)
12683 int foo (int, int);
12684 if the simdlen is assumed to be 8 for the first one, etc. */
12685 for (struct cgraph_node *clone = node->simd_clones; clone;
12686 clone = clone->simdclone->next_clone)
12687 if (strcmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (clone->decl)),
12688 str) == 0)
12689 return NULL_TREE;
12690
12691 return get_identifier (str);
12692}
12693
12694/* Create a simd clone of OLD_NODE and return it. */
12695
12696static struct cgraph_node *
12697simd_clone_create (struct cgraph_node *old_node)
12698{
12699 struct cgraph_node *new_node;
12700 if (old_node->definition)
e06f9964 12701 {
d52f5295 12702 if (!old_node->has_gimple_body_p ())
e06f9964 12703 return NULL;
d52f5295
ML
12704 old_node->get_body ();
12705 new_node = old_node->create_version_clone_with_body (vNULL, NULL, NULL,
12706 false, NULL, NULL,
12707 "simdclone");
e06f9964 12708 }
0136f8f0
AH
12709 else
12710 {
12711 tree old_decl = old_node->decl;
12712 tree new_decl = copy_node (old_node->decl);
12713 DECL_NAME (new_decl) = clone_function_name (old_decl, "simdclone");
12714 SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl));
12715 SET_DECL_RTL (new_decl, NULL);
12716 DECL_STATIC_CONSTRUCTOR (new_decl) = 0;
12717 DECL_STATIC_DESTRUCTOR (new_decl) = 0;
d52f5295 12718 new_node = old_node->create_version_clone (new_decl, vNULL, NULL);
3dafb85c 12719 symtab->call_cgraph_insertion_hooks (new_node);
0136f8f0
AH
12720 }
12721 if (new_node == NULL)
12722 return new_node;
12723
12724 TREE_PUBLIC (new_node->decl) = TREE_PUBLIC (old_node->decl);
12725
12726 /* The function cgraph_function_versioning () will force the new
12727 symbol local. Undo this, and inherit external visability from
12728 the old node. */
12729 new_node->local.local = old_node->local.local;
12730 new_node->externally_visible = old_node->externally_visible;
12731
12732 return new_node;
12733}
12734
12735/* Adjust the return type of the given function to its appropriate
12736 vector counterpart. Returns a simd array to be used throughout the
12737 function as a return value. */
12738
12739static tree
12740simd_clone_adjust_return_type (struct cgraph_node *node)
12741{
12742 tree fndecl = node->decl;
12743 tree orig_rettype = TREE_TYPE (TREE_TYPE (fndecl));
12744 unsigned int veclen;
12745 tree t;
12746
12747 /* Adjust the function return type. */
12748 if (orig_rettype == void_type_node)
12749 return NULL_TREE;
12750 TREE_TYPE (fndecl) = build_distinct_type_copy (TREE_TYPE (fndecl));
1c4967b9
JJ
12751 t = TREE_TYPE (TREE_TYPE (fndecl));
12752 if (INTEGRAL_TYPE_P (t) || POINTER_TYPE_P (t))
0136f8f0
AH
12753 veclen = node->simdclone->vecsize_int;
12754 else
12755 veclen = node->simdclone->vecsize_float;
1c4967b9 12756 veclen /= GET_MODE_BITSIZE (TYPE_MODE (t));
0136f8f0
AH
12757 if (veclen > node->simdclone->simdlen)
12758 veclen = node->simdclone->simdlen;
1c4967b9
JJ
12759 if (POINTER_TYPE_P (t))
12760 t = pointer_sized_int_node;
0136f8f0 12761 if (veclen == node->simdclone->simdlen)
1c4967b9 12762 t = build_vector_type (t, node->simdclone->simdlen);
0136f8f0
AH
12763 else
12764 {
1c4967b9 12765 t = build_vector_type (t, veclen);
0136f8f0 12766 t = build_array_type_nelts (t, node->simdclone->simdlen / veclen);
0136f8f0 12767 }
1c4967b9 12768 TREE_TYPE (TREE_TYPE (fndecl)) = t;
0136f8f0
AH
12769 if (!node->definition)
12770 return NULL_TREE;
12771
12772 t = DECL_RESULT (fndecl);
12773 /* Adjust the DECL_RESULT. */
12774 gcc_assert (TREE_TYPE (t) != void_type_node);
12775 TREE_TYPE (t) = TREE_TYPE (TREE_TYPE (fndecl));
12776 relayout_decl (t);
12777
12778 tree atype = build_array_type_nelts (orig_rettype,
12779 node->simdclone->simdlen);
12780 if (veclen != node->simdclone->simdlen)
12781 return build1 (VIEW_CONVERT_EXPR, atype, t);
12782
12783 /* Set up a SIMD array to use as the return value. */
12784 tree retval = create_tmp_var_raw (atype, "retval");
12785 gimple_add_tmp_var (retval);
12786 return retval;
12787}
12788
12789/* Each vector argument has a corresponding array to be used locally
12790 as part of the eventual loop. Create such temporary array and
12791 return it.
12792
12793 PREFIX is the prefix to be used for the temporary.
12794
12795 TYPE is the inner element type.
12796
12797 SIMDLEN is the number of elements. */
12798
12799static tree
12800create_tmp_simd_array (const char *prefix, tree type, int simdlen)
12801{
12802 tree atype = build_array_type_nelts (type, simdlen);
12803 tree avar = create_tmp_var_raw (atype, prefix);
12804 gimple_add_tmp_var (avar);
12805 return avar;
12806}
12807
12808/* Modify the function argument types to their corresponding vector
12809 counterparts if appropriate. Also, create one array for each simd
12810 argument to be used locally when using the function arguments as
12811 part of the loop.
12812
12813 NODE is the function whose arguments are to be adjusted.
12814
12815 Returns an adjustment vector that will be filled describing how the
12816 argument types will be adjusted. */
12817
12818static ipa_parm_adjustment_vec
12819simd_clone_adjust_argument_types (struct cgraph_node *node)
12820{
12821 vec<tree> args;
12822 ipa_parm_adjustment_vec adjustments;
12823
12824 if (node->definition)
12825 args = ipa_get_vector_of_formal_parms (node->decl);
12826 else
12827 args = simd_clone_vector_of_formal_parm_types (node->decl);
12828 adjustments.create (args.length ());
12829 unsigned i, j, veclen;
12830 struct ipa_parm_adjustment adj;
12831 for (i = 0; i < node->simdclone->nargs; ++i)
12832 {
12833 memset (&adj, 0, sizeof (adj));
12834 tree parm = args[i];
12835 tree parm_type = node->definition ? TREE_TYPE (parm) : parm;
12836 adj.base_index = i;
12837 adj.base = parm;
12838
12839 node->simdclone->args[i].orig_arg = node->definition ? parm : NULL_TREE;
12840 node->simdclone->args[i].orig_type = parm_type;
12841
12842 if (node->simdclone->args[i].arg_type != SIMD_CLONE_ARG_TYPE_VECTOR)
12843 {
12844 /* No adjustment necessary for scalar arguments. */
12845 adj.op = IPA_PARM_OP_COPY;
12846 }
12847 else
12848 {
12849 if (INTEGRAL_TYPE_P (parm_type) || POINTER_TYPE_P (parm_type))
12850 veclen = node->simdclone->vecsize_int;
12851 else
12852 veclen = node->simdclone->vecsize_float;
12853 veclen /= GET_MODE_BITSIZE (TYPE_MODE (parm_type));
12854 if (veclen > node->simdclone->simdlen)
12855 veclen = node->simdclone->simdlen;
12856 adj.arg_prefix = "simd";
1c4967b9
JJ
12857 if (POINTER_TYPE_P (parm_type))
12858 adj.type = build_vector_type (pointer_sized_int_node, veclen);
12859 else
12860 adj.type = build_vector_type (parm_type, veclen);
0136f8f0
AH
12861 node->simdclone->args[i].vector_type = adj.type;
12862 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
12863 {
12864 adjustments.safe_push (adj);
12865 if (j == veclen)
12866 {
12867 memset (&adj, 0, sizeof (adj));
12868 adj.op = IPA_PARM_OP_NEW;
12869 adj.arg_prefix = "simd";
12870 adj.base_index = i;
12871 adj.type = node->simdclone->args[i].vector_type;
12872 }
12873 }
12874
12875 if (node->definition)
12876 node->simdclone->args[i].simd_array
12877 = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm)),
12878 parm_type, node->simdclone->simdlen);
12879 }
12880 adjustments.safe_push (adj);
12881 }
12882
12883 if (node->simdclone->inbranch)
12884 {
12885 tree base_type
12886 = simd_clone_compute_base_data_type (node->simdclone->origin,
12887 node->simdclone);
12888
12889 memset (&adj, 0, sizeof (adj));
12890 adj.op = IPA_PARM_OP_NEW;
12891 adj.arg_prefix = "mask";
12892
12893 adj.base_index = i;
12894 if (INTEGRAL_TYPE_P (base_type) || POINTER_TYPE_P (base_type))
12895 veclen = node->simdclone->vecsize_int;
12896 else
12897 veclen = node->simdclone->vecsize_float;
12898 veclen /= GET_MODE_BITSIZE (TYPE_MODE (base_type));
12899 if (veclen > node->simdclone->simdlen)
12900 veclen = node->simdclone->simdlen;
1c4967b9
JJ
12901 if (POINTER_TYPE_P (base_type))
12902 adj.type = build_vector_type (pointer_sized_int_node, veclen);
12903 else
12904 adj.type = build_vector_type (base_type, veclen);
0136f8f0
AH
12905 adjustments.safe_push (adj);
12906
12907 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
12908 adjustments.safe_push (adj);
12909
12910 /* We have previously allocated one extra entry for the mask. Use
12911 it and fill it. */
12912 struct cgraph_simd_clone *sc = node->simdclone;
12913 sc->nargs++;
12914 if (node->definition)
12915 {
12916 sc->args[i].orig_arg
12917 = build_decl (UNKNOWN_LOCATION, PARM_DECL, NULL, base_type);
12918 sc->args[i].simd_array
12919 = create_tmp_simd_array ("mask", base_type, sc->simdlen);
12920 }
12921 sc->args[i].orig_type = base_type;
12922 sc->args[i].arg_type = SIMD_CLONE_ARG_TYPE_MASK;
12923 }
12924
12925 if (node->definition)
12926 ipa_modify_formal_parameters (node->decl, adjustments);
12927 else
12928 {
12929 tree new_arg_types = NULL_TREE, new_reversed;
12930 bool last_parm_void = false;
12931 if (args.length () > 0 && args.last () == void_type_node)
12932 last_parm_void = true;
12933
12934 gcc_assert (TYPE_ARG_TYPES (TREE_TYPE (node->decl)));
12935 j = adjustments.length ();
12936 for (i = 0; i < j; i++)
12937 {
12938 struct ipa_parm_adjustment *adj = &adjustments[i];
12939 tree ptype;
12940 if (adj->op == IPA_PARM_OP_COPY)
12941 ptype = args[adj->base_index];
12942 else
12943 ptype = adj->type;
12944 new_arg_types = tree_cons (NULL_TREE, ptype, new_arg_types);
12945 }
12946 new_reversed = nreverse (new_arg_types);
12947 if (last_parm_void)
12948 {
12949 if (new_reversed)
12950 TREE_CHAIN (new_arg_types) = void_list_node;
12951 else
12952 new_reversed = void_list_node;
12953 }
12954
12955 tree new_type = build_distinct_type_copy (TREE_TYPE (node->decl));
12956 TYPE_ARG_TYPES (new_type) = new_reversed;
12957 TREE_TYPE (node->decl) = new_type;
12958
12959 adjustments.release ();
12960 }
12961 args.release ();
12962 return adjustments;
12963}
12964
12965/* Initialize and copy the function arguments in NODE to their
12966 corresponding local simd arrays. Returns a fresh gimple_seq with
12967 the instruction sequence generated. */
12968
12969static gimple_seq
12970simd_clone_init_simd_arrays (struct cgraph_node *node,
12971 ipa_parm_adjustment_vec adjustments)
12972{
12973 gimple_seq seq = NULL;
12974 unsigned i = 0, j = 0, k;
12975
12976 for (tree arg = DECL_ARGUMENTS (node->decl);
12977 arg;
12978 arg = DECL_CHAIN (arg), i++, j++)
12979 {
12980 if (adjustments[j].op == IPA_PARM_OP_COPY)
12981 continue;
12982
12983 node->simdclone->args[i].vector_arg = arg;
12984
12985 tree array = node->simdclone->args[i].simd_array;
12986 if (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg)) == node->simdclone->simdlen)
12987 {
12988 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
12989 tree ptr = build_fold_addr_expr (array);
12990 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
12991 build_int_cst (ptype, 0));
12992 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
12993 gimplify_and_add (t, &seq);
12994 }
12995 else
12996 {
12997 unsigned int simdlen = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg));
12998 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
12999 for (k = 0; k < node->simdclone->simdlen; k += simdlen)
13000 {
13001 tree ptr = build_fold_addr_expr (array);
13002 int elemsize;
13003 if (k)
13004 {
13005 arg = DECL_CHAIN (arg);
13006 j++;
13007 }
13008 elemsize
13009 = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg))));
13010 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
13011 build_int_cst (ptype, k * elemsize));
13012 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
13013 gimplify_and_add (t, &seq);
13014 }
13015 }
13016 }
13017 return seq;
13018}
13019
13020/* Callback info for ipa_simd_modify_stmt_ops below. */
13021
13022struct modify_stmt_info {
13023 ipa_parm_adjustment_vec adjustments;
13024 gimple stmt;
13025 /* True if the parent statement was modified by
13026 ipa_simd_modify_stmt_ops. */
13027 bool modified;
13028};
13029
13030/* Callback for walk_gimple_op.
13031
13032 Adjust operands from a given statement as specified in the
13033 adjustments vector in the callback data. */
13034
13035static tree
13036ipa_simd_modify_stmt_ops (tree *tp, int *walk_subtrees, void *data)
13037{
13038 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
2044a4c3
JJ
13039 struct modify_stmt_info *info = (struct modify_stmt_info *) wi->info;
13040 tree *orig_tp = tp;
13041 if (TREE_CODE (*tp) == ADDR_EXPR)
13042 tp = &TREE_OPERAND (*tp, 0);
13043 struct ipa_parm_adjustment *cand = NULL;
13044 if (TREE_CODE (*tp) == PARM_DECL)
13045 cand = ipa_get_adjustment_candidate (&tp, NULL, info->adjustments, true);
13046 else
0136f8f0 13047 {
0136f8f0
AH
13048 if (TYPE_P (*tp))
13049 *walk_subtrees = 0;
0136f8f0 13050 }
0136f8f0 13051
2044a4c3
JJ
13052 tree repl = NULL_TREE;
13053 if (cand)
13054 repl = unshare_expr (cand->new_decl);
13055 else
0136f8f0 13056 {
2044a4c3
JJ
13057 if (tp != orig_tp)
13058 {
13059 *walk_subtrees = 0;
13060 bool modified = info->modified;
13061 info->modified = false;
13062 walk_tree (tp, ipa_simd_modify_stmt_ops, wi, wi->pset);
13063 if (!info->modified)
13064 {
13065 info->modified = modified;
13066 return NULL_TREE;
13067 }
13068 info->modified = modified;
13069 repl = *tp;
13070 }
13071 else
13072 return NULL_TREE;
0136f8f0 13073 }
2044a4c3
JJ
13074
13075 if (tp != orig_tp)
0136f8f0 13076 {
2044a4c3 13077 repl = build_fold_addr_expr (repl);
932b6d61
JJ
13078 gimple stmt;
13079 if (is_gimple_debug (info->stmt))
13080 {
13081 tree vexpr = make_node (DEBUG_EXPR_DECL);
13082 stmt = gimple_build_debug_source_bind (vexpr, repl, NULL);
13083 DECL_ARTIFICIAL (vexpr) = 1;
13084 TREE_TYPE (vexpr) = TREE_TYPE (repl);
13085 DECL_MODE (vexpr) = TYPE_MODE (TREE_TYPE (repl));
13086 repl = vexpr;
13087 }
13088 else
13089 {
b731b390 13090 stmt = gimple_build_assign (make_ssa_name (TREE_TYPE (repl)), repl);
932b6d61
JJ
13091 repl = gimple_assign_lhs (stmt);
13092 }
2044a4c3 13093 gimple_stmt_iterator gsi = gsi_for_stmt (info->stmt);
0136f8f0 13094 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
2044a4c3 13095 *orig_tp = repl;
0136f8f0 13096 }
2044a4c3 13097 else if (!useless_type_conversion_p (TREE_TYPE (*tp), TREE_TYPE (repl)))
0136f8f0
AH
13098 {
13099 tree vce = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (*tp), repl);
13100 *tp = vce;
13101 }
13102 else
13103 *tp = repl;
13104
13105 info->modified = true;
0136f8f0
AH
13106 return NULL_TREE;
13107}
13108
13109/* Traverse the function body and perform all modifications as
13110 described in ADJUSTMENTS. At function return, ADJUSTMENTS will be
13111 modified such that the replacement/reduction value will now be an
13112 offset into the corresponding simd_array.
13113
13114 This function will replace all function argument uses with their
13115 corresponding simd array elements, and ajust the return values
13116 accordingly. */
13117
13118static void
13119ipa_simd_modify_function_body (struct cgraph_node *node,
13120 ipa_parm_adjustment_vec adjustments,
13121 tree retval_array, tree iter)
13122{
13123 basic_block bb;
2044a4c3 13124 unsigned int i, j, l;
0136f8f0
AH
13125
13126 /* Re-use the adjustments array, but this time use it to replace
13127 every function argument use to an offset into the corresponding
13128 simd_array. */
13129 for (i = 0, j = 0; i < node->simdclone->nargs; ++i, ++j)
13130 {
13131 if (!node->simdclone->args[i].vector_arg)
13132 continue;
13133
13134 tree basetype = TREE_TYPE (node->simdclone->args[i].orig_arg);
13135 tree vectype = TREE_TYPE (node->simdclone->args[i].vector_arg);
13136 adjustments[j].new_decl
13137 = build4 (ARRAY_REF,
13138 basetype,
13139 node->simdclone->args[i].simd_array,
13140 iter,
13141 NULL_TREE, NULL_TREE);
13142 if (adjustments[j].op == IPA_PARM_OP_NONE
13143 && TYPE_VECTOR_SUBPARTS (vectype) < node->simdclone->simdlen)
13144 j += node->simdclone->simdlen / TYPE_VECTOR_SUBPARTS (vectype) - 1;
13145 }
13146
2044a4c3
JJ
13147 l = adjustments.length ();
13148 for (i = 1; i < num_ssa_names; i++)
13149 {
13150 tree name = ssa_name (i);
13151 if (name
13152 && SSA_NAME_VAR (name)
13153 && TREE_CODE (SSA_NAME_VAR (name)) == PARM_DECL)
13154 {
13155 for (j = 0; j < l; j++)
13156 if (SSA_NAME_VAR (name) == adjustments[j].base
13157 && adjustments[j].new_decl)
13158 {
13159 tree base_var;
13160 if (adjustments[j].new_ssa_base == NULL_TREE)
13161 {
13162 base_var
13163 = copy_var_decl (adjustments[j].base,
13164 DECL_NAME (adjustments[j].base),
13165 TREE_TYPE (adjustments[j].base));
13166 adjustments[j].new_ssa_base = base_var;
13167 }
13168 else
13169 base_var = adjustments[j].new_ssa_base;
13170 if (SSA_NAME_IS_DEFAULT_DEF (name))
13171 {
13172 bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
13173 gimple_stmt_iterator gsi = gsi_after_labels (bb);
13174 tree new_decl = unshare_expr (adjustments[j].new_decl);
13175 set_ssa_default_def (cfun, adjustments[j].base, NULL_TREE);
13176 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
13177 SSA_NAME_IS_DEFAULT_DEF (name) = 0;
13178 gimple stmt = gimple_build_assign (name, new_decl);
13179 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
13180 }
13181 else
13182 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
13183 }
13184 }
13185 }
13186
0136f8f0
AH
13187 struct modify_stmt_info info;
13188 info.adjustments = adjustments;
13189
13190 FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl))
13191 {
13192 gimple_stmt_iterator gsi;
13193
13194 gsi = gsi_start_bb (bb);
13195 while (!gsi_end_p (gsi))
13196 {
13197 gimple stmt = gsi_stmt (gsi);
13198 info.stmt = stmt;
13199 struct walk_stmt_info wi;
13200
13201 memset (&wi, 0, sizeof (wi));
13202 info.modified = false;
13203 wi.info = &info;
13204 walk_gimple_op (stmt, ipa_simd_modify_stmt_ops, &wi);
13205
538dd0b7 13206 if (greturn *return_stmt = dyn_cast <greturn *> (stmt))
0136f8f0 13207 {
538dd0b7 13208 tree retval = gimple_return_retval (return_stmt);
0136f8f0
AH
13209 if (!retval)
13210 {
13211 gsi_remove (&gsi, true);
13212 continue;
13213 }
13214
13215 /* Replace `return foo' with `retval_array[iter] = foo'. */
13216 tree ref = build4 (ARRAY_REF, TREE_TYPE (retval),
13217 retval_array, iter, NULL, NULL);
13218 stmt = gimple_build_assign (ref, retval);
13219 gsi_replace (&gsi, stmt, true);
13220 info.modified = true;
13221 }
13222
13223 if (info.modified)
13224 {
13225 update_stmt (stmt);
13226 if (maybe_clean_eh_stmt (stmt))
13227 gimple_purge_dead_eh_edges (gimple_bb (stmt));
13228 }
13229 gsi_next (&gsi);
13230 }
13231 }
13232}
13233
13234/* Adjust the argument types in NODE to their appropriate vector
13235 counterparts. */
13236
13237static void
13238simd_clone_adjust (struct cgraph_node *node)
13239{
13240 push_cfun (DECL_STRUCT_FUNCTION (node->decl));
13241
13242 targetm.simd_clone.adjust (node);
13243
13244 tree retval = simd_clone_adjust_return_type (node);
13245 ipa_parm_adjustment_vec adjustments
13246 = simd_clone_adjust_argument_types (node);
13247
13248 push_gimplify_context ();
13249
13250 gimple_seq seq = simd_clone_init_simd_arrays (node, adjustments);
13251
13252 /* Adjust all uses of vector arguments accordingly. Adjust all
13253 return values accordingly. */
13254 tree iter = create_tmp_var (unsigned_type_node, "iter");
b731b390
JJ
13255 tree iter1 = make_ssa_name (iter);
13256 tree iter2 = make_ssa_name (iter);
0136f8f0
AH
13257 ipa_simd_modify_function_body (node, adjustments, retval, iter1);
13258
13259 /* Initialize the iteration variable. */
13260 basic_block entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
13261 basic_block body_bb = split_block_after_labels (entry_bb)->dest;
13262 gimple_stmt_iterator gsi = gsi_after_labels (entry_bb);
13263 /* Insert the SIMD array and iv initialization at function
13264 entry. */
13265 gsi_insert_seq_before (&gsi, seq, GSI_NEW_STMT);
13266
13267 pop_gimplify_context (NULL);
13268
13269 /* Create a new BB right before the original exit BB, to hold the
13270 iteration increment and the condition/branch. */
13271 basic_block orig_exit = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), 0)->src;
13272 basic_block incr_bb = create_empty_bb (orig_exit);
33d9078a 13273 add_bb_to_loop (incr_bb, body_bb->loop_father);
0136f8f0
AH
13274 /* The succ of orig_exit was EXIT_BLOCK_PTR_FOR_FN (cfun), with an empty
13275 flag. Set it now to be a FALLTHRU_EDGE. */
13276 gcc_assert (EDGE_COUNT (orig_exit->succs) == 1);
13277 EDGE_SUCC (orig_exit, 0)->flags |= EDGE_FALLTHRU;
13278 for (unsigned i = 0;
13279 i < EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds); ++i)
13280 {
13281 edge e = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), i);
13282 redirect_edge_succ (e, incr_bb);
13283 }
13284 edge e = make_edge (incr_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
13285 e->probability = REG_BR_PROB_BASE;
13286 gsi = gsi_last_bb (incr_bb);
0d0e4a03
JJ
13287 gimple g = gimple_build_assign (iter2, PLUS_EXPR, iter1,
13288 build_int_cst (unsigned_type_node, 1));
0136f8f0
AH
13289 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13290
13291 /* Mostly annotate the loop for the vectorizer (the rest is done below). */
13292 struct loop *loop = alloc_loop ();
b15b5979 13293 cfun->has_force_vectorize_loops = true;
0136f8f0 13294 loop->safelen = node->simdclone->simdlen;
b15b5979 13295 loop->force_vectorize = true;
0136f8f0 13296 loop->header = body_bb;
0136f8f0
AH
13297
13298 /* Branch around the body if the mask applies. */
13299 if (node->simdclone->inbranch)
13300 {
13301 gimple_stmt_iterator gsi = gsi_last_bb (loop->header);
13302 tree mask_array
13303 = node->simdclone->args[node->simdclone->nargs - 1].simd_array;
b731b390 13304 tree mask = make_ssa_name (TREE_TYPE (TREE_TYPE (mask_array)));
0136f8f0
AH
13305 tree aref = build4 (ARRAY_REF,
13306 TREE_TYPE (TREE_TYPE (mask_array)),
13307 mask_array, iter1,
13308 NULL, NULL);
13309 g = gimple_build_assign (mask, aref);
13310 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13311 int bitsize = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (aref)));
13312 if (!INTEGRAL_TYPE_P (TREE_TYPE (aref)))
13313 {
13314 aref = build1 (VIEW_CONVERT_EXPR,
13315 build_nonstandard_integer_type (bitsize, 0), mask);
b731b390 13316 mask = make_ssa_name (TREE_TYPE (aref));
0136f8f0
AH
13317 g = gimple_build_assign (mask, aref);
13318 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13319 }
13320
13321 g = gimple_build_cond (EQ_EXPR, mask, build_zero_cst (TREE_TYPE (mask)),
13322 NULL, NULL);
13323 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13324 make_edge (loop->header, incr_bb, EDGE_TRUE_VALUE);
13325 FALLTHRU_EDGE (loop->header)->flags = EDGE_FALSE_VALUE;
13326 }
13327
13328 /* Generate the condition. */
13329 g = gimple_build_cond (LT_EXPR,
13330 iter2,
13331 build_int_cst (unsigned_type_node,
13332 node->simdclone->simdlen),
13333 NULL, NULL);
13334 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13335 e = split_block (incr_bb, gsi_stmt (gsi));
13336 basic_block latch_bb = e->dest;
33d9078a 13337 basic_block new_exit_bb;
0136f8f0
AH
13338 new_exit_bb = split_block (latch_bb, NULL)->dest;
13339 loop->latch = latch_bb;
13340
13341 redirect_edge_succ (FALLTHRU_EDGE (latch_bb), body_bb);
13342
13343 make_edge (incr_bb, new_exit_bb, EDGE_FALSE_VALUE);
13344 /* The successor of incr_bb is already pointing to latch_bb; just
13345 change the flags.
13346 make_edge (incr_bb, latch_bb, EDGE_TRUE_VALUE); */
13347 FALLTHRU_EDGE (incr_bb)->flags = EDGE_TRUE_VALUE;
13348
538dd0b7 13349 gphi *phi = create_phi_node (iter1, body_bb);
0136f8f0
AH
13350 edge preheader_edge = find_edge (entry_bb, body_bb);
13351 edge latch_edge = single_succ_edge (latch_bb);
13352 add_phi_arg (phi, build_zero_cst (unsigned_type_node), preheader_edge,
13353 UNKNOWN_LOCATION);
13354 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
13355
13356 /* Generate the new return. */
13357 gsi = gsi_last_bb (new_exit_bb);
13358 if (retval
13359 && TREE_CODE (retval) == VIEW_CONVERT_EXPR
13360 && TREE_CODE (TREE_OPERAND (retval, 0)) == RESULT_DECL)
13361 retval = TREE_OPERAND (retval, 0);
13362 else if (retval)
13363 {
13364 retval = build1 (VIEW_CONVERT_EXPR,
13365 TREE_TYPE (TREE_TYPE (node->decl)),
13366 retval);
13367 retval = force_gimple_operand_gsi (&gsi, retval, true, NULL,
13368 false, GSI_CONTINUE_LINKING);
13369 }
13370 g = gimple_build_return (retval);
13371 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13372
13373 /* Handle aligned clauses by replacing default defs of the aligned
13374 uniform args with __builtin_assume_aligned (arg_N(D), alignment)
13375 lhs. Handle linear by adding PHIs. */
13376 for (unsigned i = 0; i < node->simdclone->nargs; i++)
13377 if (node->simdclone->args[i].alignment
13378 && node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
13379 && (node->simdclone->args[i].alignment
13380 & (node->simdclone->args[i].alignment - 1)) == 0
13381 && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
13382 == POINTER_TYPE)
13383 {
13384 unsigned int alignment = node->simdclone->args[i].alignment;
13385 tree orig_arg = node->simdclone->args[i].orig_arg;
13386 tree def = ssa_default_def (cfun, orig_arg);
ab04b46e 13387 if (def && !has_zero_uses (def))
0136f8f0
AH
13388 {
13389 tree fn = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
13390 gimple_seq seq = NULL;
13391 bool need_cvt = false;
538dd0b7 13392 gcall *call
0136f8f0
AH
13393 = gimple_build_call (fn, 2, def, size_int (alignment));
13394 g = call;
13395 if (!useless_type_conversion_p (TREE_TYPE (orig_arg),
13396 ptr_type_node))
13397 need_cvt = true;
b731b390 13398 tree t = make_ssa_name (need_cvt ? ptr_type_node : orig_arg);
0136f8f0
AH
13399 gimple_call_set_lhs (g, t);
13400 gimple_seq_add_stmt_without_update (&seq, g);
13401 if (need_cvt)
13402 {
b731b390 13403 t = make_ssa_name (orig_arg);
0d0e4a03 13404 g = gimple_build_assign (t, NOP_EXPR, gimple_call_lhs (g));
0136f8f0
AH
13405 gimple_seq_add_stmt_without_update (&seq, g);
13406 }
13407 gsi_insert_seq_on_edge_immediate
13408 (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)), seq);
13409
13410 entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
13411 int freq = compute_call_stmt_bb_frequency (current_function_decl,
13412 entry_bb);
d52f5295
ML
13413 node->create_edge (cgraph_node::get_create (fn),
13414 call, entry_bb->count, freq);
0136f8f0
AH
13415
13416 imm_use_iterator iter;
13417 use_operand_p use_p;
13418 gimple use_stmt;
13419 tree repl = gimple_get_lhs (g);
13420 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
13421 if (is_gimple_debug (use_stmt) || use_stmt == call)
13422 continue;
13423 else
13424 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
13425 SET_USE (use_p, repl);
13426 }
13427 }
13428 else if (node->simdclone->args[i].arg_type
13429 == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
13430 {
13431 tree orig_arg = node->simdclone->args[i].orig_arg;
13432 tree def = ssa_default_def (cfun, orig_arg);
13433 gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
13434 || POINTER_TYPE_P (TREE_TYPE (orig_arg)));
ab04b46e 13435 if (def && !has_zero_uses (def))
0136f8f0 13436 {
b731b390
JJ
13437 iter1 = make_ssa_name (orig_arg);
13438 iter2 = make_ssa_name (orig_arg);
0136f8f0
AH
13439 phi = create_phi_node (iter1, body_bb);
13440 add_phi_arg (phi, def, preheader_edge, UNKNOWN_LOCATION);
13441 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
13442 enum tree_code code = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
13443 ? PLUS_EXPR : POINTER_PLUS_EXPR;
13444 tree addtype = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
13445 ? TREE_TYPE (orig_arg) : sizetype;
13446 tree addcst
13447 = build_int_cst (addtype, node->simdclone->args[i].linear_step);
0d0e4a03 13448 g = gimple_build_assign (iter2, code, iter1, addcst);
0136f8f0
AH
13449 gsi = gsi_last_bb (incr_bb);
13450 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
13451
13452 imm_use_iterator iter;
13453 use_operand_p use_p;
13454 gimple use_stmt;
13455 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
13456 if (use_stmt == phi)
13457 continue;
13458 else
13459 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
13460 SET_USE (use_p, iter1);
13461 }
13462 }
13463
13464 calculate_dominance_info (CDI_DOMINATORS);
13465 add_loop (loop, loop->header->loop_father);
13466 update_ssa (TODO_update_ssa);
13467
13468 pop_cfun ();
13469}
13470
13471/* If the function in NODE is tagged as an elemental SIMD function,
13472 create the appropriate SIMD clones. */
13473
13474static void
13475expand_simd_clones (struct cgraph_node *node)
13476{
0136f8f0
AH
13477 tree attr = lookup_attribute ("omp declare simd",
13478 DECL_ATTRIBUTES (node->decl));
e06f9964
JJ
13479 if (attr == NULL_TREE
13480 || node->global.inlined_to
13481 || lookup_attribute ("noclone", DECL_ATTRIBUTES (node->decl)))
0136f8f0 13482 return;
e06f9964 13483
0136f8f0
AH
13484 /* Ignore
13485 #pragma omp declare simd
13486 extern int foo ();
13487 in C, there we don't know the argument types at all. */
13488 if (!node->definition
13489 && TYPE_ARG_TYPES (TREE_TYPE (node->decl)) == NULL_TREE)
13490 return;
13491
13492 do
13493 {
13494 /* Start with parsing the "omp declare simd" attribute(s). */
13495 bool inbranch_clause_specified;
13496 struct cgraph_simd_clone *clone_info
13497 = simd_clone_clauses_extract (node, TREE_VALUE (attr),
13498 &inbranch_clause_specified);
13499 if (clone_info == NULL)
13500 continue;
13501
13502 int orig_simdlen = clone_info->simdlen;
13503 tree base_type = simd_clone_compute_base_data_type (node, clone_info);
13504 /* The target can return 0 (no simd clones should be created),
13505 1 (just one ISA of simd clones should be created) or higher
13506 count of ISA variants. In that case, clone_info is initialized
13507 for the first ISA variant. */
13508 int count
13509 = targetm.simd_clone.compute_vecsize_and_simdlen (node, clone_info,
13510 base_type, 0);
13511 if (count == 0)
13512 continue;
13513
13514 /* Loop over all COUNT ISA variants, and if !INBRANCH_CLAUSE_SPECIFIED,
13515 also create one inbranch and one !inbranch clone of it. */
13516 for (int i = 0; i < count * 2; i++)
13517 {
13518 struct cgraph_simd_clone *clone = clone_info;
13519 if (inbranch_clause_specified && (i & 1) != 0)
13520 continue;
13521
13522 if (i != 0)
13523 {
13524 clone = simd_clone_struct_alloc (clone_info->nargs
0136f8f0
AH
13525 + ((i & 1) != 0));
13526 simd_clone_struct_copy (clone, clone_info);
13527 /* Undo changes targetm.simd_clone.compute_vecsize_and_simdlen
13528 and simd_clone_adjust_argument_types did to the first
13529 clone's info. */
13530 clone->nargs -= clone_info->inbranch;
13531 clone->simdlen = orig_simdlen;
13532 /* And call the target hook again to get the right ISA. */
13533 targetm.simd_clone.compute_vecsize_and_simdlen (node, clone,
13534 base_type,
13535 i / 2);
13536 if ((i & 1) != 0)
13537 clone->inbranch = 1;
13538 }
13539
13540 /* simd_clone_mangle might fail if such a clone has been created
13541 already. */
13542 tree id = simd_clone_mangle (node, clone);
13543 if (id == NULL_TREE)
13544 continue;
13545
13546 /* Only when we are sure we want to create the clone actually
13547 clone the function (or definitions) or create another
13548 extern FUNCTION_DECL (for prototypes without definitions). */
13549 struct cgraph_node *n = simd_clone_create (node);
13550 if (n == NULL)
13551 continue;
13552
13553 n->simdclone = clone;
13554 clone->origin = node;
13555 clone->next_clone = NULL;
13556 if (node->simd_clones == NULL)
13557 {
13558 clone->prev_clone = n;
13559 node->simd_clones = n;
13560 }
13561 else
13562 {
13563 clone->prev_clone = node->simd_clones->simdclone->prev_clone;
13564 clone->prev_clone->simdclone->next_clone = n;
13565 node->simd_clones->simdclone->prev_clone = n;
13566 }
3dafb85c 13567 symtab->change_decl_assembler_name (n->decl, id);
0136f8f0
AH
13568 /* And finally adjust the return type, parameters and for
13569 definitions also function body. */
13570 if (node->definition)
13571 simd_clone_adjust (n);
13572 else
13573 {
13574 simd_clone_adjust_return_type (n);
13575 simd_clone_adjust_argument_types (n);
13576 }
13577 }
13578 }
13579 while ((attr = lookup_attribute ("omp declare simd", TREE_CHAIN (attr))));
13580}
13581
13582/* Entry point for IPA simd clone creation pass. */
13583
13584static unsigned int
13585ipa_omp_simd_clone (void)
13586{
13587 struct cgraph_node *node;
13588 FOR_EACH_FUNCTION (node)
13589 expand_simd_clones (node);
13590 return 0;
13591}
13592
13593namespace {
13594
13595const pass_data pass_data_omp_simd_clone =
13596{
13597 SIMPLE_IPA_PASS, /* type */
13598 "simdclone", /* name */
13599 OPTGROUP_NONE, /* optinfo_flags */
0136f8f0
AH
13600 TV_NONE, /* tv_id */
13601 ( PROP_ssa | PROP_cfg ), /* properties_required */
13602 0, /* properties_provided */
13603 0, /* properties_destroyed */
13604 0, /* todo_flags_start */
13605 0, /* todo_flags_finish */
13606};
13607
13608class pass_omp_simd_clone : public simple_ipa_opt_pass
13609{
13610public:
13611 pass_omp_simd_clone(gcc::context *ctxt)
13612 : simple_ipa_opt_pass(pass_data_omp_simd_clone, ctxt)
13613 {}
13614
13615 /* opt_pass methods: */
1a3d085c 13616 virtual bool gate (function *);
be55bfe6 13617 virtual unsigned int execute (function *) { return ipa_omp_simd_clone (); }
0136f8f0
AH
13618};
13619
1a3d085c
TS
13620bool
13621pass_omp_simd_clone::gate (function *)
13622{
13623 return ((flag_openmp || flag_openmp_simd
13624 || flag_cilkplus
13625 || (in_lto_p && !flag_wpa))
13626 && (targetm.simd_clone.compute_vecsize_and_simdlen != NULL));
13627}
13628
0136f8f0
AH
13629} // anon namespace
13630
13631simple_ipa_opt_pass *
13632make_pass_omp_simd_clone (gcc::context *ctxt)
13633{
13634 return new pass_omp_simd_clone (ctxt);
13635}
27a4cd48 13636
ec6fe917
IV
13637/* Helper function for omp_finish_file routine. Takes decls from V_DECLS and
13638 adds their addresses and sizes to constructor-vector V_CTOR. */
13639static void
13640add_decls_addresses_to_decl_constructor (vec<tree, va_gc> *v_decls,
13641 vec<constructor_elt, va_gc> *v_ctor)
13642{
13643 unsigned len = vec_safe_length (v_decls);
13644 for (unsigned i = 0; i < len; i++)
13645 {
13646 tree it = (*v_decls)[i];
13647 bool is_function = TREE_CODE (it) != VAR_DECL;
13648
13649 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE, build_fold_addr_expr (it));
13650 if (!is_function)
13651 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE,
13652 fold_convert (const_ptr_type_node,
13653 DECL_SIZE_UNIT (it)));
13654 }
13655}
13656
13657/* Create new symbols containing (address, size) pairs for global variables,
13658 marked with "omp declare target" attribute, as well as addresses for the
41dbbb37 13659 functions, which are outlined offloading regions. */
ec6fe917
IV
13660void
13661omp_finish_file (void)
13662{
13663 unsigned num_funcs = vec_safe_length (offload_funcs);
13664 unsigned num_vars = vec_safe_length (offload_vars);
13665
13666 if (num_funcs == 0 && num_vars == 0)
13667 return;
13668
13669 if (targetm_common.have_named_sections)
13670 {
13671 vec<constructor_elt, va_gc> *v_f, *v_v;
13672 vec_alloc (v_f, num_funcs);
13673 vec_alloc (v_v, num_vars * 2);
13674
13675 add_decls_addresses_to_decl_constructor (offload_funcs, v_f);
13676 add_decls_addresses_to_decl_constructor (offload_vars, v_v);
13677
13678 tree vars_decl_type = build_array_type_nelts (pointer_sized_int_node,
13679 num_vars * 2);
13680 tree funcs_decl_type = build_array_type_nelts (pointer_sized_int_node,
13681 num_funcs);
13682 TYPE_ALIGN (vars_decl_type) = TYPE_ALIGN (pointer_sized_int_node);
13683 TYPE_ALIGN (funcs_decl_type) = TYPE_ALIGN (pointer_sized_int_node);
13684 tree ctor_v = build_constructor (vars_decl_type, v_v);
13685 tree ctor_f = build_constructor (funcs_decl_type, v_f);
13686 TREE_CONSTANT (ctor_v) = TREE_CONSTANT (ctor_f) = 1;
13687 TREE_STATIC (ctor_v) = TREE_STATIC (ctor_f) = 1;
13688 tree funcs_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
13689 get_identifier (".offload_func_table"),
13690 funcs_decl_type);
13691 tree vars_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
13692 get_identifier (".offload_var_table"),
13693 vars_decl_type);
13694 TREE_STATIC (funcs_decl) = TREE_STATIC (vars_decl) = 1;
13695 /* Do not align tables more than TYPE_ALIGN (pointer_sized_int_node),
13696 otherwise a joint table in a binary will contain padding between
13697 tables from multiple object files. */
13698 DECL_USER_ALIGN (funcs_decl) = DECL_USER_ALIGN (vars_decl) = 1;
13699 DECL_ALIGN (funcs_decl) = TYPE_ALIGN (funcs_decl_type);
13700 DECL_ALIGN (vars_decl) = TYPE_ALIGN (vars_decl_type);
13701 DECL_INITIAL (funcs_decl) = ctor_f;
13702 DECL_INITIAL (vars_decl) = ctor_v;
13703 set_decl_section_name (funcs_decl, OFFLOAD_FUNC_TABLE_SECTION_NAME);
13704 set_decl_section_name (vars_decl, OFFLOAD_VAR_TABLE_SECTION_NAME);
13705
13706 varpool_node::finalize_decl (vars_decl);
13707 varpool_node::finalize_decl (funcs_decl);
844b0125 13708 }
ec6fe917
IV
13709 else
13710 {
13711 for (unsigned i = 0; i < num_funcs; i++)
13712 {
13713 tree it = (*offload_funcs)[i];
13714 targetm.record_offload_symbol (it);
13715 }
13716 for (unsigned i = 0; i < num_vars; i++)
13717 {
13718 tree it = (*offload_vars)[i];
13719 targetm.record_offload_symbol (it);
13720 }
13721 }
13722}
13723
953ff289 13724#include "gt-omp-low.h"