]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/omp-low.c
Daily bump.
[thirdparty/gcc.git] / gcc / omp-low.c
CommitLineData
ca4c3545 1/* Lowering pass for OMP directives. Converts OMP directives into explicit
2 calls to the runtime library (libgomp), data marshalling to implement data
3 sharing and copying clauses, offloading to accelerators, and more.
4
1e8e9920 5 Contributed by Diego Novillo <dnovillo@redhat.com>
6
d353bf18 7 Copyright (C) 2005-2015 Free Software Foundation, Inc.
1e8e9920 8
9This file is part of GCC.
10
11GCC is free software; you can redistribute it and/or modify it under
12the terms of the GNU General Public License as published by the Free
8c4c00c1 13Software Foundation; either version 3, or (at your option) any later
1e8e9920 14version.
15
16GCC is distributed in the hope that it will be useful, but WITHOUT ANY
17WARRANTY; without even the implied warranty of MERCHANTABILITY or
18FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19for more details.
20
21You should have received a copy of the GNU General Public License
8c4c00c1 22along with GCC; see the file COPYING3. If not see
23<http://www.gnu.org/licenses/>. */
1e8e9920 24
25#include "config.h"
26#include "system.h"
27#include "coretypes.h"
9ef16211 28#include "backend.h"
d040a5b0 29#include "cfghooks.h"
1e8e9920 30#include "tree.h"
9ef16211 31#include "gimple.h"
32#include "rtl.h"
33#include "ssa.h"
34#include "alias.h"
b20a8bb4 35#include "fold-const.h"
9ed99284 36#include "stor-layout.h"
94ea8568 37#include "cfganal.h"
bc61cadb 38#include "internal-fn.h"
39#include "gimple-fold.h"
a8783bee 40#include "gimplify.h"
dcf1a1ec 41#include "gimple-iterator.h"
e795d6e1 42#include "gimplify-me.h"
dcf1a1ec 43#include "gimple-walk.h"
75a70cf9 44#include "tree-iterator.h"
1e8e9920 45#include "tree-inline.h"
46#include "langhooks.h"
852f689e 47#include "diagnostic-core.h"
073c1fd5 48#include "cgraph.h"
49#include "tree-cfg.h"
073c1fd5 50#include "tree-into-ssa.h"
d53441c8 51#include "flags.h"
d53441c8 52#include "insn-config.h"
53#include "expmed.h"
54#include "dojump.h"
55#include "explow.h"
56#include "calls.h"
57#include "emit-rtl.h"
58#include "varasm.h"
59#include "stmt.h"
9ed99284 60#include "expr.h"
073c1fd5 61#include "tree-dfa.h"
69ee5dbb 62#include "tree-ssa.h"
1e8e9920 63#include "tree-pass.h"
1e8e9920 64#include "except.h"
e3022db7 65#include "splay-tree.h"
34517c64 66#include "insn-codes.h"
cb7f680b 67#include "optabs.h"
68#include "cfgloop.h"
3d483a94 69#include "target.h"
dccabdd1 70#include "common/common-target.h"
7740abd8 71#include "omp-low.h"
424a4a92 72#include "gimple-low.h"
73#include "tree-cfgcleanup.h"
d09768a4 74#include "pretty-print.h"
1140c305 75#include "alloc-pool.h"
2cc80ac3 76#include "symbol-summary.h"
d09768a4 77#include "ipa-prop.h"
e797f49f 78#include "tree-nested.h"
d09768a4 79#include "tree-eh.h"
40750995 80#include "cilk.h"
b0c5e347 81#include "context.h"
dccabdd1 82#include "lto-section-names.h"
ca4c3545 83#include "gomp-constants.h"
1e8e9920 84
75a70cf9 85
ca4c3545 86/* Lowering of OMP parallel and workshare constructs proceeds in two
1e8e9920 87 phases. The first phase scans the function looking for OMP statements
88 and then for variables that must be replaced to satisfy data sharing
89 clauses. The second phase expands code for the constructs, as well as
334ec2d8 90 re-gimplifying things when variables have been replaced with complex
1e8e9920 91 expressions.
92
d134bccc 93 Final code generation is done by pass_expand_omp. The flowgraph is
ca4c3545 94 scanned for regions which are then moved to a new
95 function, to be invoked by the thread library, or offloaded. */
1e8e9920 96
ca4c3545 97/* OMP region information. Every parallel and workshare
7740abd8 98 directive is enclosed between two markers, the OMP_* directive
99 and a corresponding OMP_RETURN statement. */
100
101struct omp_region
102{
103 /* The enclosing region. */
104 struct omp_region *outer;
105
106 /* First child region. */
107 struct omp_region *inner;
108
109 /* Next peer region. */
110 struct omp_region *next;
111
112 /* Block containing the omp directive as its last stmt. */
113 basic_block entry;
114
115 /* Block containing the OMP_RETURN as its last stmt. */
116 basic_block exit;
117
118 /* Block containing the OMP_CONTINUE as its last stmt. */
119 basic_block cont;
120
121 /* If this is a combined parallel+workshare region, this is a list
122 of additional arguments needed by the combined parallel+workshare
123 library call. */
124 vec<tree, va_gc> *ws_args;
125
126 /* The code for the omp directive of this region. */
127 enum gimple_code type;
128
129 /* Schedule kind, only used for OMP_FOR type regions. */
130 enum omp_clause_schedule_kind sched_kind;
131
132 /* True if this is a combined parallel+workshare region. */
133 bool is_combined_parallel;
134};
135
ca4c3545 136/* Levels of parallelism as defined by OpenACC. Increasing numbers
137 correspond to deeper loop nesting levels. */
138#define MASK_GANG 1
139#define MASK_WORKER 2
140#define MASK_VECTOR 4
141
1e8e9920 142/* Context structure. Used to store information about each parallel
143 directive in the code. */
144
145typedef struct omp_context
146{
147 /* This field must be at the beginning, as we do "inheritance": Some
148 callback functions for tree-inline.c (e.g., omp_copy_decl)
149 receive a copy_body_data pointer that is up-casted to an
150 omp_context pointer. */
151 copy_body_data cb;
152
153 /* The tree of contexts corresponding to the encountered constructs. */
154 struct omp_context *outer;
75a70cf9 155 gimple stmt;
1e8e9920 156
48e1416a 157 /* Map variables to fields in a structure that allows communication
1e8e9920 158 between sending and receiving threads. */
159 splay_tree field_map;
160 tree record_type;
161 tree sender_decl;
162 tree receiver_decl;
163
fd6481cf 164 /* These are used just by task contexts, if task firstprivate fn is
165 needed. srecord_type is used to communicate from the thread
166 that encountered the task construct to task firstprivate fn,
167 record_type is allocated by GOMP_task, initialized by task firstprivate
168 fn and passed to the task body fn. */
169 splay_tree sfield_map;
170 tree srecord_type;
171
1e8e9920 172 /* A chain of variables to add to the top-level block surrounding the
173 construct. In the case of a parallel, this is in the child function. */
174 tree block_vars;
175
ca4c3545 176 /* A map of reduction pointer variables. For accelerators, each
177 reduction variable is replaced with an array. Each thread, in turn,
178 is assigned to a slot on that array. */
179 splay_tree reduction_map;
180
bc7bff74 181 /* Label to which GOMP_cancel{,llation_point} and explicit and implicit
182 barriers should jump to during omplower pass. */
183 tree cancel_label;
184
1e8e9920 185 /* What to do with variables with implicitly determined sharing
186 attributes. */
187 enum omp_clause_default_kind default_kind;
188
189 /* Nesting depth of this context. Used to beautify error messages re
190 invalid gotos. The outermost ctx is depth 1, with depth 0 being
191 reserved for the main body of the function. */
192 int depth;
193
1e8e9920 194 /* True if this parallel directive is nested within another. */
195 bool is_nested;
bc7bff74 196
197 /* True if this construct can be cancelled. */
198 bool cancellable;
ca4c3545 199
200 /* For OpenACC loops, a mask of gang, worker and vector used at
201 levels below this one. */
202 int gwv_below;
203 /* For OpenACC loops, a mask of gang, worker and vector used at
204 this level and above. For parallel and kernels clauses, a mask
205 indicating which of num_gangs/num_workers/num_vectors was used. */
206 int gwv_this;
1e8e9920 207} omp_context;
208
ca4c3545 209/* A structure holding the elements of:
210 for (V = N1; V cond N2; V += STEP) [...] */
1e8e9920 211
fd6481cf 212struct omp_for_data_loop
213{
214 tree v, n1, n2, step;
215 enum tree_code cond_code;
216};
217
773c5ba7 218/* A structure describing the main elements of a parallel loop. */
1e8e9920 219
773c5ba7 220struct omp_for_data
1e8e9920 221{
fd6481cf 222 struct omp_for_data_loop loop;
75a70cf9 223 tree chunk_size;
1a91d914 224 gomp_for *for_stmt;
fd6481cf 225 tree pre, iter_type;
226 int collapse;
1e8e9920 227 bool have_nowait, have_ordered;
228 enum omp_clause_schedule_kind sched_kind;
fd6481cf 229 struct omp_for_data_loop *loops;
1e8e9920 230};
231
773c5ba7 232
1e8e9920 233static splay_tree all_contexts;
fd6481cf 234static int taskreg_nesting_level;
bc7bff74 235static int target_nesting_level;
7740abd8 236static struct omp_region *root_omp_region;
fd6481cf 237static bitmap task_shared_vars;
37eaded9 238static vec<omp_context *> taskreg_contexts;
1e8e9920 239
ab129075 240static void scan_omp (gimple_seq *, omp_context *);
75a70cf9 241static tree scan_omp_1_op (tree *, int *, void *);
242
243#define WALK_SUBSTMTS \
244 case GIMPLE_BIND: \
245 case GIMPLE_TRY: \
246 case GIMPLE_CATCH: \
247 case GIMPLE_EH_FILTER: \
4c0315d0 248 case GIMPLE_TRANSACTION: \
75a70cf9 249 /* The sub-statements for these should be walked. */ \
250 *handled_ops_p = false; \
251 break;
252
ca4c3545 253/* Helper function to get the name of the array containing the partial
254 reductions for OpenACC reductions. */
255static const char *
256oacc_get_reduction_array_id (tree node)
257{
258 const char *id = IDENTIFIER_POINTER (DECL_NAME (node));
259 int len = strlen ("OACC") + strlen (id);
260 char *temp_name = XALLOCAVEC (char, len + 1);
261 snprintf (temp_name, len + 1, "OACC%s", id);
262 return IDENTIFIER_POINTER (get_identifier (temp_name));
263}
264
265/* Determine the number of threads OpenACC threads used to determine the
266 size of the array of partial reductions. Currently, this is num_gangs
267 * vector_length. This value may be different than GOACC_GET_NUM_THREADS,
268 because it is independed of the device used. */
269
270static tree
271oacc_max_threads (omp_context *ctx)
272{
273 tree nthreads, vector_length, gangs, clauses;
274
275 gangs = fold_convert (sizetype, integer_one_node);
276 vector_length = gangs;
277
278 /* The reduction clause may be nested inside a loop directive.
279 Scan for the innermost vector_length clause. */
280 for (omp_context *oc = ctx; oc; oc = oc->outer)
281 {
282 if (gimple_code (oc->stmt) != GIMPLE_OMP_TARGET
283 || (gimple_omp_target_kind (oc->stmt)
284 != GF_OMP_TARGET_KIND_OACC_PARALLEL))
285 continue;
286
287 clauses = gimple_omp_target_clauses (oc->stmt);
288
289 vector_length = find_omp_clause (clauses, OMP_CLAUSE_VECTOR_LENGTH);
290 if (vector_length)
291 vector_length = fold_convert_loc (OMP_CLAUSE_LOCATION (vector_length),
292 sizetype,
293 OMP_CLAUSE_VECTOR_LENGTH_EXPR
294 (vector_length));
295 else
296 vector_length = fold_convert (sizetype, integer_one_node);
297
298 gangs = find_omp_clause (clauses, OMP_CLAUSE_NUM_GANGS);
299 if (gangs)
300 gangs = fold_convert_loc (OMP_CLAUSE_LOCATION (gangs), sizetype,
301 OMP_CLAUSE_NUM_GANGS_EXPR (gangs));
302 else
303 gangs = fold_convert (sizetype, integer_one_node);
304
305 break;
306 }
307
308 nthreads = fold_build2 (MULT_EXPR, sizetype, gangs, vector_length);
309
310 return nthreads;
311}
312
dccabdd1 313/* Holds offload tables with decls. */
314vec<tree, va_gc> *offload_funcs, *offload_vars;
315
75a70cf9 316/* Convenience function for calling scan_omp_1_op on tree operands. */
317
318static inline tree
319scan_omp_op (tree *tp, omp_context *ctx)
320{
321 struct walk_stmt_info wi;
322
323 memset (&wi, 0, sizeof (wi));
324 wi.info = ctx;
325 wi.want_locations = true;
326
327 return walk_tree (tp, scan_omp_1_op, &wi, NULL);
328}
329
e3a19533 330static void lower_omp (gimple_seq *, omp_context *);
f49d7bb5 331static tree lookup_decl_in_outer_ctx (tree, omp_context *);
332static tree maybe_lookup_decl_in_outer_ctx (tree, omp_context *);
1e8e9920 333
ca4c3545 334/* Find an OMP clause of type KIND within CLAUSES. */
1e8e9920 335
79acaae1 336tree
590c3166 337find_omp_clause (tree clauses, enum omp_clause_code kind)
1e8e9920 338{
339 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
55d6e7cd 340 if (OMP_CLAUSE_CODE (clauses) == kind)
1e8e9920 341 return clauses;
342
343 return NULL_TREE;
344}
345
346/* Return true if CTX is for an omp parallel. */
347
348static inline bool
349is_parallel_ctx (omp_context *ctx)
350{
75a70cf9 351 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL;
1e8e9920 352}
353
773c5ba7 354
fd6481cf 355/* Return true if CTX is for an omp task. */
356
357static inline bool
358is_task_ctx (omp_context *ctx)
359{
75a70cf9 360 return gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
fd6481cf 361}
362
363
364/* Return true if CTX is for an omp parallel or omp task. */
365
366static inline bool
367is_taskreg_ctx (omp_context *ctx)
368{
75a70cf9 369 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL
370 || gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
fd6481cf 371}
372
373
773c5ba7 374/* Return true if REGION is a combined parallel+workshare region. */
1e8e9920 375
376static inline bool
773c5ba7 377is_combined_parallel (struct omp_region *region)
378{
379 return region->is_combined_parallel;
380}
381
382
383/* Extract the header elements of parallel loop FOR_STMT and store
384 them into *FD. */
385
386static void
1a91d914 387extract_omp_for_data (gomp_for *for_stmt, struct omp_for_data *fd,
fd6481cf 388 struct omp_for_data_loop *loops)
773c5ba7 389{
fd6481cf 390 tree t, var, *collapse_iter, *collapse_count;
391 tree count = NULL_TREE, iter_type = long_integer_type_node;
392 struct omp_for_data_loop *loop;
393 int i;
394 struct omp_for_data_loop dummy_loop;
389dd41b 395 location_t loc = gimple_location (for_stmt);
10c55644 396 bool simd = gimple_omp_for_kind (for_stmt) & GF_OMP_FOR_SIMD;
bc7bff74 397 bool distribute = gimple_omp_for_kind (for_stmt)
398 == GF_OMP_FOR_KIND_DISTRIBUTE;
773c5ba7 399
400 fd->for_stmt = for_stmt;
401 fd->pre = NULL;
75a70cf9 402 fd->collapse = gimple_omp_for_collapse (for_stmt);
fd6481cf 403 if (fd->collapse > 1)
404 fd->loops = loops;
405 else
406 fd->loops = &fd->loop;
773c5ba7 407
bc7bff74 408 fd->have_nowait = distribute || simd;
409 fd->have_ordered = false;
773c5ba7 410 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
411 fd->chunk_size = NULL_TREE;
40750995 412 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
413 fd->sched_kind = OMP_CLAUSE_SCHEDULE_CILKFOR;
fd6481cf 414 collapse_iter = NULL;
415 collapse_count = NULL;
773c5ba7 416
75a70cf9 417 for (t = gimple_omp_for_clauses (for_stmt); t ; t = OMP_CLAUSE_CHAIN (t))
55d6e7cd 418 switch (OMP_CLAUSE_CODE (t))
773c5ba7 419 {
420 case OMP_CLAUSE_NOWAIT:
421 fd->have_nowait = true;
422 break;
423 case OMP_CLAUSE_ORDERED:
424 fd->have_ordered = true;
425 break;
426 case OMP_CLAUSE_SCHEDULE:
bc7bff74 427 gcc_assert (!distribute);
773c5ba7 428 fd->sched_kind = OMP_CLAUSE_SCHEDULE_KIND (t);
429 fd->chunk_size = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t);
430 break;
bc7bff74 431 case OMP_CLAUSE_DIST_SCHEDULE:
432 gcc_assert (distribute);
433 fd->chunk_size = OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (t);
434 break;
fd6481cf 435 case OMP_CLAUSE_COLLAPSE:
436 if (fd->collapse > 1)
437 {
438 collapse_iter = &OMP_CLAUSE_COLLAPSE_ITERVAR (t);
439 collapse_count = &OMP_CLAUSE_COLLAPSE_COUNT (t);
440 }
757abb46 441 break;
773c5ba7 442 default:
443 break;
444 }
445
fd6481cf 446 /* FIXME: for now map schedule(auto) to schedule(static).
447 There should be analysis to determine whether all iterations
448 are approximately the same amount of work (then schedule(static)
bde357c8 449 is best) or if it varies (then schedule(dynamic,N) is better). */
fd6481cf 450 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_AUTO)
451 {
452 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
453 gcc_assert (fd->chunk_size == NULL);
454 }
455 gcc_assert (fd->collapse == 1 || collapse_iter != NULL);
773c5ba7 456 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
457 gcc_assert (fd->chunk_size == NULL);
458 else if (fd->chunk_size == NULL)
459 {
460 /* We only need to compute a default chunk size for ordered
461 static loops and dynamic loops. */
fd6481cf 462 if (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
bc7bff74 463 || fd->have_ordered)
773c5ba7 464 fd->chunk_size = (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
465 ? integer_zero_node : integer_one_node;
466 }
fd6481cf 467
468 for (i = 0; i < fd->collapse; i++)
469 {
470 if (fd->collapse == 1)
471 loop = &fd->loop;
472 else if (loops != NULL)
473 loop = loops + i;
474 else
475 loop = &dummy_loop;
476
75a70cf9 477 loop->v = gimple_omp_for_index (for_stmt, i);
fd6481cf 478 gcc_assert (SSA_VAR_P (loop->v));
479 gcc_assert (TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
480 || TREE_CODE (TREE_TYPE (loop->v)) == POINTER_TYPE);
481 var = TREE_CODE (loop->v) == SSA_NAME ? SSA_NAME_VAR (loop->v) : loop->v;
75a70cf9 482 loop->n1 = gimple_omp_for_initial (for_stmt, i);
fd6481cf 483
75a70cf9 484 loop->cond_code = gimple_omp_for_cond (for_stmt, i);
485 loop->n2 = gimple_omp_for_final (for_stmt, i);
fd6481cf 486 switch (loop->cond_code)
487 {
488 case LT_EXPR:
489 case GT_EXPR:
490 break;
f2697631 491 case NE_EXPR:
492 gcc_assert (gimple_omp_for_kind (for_stmt)
40750995 493 == GF_OMP_FOR_KIND_CILKSIMD
494 || (gimple_omp_for_kind (for_stmt)
495 == GF_OMP_FOR_KIND_CILKFOR));
f2697631 496 break;
fd6481cf 497 case LE_EXPR:
498 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
2cc66f2a 499 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, 1);
fd6481cf 500 else
389dd41b 501 loop->n2 = fold_build2_loc (loc,
502 PLUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
fd6481cf 503 build_int_cst (TREE_TYPE (loop->n2), 1));
504 loop->cond_code = LT_EXPR;
505 break;
506 case GE_EXPR:
507 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
2cc66f2a 508 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, -1);
fd6481cf 509 else
389dd41b 510 loop->n2 = fold_build2_loc (loc,
511 MINUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
fd6481cf 512 build_int_cst (TREE_TYPE (loop->n2), 1));
513 loop->cond_code = GT_EXPR;
514 break;
515 default:
516 gcc_unreachable ();
517 }
518
75a70cf9 519 t = gimple_omp_for_incr (for_stmt, i);
fd6481cf 520 gcc_assert (TREE_OPERAND (t, 0) == var);
521 switch (TREE_CODE (t))
522 {
523 case PLUS_EXPR:
fd6481cf 524 loop->step = TREE_OPERAND (t, 1);
525 break;
85d86b55 526 case POINTER_PLUS_EXPR:
527 loop->step = fold_convert (ssizetype, TREE_OPERAND (t, 1));
528 break;
fd6481cf 529 case MINUS_EXPR:
530 loop->step = TREE_OPERAND (t, 1);
389dd41b 531 loop->step = fold_build1_loc (loc,
532 NEGATE_EXPR, TREE_TYPE (loop->step),
fd6481cf 533 loop->step);
534 break;
535 default:
536 gcc_unreachable ();
537 }
538
bc7bff74 539 if (simd
540 || (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
541 && !fd->have_ordered))
3d483a94 542 {
543 if (fd->collapse == 1)
544 iter_type = TREE_TYPE (loop->v);
545 else if (i == 0
546 || TYPE_PRECISION (iter_type)
547 < TYPE_PRECISION (TREE_TYPE (loop->v)))
548 iter_type
549 = build_nonstandard_integer_type
bc7bff74 550 (TYPE_PRECISION (TREE_TYPE (loop->v)), 1);
3d483a94 551 }
552 else if (iter_type != long_long_unsigned_type_node)
fd6481cf 553 {
554 if (POINTER_TYPE_P (TREE_TYPE (loop->v)))
555 iter_type = long_long_unsigned_type_node;
556 else if (TYPE_UNSIGNED (TREE_TYPE (loop->v))
557 && TYPE_PRECISION (TREE_TYPE (loop->v))
558 >= TYPE_PRECISION (iter_type))
559 {
560 tree n;
561
562 if (loop->cond_code == LT_EXPR)
389dd41b 563 n = fold_build2_loc (loc,
564 PLUS_EXPR, TREE_TYPE (loop->v),
fd6481cf 565 loop->n2, loop->step);
566 else
567 n = loop->n1;
568 if (TREE_CODE (n) != INTEGER_CST
569 || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type), n))
570 iter_type = long_long_unsigned_type_node;
571 }
572 else if (TYPE_PRECISION (TREE_TYPE (loop->v))
573 > TYPE_PRECISION (iter_type))
574 {
575 tree n1, n2;
576
577 if (loop->cond_code == LT_EXPR)
578 {
579 n1 = loop->n1;
389dd41b 580 n2 = fold_build2_loc (loc,
581 PLUS_EXPR, TREE_TYPE (loop->v),
fd6481cf 582 loop->n2, loop->step);
583 }
584 else
585 {
389dd41b 586 n1 = fold_build2_loc (loc,
587 MINUS_EXPR, TREE_TYPE (loop->v),
fd6481cf 588 loop->n2, loop->step);
589 n2 = loop->n1;
590 }
591 if (TREE_CODE (n1) != INTEGER_CST
592 || TREE_CODE (n2) != INTEGER_CST
593 || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type), n1)
594 || !tree_int_cst_lt (n2, TYPE_MAX_VALUE (iter_type)))
595 iter_type = long_long_unsigned_type_node;
596 }
597 }
598
599 if (collapse_count && *collapse_count == NULL)
600 {
8e6b4515 601 t = fold_binary (loop->cond_code, boolean_type_node,
602 fold_convert (TREE_TYPE (loop->v), loop->n1),
603 fold_convert (TREE_TYPE (loop->v), loop->n2));
604 if (t && integer_zerop (t))
605 count = build_zero_cst (long_long_unsigned_type_node);
606 else if ((i == 0 || count != NULL_TREE)
607 && TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
608 && TREE_CONSTANT (loop->n1)
609 && TREE_CONSTANT (loop->n2)
610 && TREE_CODE (loop->step) == INTEGER_CST)
fd6481cf 611 {
612 tree itype = TREE_TYPE (loop->v);
613
614 if (POINTER_TYPE_P (itype))
3cea8318 615 itype = signed_type_for (itype);
fd6481cf 616 t = build_int_cst (itype, (loop->cond_code == LT_EXPR ? -1 : 1));
389dd41b 617 t = fold_build2_loc (loc,
618 PLUS_EXPR, itype,
619 fold_convert_loc (loc, itype, loop->step), t);
620 t = fold_build2_loc (loc, PLUS_EXPR, itype, t,
621 fold_convert_loc (loc, itype, loop->n2));
622 t = fold_build2_loc (loc, MINUS_EXPR, itype, t,
623 fold_convert_loc (loc, itype, loop->n1));
fd6481cf 624 if (TYPE_UNSIGNED (itype) && loop->cond_code == GT_EXPR)
389dd41b 625 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype,
626 fold_build1_loc (loc, NEGATE_EXPR, itype, t),
627 fold_build1_loc (loc, NEGATE_EXPR, itype,
628 fold_convert_loc (loc, itype,
629 loop->step)));
fd6481cf 630 else
389dd41b 631 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, t,
632 fold_convert_loc (loc, itype, loop->step));
633 t = fold_convert_loc (loc, long_long_unsigned_type_node, t);
fd6481cf 634 if (count != NULL_TREE)
389dd41b 635 count = fold_build2_loc (loc,
636 MULT_EXPR, long_long_unsigned_type_node,
fd6481cf 637 count, t);
638 else
639 count = t;
640 if (TREE_CODE (count) != INTEGER_CST)
641 count = NULL_TREE;
642 }
8e6b4515 643 else if (count && !integer_zerop (count))
fd6481cf 644 count = NULL_TREE;
645 }
646 }
647
3d483a94 648 if (count
bc7bff74 649 && !simd
650 && (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
651 || fd->have_ordered))
fd6481cf 652 {
653 if (!tree_int_cst_lt (count, TYPE_MAX_VALUE (long_integer_type_node)))
654 iter_type = long_long_unsigned_type_node;
655 else
656 iter_type = long_integer_type_node;
657 }
658 else if (collapse_iter && *collapse_iter != NULL)
659 iter_type = TREE_TYPE (*collapse_iter);
660 fd->iter_type = iter_type;
661 if (collapse_iter && *collapse_iter == NULL)
662 *collapse_iter = create_tmp_var (iter_type, ".iter");
663 if (collapse_count && *collapse_count == NULL)
664 {
665 if (count)
389dd41b 666 *collapse_count = fold_convert_loc (loc, iter_type, count);
fd6481cf 667 else
668 *collapse_count = create_tmp_var (iter_type, ".count");
669 }
670
671 if (fd->collapse > 1)
672 {
673 fd->loop.v = *collapse_iter;
674 fd->loop.n1 = build_int_cst (TREE_TYPE (fd->loop.v), 0);
675 fd->loop.n2 = *collapse_count;
676 fd->loop.step = build_int_cst (TREE_TYPE (fd->loop.v), 1);
677 fd->loop.cond_code = LT_EXPR;
678 }
ca4c3545 679
680 /* For OpenACC loops, force a chunk size of one, as this avoids the default
681 scheduling where several subsequent iterations are being executed by the
682 same thread. */
683 if (gimple_omp_for_kind (for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
684 {
685 gcc_assert (fd->chunk_size == NULL_TREE);
686 fd->chunk_size = build_int_cst (TREE_TYPE (fd->loop.v), 1);
687 }
773c5ba7 688}
689
690
691/* Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB
692 is the immediate dominator of PAR_ENTRY_BB, return true if there
693 are no data dependencies that would prevent expanding the parallel
694 directive at PAR_ENTRY_BB as a combined parallel+workshare region.
695
696 When expanding a combined parallel+workshare region, the call to
697 the child function may need additional arguments in the case of
75a70cf9 698 GIMPLE_OMP_FOR regions. In some cases, these arguments are
699 computed out of variables passed in from the parent to the child
700 via 'struct .omp_data_s'. For instance:
773c5ba7 701
702 #pragma omp parallel for schedule (guided, i * 4)
703 for (j ...)
704
705 Is lowered into:
706
707 # BLOCK 2 (PAR_ENTRY_BB)
708 .omp_data_o.i = i;
709 #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
48e1416a 710
773c5ba7 711 # BLOCK 3 (WS_ENTRY_BB)
712 .omp_data_i = &.omp_data_o;
713 D.1667 = .omp_data_i->i;
714 D.1598 = D.1667 * 4;
715 #pragma omp for schedule (guided, D.1598)
716
717 When we outline the parallel region, the call to the child function
718 'bar.omp_fn.0' will need the value D.1598 in its argument list, but
719 that value is computed *after* the call site. So, in principle we
720 cannot do the transformation.
721
722 To see whether the code in WS_ENTRY_BB blocks the combined
723 parallel+workshare call, we collect all the variables used in the
75a70cf9 724 GIMPLE_OMP_FOR header check whether they appear on the LHS of any
773c5ba7 725 statement in WS_ENTRY_BB. If so, then we cannot emit the combined
726 call.
727
728 FIXME. If we had the SSA form built at this point, we could merely
729 hoist the code in block 3 into block 2 and be done with it. But at
730 this point we don't have dataflow information and though we could
731 hack something up here, it is really not worth the aggravation. */
732
733static bool
f018d957 734workshare_safe_to_combine_p (basic_block ws_entry_bb)
773c5ba7 735{
736 struct omp_for_data fd;
f018d957 737 gimple ws_stmt = last_stmt (ws_entry_bb);
773c5ba7 738
75a70cf9 739 if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
773c5ba7 740 return true;
741
75a70cf9 742 gcc_assert (gimple_code (ws_stmt) == GIMPLE_OMP_FOR);
773c5ba7 743
1a91d914 744 extract_omp_for_data (as_a <gomp_for *> (ws_stmt), &fd, NULL);
fd6481cf 745
746 if (fd.collapse > 1 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
747 return false;
748 if (fd.iter_type != long_integer_type_node)
749 return false;
773c5ba7 750
751 /* FIXME. We give up too easily here. If any of these arguments
752 are not constants, they will likely involve variables that have
753 been mapped into fields of .omp_data_s for sharing with the child
754 function. With appropriate data flow, it would be possible to
755 see through this. */
fd6481cf 756 if (!is_gimple_min_invariant (fd.loop.n1)
757 || !is_gimple_min_invariant (fd.loop.n2)
758 || !is_gimple_min_invariant (fd.loop.step)
773c5ba7 759 || (fd.chunk_size && !is_gimple_min_invariant (fd.chunk_size)))
760 return false;
761
762 return true;
763}
764
765
766/* Collect additional arguments needed to emit a combined
767 parallel+workshare call. WS_STMT is the workshare directive being
768 expanded. */
769
f1f41a6c 770static vec<tree, va_gc> *
bc7bff74 771get_ws_args_for (gimple par_stmt, gimple ws_stmt)
773c5ba7 772{
773 tree t;
389dd41b 774 location_t loc = gimple_location (ws_stmt);
f1f41a6c 775 vec<tree, va_gc> *ws_args;
773c5ba7 776
1a91d914 777 if (gomp_for *for_stmt = dyn_cast <gomp_for *> (ws_stmt))
773c5ba7 778 {
779 struct omp_for_data fd;
bc7bff74 780 tree n1, n2;
773c5ba7 781
1a91d914 782 extract_omp_for_data (for_stmt, &fd, NULL);
bc7bff74 783 n1 = fd.loop.n1;
784 n2 = fd.loop.n2;
785
1a91d914 786 if (gimple_omp_for_combined_into_p (for_stmt))
bc7bff74 787 {
788 tree innerc
789 = find_omp_clause (gimple_omp_parallel_clauses (par_stmt),
790 OMP_CLAUSE__LOOPTEMP_);
791 gcc_assert (innerc);
792 n1 = OMP_CLAUSE_DECL (innerc);
793 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
794 OMP_CLAUSE__LOOPTEMP_);
795 gcc_assert (innerc);
796 n2 = OMP_CLAUSE_DECL (innerc);
797 }
773c5ba7 798
f1f41a6c 799 vec_alloc (ws_args, 3 + (fd.chunk_size != 0));
773c5ba7 800
bc7bff74 801 t = fold_convert_loc (loc, long_integer_type_node, n1);
f1f41a6c 802 ws_args->quick_push (t);
773c5ba7 803
bc7bff74 804 t = fold_convert_loc (loc, long_integer_type_node, n2);
f1f41a6c 805 ws_args->quick_push (t);
773c5ba7 806
414c3a2c 807 t = fold_convert_loc (loc, long_integer_type_node, fd.loop.step);
f1f41a6c 808 ws_args->quick_push (t);
414c3a2c 809
810 if (fd.chunk_size)
811 {
812 t = fold_convert_loc (loc, long_integer_type_node, fd.chunk_size);
f1f41a6c 813 ws_args->quick_push (t);
414c3a2c 814 }
773c5ba7 815
816 return ws_args;
817 }
75a70cf9 818 else if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
773c5ba7 819 {
ac6e3339 820 /* Number of sections is equal to the number of edges from the
75a70cf9 821 GIMPLE_OMP_SECTIONS_SWITCH statement, except for the one to
822 the exit of the sections region. */
823 basic_block bb = single_succ (gimple_bb (ws_stmt));
ac6e3339 824 t = build_int_cst (unsigned_type_node, EDGE_COUNT (bb->succs) - 1);
f1f41a6c 825 vec_alloc (ws_args, 1);
826 ws_args->quick_push (t);
414c3a2c 827 return ws_args;
773c5ba7 828 }
829
830 gcc_unreachable ();
831}
832
833
834/* Discover whether REGION is a combined parallel+workshare region. */
835
836static void
837determine_parallel_type (struct omp_region *region)
1e8e9920 838{
773c5ba7 839 basic_block par_entry_bb, par_exit_bb;
840 basic_block ws_entry_bb, ws_exit_bb;
841
03ed154b 842 if (region == NULL || region->inner == NULL
ac6e3339 843 || region->exit == NULL || region->inner->exit == NULL
844 || region->inner->cont == NULL)
773c5ba7 845 return;
846
847 /* We only support parallel+for and parallel+sections. */
75a70cf9 848 if (region->type != GIMPLE_OMP_PARALLEL
849 || (region->inner->type != GIMPLE_OMP_FOR
850 && region->inner->type != GIMPLE_OMP_SECTIONS))
773c5ba7 851 return;
852
853 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
854 WS_EXIT_BB -> PAR_EXIT_BB. */
61e47ac8 855 par_entry_bb = region->entry;
856 par_exit_bb = region->exit;
857 ws_entry_bb = region->inner->entry;
858 ws_exit_bb = region->inner->exit;
773c5ba7 859
860 if (single_succ (par_entry_bb) == ws_entry_bb
861 && single_succ (ws_exit_bb) == par_exit_bb
f018d957 862 && workshare_safe_to_combine_p (ws_entry_bb)
75a70cf9 863 && (gimple_omp_parallel_combined_p (last_stmt (par_entry_bb))
de7ef844 864 || (last_and_only_stmt (ws_entry_bb)
865 && last_and_only_stmt (par_exit_bb))))
773c5ba7 866 {
bc7bff74 867 gimple par_stmt = last_stmt (par_entry_bb);
75a70cf9 868 gimple ws_stmt = last_stmt (ws_entry_bb);
61e47ac8 869
75a70cf9 870 if (region->inner->type == GIMPLE_OMP_FOR)
773c5ba7 871 {
872 /* If this is a combined parallel loop, we need to determine
873 whether or not to use the combined library calls. There
874 are two cases where we do not apply the transformation:
875 static loops and any kind of ordered loop. In the first
876 case, we already open code the loop so there is no need
877 to do anything else. In the latter case, the combined
878 parallel loop call would still need extra synchronization
879 to implement ordered semantics, so there would not be any
880 gain in using the combined call. */
75a70cf9 881 tree clauses = gimple_omp_for_clauses (ws_stmt);
773c5ba7 882 tree c = find_omp_clause (clauses, OMP_CLAUSE_SCHEDULE);
883 if (c == NULL
884 || OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_STATIC
885 || find_omp_clause (clauses, OMP_CLAUSE_ORDERED))
886 {
887 region->is_combined_parallel = false;
888 region->inner->is_combined_parallel = false;
889 return;
890 }
891 }
892
893 region->is_combined_parallel = true;
894 region->inner->is_combined_parallel = true;
bc7bff74 895 region->ws_args = get_ws_args_for (par_stmt, ws_stmt);
773c5ba7 896 }
1e8e9920 897}
898
773c5ba7 899
1e8e9920 900/* Return true if EXPR is variable sized. */
901
902static inline bool
1f1872fd 903is_variable_sized (const_tree expr)
1e8e9920 904{
905 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr)));
906}
907
908/* Return true if DECL is a reference type. */
909
910static inline bool
911is_reference (tree decl)
912{
913 return lang_hooks.decls.omp_privatize_by_reference (decl);
914}
915
ca4c3545 916/* Return the type of a decl. If the decl is reference type,
917 return its base type. */
918static inline tree
919get_base_type (tree decl)
920{
921 tree type = TREE_TYPE (decl);
922 if (is_reference (decl))
923 type = TREE_TYPE (type);
924 return type;
925}
926
927/* Lookup variables. The "maybe" form
1e8e9920 928 allows for the variable form to not have been entered, otherwise we
929 assert that the variable must have been entered. */
930
931static inline tree
932lookup_decl (tree var, omp_context *ctx)
933{
06ecf488 934 tree *n = ctx->cb.decl_map->get (var);
e3022db7 935 return *n;
1e8e9920 936}
937
938static inline tree
e8a588af 939maybe_lookup_decl (const_tree var, omp_context *ctx)
1e8e9920 940{
06ecf488 941 tree *n = ctx->cb.decl_map->get (const_cast<tree> (var));
e3022db7 942 return n ? *n : NULL_TREE;
1e8e9920 943}
944
945static inline tree
946lookup_field (tree var, omp_context *ctx)
947{
948 splay_tree_node n;
949 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
950 return (tree) n->value;
951}
952
fd6481cf 953static inline tree
954lookup_sfield (tree var, omp_context *ctx)
955{
956 splay_tree_node n;
957 n = splay_tree_lookup (ctx->sfield_map
958 ? ctx->sfield_map : ctx->field_map,
959 (splay_tree_key) var);
960 return (tree) n->value;
961}
962
1e8e9920 963static inline tree
964maybe_lookup_field (tree var, omp_context *ctx)
965{
966 splay_tree_node n;
967 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
968 return n ? (tree) n->value : NULL_TREE;
969}
970
ca4c3545 971static inline tree
972lookup_oacc_reduction (const char *id, omp_context *ctx)
973{
974 splay_tree_node n;
975 n = splay_tree_lookup (ctx->reduction_map, (splay_tree_key) id);
976 return (tree) n->value;
977}
978
979static inline tree
980maybe_lookup_oacc_reduction (tree var, omp_context *ctx)
981{
982 splay_tree_node n = NULL;
983 if (ctx->reduction_map)
984 n = splay_tree_lookup (ctx->reduction_map, (splay_tree_key) var);
985 return n ? (tree) n->value : NULL_TREE;
986}
987
e8a588af 988/* Return true if DECL should be copied by pointer. SHARED_CTX is
989 the parallel context if DECL is to be shared. */
1e8e9920 990
991static bool
fd6481cf 992use_pointer_for_field (tree decl, omp_context *shared_ctx)
1e8e9920 993{
994 if (AGGREGATE_TYPE_P (TREE_TYPE (decl)))
995 return true;
996
554f2707 997 /* We can only use copy-in/copy-out semantics for shared variables
1e8e9920 998 when we know the value is not accessible from an outer scope. */
e8a588af 999 if (shared_ctx)
1e8e9920 1000 {
ca4c3545 1001 gcc_assert (!is_gimple_omp_oacc (shared_ctx->stmt));
1002
1e8e9920 1003 /* ??? Trivially accessible from anywhere. But why would we even
1004 be passing an address in this case? Should we simply assert
1005 this to be false, or should we have a cleanup pass that removes
1006 these from the list of mappings? */
1007 if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
1008 return true;
1009
1010 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
1011 without analyzing the expression whether or not its location
1012 is accessible to anyone else. In the case of nested parallel
1013 regions it certainly may be. */
df2c34fc 1014 if (TREE_CODE (decl) != RESULT_DECL && DECL_HAS_VALUE_EXPR_P (decl))
1e8e9920 1015 return true;
1016
1017 /* Do not use copy-in/copy-out for variables that have their
1018 address taken. */
1019 if (TREE_ADDRESSABLE (decl))
1020 return true;
e8a588af 1021
b8214689 1022 /* lower_send_shared_vars only uses copy-in, but not copy-out
1023 for these. */
1024 if (TREE_READONLY (decl)
1025 || ((TREE_CODE (decl) == RESULT_DECL
1026 || TREE_CODE (decl) == PARM_DECL)
1027 && DECL_BY_REFERENCE (decl)))
1028 return false;
1029
e8a588af 1030 /* Disallow copy-in/out in nested parallel if
1031 decl is shared in outer parallel, otherwise
1032 each thread could store the shared variable
1033 in its own copy-in location, making the
1034 variable no longer really shared. */
b8214689 1035 if (shared_ctx->is_nested)
e8a588af 1036 {
1037 omp_context *up;
1038
1039 for (up = shared_ctx->outer; up; up = up->outer)
0cb159ec 1040 if (is_taskreg_ctx (up) && maybe_lookup_decl (decl, up))
e8a588af 1041 break;
1042
0cb159ec 1043 if (up)
e8a588af 1044 {
1045 tree c;
1046
75a70cf9 1047 for (c = gimple_omp_taskreg_clauses (up->stmt);
e8a588af 1048 c; c = OMP_CLAUSE_CHAIN (c))
1049 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
1050 && OMP_CLAUSE_DECL (c) == decl)
1051 break;
1052
1053 if (c)
784ad964 1054 goto maybe_mark_addressable_and_ret;
e8a588af 1055 }
1056 }
fd6481cf 1057
b8214689 1058 /* For tasks avoid using copy-in/out. As tasks can be
fd6481cf 1059 deferred or executed in different thread, when GOMP_task
1060 returns, the task hasn't necessarily terminated. */
b8214689 1061 if (is_task_ctx (shared_ctx))
fd6481cf 1062 {
784ad964 1063 tree outer;
1064 maybe_mark_addressable_and_ret:
1065 outer = maybe_lookup_decl_in_outer_ctx (decl, shared_ctx);
fd6481cf 1066 if (is_gimple_reg (outer))
1067 {
1068 /* Taking address of OUTER in lower_send_shared_vars
1069 might need regimplification of everything that uses the
1070 variable. */
1071 if (!task_shared_vars)
1072 task_shared_vars = BITMAP_ALLOC (NULL);
1073 bitmap_set_bit (task_shared_vars, DECL_UID (outer));
1074 TREE_ADDRESSABLE (outer) = 1;
1075 }
1076 return true;
1077 }
1e8e9920 1078 }
1079
1080 return false;
1081}
1082
79acaae1 1083/* Construct a new automatic decl similar to VAR. */
1084
1085static tree
1086omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx)
1087{
1088 tree copy = copy_var_decl (var, name, type);
1089
1090 DECL_CONTEXT (copy) = current_function_decl;
1767a056 1091 DECL_CHAIN (copy) = ctx->block_vars;
1e8e9920 1092 ctx->block_vars = copy;
1093
1094 return copy;
1095}
1096
1097static tree
1098omp_copy_decl_1 (tree var, omp_context *ctx)
1099{
1100 return omp_copy_decl_2 (var, DECL_NAME (var), TREE_TYPE (var), ctx);
1101}
1102
445d06b6 1103/* Build COMPONENT_REF and set TREE_THIS_VOLATILE and TREE_READONLY on it
1104 as appropriate. */
1105static tree
1106omp_build_component_ref (tree obj, tree field)
1107{
1108 tree ret = build3 (COMPONENT_REF, TREE_TYPE (field), obj, field, NULL);
1109 if (TREE_THIS_VOLATILE (field))
1110 TREE_THIS_VOLATILE (ret) |= 1;
1111 if (TREE_READONLY (field))
1112 TREE_READONLY (ret) |= 1;
1113 return ret;
1114}
1115
1e8e9920 1116/* Build tree nodes to access the field for VAR on the receiver side. */
1117
1118static tree
1119build_receiver_ref (tree var, bool by_ref, omp_context *ctx)
1120{
1121 tree x, field = lookup_field (var, ctx);
1122
1123 /* If the receiver record type was remapped in the child function,
1124 remap the field into the new record type. */
1125 x = maybe_lookup_field (field, ctx);
1126 if (x != NULL)
1127 field = x;
1128
182cf5a9 1129 x = build_simple_mem_ref (ctx->receiver_decl);
445d06b6 1130 x = omp_build_component_ref (x, field);
1e8e9920 1131 if (by_ref)
182cf5a9 1132 x = build_simple_mem_ref (x);
1e8e9920 1133
1134 return x;
1135}
1136
1137/* Build tree nodes to access VAR in the scope outer to CTX. In the case
1138 of a parallel, this is a component reference; for workshare constructs
1139 this is some variable. */
1140
1141static tree
1142build_outer_var_ref (tree var, omp_context *ctx)
1143{
1144 tree x;
1145
f49d7bb5 1146 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx)))
1e8e9920 1147 x = var;
1148 else if (is_variable_sized (var))
1149 {
1150 x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
1151 x = build_outer_var_ref (x, ctx);
182cf5a9 1152 x = build_simple_mem_ref (x);
1e8e9920 1153 }
fd6481cf 1154 else if (is_taskreg_ctx (ctx))
1e8e9920 1155 {
e8a588af 1156 bool by_ref = use_pointer_for_field (var, NULL);
1e8e9920 1157 x = build_receiver_ref (var, by_ref, ctx);
1158 }
3d483a94 1159 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
10c55644 1160 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3d483a94 1161 {
1162 /* #pragma omp simd isn't a worksharing construct, and can reference even
1163 private vars in its linear etc. clauses. */
1164 x = NULL_TREE;
1165 if (ctx->outer && is_taskreg_ctx (ctx))
1166 x = lookup_decl (var, ctx->outer);
1167 else if (ctx->outer)
84cb1020 1168 x = maybe_lookup_decl_in_outer_ctx (var, ctx);
3d483a94 1169 if (x == NULL_TREE)
1170 x = var;
1171 }
1e8e9920 1172 else if (ctx->outer)
1173 x = lookup_decl (var, ctx->outer);
9438af57 1174 else if (is_reference (var))
1175 /* This can happen with orphaned constructs. If var is reference, it is
1176 possible it is shared and as such valid. */
1177 x = var;
1e8e9920 1178 else
1179 gcc_unreachable ();
1180
1181 if (is_reference (var))
182cf5a9 1182 x = build_simple_mem_ref (x);
1e8e9920 1183
1184 return x;
1185}
1186
1187/* Build tree nodes to access the field for VAR on the sender side. */
1188
1189static tree
1190build_sender_ref (tree var, omp_context *ctx)
1191{
fd6481cf 1192 tree field = lookup_sfield (var, ctx);
445d06b6 1193 return omp_build_component_ref (ctx->sender_decl, field);
1e8e9920 1194}
1195
1196/* Add a new field for VAR inside the structure CTX->SENDER_DECL. */
1197
1198static void
fd6481cf 1199install_var_field (tree var, bool by_ref, int mask, omp_context *ctx)
1e8e9920 1200{
fd6481cf 1201 tree field, type, sfield = NULL_TREE;
1e8e9920 1202
fd6481cf 1203 gcc_assert ((mask & 1) == 0
1204 || !splay_tree_lookup (ctx->field_map, (splay_tree_key) var));
1205 gcc_assert ((mask & 2) == 0 || !ctx->sfield_map
1206 || !splay_tree_lookup (ctx->sfield_map, (splay_tree_key) var));
ca4c3545 1207 gcc_assert ((mask & 3) == 3
1208 || !is_gimple_omp_oacc (ctx->stmt));
1e8e9920 1209
1210 type = TREE_TYPE (var);
bc7bff74 1211 if (mask & 4)
1212 {
1213 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
1214 type = build_pointer_type (build_pointer_type (type));
1215 }
1216 else if (by_ref)
1e8e9920 1217 type = build_pointer_type (type);
fd6481cf 1218 else if ((mask & 3) == 1 && is_reference (var))
1219 type = TREE_TYPE (type);
1e8e9920 1220
e60a6f7b 1221 field = build_decl (DECL_SOURCE_LOCATION (var),
1222 FIELD_DECL, DECL_NAME (var), type);
1e8e9920 1223
1224 /* Remember what variable this field was created for. This does have a
1225 side effect of making dwarf2out ignore this member, so for helpful
1226 debugging we clear it later in delete_omp_context. */
1227 DECL_ABSTRACT_ORIGIN (field) = var;
fd6481cf 1228 if (type == TREE_TYPE (var))
1229 {
1230 DECL_ALIGN (field) = DECL_ALIGN (var);
1231 DECL_USER_ALIGN (field) = DECL_USER_ALIGN (var);
1232 TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (var);
1233 }
1234 else
1235 DECL_ALIGN (field) = TYPE_ALIGN (type);
1e8e9920 1236
fd6481cf 1237 if ((mask & 3) == 3)
1238 {
1239 insert_field_into_struct (ctx->record_type, field);
1240 if (ctx->srecord_type)
1241 {
e60a6f7b 1242 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1243 FIELD_DECL, DECL_NAME (var), type);
fd6481cf 1244 DECL_ABSTRACT_ORIGIN (sfield) = var;
1245 DECL_ALIGN (sfield) = DECL_ALIGN (field);
1246 DECL_USER_ALIGN (sfield) = DECL_USER_ALIGN (field);
1247 TREE_THIS_VOLATILE (sfield) = TREE_THIS_VOLATILE (field);
1248 insert_field_into_struct (ctx->srecord_type, sfield);
1249 }
1250 }
1251 else
1252 {
1253 if (ctx->srecord_type == NULL_TREE)
1254 {
1255 tree t;
1256
1257 ctx->srecord_type = lang_hooks.types.make_type (RECORD_TYPE);
1258 ctx->sfield_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1259 for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
1260 {
e60a6f7b 1261 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1262 FIELD_DECL, DECL_NAME (t), TREE_TYPE (t));
fd6481cf 1263 DECL_ABSTRACT_ORIGIN (sfield) = DECL_ABSTRACT_ORIGIN (t);
1264 insert_field_into_struct (ctx->srecord_type, sfield);
1265 splay_tree_insert (ctx->sfield_map,
1266 (splay_tree_key) DECL_ABSTRACT_ORIGIN (t),
1267 (splay_tree_value) sfield);
1268 }
1269 }
1270 sfield = field;
1271 insert_field_into_struct ((mask & 1) ? ctx->record_type
1272 : ctx->srecord_type, field);
1273 }
1e8e9920 1274
fd6481cf 1275 if (mask & 1)
1276 splay_tree_insert (ctx->field_map, (splay_tree_key) var,
1277 (splay_tree_value) field);
1278 if ((mask & 2) && ctx->sfield_map)
1279 splay_tree_insert (ctx->sfield_map, (splay_tree_key) var,
1280 (splay_tree_value) sfield);
1e8e9920 1281}
1282
1283static tree
1284install_var_local (tree var, omp_context *ctx)
1285{
1286 tree new_var = omp_copy_decl_1 (var, ctx);
1287 insert_decl_map (&ctx->cb, var, new_var);
1288 return new_var;
1289}
1290
1291/* Adjust the replacement for DECL in CTX for the new context. This means
1292 copying the DECL_VALUE_EXPR, and fixing up the type. */
1293
1294static void
1295fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug)
1296{
1297 tree new_decl, size;
1298
1299 new_decl = lookup_decl (decl, ctx);
1300
1301 TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb);
1302
1303 if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug)
1304 && DECL_HAS_VALUE_EXPR_P (decl))
1305 {
1306 tree ve = DECL_VALUE_EXPR (decl);
75a70cf9 1307 walk_tree (&ve, copy_tree_body_r, &ctx->cb, NULL);
1e8e9920 1308 SET_DECL_VALUE_EXPR (new_decl, ve);
1309 DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
1310 }
1311
1312 if (!TREE_CONSTANT (DECL_SIZE (new_decl)))
1313 {
1314 size = remap_decl (DECL_SIZE (decl), &ctx->cb);
1315 if (size == error_mark_node)
1316 size = TYPE_SIZE (TREE_TYPE (new_decl));
1317 DECL_SIZE (new_decl) = size;
1318
1319 size = remap_decl (DECL_SIZE_UNIT (decl), &ctx->cb);
1320 if (size == error_mark_node)
1321 size = TYPE_SIZE_UNIT (TREE_TYPE (new_decl));
1322 DECL_SIZE_UNIT (new_decl) = size;
1323 }
1324}
1325
1326/* The callback for remap_decl. Search all containing contexts for a
1327 mapping of the variable; this avoids having to duplicate the splay
1328 tree ahead of time. We know a mapping doesn't already exist in the
1329 given context. Create new mappings to implement default semantics. */
1330
1331static tree
1332omp_copy_decl (tree var, copy_body_data *cb)
1333{
1334 omp_context *ctx = (omp_context *) cb;
1335 tree new_var;
1336
1e8e9920 1337 if (TREE_CODE (var) == LABEL_DECL)
1338 {
e60a6f7b 1339 new_var = create_artificial_label (DECL_SOURCE_LOCATION (var));
773c5ba7 1340 DECL_CONTEXT (new_var) = current_function_decl;
1e8e9920 1341 insert_decl_map (&ctx->cb, var, new_var);
1342 return new_var;
1343 }
1344
fd6481cf 1345 while (!is_taskreg_ctx (ctx))
1e8e9920 1346 {
1347 ctx = ctx->outer;
1348 if (ctx == NULL)
1349 return var;
1350 new_var = maybe_lookup_decl (var, ctx);
1351 if (new_var)
1352 return new_var;
1353 }
1354
f49d7bb5 1355 if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn)
1356 return var;
1357
1e8e9920 1358 return error_mark_node;
1359}
1360
773c5ba7 1361
773c5ba7 1362/* Debugging dumps for parallel regions. */
1363void dump_omp_region (FILE *, struct omp_region *, int);
1364void debug_omp_region (struct omp_region *);
1365void debug_all_omp_regions (void);
1366
1367/* Dump the parallel region tree rooted at REGION. */
1368
1369void
1370dump_omp_region (FILE *file, struct omp_region *region, int indent)
1371{
61e47ac8 1372 fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index,
75a70cf9 1373 gimple_code_name[region->type]);
773c5ba7 1374
1375 if (region->inner)
1376 dump_omp_region (file, region->inner, indent + 4);
1377
61e47ac8 1378 if (region->cont)
1379 {
75a70cf9 1380 fprintf (file, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent, "",
61e47ac8 1381 region->cont->index);
1382 }
48e1416a 1383
773c5ba7 1384 if (region->exit)
75a70cf9 1385 fprintf (file, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent, "",
61e47ac8 1386 region->exit->index);
773c5ba7 1387 else
61e47ac8 1388 fprintf (file, "%*s[no exit marker]\n", indent, "");
773c5ba7 1389
1390 if (region->next)
61e47ac8 1391 dump_omp_region (file, region->next, indent);
773c5ba7 1392}
1393
4b987fac 1394DEBUG_FUNCTION void
773c5ba7 1395debug_omp_region (struct omp_region *region)
1396{
1397 dump_omp_region (stderr, region, 0);
1398}
1399
4b987fac 1400DEBUG_FUNCTION void
773c5ba7 1401debug_all_omp_regions (void)
1402{
1403 dump_omp_region (stderr, root_omp_region, 0);
1404}
1405
1406
1407/* Create a new parallel region starting at STMT inside region PARENT. */
1408
7740abd8 1409static struct omp_region *
75a70cf9 1410new_omp_region (basic_block bb, enum gimple_code type,
1411 struct omp_region *parent)
773c5ba7 1412{
4077bf7a 1413 struct omp_region *region = XCNEW (struct omp_region);
773c5ba7 1414
1415 region->outer = parent;
61e47ac8 1416 region->entry = bb;
1417 region->type = type;
773c5ba7 1418
1419 if (parent)
1420 {
1421 /* This is a nested region. Add it to the list of inner
1422 regions in PARENT. */
1423 region->next = parent->inner;
1424 parent->inner = region;
1425 }
61e47ac8 1426 else
773c5ba7 1427 {
1428 /* This is a toplevel region. Add it to the list of toplevel
1429 regions in ROOT_OMP_REGION. */
1430 region->next = root_omp_region;
1431 root_omp_region = region;
1432 }
61e47ac8 1433
1434 return region;
1435}
1436
1437/* Release the memory associated with the region tree rooted at REGION. */
1438
1439static void
1440free_omp_region_1 (struct omp_region *region)
1441{
1442 struct omp_region *i, *n;
1443
1444 for (i = region->inner; i ; i = n)
773c5ba7 1445 {
61e47ac8 1446 n = i->next;
1447 free_omp_region_1 (i);
773c5ba7 1448 }
1449
61e47ac8 1450 free (region);
1451}
773c5ba7 1452
61e47ac8 1453/* Release the memory for the entire omp region tree. */
1454
1455void
1456free_omp_regions (void)
1457{
1458 struct omp_region *r, *n;
1459 for (r = root_omp_region; r ; r = n)
1460 {
1461 n = r->next;
1462 free_omp_region_1 (r);
1463 }
1464 root_omp_region = NULL;
773c5ba7 1465}
1466
1467
1e8e9920 1468/* Create a new context, with OUTER_CTX being the surrounding context. */
1469
1470static omp_context *
75a70cf9 1471new_omp_context (gimple stmt, omp_context *outer_ctx)
1e8e9920 1472{
1473 omp_context *ctx = XCNEW (omp_context);
1474
1475 splay_tree_insert (all_contexts, (splay_tree_key) stmt,
1476 (splay_tree_value) ctx);
1477 ctx->stmt = stmt;
1478
1479 if (outer_ctx)
1480 {
1481 ctx->outer = outer_ctx;
1482 ctx->cb = outer_ctx->cb;
1483 ctx->cb.block = NULL;
1484 ctx->depth = outer_ctx->depth + 1;
ca4c3545 1485 ctx->reduction_map = outer_ctx->reduction_map;
1e8e9920 1486 }
1487 else
1488 {
1489 ctx->cb.src_fn = current_function_decl;
1490 ctx->cb.dst_fn = current_function_decl;
415d1b9a 1491 ctx->cb.src_node = cgraph_node::get (current_function_decl);
53f79206 1492 gcc_checking_assert (ctx->cb.src_node);
1e8e9920 1493 ctx->cb.dst_node = ctx->cb.src_node;
1494 ctx->cb.src_cfun = cfun;
1495 ctx->cb.copy_decl = omp_copy_decl;
e38def9c 1496 ctx->cb.eh_lp_nr = 0;
1e8e9920 1497 ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
1498 ctx->depth = 1;
1499 }
1500
06ecf488 1501 ctx->cb.decl_map = new hash_map<tree, tree>;
1e8e9920 1502
1503 return ctx;
1504}
1505
75a70cf9 1506static gimple_seq maybe_catch_exception (gimple_seq);
f6430caa 1507
1508/* Finalize task copyfn. */
1509
1510static void
1a91d914 1511finalize_task_copyfn (gomp_task *task_stmt)
f6430caa 1512{
1513 struct function *child_cfun;
9078126c 1514 tree child_fn;
e3a19533 1515 gimple_seq seq = NULL, new_seq;
1a91d914 1516 gbind *bind;
f6430caa 1517
75a70cf9 1518 child_fn = gimple_omp_task_copy_fn (task_stmt);
f6430caa 1519 if (child_fn == NULL_TREE)
1520 return;
1521
1522 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
82b40354 1523 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
f6430caa 1524
f6430caa 1525 push_cfun (child_cfun);
7e3aae05 1526 bind = gimplify_body (child_fn, false);
75a70cf9 1527 gimple_seq_add_stmt (&seq, bind);
1528 new_seq = maybe_catch_exception (seq);
1529 if (new_seq != seq)
1530 {
1531 bind = gimple_build_bind (NULL, new_seq, NULL);
e3a19533 1532 seq = NULL;
75a70cf9 1533 gimple_seq_add_stmt (&seq, bind);
1534 }
1535 gimple_set_body (child_fn, seq);
f6430caa 1536 pop_cfun ();
f6430caa 1537
82b40354 1538 /* Inform the callgraph about the new function. */
47300487 1539 cgraph_node *node = cgraph_node::get_create (child_fn);
1540 node->parallelized_function = 1;
415d1b9a 1541 cgraph_node::add_new_function (child_fn, false);
f6430caa 1542}
1543
1e8e9920 1544/* Destroy a omp_context data structures. Called through the splay tree
1545 value delete callback. */
1546
1547static void
1548delete_omp_context (splay_tree_value value)
1549{
1550 omp_context *ctx = (omp_context *) value;
1551
06ecf488 1552 delete ctx->cb.decl_map;
1e8e9920 1553
1554 if (ctx->field_map)
1555 splay_tree_delete (ctx->field_map);
fd6481cf 1556 if (ctx->sfield_map)
1557 splay_tree_delete (ctx->sfield_map);
42d49354 1558 /* Reduction map is copied to nested contexts, so only delete it in the
1559 owner. */
ca4c3545 1560 if (ctx->reduction_map
42d49354 1561 && gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET
1562 && is_gimple_omp_offloaded (ctx->stmt)
1563 && is_gimple_omp_oacc (ctx->stmt))
ca4c3545 1564 splay_tree_delete (ctx->reduction_map);
1e8e9920 1565
1566 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
1567 it produces corrupt debug information. */
1568 if (ctx->record_type)
1569 {
1570 tree t;
1767a056 1571 for (t = TYPE_FIELDS (ctx->record_type); t ; t = DECL_CHAIN (t))
1e8e9920 1572 DECL_ABSTRACT_ORIGIN (t) = NULL;
1573 }
fd6481cf 1574 if (ctx->srecord_type)
1575 {
1576 tree t;
1767a056 1577 for (t = TYPE_FIELDS (ctx->srecord_type); t ; t = DECL_CHAIN (t))
fd6481cf 1578 DECL_ABSTRACT_ORIGIN (t) = NULL;
1579 }
1e8e9920 1580
f6430caa 1581 if (is_task_ctx (ctx))
1a91d914 1582 finalize_task_copyfn (as_a <gomp_task *> (ctx->stmt));
f6430caa 1583
1e8e9920 1584 XDELETE (ctx);
1585}
1586
1587/* Fix up RECEIVER_DECL with a type that has been remapped to the child
1588 context. */
1589
1590static void
1591fixup_child_record_type (omp_context *ctx)
1592{
1593 tree f, type = ctx->record_type;
1594
1595 /* ??? It isn't sufficient to just call remap_type here, because
1596 variably_modified_type_p doesn't work the way we expect for
1597 record types. Testing each field for whether it needs remapping
1598 and creating a new record by hand works, however. */
1767a056 1599 for (f = TYPE_FIELDS (type); f ; f = DECL_CHAIN (f))
1e8e9920 1600 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
1601 break;
1602 if (f)
1603 {
1604 tree name, new_fields = NULL;
1605
1606 type = lang_hooks.types.make_type (RECORD_TYPE);
1607 name = DECL_NAME (TYPE_NAME (ctx->record_type));
e60a6f7b 1608 name = build_decl (DECL_SOURCE_LOCATION (ctx->receiver_decl),
1609 TYPE_DECL, name, type);
1e8e9920 1610 TYPE_NAME (type) = name;
1611
1767a056 1612 for (f = TYPE_FIELDS (ctx->record_type); f ; f = DECL_CHAIN (f))
1e8e9920 1613 {
1614 tree new_f = copy_node (f);
1615 DECL_CONTEXT (new_f) = type;
1616 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
1767a056 1617 DECL_CHAIN (new_f) = new_fields;
75a70cf9 1618 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &ctx->cb, NULL);
1619 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r,
1620 &ctx->cb, NULL);
1621 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
1622 &ctx->cb, NULL);
1e8e9920 1623 new_fields = new_f;
1624
1625 /* Arrange to be able to look up the receiver field
1626 given the sender field. */
1627 splay_tree_insert (ctx->field_map, (splay_tree_key) f,
1628 (splay_tree_value) new_f);
1629 }
1630 TYPE_FIELDS (type) = nreverse (new_fields);
1631 layout_type (type);
1632 }
1633
5455b100 1634 TREE_TYPE (ctx->receiver_decl)
1635 = build_qualified_type (build_reference_type (type), TYPE_QUAL_RESTRICT);
1e8e9920 1636}
1637
1638/* Instantiate decls as necessary in CTX to satisfy the data sharing
1639 specified by CLAUSES. */
1640
1641static void
1642scan_sharing_clauses (tree clauses, omp_context *ctx)
1643{
1644 tree c, decl;
1645 bool scan_array_reductions = false;
1646
1647 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1648 {
1649 bool by_ref;
1650
55d6e7cd 1651 switch (OMP_CLAUSE_CODE (c))
1e8e9920 1652 {
1653 case OMP_CLAUSE_PRIVATE:
1654 decl = OMP_CLAUSE_DECL (c);
fd6481cf 1655 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
1656 goto do_private;
1657 else if (!is_variable_sized (decl))
1e8e9920 1658 install_var_local (decl, ctx);
1659 break;
1660
1661 case OMP_CLAUSE_SHARED:
5fddcf34 1662 decl = OMP_CLAUSE_DECL (c);
bc7bff74 1663 /* Ignore shared directives in teams construct. */
1664 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
5fddcf34 1665 {
1666 /* Global variables don't need to be copied,
1667 the receiver side will use them directly. */
1668 tree odecl = maybe_lookup_decl_in_outer_ctx (decl, ctx);
1669 if (is_global_var (odecl))
1670 break;
1671 insert_decl_map (&ctx->cb, decl, odecl);
1672 break;
1673 }
fd6481cf 1674 gcc_assert (is_taskreg_ctx (ctx));
e7327393 1675 gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl))
1676 || !is_variable_sized (decl));
f49d7bb5 1677 /* Global variables don't need to be copied,
1678 the receiver side will use them directly. */
1679 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1680 break;
fd6481cf 1681 by_ref = use_pointer_for_field (decl, ctx);
1e8e9920 1682 if (! TREE_READONLY (decl)
1683 || TREE_ADDRESSABLE (decl)
1684 || by_ref
1685 || is_reference (decl))
1686 {
fd6481cf 1687 install_var_field (decl, by_ref, 3, ctx);
1e8e9920 1688 install_var_local (decl, ctx);
1689 break;
1690 }
1691 /* We don't need to copy const scalar vars back. */
55d6e7cd 1692 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
1e8e9920 1693 goto do_private;
1694
1695 case OMP_CLAUSE_LASTPRIVATE:
1696 /* Let the corresponding firstprivate clause create
1697 the variable. */
1698 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1699 break;
1700 /* FALLTHRU */
1701
1702 case OMP_CLAUSE_FIRSTPRIVATE:
ca4c3545 1703 if (is_gimple_omp_oacc (ctx->stmt))
1704 {
1705 sorry ("clause not supported yet");
1706 break;
1707 }
1708 /* FALLTHRU */
1e8e9920 1709 case OMP_CLAUSE_REDUCTION:
3d483a94 1710 case OMP_CLAUSE_LINEAR:
1e8e9920 1711 decl = OMP_CLAUSE_DECL (c);
1712 do_private:
1713 if (is_variable_sized (decl))
1e8e9920 1714 {
fd6481cf 1715 if (is_task_ctx (ctx))
1716 install_var_field (decl, false, 1, ctx);
1717 break;
1718 }
1719 else if (is_taskreg_ctx (ctx))
1720 {
1721 bool global
1722 = is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx));
e8a588af 1723 by_ref = use_pointer_for_field (decl, NULL);
fd6481cf 1724
1725 if (is_task_ctx (ctx)
1726 && (global || by_ref || is_reference (decl)))
1727 {
1728 install_var_field (decl, false, 1, ctx);
1729 if (!global)
1730 install_var_field (decl, by_ref, 2, ctx);
1731 }
1732 else if (!global)
1733 install_var_field (decl, by_ref, 3, ctx);
1e8e9920 1734 }
1735 install_var_local (decl, ctx);
ca4c3545 1736 if (is_gimple_omp_oacc (ctx->stmt)
1737 && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
1738 {
1739 /* Create a decl for the reduction array. */
1740 tree var = OMP_CLAUSE_DECL (c);
1741 tree type = get_base_type (var);
1742 tree ptype = build_pointer_type (type);
1743 tree array = create_tmp_var (ptype,
1744 oacc_get_reduction_array_id (var));
1745 omp_context *c = (ctx->field_map ? ctx : ctx->outer);
1746 install_var_field (array, true, 3, c);
1747 install_var_local (array, c);
1748
1749 /* Insert it into the current context. */
1750 splay_tree_insert (ctx->reduction_map, (splay_tree_key)
1751 oacc_get_reduction_array_id (var),
1752 (splay_tree_value) array);
1753 splay_tree_insert (ctx->reduction_map,
1754 (splay_tree_key) array,
1755 (splay_tree_value) array);
1756 }
1e8e9920 1757 break;
1758
bc7bff74 1759 case OMP_CLAUSE__LOOPTEMP_:
1760 gcc_assert (is_parallel_ctx (ctx));
1761 decl = OMP_CLAUSE_DECL (c);
1762 install_var_field (decl, false, 3, ctx);
1763 install_var_local (decl, ctx);
1764 break;
1765
1e8e9920 1766 case OMP_CLAUSE_COPYPRIVATE:
1e8e9920 1767 case OMP_CLAUSE_COPYIN:
1768 decl = OMP_CLAUSE_DECL (c);
e8a588af 1769 by_ref = use_pointer_for_field (decl, NULL);
fd6481cf 1770 install_var_field (decl, by_ref, 3, ctx);
1e8e9920 1771 break;
1772
1773 case OMP_CLAUSE_DEFAULT:
1774 ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
1775 break;
1776
2169f33b 1777 case OMP_CLAUSE_FINAL:
1e8e9920 1778 case OMP_CLAUSE_IF:
1779 case OMP_CLAUSE_NUM_THREADS:
bc7bff74 1780 case OMP_CLAUSE_NUM_TEAMS:
1781 case OMP_CLAUSE_THREAD_LIMIT:
1782 case OMP_CLAUSE_DEVICE:
1e8e9920 1783 case OMP_CLAUSE_SCHEDULE:
bc7bff74 1784 case OMP_CLAUSE_DIST_SCHEDULE:
1785 case OMP_CLAUSE_DEPEND:
40750995 1786 case OMP_CLAUSE__CILK_FOR_COUNT_:
ca4c3545 1787 case OMP_CLAUSE_NUM_GANGS:
1788 case OMP_CLAUSE_NUM_WORKERS:
1789 case OMP_CLAUSE_VECTOR_LENGTH:
1e8e9920 1790 if (ctx->outer)
75a70cf9 1791 scan_omp_op (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
1e8e9920 1792 break;
1793
bc7bff74 1794 case OMP_CLAUSE_TO:
1795 case OMP_CLAUSE_FROM:
1796 case OMP_CLAUSE_MAP:
1797 if (ctx->outer)
1798 scan_omp_op (&OMP_CLAUSE_SIZE (c), ctx->outer);
1799 decl = OMP_CLAUSE_DECL (c);
1800 /* Global variables with "omp declare target" attribute
1801 don't need to be copied, the receiver side will use them
1802 directly. */
1803 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1804 && DECL_P (decl)
1805 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
b0c5e347 1806 && varpool_node::get_create (decl)->offloadable)
bc7bff74 1807 break;
1808 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
ca4c3545 1809 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER)
bc7bff74 1810 {
ca4c3545 1811 /* Ignore GOMP_MAP_POINTER kind for arrays in regions that are
1812 not offloaded; there is nothing to map for those. */
1813 if (!is_gimple_omp_offloaded (ctx->stmt)
c1a114c2 1814 && !POINTER_TYPE_P (TREE_TYPE (decl))
1815 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
bc7bff74 1816 break;
1817 }
1818 if (DECL_P (decl))
1819 {
1820 if (DECL_SIZE (decl)
1821 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1822 {
1823 tree decl2 = DECL_VALUE_EXPR (decl);
1824 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1825 decl2 = TREE_OPERAND (decl2, 0);
1826 gcc_assert (DECL_P (decl2));
1827 install_var_field (decl2, true, 3, ctx);
1828 install_var_local (decl2, ctx);
1829 install_var_local (decl, ctx);
1830 }
1831 else
1832 {
1833 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
ca4c3545 1834 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
bc7bff74 1835 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
1836 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1837 install_var_field (decl, true, 7, ctx);
1838 else
1839 install_var_field (decl, true, 3, ctx);
ca4c3545 1840 if (is_gimple_omp_offloaded (ctx->stmt))
bc7bff74 1841 install_var_local (decl, ctx);
1842 }
1843 }
1844 else
1845 {
1846 tree base = get_base_address (decl);
1847 tree nc = OMP_CLAUSE_CHAIN (c);
1848 if (DECL_P (base)
1849 && nc != NULL_TREE
1850 && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
1851 && OMP_CLAUSE_DECL (nc) == base
ca4c3545 1852 && OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_POINTER
bc7bff74 1853 && integer_zerop (OMP_CLAUSE_SIZE (nc)))
1854 {
1855 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c) = 1;
1856 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (nc) = 1;
1857 }
1858 else
1859 {
691447ab 1860 if (ctx->outer)
1861 {
1862 scan_omp_op (&OMP_CLAUSE_DECL (c), ctx->outer);
1863 decl = OMP_CLAUSE_DECL (c);
1864 }
bc7bff74 1865 gcc_assert (!splay_tree_lookup (ctx->field_map,
1866 (splay_tree_key) decl));
1867 tree field
1868 = build_decl (OMP_CLAUSE_LOCATION (c),
1869 FIELD_DECL, NULL_TREE, ptr_type_node);
1870 DECL_ALIGN (field) = TYPE_ALIGN (ptr_type_node);
1871 insert_field_into_struct (ctx->record_type, field);
1872 splay_tree_insert (ctx->field_map, (splay_tree_key) decl,
1873 (splay_tree_value) field);
1874 }
1875 }
1876 break;
1877
1e8e9920 1878 case OMP_CLAUSE_NOWAIT:
1879 case OMP_CLAUSE_ORDERED:
fd6481cf 1880 case OMP_CLAUSE_COLLAPSE:
1881 case OMP_CLAUSE_UNTIED:
2169f33b 1882 case OMP_CLAUSE_MERGEABLE:
bc7bff74 1883 case OMP_CLAUSE_PROC_BIND:
3d483a94 1884 case OMP_CLAUSE_SAFELEN:
ca4c3545 1885 case OMP_CLAUSE_ASYNC:
1886 case OMP_CLAUSE_WAIT:
1887 case OMP_CLAUSE_GANG:
1888 case OMP_CLAUSE_WORKER:
1889 case OMP_CLAUSE_VECTOR:
1e8e9920 1890 break;
1891
bc7bff74 1892 case OMP_CLAUSE_ALIGNED:
1893 decl = OMP_CLAUSE_DECL (c);
1894 if (is_global_var (decl)
1895 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1896 install_var_local (decl, ctx);
1897 break;
1898
ca4c3545 1899 case OMP_CLAUSE_DEVICE_RESIDENT:
1900 case OMP_CLAUSE_USE_DEVICE:
1901 case OMP_CLAUSE__CACHE_:
1902 case OMP_CLAUSE_INDEPENDENT:
1903 case OMP_CLAUSE_AUTO:
1904 case OMP_CLAUSE_SEQ:
1905 sorry ("Clause not supported yet");
1906 break;
1907
1e8e9920 1908 default:
1909 gcc_unreachable ();
1910 }
1911 }
1912
1913 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1914 {
55d6e7cd 1915 switch (OMP_CLAUSE_CODE (c))
1e8e9920 1916 {
1917 case OMP_CLAUSE_LASTPRIVATE:
1918 /* Let the corresponding firstprivate clause create
1919 the variable. */
75a70cf9 1920 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
fd6481cf 1921 scan_array_reductions = true;
1e8e9920 1922 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1923 break;
1924 /* FALLTHRU */
1925
1e8e9920 1926 case OMP_CLAUSE_FIRSTPRIVATE:
ca4c3545 1927 if (is_gimple_omp_oacc (ctx->stmt))
1928 {
1929 sorry ("clause not supported yet");
1930 break;
1931 }
1932 /* FALLTHRU */
1933 case OMP_CLAUSE_PRIVATE:
1e8e9920 1934 case OMP_CLAUSE_REDUCTION:
3d483a94 1935 case OMP_CLAUSE_LINEAR:
1e8e9920 1936 decl = OMP_CLAUSE_DECL (c);
1937 if (is_variable_sized (decl))
1938 install_var_local (decl, ctx);
1939 fixup_remapped_decl (decl, ctx,
55d6e7cd 1940 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
1e8e9920 1941 && OMP_CLAUSE_PRIVATE_DEBUG (c));
55d6e7cd 1942 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1e8e9920 1943 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1944 scan_array_reductions = true;
2b536a17 1945 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
1946 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
1947 scan_array_reductions = true;
1e8e9920 1948 break;
1949
1950 case OMP_CLAUSE_SHARED:
bc7bff74 1951 /* Ignore shared directives in teams construct. */
1952 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1953 break;
1e8e9920 1954 decl = OMP_CLAUSE_DECL (c);
f49d7bb5 1955 if (! is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1956 fixup_remapped_decl (decl, ctx, false);
1e8e9920 1957 break;
1958
bc7bff74 1959 case OMP_CLAUSE_MAP:
ca4c3545 1960 if (!is_gimple_omp_offloaded (ctx->stmt))
bc7bff74 1961 break;
1962 decl = OMP_CLAUSE_DECL (c);
1963 if (DECL_P (decl)
1964 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
b0c5e347 1965 && varpool_node::get_create (decl)->offloadable)
bc7bff74 1966 break;
1967 if (DECL_P (decl))
1968 {
ca4c3545 1969 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
bc7bff74 1970 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
1971 && !COMPLETE_TYPE_P (TREE_TYPE (decl)))
1972 {
1973 tree new_decl = lookup_decl (decl, ctx);
1974 TREE_TYPE (new_decl)
1975 = remap_type (TREE_TYPE (decl), &ctx->cb);
1976 }
1977 else if (DECL_SIZE (decl)
1978 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1979 {
1980 tree decl2 = DECL_VALUE_EXPR (decl);
1981 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1982 decl2 = TREE_OPERAND (decl2, 0);
1983 gcc_assert (DECL_P (decl2));
1984 fixup_remapped_decl (decl2, ctx, false);
1985 fixup_remapped_decl (decl, ctx, true);
1986 }
1987 else
1988 fixup_remapped_decl (decl, ctx, false);
1989 }
1990 break;
1991
1e8e9920 1992 case OMP_CLAUSE_COPYPRIVATE:
1993 case OMP_CLAUSE_COPYIN:
1994 case OMP_CLAUSE_DEFAULT:
1995 case OMP_CLAUSE_IF:
1996 case OMP_CLAUSE_NUM_THREADS:
bc7bff74 1997 case OMP_CLAUSE_NUM_TEAMS:
1998 case OMP_CLAUSE_THREAD_LIMIT:
1999 case OMP_CLAUSE_DEVICE:
1e8e9920 2000 case OMP_CLAUSE_SCHEDULE:
bc7bff74 2001 case OMP_CLAUSE_DIST_SCHEDULE:
1e8e9920 2002 case OMP_CLAUSE_NOWAIT:
2003 case OMP_CLAUSE_ORDERED:
fd6481cf 2004 case OMP_CLAUSE_COLLAPSE:
2005 case OMP_CLAUSE_UNTIED:
2169f33b 2006 case OMP_CLAUSE_FINAL:
2007 case OMP_CLAUSE_MERGEABLE:
bc7bff74 2008 case OMP_CLAUSE_PROC_BIND:
3d483a94 2009 case OMP_CLAUSE_SAFELEN:
bc7bff74 2010 case OMP_CLAUSE_ALIGNED:
2011 case OMP_CLAUSE_DEPEND:
2012 case OMP_CLAUSE__LOOPTEMP_:
2013 case OMP_CLAUSE_TO:
2014 case OMP_CLAUSE_FROM:
40750995 2015 case OMP_CLAUSE__CILK_FOR_COUNT_:
ca4c3545 2016 case OMP_CLAUSE_ASYNC:
2017 case OMP_CLAUSE_WAIT:
2018 case OMP_CLAUSE_NUM_GANGS:
2019 case OMP_CLAUSE_NUM_WORKERS:
2020 case OMP_CLAUSE_VECTOR_LENGTH:
2021 case OMP_CLAUSE_GANG:
2022 case OMP_CLAUSE_WORKER:
2023 case OMP_CLAUSE_VECTOR:
2024 break;
2025
2026 case OMP_CLAUSE_DEVICE_RESIDENT:
2027 case OMP_CLAUSE_USE_DEVICE:
2028 case OMP_CLAUSE__CACHE_:
2029 case OMP_CLAUSE_INDEPENDENT:
2030 case OMP_CLAUSE_AUTO:
2031 case OMP_CLAUSE_SEQ:
2032 sorry ("Clause not supported yet");
1e8e9920 2033 break;
2034
2035 default:
2036 gcc_unreachable ();
2037 }
2038 }
2039
ca4c3545 2040 gcc_checking_assert (!scan_array_reductions
2041 || !is_gimple_omp_oacc (ctx->stmt));
1e8e9920 2042 if (scan_array_reductions)
2043 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
55d6e7cd 2044 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1e8e9920 2045 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2046 {
ab129075 2047 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
2048 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
1e8e9920 2049 }
fd6481cf 2050 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
75a70cf9 2051 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
ab129075 2052 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
2b536a17 2053 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
2054 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
2055 scan_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
1e8e9920 2056}
2057
40750995 2058/* Create a new name for omp child function. Returns an identifier. If
2059 IS_CILK_FOR is true then the suffix for the child function is
2060 "_cilk_for_fn." */
1e8e9920 2061
1e8e9920 2062static tree
40750995 2063create_omp_child_function_name (bool task_copy, bool is_cilk_for)
1e8e9920 2064{
40750995 2065 if (is_cilk_for)
2066 return clone_function_name (current_function_decl, "_cilk_for_fn");
2067 return clone_function_name (current_function_decl,
2068 task_copy ? "_omp_cpyfn" : "_omp_fn");
2069}
2070
2071/* Returns the type of the induction variable for the child function for
2072 _Cilk_for and the types for _high and _low variables based on TYPE. */
2073
2074static tree
2075cilk_for_check_loop_diff_type (tree type)
2076{
2077 if (TYPE_PRECISION (type) <= TYPE_PRECISION (uint32_type_node))
2078 {
2079 if (TYPE_UNSIGNED (type))
2080 return uint32_type_node;
2081 else
2082 return integer_type_node;
2083 }
2084 else
2085 {
2086 if (TYPE_UNSIGNED (type))
2087 return uint64_type_node;
2088 else
2089 return long_long_integer_type_node;
2090 }
1e8e9920 2091}
2092
2093/* Build a decl for the omp child function. It'll not contain a body
2094 yet, just the bare decl. */
2095
2096static void
fd6481cf 2097create_omp_child_function (omp_context *ctx, bool task_copy)
1e8e9920 2098{
2099 tree decl, type, name, t;
2100
40750995 2101 tree cilk_for_count
2102 = (flag_cilkplus && gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2103 ? find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
2104 OMP_CLAUSE__CILK_FOR_COUNT_) : NULL_TREE;
2105 tree cilk_var_type = NULL_TREE;
2106
2107 name = create_omp_child_function_name (task_copy,
2108 cilk_for_count != NULL_TREE);
fd6481cf 2109 if (task_copy)
2110 type = build_function_type_list (void_type_node, ptr_type_node,
2111 ptr_type_node, NULL_TREE);
40750995 2112 else if (cilk_for_count)
2113 {
2114 type = TREE_TYPE (OMP_CLAUSE_OPERAND (cilk_for_count, 0));
2115 cilk_var_type = cilk_for_check_loop_diff_type (type);
2116 type = build_function_type_list (void_type_node, ptr_type_node,
2117 cilk_var_type, cilk_var_type, NULL_TREE);
2118 }
fd6481cf 2119 else
2120 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
1e8e9920 2121
40750995 2122 decl = build_decl (gimple_location (ctx->stmt), FUNCTION_DECL, name, type);
1e8e9920 2123
ca4c3545 2124 gcc_checking_assert (!is_gimple_omp_oacc (ctx->stmt)
2125 || !task_copy);
fd6481cf 2126 if (!task_copy)
2127 ctx->cb.dst_fn = decl;
2128 else
75a70cf9 2129 gimple_omp_task_set_copy_fn (ctx->stmt, decl);
1e8e9920 2130
2131 TREE_STATIC (decl) = 1;
2132 TREE_USED (decl) = 1;
2133 DECL_ARTIFICIAL (decl) = 1;
2134 DECL_IGNORED_P (decl) = 0;
2135 TREE_PUBLIC (decl) = 0;
2136 DECL_UNINLINABLE (decl) = 1;
2137 DECL_EXTERNAL (decl) = 0;
2138 DECL_CONTEXT (decl) = NULL_TREE;
773c5ba7 2139 DECL_INITIAL (decl) = make_node (BLOCK);
b0c5e347 2140 if (cgraph_node::get (current_function_decl)->offloadable)
2141 cgraph_node::get_create (decl)->offloadable = 1;
bc7bff74 2142 else
2143 {
2144 omp_context *octx;
2145 for (octx = ctx; octx; octx = octx->outer)
ca4c3545 2146 if (is_gimple_omp_offloaded (octx->stmt))
bc7bff74 2147 {
b0c5e347 2148 cgraph_node::get_create (decl)->offloadable = 1;
7114ebdd 2149#ifdef ENABLE_OFFLOADING
b0c5e347 2150 g->have_offload = true;
7114ebdd 2151#endif
bc7bff74 2152 break;
2153 }
2154 }
1e8e9920 2155
ec12b31a 2156 if (cgraph_node::get_create (decl)->offloadable
2157 && !lookup_attribute ("omp declare target",
2158 DECL_ATTRIBUTES (current_function_decl)))
2159 DECL_ATTRIBUTES (decl)
2160 = tree_cons (get_identifier ("omp target entrypoint"),
2161 NULL_TREE, DECL_ATTRIBUTES (decl));
2162
e60a6f7b 2163 t = build_decl (DECL_SOURCE_LOCATION (decl),
2164 RESULT_DECL, NULL_TREE, void_type_node);
1e8e9920 2165 DECL_ARTIFICIAL (t) = 1;
2166 DECL_IGNORED_P (t) = 1;
8e5b4ed6 2167 DECL_CONTEXT (t) = decl;
1e8e9920 2168 DECL_RESULT (decl) = t;
2169
40750995 2170 /* _Cilk_for's child function requires two extra parameters called
2171 __low and __high that are set the by Cilk runtime when it calls this
2172 function. */
2173 if (cilk_for_count)
2174 {
2175 t = build_decl (DECL_SOURCE_LOCATION (decl),
2176 PARM_DECL, get_identifier ("__high"), cilk_var_type);
2177 DECL_ARTIFICIAL (t) = 1;
2178 DECL_NAMELESS (t) = 1;
2179 DECL_ARG_TYPE (t) = ptr_type_node;
2180 DECL_CONTEXT (t) = current_function_decl;
2181 TREE_USED (t) = 1;
2182 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2183 DECL_ARGUMENTS (decl) = t;
2184
2185 t = build_decl (DECL_SOURCE_LOCATION (decl),
2186 PARM_DECL, get_identifier ("__low"), cilk_var_type);
2187 DECL_ARTIFICIAL (t) = 1;
2188 DECL_NAMELESS (t) = 1;
2189 DECL_ARG_TYPE (t) = ptr_type_node;
2190 DECL_CONTEXT (t) = current_function_decl;
2191 TREE_USED (t) = 1;
2192 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2193 DECL_ARGUMENTS (decl) = t;
2194 }
2195
2196 tree data_name = get_identifier (".omp_data_i");
2197 t = build_decl (DECL_SOURCE_LOCATION (decl), PARM_DECL, data_name,
2198 ptr_type_node);
1e8e9920 2199 DECL_ARTIFICIAL (t) = 1;
84bfaaeb 2200 DECL_NAMELESS (t) = 1;
1e8e9920 2201 DECL_ARG_TYPE (t) = ptr_type_node;
773c5ba7 2202 DECL_CONTEXT (t) = current_function_decl;
1e8e9920 2203 TREE_USED (t) = 1;
40750995 2204 if (cilk_for_count)
2205 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
1e8e9920 2206 DECL_ARGUMENTS (decl) = t;
fd6481cf 2207 if (!task_copy)
2208 ctx->receiver_decl = t;
2209 else
2210 {
e60a6f7b 2211 t = build_decl (DECL_SOURCE_LOCATION (decl),
2212 PARM_DECL, get_identifier (".omp_data_o"),
fd6481cf 2213 ptr_type_node);
2214 DECL_ARTIFICIAL (t) = 1;
84bfaaeb 2215 DECL_NAMELESS (t) = 1;
fd6481cf 2216 DECL_ARG_TYPE (t) = ptr_type_node;
2217 DECL_CONTEXT (t) = current_function_decl;
2218 TREE_USED (t) = 1;
86f2ad37 2219 TREE_ADDRESSABLE (t) = 1;
1767a056 2220 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
fd6481cf 2221 DECL_ARGUMENTS (decl) = t;
2222 }
1e8e9920 2223
48e1416a 2224 /* Allocate memory for the function structure. The call to
773c5ba7 2225 allocate_struct_function clobbers CFUN, so we need to restore
1e8e9920 2226 it afterward. */
87d4aa85 2227 push_struct_function (decl);
75a70cf9 2228 cfun->function_end_locus = gimple_location (ctx->stmt);
87d4aa85 2229 pop_cfun ();
1e8e9920 2230}
2231
bc7bff74 2232/* Callback for walk_gimple_seq. Check if combined parallel
2233 contains gimple_omp_for_combined_into_p OMP_FOR. */
2234
2235static tree
2236find_combined_for (gimple_stmt_iterator *gsi_p,
2237 bool *handled_ops_p,
2238 struct walk_stmt_info *wi)
2239{
2240 gimple stmt = gsi_stmt (*gsi_p);
2241
2242 *handled_ops_p = true;
2243 switch (gimple_code (stmt))
2244 {
2245 WALK_SUBSTMTS;
2246
2247 case GIMPLE_OMP_FOR:
2248 if (gimple_omp_for_combined_into_p (stmt)
2249 && gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR)
2250 {
2251 wi->info = stmt;
2252 return integer_zero_node;
2253 }
2254 break;
2255 default:
2256 break;
2257 }
2258 return NULL;
2259}
2260
1e8e9920 2261/* Scan an OpenMP parallel directive. */
2262
2263static void
75a70cf9 2264scan_omp_parallel (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
1e8e9920 2265{
2266 omp_context *ctx;
2267 tree name;
1a91d914 2268 gomp_parallel *stmt = as_a <gomp_parallel *> (gsi_stmt (*gsi));
1e8e9920 2269
2270 /* Ignore parallel directives with empty bodies, unless there
2271 are copyin clauses. */
2272 if (optimize > 0
75a70cf9 2273 && empty_body_p (gimple_omp_body (stmt))
2274 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
2275 OMP_CLAUSE_COPYIN) == NULL)
1e8e9920 2276 {
75a70cf9 2277 gsi_replace (gsi, gimple_build_nop (), false);
1e8e9920 2278 return;
2279 }
2280
bc7bff74 2281 if (gimple_omp_parallel_combined_p (stmt))
2282 {
bc7bff74 2283 struct walk_stmt_info wi;
2284
2285 memset (&wi, 0, sizeof (wi));
2286 wi.val_only = true;
2287 walk_gimple_seq (gimple_omp_body (stmt),
2288 find_combined_for, NULL, &wi);
1a91d914 2289 if (wi.info)
bc7bff74 2290 {
1a91d914 2291 gomp_for *for_stmt = as_a <gomp_for *> ((gimple) wi.info);
bc7bff74 2292 struct omp_for_data fd;
2293 extract_omp_for_data (for_stmt, &fd, NULL);
2294 /* We need two temporaries with fd.loop.v type (istart/iend)
2295 and then (fd.collapse - 1) temporaries with the same
2296 type for count2 ... countN-1 vars if not constant. */
2297 size_t count = 2, i;
2298 tree type = fd.iter_type;
2299 if (fd.collapse > 1
2300 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
2301 count += fd.collapse - 1;
2302 for (i = 0; i < count; i++)
2303 {
f9e245b2 2304 tree temp = create_tmp_var (type);
bc7bff74 2305 tree c = build_omp_clause (UNKNOWN_LOCATION,
2306 OMP_CLAUSE__LOOPTEMP_);
691447ab 2307 insert_decl_map (&outer_ctx->cb, temp, temp);
bc7bff74 2308 OMP_CLAUSE_DECL (c) = temp;
2309 OMP_CLAUSE_CHAIN (c) = gimple_omp_parallel_clauses (stmt);
2310 gimple_omp_parallel_set_clauses (stmt, c);
2311 }
2312 }
2313 }
2314
75a70cf9 2315 ctx = new_omp_context (stmt, outer_ctx);
37eaded9 2316 taskreg_contexts.safe_push (ctx);
fd6481cf 2317 if (taskreg_nesting_level > 1)
773c5ba7 2318 ctx->is_nested = true;
1e8e9920 2319 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1e8e9920 2320 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2321 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
1e8e9920 2322 name = create_tmp_var_name (".omp_data_s");
e60a6f7b 2323 name = build_decl (gimple_location (stmt),
2324 TYPE_DECL, name, ctx->record_type);
84bfaaeb 2325 DECL_ARTIFICIAL (name) = 1;
2326 DECL_NAMELESS (name) = 1;
1e8e9920 2327 TYPE_NAME (ctx->record_type) = name;
240131b5 2328 TYPE_ARTIFICIAL (ctx->record_type) = 1;
fd6481cf 2329 create_omp_child_function (ctx, false);
75a70cf9 2330 gimple_omp_parallel_set_child_fn (stmt, ctx->cb.dst_fn);
1e8e9920 2331
75a70cf9 2332 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt), ctx);
ab129075 2333 scan_omp (gimple_omp_body_ptr (stmt), ctx);
1e8e9920 2334
2335 if (TYPE_FIELDS (ctx->record_type) == NULL)
2336 ctx->record_type = ctx->receiver_decl = NULL;
1e8e9920 2337}
2338
fd6481cf 2339/* Scan an OpenMP task directive. */
2340
2341static void
75a70cf9 2342scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
fd6481cf 2343{
2344 omp_context *ctx;
75a70cf9 2345 tree name, t;
1a91d914 2346 gomp_task *stmt = as_a <gomp_task *> (gsi_stmt (*gsi));
fd6481cf 2347
2348 /* Ignore task directives with empty bodies. */
2349 if (optimize > 0
75a70cf9 2350 && empty_body_p (gimple_omp_body (stmt)))
fd6481cf 2351 {
75a70cf9 2352 gsi_replace (gsi, gimple_build_nop (), false);
fd6481cf 2353 return;
2354 }
2355
75a70cf9 2356 ctx = new_omp_context (stmt, outer_ctx);
37eaded9 2357 taskreg_contexts.safe_push (ctx);
fd6481cf 2358 if (taskreg_nesting_level > 1)
2359 ctx->is_nested = true;
2360 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2361 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2362 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2363 name = create_tmp_var_name (".omp_data_s");
e60a6f7b 2364 name = build_decl (gimple_location (stmt),
2365 TYPE_DECL, name, ctx->record_type);
84bfaaeb 2366 DECL_ARTIFICIAL (name) = 1;
2367 DECL_NAMELESS (name) = 1;
fd6481cf 2368 TYPE_NAME (ctx->record_type) = name;
240131b5 2369 TYPE_ARTIFICIAL (ctx->record_type) = 1;
fd6481cf 2370 create_omp_child_function (ctx, false);
75a70cf9 2371 gimple_omp_task_set_child_fn (stmt, ctx->cb.dst_fn);
fd6481cf 2372
75a70cf9 2373 scan_sharing_clauses (gimple_omp_task_clauses (stmt), ctx);
fd6481cf 2374
2375 if (ctx->srecord_type)
2376 {
2377 name = create_tmp_var_name (".omp_data_a");
e60a6f7b 2378 name = build_decl (gimple_location (stmt),
2379 TYPE_DECL, name, ctx->srecord_type);
84bfaaeb 2380 DECL_ARTIFICIAL (name) = 1;
2381 DECL_NAMELESS (name) = 1;
fd6481cf 2382 TYPE_NAME (ctx->srecord_type) = name;
240131b5 2383 TYPE_ARTIFICIAL (ctx->srecord_type) = 1;
fd6481cf 2384 create_omp_child_function (ctx, true);
2385 }
2386
ab129075 2387 scan_omp (gimple_omp_body_ptr (stmt), ctx);
fd6481cf 2388
2389 if (TYPE_FIELDS (ctx->record_type) == NULL)
2390 {
2391 ctx->record_type = ctx->receiver_decl = NULL;
75a70cf9 2392 t = build_int_cst (long_integer_type_node, 0);
2393 gimple_omp_task_set_arg_size (stmt, t);
2394 t = build_int_cst (long_integer_type_node, 1);
2395 gimple_omp_task_set_arg_align (stmt, t);
fd6481cf 2396 }
37eaded9 2397}
2398
2399
2400/* If any decls have been made addressable during scan_omp,
2401 adjust their fields if needed, and layout record types
2402 of parallel/task constructs. */
2403
2404static void
2405finish_taskreg_scan (omp_context *ctx)
2406{
2407 if (ctx->record_type == NULL_TREE)
2408 return;
2409
2410 /* If any task_shared_vars were needed, verify all
2411 OMP_CLAUSE_SHARED clauses on GIMPLE_OMP_{PARALLEL,TASK}
2412 statements if use_pointer_for_field hasn't changed
2413 because of that. If it did, update field types now. */
2414 if (task_shared_vars)
2415 {
2416 tree c;
2417
2418 for (c = gimple_omp_taskreg_clauses (ctx->stmt);
2419 c; c = OMP_CLAUSE_CHAIN (c))
2420 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED)
2421 {
2422 tree decl = OMP_CLAUSE_DECL (c);
2423
2424 /* Global variables don't need to be copied,
2425 the receiver side will use them directly. */
2426 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
2427 continue;
2428 if (!bitmap_bit_p (task_shared_vars, DECL_UID (decl))
2429 || !use_pointer_for_field (decl, ctx))
2430 continue;
2431 tree field = lookup_field (decl, ctx);
2432 if (TREE_CODE (TREE_TYPE (field)) == POINTER_TYPE
2433 && TREE_TYPE (TREE_TYPE (field)) == TREE_TYPE (decl))
2434 continue;
2435 TREE_TYPE (field) = build_pointer_type (TREE_TYPE (decl));
2436 TREE_THIS_VOLATILE (field) = 0;
2437 DECL_USER_ALIGN (field) = 0;
2438 DECL_ALIGN (field) = TYPE_ALIGN (TREE_TYPE (field));
2439 if (TYPE_ALIGN (ctx->record_type) < DECL_ALIGN (field))
2440 TYPE_ALIGN (ctx->record_type) = DECL_ALIGN (field);
2441 if (ctx->srecord_type)
2442 {
2443 tree sfield = lookup_sfield (decl, ctx);
2444 TREE_TYPE (sfield) = TREE_TYPE (field);
2445 TREE_THIS_VOLATILE (sfield) = 0;
2446 DECL_USER_ALIGN (sfield) = 0;
2447 DECL_ALIGN (sfield) = DECL_ALIGN (field);
2448 if (TYPE_ALIGN (ctx->srecord_type) < DECL_ALIGN (sfield))
2449 TYPE_ALIGN (ctx->srecord_type) = DECL_ALIGN (sfield);
2450 }
2451 }
2452 }
2453
2454 if (gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2455 {
2456 layout_type (ctx->record_type);
2457 fixup_child_record_type (ctx);
2458 }
fd6481cf 2459 else
2460 {
37eaded9 2461 location_t loc = gimple_location (ctx->stmt);
fd6481cf 2462 tree *p, vla_fields = NULL_TREE, *q = &vla_fields;
2463 /* Move VLA fields to the end. */
2464 p = &TYPE_FIELDS (ctx->record_type);
2465 while (*p)
2466 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p))
2467 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p))))
2468 {
2469 *q = *p;
2470 *p = TREE_CHAIN (*p);
2471 TREE_CHAIN (*q) = NULL_TREE;
2472 q = &TREE_CHAIN (*q);
2473 }
2474 else
1767a056 2475 p = &DECL_CHAIN (*p);
fd6481cf 2476 *p = vla_fields;
2477 layout_type (ctx->record_type);
2478 fixup_child_record_type (ctx);
2479 if (ctx->srecord_type)
2480 layout_type (ctx->srecord_type);
37eaded9 2481 tree t = fold_convert_loc (loc, long_integer_type_node,
2482 TYPE_SIZE_UNIT (ctx->record_type));
2483 gimple_omp_task_set_arg_size (ctx->stmt, t);
75a70cf9 2484 t = build_int_cst (long_integer_type_node,
fd6481cf 2485 TYPE_ALIGN_UNIT (ctx->record_type));
37eaded9 2486 gimple_omp_task_set_arg_align (ctx->stmt, t);
fd6481cf 2487 }
2488}
2489
1e8e9920 2490
ca4c3545 2491static omp_context *
2492enclosing_target_ctx (omp_context *ctx)
2493{
2494 while (ctx != NULL
2495 && gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET)
2496 ctx = ctx->outer;
2497 gcc_assert (ctx != NULL);
2498 return ctx;
2499}
2500
2501static bool
2502oacc_loop_or_target_p (gimple stmt)
2503{
2504 enum gimple_code outer_type = gimple_code (stmt);
2505 return ((outer_type == GIMPLE_OMP_TARGET
2506 && ((gimple_omp_target_kind (stmt)
2507 == GF_OMP_TARGET_KIND_OACC_PARALLEL)
2508 || (gimple_omp_target_kind (stmt)
2509 == GF_OMP_TARGET_KIND_OACC_KERNELS)))
2510 || (outer_type == GIMPLE_OMP_FOR
2511 && gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_OACC_LOOP));
2512}
2513
2514/* Scan a GIMPLE_OMP_FOR. */
1e8e9920 2515
2516static void
1a91d914 2517scan_omp_for (gomp_for *stmt, omp_context *outer_ctx)
1e8e9920 2518{
ca4c3545 2519 enum gimple_code outer_type = GIMPLE_ERROR_MARK;
773c5ba7 2520 omp_context *ctx;
75a70cf9 2521 size_t i;
ca4c3545 2522 tree clauses = gimple_omp_for_clauses (stmt);
2523
2524 if (outer_ctx)
2525 outer_type = gimple_code (outer_ctx->stmt);
1e8e9920 2526
773c5ba7 2527 ctx = new_omp_context (stmt, outer_ctx);
1e8e9920 2528
ca4c3545 2529 if (is_gimple_omp_oacc (stmt))
2530 {
2531 if (outer_ctx && outer_type == GIMPLE_OMP_FOR)
2532 ctx->gwv_this = outer_ctx->gwv_this;
2533 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2534 {
2535 int val;
2536 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_GANG)
2537 val = MASK_GANG;
2538 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_WORKER)
2539 val = MASK_WORKER;
2540 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_VECTOR)
2541 val = MASK_VECTOR;
2542 else
2543 continue;
2544 ctx->gwv_this |= val;
2545 if (!outer_ctx)
2546 {
2547 /* Skip; not nested inside a region. */
2548 continue;
2549 }
2550 if (!oacc_loop_or_target_p (outer_ctx->stmt))
2551 {
2552 /* Skip; not nested inside an OpenACC region. */
2553 continue;
2554 }
2555 if (outer_type == GIMPLE_OMP_FOR)
2556 outer_ctx->gwv_below |= val;
2557 if (OMP_CLAUSE_OPERAND (c, 0) != NULL_TREE)
2558 {
2559 omp_context *enclosing = enclosing_target_ctx (outer_ctx);
2560 if (gimple_omp_target_kind (enclosing->stmt)
2561 == GF_OMP_TARGET_KIND_OACC_PARALLEL)
2562 error_at (gimple_location (stmt),
2563 "no arguments allowed to gang, worker and vector clauses inside parallel");
2564 }
2565 }
2566 }
2567
2568 scan_sharing_clauses (clauses, ctx);
1e8e9920 2569
ab129075 2570 scan_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
75a70cf9 2571 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
fd6481cf 2572 {
75a70cf9 2573 scan_omp_op (gimple_omp_for_index_ptr (stmt, i), ctx);
2574 scan_omp_op (gimple_omp_for_initial_ptr (stmt, i), ctx);
2575 scan_omp_op (gimple_omp_for_final_ptr (stmt, i), ctx);
2576 scan_omp_op (gimple_omp_for_incr_ptr (stmt, i), ctx);
fd6481cf 2577 }
ab129075 2578 scan_omp (gimple_omp_body_ptr (stmt), ctx);
ca4c3545 2579
2580 if (is_gimple_omp_oacc (stmt))
2581 {
2582 if (ctx->gwv_this & ctx->gwv_below)
2583 error_at (gimple_location (stmt),
2584 "gang, worker and vector may occur only once in a loop nest");
2585 else if (ctx->gwv_below != 0
2586 && ctx->gwv_this > ctx->gwv_below)
2587 error_at (gimple_location (stmt),
2588 "gang, worker and vector must occur in this order in a loop nest");
2589 if (outer_ctx && outer_type == GIMPLE_OMP_FOR)
2590 outer_ctx->gwv_below |= ctx->gwv_below;
2591 }
1e8e9920 2592}
2593
2594/* Scan an OpenMP sections directive. */
2595
2596static void
1a91d914 2597scan_omp_sections (gomp_sections *stmt, omp_context *outer_ctx)
1e8e9920 2598{
1e8e9920 2599 omp_context *ctx;
2600
2601 ctx = new_omp_context (stmt, outer_ctx);
75a70cf9 2602 scan_sharing_clauses (gimple_omp_sections_clauses (stmt), ctx);
ab129075 2603 scan_omp (gimple_omp_body_ptr (stmt), ctx);
1e8e9920 2604}
2605
2606/* Scan an OpenMP single directive. */
2607
2608static void
1a91d914 2609scan_omp_single (gomp_single *stmt, omp_context *outer_ctx)
1e8e9920 2610{
1e8e9920 2611 omp_context *ctx;
2612 tree name;
2613
2614 ctx = new_omp_context (stmt, outer_ctx);
2615 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2616 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2617 name = create_tmp_var_name (".omp_copy_s");
e60a6f7b 2618 name = build_decl (gimple_location (stmt),
2619 TYPE_DECL, name, ctx->record_type);
1e8e9920 2620 TYPE_NAME (ctx->record_type) = name;
2621
75a70cf9 2622 scan_sharing_clauses (gimple_omp_single_clauses (stmt), ctx);
ab129075 2623 scan_omp (gimple_omp_body_ptr (stmt), ctx);
1e8e9920 2624
2625 if (TYPE_FIELDS (ctx->record_type) == NULL)
2626 ctx->record_type = NULL;
2627 else
2628 layout_type (ctx->record_type);
2629}
2630
ca4c3545 2631/* Scan a GIMPLE_OMP_TARGET. */
bc7bff74 2632
2633static void
1a91d914 2634scan_omp_target (gomp_target *stmt, omp_context *outer_ctx)
bc7bff74 2635{
2636 omp_context *ctx;
2637 tree name;
ca4c3545 2638 bool offloaded = is_gimple_omp_offloaded (stmt);
2639 tree clauses = gimple_omp_target_clauses (stmt);
bc7bff74 2640
2641 ctx = new_omp_context (stmt, outer_ctx);
2642 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2643 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2644 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2645 name = create_tmp_var_name (".omp_data_t");
2646 name = build_decl (gimple_location (stmt),
2647 TYPE_DECL, name, ctx->record_type);
2648 DECL_ARTIFICIAL (name) = 1;
2649 DECL_NAMELESS (name) = 1;
2650 TYPE_NAME (ctx->record_type) = name;
240131b5 2651 TYPE_ARTIFICIAL (ctx->record_type) = 1;
ca4c3545 2652 if (offloaded)
bc7bff74 2653 {
ca4c3545 2654 if (is_gimple_omp_oacc (stmt))
2655 ctx->reduction_map = splay_tree_new (splay_tree_compare_pointers,
2656 0, 0);
2657
bc7bff74 2658 create_omp_child_function (ctx, false);
2659 gimple_omp_target_set_child_fn (stmt, ctx->cb.dst_fn);
2660 }
2661
ca4c3545 2662 if (is_gimple_omp_oacc (stmt))
2663 {
2664 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2665 {
2666 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NUM_GANGS)
2667 ctx->gwv_this |= MASK_GANG;
2668 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NUM_WORKERS)
2669 ctx->gwv_this |= MASK_WORKER;
2670 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_VECTOR_LENGTH)
2671 ctx->gwv_this |= MASK_VECTOR;
2672 }
2673 }
2674
2675 scan_sharing_clauses (clauses, ctx);
bc7bff74 2676 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2677
2678 if (TYPE_FIELDS (ctx->record_type) == NULL)
2679 ctx->record_type = ctx->receiver_decl = NULL;
2680 else
2681 {
2682 TYPE_FIELDS (ctx->record_type)
2683 = nreverse (TYPE_FIELDS (ctx->record_type));
2684#ifdef ENABLE_CHECKING
2685 tree field;
2686 unsigned int align = DECL_ALIGN (TYPE_FIELDS (ctx->record_type));
2687 for (field = TYPE_FIELDS (ctx->record_type);
2688 field;
2689 field = DECL_CHAIN (field))
2690 gcc_assert (DECL_ALIGN (field) == align);
2691#endif
2692 layout_type (ctx->record_type);
ca4c3545 2693 if (offloaded)
bc7bff74 2694 fixup_child_record_type (ctx);
2695 }
2696}
2697
2698/* Scan an OpenMP teams directive. */
2699
2700static void
1a91d914 2701scan_omp_teams (gomp_teams *stmt, omp_context *outer_ctx)
bc7bff74 2702{
2703 omp_context *ctx = new_omp_context (stmt, outer_ctx);
2704 scan_sharing_clauses (gimple_omp_teams_clauses (stmt), ctx);
2705 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2706}
1e8e9920 2707
ca4c3545 2708/* Check nesting restrictions. */
ab129075 2709static bool
2710check_omp_nesting_restrictions (gimple stmt, omp_context *ctx)
c1d127dd 2711{
ca4c3545 2712 /* No nesting of non-OpenACC STMT (that is, an OpenMP one, or a GOMP builtin)
2713 inside an OpenACC CTX. */
2714 if (!(is_gimple_omp (stmt)
2715 && is_gimple_omp_oacc (stmt)))
2716 {
2717 for (omp_context *ctx_ = ctx; ctx_ != NULL; ctx_ = ctx_->outer)
2718 if (is_gimple_omp (ctx_->stmt)
2719 && is_gimple_omp_oacc (ctx_->stmt))
2720 {
2721 error_at (gimple_location (stmt),
2722 "non-OpenACC construct inside of OpenACC region");
2723 return false;
2724 }
2725 }
2726
3d483a94 2727 if (ctx != NULL)
2728 {
2729 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
10c55644 2730 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3d483a94 2731 {
2732 error_at (gimple_location (stmt),
2733 "OpenMP constructs may not be nested inside simd region");
2734 return false;
2735 }
bc7bff74 2736 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
2737 {
2738 if ((gimple_code (stmt) != GIMPLE_OMP_FOR
2739 || (gimple_omp_for_kind (stmt)
2740 != GF_OMP_FOR_KIND_DISTRIBUTE))
2741 && gimple_code (stmt) != GIMPLE_OMP_PARALLEL)
2742 {
2743 error_at (gimple_location (stmt),
2744 "only distribute or parallel constructs are allowed to "
2745 "be closely nested inside teams construct");
2746 return false;
2747 }
2748 }
3d483a94 2749 }
75a70cf9 2750 switch (gimple_code (stmt))
c1d127dd 2751 {
75a70cf9 2752 case GIMPLE_OMP_FOR:
10c55644 2753 if (gimple_omp_for_kind (stmt) & GF_OMP_FOR_SIMD)
3d483a94 2754 return true;
bc7bff74 2755 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
2756 {
2757 if (ctx != NULL && gimple_code (ctx->stmt) != GIMPLE_OMP_TEAMS)
2758 {
2759 error_at (gimple_location (stmt),
2760 "distribute construct must be closely nested inside "
2761 "teams construct");
2762 return false;
2763 }
2764 return true;
2765 }
2766 /* FALLTHRU */
2767 case GIMPLE_CALL:
2768 if (is_gimple_call (stmt)
2769 && (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2770 == BUILT_IN_GOMP_CANCEL
2771 || DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2772 == BUILT_IN_GOMP_CANCELLATION_POINT))
2773 {
2774 const char *bad = NULL;
2775 const char *kind = NULL;
2776 if (ctx == NULL)
2777 {
2778 error_at (gimple_location (stmt), "orphaned %qs construct",
2779 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2780 == BUILT_IN_GOMP_CANCEL
2781 ? "#pragma omp cancel"
2782 : "#pragma omp cancellation point");
2783 return false;
2784 }
6b409616 2785 switch (tree_fits_shwi_p (gimple_call_arg (stmt, 0))
2786 ? tree_to_shwi (gimple_call_arg (stmt, 0))
bc7bff74 2787 : 0)
2788 {
2789 case 1:
2790 if (gimple_code (ctx->stmt) != GIMPLE_OMP_PARALLEL)
2791 bad = "#pragma omp parallel";
2792 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2793 == BUILT_IN_GOMP_CANCEL
2794 && !integer_zerop (gimple_call_arg (stmt, 1)))
2795 ctx->cancellable = true;
2796 kind = "parallel";
2797 break;
2798 case 2:
2799 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
2800 || gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR)
2801 bad = "#pragma omp for";
2802 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2803 == BUILT_IN_GOMP_CANCEL
2804 && !integer_zerop (gimple_call_arg (stmt, 1)))
2805 {
2806 ctx->cancellable = true;
2807 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2808 OMP_CLAUSE_NOWAIT))
2809 warning_at (gimple_location (stmt), 0,
2810 "%<#pragma omp cancel for%> inside "
2811 "%<nowait%> for construct");
2812 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2813 OMP_CLAUSE_ORDERED))
2814 warning_at (gimple_location (stmt), 0,
2815 "%<#pragma omp cancel for%> inside "
2816 "%<ordered%> for construct");
2817 }
2818 kind = "for";
2819 break;
2820 case 4:
2821 if (gimple_code (ctx->stmt) != GIMPLE_OMP_SECTIONS
2822 && gimple_code (ctx->stmt) != GIMPLE_OMP_SECTION)
2823 bad = "#pragma omp sections";
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 if (gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS)
2829 {
2830 ctx->cancellable = true;
2831 if (find_omp_clause (gimple_omp_sections_clauses
2832 (ctx->stmt),
2833 OMP_CLAUSE_NOWAIT))
2834 warning_at (gimple_location (stmt), 0,
2835 "%<#pragma omp cancel sections%> inside "
2836 "%<nowait%> sections construct");
2837 }
2838 else
2839 {
2840 gcc_assert (ctx->outer
2841 && gimple_code (ctx->outer->stmt)
2842 == GIMPLE_OMP_SECTIONS);
2843 ctx->outer->cancellable = true;
2844 if (find_omp_clause (gimple_omp_sections_clauses
2845 (ctx->outer->stmt),
2846 OMP_CLAUSE_NOWAIT))
2847 warning_at (gimple_location (stmt), 0,
2848 "%<#pragma omp cancel sections%> inside "
2849 "%<nowait%> sections construct");
2850 }
2851 }
2852 kind = "sections";
2853 break;
2854 case 8:
2855 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TASK)
2856 bad = "#pragma omp task";
2857 else
2858 ctx->cancellable = true;
2859 kind = "taskgroup";
2860 break;
2861 default:
2862 error_at (gimple_location (stmt), "invalid arguments");
2863 return false;
2864 }
2865 if (bad)
2866 {
2867 error_at (gimple_location (stmt),
2868 "%<%s %s%> construct not closely nested inside of %qs",
2869 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2870 == BUILT_IN_GOMP_CANCEL
2871 ? "#pragma omp cancel"
2872 : "#pragma omp cancellation point", kind, bad);
2873 return false;
2874 }
2875 }
3d483a94 2876 /* FALLTHRU */
75a70cf9 2877 case GIMPLE_OMP_SECTIONS:
2878 case GIMPLE_OMP_SINGLE:
c1d127dd 2879 for (; ctx != NULL; ctx = ctx->outer)
75a70cf9 2880 switch (gimple_code (ctx->stmt))
c1d127dd 2881 {
75a70cf9 2882 case GIMPLE_OMP_FOR:
2883 case GIMPLE_OMP_SECTIONS:
2884 case GIMPLE_OMP_SINGLE:
2885 case GIMPLE_OMP_ORDERED:
2886 case GIMPLE_OMP_MASTER:
2887 case GIMPLE_OMP_TASK:
bc7bff74 2888 case GIMPLE_OMP_CRITICAL:
75a70cf9 2889 if (is_gimple_call (stmt))
fd6481cf 2890 {
bc7bff74 2891 if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2892 != BUILT_IN_GOMP_BARRIER)
2893 return true;
ab129075 2894 error_at (gimple_location (stmt),
2895 "barrier region may not be closely nested inside "
2896 "of work-sharing, critical, ordered, master or "
2897 "explicit task region");
2898 return false;
fd6481cf 2899 }
ab129075 2900 error_at (gimple_location (stmt),
2901 "work-sharing region may not be closely nested inside "
2902 "of work-sharing, critical, ordered, master or explicit "
2903 "task region");
2904 return false;
75a70cf9 2905 case GIMPLE_OMP_PARALLEL:
ab129075 2906 return true;
c1d127dd 2907 default:
2908 break;
2909 }
2910 break;
75a70cf9 2911 case GIMPLE_OMP_MASTER:
c1d127dd 2912 for (; ctx != NULL; ctx = ctx->outer)
75a70cf9 2913 switch (gimple_code (ctx->stmt))
c1d127dd 2914 {
75a70cf9 2915 case GIMPLE_OMP_FOR:
2916 case GIMPLE_OMP_SECTIONS:
2917 case GIMPLE_OMP_SINGLE:
2918 case GIMPLE_OMP_TASK:
ab129075 2919 error_at (gimple_location (stmt),
2920 "master region may not be closely nested inside "
2921 "of work-sharing or explicit task region");
2922 return false;
75a70cf9 2923 case GIMPLE_OMP_PARALLEL:
ab129075 2924 return true;
c1d127dd 2925 default:
2926 break;
2927 }
2928 break;
75a70cf9 2929 case GIMPLE_OMP_ORDERED:
c1d127dd 2930 for (; ctx != NULL; ctx = ctx->outer)
75a70cf9 2931 switch (gimple_code (ctx->stmt))
c1d127dd 2932 {
75a70cf9 2933 case GIMPLE_OMP_CRITICAL:
2934 case GIMPLE_OMP_TASK:
ab129075 2935 error_at (gimple_location (stmt),
2936 "ordered region may not be closely nested inside "
2937 "of critical or explicit task region");
2938 return false;
75a70cf9 2939 case GIMPLE_OMP_FOR:
2940 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
c1d127dd 2941 OMP_CLAUSE_ORDERED) == NULL)
ab129075 2942 {
2943 error_at (gimple_location (stmt),
2944 "ordered region must be closely nested inside "
c1d127dd 2945 "a loop region with an ordered clause");
ab129075 2946 return false;
2947 }
2948 return true;
75a70cf9 2949 case GIMPLE_OMP_PARALLEL:
bc7bff74 2950 error_at (gimple_location (stmt),
2951 "ordered region must be closely nested inside "
2952 "a loop region with an ordered clause");
2953 return false;
c1d127dd 2954 default:
2955 break;
2956 }
2957 break;
75a70cf9 2958 case GIMPLE_OMP_CRITICAL:
1a91d914 2959 {
2960 tree this_stmt_name
2961 = gimple_omp_critical_name (as_a <gomp_critical *> (stmt));
2962 for (; ctx != NULL; ctx = ctx->outer)
2963 if (gomp_critical *other_crit
2964 = dyn_cast <gomp_critical *> (ctx->stmt))
2965 if (this_stmt_name == gimple_omp_critical_name (other_crit))
2966 {
2967 error_at (gimple_location (stmt),
2968 "critical region may not be nested inside a critical "
2969 "region with the same name");
2970 return false;
2971 }
2972 }
c1d127dd 2973 break;
bc7bff74 2974 case GIMPLE_OMP_TEAMS:
2975 if (ctx == NULL
2976 || gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET
2977 || gimple_omp_target_kind (ctx->stmt) != GF_OMP_TARGET_KIND_REGION)
2978 {
2979 error_at (gimple_location (stmt),
2980 "teams construct not closely nested inside of target "
2981 "region");
2982 return false;
2983 }
2984 break;
691447ab 2985 case GIMPLE_OMP_TARGET:
2986 for (; ctx != NULL; ctx = ctx->outer)
ca4c3545 2987 {
2988 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET)
2989 {
2990 if (is_gimple_omp (stmt)
2991 && is_gimple_omp_oacc (stmt)
2992 && is_gimple_omp (ctx->stmt))
2993 {
2994 error_at (gimple_location (stmt),
2995 "OpenACC construct inside of non-OpenACC region");
2996 return false;
2997 }
2998 continue;
2999 }
3000
3001 const char *stmt_name, *ctx_stmt_name;
3002 switch (gimple_omp_target_kind (stmt))
3003 {
3004 case GF_OMP_TARGET_KIND_REGION: stmt_name = "target"; break;
3005 case GF_OMP_TARGET_KIND_DATA: stmt_name = "target data"; break;
3006 case GF_OMP_TARGET_KIND_UPDATE: stmt_name = "target update"; break;
3007 case GF_OMP_TARGET_KIND_OACC_PARALLEL: stmt_name = "parallel"; break;
3008 case GF_OMP_TARGET_KIND_OACC_KERNELS: stmt_name = "kernels"; break;
3009 case GF_OMP_TARGET_KIND_OACC_DATA: stmt_name = "data"; break;
3010 case GF_OMP_TARGET_KIND_OACC_UPDATE: stmt_name = "update"; break;
3011 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA: stmt_name = "enter/exit data"; break;
3012 default: gcc_unreachable ();
3013 }
3014 switch (gimple_omp_target_kind (ctx->stmt))
3015 {
3016 case GF_OMP_TARGET_KIND_REGION: ctx_stmt_name = "target"; break;
3017 case GF_OMP_TARGET_KIND_DATA: ctx_stmt_name = "target data"; break;
3018 case GF_OMP_TARGET_KIND_OACC_PARALLEL: ctx_stmt_name = "parallel"; break;
3019 case GF_OMP_TARGET_KIND_OACC_KERNELS: ctx_stmt_name = "kernels"; break;
3020 case GF_OMP_TARGET_KIND_OACC_DATA: ctx_stmt_name = "data"; break;
3021 default: gcc_unreachable ();
3022 }
3023
3024 /* OpenACC/OpenMP mismatch? */
3025 if (is_gimple_omp_oacc (stmt)
3026 != is_gimple_omp_oacc (ctx->stmt))
3027 {
3028 error_at (gimple_location (stmt),
3029 "%s %s construct inside of %s %s region",
3030 (is_gimple_omp_oacc (stmt)
3031 ? "OpenACC" : "OpenMP"), stmt_name,
3032 (is_gimple_omp_oacc (ctx->stmt)
3033 ? "OpenACC" : "OpenMP"), ctx_stmt_name);
3034 return false;
3035 }
3036 if (is_gimple_omp_offloaded (ctx->stmt))
3037 {
3038 /* No GIMPLE_OMP_TARGET inside offloaded OpenACC CTX. */
3039 if (is_gimple_omp_oacc (ctx->stmt))
3040 {
3041 error_at (gimple_location (stmt),
3042 "%s construct inside of %s region",
3043 stmt_name, ctx_stmt_name);
3044 return false;
3045 }
3046 else
3047 {
3048 gcc_checking_assert (!is_gimple_omp_oacc (stmt));
3049 warning_at (gimple_location (stmt), 0,
3050 "%s construct inside of %s region",
3051 stmt_name, ctx_stmt_name);
3052 }
3053 }
3054 }
691447ab 3055 break;
c1d127dd 3056 default:
3057 break;
3058 }
ab129075 3059 return true;
c1d127dd 3060}
3061
3062
75a70cf9 3063/* Helper function scan_omp.
3064
3065 Callback for walk_tree or operators in walk_gimple_stmt used to
ca4c3545 3066 scan for OMP directives in TP. */
1e8e9920 3067
3068static tree
75a70cf9 3069scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
1e8e9920 3070{
4077bf7a 3071 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
3072 omp_context *ctx = (omp_context *) wi->info;
1e8e9920 3073 tree t = *tp;
3074
75a70cf9 3075 switch (TREE_CODE (t))
3076 {
3077 case VAR_DECL:
3078 case PARM_DECL:
3079 case LABEL_DECL:
3080 case RESULT_DECL:
3081 if (ctx)
3082 *tp = remap_decl (t, &ctx->cb);
3083 break;
3084
3085 default:
3086 if (ctx && TYPE_P (t))
3087 *tp = remap_type (t, &ctx->cb);
3088 else if (!DECL_P (t))
7cf869dd 3089 {
3090 *walk_subtrees = 1;
3091 if (ctx)
182cf5a9 3092 {
3093 tree tem = remap_type (TREE_TYPE (t), &ctx->cb);
3094 if (tem != TREE_TYPE (t))
3095 {
3096 if (TREE_CODE (t) == INTEGER_CST)
e913b5cd 3097 *tp = wide_int_to_tree (tem, t);
182cf5a9 3098 else
3099 TREE_TYPE (t) = tem;
3100 }
3101 }
7cf869dd 3102 }
75a70cf9 3103 break;
3104 }
3105
3106 return NULL_TREE;
3107}
3108
f2697631 3109/* Return true if FNDECL is a setjmp or a longjmp. */
3110
3111static bool
3112setjmp_or_longjmp_p (const_tree fndecl)
3113{
3114 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
3115 && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_SETJMP
3116 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LONGJMP))
3117 return true;
3118
3119 tree declname = DECL_NAME (fndecl);
3120 if (!declname)
3121 return false;
3122 const char *name = IDENTIFIER_POINTER (declname);
3123 return !strcmp (name, "setjmp") || !strcmp (name, "longjmp");
3124}
3125
75a70cf9 3126
3127/* Helper function for scan_omp.
3128
ca4c3545 3129 Callback for walk_gimple_stmt used to scan for OMP directives in
75a70cf9 3130 the current statement in GSI. */
3131
3132static tree
3133scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
3134 struct walk_stmt_info *wi)
3135{
3136 gimple stmt = gsi_stmt (*gsi);
3137 omp_context *ctx = (omp_context *) wi->info;
3138
3139 if (gimple_has_location (stmt))
3140 input_location = gimple_location (stmt);
1e8e9920 3141
ca4c3545 3142 /* Check the nesting restrictions. */
bc7bff74 3143 bool remove = false;
3144 if (is_gimple_omp (stmt))
3145 remove = !check_omp_nesting_restrictions (stmt, ctx);
3146 else if (is_gimple_call (stmt))
3147 {
3148 tree fndecl = gimple_call_fndecl (stmt);
f2697631 3149 if (fndecl)
3150 {
3151 if (setjmp_or_longjmp_p (fndecl)
3152 && ctx
3153 && gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
10c55644 3154 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
f2697631 3155 {
3156 remove = true;
3157 error_at (gimple_location (stmt),
3158 "setjmp/longjmp inside simd construct");
3159 }
3160 else if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
3161 switch (DECL_FUNCTION_CODE (fndecl))
3162 {
3163 case BUILT_IN_GOMP_BARRIER:
3164 case BUILT_IN_GOMP_CANCEL:
3165 case BUILT_IN_GOMP_CANCELLATION_POINT:
3166 case BUILT_IN_GOMP_TASKYIELD:
3167 case BUILT_IN_GOMP_TASKWAIT:
3168 case BUILT_IN_GOMP_TASKGROUP_START:
3169 case BUILT_IN_GOMP_TASKGROUP_END:
3170 remove = !check_omp_nesting_restrictions (stmt, ctx);
3171 break;
3172 default:
3173 break;
3174 }
3175 }
bc7bff74 3176 }
3177 if (remove)
3178 {
3179 stmt = gimple_build_nop ();
3180 gsi_replace (gsi, stmt, false);
fd6481cf 3181 }
c1d127dd 3182
75a70cf9 3183 *handled_ops_p = true;
3184
3185 switch (gimple_code (stmt))
1e8e9920 3186 {
75a70cf9 3187 case GIMPLE_OMP_PARALLEL:
fd6481cf 3188 taskreg_nesting_level++;
75a70cf9 3189 scan_omp_parallel (gsi, ctx);
fd6481cf 3190 taskreg_nesting_level--;
3191 break;
3192
75a70cf9 3193 case GIMPLE_OMP_TASK:
fd6481cf 3194 taskreg_nesting_level++;
75a70cf9 3195 scan_omp_task (gsi, ctx);
fd6481cf 3196 taskreg_nesting_level--;
1e8e9920 3197 break;
3198
75a70cf9 3199 case GIMPLE_OMP_FOR:
1a91d914 3200 scan_omp_for (as_a <gomp_for *> (stmt), ctx);
1e8e9920 3201 break;
3202
75a70cf9 3203 case GIMPLE_OMP_SECTIONS:
1a91d914 3204 scan_omp_sections (as_a <gomp_sections *> (stmt), ctx);
1e8e9920 3205 break;
3206
75a70cf9 3207 case GIMPLE_OMP_SINGLE:
1a91d914 3208 scan_omp_single (as_a <gomp_single *> (stmt), ctx);
1e8e9920 3209 break;
3210
75a70cf9 3211 case GIMPLE_OMP_SECTION:
3212 case GIMPLE_OMP_MASTER:
bc7bff74 3213 case GIMPLE_OMP_TASKGROUP:
75a70cf9 3214 case GIMPLE_OMP_ORDERED:
3215 case GIMPLE_OMP_CRITICAL:
3216 ctx = new_omp_context (stmt, ctx);
ab129075 3217 scan_omp (gimple_omp_body_ptr (stmt), ctx);
1e8e9920 3218 break;
3219
bc7bff74 3220 case GIMPLE_OMP_TARGET:
1a91d914 3221 scan_omp_target (as_a <gomp_target *> (stmt), ctx);
bc7bff74 3222 break;
3223
3224 case GIMPLE_OMP_TEAMS:
1a91d914 3225 scan_omp_teams (as_a <gomp_teams *> (stmt), ctx);
bc7bff74 3226 break;
3227
75a70cf9 3228 case GIMPLE_BIND:
1e8e9920 3229 {
3230 tree var;
1e8e9920 3231
75a70cf9 3232 *handled_ops_p = false;
3233 if (ctx)
1a91d914 3234 for (var = gimple_bind_vars (as_a <gbind *> (stmt));
3235 var ;
3236 var = DECL_CHAIN (var))
75a70cf9 3237 insert_decl_map (&ctx->cb, var, var);
1e8e9920 3238 }
3239 break;
1e8e9920 3240 default:
75a70cf9 3241 *handled_ops_p = false;
1e8e9920 3242 break;
3243 }
3244
3245 return NULL_TREE;
3246}
3247
3248
75a70cf9 3249/* Scan all the statements starting at the current statement. CTX
ca4c3545 3250 contains context information about the OMP directives and
75a70cf9 3251 clauses found during the scan. */
1e8e9920 3252
3253static void
ab129075 3254scan_omp (gimple_seq *body_p, omp_context *ctx)
1e8e9920 3255{
3256 location_t saved_location;
3257 struct walk_stmt_info wi;
3258
3259 memset (&wi, 0, sizeof (wi));
1e8e9920 3260 wi.info = ctx;
1e8e9920 3261 wi.want_locations = true;
3262
3263 saved_location = input_location;
ab129075 3264 walk_gimple_seq_mod (body_p, scan_omp_1_stmt, scan_omp_1_op, &wi);
1e8e9920 3265 input_location = saved_location;
3266}
3267\f
3268/* Re-gimplification and code generation routines. */
3269
3270/* Build a call to GOMP_barrier. */
3271
bc7bff74 3272static gimple
3273build_omp_barrier (tree lhs)
3274{
3275 tree fndecl = builtin_decl_explicit (lhs ? BUILT_IN_GOMP_BARRIER_CANCEL
3276 : BUILT_IN_GOMP_BARRIER);
1a91d914 3277 gcall *g = gimple_build_call (fndecl, 0);
bc7bff74 3278 if (lhs)
3279 gimple_call_set_lhs (g, lhs);
3280 return g;
1e8e9920 3281}
3282
3283/* If a context was created for STMT when it was scanned, return it. */
3284
3285static omp_context *
75a70cf9 3286maybe_lookup_ctx (gimple stmt)
1e8e9920 3287{
3288 splay_tree_node n;
3289 n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
3290 return n ? (omp_context *) n->value : NULL;
3291}
3292
773c5ba7 3293
3294/* Find the mapping for DECL in CTX or the immediately enclosing
3295 context that has a mapping for DECL.
3296
3297 If CTX is a nested parallel directive, we may have to use the decl
3298 mappings created in CTX's parent context. Suppose that we have the
3299 following parallel nesting (variable UIDs showed for clarity):
3300
3301 iD.1562 = 0;
3302 #omp parallel shared(iD.1562) -> outer parallel
3303 iD.1562 = iD.1562 + 1;
3304
3305 #omp parallel shared (iD.1562) -> inner parallel
3306 iD.1562 = iD.1562 - 1;
3307
3308 Each parallel structure will create a distinct .omp_data_s structure
3309 for copying iD.1562 in/out of the directive:
3310
3311 outer parallel .omp_data_s.1.i -> iD.1562
3312 inner parallel .omp_data_s.2.i -> iD.1562
3313
3314 A shared variable mapping will produce a copy-out operation before
3315 the parallel directive and a copy-in operation after it. So, in
3316 this case we would have:
3317
3318 iD.1562 = 0;
3319 .omp_data_o.1.i = iD.1562;
3320 #omp parallel shared(iD.1562) -> outer parallel
3321 .omp_data_i.1 = &.omp_data_o.1
3322 .omp_data_i.1->i = .omp_data_i.1->i + 1;
3323
3324 .omp_data_o.2.i = iD.1562; -> **
3325 #omp parallel shared(iD.1562) -> inner parallel
3326 .omp_data_i.2 = &.omp_data_o.2
3327 .omp_data_i.2->i = .omp_data_i.2->i - 1;
3328
3329
3330 ** This is a problem. The symbol iD.1562 cannot be referenced
3331 inside the body of the outer parallel region. But since we are
3332 emitting this copy operation while expanding the inner parallel
3333 directive, we need to access the CTX structure of the outer
3334 parallel directive to get the correct mapping:
3335
3336 .omp_data_o.2.i = .omp_data_i.1->i
3337
3338 Since there may be other workshare or parallel directives enclosing
3339 the parallel directive, it may be necessary to walk up the context
3340 parent chain. This is not a problem in general because nested
3341 parallelism happens only rarely. */
3342
3343static tree
3344lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
3345{
3346 tree t;
3347 omp_context *up;
3348
773c5ba7 3349 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
3350 t = maybe_lookup_decl (decl, up);
3351
87b31375 3352 gcc_assert (!ctx->is_nested || t || is_global_var (decl));
773c5ba7 3353
c37594c7 3354 return t ? t : decl;
773c5ba7 3355}
3356
3357
f49d7bb5 3358/* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
3359 in outer contexts. */
3360
3361static tree
3362maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
3363{
3364 tree t = NULL;
3365 omp_context *up;
3366
87b31375 3367 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
3368 t = maybe_lookup_decl (decl, up);
f49d7bb5 3369
3370 return t ? t : decl;
3371}
3372
3373
1e8e9920 3374/* Construct the initialization value for reduction CLAUSE. */
3375
3376tree
3377omp_reduction_init (tree clause, tree type)
3378{
389dd41b 3379 location_t loc = OMP_CLAUSE_LOCATION (clause);
1e8e9920 3380 switch (OMP_CLAUSE_REDUCTION_CODE (clause))
3381 {
3382 case PLUS_EXPR:
3383 case MINUS_EXPR:
3384 case BIT_IOR_EXPR:
3385 case BIT_XOR_EXPR:
3386 case TRUTH_OR_EXPR:
3387 case TRUTH_ORIF_EXPR:
3388 case TRUTH_XOR_EXPR:
3389 case NE_EXPR:
385f3f36 3390 return build_zero_cst (type);
1e8e9920 3391
3392 case MULT_EXPR:
3393 case TRUTH_AND_EXPR:
3394 case TRUTH_ANDIF_EXPR:
3395 case EQ_EXPR:
389dd41b 3396 return fold_convert_loc (loc, type, integer_one_node);
1e8e9920 3397
3398 case BIT_AND_EXPR:
389dd41b 3399 return fold_convert_loc (loc, type, integer_minus_one_node);
1e8e9920 3400
3401 case MAX_EXPR:
3402 if (SCALAR_FLOAT_TYPE_P (type))
3403 {
3404 REAL_VALUE_TYPE max, min;
fe994837 3405 if (HONOR_INFINITIES (type))
1e8e9920 3406 {
3407 real_inf (&max);
3408 real_arithmetic (&min, NEGATE_EXPR, &max, NULL);
3409 }
3410 else
3411 real_maxval (&min, 1, TYPE_MODE (type));
3412 return build_real (type, min);
3413 }
3414 else
3415 {
3416 gcc_assert (INTEGRAL_TYPE_P (type));
3417 return TYPE_MIN_VALUE (type);
3418 }
3419
3420 case MIN_EXPR:
3421 if (SCALAR_FLOAT_TYPE_P (type))
3422 {
3423 REAL_VALUE_TYPE max;
fe994837 3424 if (HONOR_INFINITIES (type))
1e8e9920 3425 real_inf (&max);
3426 else
3427 real_maxval (&max, 0, TYPE_MODE (type));
3428 return build_real (type, max);
3429 }
3430 else
3431 {
3432 gcc_assert (INTEGRAL_TYPE_P (type));
3433 return TYPE_MAX_VALUE (type);
3434 }
3435
3436 default:
3437 gcc_unreachable ();
3438 }
3439}
3440
bc7bff74 3441/* Return alignment to be assumed for var in CLAUSE, which should be
3442 OMP_CLAUSE_ALIGNED. */
3443
3444static tree
3445omp_clause_aligned_alignment (tree clause)
3446{
3447 if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause))
3448 return OMP_CLAUSE_ALIGNED_ALIGNMENT (clause);
3449
3450 /* Otherwise return implementation defined alignment. */
3451 unsigned int al = 1;
3754d046 3452 machine_mode mode, vmode;
bc7bff74 3453 int vs = targetm.vectorize.autovectorize_vector_sizes ();
3454 if (vs)
3455 vs = 1 << floor_log2 (vs);
3456 static enum mode_class classes[]
3457 = { MODE_INT, MODE_VECTOR_INT, MODE_FLOAT, MODE_VECTOR_FLOAT };
3458 for (int i = 0; i < 4; i += 2)
3459 for (mode = GET_CLASS_NARROWEST_MODE (classes[i]);
3460 mode != VOIDmode;
3461 mode = GET_MODE_WIDER_MODE (mode))
3462 {
3463 vmode = targetm.vectorize.preferred_simd_mode (mode);
3464 if (GET_MODE_CLASS (vmode) != classes[i + 1])
3465 continue;
3466 while (vs
3467 && GET_MODE_SIZE (vmode) < vs
3468 && GET_MODE_2XWIDER_MODE (vmode) != VOIDmode)
3469 vmode = GET_MODE_2XWIDER_MODE (vmode);
3470
3471 tree type = lang_hooks.types.type_for_mode (mode, 1);
3472 if (type == NULL_TREE || TYPE_MODE (type) != mode)
3473 continue;
3474 type = build_vector_type (type, GET_MODE_SIZE (vmode)
3475 / GET_MODE_SIZE (mode));
3476 if (TYPE_MODE (type) != vmode)
3477 continue;
3478 if (TYPE_ALIGN_UNIT (type) > al)
3479 al = TYPE_ALIGN_UNIT (type);
3480 }
3481 return build_int_cst (integer_type_node, al);
3482}
3483
3d483a94 3484/* Return maximum possible vectorization factor for the target. */
3485
3486static int
3487omp_max_vf (void)
3488{
3489 if (!optimize
3490 || optimize_debug
ad45e43e 3491 || !flag_tree_loop_optimize
043115ec 3492 || (!flag_tree_loop_vectorize
3493 && (global_options_set.x_flag_tree_loop_vectorize
3494 || global_options_set.x_flag_tree_vectorize)))
3d483a94 3495 return 1;
3496
3497 int vs = targetm.vectorize.autovectorize_vector_sizes ();
3498 if (vs)
3499 {
3500 vs = 1 << floor_log2 (vs);
3501 return vs;
3502 }
3754d046 3503 machine_mode vqimode = targetm.vectorize.preferred_simd_mode (QImode);
3d483a94 3504 if (GET_MODE_CLASS (vqimode) == MODE_VECTOR_INT)
3505 return GET_MODE_NUNITS (vqimode);
3506 return 1;
3507}
3508
3509/* Helper function of lower_rec_input_clauses, used for #pragma omp simd
3510 privatization. */
3511
3512static bool
3513lower_rec_simd_input_clauses (tree new_var, omp_context *ctx, int &max_vf,
3514 tree &idx, tree &lane, tree &ivar, tree &lvar)
3515{
3516 if (max_vf == 0)
3517 {
3518 max_vf = omp_max_vf ();
3519 if (max_vf > 1)
3520 {
3521 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3522 OMP_CLAUSE_SAFELEN);
c3f3b68d 3523 if (c && TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) != INTEGER_CST)
3524 max_vf = 1;
3525 else if (c && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
3526 max_vf) == -1)
d85a2013 3527 max_vf = tree_to_shwi (OMP_CLAUSE_SAFELEN_EXPR (c));
3d483a94 3528 }
3529 if (max_vf > 1)
3530 {
f9e245b2 3531 idx = create_tmp_var (unsigned_type_node);
3532 lane = create_tmp_var (unsigned_type_node);
3d483a94 3533 }
3534 }
3535 if (max_vf == 1)
3536 return false;
3537
3538 tree atype = build_array_type_nelts (TREE_TYPE (new_var), max_vf);
f9e245b2 3539 tree avar = create_tmp_var_raw (atype);
3d483a94 3540 if (TREE_ADDRESSABLE (new_var))
3541 TREE_ADDRESSABLE (avar) = 1;
3542 DECL_ATTRIBUTES (avar)
3543 = tree_cons (get_identifier ("omp simd array"), NULL,
3544 DECL_ATTRIBUTES (avar));
3545 gimple_add_tmp_var (avar);
3546 ivar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, idx,
3547 NULL_TREE, NULL_TREE);
3548 lvar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, lane,
3549 NULL_TREE, NULL_TREE);
bc7bff74 3550 if (DECL_P (new_var))
3551 {
3552 SET_DECL_VALUE_EXPR (new_var, lvar);
3553 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3554 }
3d483a94 3555 return true;
3556}
3557
2712b6de 3558/* Helper function of lower_rec_input_clauses. For a reference
3559 in simd reduction, add an underlying variable it will reference. */
3560
3561static void
3562handle_simd_reference (location_t loc, tree new_vard, gimple_seq *ilist)
3563{
3564 tree z = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard)));
3565 if (TREE_CONSTANT (z))
3566 {
3567 const char *name = NULL;
3568 if (DECL_NAME (new_vard))
3569 name = IDENTIFIER_POINTER (DECL_NAME (new_vard));
3570
3571 z = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_vard)), name);
3572 gimple_add_tmp_var (z);
3573 TREE_ADDRESSABLE (z) = 1;
3574 z = build_fold_addr_expr_loc (loc, z);
3575 gimplify_assign (new_vard, z, ilist);
3576 }
3577}
3578
1e8e9920 3579/* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
3580 from the receiver (aka child) side and initializers for REFERENCE_TYPE
3581 private variables. Initialization statements go in ILIST, while calls
3582 to destructors go in DLIST. */
3583
3584static void
75a70cf9 3585lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
bc7bff74 3586 omp_context *ctx, struct omp_for_data *fd)
1e8e9920 3587{
c2f47e15 3588 tree c, dtor, copyin_seq, x, ptr;
1e8e9920 3589 bool copyin_by_ref = false;
f49d7bb5 3590 bool lastprivate_firstprivate = false;
bc7bff74 3591 bool reduction_omp_orig_ref = false;
1e8e9920 3592 int pass;
3d483a94 3593 bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
10c55644 3594 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD);
3d483a94 3595 int max_vf = 0;
3596 tree lane = NULL_TREE, idx = NULL_TREE;
3597 tree ivar = NULL_TREE, lvar = NULL_TREE;
3598 gimple_seq llist[2] = { NULL, NULL };
1e8e9920 3599
1e8e9920 3600 copyin_seq = NULL;
3601
3d483a94 3602 /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
3603 with data sharing clauses referencing variable sized vars. That
3604 is unnecessarily hard to support and very unlikely to result in
3605 vectorized code anyway. */
3606 if (is_simd)
3607 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3608 switch (OMP_CLAUSE_CODE (c))
3609 {
9580cb79 3610 case OMP_CLAUSE_LINEAR:
3611 if (OMP_CLAUSE_LINEAR_ARRAY (c))
3612 max_vf = 1;
3613 /* FALLTHRU */
3d483a94 3614 case OMP_CLAUSE_REDUCTION:
3d483a94 3615 case OMP_CLAUSE_PRIVATE:
3616 case OMP_CLAUSE_FIRSTPRIVATE:
3617 case OMP_CLAUSE_LASTPRIVATE:
3d483a94 3618 if (is_variable_sized (OMP_CLAUSE_DECL (c)))
3619 max_vf = 1;
3620 break;
3621 default:
3622 continue;
3623 }
3624
1e8e9920 3625 /* Do all the fixed sized types in the first pass, and the variable sized
3626 types in the second pass. This makes sure that the scalar arguments to
48e1416a 3627 the variable sized types are processed before we use them in the
1e8e9920 3628 variable sized operations. */
3629 for (pass = 0; pass < 2; ++pass)
3630 {
3631 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3632 {
55d6e7cd 3633 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
1e8e9920 3634 tree var, new_var;
3635 bool by_ref;
389dd41b 3636 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
1e8e9920 3637
3638 switch (c_kind)
3639 {
3640 case OMP_CLAUSE_PRIVATE:
3641 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
3642 continue;
3643 break;
3644 case OMP_CLAUSE_SHARED:
bc7bff74 3645 /* Ignore shared directives in teams construct. */
3646 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3647 continue;
f49d7bb5 3648 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
3649 {
3650 gcc_assert (is_global_var (OMP_CLAUSE_DECL (c)));
3651 continue;
3652 }
1e8e9920 3653 case OMP_CLAUSE_FIRSTPRIVATE:
1e8e9920 3654 case OMP_CLAUSE_COPYIN:
bc7bff74 3655 case OMP_CLAUSE_LINEAR:
3656 break;
1e8e9920 3657 case OMP_CLAUSE_REDUCTION:
bc7bff74 3658 if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
3659 reduction_omp_orig_ref = true;
1e8e9920 3660 break;
bc7bff74 3661 case OMP_CLAUSE__LOOPTEMP_:
3662 /* Handle _looptemp_ clauses only on parallel. */
3663 if (fd)
3664 continue;
3d483a94 3665 break;
df2c34fc 3666 case OMP_CLAUSE_LASTPRIVATE:
f49d7bb5 3667 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3668 {
3669 lastprivate_firstprivate = true;
3670 if (pass != 0)
3671 continue;
3672 }
cf5f881f 3673 /* Even without corresponding firstprivate, if
3674 decl is Fortran allocatable, it needs outer var
3675 reference. */
3676 else if (pass == 0
3677 && lang_hooks.decls.omp_private_outer_ref
3678 (OMP_CLAUSE_DECL (c)))
3679 lastprivate_firstprivate = true;
df2c34fc 3680 break;
bc7bff74 3681 case OMP_CLAUSE_ALIGNED:
3682 if (pass == 0)
3683 continue;
3684 var = OMP_CLAUSE_DECL (c);
3685 if (TREE_CODE (TREE_TYPE (var)) == POINTER_TYPE
3686 && !is_global_var (var))
3687 {
3688 new_var = maybe_lookup_decl (var, ctx);
3689 if (new_var == NULL_TREE)
3690 new_var = maybe_lookup_decl_in_outer_ctx (var, ctx);
3691 x = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3692 x = build_call_expr_loc (clause_loc, x, 2, new_var,
3693 omp_clause_aligned_alignment (c));
3694 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3695 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
3696 gimplify_and_add (x, ilist);
3697 }
3698 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
3699 && is_global_var (var))
3700 {
3701 tree ptype = build_pointer_type (TREE_TYPE (var)), t, t2;
3702 new_var = lookup_decl (var, ctx);
3703 t = maybe_lookup_decl_in_outer_ctx (var, ctx);
3704 t = build_fold_addr_expr_loc (clause_loc, t);
3705 t2 = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3706 t = build_call_expr_loc (clause_loc, t2, 2, t,
3707 omp_clause_aligned_alignment (c));
3708 t = fold_convert_loc (clause_loc, ptype, t);
f9e245b2 3709 x = create_tmp_var (ptype);
bc7bff74 3710 t = build2 (MODIFY_EXPR, ptype, x, t);
3711 gimplify_and_add (t, ilist);
3712 t = build_simple_mem_ref_loc (clause_loc, x);
3713 SET_DECL_VALUE_EXPR (new_var, t);
3714 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3715 }
3716 continue;
1e8e9920 3717 default:
3718 continue;
3719 }
3720
3721 new_var = var = OMP_CLAUSE_DECL (c);
3722 if (c_kind != OMP_CLAUSE_COPYIN)
3723 new_var = lookup_decl (var, ctx);
3724
3725 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
3726 {
3727 if (pass != 0)
3728 continue;
3729 }
1e8e9920 3730 else if (is_variable_sized (var))
3731 {
773c5ba7 3732 /* For variable sized types, we need to allocate the
3733 actual storage here. Call alloca and store the
3734 result in the pointer decl that we created elsewhere. */
1e8e9920 3735 if (pass == 0)
3736 continue;
3737
fd6481cf 3738 if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
3739 {
1a91d914 3740 gcall *stmt;
b9a16870 3741 tree tmp, atmp;
75a70cf9 3742
fd6481cf 3743 ptr = DECL_VALUE_EXPR (new_var);
3744 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
3745 ptr = TREE_OPERAND (ptr, 0);
3746 gcc_assert (DECL_P (ptr));
3747 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
75a70cf9 3748
3749 /* void *tmp = __builtin_alloca */
b9a16870 3750 atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3751 stmt = gimple_build_call (atmp, 1, x);
f9e245b2 3752 tmp = create_tmp_var_raw (ptr_type_node);
75a70cf9 3753 gimple_add_tmp_var (tmp);
3754 gimple_call_set_lhs (stmt, tmp);
3755
3756 gimple_seq_add_stmt (ilist, stmt);
3757
389dd41b 3758 x = fold_convert_loc (clause_loc, TREE_TYPE (ptr), tmp);
75a70cf9 3759 gimplify_assign (ptr, x, ilist);
fd6481cf 3760 }
1e8e9920 3761 }
1e8e9920 3762 else if (is_reference (var))
3763 {
773c5ba7 3764 /* For references that are being privatized for Fortran,
3765 allocate new backing storage for the new pointer
3766 variable. This allows us to avoid changing all the
3767 code that expects a pointer to something that expects
bc7bff74 3768 a direct variable. */
1e8e9920 3769 if (pass == 0)
3770 continue;
3771
3772 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
fd6481cf 3773 if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx))
3774 {
3775 x = build_receiver_ref (var, false, ctx);
389dd41b 3776 x = build_fold_addr_expr_loc (clause_loc, x);
fd6481cf 3777 }
3778 else if (TREE_CONSTANT (x))
1e8e9920 3779 {
2712b6de 3780 /* For reduction in SIMD loop, defer adding the
3781 initialization of the reference, because if we decide
3782 to use SIMD array for it, the initilization could cause
3783 expansion ICE. */
3784 if (c_kind == OMP_CLAUSE_REDUCTION && is_simd)
09d1c205 3785 x = NULL_TREE;
3786 else
3787 {
3788 const char *name = NULL;
3789 if (DECL_NAME (var))
3790 name = IDENTIFIER_POINTER (DECL_NAME (new_var));
3791
3792 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
3793 name);
3794 gimple_add_tmp_var (x);
3795 TREE_ADDRESSABLE (x) = 1;
3796 x = build_fold_addr_expr_loc (clause_loc, x);
3797 }
1e8e9920 3798 }
3799 else
3800 {
b9a16870 3801 tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3802 x = build_call_expr_loc (clause_loc, atmp, 1, x);
1e8e9920 3803 }
3804
09d1c205 3805 if (x)
3806 {
3807 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3808 gimplify_assign (new_var, x, ilist);
3809 }
1e8e9920 3810
182cf5a9 3811 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
1e8e9920 3812 }
3813 else if (c_kind == OMP_CLAUSE_REDUCTION
3814 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3815 {
3816 if (pass == 0)
3817 continue;
3818 }
3819 else if (pass != 0)
3820 continue;
3821
55d6e7cd 3822 switch (OMP_CLAUSE_CODE (c))
1e8e9920 3823 {
3824 case OMP_CLAUSE_SHARED:
bc7bff74 3825 /* Ignore shared directives in teams construct. */
3826 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3827 continue;
f49d7bb5 3828 /* Shared global vars are just accessed directly. */
3829 if (is_global_var (new_var))
3830 break;
1e8e9920 3831 /* Set up the DECL_VALUE_EXPR for shared variables now. This
3832 needs to be delayed until after fixup_child_record_type so
3833 that we get the correct type during the dereference. */
e8a588af 3834 by_ref = use_pointer_for_field (var, ctx);
1e8e9920 3835 x = build_receiver_ref (var, by_ref, ctx);
3836 SET_DECL_VALUE_EXPR (new_var, x);
3837 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3838
3839 /* ??? If VAR is not passed by reference, and the variable
3840 hasn't been initialized yet, then we'll get a warning for
3841 the store into the omp_data_s structure. Ideally, we'd be
48e1416a 3842 able to notice this and not store anything at all, but
1e8e9920 3843 we're generating code too early. Suppress the warning. */
3844 if (!by_ref)
3845 TREE_NO_WARNING (var) = 1;
3846 break;
3847
3848 case OMP_CLAUSE_LASTPRIVATE:
3849 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3850 break;
3851 /* FALLTHRU */
3852
3853 case OMP_CLAUSE_PRIVATE:
fd6481cf 3854 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE)
3855 x = build_outer_var_ref (var, ctx);
3856 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
3857 {
3858 if (is_task_ctx (ctx))
3859 x = build_receiver_ref (var, false, ctx);
3860 else
3861 x = build_outer_var_ref (var, ctx);
3862 }
3863 else
3864 x = NULL;
3d483a94 3865 do_private:
bc7bff74 3866 tree nx;
3867 nx = lang_hooks.decls.omp_clause_default_ctor (c, new_var, x);
3d483a94 3868 if (is_simd)
3869 {
3870 tree y = lang_hooks.decls.omp_clause_dtor (c, new_var);
bc7bff74 3871 if ((TREE_ADDRESSABLE (new_var) || nx || y
3d483a94 3872 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
3873 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3874 idx, lane, ivar, lvar))
3875 {
bc7bff74 3876 if (nx)
3d483a94 3877 x = lang_hooks.decls.omp_clause_default_ctor
3878 (c, unshare_expr (ivar), x);
bc7bff74 3879 if (nx && x)
3d483a94 3880 gimplify_and_add (x, &llist[0]);
3881 if (y)
3882 {
3883 y = lang_hooks.decls.omp_clause_dtor (c, ivar);
3884 if (y)
3885 {
3886 gimple_seq tseq = NULL;
3887
3888 dtor = y;
3889 gimplify_stmt (&dtor, &tseq);
3890 gimple_seq_add_seq (&llist[1], tseq);
3891 }
3892 }
3893 break;
3894 }
3895 }
bc7bff74 3896 if (nx)
3897 gimplify_and_add (nx, ilist);
1e8e9920 3898 /* FALLTHRU */
3899
3900 do_dtor:
3901 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
3902 if (x)
3903 {
75a70cf9 3904 gimple_seq tseq = NULL;
3905
1e8e9920 3906 dtor = x;
75a70cf9 3907 gimplify_stmt (&dtor, &tseq);
e3a19533 3908 gimple_seq_add_seq (dlist, tseq);
1e8e9920 3909 }
3910 break;
3911
3d483a94 3912 case OMP_CLAUSE_LINEAR:
3913 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c))
3914 goto do_firstprivate;
3915 if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
3916 x = NULL;
3917 else
3918 x = build_outer_var_ref (var, ctx);
3919 goto do_private;
3920
1e8e9920 3921 case OMP_CLAUSE_FIRSTPRIVATE:
fd6481cf 3922 if (is_task_ctx (ctx))
3923 {
3924 if (is_reference (var) || is_variable_sized (var))
3925 goto do_dtor;
3926 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var,
3927 ctx))
3928 || use_pointer_for_field (var, NULL))
3929 {
3930 x = build_receiver_ref (var, false, ctx);
3931 SET_DECL_VALUE_EXPR (new_var, x);
3932 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3933 goto do_dtor;
3934 }
3935 }
3d483a94 3936 do_firstprivate:
1e8e9920 3937 x = build_outer_var_ref (var, ctx);
3d483a94 3938 if (is_simd)
3939 {
bc7bff74 3940 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3941 && gimple_omp_for_combined_into_p (ctx->stmt))
3942 {
9580cb79 3943 tree t = OMP_CLAUSE_LINEAR_STEP (c);
3944 tree stept = TREE_TYPE (t);
3945 tree ct = find_omp_clause (clauses,
3946 OMP_CLAUSE__LOOPTEMP_);
3947 gcc_assert (ct);
3948 tree l = OMP_CLAUSE_DECL (ct);
e471cc6f 3949 tree n1 = fd->loop.n1;
3950 tree step = fd->loop.step;
3951 tree itype = TREE_TYPE (l);
3952 if (POINTER_TYPE_P (itype))
3953 itype = signed_type_for (itype);
3954 l = fold_build2 (MINUS_EXPR, itype, l, n1);
3955 if (TYPE_UNSIGNED (itype)
3956 && fd->loop.cond_code == GT_EXPR)
3957 l = fold_build2 (TRUNC_DIV_EXPR, itype,
3958 fold_build1 (NEGATE_EXPR, itype, l),
3959 fold_build1 (NEGATE_EXPR,
3960 itype, step));
3961 else
3962 l = fold_build2 (TRUNC_DIV_EXPR, itype, l, step);
bc7bff74 3963 t = fold_build2 (MULT_EXPR, stept,
3964 fold_convert (stept, l), t);
9580cb79 3965
3966 if (OMP_CLAUSE_LINEAR_ARRAY (c))
3967 {
3968 x = lang_hooks.decls.omp_clause_linear_ctor
3969 (c, new_var, x, t);
3970 gimplify_and_add (x, ilist);
3971 goto do_dtor;
3972 }
3973
bc7bff74 3974 if (POINTER_TYPE_P (TREE_TYPE (x)))
3975 x = fold_build2 (POINTER_PLUS_EXPR,
3976 TREE_TYPE (x), x, t);
3977 else
3978 x = fold_build2 (PLUS_EXPR, TREE_TYPE (x), x, t);
3979 }
3980
3d483a94 3981 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
3982 || TREE_ADDRESSABLE (new_var))
3983 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3984 idx, lane, ivar, lvar))
3985 {
3986 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR)
3987 {
f9e245b2 3988 tree iv = create_tmp_var (TREE_TYPE (new_var));
3d483a94 3989 x = lang_hooks.decls.omp_clause_copy_ctor (c, iv, x);
3990 gimplify_and_add (x, ilist);
3991 gimple_stmt_iterator gsi
3992 = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
1a91d914 3993 gassign *g
3d483a94 3994 = gimple_build_assign (unshare_expr (lvar), iv);
3995 gsi_insert_before_without_update (&gsi, g,
3996 GSI_SAME_STMT);
9580cb79 3997 tree t = OMP_CLAUSE_LINEAR_STEP (c);
3d483a94 3998 enum tree_code code = PLUS_EXPR;
3999 if (POINTER_TYPE_P (TREE_TYPE (new_var)))
4000 code = POINTER_PLUS_EXPR;
e9cf809e 4001 g = gimple_build_assign (iv, code, iv, t);
3d483a94 4002 gsi_insert_before_without_update (&gsi, g,
4003 GSI_SAME_STMT);
4004 break;
4005 }
4006 x = lang_hooks.decls.omp_clause_copy_ctor
4007 (c, unshare_expr (ivar), x);
4008 gimplify_and_add (x, &llist[0]);
4009 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
4010 if (x)
4011 {
4012 gimple_seq tseq = NULL;
4013
4014 dtor = x;
4015 gimplify_stmt (&dtor, &tseq);
4016 gimple_seq_add_seq (&llist[1], tseq);
4017 }
4018 break;
4019 }
4020 }
1e8e9920 4021 x = lang_hooks.decls.omp_clause_copy_ctor (c, new_var, x);
4022 gimplify_and_add (x, ilist);
4023 goto do_dtor;
1e8e9920 4024
bc7bff74 4025 case OMP_CLAUSE__LOOPTEMP_:
4026 gcc_assert (is_parallel_ctx (ctx));
4027 x = build_outer_var_ref (var, ctx);
4028 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
4029 gimplify_and_add (x, ilist);
4030 break;
4031
1e8e9920 4032 case OMP_CLAUSE_COPYIN:
e8a588af 4033 by_ref = use_pointer_for_field (var, NULL);
1e8e9920 4034 x = build_receiver_ref (var, by_ref, ctx);
4035 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
4036 append_to_statement_list (x, &copyin_seq);
4037 copyin_by_ref |= by_ref;
4038 break;
4039
4040 case OMP_CLAUSE_REDUCTION:
4041 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4042 {
fd6481cf 4043 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
bc7bff74 4044 gimple tseq;
fd6481cf 4045 x = build_outer_var_ref (var, ctx);
4046
bc7bff74 4047 if (is_reference (var)
4048 && !useless_type_conversion_p (TREE_TYPE (placeholder),
4049 TREE_TYPE (x)))
389dd41b 4050 x = build_fold_addr_expr_loc (clause_loc, x);
fd6481cf 4051 SET_DECL_VALUE_EXPR (placeholder, x);
4052 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
bc7bff74 4053 tree new_vard = new_var;
4054 if (is_reference (var))
4055 {
4056 gcc_assert (TREE_CODE (new_var) == MEM_REF);
4057 new_vard = TREE_OPERAND (new_var, 0);
4058 gcc_assert (DECL_P (new_vard));
4059 }
3d483a94 4060 if (is_simd
4061 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4062 idx, lane, ivar, lvar))
4063 {
bc7bff74 4064 if (new_vard == new_var)
4065 {
4066 gcc_assert (DECL_VALUE_EXPR (new_var) == lvar);
4067 SET_DECL_VALUE_EXPR (new_var, ivar);
4068 }
4069 else
4070 {
4071 SET_DECL_VALUE_EXPR (new_vard,
4072 build_fold_addr_expr (ivar));
4073 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
4074 }
4075 x = lang_hooks.decls.omp_clause_default_ctor
4076 (c, unshare_expr (ivar),
4077 build_outer_var_ref (var, ctx));
4078 if (x)
4079 gimplify_and_add (x, &llist[0]);
4080 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
4081 {
4082 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
4083 lower_omp (&tseq, ctx);
4084 gimple_seq_add_seq (&llist[0], tseq);
4085 }
4086 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
4087 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
4088 lower_omp (&tseq, ctx);
4089 gimple_seq_add_seq (&llist[1], tseq);
4090 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4091 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
4092 if (new_vard == new_var)
4093 SET_DECL_VALUE_EXPR (new_var, lvar);
4094 else
4095 SET_DECL_VALUE_EXPR (new_vard,
4096 build_fold_addr_expr (lvar));
4097 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
4098 if (x)
4099 {
4100 tseq = NULL;
4101 dtor = x;
4102 gimplify_stmt (&dtor, &tseq);
4103 gimple_seq_add_seq (&llist[1], tseq);
4104 }
4105 break;
4106 }
09d1c205 4107 /* If this is a reference to constant size reduction var
4108 with placeholder, we haven't emitted the initializer
4109 for it because it is undesirable if SIMD arrays are used.
4110 But if they aren't used, we need to emit the deferred
4111 initialization now. */
4112 else if (is_reference (var) && is_simd)
2712b6de 4113 handle_simd_reference (clause_loc, new_vard, ilist);
bc7bff74 4114 x = lang_hooks.decls.omp_clause_default_ctor
cf5f881f 4115 (c, unshare_expr (new_var),
4116 build_outer_var_ref (var, ctx));
bc7bff74 4117 if (x)
4118 gimplify_and_add (x, ilist);
4119 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
4120 {
4121 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
4122 lower_omp (&tseq, ctx);
4123 gimple_seq_add_seq (ilist, tseq);
4124 }
75a70cf9 4125 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
bc7bff74 4126 if (is_simd)
4127 {
4128 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
4129 lower_omp (&tseq, ctx);
4130 gimple_seq_add_seq (dlist, tseq);
4131 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4132 }
fd6481cf 4133 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
bc7bff74 4134 goto do_dtor;
1e8e9920 4135 }
4136 else
4137 {
4138 x = omp_reduction_init (c, TREE_TYPE (new_var));
4139 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
c22ad515 4140 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
4141
4142 /* reduction(-:var) sums up the partial results, so it
4143 acts identically to reduction(+:var). */
4144 if (code == MINUS_EXPR)
4145 code = PLUS_EXPR;
4146
2712b6de 4147 tree new_vard = new_var;
4148 if (is_simd && is_reference (var))
4149 {
4150 gcc_assert (TREE_CODE (new_var) == MEM_REF);
4151 new_vard = TREE_OPERAND (new_var, 0);
4152 gcc_assert (DECL_P (new_vard));
4153 }
3d483a94 4154 if (is_simd
4155 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4156 idx, lane, ivar, lvar))
4157 {
3d483a94 4158 tree ref = build_outer_var_ref (var, ctx);
4159
4160 gimplify_assign (unshare_expr (ivar), x, &llist[0]);
4161
3d483a94 4162 x = build2 (code, TREE_TYPE (ref), ref, ivar);
4163 ref = build_outer_var_ref (var, ctx);
4164 gimplify_assign (ref, x, &llist[1]);
2712b6de 4165
4166 if (new_vard != new_var)
4167 {
4168 SET_DECL_VALUE_EXPR (new_vard,
4169 build_fold_addr_expr (lvar));
4170 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
4171 }
3d483a94 4172 }
4173 else
4174 {
2712b6de 4175 if (is_reference (var) && is_simd)
4176 handle_simd_reference (clause_loc, new_vard, ilist);
3d483a94 4177 gimplify_assign (new_var, x, ilist);
4178 if (is_simd)
c22ad515 4179 {
4180 tree ref = build_outer_var_ref (var, ctx);
4181
4182 x = build2 (code, TREE_TYPE (ref), ref, new_var);
4183 ref = build_outer_var_ref (var, ctx);
4184 gimplify_assign (ref, x, dlist);
4185 }
3d483a94 4186 }
1e8e9920 4187 }
4188 break;
4189
4190 default:
4191 gcc_unreachable ();
4192 }
4193 }
4194 }
4195
3d483a94 4196 if (lane)
4197 {
4198 tree uid = create_tmp_var (ptr_type_node, "simduid");
8e1a382d 4199 /* Don't want uninit warnings on simduid, it is always uninitialized,
4200 but we use it not for the value, but for the DECL_UID only. */
4201 TREE_NO_WARNING (uid) = 1;
3d483a94 4202 gimple g
4203 = gimple_build_call_internal (IFN_GOMP_SIMD_LANE, 1, uid);
4204 gimple_call_set_lhs (g, lane);
4205 gimple_stmt_iterator gsi = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
4206 gsi_insert_before_without_update (&gsi, g, GSI_SAME_STMT);
4207 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SIMDUID_);
4208 OMP_CLAUSE__SIMDUID__DECL (c) = uid;
4209 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
4210 gimple_omp_for_set_clauses (ctx->stmt, c);
e9cf809e 4211 g = gimple_build_assign (lane, INTEGER_CST,
4212 build_int_cst (unsigned_type_node, 0));
3d483a94 4213 gimple_seq_add_stmt (ilist, g);
4214 for (int i = 0; i < 2; i++)
4215 if (llist[i])
4216 {
f9e245b2 4217 tree vf = create_tmp_var (unsigned_type_node);
3d483a94 4218 g = gimple_build_call_internal (IFN_GOMP_SIMD_VF, 1, uid);
4219 gimple_call_set_lhs (g, vf);
4220 gimple_seq *seq = i == 0 ? ilist : dlist;
4221 gimple_seq_add_stmt (seq, g);
4222 tree t = build_int_cst (unsigned_type_node, 0);
e9cf809e 4223 g = gimple_build_assign (idx, INTEGER_CST, t);
3d483a94 4224 gimple_seq_add_stmt (seq, g);
4225 tree body = create_artificial_label (UNKNOWN_LOCATION);
4226 tree header = create_artificial_label (UNKNOWN_LOCATION);
4227 tree end = create_artificial_label (UNKNOWN_LOCATION);
4228 gimple_seq_add_stmt (seq, gimple_build_goto (header));
4229 gimple_seq_add_stmt (seq, gimple_build_label (body));
4230 gimple_seq_add_seq (seq, llist[i]);
4231 t = build_int_cst (unsigned_type_node, 1);
e9cf809e 4232 g = gimple_build_assign (idx, PLUS_EXPR, idx, t);
3d483a94 4233 gimple_seq_add_stmt (seq, g);
4234 gimple_seq_add_stmt (seq, gimple_build_label (header));
4235 g = gimple_build_cond (LT_EXPR, idx, vf, body, end);
4236 gimple_seq_add_stmt (seq, g);
4237 gimple_seq_add_stmt (seq, gimple_build_label (end));
4238 }
4239 }
4240
1e8e9920 4241 /* The copyin sequence is not to be executed by the main thread, since
4242 that would result in self-copies. Perhaps not visible to scalars,
4243 but it certainly is to C++ operator=. */
4244 if (copyin_seq)
4245 {
b9a16870 4246 x = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM),
4247 0);
1e8e9920 4248 x = build2 (NE_EXPR, boolean_type_node, x,
4249 build_int_cst (TREE_TYPE (x), 0));
4250 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
4251 gimplify_and_add (x, ilist);
4252 }
4253
4254 /* If any copyin variable is passed by reference, we must ensure the
4255 master thread doesn't modify it before it is copied over in all
f49d7bb5 4256 threads. Similarly for variables in both firstprivate and
4257 lastprivate clauses we need to ensure the lastprivate copying
bc7bff74 4258 happens after firstprivate copying in all threads. And similarly
4259 for UDRs if initializer expression refers to omp_orig. */
4260 if (copyin_by_ref || lastprivate_firstprivate || reduction_omp_orig_ref)
3d483a94 4261 {
4262 /* Don't add any barrier for #pragma omp simd or
4263 #pragma omp distribute. */
4264 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
7c01fa6c 4265 || gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_FOR)
bc7bff74 4266 gimple_seq_add_stmt (ilist, build_omp_barrier (NULL_TREE));
3d483a94 4267 }
4268
4269 /* If max_vf is non-zero, then we can use only a vectorization factor
4270 up to the max_vf we chose. So stick it into the safelen clause. */
4271 if (max_vf)
4272 {
4273 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
4274 OMP_CLAUSE_SAFELEN);
4275 if (c == NULL_TREE
c3f3b68d 4276 || (TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) == INTEGER_CST
4277 && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
4278 max_vf) == 1))
3d483a94 4279 {
4280 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_SAFELEN);
4281 OMP_CLAUSE_SAFELEN_EXPR (c) = build_int_cst (integer_type_node,
4282 max_vf);
4283 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
4284 gimple_omp_for_set_clauses (ctx->stmt, c);
4285 }
4286 }
1e8e9920 4287}
4288
773c5ba7 4289
1e8e9920 4290/* Generate code to implement the LASTPRIVATE clauses. This is used for
4291 both parallel and workshare constructs. PREDICATE may be NULL if it's
4292 always true. */
4293
4294static void
75a70cf9 4295lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
bc7bff74 4296 omp_context *ctx)
1e8e9920 4297{
3d483a94 4298 tree x, c, label = NULL, orig_clauses = clauses;
fd6481cf 4299 bool par_clauses = false;
3d483a94 4300 tree simduid = NULL, lastlane = NULL;
1e8e9920 4301
3d483a94 4302 /* Early exit if there are no lastprivate or linear clauses. */
4303 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
4304 if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LASTPRIVATE
4305 || (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LINEAR
4306 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses)))
4307 break;
1e8e9920 4308 if (clauses == NULL)
4309 {
4310 /* If this was a workshare clause, see if it had been combined
4311 with its parallel. In that case, look for the clauses on the
4312 parallel statement itself. */
4313 if (is_parallel_ctx (ctx))
4314 return;
4315
4316 ctx = ctx->outer;
4317 if (ctx == NULL || !is_parallel_ctx (ctx))
4318 return;
4319
75a70cf9 4320 clauses = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
1e8e9920 4321 OMP_CLAUSE_LASTPRIVATE);
4322 if (clauses == NULL)
4323 return;
fd6481cf 4324 par_clauses = true;
1e8e9920 4325 }
4326
75a70cf9 4327 if (predicate)
4328 {
1a91d914 4329 gcond *stmt;
75a70cf9 4330 tree label_true, arm1, arm2;
4331
e60a6f7b 4332 label = create_artificial_label (UNKNOWN_LOCATION);
4333 label_true = create_artificial_label (UNKNOWN_LOCATION);
75a70cf9 4334 arm1 = TREE_OPERAND (predicate, 0);
4335 arm2 = TREE_OPERAND (predicate, 1);
4336 gimplify_expr (&arm1, stmt_list, NULL, is_gimple_val, fb_rvalue);
4337 gimplify_expr (&arm2, stmt_list, NULL, is_gimple_val, fb_rvalue);
4338 stmt = gimple_build_cond (TREE_CODE (predicate), arm1, arm2,
4339 label_true, label);
4340 gimple_seq_add_stmt (stmt_list, stmt);
4341 gimple_seq_add_stmt (stmt_list, gimple_build_label (label_true));
4342 }
1e8e9920 4343
3d483a94 4344 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
10c55644 4345 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3d483a94 4346 {
4347 simduid = find_omp_clause (orig_clauses, OMP_CLAUSE__SIMDUID_);
4348 if (simduid)
4349 simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
4350 }
4351
fd6481cf 4352 for (c = clauses; c ;)
1e8e9920 4353 {
4354 tree var, new_var;
389dd41b 4355 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
1e8e9920 4356
3d483a94 4357 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
4358 || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
4359 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
fd6481cf 4360 {
4361 var = OMP_CLAUSE_DECL (c);
4362 new_var = lookup_decl (var, ctx);
1e8e9920 4363
3d483a94 4364 if (simduid && DECL_HAS_VALUE_EXPR_P (new_var))
4365 {
4366 tree val = DECL_VALUE_EXPR (new_var);
4367 if (TREE_CODE (val) == ARRAY_REF
4368 && VAR_P (TREE_OPERAND (val, 0))
4369 && lookup_attribute ("omp simd array",
4370 DECL_ATTRIBUTES (TREE_OPERAND (val,
4371 0))))
4372 {
4373 if (lastlane == NULL)
4374 {
f9e245b2 4375 lastlane = create_tmp_var (unsigned_type_node);
1a91d914 4376 gcall *g
3d483a94 4377 = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE,
4378 2, simduid,
4379 TREE_OPERAND (val, 1));
4380 gimple_call_set_lhs (g, lastlane);
4381 gimple_seq_add_stmt (stmt_list, g);
4382 }
4383 new_var = build4 (ARRAY_REF, TREE_TYPE (val),
4384 TREE_OPERAND (val, 0), lastlane,
4385 NULL_TREE, NULL_TREE);
4386 }
4387 }
4388
4389 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
4390 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
75a70cf9 4391 {
e3a19533 4392 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
75a70cf9 4393 gimple_seq_add_seq (stmt_list,
4394 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
3d483a94 4395 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) = NULL;
75a70cf9 4396 }
2b536a17 4397 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
4398 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
4399 {
4400 lower_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
4401 gimple_seq_add_seq (stmt_list,
4402 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c));
4403 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c) = NULL;
4404 }
1e8e9920 4405
fd6481cf 4406 x = build_outer_var_ref (var, ctx);
4407 if (is_reference (var))
182cf5a9 4408 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
fd6481cf 4409 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
75a70cf9 4410 gimplify_and_add (x, stmt_list);
fd6481cf 4411 }
4412 c = OMP_CLAUSE_CHAIN (c);
4413 if (c == NULL && !par_clauses)
4414 {
4415 /* If this was a workshare clause, see if it had been combined
4416 with its parallel. In that case, continue looking for the
4417 clauses also on the parallel statement itself. */
4418 if (is_parallel_ctx (ctx))
4419 break;
4420
4421 ctx = ctx->outer;
4422 if (ctx == NULL || !is_parallel_ctx (ctx))
4423 break;
4424
75a70cf9 4425 c = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
fd6481cf 4426 OMP_CLAUSE_LASTPRIVATE);
4427 par_clauses = true;
4428 }
1e8e9920 4429 }
4430
75a70cf9 4431 if (label)
4432 gimple_seq_add_stmt (stmt_list, gimple_build_label (label));
1e8e9920 4433}
4434
ca4c3545 4435static void
4436oacc_lower_reduction_var_helper (gimple_seq *stmt_seqp, omp_context *ctx,
4437 tree tid, tree var, tree new_var)
4438{
4439 /* The atomic add at the end of the sum creates unnecessary
4440 write contention on accelerators. To work around this,
4441 create an array to store the partial reductions. Later, in
4442 lower_omp_for (for openacc), the values of array will be
4443 combined. */
4444
4445 tree t = NULL_TREE, array, x;
4446 tree type = get_base_type (var);
4447 gimple stmt;
4448
4449 /* Now insert the partial reductions into the array. */
4450
4451 /* Find the reduction array. */
4452
4453 tree ptype = build_pointer_type (type);
4454
4455 t = lookup_oacc_reduction (oacc_get_reduction_array_id (var), ctx);
4456 t = build_receiver_ref (t, false, ctx->outer);
4457
4458 array = create_tmp_var (ptype);
4459 gimplify_assign (array, t, stmt_seqp);
4460
4461 tree ptr = create_tmp_var (TREE_TYPE (array));
4462
4463 /* Find the reduction array. */
4464
4465 /* testing a unary conversion. */
4466 tree offset = create_tmp_var (sizetype);
4467 gimplify_assign (offset, TYPE_SIZE_UNIT (type),
4468 stmt_seqp);
4469 t = create_tmp_var (sizetype);
4470 gimplify_assign (t, unshare_expr (fold_build1 (NOP_EXPR, sizetype, tid)),
4471 stmt_seqp);
4472 stmt = gimple_build_assign (offset, MULT_EXPR, offset, t);
4473 gimple_seq_add_stmt (stmt_seqp, stmt);
4474
4475 /* Offset expression. Does the POINTER_PLUS_EXPR take care
4476 of adding sizeof(var) to the array? */
4477 ptr = create_tmp_var (ptype);
4478 stmt = gimple_build_assign (unshare_expr (ptr), POINTER_PLUS_EXPR, array,
4479 offset);
4480 gimple_seq_add_stmt (stmt_seqp, stmt);
4481
4482 /* Move the local sum to gfc$sum[i]. */
4483 x = unshare_expr (build_simple_mem_ref (ptr));
4484 stmt = gimplify_assign (x, new_var, stmt_seqp);
4485}
773c5ba7 4486
1e8e9920 4487/* Generate code to implement the REDUCTION clauses. */
4488
4489static void
75a70cf9 4490lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
1e8e9920 4491{
75a70cf9 4492 gimple_seq sub_seq = NULL;
4493 gimple stmt;
ca4c3545 4494 tree x, c, tid = NULL_TREE;
1e8e9920 4495 int count = 0;
4496
3d483a94 4497 /* SIMD reductions are handled in lower_rec_input_clauses. */
4498 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
10c55644 4499 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3d483a94 4500 return;
4501
1e8e9920 4502 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
4503 update in that case, otherwise use a lock. */
4504 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
55d6e7cd 4505 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
1e8e9920 4506 {
4507 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4508 {
bc7bff74 4509 /* Never use OMP_ATOMIC for array reductions or UDRs. */
1e8e9920 4510 count = -1;
4511 break;
4512 }
4513 count++;
4514 }
4515
4516 if (count == 0)
4517 return;
4518
ca4c3545 4519 /* Initialize thread info for OpenACC. */
4520 if (is_gimple_omp_oacc (ctx->stmt))
4521 {
4522 /* Get the current thread id. */
4523 tree call = builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM);
4524 tid = create_tmp_var (TREE_TYPE (TREE_TYPE (call)));
4525 gimple stmt = gimple_build_call (call, 0);
4526 gimple_call_set_lhs (stmt, tid);
4527 gimple_seq_add_stmt (stmt_seqp, stmt);
4528 }
4529
1e8e9920 4530 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4531 {
4532 tree var, ref, new_var;
4533 enum tree_code code;
389dd41b 4534 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
1e8e9920 4535
55d6e7cd 4536 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
1e8e9920 4537 continue;
4538
4539 var = OMP_CLAUSE_DECL (c);
4540 new_var = lookup_decl (var, ctx);
4541 if (is_reference (var))
182cf5a9 4542 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
1e8e9920 4543 ref = build_outer_var_ref (var, ctx);
4544 code = OMP_CLAUSE_REDUCTION_CODE (c);
773c5ba7 4545
4546 /* reduction(-:var) sums up the partial results, so it acts
4547 identically to reduction(+:var). */
1e8e9920 4548 if (code == MINUS_EXPR)
4549 code = PLUS_EXPR;
4550
ca4c3545 4551 if (is_gimple_omp_oacc (ctx->stmt))
4552 {
4553 gcc_checking_assert (!OMP_CLAUSE_REDUCTION_PLACEHOLDER (c));
4554
4555 oacc_lower_reduction_var_helper (stmt_seqp, ctx, tid, var, new_var);
4556 }
4557 else if (count == 1)
1e8e9920 4558 {
389dd41b 4559 tree addr = build_fold_addr_expr_loc (clause_loc, ref);
1e8e9920 4560
4561 addr = save_expr (addr);
4562 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
389dd41b 4563 x = fold_build2_loc (clause_loc, code, TREE_TYPE (ref), ref, new_var);
1e8e9920 4564 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
75a70cf9 4565 gimplify_and_add (x, stmt_seqp);
1e8e9920 4566 return;
4567 }
ca4c3545 4568 else if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1e8e9920 4569 {
4570 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
4571
bc7bff74 4572 if (is_reference (var)
4573 && !useless_type_conversion_p (TREE_TYPE (placeholder),
4574 TREE_TYPE (ref)))
389dd41b 4575 ref = build_fold_addr_expr_loc (clause_loc, ref);
1e8e9920 4576 SET_DECL_VALUE_EXPR (placeholder, ref);
4577 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
e3a19533 4578 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
75a70cf9 4579 gimple_seq_add_seq (&sub_seq, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
4580 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
1e8e9920 4581 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
4582 }
4583 else
4584 {
4585 x = build2 (code, TREE_TYPE (ref), ref, new_var);
4586 ref = build_outer_var_ref (var, ctx);
75a70cf9 4587 gimplify_assign (ref, x, &sub_seq);
1e8e9920 4588 }
4589 }
4590
ca4c3545 4591 if (is_gimple_omp_oacc (ctx->stmt))
4592 return;
4593
b9a16870 4594 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START),
4595 0);
75a70cf9 4596 gimple_seq_add_stmt (stmt_seqp, stmt);
1e8e9920 4597
75a70cf9 4598 gimple_seq_add_seq (stmt_seqp, sub_seq);
1e8e9920 4599
b9a16870 4600 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END),
4601 0);
75a70cf9 4602 gimple_seq_add_stmt (stmt_seqp, stmt);
1e8e9920 4603}
4604
773c5ba7 4605
1e8e9920 4606/* Generate code to implement the COPYPRIVATE clauses. */
4607
4608static void
75a70cf9 4609lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist,
1e8e9920 4610 omp_context *ctx)
4611{
4612 tree c;
4613
4614 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4615 {
cb561506 4616 tree var, new_var, ref, x;
1e8e9920 4617 bool by_ref;
389dd41b 4618 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
1e8e9920 4619
55d6e7cd 4620 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
1e8e9920 4621 continue;
4622
4623 var = OMP_CLAUSE_DECL (c);
e8a588af 4624 by_ref = use_pointer_for_field (var, NULL);
1e8e9920 4625
4626 ref = build_sender_ref (var, ctx);
cb561506 4627 x = new_var = lookup_decl_in_outer_ctx (var, ctx);
4628 if (by_ref)
4629 {
4630 x = build_fold_addr_expr_loc (clause_loc, new_var);
4631 x = fold_convert_loc (clause_loc, TREE_TYPE (ref), x);
4632 }
75a70cf9 4633 gimplify_assign (ref, x, slist);
1e8e9920 4634
cb561506 4635 ref = build_receiver_ref (var, false, ctx);
4636 if (by_ref)
4637 {
4638 ref = fold_convert_loc (clause_loc,
4639 build_pointer_type (TREE_TYPE (new_var)),
4640 ref);
4641 ref = build_fold_indirect_ref_loc (clause_loc, ref);
4642 }
1e8e9920 4643 if (is_reference (var))
4644 {
cb561506 4645 ref = fold_convert_loc (clause_loc, TREE_TYPE (new_var), ref);
182cf5a9 4646 ref = build_simple_mem_ref_loc (clause_loc, ref);
4647 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
1e8e9920 4648 }
cb561506 4649 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, ref);
1e8e9920 4650 gimplify_and_add (x, rlist);
4651 }
4652}
4653
773c5ba7 4654
1e8e9920 4655/* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
4656 and REDUCTION from the sender (aka parent) side. */
4657
4658static void
75a70cf9 4659lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
4660 omp_context *ctx)
1e8e9920 4661{
4662 tree c;
4663
4664 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4665 {
773c5ba7 4666 tree val, ref, x, var;
1e8e9920 4667 bool by_ref, do_in = false, do_out = false;
389dd41b 4668 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
1e8e9920 4669
55d6e7cd 4670 switch (OMP_CLAUSE_CODE (c))
1e8e9920 4671 {
fd6481cf 4672 case OMP_CLAUSE_PRIVATE:
4673 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
4674 break;
4675 continue;
1e8e9920 4676 case OMP_CLAUSE_FIRSTPRIVATE:
4677 case OMP_CLAUSE_COPYIN:
4678 case OMP_CLAUSE_LASTPRIVATE:
4679 case OMP_CLAUSE_REDUCTION:
bc7bff74 4680 case OMP_CLAUSE__LOOPTEMP_:
1e8e9920 4681 break;
4682 default:
4683 continue;
4684 }
4685
87b31375 4686 val = OMP_CLAUSE_DECL (c);
4687 var = lookup_decl_in_outer_ctx (val, ctx);
773c5ba7 4688
f49d7bb5 4689 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
4690 && is_global_var (var))
4691 continue;
1e8e9920 4692 if (is_variable_sized (val))
4693 continue;
e8a588af 4694 by_ref = use_pointer_for_field (val, NULL);
1e8e9920 4695
55d6e7cd 4696 switch (OMP_CLAUSE_CODE (c))
1e8e9920 4697 {
fd6481cf 4698 case OMP_CLAUSE_PRIVATE:
1e8e9920 4699 case OMP_CLAUSE_FIRSTPRIVATE:
4700 case OMP_CLAUSE_COPYIN:
bc7bff74 4701 case OMP_CLAUSE__LOOPTEMP_:
1e8e9920 4702 do_in = true;
4703 break;
4704
4705 case OMP_CLAUSE_LASTPRIVATE:
4706 if (by_ref || is_reference (val))
4707 {
4708 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4709 continue;
4710 do_in = true;
4711 }
4712 else
fd6481cf 4713 {
4714 do_out = true;
4715 if (lang_hooks.decls.omp_private_outer_ref (val))
4716 do_in = true;
4717 }
1e8e9920 4718 break;
4719
4720 case OMP_CLAUSE_REDUCTION:
4721 do_in = true;
4722 do_out = !(by_ref || is_reference (val));
4723 break;
4724
4725 default:
4726 gcc_unreachable ();
4727 }
4728
4729 if (do_in)
4730 {
4731 ref = build_sender_ref (val, ctx);
389dd41b 4732 x = by_ref ? build_fold_addr_expr_loc (clause_loc, var) : var;
75a70cf9 4733 gimplify_assign (ref, x, ilist);
fd6481cf 4734 if (is_task_ctx (ctx))
4735 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref, 1)) = NULL;
1e8e9920 4736 }
773c5ba7 4737
1e8e9920 4738 if (do_out)
4739 {
4740 ref = build_sender_ref (val, ctx);
75a70cf9 4741 gimplify_assign (var, ref, olist);
1e8e9920 4742 }
4743 }
4744}
4745
75a70cf9 4746/* Generate code to implement SHARED from the sender (aka parent)
4747 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
4748 list things that got automatically shared. */
1e8e9920 4749
4750static void
75a70cf9 4751lower_send_shared_vars (gimple_seq *ilist, gimple_seq *olist, omp_context *ctx)
1e8e9920 4752{
fd6481cf 4753 tree var, ovar, nvar, f, x, record_type;
1e8e9920 4754
4755 if (ctx->record_type == NULL)
4756 return;
773c5ba7 4757
fd6481cf 4758 record_type = ctx->srecord_type ? ctx->srecord_type : ctx->record_type;
1767a056 4759 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
1e8e9920 4760 {
4761 ovar = DECL_ABSTRACT_ORIGIN (f);
4762 nvar = maybe_lookup_decl (ovar, ctx);
4763 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
4764 continue;
4765
773c5ba7 4766 /* If CTX is a nested parallel directive. Find the immediately
4767 enclosing parallel or workshare construct that contains a
4768 mapping for OVAR. */
87b31375 4769 var = lookup_decl_in_outer_ctx (ovar, ctx);
773c5ba7 4770
e8a588af 4771 if (use_pointer_for_field (ovar, ctx))
1e8e9920 4772 {
4773 x = build_sender_ref (ovar, ctx);
773c5ba7 4774 var = build_fold_addr_expr (var);
75a70cf9 4775 gimplify_assign (x, var, ilist);
1e8e9920 4776 }
4777 else
4778 {
4779 x = build_sender_ref (ovar, ctx);
75a70cf9 4780 gimplify_assign (x, var, ilist);
1e8e9920 4781
d2263ebb 4782 if (!TREE_READONLY (var)
4783 /* We don't need to receive a new reference to a result
4784 or parm decl. In fact we may not store to it as we will
4785 invalidate any pending RSO and generate wrong gimple
4786 during inlining. */
4787 && !((TREE_CODE (var) == RESULT_DECL
4788 || TREE_CODE (var) == PARM_DECL)
4789 && DECL_BY_REFERENCE (var)))
fd6481cf 4790 {
4791 x = build_sender_ref (ovar, ctx);
75a70cf9 4792 gimplify_assign (var, x, olist);
fd6481cf 4793 }
1e8e9920 4794 }
4795 }
4796}
4797
75a70cf9 4798
4799/* A convenience function to build an empty GIMPLE_COND with just the
4800 condition. */
4801
1a91d914 4802static gcond *
75a70cf9 4803gimple_build_cond_empty (tree cond)
4804{
4805 enum tree_code pred_code;
4806 tree lhs, rhs;
4807
4808 gimple_cond_get_ops_from_tree (cond, &pred_code, &lhs, &rhs);
4809 return gimple_build_cond (pred_code, lhs, rhs, NULL_TREE, NULL_TREE);
4810}
4811
4812
48e1416a 4813/* Build the function calls to GOMP_parallel_start etc to actually
773c5ba7 4814 generate the parallel operation. REGION is the parallel region
4815 being expanded. BB is the block where to insert the code. WS_ARGS
4816 will be set if this is a call to a combined parallel+workshare
4817 construct, it contains the list of additional arguments needed by
4818 the workshare construct. */
1e8e9920 4819
4820static void
61e47ac8 4821expand_parallel_call (struct omp_region *region, basic_block bb,
1a91d914 4822 gomp_parallel *entry_stmt,
4823 vec<tree, va_gc> *ws_args)
1e8e9920 4824{
bc7bff74 4825 tree t, t1, t2, val, cond, c, clauses, flags;
75a70cf9 4826 gimple_stmt_iterator gsi;
4827 gimple stmt;
b9a16870 4828 enum built_in_function start_ix;
4829 int start_ix2;
389dd41b 4830 location_t clause_loc;
f1f41a6c 4831 vec<tree, va_gc> *args;
773c5ba7 4832
75a70cf9 4833 clauses = gimple_omp_parallel_clauses (entry_stmt);
773c5ba7 4834
bc7bff74 4835 /* Determine what flavor of GOMP_parallel we will be
773c5ba7 4836 emitting. */
bc7bff74 4837 start_ix = BUILT_IN_GOMP_PARALLEL;
773c5ba7 4838 if (is_combined_parallel (region))
4839 {
61e47ac8 4840 switch (region->inner->type)
773c5ba7 4841 {
75a70cf9 4842 case GIMPLE_OMP_FOR:
fd6481cf 4843 gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
bc7bff74 4844 start_ix2 = ((int)BUILT_IN_GOMP_PARALLEL_LOOP_STATIC
b9a16870 4845 + (region->inner->sched_kind
4846 == OMP_CLAUSE_SCHEDULE_RUNTIME
4847 ? 3 : region->inner->sched_kind));
4848 start_ix = (enum built_in_function)start_ix2;
61e47ac8 4849 break;
75a70cf9 4850 case GIMPLE_OMP_SECTIONS:
bc7bff74 4851 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS;
61e47ac8 4852 break;
4853 default:
4854 gcc_unreachable ();
773c5ba7 4855 }
773c5ba7 4856 }
1e8e9920 4857
4858 /* By default, the value of NUM_THREADS is zero (selected at run time)
4859 and there is no conditional. */
4860 cond = NULL_TREE;
4861 val = build_int_cst (unsigned_type_node, 0);
bc7bff74 4862 flags = build_int_cst (unsigned_type_node, 0);
1e8e9920 4863
4864 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
4865 if (c)
4866 cond = OMP_CLAUSE_IF_EXPR (c);
4867
4868 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
4869 if (c)
389dd41b 4870 {
4871 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
4872 clause_loc = OMP_CLAUSE_LOCATION (c);
4873 }
4874 else
4875 clause_loc = gimple_location (entry_stmt);
1e8e9920 4876
bc7bff74 4877 c = find_omp_clause (clauses, OMP_CLAUSE_PROC_BIND);
4878 if (c)
4879 flags = build_int_cst (unsigned_type_node, OMP_CLAUSE_PROC_BIND_KIND (c));
4880
1e8e9920 4881 /* Ensure 'val' is of the correct type. */
389dd41b 4882 val = fold_convert_loc (clause_loc, unsigned_type_node, val);
1e8e9920 4883
4884 /* If we found the clause 'if (cond)', build either
4885 (cond != 0) or (cond ? val : 1u). */
4886 if (cond)
4887 {
773c5ba7 4888 cond = gimple_boolify (cond);
4889
1e8e9920 4890 if (integer_zerop (val))
389dd41b 4891 val = fold_build2_loc (clause_loc,
4892 EQ_EXPR, unsigned_type_node, cond,
79acaae1 4893 build_int_cst (TREE_TYPE (cond), 0));
1e8e9920 4894 else
773c5ba7 4895 {
4896 basic_block cond_bb, then_bb, else_bb;
79acaae1 4897 edge e, e_then, e_else;
75a70cf9 4898 tree tmp_then, tmp_else, tmp_join, tmp_var;
79acaae1 4899
f9e245b2 4900 tmp_var = create_tmp_var (TREE_TYPE (val));
79acaae1 4901 if (gimple_in_ssa_p (cfun))
4902 {
f9e245b2 4903 tmp_then = make_ssa_name (tmp_var);
4904 tmp_else = make_ssa_name (tmp_var);
4905 tmp_join = make_ssa_name (tmp_var);
79acaae1 4906 }
4907 else
4908 {
4909 tmp_then = tmp_var;
4910 tmp_else = tmp_var;
4911 tmp_join = tmp_var;
4912 }
773c5ba7 4913
4302d619 4914 e = split_block_after_labels (bb);
773c5ba7 4915 cond_bb = e->src;
4916 bb = e->dest;
4917 remove_edge (e);
4918
4919 then_bb = create_empty_bb (cond_bb);
4920 else_bb = create_empty_bb (then_bb);
79acaae1 4921 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
4922 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
773c5ba7 4923
75a70cf9 4924 stmt = gimple_build_cond_empty (cond);
4925 gsi = gsi_start_bb (cond_bb);
4926 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
773c5ba7 4927
75a70cf9 4928 gsi = gsi_start_bb (then_bb);
4929 stmt = gimple_build_assign (tmp_then, val);
4930 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
773c5ba7 4931
75a70cf9 4932 gsi = gsi_start_bb (else_bb);
4933 stmt = gimple_build_assign
4934 (tmp_else, build_int_cst (unsigned_type_node, 1));
4935 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
773c5ba7 4936
4937 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
4938 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
b3083327 4939 add_bb_to_loop (then_bb, cond_bb->loop_father);
4940 add_bb_to_loop (else_bb, cond_bb->loop_father);
79acaae1 4941 e_then = make_edge (then_bb, bb, EDGE_FALLTHRU);
4942 e_else = make_edge (else_bb, bb, EDGE_FALLTHRU);
773c5ba7 4943
79acaae1 4944 if (gimple_in_ssa_p (cfun))
4945 {
1a91d914 4946 gphi *phi = create_phi_node (tmp_join, bb);
60d535d2 4947 add_phi_arg (phi, tmp_then, e_then, UNKNOWN_LOCATION);
4948 add_phi_arg (phi, tmp_else, e_else, UNKNOWN_LOCATION);
79acaae1 4949 }
4950
4951 val = tmp_join;
773c5ba7 4952 }
4953
75a70cf9 4954 gsi = gsi_start_bb (bb);
4955 val = force_gimple_operand_gsi (&gsi, val, true, NULL_TREE,
4956 false, GSI_CONTINUE_LINKING);
1e8e9920 4957 }
4958
75a70cf9 4959 gsi = gsi_last_bb (bb);
4960 t = gimple_omp_parallel_data_arg (entry_stmt);
1e8e9920 4961 if (t == NULL)
c2f47e15 4962 t1 = null_pointer_node;
1e8e9920 4963 else
c2f47e15 4964 t1 = build_fold_addr_expr (t);
75a70cf9 4965 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
773c5ba7 4966
bc7bff74 4967 vec_alloc (args, 4 + vec_safe_length (ws_args));
f1f41a6c 4968 args->quick_push (t2);
4969 args->quick_push (t1);
4970 args->quick_push (val);
4971 if (ws_args)
4972 args->splice (*ws_args);
bc7bff74 4973 args->quick_push (flags);
414c3a2c 4974
4975 t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
b9a16870 4976 builtin_decl_explicit (start_ix), args);
773c5ba7 4977
75a70cf9 4978 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4979 false, GSI_CONTINUE_LINKING);
1e8e9920 4980}
4981
40750995 4982/* Insert a function call whose name is FUNC_NAME with the information from
4983 ENTRY_STMT into the basic_block BB. */
4984
4985static void
1a91d914 4986expand_cilk_for_call (basic_block bb, gomp_parallel *entry_stmt,
40750995 4987 vec <tree, va_gc> *ws_args)
4988{
4989 tree t, t1, t2;
4990 gimple_stmt_iterator gsi;
4991 vec <tree, va_gc> *args;
4992
4993 gcc_assert (vec_safe_length (ws_args) == 2);
4994 tree func_name = (*ws_args)[0];
4995 tree grain = (*ws_args)[1];
4996
4997 tree clauses = gimple_omp_parallel_clauses (entry_stmt);
4998 tree count = find_omp_clause (clauses, OMP_CLAUSE__CILK_FOR_COUNT_);
4999 gcc_assert (count != NULL_TREE);
5000 count = OMP_CLAUSE_OPERAND (count, 0);
5001
5002 gsi = gsi_last_bb (bb);
5003 t = gimple_omp_parallel_data_arg (entry_stmt);
5004 if (t == NULL)
5005 t1 = null_pointer_node;
5006 else
5007 t1 = build_fold_addr_expr (t);
5008 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
5009
5010 vec_alloc (args, 4);
5011 args->quick_push (t2);
5012 args->quick_push (t1);
5013 args->quick_push (count);
5014 args->quick_push (grain);
5015 t = build_call_expr_loc_vec (UNKNOWN_LOCATION, func_name, args);
5016
5017 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, false,
5018 GSI_CONTINUE_LINKING);
5019}
773c5ba7 5020
fd6481cf 5021/* Build the function call to GOMP_task to actually
5022 generate the task operation. BB is the block where to insert the code. */
5023
5024static void
1a91d914 5025expand_task_call (basic_block bb, gomp_task *entry_stmt)
fd6481cf 5026{
bc7bff74 5027 tree t, t1, t2, t3, flags, cond, c, c2, clauses, depend;
75a70cf9 5028 gimple_stmt_iterator gsi;
389dd41b 5029 location_t loc = gimple_location (entry_stmt);
fd6481cf 5030
75a70cf9 5031 clauses = gimple_omp_task_clauses (entry_stmt);
fd6481cf 5032
fd6481cf 5033 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
5034 if (c)
5035 cond = gimple_boolify (OMP_CLAUSE_IF_EXPR (c));
5036 else
5037 cond = boolean_true_node;
5038
5039 c = find_omp_clause (clauses, OMP_CLAUSE_UNTIED);
2169f33b 5040 c2 = find_omp_clause (clauses, OMP_CLAUSE_MERGEABLE);
bc7bff74 5041 depend = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
2169f33b 5042 flags = build_int_cst (unsigned_type_node,
bc7bff74 5043 (c ? 1 : 0) + (c2 ? 4 : 0) + (depend ? 8 : 0));
2169f33b 5044
5045 c = find_omp_clause (clauses, OMP_CLAUSE_FINAL);
5046 if (c)
5047 {
5048 c = gimple_boolify (OMP_CLAUSE_FINAL_EXPR (c));
5049 c = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, c,
5050 build_int_cst (unsigned_type_node, 2),
5051 build_int_cst (unsigned_type_node, 0));
5052 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node, flags, c);
5053 }
bc7bff74 5054 if (depend)
5055 depend = OMP_CLAUSE_DECL (depend);
5056 else
5057 depend = build_int_cst (ptr_type_node, 0);
fd6481cf 5058
75a70cf9 5059 gsi = gsi_last_bb (bb);
5060 t = gimple_omp_task_data_arg (entry_stmt);
fd6481cf 5061 if (t == NULL)
5062 t2 = null_pointer_node;
5063 else
389dd41b 5064 t2 = build_fold_addr_expr_loc (loc, t);
5065 t1 = build_fold_addr_expr_loc (loc, gimple_omp_task_child_fn (entry_stmt));
75a70cf9 5066 t = gimple_omp_task_copy_fn (entry_stmt);
fd6481cf 5067 if (t == NULL)
5068 t3 = null_pointer_node;
5069 else
389dd41b 5070 t3 = build_fold_addr_expr_loc (loc, t);
fd6481cf 5071
b9a16870 5072 t = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK),
bc7bff74 5073 8, t1, t2, t3,
75a70cf9 5074 gimple_omp_task_arg_size (entry_stmt),
bc7bff74 5075 gimple_omp_task_arg_align (entry_stmt), cond, flags,
5076 depend);
fd6481cf 5077
75a70cf9 5078 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5079 false, GSI_CONTINUE_LINKING);
fd6481cf 5080}
5081
5082
75a70cf9 5083/* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
5084 catch handler and return it. This prevents programs from violating the
5085 structured block semantics with throws. */
1e8e9920 5086
75a70cf9 5087static gimple_seq
5088maybe_catch_exception (gimple_seq body)
1e8e9920 5089{
e38def9c 5090 gimple g;
5091 tree decl;
1e8e9920 5092
5093 if (!flag_exceptions)
75a70cf9 5094 return body;
1e8e9920 5095
596981c8 5096 if (lang_hooks.eh_protect_cleanup_actions != NULL)
5097 decl = lang_hooks.eh_protect_cleanup_actions ();
1e8e9920 5098 else
b9a16870 5099 decl = builtin_decl_explicit (BUILT_IN_TRAP);
75a70cf9 5100
e38def9c 5101 g = gimple_build_eh_must_not_throw (decl);
5102 g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g),
75a70cf9 5103 GIMPLE_TRY_CATCH);
1e8e9920 5104
e38def9c 5105 return gimple_seq_alloc_with_stmt (g);
1e8e9920 5106}
5107
773c5ba7 5108/* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
1e8e9920 5109
773c5ba7 5110static tree
f1f41a6c 5111vec2chain (vec<tree, va_gc> *v)
1e8e9920 5112{
2ab2ce89 5113 tree chain = NULL_TREE, t;
5114 unsigned ix;
1e8e9920 5115
f1f41a6c 5116 FOR_EACH_VEC_SAFE_ELT_REVERSE (v, ix, t)
773c5ba7 5117 {
1767a056 5118 DECL_CHAIN (t) = chain;
2ab2ce89 5119 chain = t;
773c5ba7 5120 }
1e8e9920 5121
2ab2ce89 5122 return chain;
773c5ba7 5123}
1e8e9920 5124
1e8e9920 5125
773c5ba7 5126/* Remove barriers in REGION->EXIT's block. Note that this is only
75a70cf9 5127 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
5128 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
5129 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
773c5ba7 5130 removed. */
1e8e9920 5131
773c5ba7 5132static void
5133remove_exit_barrier (struct omp_region *region)
5134{
75a70cf9 5135 gimple_stmt_iterator gsi;
773c5ba7 5136 basic_block exit_bb;
61e47ac8 5137 edge_iterator ei;
5138 edge e;
75a70cf9 5139 gimple stmt;
4a04f4b4 5140 int any_addressable_vars = -1;
1e8e9920 5141
61e47ac8 5142 exit_bb = region->exit;
1e8e9920 5143
5056ba1a 5144 /* If the parallel region doesn't return, we don't have REGION->EXIT
5145 block at all. */
5146 if (! exit_bb)
5147 return;
5148
75a70cf9 5149 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
5150 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
61e47ac8 5151 statements that can appear in between are extremely limited -- no
5152 memory operations at all. Here, we allow nothing at all, so the
75a70cf9 5153 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
5154 gsi = gsi_last_bb (exit_bb);
5155 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
5156 gsi_prev (&gsi);
5157 if (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
773c5ba7 5158 return;
1e8e9920 5159
61e47ac8 5160 FOR_EACH_EDGE (e, ei, exit_bb->preds)
5161 {
75a70cf9 5162 gsi = gsi_last_bb (e->src);
5163 if (gsi_end_p (gsi))
61e47ac8 5164 continue;
75a70cf9 5165 stmt = gsi_stmt (gsi);
4a04f4b4 5166 if (gimple_code (stmt) == GIMPLE_OMP_RETURN
5167 && !gimple_omp_return_nowait_p (stmt))
5168 {
5169 /* OpenMP 3.0 tasks unfortunately prevent this optimization
5170 in many cases. If there could be tasks queued, the barrier
5171 might be needed to let the tasks run before some local
5172 variable of the parallel that the task uses as shared
5173 runs out of scope. The task can be spawned either
5174 from within current function (this would be easy to check)
5175 or from some function it calls and gets passed an address
5176 of such a variable. */
5177 if (any_addressable_vars < 0)
5178 {
1a91d914 5179 gomp_parallel *parallel_stmt
5180 = as_a <gomp_parallel *> (last_stmt (region->entry));
4a04f4b4 5181 tree child_fun = gimple_omp_parallel_child_fn (parallel_stmt);
2ab2ce89 5182 tree local_decls, block, decl;
5183 unsigned ix;
4a04f4b4 5184
5185 any_addressable_vars = 0;
2ab2ce89 5186 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun), ix, decl)
5187 if (TREE_ADDRESSABLE (decl))
4a04f4b4 5188 {
5189 any_addressable_vars = 1;
5190 break;
5191 }
5192 for (block = gimple_block (stmt);
5193 !any_addressable_vars
5194 && block
5195 && TREE_CODE (block) == BLOCK;
5196 block = BLOCK_SUPERCONTEXT (block))
5197 {
5198 for (local_decls = BLOCK_VARS (block);
5199 local_decls;
1767a056 5200 local_decls = DECL_CHAIN (local_decls))
4a04f4b4 5201 if (TREE_ADDRESSABLE (local_decls))
5202 {
5203 any_addressable_vars = 1;
5204 break;
5205 }
5206 if (block == gimple_block (parallel_stmt))
5207 break;
5208 }
5209 }
5210 if (!any_addressable_vars)
5211 gimple_omp_return_set_nowait (stmt);
5212 }
61e47ac8 5213 }
1e8e9920 5214}
5215
61e47ac8 5216static void
5217remove_exit_barriers (struct omp_region *region)
5218{
75a70cf9 5219 if (region->type == GIMPLE_OMP_PARALLEL)
61e47ac8 5220 remove_exit_barrier (region);
5221
5222 if (region->inner)
5223 {
5224 region = region->inner;
5225 remove_exit_barriers (region);
5226 while (region->next)
5227 {
5228 region = region->next;
5229 remove_exit_barriers (region);
5230 }
5231 }
5232}
773c5ba7 5233
658b4427 5234/* Optimize omp_get_thread_num () and omp_get_num_threads ()
5235 calls. These can't be declared as const functions, but
5236 within one parallel body they are constant, so they can be
5237 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
fd6481cf 5238 which are declared const. Similarly for task body, except
5239 that in untied task omp_get_thread_num () can change at any task
5240 scheduling point. */
658b4427 5241
5242static void
75a70cf9 5243optimize_omp_library_calls (gimple entry_stmt)
658b4427 5244{
5245 basic_block bb;
75a70cf9 5246 gimple_stmt_iterator gsi;
b9a16870 5247 tree thr_num_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
5248 tree thr_num_id = DECL_ASSEMBLER_NAME (thr_num_tree);
5249 tree num_thr_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
5250 tree num_thr_id = DECL_ASSEMBLER_NAME (num_thr_tree);
75a70cf9 5251 bool untied_task = (gimple_code (entry_stmt) == GIMPLE_OMP_TASK
5252 && find_omp_clause (gimple_omp_task_clauses (entry_stmt),
fd6481cf 5253 OMP_CLAUSE_UNTIED) != NULL);
658b4427 5254
fc00614f 5255 FOR_EACH_BB_FN (bb, cfun)
75a70cf9 5256 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
658b4427 5257 {
75a70cf9 5258 gimple call = gsi_stmt (gsi);
658b4427 5259 tree decl;
5260
75a70cf9 5261 if (is_gimple_call (call)
5262 && (decl = gimple_call_fndecl (call))
658b4427 5263 && DECL_EXTERNAL (decl)
5264 && TREE_PUBLIC (decl)
5265 && DECL_INITIAL (decl) == NULL)
5266 {
5267 tree built_in;
5268
5269 if (DECL_NAME (decl) == thr_num_id)
fd6481cf 5270 {
5271 /* In #pragma omp task untied omp_get_thread_num () can change
5272 during the execution of the task region. */
5273 if (untied_task)
5274 continue;
b9a16870 5275 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
fd6481cf 5276 }
658b4427 5277 else if (DECL_NAME (decl) == num_thr_id)
b9a16870 5278 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
658b4427 5279 else
5280 continue;
5281
5282 if (DECL_ASSEMBLER_NAME (decl) != DECL_ASSEMBLER_NAME (built_in)
75a70cf9 5283 || gimple_call_num_args (call) != 0)
658b4427 5284 continue;
5285
5286 if (flag_exceptions && !TREE_NOTHROW (decl))
5287 continue;
5288
5289 if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
1ea6a73c 5290 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl)),
5291 TREE_TYPE (TREE_TYPE (built_in))))
658b4427 5292 continue;
5293
0acacf9e 5294 gimple_call_set_fndecl (call, built_in);
658b4427 5295 }
5296 }
5297}
5298
8e6b4515 5299/* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
5300 regimplified. */
5301
5302static tree
5303expand_omp_regimplify_p (tree *tp, int *walk_subtrees, void *)
5304{
5305 tree t = *tp;
5306
5307 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
5308 if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t))
5309 return t;
5310
5311 if (TREE_CODE (t) == ADDR_EXPR)
5312 recompute_tree_invariant_for_addr_expr (t);
5313
5314 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
5315 return NULL_TREE;
5316}
5317
3d483a94 5318/* Prepend TO = FROM assignment before *GSI_P. */
5319
5320static void
5321expand_omp_build_assign (gimple_stmt_iterator *gsi_p, tree to, tree from)
5322{
5323 bool simple_p = DECL_P (to) && TREE_ADDRESSABLE (to);
5324 from = force_gimple_operand_gsi (gsi_p, from, simple_p, NULL_TREE,
5325 true, GSI_SAME_STMT);
5326 gimple stmt = gimple_build_assign (to, from);
5327 gsi_insert_before (gsi_p, stmt, GSI_SAME_STMT);
5328 if (walk_tree (&from, expand_omp_regimplify_p, NULL, NULL)
5329 || walk_tree (&to, expand_omp_regimplify_p, NULL, NULL))
5330 {
5331 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
5332 gimple_regimplify_operands (stmt, &gsi);
5333 }
5334}
5335
fd6481cf 5336/* Expand the OpenMP parallel or task directive starting at REGION. */
1e8e9920 5337
5338static void
fd6481cf 5339expand_omp_taskreg (struct omp_region *region)
1e8e9920 5340{
773c5ba7 5341 basic_block entry_bb, exit_bb, new_bb;
87d4aa85 5342 struct function *child_cfun;
414c3a2c 5343 tree child_fn, block, t;
75a70cf9 5344 gimple_stmt_iterator gsi;
5345 gimple entry_stmt, stmt;
773c5ba7 5346 edge e;
f1f41a6c 5347 vec<tree, va_gc> *ws_args;
773c5ba7 5348
61e47ac8 5349 entry_stmt = last_stmt (region->entry);
75a70cf9 5350 child_fn = gimple_omp_taskreg_child_fn (entry_stmt);
773c5ba7 5351 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
773c5ba7 5352
61e47ac8 5353 entry_bb = region->entry;
b25f70fd 5354 if (gimple_code (entry_stmt) == GIMPLE_OMP_TASK)
5355 exit_bb = region->cont;
5356 else
5357 exit_bb = region->exit;
773c5ba7 5358
40750995 5359 bool is_cilk_for
5360 = (flag_cilkplus
5361 && gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL
5362 && find_omp_clause (gimple_omp_parallel_clauses (entry_stmt),
5363 OMP_CLAUSE__CILK_FOR_COUNT_) != NULL_TREE);
5364
5365 if (is_cilk_for)
5366 /* If it is a _Cilk_for statement, it is modelled *like* a parallel for,
5367 and the inner statement contains the name of the built-in function
5368 and grain. */
5369 ws_args = region->inner->ws_args;
5370 else if (is_combined_parallel (region))
61e47ac8 5371 ws_args = region->ws_args;
773c5ba7 5372 else
414c3a2c 5373 ws_args = NULL;
1e8e9920 5374
61e47ac8 5375 if (child_cfun->cfg)
1e8e9920 5376 {
773c5ba7 5377 /* Due to inlining, it may happen that we have already outlined
5378 the region, in which case all we need to do is make the
5379 sub-graph unreachable and emit the parallel call. */
5380 edge entry_succ_e, exit_succ_e;
773c5ba7 5381
5382 entry_succ_e = single_succ_edge (entry_bb);
773c5ba7 5383
75a70cf9 5384 gsi = gsi_last_bb (entry_bb);
5385 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_PARALLEL
5386 || gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_TASK);
5387 gsi_remove (&gsi, true);
773c5ba7 5388
5389 new_bb = entry_bb;
03ed154b 5390 if (exit_bb)
5391 {
5392 exit_succ_e = single_succ_edge (exit_bb);
5393 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
5394 }
79acaae1 5395 remove_edge_and_dominated_blocks (entry_succ_e);
1e8e9920 5396 }
773c5ba7 5397 else
5398 {
501bdd19 5399 unsigned srcidx, dstidx, num;
2ab2ce89 5400
773c5ba7 5401 /* If the parallel region needs data sent from the parent
3480139d 5402 function, then the very first statement (except possible
5403 tree profile counter updates) of the parallel body
773c5ba7 5404 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
5405 &.OMP_DATA_O is passed as an argument to the child function,
5406 we need to replace it with the argument as seen by the child
5407 function.
5408
5409 In most cases, this will end up being the identity assignment
5410 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
5411 a function call that has been inlined, the original PARM_DECL
5412 .OMP_DATA_I may have been converted into a different local
5413 variable. In which case, we need to keep the assignment. */
75a70cf9 5414 if (gimple_omp_taskreg_data_arg (entry_stmt))
773c5ba7 5415 {
b25f70fd 5416 basic_block entry_succ_bb
5417 = single_succ_p (entry_bb) ? single_succ (entry_bb)
5418 : FALLTHRU_EDGE (entry_bb)->dest;
75a70cf9 5419 tree arg, narg;
5420 gimple parcopy_stmt = NULL;
1e8e9920 5421
75a70cf9 5422 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
3480139d 5423 {
75a70cf9 5424 gimple stmt;
3480139d 5425
75a70cf9 5426 gcc_assert (!gsi_end_p (gsi));
5427 stmt = gsi_stmt (gsi);
5428 if (gimple_code (stmt) != GIMPLE_ASSIGN)
cc6b725b 5429 continue;
5430
75a70cf9 5431 if (gimple_num_ops (stmt) == 2)
3480139d 5432 {
75a70cf9 5433 tree arg = gimple_assign_rhs1 (stmt);
5434
5435 /* We're ignore the subcode because we're
5436 effectively doing a STRIP_NOPS. */
5437
5438 if (TREE_CODE (arg) == ADDR_EXPR
5439 && TREE_OPERAND (arg, 0)
5440 == gimple_omp_taskreg_data_arg (entry_stmt))
5441 {
5442 parcopy_stmt = stmt;
5443 break;
5444 }
3480139d 5445 }
5446 }
79acaae1 5447
75a70cf9 5448 gcc_assert (parcopy_stmt != NULL);
79acaae1 5449 arg = DECL_ARGUMENTS (child_fn);
5450
5451 if (!gimple_in_ssa_p (cfun))
5452 {
75a70cf9 5453 if (gimple_assign_lhs (parcopy_stmt) == arg)
5454 gsi_remove (&gsi, true);
79acaae1 5455 else
75a70cf9 5456 {
5457 /* ?? Is setting the subcode really necessary ?? */
5458 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (arg));
5459 gimple_assign_set_rhs1 (parcopy_stmt, arg);
5460 }
79acaae1 5461 }
5462 else
5463 {
5464 /* If we are in ssa form, we must load the value from the default
5465 definition of the argument. That should not be defined now,
5466 since the argument is not used uninitialized. */
c6dfe037 5467 gcc_assert (ssa_default_def (cfun, arg) == NULL);
75a70cf9 5468 narg = make_ssa_name (arg, gimple_build_nop ());
c6dfe037 5469 set_ssa_default_def (cfun, arg, narg);
75a70cf9 5470 /* ?? Is setting the subcode really necessary ?? */
5471 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (narg));
5472 gimple_assign_set_rhs1 (parcopy_stmt, narg);
79acaae1 5473 update_stmt (parcopy_stmt);
5474 }
773c5ba7 5475 }
5476
5477 /* Declare local variables needed in CHILD_CFUN. */
5478 block = DECL_INITIAL (child_fn);
2ab2ce89 5479 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
e1a7ccb9 5480 /* The gimplifier could record temporaries in parallel/task block
5481 rather than in containing function's local_decls chain,
5482 which would mean cgraph missed finalizing them. Do it now. */
1767a056 5483 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
e1a7ccb9 5484 if (TREE_CODE (t) == VAR_DECL
5485 && TREE_STATIC (t)
5486 && !DECL_EXTERNAL (t))
97221fd7 5487 varpool_node::finalize_decl (t);
75a70cf9 5488 DECL_SAVED_TREE (child_fn) = NULL;
e3a19533 5489 /* We'll create a CFG for child_fn, so no gimple body is needed. */
5490 gimple_set_body (child_fn, NULL);
1d22f541 5491 TREE_USED (block) = 1;
773c5ba7 5492
79acaae1 5493 /* Reset DECL_CONTEXT on function arguments. */
1767a056 5494 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
773c5ba7 5495 DECL_CONTEXT (t) = child_fn;
5496
75a70cf9 5497 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
5498 so that it can be moved to the child function. */
5499 gsi = gsi_last_bb (entry_bb);
5500 stmt = gsi_stmt (gsi);
5501 gcc_assert (stmt && (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
5502 || gimple_code (stmt) == GIMPLE_OMP_TASK));
75a70cf9 5503 e = split_block (entry_bb, stmt);
923635e7 5504 gsi_remove (&gsi, true);
773c5ba7 5505 entry_bb = e->dest;
b25f70fd 5506 edge e2 = NULL;
5507 if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
5508 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
5509 else
5510 {
5511 e2 = make_edge (e->src, BRANCH_EDGE (entry_bb)->dest, EDGE_ABNORMAL);
5512 gcc_assert (e2->dest == region->exit);
5513 remove_edge (BRANCH_EDGE (entry_bb));
5514 set_immediate_dominator (CDI_DOMINATORS, e2->dest, e->src);
5515 gsi = gsi_last_bb (region->exit);
5516 gcc_assert (!gsi_end_p (gsi)
5517 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
5518 gsi_remove (&gsi, true);
5519 }
773c5ba7 5520
b25f70fd 5521 /* Convert GIMPLE_OMP_{RETURN,CONTINUE} into a RETURN_EXPR. */
5056ba1a 5522 if (exit_bb)
5523 {
75a70cf9 5524 gsi = gsi_last_bb (exit_bb);
5525 gcc_assert (!gsi_end_p (gsi)
b25f70fd 5526 && (gimple_code (gsi_stmt (gsi))
5527 == (e2 ? GIMPLE_OMP_CONTINUE : GIMPLE_OMP_RETURN)));
75a70cf9 5528 stmt = gimple_build_return (NULL);
5529 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
5530 gsi_remove (&gsi, true);
5056ba1a 5531 }
79acaae1 5532
5533 /* Move the parallel region into CHILD_CFUN. */
48e1416a 5534
79acaae1 5535 if (gimple_in_ssa_p (cfun))
5536 {
bcaa2770 5537 init_tree_ssa (child_cfun);
5084b2e4 5538 init_ssa_operands (child_cfun);
5539 child_cfun->gimple_df->in_ssa_p = true;
1d22f541 5540 block = NULL_TREE;
79acaae1 5541 }
1d22f541 5542 else
75a70cf9 5543 block = gimple_block (entry_stmt);
1d22f541 5544
5545 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
79acaae1 5546 if (exit_bb)
5547 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
b25f70fd 5548 if (e2)
5549 {
5550 basic_block dest_bb = e2->dest;
5551 if (!exit_bb)
5552 make_edge (new_bb, dest_bb, EDGE_FALLTHRU);
5553 remove_edge (e2);
5554 set_immediate_dominator (CDI_DOMINATORS, dest_bb, new_bb);
5555 }
04c2922b 5556 /* When the OMP expansion process cannot guarantee an up-to-date
5557 loop tree arrange for the child function to fixup loops. */
5558 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
5559 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
79acaae1 5560
1d22f541 5561 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
f1f41a6c 5562 num = vec_safe_length (child_cfun->local_decls);
501bdd19 5563 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
5564 {
f1f41a6c 5565 t = (*child_cfun->local_decls)[srcidx];
501bdd19 5566 if (DECL_CONTEXT (t) == cfun->decl)
5567 continue;
5568 if (srcidx != dstidx)
f1f41a6c 5569 (*child_cfun->local_decls)[dstidx] = t;
501bdd19 5570 dstidx++;
5571 }
5572 if (dstidx != num)
f1f41a6c 5573 vec_safe_truncate (child_cfun->local_decls, dstidx);
1d22f541 5574
79acaae1 5575 /* Inform the callgraph about the new function. */
9918db44 5576 child_cfun->curr_properties = cfun->curr_properties;
5577 child_cfun->has_simduid_loops |= cfun->has_simduid_loops;
5578 child_cfun->has_force_vectorize_loops |= cfun->has_force_vectorize_loops;
47300487 5579 cgraph_node *node = cgraph_node::get_create (child_fn);
5580 node->parallelized_function = 1;
415d1b9a 5581 cgraph_node::add_new_function (child_fn, true);
79acaae1 5582
5583 /* Fix the callgraph edges for child_cfun. Those for cfun will be
5584 fixed in a following pass. */
5585 push_cfun (child_cfun);
658b4427 5586 if (optimize)
fd6481cf 5587 optimize_omp_library_calls (entry_stmt);
35ee1c66 5588 cgraph_edge::rebuild_edges ();
fbe86b1b 5589
5590 /* Some EH regions might become dead, see PR34608. If
5591 pass_cleanup_cfg isn't the first pass to happen with the
5592 new child, these dead EH edges might cause problems.
5593 Clean them up now. */
5594 if (flag_exceptions)
5595 {
5596 basic_block bb;
fbe86b1b 5597 bool changed = false;
5598
fc00614f 5599 FOR_EACH_BB_FN (bb, cfun)
75a70cf9 5600 changed |= gimple_purge_dead_eh_edges (bb);
fbe86b1b 5601 if (changed)
5602 cleanup_tree_cfg ();
fbe86b1b 5603 }
dd277d48 5604 if (gimple_in_ssa_p (cfun))
5605 update_ssa (TODO_update_ssa);
79acaae1 5606 pop_cfun ();
773c5ba7 5607 }
48e1416a 5608
773c5ba7 5609 /* Emit a library call to launch the children threads. */
40750995 5610 if (is_cilk_for)
1a91d914 5611 expand_cilk_for_call (new_bb,
5612 as_a <gomp_parallel *> (entry_stmt), ws_args);
40750995 5613 else if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
1a91d914 5614 expand_parallel_call (region, new_bb,
5615 as_a <gomp_parallel *> (entry_stmt), ws_args);
fd6481cf 5616 else
1a91d914 5617 expand_task_call (new_bb, as_a <gomp_task *> (entry_stmt));
083152fb 5618 if (gimple_in_ssa_p (cfun))
5619 update_ssa (TODO_update_ssa_only_virtuals);
1e8e9920 5620}
5621
773c5ba7 5622
3d483a94 5623/* Helper function for expand_omp_{for_*,simd}. If this is the outermost
5624 of the combined collapse > 1 loop constructs, generate code like:
5625 if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
5626 if (cond3 is <)
5627 adj = STEP3 - 1;
5628 else
5629 adj = STEP3 + 1;
5630 count3 = (adj + N32 - N31) / STEP3;
5631 if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
5632 if (cond2 is <)
5633 adj = STEP2 - 1;
5634 else
5635 adj = STEP2 + 1;
5636 count2 = (adj + N22 - N21) / STEP2;
5637 if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
5638 if (cond1 is <)
5639 adj = STEP1 - 1;
5640 else
5641 adj = STEP1 + 1;
5642 count1 = (adj + N12 - N11) / STEP1;
5643 count = count1 * count2 * count3;
5644 Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
5645 count = 0;
bc7bff74 5646 and set ZERO_ITER_BB to that bb. If this isn't the outermost
5647 of the combined loop constructs, just initialize COUNTS array
5648 from the _looptemp_ clauses. */
3d483a94 5649
5650/* NOTE: It *could* be better to moosh all of the BBs together,
5651 creating one larger BB with all the computation and the unexpected
5652 jump at the end. I.e.
5653
5654 bool zero3, zero2, zero1, zero;
5655
5656 zero3 = N32 c3 N31;
5657 count3 = (N32 - N31) /[cl] STEP3;
5658 zero2 = N22 c2 N21;
5659 count2 = (N22 - N21) /[cl] STEP2;
5660 zero1 = N12 c1 N11;
5661 count1 = (N12 - N11) /[cl] STEP1;
5662 zero = zero3 || zero2 || zero1;
5663 count = count1 * count2 * count3;
5664 if (__builtin_expect(zero, false)) goto zero_iter_bb;
5665
5666 After all, we expect the zero=false, and thus we expect to have to
5667 evaluate all of the comparison expressions, so short-circuiting
5668 oughtn't be a win. Since the condition isn't protecting a
5669 denominator, we're not concerned about divide-by-zero, so we can
5670 fully evaluate count even if a numerator turned out to be wrong.
5671
5672 It seems like putting this all together would create much better
5673 scheduling opportunities, and less pressure on the chip's branch
5674 predictor. */
5675
5676static void
5677expand_omp_for_init_counts (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
5678 basic_block &entry_bb, tree *counts,
5679 basic_block &zero_iter_bb, int &first_zero_iter,
5680 basic_block &l2_dom_bb)
5681{
5682 tree t, type = TREE_TYPE (fd->loop.v);
3d483a94 5683 edge e, ne;
5684 int i;
5685
5686 /* Collapsed loops need work for expansion into SSA form. */
5687 gcc_assert (!gimple_in_ssa_p (cfun));
5688
bc7bff74 5689 if (gimple_omp_for_combined_into_p (fd->for_stmt)
5690 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
5691 {
5692 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5693 isn't supposed to be handled, as the inner loop doesn't
5694 use it. */
5695 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
5696 OMP_CLAUSE__LOOPTEMP_);
5697 gcc_assert (innerc);
5698 for (i = 0; i < fd->collapse; i++)
5699 {
5700 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5701 OMP_CLAUSE__LOOPTEMP_);
5702 gcc_assert (innerc);
5703 if (i)
5704 counts[i] = OMP_CLAUSE_DECL (innerc);
5705 else
5706 counts[0] = NULL_TREE;
5707 }
5708 return;
5709 }
5710
3d483a94 5711 for (i = 0; i < fd->collapse; i++)
5712 {
5713 tree itype = TREE_TYPE (fd->loops[i].v);
5714
5715 if (SSA_VAR_P (fd->loop.n2)
5716 && ((t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
5717 fold_convert (itype, fd->loops[i].n1),
5718 fold_convert (itype, fd->loops[i].n2)))
5719 == NULL_TREE || !integer_onep (t)))
5720 {
1a91d914 5721 gcond *cond_stmt;
3d483a94 5722 tree n1, n2;
5723 n1 = fold_convert (itype, unshare_expr (fd->loops[i].n1));
5724 n1 = force_gimple_operand_gsi (gsi, n1, true, NULL_TREE,
5725 true, GSI_SAME_STMT);
5726 n2 = fold_convert (itype, unshare_expr (fd->loops[i].n2));
5727 n2 = force_gimple_operand_gsi (gsi, n2, true, NULL_TREE,
5728 true, GSI_SAME_STMT);
1a91d914 5729 cond_stmt = gimple_build_cond (fd->loops[i].cond_code, n1, n2,
5730 NULL_TREE, NULL_TREE);
5731 gsi_insert_before (gsi, cond_stmt, GSI_SAME_STMT);
5732 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
3d483a94 5733 expand_omp_regimplify_p, NULL, NULL)
1a91d914 5734 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
3d483a94 5735 expand_omp_regimplify_p, NULL, NULL))
5736 {
1a91d914 5737 *gsi = gsi_for_stmt (cond_stmt);
5738 gimple_regimplify_operands (cond_stmt, gsi);
3d483a94 5739 }
1a91d914 5740 e = split_block (entry_bb, cond_stmt);
3d483a94 5741 if (zero_iter_bb == NULL)
5742 {
1a91d914 5743 gassign *assign_stmt;
3d483a94 5744 first_zero_iter = i;
5745 zero_iter_bb = create_empty_bb (entry_bb);
b3083327 5746 add_bb_to_loop (zero_iter_bb, entry_bb->loop_father);
3d483a94 5747 *gsi = gsi_after_labels (zero_iter_bb);
1a91d914 5748 assign_stmt = gimple_build_assign (fd->loop.n2,
5749 build_zero_cst (type));
5750 gsi_insert_before (gsi, assign_stmt, GSI_SAME_STMT);
3d483a94 5751 set_immediate_dominator (CDI_DOMINATORS, zero_iter_bb,
5752 entry_bb);
5753 }
5754 ne = make_edge (entry_bb, zero_iter_bb, EDGE_FALSE_VALUE);
5755 ne->probability = REG_BR_PROB_BASE / 2000 - 1;
5756 e->flags = EDGE_TRUE_VALUE;
5757 e->probability = REG_BR_PROB_BASE - ne->probability;
5758 if (l2_dom_bb == NULL)
5759 l2_dom_bb = entry_bb;
5760 entry_bb = e->dest;
5761 *gsi = gsi_last_bb (entry_bb);
5762 }
5763
5764 if (POINTER_TYPE_P (itype))
5765 itype = signed_type_for (itype);
5766 t = build_int_cst (itype, (fd->loops[i].cond_code == LT_EXPR
5767 ? -1 : 1));
5768 t = fold_build2 (PLUS_EXPR, itype,
5769 fold_convert (itype, fd->loops[i].step), t);
5770 t = fold_build2 (PLUS_EXPR, itype, t,
5771 fold_convert (itype, fd->loops[i].n2));
5772 t = fold_build2 (MINUS_EXPR, itype, t,
5773 fold_convert (itype, fd->loops[i].n1));
5774 /* ?? We could probably use CEIL_DIV_EXPR instead of
5775 TRUNC_DIV_EXPR and adjusting by hand. Unless we can't
5776 generate the same code in the end because generically we
5777 don't know that the values involved must be negative for
5778 GT?? */
5779 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
5780 t = fold_build2 (TRUNC_DIV_EXPR, itype,
5781 fold_build1 (NEGATE_EXPR, itype, t),
5782 fold_build1 (NEGATE_EXPR, itype,
5783 fold_convert (itype,
5784 fd->loops[i].step)));
5785 else
5786 t = fold_build2 (TRUNC_DIV_EXPR, itype, t,
5787 fold_convert (itype, fd->loops[i].step));
5788 t = fold_convert (type, t);
5789 if (TREE_CODE (t) == INTEGER_CST)
5790 counts[i] = t;
5791 else
5792 {
5793 counts[i] = create_tmp_reg (type, ".count");
5794 expand_omp_build_assign (gsi, counts[i], t);
5795 }
5796 if (SSA_VAR_P (fd->loop.n2))
5797 {
5798 if (i == 0)
5799 t = counts[0];
5800 else
5801 t = fold_build2 (MULT_EXPR, type, fd->loop.n2, counts[i]);
5802 expand_omp_build_assign (gsi, fd->loop.n2, t);
5803 }
5804 }
5805}
5806
5807
5808/* Helper function for expand_omp_{for_*,simd}. Generate code like:
5809 T = V;
5810 V3 = N31 + (T % count3) * STEP3;
5811 T = T / count3;
5812 V2 = N21 + (T % count2) * STEP2;
5813 T = T / count2;
5814 V1 = N11 + T * STEP1;
bc7bff74 5815 if this loop doesn't have an inner loop construct combined with it.
5816 If it does have an inner loop construct combined with it and the
5817 iteration count isn't known constant, store values from counts array
5818 into its _looptemp_ temporaries instead. */
3d483a94 5819
5820static void
5821expand_omp_for_init_vars (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
bc7bff74 5822 tree *counts, gimple inner_stmt, tree startvar)
3d483a94 5823{
5824 int i;
bc7bff74 5825 if (gimple_omp_for_combined_p (fd->for_stmt))
5826 {
5827 /* If fd->loop.n2 is constant, then no propagation of the counts
5828 is needed, they are constant. */
5829 if (TREE_CODE (fd->loop.n2) == INTEGER_CST)
5830 return;
5831
5832 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
5833 ? gimple_omp_parallel_clauses (inner_stmt)
5834 : gimple_omp_for_clauses (inner_stmt);
5835 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5836 isn't supposed to be handled, as the inner loop doesn't
5837 use it. */
5838 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
5839 gcc_assert (innerc);
5840 for (i = 0; i < fd->collapse; i++)
5841 {
5842 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5843 OMP_CLAUSE__LOOPTEMP_);
5844 gcc_assert (innerc);
5845 if (i)
5846 {
5847 tree tem = OMP_CLAUSE_DECL (innerc);
5848 tree t = fold_convert (TREE_TYPE (tem), counts[i]);
5849 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5850 false, GSI_CONTINUE_LINKING);
1a91d914 5851 gassign *stmt = gimple_build_assign (tem, t);
bc7bff74 5852 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5853 }
5854 }
5855 return;
5856 }
5857
3d483a94 5858 tree type = TREE_TYPE (fd->loop.v);
5859 tree tem = create_tmp_reg (type, ".tem");
1a91d914 5860 gassign *stmt = gimple_build_assign (tem, startvar);
3d483a94 5861 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5862
5863 for (i = fd->collapse - 1; i >= 0; i--)
5864 {
5865 tree vtype = TREE_TYPE (fd->loops[i].v), itype, t;
5866 itype = vtype;
5867 if (POINTER_TYPE_P (vtype))
5868 itype = signed_type_for (vtype);
5869 if (i != 0)
5870 t = fold_build2 (TRUNC_MOD_EXPR, type, tem, counts[i]);
5871 else
5872 t = tem;
5873 t = fold_convert (itype, t);
5874 t = fold_build2 (MULT_EXPR, itype, t,
5875 fold_convert (itype, fd->loops[i].step));
5876 if (POINTER_TYPE_P (vtype))
5877 t = fold_build_pointer_plus (fd->loops[i].n1, t);
5878 else
5879 t = fold_build2 (PLUS_EXPR, itype, fd->loops[i].n1, t);
5880 t = force_gimple_operand_gsi (gsi, t,
5881 DECL_P (fd->loops[i].v)
5882 && TREE_ADDRESSABLE (fd->loops[i].v),
5883 NULL_TREE, false,
5884 GSI_CONTINUE_LINKING);
5885 stmt = gimple_build_assign (fd->loops[i].v, t);
5886 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5887 if (i != 0)
5888 {
5889 t = fold_build2 (TRUNC_DIV_EXPR, type, tem, counts[i]);
5890 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5891 false, GSI_CONTINUE_LINKING);
5892 stmt = gimple_build_assign (tem, t);
5893 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5894 }
5895 }
5896}
5897
5898
5899/* Helper function for expand_omp_for_*. Generate code like:
5900 L10:
5901 V3 += STEP3;
5902 if (V3 cond3 N32) goto BODY_BB; else goto L11;
5903 L11:
5904 V3 = N31;
5905 V2 += STEP2;
5906 if (V2 cond2 N22) goto BODY_BB; else goto L12;
5907 L12:
5908 V2 = N21;
5909 V1 += STEP1;
5910 goto BODY_BB; */
5911
5912static basic_block
5913extract_omp_for_update_vars (struct omp_for_data *fd, basic_block cont_bb,
5914 basic_block body_bb)
5915{
5916 basic_block last_bb, bb, collapse_bb = NULL;
5917 int i;
5918 gimple_stmt_iterator gsi;
5919 edge e;
5920 tree t;
5921 gimple stmt;
5922
5923 last_bb = cont_bb;
5924 for (i = fd->collapse - 1; i >= 0; i--)
5925 {
5926 tree vtype = TREE_TYPE (fd->loops[i].v);
5927
5928 bb = create_empty_bb (last_bb);
b3083327 5929 add_bb_to_loop (bb, last_bb->loop_father);
3d483a94 5930 gsi = gsi_start_bb (bb);
5931
5932 if (i < fd->collapse - 1)
5933 {
5934 e = make_edge (last_bb, bb, EDGE_FALSE_VALUE);
5935 e->probability = REG_BR_PROB_BASE / 8;
5936
5937 t = fd->loops[i + 1].n1;
5938 t = force_gimple_operand_gsi (&gsi, t,
5939 DECL_P (fd->loops[i + 1].v)
5940 && TREE_ADDRESSABLE (fd->loops[i
5941 + 1].v),
5942 NULL_TREE, false,
5943 GSI_CONTINUE_LINKING);
5944 stmt = gimple_build_assign (fd->loops[i + 1].v, t);
5945 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5946 }
5947 else
5948 collapse_bb = bb;
5949
5950 set_immediate_dominator (CDI_DOMINATORS, bb, last_bb);
5951
5952 if (POINTER_TYPE_P (vtype))
5953 t = fold_build_pointer_plus (fd->loops[i].v, fd->loops[i].step);
5954 else
5955 t = fold_build2 (PLUS_EXPR, vtype, fd->loops[i].v, fd->loops[i].step);
5956 t = force_gimple_operand_gsi (&gsi, t,
5957 DECL_P (fd->loops[i].v)
5958 && TREE_ADDRESSABLE (fd->loops[i].v),
5959 NULL_TREE, false, GSI_CONTINUE_LINKING);
5960 stmt = gimple_build_assign (fd->loops[i].v, t);
5961 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5962
5963 if (i > 0)
5964 {
5965 t = fd->loops[i].n2;
5966 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5967 false, GSI_CONTINUE_LINKING);
5968 tree v = fd->loops[i].v;
5969 if (DECL_P (v) && TREE_ADDRESSABLE (v))
5970 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
5971 false, GSI_CONTINUE_LINKING);
5972 t = fold_build2 (fd->loops[i].cond_code, boolean_type_node, v, t);
5973 stmt = gimple_build_cond_empty (t);
5974 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5975 e = make_edge (bb, body_bb, EDGE_TRUE_VALUE);
5976 e->probability = REG_BR_PROB_BASE * 7 / 8;
5977 }
5978 else
5979 make_edge (bb, body_bb, EDGE_FALLTHRU);
5980 last_bb = bb;
5981 }
5982
5983 return collapse_bb;
5984}
5985
5986
773c5ba7 5987/* A subroutine of expand_omp_for. Generate code for a parallel
1e8e9920 5988 loop with any schedule. Given parameters:
5989
5990 for (V = N1; V cond N2; V += STEP) BODY;
5991
5992 where COND is "<" or ">", we generate pseudocode
5993
5994 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
773c5ba7 5995 if (more) goto L0; else goto L3;
1e8e9920 5996 L0:
5997 V = istart0;
5998 iend = iend0;
5999 L1:
6000 BODY;
6001 V += STEP;
773c5ba7 6002 if (V cond iend) goto L1; else goto L2;
1e8e9920 6003 L2:
773c5ba7 6004 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
6005 L3:
1e8e9920 6006
773c5ba7 6007 If this is a combined omp parallel loop, instead of the call to
fd6481cf 6008 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
bc7bff74 6009 If this is gimple_omp_for_combined_p loop, then instead of assigning
6010 V and iend in L0 we assign the first two _looptemp_ clause decls of the
6011 inner GIMPLE_OMP_FOR and V += STEP; and
6012 if (V cond iend) goto L1; else goto L2; are removed.
fd6481cf 6013
6014 For collapsed loops, given parameters:
6015 collapse(3)
6016 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
6017 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
6018 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
6019 BODY;
6020
6021 we generate pseudocode
6022
8e6b4515 6023 if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
fd6481cf 6024 if (cond3 is <)
6025 adj = STEP3 - 1;
6026 else
6027 adj = STEP3 + 1;
6028 count3 = (adj + N32 - N31) / STEP3;
8e6b4515 6029 if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
fd6481cf 6030 if (cond2 is <)
6031 adj = STEP2 - 1;
6032 else
6033 adj = STEP2 + 1;
6034 count2 = (adj + N22 - N21) / STEP2;
8e6b4515 6035 if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
fd6481cf 6036 if (cond1 is <)
6037 adj = STEP1 - 1;
6038 else
6039 adj = STEP1 + 1;
6040 count1 = (adj + N12 - N11) / STEP1;
6041 count = count1 * count2 * count3;
8e6b4515 6042 goto Z1;
6043 Z0:
6044 count = 0;
6045 Z1:
fd6481cf 6046 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
6047 if (more) goto L0; else goto L3;
6048 L0:
6049 V = istart0;
6050 T = V;
6051 V3 = N31 + (T % count3) * STEP3;
6052 T = T / count3;
6053 V2 = N21 + (T % count2) * STEP2;
6054 T = T / count2;
6055 V1 = N11 + T * STEP1;
6056 iend = iend0;
6057 L1:
6058 BODY;
6059 V += 1;
6060 if (V < iend) goto L10; else goto L2;
6061 L10:
6062 V3 += STEP3;
6063 if (V3 cond3 N32) goto L1; else goto L11;
6064 L11:
6065 V3 = N31;
6066 V2 += STEP2;
6067 if (V2 cond2 N22) goto L1; else goto L12;
6068 L12:
6069 V2 = N21;
6070 V1 += STEP1;
6071 goto L1;
6072 L2:
6073 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
6074 L3:
6075
6076 */
1e8e9920 6077
61e47ac8 6078static void
773c5ba7 6079expand_omp_for_generic (struct omp_region *region,
6080 struct omp_for_data *fd,
1e8e9920 6081 enum built_in_function start_fn,
bc7bff74 6082 enum built_in_function next_fn,
6083 gimple inner_stmt)
1e8e9920 6084{
75a70cf9 6085 tree type, istart0, iend0, iend;
fd6481cf 6086 tree t, vmain, vback, bias = NULL_TREE;
6087 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, collapse_bb;
03ed154b 6088 basic_block l2_bb = NULL, l3_bb = NULL;
75a70cf9 6089 gimple_stmt_iterator gsi;
1a91d914 6090 gassign *assign_stmt;
773c5ba7 6091 bool in_combined_parallel = is_combined_parallel (region);
ac6e3339 6092 bool broken_loop = region->cont == NULL;
79acaae1 6093 edge e, ne;
fd6481cf 6094 tree *counts = NULL;
6095 int i;
ac6e3339 6096
6097 gcc_assert (!broken_loop || !in_combined_parallel);
fd6481cf 6098 gcc_assert (fd->iter_type == long_integer_type_node
6099 || !in_combined_parallel);
1e8e9920 6100
fd6481cf 6101 type = TREE_TYPE (fd->loop.v);
6102 istart0 = create_tmp_var (fd->iter_type, ".istart0");
6103 iend0 = create_tmp_var (fd->iter_type, ".iend0");
6d63fc03 6104 TREE_ADDRESSABLE (istart0) = 1;
6105 TREE_ADDRESSABLE (iend0) = 1;
1e8e9920 6106
fd6481cf 6107 /* See if we need to bias by LLONG_MIN. */
6108 if (fd->iter_type == long_long_unsigned_type_node
6109 && TREE_CODE (type) == INTEGER_TYPE
6110 && !TYPE_UNSIGNED (type))
6111 {
6112 tree n1, n2;
6113
6114 if (fd->loop.cond_code == LT_EXPR)
6115 {
6116 n1 = fd->loop.n1;
6117 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
6118 }
6119 else
6120 {
6121 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
6122 n2 = fd->loop.n1;
6123 }
6124 if (TREE_CODE (n1) != INTEGER_CST
6125 || TREE_CODE (n2) != INTEGER_CST
6126 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
6127 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
6128 }
6129
61e47ac8 6130 entry_bb = region->entry;
03ed154b 6131 cont_bb = region->cont;
fd6481cf 6132 collapse_bb = NULL;
ac6e3339 6133 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
6134 gcc_assert (broken_loop
6135 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
6136 l0_bb = split_edge (FALLTHRU_EDGE (entry_bb));
6137 l1_bb = single_succ (l0_bb);
6138 if (!broken_loop)
03ed154b 6139 {
6140 l2_bb = create_empty_bb (cont_bb);
ac6e3339 6141 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb);
6142 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
03ed154b 6143 }
ac6e3339 6144 else
6145 l2_bb = NULL;
6146 l3_bb = BRANCH_EDGE (entry_bb)->dest;
6147 exit_bb = region->exit;
773c5ba7 6148
75a70cf9 6149 gsi = gsi_last_bb (entry_bb);
fd6481cf 6150
75a70cf9 6151 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
fd6481cf 6152 if (fd->collapse > 1)
6153 {
8e6b4515 6154 int first_zero_iter = -1;
3d483a94 6155 basic_block zero_iter_bb = NULL, l2_dom_bb = NULL;
8e6b4515 6156
3d483a94 6157 counts = XALLOCAVEC (tree, fd->collapse);
6158 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6159 zero_iter_bb, first_zero_iter,
6160 l2_dom_bb);
fd6481cf 6161
8e6b4515 6162 if (zero_iter_bb)
6163 {
6164 /* Some counts[i] vars might be uninitialized if
6165 some loop has zero iterations. But the body shouldn't
6166 be executed in that case, so just avoid uninit warnings. */
6167 for (i = first_zero_iter; i < fd->collapse; i++)
6168 if (SSA_VAR_P (counts[i]))
6169 TREE_NO_WARNING (counts[i]) = 1;
6170 gsi_prev (&gsi);
6171 e = split_block (entry_bb, gsi_stmt (gsi));
6172 entry_bb = e->dest;
6173 make_edge (zero_iter_bb, entry_bb, EDGE_FALLTHRU);
6174 gsi = gsi_last_bb (entry_bb);
6175 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
6176 get_immediate_dominator (CDI_DOMINATORS,
6177 zero_iter_bb));
6178 }
fd6481cf 6179 }
79acaae1 6180 if (in_combined_parallel)
6181 {
6182 /* In a combined parallel loop, emit a call to
6183 GOMP_loop_foo_next. */
b9a16870 6184 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
79acaae1 6185 build_fold_addr_expr (istart0),
6186 build_fold_addr_expr (iend0));
6187 }
6188 else
1e8e9920 6189 {
c2f47e15 6190 tree t0, t1, t2, t3, t4;
773c5ba7 6191 /* If this is not a combined parallel loop, emit a call to
6192 GOMP_loop_foo_start in ENTRY_BB. */
c2f47e15 6193 t4 = build_fold_addr_expr (iend0);
6194 t3 = build_fold_addr_expr (istart0);
fd6481cf 6195 t2 = fold_convert (fd->iter_type, fd->loop.step);
3d483a94 6196 t1 = fd->loop.n2;
6197 t0 = fd->loop.n1;
bc7bff74 6198 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6199 {
6200 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6201 OMP_CLAUSE__LOOPTEMP_);
6202 gcc_assert (innerc);
6203 t0 = OMP_CLAUSE_DECL (innerc);
6204 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6205 OMP_CLAUSE__LOOPTEMP_);
6206 gcc_assert (innerc);
6207 t1 = OMP_CLAUSE_DECL (innerc);
6208 }
3d483a94 6209 if (POINTER_TYPE_P (TREE_TYPE (t0))
6210 && TYPE_PRECISION (TREE_TYPE (t0))
6211 != TYPE_PRECISION (fd->iter_type))
c799f233 6212 {
6213 /* Avoid casting pointers to integer of a different size. */
3cea8318 6214 tree itype = signed_type_for (type);
3d483a94 6215 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
6216 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
c799f233 6217 }
6218 else
6219 {
3d483a94 6220 t1 = fold_convert (fd->iter_type, t1);
6221 t0 = fold_convert (fd->iter_type, t0);
c799f233 6222 }
fd6481cf 6223 if (bias)
1e8e9920 6224 {
fd6481cf 6225 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
6226 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
6227 }
6228 if (fd->iter_type == long_integer_type_node)
6229 {
6230 if (fd->chunk_size)
6231 {
6232 t = fold_convert (fd->iter_type, fd->chunk_size);
b9a16870 6233 t = build_call_expr (builtin_decl_explicit (start_fn),
6234 6, t0, t1, t2, t, t3, t4);
fd6481cf 6235 }
6236 else
b9a16870 6237 t = build_call_expr (builtin_decl_explicit (start_fn),
6238 5, t0, t1, t2, t3, t4);
1e8e9920 6239 }
c2f47e15 6240 else
fd6481cf 6241 {
6242 tree t5;
6243 tree c_bool_type;
b9a16870 6244 tree bfn_decl;
fd6481cf 6245
6246 /* The GOMP_loop_ull_*start functions have additional boolean
6247 argument, true for < loops and false for > loops.
6248 In Fortran, the C bool type can be different from
6249 boolean_type_node. */
b9a16870 6250 bfn_decl = builtin_decl_explicit (start_fn);
6251 c_bool_type = TREE_TYPE (TREE_TYPE (bfn_decl));
fd6481cf 6252 t5 = build_int_cst (c_bool_type,
6253 fd->loop.cond_code == LT_EXPR ? 1 : 0);
6254 if (fd->chunk_size)
6255 {
b9a16870 6256 tree bfn_decl = builtin_decl_explicit (start_fn);
fd6481cf 6257 t = fold_convert (fd->iter_type, fd->chunk_size);
b9a16870 6258 t = build_call_expr (bfn_decl, 7, t5, t0, t1, t2, t, t3, t4);
fd6481cf 6259 }
6260 else
b9a16870 6261 t = build_call_expr (builtin_decl_explicit (start_fn),
6262 6, t5, t0, t1, t2, t3, t4);
fd6481cf 6263 }
1e8e9920 6264 }
fd6481cf 6265 if (TREE_TYPE (t) != boolean_type_node)
6266 t = fold_build2 (NE_EXPR, boolean_type_node,
6267 t, build_int_cst (TREE_TYPE (t), 0));
75a70cf9 6268 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6269 true, GSI_SAME_STMT);
6270 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
79acaae1 6271
75a70cf9 6272 /* Remove the GIMPLE_OMP_FOR statement. */
6273 gsi_remove (&gsi, true);
1e8e9920 6274
773c5ba7 6275 /* Iteration setup for sequential loop goes in L0_BB. */
3d483a94 6276 tree startvar = fd->loop.v;
6277 tree endvar = NULL_TREE;
6278
bc7bff74 6279 if (gimple_omp_for_combined_p (fd->for_stmt))
6280 {
6281 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_FOR
6282 && gimple_omp_for_kind (inner_stmt)
6283 == GF_OMP_FOR_KIND_SIMD);
6284 tree innerc = find_omp_clause (gimple_omp_for_clauses (inner_stmt),
6285 OMP_CLAUSE__LOOPTEMP_);
6286 gcc_assert (innerc);
6287 startvar = OMP_CLAUSE_DECL (innerc);
6288 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6289 OMP_CLAUSE__LOOPTEMP_);
6290 gcc_assert (innerc);
6291 endvar = OMP_CLAUSE_DECL (innerc);
6292 }
6293
75a70cf9 6294 gsi = gsi_start_bb (l0_bb);
1efcacec 6295 t = istart0;
fd6481cf 6296 if (bias)
1efcacec 6297 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
3d483a94 6298 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
6299 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
6300 t = fold_convert (TREE_TYPE (startvar), t);
4abecb72 6301 t = force_gimple_operand_gsi (&gsi, t,
3d483a94 6302 DECL_P (startvar)
6303 && TREE_ADDRESSABLE (startvar),
4abecb72 6304 NULL_TREE, false, GSI_CONTINUE_LINKING);
1a91d914 6305 assign_stmt = gimple_build_assign (startvar, t);
6306 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
1e8e9920 6307
1efcacec 6308 t = iend0;
fd6481cf 6309 if (bias)
1efcacec 6310 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
3d483a94 6311 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
6312 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
6313 t = fold_convert (TREE_TYPE (startvar), t);
75a70cf9 6314 iend = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6315 false, GSI_CONTINUE_LINKING);
3d483a94 6316 if (endvar)
fd6481cf 6317 {
1a91d914 6318 assign_stmt = gimple_build_assign (endvar, iend);
6319 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
d44f2f7c 6320 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (iend)))
1a91d914 6321 assign_stmt = gimple_build_assign (fd->loop.v, iend);
d44f2f7c 6322 else
e9cf809e 6323 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, iend);
1a91d914 6324 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
fd6481cf 6325 }
3d483a94 6326 if (fd->collapse > 1)
bc7bff74 6327 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
773c5ba7 6328
ac6e3339 6329 if (!broken_loop)
03ed154b 6330 {
ac6e3339 6331 /* Code to control the increment and predicate for the sequential
6332 loop goes in the CONT_BB. */
75a70cf9 6333 gsi = gsi_last_bb (cont_bb);
1a91d914 6334 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
6335 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
6336 vmain = gimple_omp_continue_control_use (cont_stmt);
6337 vback = gimple_omp_continue_control_def (cont_stmt);
79acaae1 6338
bc7bff74 6339 if (!gimple_omp_for_combined_p (fd->for_stmt))
3d483a94 6340 {
6341 if (POINTER_TYPE_P (type))
6342 t = fold_build_pointer_plus (vmain, fd->loop.step);
6343 else
6344 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
6345 t = force_gimple_operand_gsi (&gsi, t,
6346 DECL_P (vback)
6347 && TREE_ADDRESSABLE (vback),
6348 NULL_TREE, true, GSI_SAME_STMT);
1a91d914 6349 assign_stmt = gimple_build_assign (vback, t);
6350 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
3d483a94 6351
6352 t = build2 (fd->loop.cond_code, boolean_type_node,
6353 DECL_P (vback) && TREE_ADDRESSABLE (vback) ? t : vback,
6354 iend);
1a91d914 6355 gcond *cond_stmt = gimple_build_cond_empty (t);
6356 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
3d483a94 6357 }
773c5ba7 6358
75a70cf9 6359 /* Remove GIMPLE_OMP_CONTINUE. */
6360 gsi_remove (&gsi, true);
773c5ba7 6361
bc7bff74 6362 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
3d483a94 6363 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, l1_bb);
fd6481cf 6364
ac6e3339 6365 /* Emit code to get the next parallel iteration in L2_BB. */
75a70cf9 6366 gsi = gsi_start_bb (l2_bb);
773c5ba7 6367
b9a16870 6368 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
ac6e3339 6369 build_fold_addr_expr (istart0),
6370 build_fold_addr_expr (iend0));
75a70cf9 6371 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6372 false, GSI_CONTINUE_LINKING);
fd6481cf 6373 if (TREE_TYPE (t) != boolean_type_node)
6374 t = fold_build2 (NE_EXPR, boolean_type_node,
6375 t, build_int_cst (TREE_TYPE (t), 0));
1a91d914 6376 gcond *cond_stmt = gimple_build_cond_empty (t);
6377 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
ac6e3339 6378 }
1e8e9920 6379
61e47ac8 6380 /* Add the loop cleanup function. */
75a70cf9 6381 gsi = gsi_last_bb (exit_bb);
6382 if (gimple_omp_return_nowait_p (gsi_stmt (gsi)))
b9a16870 6383 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
bc7bff74 6384 else if (gimple_omp_return_lhs (gsi_stmt (gsi)))
6385 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL);
61e47ac8 6386 else
b9a16870 6387 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END);
1a91d914 6388 gcall *call_stmt = gimple_build_call (t, 0);
bc7bff74 6389 if (gimple_omp_return_lhs (gsi_stmt (gsi)))
1a91d914 6390 gimple_call_set_lhs (call_stmt, gimple_omp_return_lhs (gsi_stmt (gsi)));
6391 gsi_insert_after (&gsi, call_stmt, GSI_SAME_STMT);
75a70cf9 6392 gsi_remove (&gsi, true);
773c5ba7 6393
6394 /* Connect the new blocks. */
79acaae1 6395 find_edge (entry_bb, l0_bb)->flags = EDGE_TRUE_VALUE;
6396 find_edge (entry_bb, l3_bb)->flags = EDGE_FALSE_VALUE;
1e8e9920 6397
ac6e3339 6398 if (!broken_loop)
6399 {
75a70cf9 6400 gimple_seq phis;
6401
79acaae1 6402 e = find_edge (cont_bb, l3_bb);
6403 ne = make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
6404
75a70cf9 6405 phis = phi_nodes (l3_bb);
6406 for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi))
6407 {
6408 gimple phi = gsi_stmt (gsi);
6409 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, ne),
6410 PHI_ARG_DEF_FROM_EDGE (phi, e));
6411 }
79acaae1 6412 remove_edge (e);
6413
ac6e3339 6414 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
b3083327 6415 add_bb_to_loop (l2_bb, cont_bb->loop_father);
3d483a94 6416 e = find_edge (cont_bb, l1_bb);
bc7bff74 6417 if (gimple_omp_for_combined_p (fd->for_stmt))
6418 {
6419 remove_edge (e);
6420 e = NULL;
6421 }
3d483a94 6422 else if (fd->collapse > 1)
fd6481cf 6423 {
fd6481cf 6424 remove_edge (e);
6425 e = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6426 }
6427 else
3d483a94 6428 e->flags = EDGE_TRUE_VALUE;
6429 if (e)
fd6481cf 6430 {
3d483a94 6431 e->probability = REG_BR_PROB_BASE * 7 / 8;
6432 find_edge (cont_bb, l2_bb)->probability = REG_BR_PROB_BASE / 8;
6433 }
6434 else
6435 {
6436 e = find_edge (cont_bb, l2_bb);
6437 e->flags = EDGE_FALLTHRU;
fd6481cf 6438 }
ac6e3339 6439 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
79acaae1 6440
6441 set_immediate_dominator (CDI_DOMINATORS, l2_bb,
6442 recompute_dominator (CDI_DOMINATORS, l2_bb));
6443 set_immediate_dominator (CDI_DOMINATORS, l3_bb,
6444 recompute_dominator (CDI_DOMINATORS, l3_bb));
6445 set_immediate_dominator (CDI_DOMINATORS, l0_bb,
6446 recompute_dominator (CDI_DOMINATORS, l0_bb));
6447 set_immediate_dominator (CDI_DOMINATORS, l1_bb,
6448 recompute_dominator (CDI_DOMINATORS, l1_bb));
04c2922b 6449
6450 struct loop *outer_loop = alloc_loop ();
6451 outer_loop->header = l0_bb;
6452 outer_loop->latch = l2_bb;
6453 add_loop (outer_loop, l0_bb->loop_father);
6454
bc7bff74 6455 if (!gimple_omp_for_combined_p (fd->for_stmt))
3d483a94 6456 {
6457 struct loop *loop = alloc_loop ();
6458 loop->header = l1_bb;
6459 /* The loop may have multiple latches. */
6460 add_loop (loop, outer_loop);
6461 }
ac6e3339 6462 }
1e8e9920 6463}
6464
6465
773c5ba7 6466/* A subroutine of expand_omp_for. Generate code for a parallel
6467 loop with static schedule and no specified chunk size. Given
6468 parameters:
1e8e9920 6469
6470 for (V = N1; V cond N2; V += STEP) BODY;
6471
6472 where COND is "<" or ">", we generate pseudocode
6473
8e6b4515 6474 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
1e8e9920 6475 if (cond is <)
6476 adj = STEP - 1;
6477 else
6478 adj = STEP + 1;
fd6481cf 6479 if ((__typeof (V)) -1 > 0 && cond is >)
6480 n = -(adj + N2 - N1) / -STEP;
6481 else
6482 n = (adj + N2 - N1) / STEP;
1e8e9920 6483 q = n / nthreads;
31712e83 6484 tt = n % nthreads;
6485 if (threadid < tt) goto L3; else goto L4;
6486 L3:
6487 tt = 0;
6488 q = q + 1;
6489 L4:
6490 s0 = q * threadid + tt;
6491 e0 = s0 + q;
79acaae1 6492 V = s0 * STEP + N1;
1e8e9920 6493 if (s0 >= e0) goto L2; else goto L0;
6494 L0:
1e8e9920 6495 e = e0 * STEP + N1;
6496 L1:
6497 BODY;
6498 V += STEP;
6499 if (V cond e) goto L1;
1e8e9920 6500 L2:
6501*/
6502
61e47ac8 6503static void
773c5ba7 6504expand_omp_for_static_nochunk (struct omp_region *region,
bc7bff74 6505 struct omp_for_data *fd,
6506 gimple inner_stmt)
1e8e9920 6507{
31712e83 6508 tree n, q, s0, e0, e, t, tt, nthreads, threadid;
fd6481cf 6509 tree type, itype, vmain, vback;
31712e83 6510 basic_block entry_bb, second_bb, third_bb, exit_bb, seq_start_bb;
bc7bff74 6511 basic_block body_bb, cont_bb, collapse_bb = NULL;
61e47ac8 6512 basic_block fin_bb;
75a70cf9 6513 gimple_stmt_iterator gsi;
31712e83 6514 edge ep;
bc7bff74 6515 bool broken_loop = region->cont == NULL;
6516 tree *counts = NULL;
6517 tree n1, n2, step;
1e8e9920 6518
ca4c3545 6519 gcc_checking_assert ((gimple_omp_for_kind (fd->for_stmt)
6520 != GF_OMP_FOR_KIND_OACC_LOOP)
6521 || !inner_stmt);
6522
fd6481cf 6523 itype = type = TREE_TYPE (fd->loop.v);
6524 if (POINTER_TYPE_P (type))
3cea8318 6525 itype = signed_type_for (type);
1e8e9920 6526
61e47ac8 6527 entry_bb = region->entry;
61e47ac8 6528 cont_bb = region->cont;
ac6e3339 6529 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
bc7bff74 6530 fin_bb = BRANCH_EDGE (entry_bb)->dest;
6531 gcc_assert (broken_loop
6532 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
ac6e3339 6533 seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb));
6534 body_bb = single_succ (seq_start_bb);
bc7bff74 6535 if (!broken_loop)
6536 {
6537 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
6538 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6539 }
61e47ac8 6540 exit_bb = region->exit;
6541
773c5ba7 6542 /* Iteration space partitioning goes in ENTRY_BB. */
75a70cf9 6543 gsi = gsi_last_bb (entry_bb);
6544 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
61e47ac8 6545
bc7bff74 6546 if (fd->collapse > 1)
6547 {
6548 int first_zero_iter = -1;
6549 basic_block l2_dom_bb = NULL;
6550
6551 counts = XALLOCAVEC (tree, fd->collapse);
6552 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6553 fin_bb, first_zero_iter,
6554 l2_dom_bb);
6555 t = NULL_TREE;
6556 }
6557 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
6558 t = integer_one_node;
6559 else
6560 t = fold_binary (fd->loop.cond_code, boolean_type_node,
6561 fold_convert (type, fd->loop.n1),
6562 fold_convert (type, fd->loop.n2));
6563 if (fd->collapse == 1
6564 && TYPE_UNSIGNED (type)
8e6b4515 6565 && (t == NULL_TREE || !integer_onep (t)))
6566 {
8e6b4515 6567 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
6568 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
6569 true, GSI_SAME_STMT);
6570 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
6571 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
6572 true, GSI_SAME_STMT);
1a91d914 6573 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
6574 NULL_TREE, NULL_TREE);
6575 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
6576 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
8e6b4515 6577 expand_omp_regimplify_p, NULL, NULL)
1a91d914 6578 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
8e6b4515 6579 expand_omp_regimplify_p, NULL, NULL))
6580 {
1a91d914 6581 gsi = gsi_for_stmt (cond_stmt);
6582 gimple_regimplify_operands (cond_stmt, &gsi);
8e6b4515 6583 }
1a91d914 6584 ep = split_block (entry_bb, cond_stmt);
8e6b4515 6585 ep->flags = EDGE_TRUE_VALUE;
6586 entry_bb = ep->dest;
6587 ep->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
6588 ep = make_edge (ep->src, fin_bb, EDGE_FALSE_VALUE);
6589 ep->probability = REG_BR_PROB_BASE / 2000 - 1;
6590 if (gimple_in_ssa_p (cfun))
6591 {
6592 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
1a91d914 6593 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
6594 !gsi_end_p (gpi); gsi_next (&gpi))
8e6b4515 6595 {
1a91d914 6596 gphi *phi = gpi.phi ();
8e6b4515 6597 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
6598 ep, UNKNOWN_LOCATION);
6599 }
6600 }
6601 gsi = gsi_last_bb (entry_bb);
6602 }
6603
ca4c3545 6604 switch (gimple_omp_for_kind (fd->for_stmt))
6605 {
6606 case GF_OMP_FOR_KIND_FOR:
6607 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
6608 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
6609 break;
6610 case GF_OMP_FOR_KIND_DISTRIBUTE:
6611 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
6612 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
6613 break;
6614 case GF_OMP_FOR_KIND_OACC_LOOP:
6615 nthreads = builtin_decl_explicit (BUILT_IN_GOACC_GET_NUM_THREADS);
6616 threadid = builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM);
6617 break;
6618 default:
6619 gcc_unreachable ();
6620 }
6621 nthreads = build_call_expr (nthreads, 0);
6622 nthreads = fold_convert (itype, nthreads);
6623 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
75a70cf9 6624 true, GSI_SAME_STMT);
ca4c3545 6625 threadid = build_call_expr (threadid, 0);
6626 threadid = fold_convert (itype, threadid);
6627 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
75a70cf9 6628 true, GSI_SAME_STMT);
1e8e9920 6629
bc7bff74 6630 n1 = fd->loop.n1;
6631 n2 = fd->loop.n2;
6632 step = fd->loop.step;
6633 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6634 {
6635 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6636 OMP_CLAUSE__LOOPTEMP_);
6637 gcc_assert (innerc);
6638 n1 = OMP_CLAUSE_DECL (innerc);
6639 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6640 OMP_CLAUSE__LOOPTEMP_);
6641 gcc_assert (innerc);
6642 n2 = OMP_CLAUSE_DECL (innerc);
6643 }
6644 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
6645 true, NULL_TREE, true, GSI_SAME_STMT);
6646 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
6647 true, NULL_TREE, true, GSI_SAME_STMT);
6648 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
6649 true, NULL_TREE, true, GSI_SAME_STMT);
fd6481cf 6650
6651 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
bc7bff74 6652 t = fold_build2 (PLUS_EXPR, itype, step, t);
6653 t = fold_build2 (PLUS_EXPR, itype, t, n2);
6654 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
fd6481cf 6655 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
6656 t = fold_build2 (TRUNC_DIV_EXPR, itype,
6657 fold_build1 (NEGATE_EXPR, itype, t),
bc7bff74 6658 fold_build1 (NEGATE_EXPR, itype, step));
fd6481cf 6659 else
bc7bff74 6660 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
fd6481cf 6661 t = fold_convert (itype, t);
75a70cf9 6662 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
1e8e9920 6663
072f7ab1 6664 q = create_tmp_reg (itype, "q");
fd6481cf 6665 t = fold_build2 (TRUNC_DIV_EXPR, itype, n, nthreads);
31712e83 6666 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
6667 gsi_insert_before (&gsi, gimple_build_assign (q, t), GSI_SAME_STMT);
6668
072f7ab1 6669 tt = create_tmp_reg (itype, "tt");
31712e83 6670 t = fold_build2 (TRUNC_MOD_EXPR, itype, n, nthreads);
6671 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
6672 gsi_insert_before (&gsi, gimple_build_assign (tt, t), GSI_SAME_STMT);
1e8e9920 6673
31712e83 6674 t = build2 (LT_EXPR, boolean_type_node, threadid, tt);
1a91d914 6675 gcond *cond_stmt = gimple_build_cond_empty (t);
6676 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
31712e83 6677
1a91d914 6678 second_bb = split_block (entry_bb, cond_stmt)->dest;
31712e83 6679 gsi = gsi_last_bb (second_bb);
6680 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6681
6682 gsi_insert_before (&gsi, gimple_build_assign (tt, build_int_cst (itype, 0)),
6683 GSI_SAME_STMT);
1a91d914 6684 gassign *assign_stmt
e9cf809e 6685 = gimple_build_assign (q, PLUS_EXPR, q, build_int_cst (itype, 1));
1a91d914 6686 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
31712e83 6687
1a91d914 6688 third_bb = split_block (second_bb, assign_stmt)->dest;
31712e83 6689 gsi = gsi_last_bb (third_bb);
6690 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
1e8e9920 6691
fd6481cf 6692 t = build2 (MULT_EXPR, itype, q, threadid);
31712e83 6693 t = build2 (PLUS_EXPR, itype, t, tt);
75a70cf9 6694 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
1e8e9920 6695
fd6481cf 6696 t = fold_build2 (PLUS_EXPR, itype, s0, q);
75a70cf9 6697 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
79acaae1 6698
1e8e9920 6699 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
75a70cf9 6700 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
773c5ba7 6701
75a70cf9 6702 /* Remove the GIMPLE_OMP_FOR statement. */
6703 gsi_remove (&gsi, true);
773c5ba7 6704
6705 /* Setup code for sequential iteration goes in SEQ_START_BB. */
75a70cf9 6706 gsi = gsi_start_bb (seq_start_bb);
1e8e9920 6707
bc7bff74 6708 tree startvar = fd->loop.v;
6709 tree endvar = NULL_TREE;
6710
6711 if (gimple_omp_for_combined_p (fd->for_stmt))
6712 {
6713 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
6714 ? gimple_omp_parallel_clauses (inner_stmt)
6715 : gimple_omp_for_clauses (inner_stmt);
6716 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
6717 gcc_assert (innerc);
6718 startvar = OMP_CLAUSE_DECL (innerc);
6719 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6720 OMP_CLAUSE__LOOPTEMP_);
6721 gcc_assert (innerc);
6722 endvar = OMP_CLAUSE_DECL (innerc);
6723 }
fd6481cf 6724 t = fold_convert (itype, s0);
bc7bff74 6725 t = fold_build2 (MULT_EXPR, itype, t, step);
fd6481cf 6726 if (POINTER_TYPE_P (type))
bc7bff74 6727 t = fold_build_pointer_plus (n1, t);
fd6481cf 6728 else
bc7bff74 6729 t = fold_build2 (PLUS_EXPR, type, t, n1);
6730 t = fold_convert (TREE_TYPE (startvar), t);
4abecb72 6731 t = force_gimple_operand_gsi (&gsi, t,
bc7bff74 6732 DECL_P (startvar)
6733 && TREE_ADDRESSABLE (startvar),
4abecb72 6734 NULL_TREE, false, GSI_CONTINUE_LINKING);
1a91d914 6735 assign_stmt = gimple_build_assign (startvar, t);
6736 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
48e1416a 6737
fd6481cf 6738 t = fold_convert (itype, e0);
bc7bff74 6739 t = fold_build2 (MULT_EXPR, itype, t, step);
fd6481cf 6740 if (POINTER_TYPE_P (type))
bc7bff74 6741 t = fold_build_pointer_plus (n1, t);
fd6481cf 6742 else
bc7bff74 6743 t = fold_build2 (PLUS_EXPR, type, t, n1);
6744 t = fold_convert (TREE_TYPE (startvar), t);
75a70cf9 6745 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6746 false, GSI_CONTINUE_LINKING);
bc7bff74 6747 if (endvar)
6748 {
1a91d914 6749 assign_stmt = gimple_build_assign (endvar, e);
6750 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
d44f2f7c 6751 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
1a91d914 6752 assign_stmt = gimple_build_assign (fd->loop.v, e);
d44f2f7c 6753 else
e9cf809e 6754 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
1a91d914 6755 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
bc7bff74 6756 }
6757 if (fd->collapse > 1)
6758 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
1e8e9920 6759
bc7bff74 6760 if (!broken_loop)
6761 {
6762 /* The code controlling the sequential loop replaces the
6763 GIMPLE_OMP_CONTINUE. */
6764 gsi = gsi_last_bb (cont_bb);
1a91d914 6765 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
6766 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
6767 vmain = gimple_omp_continue_control_use (cont_stmt);
6768 vback = gimple_omp_continue_control_def (cont_stmt);
79acaae1 6769
bc7bff74 6770 if (!gimple_omp_for_combined_p (fd->for_stmt))
6771 {
6772 if (POINTER_TYPE_P (type))
6773 t = fold_build_pointer_plus (vmain, step);
6774 else
6775 t = fold_build2 (PLUS_EXPR, type, vmain, step);
6776 t = force_gimple_operand_gsi (&gsi, t,
6777 DECL_P (vback)
6778 && TREE_ADDRESSABLE (vback),
6779 NULL_TREE, true, GSI_SAME_STMT);
1a91d914 6780 assign_stmt = gimple_build_assign (vback, t);
6781 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
79acaae1 6782
bc7bff74 6783 t = build2 (fd->loop.cond_code, boolean_type_node,
6784 DECL_P (vback) && TREE_ADDRESSABLE (vback)
6785 ? t : vback, e);
6786 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6787 }
1e8e9920 6788
bc7bff74 6789 /* Remove the GIMPLE_OMP_CONTINUE statement. */
6790 gsi_remove (&gsi, true);
6791
6792 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
6793 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
6794 }
773c5ba7 6795
75a70cf9 6796 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
6797 gsi = gsi_last_bb (exit_bb);
6798 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
bc7bff74 6799 {
6800 t = gimple_omp_return_lhs (gsi_stmt (gsi));
ca4c3545 6801 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
6802 gcc_checking_assert (t == NULL_TREE);
6803 else
6804 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
bc7bff74 6805 }
75a70cf9 6806 gsi_remove (&gsi, true);
773c5ba7 6807
6808 /* Connect all the blocks. */
31712e83 6809 ep = make_edge (entry_bb, third_bb, EDGE_FALSE_VALUE);
6810 ep->probability = REG_BR_PROB_BASE / 4 * 3;
6811 ep = find_edge (entry_bb, second_bb);
6812 ep->flags = EDGE_TRUE_VALUE;
6813 ep->probability = REG_BR_PROB_BASE / 4;
6814 find_edge (third_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
6815 find_edge (third_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
79acaae1 6816
bc7bff74 6817 if (!broken_loop)
6818 {
6819 ep = find_edge (cont_bb, body_bb);
6820 if (gimple_omp_for_combined_p (fd->for_stmt))
6821 {
6822 remove_edge (ep);
6823 ep = NULL;
6824 }
6825 else if (fd->collapse > 1)
6826 {
6827 remove_edge (ep);
6828 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6829 }
6830 else
6831 ep->flags = EDGE_TRUE_VALUE;
6832 find_edge (cont_bb, fin_bb)->flags
6833 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
6834 }
48e1416a 6835
31712e83 6836 set_immediate_dominator (CDI_DOMINATORS, second_bb, entry_bb);
6837 set_immediate_dominator (CDI_DOMINATORS, third_bb, entry_bb);
6838 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, third_bb);
bc7bff74 6839
79acaae1 6840 set_immediate_dominator (CDI_DOMINATORS, body_bb,
6841 recompute_dominator (CDI_DOMINATORS, body_bb));
6842 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
6843 recompute_dominator (CDI_DOMINATORS, fin_bb));
04c2922b 6844
bc7bff74 6845 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
6846 {
6847 struct loop *loop = alloc_loop ();
6848 loop->header = body_bb;
6849 if (collapse_bb == NULL)
6850 loop->latch = cont_bb;
6851 add_loop (loop, body_bb->loop_father);
6852 }
1e8e9920 6853}
6854
773c5ba7 6855
6856/* A subroutine of expand_omp_for. Generate code for a parallel
6857 loop with static schedule and a specified chunk size. Given
6858 parameters:
1e8e9920 6859
6860 for (V = N1; V cond N2; V += STEP) BODY;
6861
6862 where COND is "<" or ">", we generate pseudocode
6863
8e6b4515 6864 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
1e8e9920 6865 if (cond is <)
6866 adj = STEP - 1;
6867 else
6868 adj = STEP + 1;
fd6481cf 6869 if ((__typeof (V)) -1 > 0 && cond is >)
6870 n = -(adj + N2 - N1) / -STEP;
6871 else
6872 n = (adj + N2 - N1) / STEP;
1e8e9920 6873 trip = 0;
79acaae1 6874 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
6875 here so that V is defined
6876 if the loop is not entered
1e8e9920 6877 L0:
6878 s0 = (trip * nthreads + threadid) * CHUNK;
6879 e0 = min(s0 + CHUNK, n);
6880 if (s0 < n) goto L1; else goto L4;
6881 L1:
6882 V = s0 * STEP + N1;
6883 e = e0 * STEP + N1;
6884 L2:
6885 BODY;
6886 V += STEP;
6887 if (V cond e) goto L2; else goto L3;
6888 L3:
6889 trip += 1;
6890 goto L0;
6891 L4:
1e8e9920 6892*/
6893
61e47ac8 6894static void
bc7bff74 6895expand_omp_for_static_chunk (struct omp_region *region,
6896 struct omp_for_data *fd, gimple inner_stmt)
1e8e9920 6897{
75a70cf9 6898 tree n, s0, e0, e, t;
79acaae1 6899 tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
93481288 6900 tree type, itype, vmain, vback, vextra;
773c5ba7 6901 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
bc7bff74 6902 basic_block trip_update_bb = NULL, cont_bb, collapse_bb = NULL, fin_bb;
93481288 6903 gimple_stmt_iterator gsi;
75a70cf9 6904 edge se;
bc7bff74 6905 bool broken_loop = region->cont == NULL;
6906 tree *counts = NULL;
6907 tree n1, n2, step;
1e8e9920 6908
ca4c3545 6909 gcc_checking_assert ((gimple_omp_for_kind (fd->for_stmt)
6910 != GF_OMP_FOR_KIND_OACC_LOOP)
6911 || !inner_stmt);
6912
fd6481cf 6913 itype = type = TREE_TYPE (fd->loop.v);
6914 if (POINTER_TYPE_P (type))
3cea8318 6915 itype = signed_type_for (type);
1e8e9920 6916
61e47ac8 6917 entry_bb = region->entry;
ac6e3339 6918 se = split_block (entry_bb, last_stmt (entry_bb));
6919 entry_bb = se->src;
6920 iter_part_bb = se->dest;
61e47ac8 6921 cont_bb = region->cont;
ac6e3339 6922 gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
bc7bff74 6923 fin_bb = BRANCH_EDGE (iter_part_bb)->dest;
6924 gcc_assert (broken_loop
6925 || fin_bb == FALLTHRU_EDGE (cont_bb)->dest);
ac6e3339 6926 seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
6927 body_bb = single_succ (seq_start_bb);
bc7bff74 6928 if (!broken_loop)
6929 {
6930 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
6931 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6932 trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
6933 }
61e47ac8 6934 exit_bb = region->exit;
773c5ba7 6935
773c5ba7 6936 /* Trip and adjustment setup goes in ENTRY_BB. */
93481288 6937 gsi = gsi_last_bb (entry_bb);
6938 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
773c5ba7 6939
bc7bff74 6940 if (fd->collapse > 1)
6941 {
6942 int first_zero_iter = -1;
6943 basic_block l2_dom_bb = NULL;
6944
6945 counts = XALLOCAVEC (tree, fd->collapse);
93481288 6946 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
bc7bff74 6947 fin_bb, first_zero_iter,
6948 l2_dom_bb);
6949 t = NULL_TREE;
6950 }
6951 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
6952 t = integer_one_node;
6953 else
6954 t = fold_binary (fd->loop.cond_code, boolean_type_node,
6955 fold_convert (type, fd->loop.n1),
6956 fold_convert (type, fd->loop.n2));
6957 if (fd->collapse == 1
6958 && TYPE_UNSIGNED (type)
8e6b4515 6959 && (t == NULL_TREE || !integer_onep (t)))
6960 {
8e6b4515 6961 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
93481288 6962 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
8e6b4515 6963 true, GSI_SAME_STMT);
6964 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
93481288 6965 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
8e6b4515 6966 true, GSI_SAME_STMT);
1a91d914 6967 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
6968 NULL_TREE, NULL_TREE);
6969 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
6970 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
8e6b4515 6971 expand_omp_regimplify_p, NULL, NULL)
1a91d914 6972 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
8e6b4515 6973 expand_omp_regimplify_p, NULL, NULL))
6974 {
1a91d914 6975 gsi = gsi_for_stmt (cond_stmt);
6976 gimple_regimplify_operands (cond_stmt, &gsi);
8e6b4515 6977 }
1a91d914 6978 se = split_block (entry_bb, cond_stmt);
8e6b4515 6979 se->flags = EDGE_TRUE_VALUE;
6980 entry_bb = se->dest;
6981 se->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
6982 se = make_edge (se->src, fin_bb, EDGE_FALSE_VALUE);
6983 se->probability = REG_BR_PROB_BASE / 2000 - 1;
6984 if (gimple_in_ssa_p (cfun))
6985 {
6986 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
1a91d914 6987 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
6988 !gsi_end_p (gpi); gsi_next (&gpi))
8e6b4515 6989 {
1a91d914 6990 gphi *phi = gpi.phi ();
8e6b4515 6991 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
6992 se, UNKNOWN_LOCATION);
6993 }
6994 }
93481288 6995 gsi = gsi_last_bb (entry_bb);
8e6b4515 6996 }
6997
ca4c3545 6998 switch (gimple_omp_for_kind (fd->for_stmt))
6999 {
7000 case GF_OMP_FOR_KIND_FOR:
7001 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
7002 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
7003 break;
7004 case GF_OMP_FOR_KIND_DISTRIBUTE:
7005 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
7006 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
7007 break;
7008 case GF_OMP_FOR_KIND_OACC_LOOP:
7009 nthreads = builtin_decl_explicit (BUILT_IN_GOACC_GET_NUM_THREADS);
7010 threadid = builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM);
7011 break;
7012 default:
7013 gcc_unreachable ();
7014 }
7015 nthreads = build_call_expr (nthreads, 0);
7016 nthreads = fold_convert (itype, nthreads);
7017 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
75a70cf9 7018 true, GSI_SAME_STMT);
ca4c3545 7019 threadid = build_call_expr (threadid, 0);
7020 threadid = fold_convert (itype, threadid);
7021 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
75a70cf9 7022 true, GSI_SAME_STMT);
79acaae1 7023
bc7bff74 7024 n1 = fd->loop.n1;
7025 n2 = fd->loop.n2;
7026 step = fd->loop.step;
7027 if (gimple_omp_for_combined_into_p (fd->for_stmt))
7028 {
7029 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7030 OMP_CLAUSE__LOOPTEMP_);
7031 gcc_assert (innerc);
7032 n1 = OMP_CLAUSE_DECL (innerc);
7033 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7034 OMP_CLAUSE__LOOPTEMP_);
7035 gcc_assert (innerc);
7036 n2 = OMP_CLAUSE_DECL (innerc);
7037 }
93481288 7038 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
bc7bff74 7039 true, NULL_TREE, true, GSI_SAME_STMT);
93481288 7040 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
bc7bff74 7041 true, NULL_TREE, true, GSI_SAME_STMT);
93481288 7042 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
bc7bff74 7043 true, NULL_TREE, true, GSI_SAME_STMT);
79acaae1 7044 fd->chunk_size
93481288 7045 = force_gimple_operand_gsi (&gsi, fold_convert (itype, fd->chunk_size),
75a70cf9 7046 true, NULL_TREE, true, GSI_SAME_STMT);
fd6481cf 7047
7048 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
bc7bff74 7049 t = fold_build2 (PLUS_EXPR, itype, step, t);
7050 t = fold_build2 (PLUS_EXPR, itype, t, n2);
7051 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
fd6481cf 7052 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
7053 t = fold_build2 (TRUNC_DIV_EXPR, itype,
7054 fold_build1 (NEGATE_EXPR, itype, t),
bc7bff74 7055 fold_build1 (NEGATE_EXPR, itype, step));
fd6481cf 7056 else
bc7bff74 7057 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
fd6481cf 7058 t = fold_convert (itype, t);
93481288 7059 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
75a70cf9 7060 true, GSI_SAME_STMT);
79acaae1 7061
083152fb 7062 trip_var = create_tmp_reg (itype, ".trip");
79acaae1 7063 if (gimple_in_ssa_p (cfun))
7064 {
f9e245b2 7065 trip_init = make_ssa_name (trip_var);
7066 trip_main = make_ssa_name (trip_var);
7067 trip_back = make_ssa_name (trip_var);
79acaae1 7068 }
1e8e9920 7069 else
79acaae1 7070 {
7071 trip_init = trip_var;
7072 trip_main = trip_var;
7073 trip_back = trip_var;
7074 }
1e8e9920 7075
1a91d914 7076 gassign *assign_stmt
7077 = gimple_build_assign (trip_init, build_int_cst (itype, 0));
7078 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
773c5ba7 7079
fd6481cf 7080 t = fold_build2 (MULT_EXPR, itype, threadid, fd->chunk_size);
bc7bff74 7081 t = fold_build2 (MULT_EXPR, itype, t, step);
fd6481cf 7082 if (POINTER_TYPE_P (type))
bc7bff74 7083 t = fold_build_pointer_plus (n1, t);
fd6481cf 7084 else
bc7bff74 7085 t = fold_build2 (PLUS_EXPR, type, t, n1);
93481288 7086 vextra = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7087 true, GSI_SAME_STMT);
79acaae1 7088
75a70cf9 7089 /* Remove the GIMPLE_OMP_FOR. */
93481288 7090 gsi_remove (&gsi, true);
773c5ba7 7091
7092 /* Iteration space partitioning goes in ITER_PART_BB. */
93481288 7093 gsi = gsi_last_bb (iter_part_bb);
1e8e9920 7094
fd6481cf 7095 t = fold_build2 (MULT_EXPR, itype, trip_main, nthreads);
7096 t = fold_build2 (PLUS_EXPR, itype, t, threadid);
7097 t = fold_build2 (MULT_EXPR, itype, t, fd->chunk_size);
93481288 7098 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
75a70cf9 7099 false, GSI_CONTINUE_LINKING);
1e8e9920 7100
fd6481cf 7101 t = fold_build2 (PLUS_EXPR, itype, s0, fd->chunk_size);
7102 t = fold_build2 (MIN_EXPR, itype, t, n);
93481288 7103 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
75a70cf9 7104 false, GSI_CONTINUE_LINKING);
1e8e9920 7105
7106 t = build2 (LT_EXPR, boolean_type_node, s0, n);
93481288 7107 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_CONTINUE_LINKING);
773c5ba7 7108
7109 /* Setup code for sequential iteration goes in SEQ_START_BB. */
93481288 7110 gsi = gsi_start_bb (seq_start_bb);
1e8e9920 7111
bc7bff74 7112 tree startvar = fd->loop.v;
7113 tree endvar = NULL_TREE;
7114
7115 if (gimple_omp_for_combined_p (fd->for_stmt))
7116 {
7117 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
7118 ? gimple_omp_parallel_clauses (inner_stmt)
7119 : gimple_omp_for_clauses (inner_stmt);
7120 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
7121 gcc_assert (innerc);
7122 startvar = OMP_CLAUSE_DECL (innerc);
7123 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7124 OMP_CLAUSE__LOOPTEMP_);
7125 gcc_assert (innerc);
7126 endvar = OMP_CLAUSE_DECL (innerc);
7127 }
7128
fd6481cf 7129 t = fold_convert (itype, s0);
bc7bff74 7130 t = fold_build2 (MULT_EXPR, itype, t, step);
fd6481cf 7131 if (POINTER_TYPE_P (type))
bc7bff74 7132 t = fold_build_pointer_plus (n1, t);
fd6481cf 7133 else
bc7bff74 7134 t = fold_build2 (PLUS_EXPR, type, t, n1);
7135 t = fold_convert (TREE_TYPE (startvar), t);
93481288 7136 t = force_gimple_operand_gsi (&gsi, t,
bc7bff74 7137 DECL_P (startvar)
7138 && TREE_ADDRESSABLE (startvar),
4abecb72 7139 NULL_TREE, false, GSI_CONTINUE_LINKING);
1a91d914 7140 assign_stmt = gimple_build_assign (startvar, t);
7141 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
1e8e9920 7142
fd6481cf 7143 t = fold_convert (itype, e0);
bc7bff74 7144 t = fold_build2 (MULT_EXPR, itype, t, step);
fd6481cf 7145 if (POINTER_TYPE_P (type))
bc7bff74 7146 t = fold_build_pointer_plus (n1, t);
fd6481cf 7147 else
bc7bff74 7148 t = fold_build2 (PLUS_EXPR, type, t, n1);
7149 t = fold_convert (TREE_TYPE (startvar), t);
93481288 7150 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
75a70cf9 7151 false, GSI_CONTINUE_LINKING);
bc7bff74 7152 if (endvar)
7153 {
1a91d914 7154 assign_stmt = gimple_build_assign (endvar, e);
7155 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
d44f2f7c 7156 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
1a91d914 7157 assign_stmt = gimple_build_assign (fd->loop.v, e);
d44f2f7c 7158 else
e9cf809e 7159 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
1a91d914 7160 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
bc7bff74 7161 }
7162 if (fd->collapse > 1)
93481288 7163 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
bc7bff74 7164
7165 if (!broken_loop)
7166 {
7167 /* The code controlling the sequential loop goes in CONT_BB,
7168 replacing the GIMPLE_OMP_CONTINUE. */
93481288 7169 gsi = gsi_last_bb (cont_bb);
1a91d914 7170 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
7171 vmain = gimple_omp_continue_control_use (cont_stmt);
7172 vback = gimple_omp_continue_control_def (cont_stmt);
1e8e9920 7173
bc7bff74 7174 if (!gimple_omp_for_combined_p (fd->for_stmt))
7175 {
7176 if (POINTER_TYPE_P (type))
93481288 7177 t = fold_build_pointer_plus (vmain, step);
bc7bff74 7178 else
93481288 7179 t = fold_build2 (PLUS_EXPR, type, vmain, step);
7180 if (DECL_P (vback) && TREE_ADDRESSABLE (vback))
7181 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
bc7bff74 7182 true, GSI_SAME_STMT);
1a91d914 7183 assign_stmt = gimple_build_assign (vback, t);
7184 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
79acaae1 7185
bc7bff74 7186 t = build2 (fd->loop.cond_code, boolean_type_node,
93481288 7187 DECL_P (vback) && TREE_ADDRESSABLE (vback)
7188 ? t : vback, e);
7189 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
bc7bff74 7190 }
79acaae1 7191
bc7bff74 7192 /* Remove GIMPLE_OMP_CONTINUE. */
93481288 7193 gsi_remove (&gsi, true);
48e1416a 7194
bc7bff74 7195 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
7196 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
773c5ba7 7197
bc7bff74 7198 /* Trip update code goes into TRIP_UPDATE_BB. */
93481288 7199 gsi = gsi_start_bb (trip_update_bb);
1e8e9920 7200
bc7bff74 7201 t = build_int_cst (itype, 1);
7202 t = build2 (PLUS_EXPR, itype, trip_main, t);
1a91d914 7203 assign_stmt = gimple_build_assign (trip_back, t);
7204 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
bc7bff74 7205 }
1e8e9920 7206
75a70cf9 7207 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
93481288 7208 gsi = gsi_last_bb (exit_bb);
7209 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
bc7bff74 7210 {
93481288 7211 t = gimple_omp_return_lhs (gsi_stmt (gsi));
ca4c3545 7212 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
7213 gcc_checking_assert (t == NULL_TREE);
7214 else
7215 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
bc7bff74 7216 }
93481288 7217 gsi_remove (&gsi, true);
1e8e9920 7218
773c5ba7 7219 /* Connect the new blocks. */
ac6e3339 7220 find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
7221 find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
79acaae1 7222
bc7bff74 7223 if (!broken_loop)
7224 {
7225 se = find_edge (cont_bb, body_bb);
7226 if (gimple_omp_for_combined_p (fd->for_stmt))
7227 {
7228 remove_edge (se);
7229 se = NULL;
7230 }
7231 else if (fd->collapse > 1)
7232 {
7233 remove_edge (se);
7234 se = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
7235 }
7236 else
7237 se->flags = EDGE_TRUE_VALUE;
7238 find_edge (cont_bb, trip_update_bb)->flags
7239 = se ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
79acaae1 7240
bc7bff74 7241 redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb);
7242 }
79acaae1 7243
7244 if (gimple_in_ssa_p (cfun))
7245 {
1a91d914 7246 gphi_iterator psi;
7247 gphi *phi;
75a70cf9 7248 edge re, ene;
75a70cf9 7249 edge_var_map *vm;
7250 size_t i;
7251
bc7bff74 7252 gcc_assert (fd->collapse == 1 && !broken_loop);
7253
79acaae1 7254 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
7255 remove arguments of the phi nodes in fin_bb. We need to create
7256 appropriate phi nodes in iter_part_bb instead. */
7257 se = single_pred_edge (fin_bb);
7258 re = single_succ_edge (trip_update_bb);
06ecf488 7259 vec<edge_var_map> *head = redirect_edge_var_map_vector (re);
79acaae1 7260 ene = single_succ_edge (entry_bb);
7261
75a70cf9 7262 psi = gsi_start_phis (fin_bb);
f1f41a6c 7263 for (i = 0; !gsi_end_p (psi) && head->iterate (i, &vm);
75a70cf9 7264 gsi_next (&psi), ++i)
79acaae1 7265 {
1a91d914 7266 gphi *nphi;
efbcb6de 7267 source_location locus;
75a70cf9 7268
1a91d914 7269 phi = psi.phi ();
75a70cf9 7270 t = gimple_phi_result (phi);
7271 gcc_assert (t == redirect_edge_var_map_result (vm));
79acaae1 7272 nphi = create_phi_node (t, iter_part_bb);
79acaae1 7273
7274 t = PHI_ARG_DEF_FROM_EDGE (phi, se);
efbcb6de 7275 locus = gimple_phi_arg_location_from_edge (phi, se);
7276
fd6481cf 7277 /* A special case -- fd->loop.v is not yet computed in
93481288 7278 iter_part_bb, we need to use vextra instead. */
fd6481cf 7279 if (t == fd->loop.v)
93481288 7280 t = vextra;
60d535d2 7281 add_phi_arg (nphi, t, ene, locus);
efbcb6de 7282 locus = redirect_edge_var_map_location (vm);
60d535d2 7283 add_phi_arg (nphi, redirect_edge_var_map_def (vm), re, locus);
75a70cf9 7284 }
a6f1094f 7285 gcc_assert (gsi_end_p (psi) && i == head->length ());
75a70cf9 7286 redirect_edge_var_map_clear (re);
7287 while (1)
7288 {
7289 psi = gsi_start_phis (fin_bb);
7290 if (gsi_end_p (psi))
7291 break;
7292 remove_phi_node (&psi, false);
79acaae1 7293 }
79acaae1 7294
7295 /* Make phi node for trip. */
7296 phi = create_phi_node (trip_main, iter_part_bb);
efbcb6de 7297 add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb),
60d535d2 7298 UNKNOWN_LOCATION);
efbcb6de 7299 add_phi_arg (phi, trip_init, single_succ_edge (entry_bb),
60d535d2 7300 UNKNOWN_LOCATION);
79acaae1 7301 }
7302
bc7bff74 7303 if (!broken_loop)
7304 set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
79acaae1 7305 set_immediate_dominator (CDI_DOMINATORS, iter_part_bb,
7306 recompute_dominator (CDI_DOMINATORS, iter_part_bb));
7307 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
7308 recompute_dominator (CDI_DOMINATORS, fin_bb));
7309 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb,
7310 recompute_dominator (CDI_DOMINATORS, seq_start_bb));
7311 set_immediate_dominator (CDI_DOMINATORS, body_bb,
7312 recompute_dominator (CDI_DOMINATORS, body_bb));
04c2922b 7313
bc7bff74 7314 if (!broken_loop)
7315 {
7316 struct loop *trip_loop = alloc_loop ();
7317 trip_loop->header = iter_part_bb;
7318 trip_loop->latch = trip_update_bb;
7319 add_loop (trip_loop, iter_part_bb->loop_father);
04c2922b 7320
bc7bff74 7321 if (!gimple_omp_for_combined_p (fd->for_stmt))
7322 {
7323 struct loop *loop = alloc_loop ();
7324 loop->header = body_bb;
33ee4d72 7325 if (collapse_bb == NULL)
7326 loop->latch = cont_bb;
bc7bff74 7327 add_loop (loop, trip_loop);
7328 }
7329 }
1e8e9920 7330}
7331
40750995 7332/* A subroutine of expand_omp_for. Generate code for _Cilk_for loop.
7333 Given parameters:
7334 for (V = N1; V cond N2; V += STEP) BODY;
7335
7336 where COND is "<" or ">" or "!=", we generate pseudocode
7337
7338 for (ind_var = low; ind_var < high; ind_var++)
7339 {
7340 V = n1 + (ind_var * STEP)
7341
7342 <BODY>
7343 }
7344
7345 In the above pseudocode, low and high are function parameters of the
7346 child function. In the function below, we are inserting a temp.
7347 variable that will be making a call to two OMP functions that will not be
7348 found in the body of _Cilk_for (since OMP_FOR cannot be mixed
7349 with _Cilk_for). These functions are replaced with low and high
7350 by the function that handles taskreg. */
7351
7352
7353static void
7354expand_cilk_for (struct omp_region *region, struct omp_for_data *fd)
7355{
7356 bool broken_loop = region->cont == NULL;
7357 basic_block entry_bb = region->entry;
7358 basic_block cont_bb = region->cont;
7359
7360 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
7361 gcc_assert (broken_loop
7362 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
7363 basic_block l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
7364 basic_block l1_bb, l2_bb;
7365
7366 if (!broken_loop)
7367 {
7368 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
7369 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
7370 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
7371 l2_bb = BRANCH_EDGE (entry_bb)->dest;
7372 }
7373 else
7374 {
7375 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
7376 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
7377 l2_bb = single_succ (l1_bb);
7378 }
7379 basic_block exit_bb = region->exit;
7380 basic_block l2_dom_bb = NULL;
7381
7382 gimple_stmt_iterator gsi = gsi_last_bb (entry_bb);
7383
7384 /* Below statements until the "tree high_val = ..." are pseudo statements
7385 used to pass information to be used by expand_omp_taskreg.
7386 low_val and high_val will be replaced by the __low and __high
7387 parameter from the child function.
7388
7389 The call_exprs part is a place-holder, it is mainly used
7390 to distinctly identify to the top-level part that this is
7391 where we should put low and high (reasoning given in header
7392 comment). */
7393
7394 tree child_fndecl
1a91d914 7395 = gimple_omp_parallel_child_fn (
7396 as_a <gomp_parallel *> (last_stmt (region->outer->entry)));
40750995 7397 tree t, low_val = NULL_TREE, high_val = NULL_TREE;
7398 for (t = DECL_ARGUMENTS (child_fndecl); t; t = TREE_CHAIN (t))
7399 {
7400 if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__high"))
7401 high_val = t;
7402 else if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__low"))
7403 low_val = t;
7404 }
7405 gcc_assert (low_val && high_val);
7406
7407 tree type = TREE_TYPE (low_val);
7408 tree ind_var = create_tmp_reg (type, "__cilk_ind_var");
7409 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
7410
7411 /* Not needed in SSA form right now. */
7412 gcc_assert (!gimple_in_ssa_p (cfun));
7413 if (l2_dom_bb == NULL)
7414 l2_dom_bb = l1_bb;
7415
7416 tree n1 = low_val;
7417 tree n2 = high_val;
7418
7419 gimple stmt = gimple_build_assign (ind_var, n1);
7420
7421 /* Replace the GIMPLE_OMP_FOR statement. */
7422 gsi_replace (&gsi, stmt, true);
7423
7424 if (!broken_loop)
7425 {
7426 /* Code to control the increment goes in the CONT_BB. */
7427 gsi = gsi_last_bb (cont_bb);
7428 stmt = gsi_stmt (gsi);
7429 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
e9cf809e 7430 stmt = gimple_build_assign (ind_var, PLUS_EXPR, ind_var,
7431 build_one_cst (type));
40750995 7432
7433 /* Replace GIMPLE_OMP_CONTINUE. */
7434 gsi_replace (&gsi, stmt, true);
7435 }
7436
7437 /* Emit the condition in L1_BB. */
7438 gsi = gsi_after_labels (l1_bb);
7439 t = fold_build2 (MULT_EXPR, TREE_TYPE (fd->loop.step),
7440 fold_convert (TREE_TYPE (fd->loop.step), ind_var),
7441 fd->loop.step);
7442 if (POINTER_TYPE_P (TREE_TYPE (fd->loop.n1)))
7443 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (fd->loop.n1),
7444 fd->loop.n1, fold_convert (sizetype, t));
7445 else
7446 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loop.n1),
7447 fd->loop.n1, fold_convert (TREE_TYPE (fd->loop.n1), t));
7448 t = fold_convert (TREE_TYPE (fd->loop.v), t);
7449 expand_omp_build_assign (&gsi, fd->loop.v, t);
7450
7451 /* The condition is always '<' since the runtime will fill in the low
7452 and high values. */
7453 stmt = gimple_build_cond (LT_EXPR, ind_var, n2, NULL_TREE, NULL_TREE);
7454 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
7455
7456 /* Remove GIMPLE_OMP_RETURN. */
7457 gsi = gsi_last_bb (exit_bb);
7458 gsi_remove (&gsi, true);
7459
7460 /* Connect the new blocks. */
7461 remove_edge (FALLTHRU_EDGE (entry_bb));
7462
7463 edge e, ne;
7464 if (!broken_loop)
7465 {
7466 remove_edge (BRANCH_EDGE (entry_bb));
7467 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
7468
7469 e = BRANCH_EDGE (l1_bb);
7470 ne = FALLTHRU_EDGE (l1_bb);
7471 e->flags = EDGE_TRUE_VALUE;
7472 }
7473 else
7474 {
7475 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7476
7477 ne = single_succ_edge (l1_bb);
7478 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
7479
7480 }
7481 ne->flags = EDGE_FALSE_VALUE;
7482 e->probability = REG_BR_PROB_BASE * 7 / 8;
7483 ne->probability = REG_BR_PROB_BASE / 8;
7484
7485 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
7486 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
7487 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
7488
7489 if (!broken_loop)
7490 {
7491 struct loop *loop = alloc_loop ();
7492 loop->header = l1_bb;
7493 loop->latch = cont_bb;
7494 add_loop (loop, l1_bb->loop_father);
7495 loop->safelen = INT_MAX;
7496 }
7497
7498 /* Pick the correct library function based on the precision of the
7499 induction variable type. */
7500 tree lib_fun = NULL_TREE;
7501 if (TYPE_PRECISION (type) == 32)
7502 lib_fun = cilk_for_32_fndecl;
7503 else if (TYPE_PRECISION (type) == 64)
7504 lib_fun = cilk_for_64_fndecl;
7505 else
7506 gcc_unreachable ();
7507
7508 gcc_assert (fd->sched_kind == OMP_CLAUSE_SCHEDULE_CILKFOR);
7509
7510 /* WS_ARGS contains the library function flavor to call:
7511 __libcilkrts_cilk_for_64 or __libcilkrts_cilk_for_32), and the
7512 user-defined grain value. If the user does not define one, then zero
7513 is passed in by the parser. */
7514 vec_alloc (region->ws_args, 2);
7515 region->ws_args->quick_push (lib_fun);
7516 region->ws_args->quick_push (fd->chunk_size);
7517}
bc7bff74 7518
3d483a94 7519/* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
7520 loop. Given parameters:
7521
7522 for (V = N1; V cond N2; V += STEP) BODY;
7523
7524 where COND is "<" or ">", we generate pseudocode
7525
7526 V = N1;
7527 goto L1;
7528 L0:
7529 BODY;
7530 V += STEP;
7531 L1:
7532 if (V cond N2) goto L0; else goto L2;
7533 L2:
7534
7535 For collapsed loops, given parameters:
7536 collapse(3)
7537 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
7538 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
7539 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
7540 BODY;
7541
7542 we generate pseudocode
7543
7544 if (cond3 is <)
7545 adj = STEP3 - 1;
7546 else
7547 adj = STEP3 + 1;
7548 count3 = (adj + N32 - N31) / STEP3;
7549 if (cond2 is <)
7550 adj = STEP2 - 1;
7551 else
7552 adj = STEP2 + 1;
7553 count2 = (adj + N22 - N21) / STEP2;
7554 if (cond1 is <)
7555 adj = STEP1 - 1;
7556 else
7557 adj = STEP1 + 1;
7558 count1 = (adj + N12 - N11) / STEP1;
7559 count = count1 * count2 * count3;
7560 V = 0;
7561 V1 = N11;
7562 V2 = N21;
7563 V3 = N31;
7564 goto L1;
7565 L0:
7566 BODY;
7567 V += 1;
7568 V3 += STEP3;
7569 V2 += (V3 cond3 N32) ? 0 : STEP2;
7570 V3 = (V3 cond3 N32) ? V3 : N31;
7571 V1 += (V2 cond2 N22) ? 0 : STEP1;
7572 V2 = (V2 cond2 N22) ? V2 : N21;
7573 L1:
7574 if (V < count) goto L0; else goto L2;
7575 L2:
7576
7577 */
7578
7579static void
7580expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
7581{
7582 tree type, t;
7583 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, l2_bb, l2_dom_bb;
7584 gimple_stmt_iterator gsi;
7585 gimple stmt;
1a91d914 7586 gcond *cond_stmt;
3d483a94 7587 bool broken_loop = region->cont == NULL;
7588 edge e, ne;
7589 tree *counts = NULL;
7590 int i;
7591 tree safelen = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7592 OMP_CLAUSE_SAFELEN);
7593 tree simduid = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7594 OMP_CLAUSE__SIMDUID_);
bc7bff74 7595 tree n1, n2;
3d483a94 7596
7597 type = TREE_TYPE (fd->loop.v);
7598 entry_bb = region->entry;
7599 cont_bb = region->cont;
7600 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
7601 gcc_assert (broken_loop
7602 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
7603 l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
7604 if (!broken_loop)
7605 {
7606 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
7607 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
7608 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
7609 l2_bb = BRANCH_EDGE (entry_bb)->dest;
7610 }
7611 else
7612 {
7613 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
7614 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
7615 l2_bb = single_succ (l1_bb);
7616 }
7617 exit_bb = region->exit;
7618 l2_dom_bb = NULL;
7619
7620 gsi = gsi_last_bb (entry_bb);
7621
7622 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
7623 /* Not needed in SSA form right now. */
7624 gcc_assert (!gimple_in_ssa_p (cfun));
7625 if (fd->collapse > 1)
7626 {
7627 int first_zero_iter = -1;
7628 basic_block zero_iter_bb = l2_bb;
7629
7630 counts = XALLOCAVEC (tree, fd->collapse);
7631 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
7632 zero_iter_bb, first_zero_iter,
7633 l2_dom_bb);
7634 }
7635 if (l2_dom_bb == NULL)
7636 l2_dom_bb = l1_bb;
7637
bc7bff74 7638 n1 = fd->loop.n1;
3d483a94 7639 n2 = fd->loop.n2;
bc7bff74 7640 if (gimple_omp_for_combined_into_p (fd->for_stmt))
7641 {
7642 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7643 OMP_CLAUSE__LOOPTEMP_);
7644 gcc_assert (innerc);
7645 n1 = OMP_CLAUSE_DECL (innerc);
7646 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7647 OMP_CLAUSE__LOOPTEMP_);
7648 gcc_assert (innerc);
7649 n2 = OMP_CLAUSE_DECL (innerc);
7650 expand_omp_build_assign (&gsi, fd->loop.v,
7651 fold_convert (type, n1));
7652 if (fd->collapse > 1)
7653 {
7654 gsi_prev (&gsi);
7655 expand_omp_for_init_vars (fd, &gsi, counts, NULL, n1);
7656 gsi_next (&gsi);
7657 }
7658 }
3d483a94 7659 else
7660 {
7661 expand_omp_build_assign (&gsi, fd->loop.v,
7662 fold_convert (type, fd->loop.n1));
7663 if (fd->collapse > 1)
7664 for (i = 0; i < fd->collapse; i++)
7665 {
7666 tree itype = TREE_TYPE (fd->loops[i].v);
7667 if (POINTER_TYPE_P (itype))
7668 itype = signed_type_for (itype);
7669 t = fold_convert (TREE_TYPE (fd->loops[i].v), fd->loops[i].n1);
7670 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7671 }
7672 }
7673
7674 /* Remove the GIMPLE_OMP_FOR statement. */
7675 gsi_remove (&gsi, true);
7676
7677 if (!broken_loop)
7678 {
7679 /* Code to control the increment goes in the CONT_BB. */
7680 gsi = gsi_last_bb (cont_bb);
7681 stmt = gsi_stmt (gsi);
7682 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
7683
7684 if (POINTER_TYPE_P (type))
7685 t = fold_build_pointer_plus (fd->loop.v, fd->loop.step);
7686 else
7687 t = fold_build2 (PLUS_EXPR, type, fd->loop.v, fd->loop.step);
7688 expand_omp_build_assign (&gsi, fd->loop.v, t);
7689
7690 if (fd->collapse > 1)
7691 {
7692 i = fd->collapse - 1;
7693 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
7694 {
7695 t = fold_convert (sizetype, fd->loops[i].step);
7696 t = fold_build_pointer_plus (fd->loops[i].v, t);
7697 }
7698 else
7699 {
7700 t = fold_convert (TREE_TYPE (fd->loops[i].v),
7701 fd->loops[i].step);
7702 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
7703 fd->loops[i].v, t);
7704 }
7705 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7706
7707 for (i = fd->collapse - 1; i > 0; i--)
7708 {
7709 tree itype = TREE_TYPE (fd->loops[i].v);
7710 tree itype2 = TREE_TYPE (fd->loops[i - 1].v);
7711 if (POINTER_TYPE_P (itype2))
7712 itype2 = signed_type_for (itype2);
7713 t = build3 (COND_EXPR, itype2,
7714 build2 (fd->loops[i].cond_code, boolean_type_node,
7715 fd->loops[i].v,
7716 fold_convert (itype, fd->loops[i].n2)),
7717 build_int_cst (itype2, 0),
7718 fold_convert (itype2, fd->loops[i - 1].step));
7719 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i - 1].v)))
7720 t = fold_build_pointer_plus (fd->loops[i - 1].v, t);
7721 else
7722 t = fold_build2 (PLUS_EXPR, itype2, fd->loops[i - 1].v, t);
7723 expand_omp_build_assign (&gsi, fd->loops[i - 1].v, t);
7724
7725 t = build3 (COND_EXPR, itype,
7726 build2 (fd->loops[i].cond_code, boolean_type_node,
7727 fd->loops[i].v,
7728 fold_convert (itype, fd->loops[i].n2)),
7729 fd->loops[i].v,
7730 fold_convert (itype, fd->loops[i].n1));
7731 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7732 }
7733 }
7734
7735 /* Remove GIMPLE_OMP_CONTINUE. */
7736 gsi_remove (&gsi, true);
7737 }
7738
7739 /* Emit the condition in L1_BB. */
7740 gsi = gsi_start_bb (l1_bb);
7741
7742 t = fold_convert (type, n2);
7743 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7744 false, GSI_CONTINUE_LINKING);
7745 t = build2 (fd->loop.cond_code, boolean_type_node, fd->loop.v, t);
1a91d914 7746 cond_stmt = gimple_build_cond_empty (t);
7747 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
7748 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt), expand_omp_regimplify_p,
3d483a94 7749 NULL, NULL)
1a91d914 7750 || walk_tree (gimple_cond_rhs_ptr (cond_stmt), expand_omp_regimplify_p,
3d483a94 7751 NULL, NULL))
7752 {
1a91d914 7753 gsi = gsi_for_stmt (cond_stmt);
7754 gimple_regimplify_operands (cond_stmt, &gsi);
3d483a94 7755 }
7756
7757 /* Remove GIMPLE_OMP_RETURN. */
7758 gsi = gsi_last_bb (exit_bb);
7759 gsi_remove (&gsi, true);
7760
7761 /* Connect the new blocks. */
7762 remove_edge (FALLTHRU_EDGE (entry_bb));
7763
7764 if (!broken_loop)
7765 {
7766 remove_edge (BRANCH_EDGE (entry_bb));
7767 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
7768
7769 e = BRANCH_EDGE (l1_bb);
7770 ne = FALLTHRU_EDGE (l1_bb);
7771 e->flags = EDGE_TRUE_VALUE;
7772 }
7773 else
7774 {
7775 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7776
7777 ne = single_succ_edge (l1_bb);
7778 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
7779
7780 }
7781 ne->flags = EDGE_FALSE_VALUE;
7782 e->probability = REG_BR_PROB_BASE * 7 / 8;
7783 ne->probability = REG_BR_PROB_BASE / 8;
7784
7785 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
7786 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
7787 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
7788
7789 if (!broken_loop)
7790 {
7791 struct loop *loop = alloc_loop ();
7792 loop->header = l1_bb;
33ee4d72 7793 loop->latch = cont_bb;
3d483a94 7794 add_loop (loop, l1_bb->loop_father);
7795 if (safelen == NULL_TREE)
7796 loop->safelen = INT_MAX;
7797 else
7798 {
7799 safelen = OMP_CLAUSE_SAFELEN_EXPR (safelen);
c3f3b68d 7800 if (TREE_CODE (safelen) != INTEGER_CST)
7801 loop->safelen = 0;
7802 else if (!tree_fits_uhwi_p (safelen)
7803 || tree_to_uhwi (safelen) > INT_MAX)
3d483a94 7804 loop->safelen = INT_MAX;
7805 else
d85a2013 7806 loop->safelen = tree_to_uhwi (safelen);
3d483a94 7807 if (loop->safelen == 1)
7808 loop->safelen = 0;
7809 }
7810 if (simduid)
7811 {
7812 loop->simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
7813 cfun->has_simduid_loops = true;
7814 }
043115ec 7815 /* If not -fno-tree-loop-vectorize, hint that we want to vectorize
3d483a94 7816 the loop. */
043115ec 7817 if ((flag_tree_loop_vectorize
7818 || (!global_options_set.x_flag_tree_loop_vectorize
7819 && !global_options_set.x_flag_tree_vectorize))
ad45e43e 7820 && flag_tree_loop_optimize
3d483a94 7821 && loop->safelen > 1)
7822 {
4c73695b 7823 loop->force_vectorize = true;
7824 cfun->has_force_vectorize_loops = true;
3d483a94 7825 }
7826 }
9918db44 7827 else if (simduid)
7828 cfun->has_simduid_loops = true;
3d483a94 7829}
7830
1e8e9920 7831
ca4c3545 7832/* Expand the OMP loop defined by REGION. */
1e8e9920 7833
773c5ba7 7834static void
bc7bff74 7835expand_omp_for (struct omp_region *region, gimple inner_stmt)
773c5ba7 7836{
7837 struct omp_for_data fd;
fd6481cf 7838 struct omp_for_data_loop *loops;
1e8e9920 7839
fd6481cf 7840 loops
7841 = (struct omp_for_data_loop *)
75a70cf9 7842 alloca (gimple_omp_for_collapse (last_stmt (region->entry))
fd6481cf 7843 * sizeof (struct omp_for_data_loop));
1a91d914 7844 extract_omp_for_data (as_a <gomp_for *> (last_stmt (region->entry)),
7845 &fd, loops);
f77459c5 7846 region->sched_kind = fd.sched_kind;
1e8e9920 7847
b3a3ddec 7848 gcc_assert (EDGE_COUNT (region->entry->succs) == 2);
7849 BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
7850 FALLTHRU_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
7851 if (region->cont)
7852 {
7853 gcc_assert (EDGE_COUNT (region->cont->succs) == 2);
7854 BRANCH_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
7855 FALLTHRU_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
7856 }
04c2922b 7857 else
75de4aa2 7858 /* If there isn't a continue then this is a degerate case where
04c2922b 7859 the introduction of abnormal edges during lowering will prevent
7860 original loops from being detected. Fix that up. */
7861 loops_state_set (LOOPS_NEED_FIXUP);
b3a3ddec 7862
10c55644 7863 if (gimple_omp_for_kind (fd.for_stmt) & GF_OMP_FOR_SIMD)
3d483a94 7864 expand_omp_simd (region, &fd);
40750995 7865 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
7866 expand_cilk_for (region, &fd);
3d483a94 7867 else if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
bc7bff74 7868 && !fd.have_ordered)
1e8e9920 7869 {
7870 if (fd.chunk_size == NULL)
bc7bff74 7871 expand_omp_for_static_nochunk (region, &fd, inner_stmt);
1e8e9920 7872 else
bc7bff74 7873 expand_omp_for_static_chunk (region, &fd, inner_stmt);
1e8e9920 7874 }
7875 else
7876 {
fd6481cf 7877 int fn_index, start_ix, next_ix;
7878
3d483a94 7879 gcc_assert (gimple_omp_for_kind (fd.for_stmt)
7880 == GF_OMP_FOR_KIND_FOR);
0416ca72 7881 if (fd.chunk_size == NULL
7882 && fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
7883 fd.chunk_size = integer_zero_node;
fd6481cf 7884 gcc_assert (fd.sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
7885 fn_index = (fd.sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
75a70cf9 7886 ? 3 : fd.sched_kind;
fd6481cf 7887 fn_index += fd.have_ordered * 4;
b9a16870 7888 start_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_START) + fn_index;
7889 next_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT) + fn_index;
fd6481cf 7890 if (fd.iter_type == long_long_unsigned_type_node)
7891 {
b9a16870 7892 start_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
7893 - (int)BUILT_IN_GOMP_LOOP_STATIC_START);
7894 next_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
7895 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT);
fd6481cf 7896 }
b9c74b4d 7897 expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
bc7bff74 7898 (enum built_in_function) next_ix, inner_stmt);
1e8e9920 7899 }
28c92cbb 7900
083152fb 7901 if (gimple_in_ssa_p (cfun))
7902 update_ssa (TODO_update_ssa_only_virtuals);
1e8e9920 7903}
7904
1e8e9920 7905
7906/* Expand code for an OpenMP sections directive. In pseudo code, we generate
7907
1e8e9920 7908 v = GOMP_sections_start (n);
7909 L0:
7910 switch (v)
7911 {
7912 case 0:
7913 goto L2;
7914 case 1:
7915 section 1;
7916 goto L1;
7917 case 2:
7918 ...
7919 case n:
7920 ...
1e8e9920 7921 default:
7922 abort ();
7923 }
7924 L1:
7925 v = GOMP_sections_next ();
7926 goto L0;
7927 L2:
7928 reduction;
7929
773c5ba7 7930 If this is a combined parallel sections, replace the call to
79acaae1 7931 GOMP_sections_start with call to GOMP_sections_next. */
1e8e9920 7932
7933static void
773c5ba7 7934expand_omp_sections (struct omp_region *region)
1e8e9920 7935{
f018d957 7936 tree t, u, vin = NULL, vmain, vnext, l2;
75a70cf9 7937 unsigned len;
ac6e3339 7938 basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
75a70cf9 7939 gimple_stmt_iterator si, switch_si;
1a91d914 7940 gomp_sections *sections_stmt;
7941 gimple stmt;
7942 gomp_continue *cont;
9884aaf8 7943 edge_iterator ei;
7944 edge e;
61e47ac8 7945 struct omp_region *inner;
75a70cf9 7946 unsigned i, casei;
ac6e3339 7947 bool exit_reachable = region->cont != NULL;
1e8e9920 7948
d244d9de 7949 gcc_assert (region->exit != NULL);
61e47ac8 7950 entry_bb = region->entry;
ac6e3339 7951 l0_bb = single_succ (entry_bb);
61e47ac8 7952 l1_bb = region->cont;
ac6e3339 7953 l2_bb = region->exit;
d244d9de 7954 if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
7955 l2 = gimple_block_label (l2_bb);
7956 else
03ed154b 7957 {
d244d9de 7958 /* This can happen if there are reductions. */
7959 len = EDGE_COUNT (l0_bb->succs);
7960 gcc_assert (len > 0);
7961 e = EDGE_SUCC (l0_bb, len - 1);
7962 si = gsi_last_bb (e->dest);
7963 l2 = NULL_TREE;
7964 if (gsi_end_p (si)
7965 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
7966 l2 = gimple_block_label (e->dest);
9884aaf8 7967 else
d244d9de 7968 FOR_EACH_EDGE (e, ei, l0_bb->succs)
7969 {
7970 si = gsi_last_bb (e->dest);
7971 if (gsi_end_p (si)
7972 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
9884aaf8 7973 {
d244d9de 7974 l2 = gimple_block_label (e->dest);
7975 break;
9884aaf8 7976 }
d244d9de 7977 }
03ed154b 7978 }
d244d9de 7979 if (exit_reachable)
7980 default_bb = create_empty_bb (l1_bb->prev_bb);
03ed154b 7981 else
d244d9de 7982 default_bb = create_empty_bb (l0_bb);
773c5ba7 7983
7984 /* We will build a switch() with enough cases for all the
75a70cf9 7985 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
773c5ba7 7986 and a default case to abort if something goes wrong. */
ac6e3339 7987 len = EDGE_COUNT (l0_bb->succs);
75a70cf9 7988
f1f41a6c 7989 /* Use vec::quick_push on label_vec throughout, since we know the size
75a70cf9 7990 in advance. */
c2078b80 7991 auto_vec<tree> label_vec (len);
1e8e9920 7992
61e47ac8 7993 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
75a70cf9 7994 GIMPLE_OMP_SECTIONS statement. */
7995 si = gsi_last_bb (entry_bb);
1a91d914 7996 sections_stmt = as_a <gomp_sections *> (gsi_stmt (si));
75a70cf9 7997 gcc_assert (gimple_code (sections_stmt) == GIMPLE_OMP_SECTIONS);
7998 vin = gimple_omp_sections_control (sections_stmt);
773c5ba7 7999 if (!is_combined_parallel (region))
1e8e9920 8000 {
773c5ba7 8001 /* If we are not inside a combined parallel+sections region,
8002 call GOMP_sections_start. */
39cb6d68 8003 t = build_int_cst (unsigned_type_node, len - 1);
b9a16870 8004 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START);
75a70cf9 8005 stmt = gimple_build_call (u, 1, t);
1e8e9920 8006 }
79acaae1 8007 else
8008 {
8009 /* Otherwise, call GOMP_sections_next. */
b9a16870 8010 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
75a70cf9 8011 stmt = gimple_build_call (u, 0);
79acaae1 8012 }
75a70cf9 8013 gimple_call_set_lhs (stmt, vin);
8014 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
8015 gsi_remove (&si, true);
8016
8017 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
8018 L0_BB. */
8019 switch_si = gsi_last_bb (l0_bb);
8020 gcc_assert (gimple_code (gsi_stmt (switch_si)) == GIMPLE_OMP_SECTIONS_SWITCH);
79acaae1 8021 if (exit_reachable)
8022 {
1a91d914 8023 cont = as_a <gomp_continue *> (last_stmt (l1_bb));
75a70cf9 8024 gcc_assert (gimple_code (cont) == GIMPLE_OMP_CONTINUE);
8025 vmain = gimple_omp_continue_control_use (cont);
8026 vnext = gimple_omp_continue_control_def (cont);
79acaae1 8027 }
8028 else
8029 {
8030 vmain = vin;
8031 vnext = NULL_TREE;
8032 }
1e8e9920 8033
d244d9de 8034 t = build_case_label (build_int_cst (unsigned_type_node, 0), NULL, l2);
f1f41a6c 8035 label_vec.quick_push (t);
d244d9de 8036 i = 1;
03ed154b 8037
75a70cf9 8038 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
ac6e3339 8039 for (inner = region->inner, casei = 1;
8040 inner;
8041 inner = inner->next, i++, casei++)
1e8e9920 8042 {
773c5ba7 8043 basic_block s_entry_bb, s_exit_bb;
8044
9884aaf8 8045 /* Skip optional reduction region. */
75a70cf9 8046 if (inner->type == GIMPLE_OMP_ATOMIC_LOAD)
9884aaf8 8047 {
8048 --i;
8049 --casei;
8050 continue;
8051 }
8052
61e47ac8 8053 s_entry_bb = inner->entry;
8054 s_exit_bb = inner->exit;
1e8e9920 8055
75a70cf9 8056 t = gimple_block_label (s_entry_bb);
ac6e3339 8057 u = build_int_cst (unsigned_type_node, casei);
b6e3dd65 8058 u = build_case_label (u, NULL, t);
f1f41a6c 8059 label_vec.quick_push (u);
61e47ac8 8060
75a70cf9 8061 si = gsi_last_bb (s_entry_bb);
8062 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SECTION);
8063 gcc_assert (i < len || gimple_omp_section_last_p (gsi_stmt (si)));
8064 gsi_remove (&si, true);
61e47ac8 8065 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
03ed154b 8066
8067 if (s_exit_bb == NULL)
8068 continue;
8069
75a70cf9 8070 si = gsi_last_bb (s_exit_bb);
8071 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
8072 gsi_remove (&si, true);
03ed154b 8073
773c5ba7 8074 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
1e8e9920 8075 }
8076
773c5ba7 8077 /* Error handling code goes in DEFAULT_BB. */
75a70cf9 8078 t = gimple_block_label (default_bb);
b6e3dd65 8079 u = build_case_label (NULL, NULL, t);
61e47ac8 8080 make_edge (l0_bb, default_bb, 0);
b3083327 8081 add_bb_to_loop (default_bb, current_loops->tree_root);
1e8e9920 8082
49a70175 8083 stmt = gimple_build_switch (vmain, u, label_vec);
75a70cf9 8084 gsi_insert_after (&switch_si, stmt, GSI_SAME_STMT);
8085 gsi_remove (&switch_si, true);
75a70cf9 8086
8087 si = gsi_start_bb (default_bb);
b9a16870 8088 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
75a70cf9 8089 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
773c5ba7 8090
ac6e3339 8091 if (exit_reachable)
03ed154b 8092 {
b9a16870 8093 tree bfn_decl;
8094
ac6e3339 8095 /* Code to get the next section goes in L1_BB. */
75a70cf9 8096 si = gsi_last_bb (l1_bb);
8097 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
1e8e9920 8098
b9a16870 8099 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
8100 stmt = gimple_build_call (bfn_decl, 0);
75a70cf9 8101 gimple_call_set_lhs (stmt, vnext);
8102 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
8103 gsi_remove (&si, true);
773c5ba7 8104
ac6e3339 8105 single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
03ed154b 8106 }
773c5ba7 8107
d244d9de 8108 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
8109 si = gsi_last_bb (l2_bb);
8110 if (gimple_omp_return_nowait_p (gsi_stmt (si)))
8111 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
bc7bff74 8112 else if (gimple_omp_return_lhs (gsi_stmt (si)))
8113 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL);
d244d9de 8114 else
8115 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
8116 stmt = gimple_build_call (t, 0);
bc7bff74 8117 if (gimple_omp_return_lhs (gsi_stmt (si)))
8118 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (si)));
d244d9de 8119 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
8120 gsi_remove (&si, true);
8121
79acaae1 8122 set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
773c5ba7 8123}
1e8e9920 8124
1e8e9920 8125
61e47ac8 8126/* Expand code for an OpenMP single directive. We've already expanded
8127 much of the code, here we simply place the GOMP_barrier call. */
8128
8129static void
8130expand_omp_single (struct omp_region *region)
8131{
8132 basic_block entry_bb, exit_bb;
75a70cf9 8133 gimple_stmt_iterator si;
61e47ac8 8134
8135 entry_bb = region->entry;
8136 exit_bb = region->exit;
8137
75a70cf9 8138 si = gsi_last_bb (entry_bb);
75a70cf9 8139 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE);
8140 gsi_remove (&si, true);
61e47ac8 8141 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
8142
75a70cf9 8143 si = gsi_last_bb (exit_bb);
bc7bff74 8144 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
8145 {
8146 tree t = gimple_omp_return_lhs (gsi_stmt (si));
8147 gsi_insert_after (&si, build_omp_barrier (t), GSI_SAME_STMT);
8148 }
75a70cf9 8149 gsi_remove (&si, true);
61e47ac8 8150 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
8151}
8152
8153
8154/* Generic expansion for OpenMP synchronization directives: master,
8155 ordered and critical. All we need to do here is remove the entry
8156 and exit markers for REGION. */
773c5ba7 8157
8158static void
8159expand_omp_synch (struct omp_region *region)
8160{
8161 basic_block entry_bb, exit_bb;
75a70cf9 8162 gimple_stmt_iterator si;
773c5ba7 8163
61e47ac8 8164 entry_bb = region->entry;
8165 exit_bb = region->exit;
773c5ba7 8166
75a70cf9 8167 si = gsi_last_bb (entry_bb);
8168 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE
8169 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASTER
bc7bff74 8170 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TASKGROUP
75a70cf9 8171 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ORDERED
bc7bff74 8172 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CRITICAL
8173 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TEAMS);
75a70cf9 8174 gsi_remove (&si, true);
773c5ba7 8175 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
8176
03ed154b 8177 if (exit_bb)
8178 {
75a70cf9 8179 si = gsi_last_bb (exit_bb);
8180 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
8181 gsi_remove (&si, true);
03ed154b 8182 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
8183 }
773c5ba7 8184}
1e8e9920 8185
2169f33b 8186/* A subroutine of expand_omp_atomic. Attempt to implement the atomic
8187 operation as a normal volatile load. */
8188
8189static bool
3ec11c49 8190expand_omp_atomic_load (basic_block load_bb, tree addr,
8191 tree loaded_val, int index)
2169f33b 8192{
3ec11c49 8193 enum built_in_function tmpbase;
8194 gimple_stmt_iterator gsi;
8195 basic_block store_bb;
8196 location_t loc;
8197 gimple stmt;
8198 tree decl, call, type, itype;
8199
8200 gsi = gsi_last_bb (load_bb);
8201 stmt = gsi_stmt (gsi);
8202 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
8203 loc = gimple_location (stmt);
8204
8205 /* ??? If the target does not implement atomic_load_optab[mode], and mode
8206 is smaller than word size, then expand_atomic_load assumes that the load
8207 is atomic. We could avoid the builtin entirely in this case. */
8208
8209 tmpbase = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
8210 decl = builtin_decl_explicit (tmpbase);
8211 if (decl == NULL_TREE)
8212 return false;
8213
8214 type = TREE_TYPE (loaded_val);
8215 itype = TREE_TYPE (TREE_TYPE (decl));
8216
8217 call = build_call_expr_loc (loc, decl, 2, addr,
bc7bff74 8218 build_int_cst (NULL,
8219 gimple_omp_atomic_seq_cst_p (stmt)
8220 ? MEMMODEL_SEQ_CST
8221 : MEMMODEL_RELAXED));
3ec11c49 8222 if (!useless_type_conversion_p (type, itype))
8223 call = fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
8224 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
8225
8226 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
8227 gsi_remove (&gsi, true);
8228
8229 store_bb = single_succ (load_bb);
8230 gsi = gsi_last_bb (store_bb);
8231 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
8232 gsi_remove (&gsi, true);
8233
8234 if (gimple_in_ssa_p (cfun))
8235 update_ssa (TODO_update_ssa_no_phi);
8236
8237 return true;
2169f33b 8238}
8239
8240/* A subroutine of expand_omp_atomic. Attempt to implement the atomic
8241 operation as a normal volatile store. */
8242
8243static bool
3ec11c49 8244expand_omp_atomic_store (basic_block load_bb, tree addr,
8245 tree loaded_val, tree stored_val, int index)
2169f33b 8246{
3ec11c49 8247 enum built_in_function tmpbase;
8248 gimple_stmt_iterator gsi;
8249 basic_block store_bb = single_succ (load_bb);
8250 location_t loc;
8251 gimple stmt;
8252 tree decl, call, type, itype;
3754d046 8253 machine_mode imode;
3ec11c49 8254 bool exchange;
8255
8256 gsi = gsi_last_bb (load_bb);
8257 stmt = gsi_stmt (gsi);
8258 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
8259
8260 /* If the load value is needed, then this isn't a store but an exchange. */
8261 exchange = gimple_omp_atomic_need_value_p (stmt);
8262
8263 gsi = gsi_last_bb (store_bb);
8264 stmt = gsi_stmt (gsi);
8265 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE);
8266 loc = gimple_location (stmt);
8267
8268 /* ??? If the target does not implement atomic_store_optab[mode], and mode
8269 is smaller than word size, then expand_atomic_store assumes that the store
8270 is atomic. We could avoid the builtin entirely in this case. */
8271
8272 tmpbase = (exchange ? BUILT_IN_ATOMIC_EXCHANGE_N : BUILT_IN_ATOMIC_STORE_N);
8273 tmpbase = (enum built_in_function) ((int) tmpbase + index + 1);
8274 decl = builtin_decl_explicit (tmpbase);
8275 if (decl == NULL_TREE)
8276 return false;
8277
8278 type = TREE_TYPE (stored_val);
8279
8280 /* Dig out the type of the function's second argument. */
8281 itype = TREE_TYPE (decl);
8282 itype = TYPE_ARG_TYPES (itype);
8283 itype = TREE_CHAIN (itype);
8284 itype = TREE_VALUE (itype);
8285 imode = TYPE_MODE (itype);
8286
8287 if (exchange && !can_atomic_exchange_p (imode, true))
8288 return false;
8289
8290 if (!useless_type_conversion_p (itype, type))
8291 stored_val = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, stored_val);
8292 call = build_call_expr_loc (loc, decl, 3, addr, stored_val,
bc7bff74 8293 build_int_cst (NULL,
8294 gimple_omp_atomic_seq_cst_p (stmt)
8295 ? MEMMODEL_SEQ_CST
8296 : MEMMODEL_RELAXED));
3ec11c49 8297 if (exchange)
8298 {
8299 if (!useless_type_conversion_p (type, itype))
8300 call = build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
8301 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
8302 }
8303
8304 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
8305 gsi_remove (&gsi, true);
8306
8307 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
8308 gsi = gsi_last_bb (load_bb);
8309 gsi_remove (&gsi, true);
8310
8311 if (gimple_in_ssa_p (cfun))
8312 update_ssa (TODO_update_ssa_no_phi);
8313
8314 return true;
2169f33b 8315}
8316
cb7f680b 8317/* A subroutine of expand_omp_atomic. Attempt to implement the atomic
1cd6e20d 8318 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
cb7f680b 8319 size of the data type, and thus usable to find the index of the builtin
8320 decl. Returns false if the expression is not of the proper form. */
8321
8322static bool
8323expand_omp_atomic_fetch_op (basic_block load_bb,
8324 tree addr, tree loaded_val,
8325 tree stored_val, int index)
8326{
b9a16870 8327 enum built_in_function oldbase, newbase, tmpbase;
cb7f680b 8328 tree decl, itype, call;
2169f33b 8329 tree lhs, rhs;
cb7f680b 8330 basic_block store_bb = single_succ (load_bb);
75a70cf9 8331 gimple_stmt_iterator gsi;
8332 gimple stmt;
389dd41b 8333 location_t loc;
1cd6e20d 8334 enum tree_code code;
2169f33b 8335 bool need_old, need_new;
3754d046 8336 machine_mode imode;
bc7bff74 8337 bool seq_cst;
cb7f680b 8338
8339 /* We expect to find the following sequences:
48e1416a 8340
cb7f680b 8341 load_bb:
75a70cf9 8342 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
cb7f680b 8343
8344 store_bb:
8345 val = tmp OP something; (or: something OP tmp)
48e1416a 8346 GIMPLE_OMP_STORE (val)
cb7f680b 8347
48e1416a 8348 ???FIXME: Allow a more flexible sequence.
cb7f680b 8349 Perhaps use data flow to pick the statements.
48e1416a 8350
cb7f680b 8351 */
8352
75a70cf9 8353 gsi = gsi_after_labels (store_bb);
8354 stmt = gsi_stmt (gsi);
389dd41b 8355 loc = gimple_location (stmt);
75a70cf9 8356 if (!is_gimple_assign (stmt))
cb7f680b 8357 return false;
75a70cf9 8358 gsi_next (&gsi);
8359 if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE)
cb7f680b 8360 return false;
2169f33b 8361 need_new = gimple_omp_atomic_need_value_p (gsi_stmt (gsi));
8362 need_old = gimple_omp_atomic_need_value_p (last_stmt (load_bb));
bc7bff74 8363 seq_cst = gimple_omp_atomic_seq_cst_p (last_stmt (load_bb));
2169f33b 8364 gcc_checking_assert (!need_old || !need_new);
cb7f680b 8365
75a70cf9 8366 if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
cb7f680b 8367 return false;
8368
cb7f680b 8369 /* Check for one of the supported fetch-op operations. */
1cd6e20d 8370 code = gimple_assign_rhs_code (stmt);
8371 switch (code)
cb7f680b 8372 {
8373 case PLUS_EXPR:
8374 case POINTER_PLUS_EXPR:
1cd6e20d 8375 oldbase = BUILT_IN_ATOMIC_FETCH_ADD_N;
8376 newbase = BUILT_IN_ATOMIC_ADD_FETCH_N;
cb7f680b 8377 break;
8378 case MINUS_EXPR:
1cd6e20d 8379 oldbase = BUILT_IN_ATOMIC_FETCH_SUB_N;
8380 newbase = BUILT_IN_ATOMIC_SUB_FETCH_N;
cb7f680b 8381 break;
8382 case BIT_AND_EXPR:
1cd6e20d 8383 oldbase = BUILT_IN_ATOMIC_FETCH_AND_N;
8384 newbase = BUILT_IN_ATOMIC_AND_FETCH_N;
cb7f680b 8385 break;
8386 case BIT_IOR_EXPR:
1cd6e20d 8387 oldbase = BUILT_IN_ATOMIC_FETCH_OR_N;
8388 newbase = BUILT_IN_ATOMIC_OR_FETCH_N;
cb7f680b 8389 break;
8390 case BIT_XOR_EXPR:
1cd6e20d 8391 oldbase = BUILT_IN_ATOMIC_FETCH_XOR_N;
8392 newbase = BUILT_IN_ATOMIC_XOR_FETCH_N;
cb7f680b 8393 break;
8394 default:
8395 return false;
8396 }
1cd6e20d 8397
cb7f680b 8398 /* Make sure the expression is of the proper form. */
75a70cf9 8399 if (operand_equal_p (gimple_assign_rhs1 (stmt), loaded_val, 0))
8400 rhs = gimple_assign_rhs2 (stmt);
8401 else if (commutative_tree_code (gimple_assign_rhs_code (stmt))
8402 && operand_equal_p (gimple_assign_rhs2 (stmt), loaded_val, 0))
8403 rhs = gimple_assign_rhs1 (stmt);
cb7f680b 8404 else
8405 return false;
8406
b9a16870 8407 tmpbase = ((enum built_in_function)
8408 ((need_new ? newbase : oldbase) + index + 1));
8409 decl = builtin_decl_explicit (tmpbase);
0f94f46b 8410 if (decl == NULL_TREE)
8411 return false;
cb7f680b 8412 itype = TREE_TYPE (TREE_TYPE (decl));
1cd6e20d 8413 imode = TYPE_MODE (itype);
cb7f680b 8414
1cd6e20d 8415 /* We could test all of the various optabs involved, but the fact of the
8416 matter is that (with the exception of i486 vs i586 and xadd) all targets
8417 that support any atomic operaton optab also implements compare-and-swap.
8418 Let optabs.c take care of expanding any compare-and-swap loop. */
29139cdc 8419 if (!can_compare_and_swap_p (imode, true))
cb7f680b 8420 return false;
8421
75a70cf9 8422 gsi = gsi_last_bb (load_bb);
8423 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
1cd6e20d 8424
8425 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
8426 It only requires that the operation happen atomically. Thus we can
8427 use the RELAXED memory model. */
8428 call = build_call_expr_loc (loc, decl, 3, addr,
8429 fold_convert_loc (loc, itype, rhs),
bc7bff74 8430 build_int_cst (NULL,
8431 seq_cst ? MEMMODEL_SEQ_CST
8432 : MEMMODEL_RELAXED));
1cd6e20d 8433
2169f33b 8434 if (need_old || need_new)
8435 {
8436 lhs = need_old ? loaded_val : stored_val;
8437 call = fold_convert_loc (loc, TREE_TYPE (lhs), call);
8438 call = build2_loc (loc, MODIFY_EXPR, void_type_node, lhs, call);
8439 }
8440 else
8441 call = fold_convert_loc (loc, void_type_node, call);
75a70cf9 8442 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
8443 gsi_remove (&gsi, true);
cb7f680b 8444
75a70cf9 8445 gsi = gsi_last_bb (store_bb);
8446 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
8447 gsi_remove (&gsi, true);
8448 gsi = gsi_last_bb (store_bb);
8449 gsi_remove (&gsi, true);
cb7f680b 8450
8451 if (gimple_in_ssa_p (cfun))
8452 update_ssa (TODO_update_ssa_no_phi);
8453
8454 return true;
8455}
8456
8457/* A subroutine of expand_omp_atomic. Implement the atomic operation as:
8458
8459 oldval = *addr;
8460 repeat:
8461 newval = rhs; // with oldval replacing *addr in rhs
8462 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
8463 if (oldval != newval)
8464 goto repeat;
8465
8466 INDEX is log2 of the size of the data type, and thus usable to find the
8467 index of the builtin decl. */
8468
8469static bool
8470expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
8471 tree addr, tree loaded_val, tree stored_val,
8472 int index)
8473{
790368c5 8474 tree loadedi, storedi, initial, new_storedi, old_vali;
cb7f680b 8475 tree type, itype, cmpxchg, iaddr;
75a70cf9 8476 gimple_stmt_iterator si;
cb7f680b 8477 basic_block loop_header = single_succ (load_bb);
75a70cf9 8478 gimple phi, stmt;
cb7f680b 8479 edge e;
b9a16870 8480 enum built_in_function fncode;
cb7f680b 8481
1cd6e20d 8482 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
8483 order to use the RELAXED memory model effectively. */
b9a16870 8484 fncode = (enum built_in_function)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
8485 + index + 1);
8486 cmpxchg = builtin_decl_explicit (fncode);
0f94f46b 8487 if (cmpxchg == NULL_TREE)
8488 return false;
cb7f680b 8489 type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
8490 itype = TREE_TYPE (TREE_TYPE (cmpxchg));
8491
29139cdc 8492 if (!can_compare_and_swap_p (TYPE_MODE (itype), true))
cb7f680b 8493 return false;
8494
75a70cf9 8495 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
8496 si = gsi_last_bb (load_bb);
8497 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
8498
790368c5 8499 /* For floating-point values, we'll need to view-convert them to integers
8500 so that we can perform the atomic compare and swap. Simplify the
8501 following code by always setting up the "i"ntegral variables. */
8502 if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
8503 {
75a70cf9 8504 tree iaddr_val;
8505
072f7ab1 8506 iaddr = create_tmp_reg (build_pointer_type_for_mode (itype, ptr_mode,
f9e245b2 8507 true));
75a70cf9 8508 iaddr_val
8509 = force_gimple_operand_gsi (&si,
8510 fold_convert (TREE_TYPE (iaddr), addr),
8511 false, NULL_TREE, true, GSI_SAME_STMT);
8512 stmt = gimple_build_assign (iaddr, iaddr_val);
8513 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
f9e245b2 8514 loadedi = create_tmp_var (itype);
790368c5 8515 if (gimple_in_ssa_p (cfun))
f9e245b2 8516 loadedi = make_ssa_name (loadedi);
790368c5 8517 }
8518 else
8519 {
8520 iaddr = addr;
8521 loadedi = loaded_val;
8522 }
75a70cf9 8523
2ed72821 8524 fncode = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
8525 tree loaddecl = builtin_decl_explicit (fncode);
8526 if (loaddecl)
8527 initial
8528 = fold_convert (TREE_TYPE (TREE_TYPE (iaddr)),
8529 build_call_expr (loaddecl, 2, iaddr,
8530 build_int_cst (NULL_TREE,
8531 MEMMODEL_RELAXED)));
8532 else
8533 initial = build2 (MEM_REF, TREE_TYPE (TREE_TYPE (iaddr)), iaddr,
8534 build_int_cst (TREE_TYPE (iaddr), 0));
8535
182cf5a9 8536 initial
2ed72821 8537 = force_gimple_operand_gsi (&si, initial, true, NULL_TREE, true,
8538 GSI_SAME_STMT);
790368c5 8539
8540 /* Move the value to the LOADEDI temporary. */
cb7f680b 8541 if (gimple_in_ssa_p (cfun))
8542 {
75a70cf9 8543 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header)));
790368c5 8544 phi = create_phi_node (loadedi, loop_header);
cb7f680b 8545 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)),
8546 initial);
8547 }
8548 else
75a70cf9 8549 gsi_insert_before (&si,
8550 gimple_build_assign (loadedi, initial),
8551 GSI_SAME_STMT);
790368c5 8552 if (loadedi != loaded_val)
8553 {
75a70cf9 8554 gimple_stmt_iterator gsi2;
8555 tree x;
790368c5 8556
8557 x = build1 (VIEW_CONVERT_EXPR, type, loadedi);
75a70cf9 8558 gsi2 = gsi_start_bb (loop_header);
790368c5 8559 if (gimple_in_ssa_p (cfun))
8560 {
1a91d914 8561 gassign *stmt;
75a70cf9 8562 x = force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
8563 true, GSI_SAME_STMT);
8564 stmt = gimple_build_assign (loaded_val, x);
8565 gsi_insert_before (&gsi2, stmt, GSI_SAME_STMT);
790368c5 8566 }
8567 else
8568 {
75a70cf9 8569 x = build2 (MODIFY_EXPR, TREE_TYPE (loaded_val), loaded_val, x);
8570 force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
8571 true, GSI_SAME_STMT);
790368c5 8572 }
8573 }
75a70cf9 8574 gsi_remove (&si, true);
cb7f680b 8575
75a70cf9 8576 si = gsi_last_bb (store_bb);
8577 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
cb7f680b 8578
790368c5 8579 if (iaddr == addr)
8580 storedi = stored_val;
cb7f680b 8581 else
790368c5 8582 storedi =
75a70cf9 8583 force_gimple_operand_gsi (&si,
790368c5 8584 build1 (VIEW_CONVERT_EXPR, itype,
8585 stored_val), true, NULL_TREE, true,
75a70cf9 8586 GSI_SAME_STMT);
cb7f680b 8587
8588 /* Build the compare&swap statement. */
8589 new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi);
75a70cf9 8590 new_storedi = force_gimple_operand_gsi (&si,
87f9ffa4 8591 fold_convert (TREE_TYPE (loadedi),
8592 new_storedi),
cb7f680b 8593 true, NULL_TREE,
75a70cf9 8594 true, GSI_SAME_STMT);
cb7f680b 8595
8596 if (gimple_in_ssa_p (cfun))
8597 old_vali = loadedi;
8598 else
8599 {
f9e245b2 8600 old_vali = create_tmp_var (TREE_TYPE (loadedi));
75a70cf9 8601 stmt = gimple_build_assign (old_vali, loadedi);
8602 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
cb7f680b 8603
75a70cf9 8604 stmt = gimple_build_assign (loadedi, new_storedi);
8605 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
cb7f680b 8606 }
8607
8608 /* Note that we always perform the comparison as an integer, even for
48e1416a 8609 floating point. This allows the atomic operation to properly
cb7f680b 8610 succeed even with NaNs and -0.0. */
75a70cf9 8611 stmt = gimple_build_cond_empty
8612 (build2 (NE_EXPR, boolean_type_node,
8613 new_storedi, old_vali));
8614 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
cb7f680b 8615
8616 /* Update cfg. */
8617 e = single_succ_edge (store_bb);
8618 e->flags &= ~EDGE_FALLTHRU;
8619 e->flags |= EDGE_FALSE_VALUE;
8620
8621 e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE);
8622
790368c5 8623 /* Copy the new value to loadedi (we already did that before the condition
cb7f680b 8624 if we are not in SSA). */
8625 if (gimple_in_ssa_p (cfun))
8626 {
75a70cf9 8627 phi = gimple_seq_first_stmt (phi_nodes (loop_header));
790368c5 8628 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), new_storedi);
cb7f680b 8629 }
8630
75a70cf9 8631 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
8632 gsi_remove (&si, true);
cb7f680b 8633
04c2922b 8634 struct loop *loop = alloc_loop ();
8635 loop->header = loop_header;
5f037457 8636 loop->latch = store_bb;
04c2922b 8637 add_loop (loop, loop_header->loop_father);
8638
cb7f680b 8639 if (gimple_in_ssa_p (cfun))
8640 update_ssa (TODO_update_ssa_no_phi);
8641
8642 return true;
8643}
8644
8645/* A subroutine of expand_omp_atomic. Implement the atomic operation as:
8646
8647 GOMP_atomic_start ();
8648 *addr = rhs;
8649 GOMP_atomic_end ();
8650
8651 The result is not globally atomic, but works so long as all parallel
8652 references are within #pragma omp atomic directives. According to
8653 responses received from omp@openmp.org, appears to be within spec.
8654 Which makes sense, since that's how several other compilers handle
48e1416a 8655 this situation as well.
75a70cf9 8656 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
8657 expanding. STORED_VAL is the operand of the matching
8658 GIMPLE_OMP_ATOMIC_STORE.
cb7f680b 8659
48e1416a 8660 We replace
8661 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
cb7f680b 8662 loaded_val = *addr;
8663
8664 and replace
3ec11c49 8665 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
48e1416a 8666 *addr = stored_val;
cb7f680b 8667*/
8668
8669static bool
8670expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
8671 tree addr, tree loaded_val, tree stored_val)
8672{
75a70cf9 8673 gimple_stmt_iterator si;
1a91d914 8674 gassign *stmt;
cb7f680b 8675 tree t;
8676
75a70cf9 8677 si = gsi_last_bb (load_bb);
8678 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
cb7f680b 8679
b9a16870 8680 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
414c3a2c 8681 t = build_call_expr (t, 0);
75a70cf9 8682 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
cb7f680b 8683
182cf5a9 8684 stmt = gimple_build_assign (loaded_val, build_simple_mem_ref (addr));
75a70cf9 8685 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8686 gsi_remove (&si, true);
cb7f680b 8687
75a70cf9 8688 si = gsi_last_bb (store_bb);
8689 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
cb7f680b 8690
182cf5a9 8691 stmt = gimple_build_assign (build_simple_mem_ref (unshare_expr (addr)),
8692 stored_val);
75a70cf9 8693 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
cb7f680b 8694
b9a16870 8695 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
414c3a2c 8696 t = build_call_expr (t, 0);
75a70cf9 8697 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
8698 gsi_remove (&si, true);
cb7f680b 8699
8700 if (gimple_in_ssa_p (cfun))
8701 update_ssa (TODO_update_ssa_no_phi);
8702 return true;
8703}
8704
48e1416a 8705/* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
8706 using expand_omp_atomic_fetch_op. If it failed, we try to
cb7f680b 8707 call expand_omp_atomic_pipeline, and if it fails too, the
8708 ultimate fallback is wrapping the operation in a mutex
48e1416a 8709 (expand_omp_atomic_mutex). REGION is the atomic region built
8710 by build_omp_regions_1(). */
cb7f680b 8711
8712static void
8713expand_omp_atomic (struct omp_region *region)
8714{
8715 basic_block load_bb = region->entry, store_bb = region->exit;
1a91d914 8716 gomp_atomic_load *load = as_a <gomp_atomic_load *> (last_stmt (load_bb));
8717 gomp_atomic_store *store = as_a <gomp_atomic_store *> (last_stmt (store_bb));
75a70cf9 8718 tree loaded_val = gimple_omp_atomic_load_lhs (load);
8719 tree addr = gimple_omp_atomic_load_rhs (load);
8720 tree stored_val = gimple_omp_atomic_store_val (store);
cb7f680b 8721 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
8722 HOST_WIDE_INT index;
8723
8724 /* Make sure the type is one of the supported sizes. */
e913b5cd 8725 index = tree_to_uhwi (TYPE_SIZE_UNIT (type));
cb7f680b 8726 index = exact_log2 (index);
8727 if (index >= 0 && index <= 4)
8728 {
8729 unsigned int align = TYPE_ALIGN_UNIT (type);
8730
8731 /* __sync builtins require strict data alignment. */
dcf7024c 8732 if (exact_log2 (align) >= index)
cb7f680b 8733 {
3ec11c49 8734 /* Atomic load. */
2169f33b 8735 if (loaded_val == stored_val
8736 && (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
8737 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
8738 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
3ec11c49 8739 && expand_omp_atomic_load (load_bb, addr, loaded_val, index))
2169f33b 8740 return;
8741
3ec11c49 8742 /* Atomic store. */
2169f33b 8743 if ((GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
8744 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
8745 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
8746 && store_bb == single_succ (load_bb)
8747 && first_stmt (store_bb) == store
3ec11c49 8748 && expand_omp_atomic_store (load_bb, addr, loaded_val,
8749 stored_val, index))
2169f33b 8750 return;
8751
cb7f680b 8752 /* When possible, use specialized atomic update functions. */
8753 if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
3ec11c49 8754 && store_bb == single_succ (load_bb)
8755 && expand_omp_atomic_fetch_op (load_bb, addr,
8756 loaded_val, stored_val, index))
8757 return;
cb7f680b 8758
8759 /* If we don't have specialized __sync builtins, try and implement
8760 as a compare and swap loop. */
8761 if (expand_omp_atomic_pipeline (load_bb, store_bb, addr,
8762 loaded_val, stored_val, index))
8763 return;
8764 }
8765 }
8766
8767 /* The ultimate fallback is wrapping the operation in a mutex. */
8768 expand_omp_atomic_mutex (load_bb, store_bb, addr, loaded_val, stored_val);
8769}
8770
1e8e9920 8771
ca4c3545 8772/* Expand the GIMPLE_OMP_TARGET starting at REGION. */
773c5ba7 8773
8774static void
bc7bff74 8775expand_omp_target (struct omp_region *region)
773c5ba7 8776{
bc7bff74 8777 basic_block entry_bb, exit_bb, new_bb;
ca4c3545 8778 struct function *child_cfun;
8779 tree child_fn, block, t;
bc7bff74 8780 gimple_stmt_iterator gsi;
1a91d914 8781 gomp_target *entry_stmt;
8782 gimple stmt;
bc7bff74 8783 edge e;
ca4c3545 8784 bool offloaded, data_region;
bc7bff74 8785
1a91d914 8786 entry_stmt = as_a <gomp_target *> (last_stmt (region->entry));
bc7bff74 8787 new_bb = region->entry;
ca4c3545 8788
8789 offloaded = is_gimple_omp_offloaded (entry_stmt);
8790 switch (gimple_omp_target_kind (entry_stmt))
8791 {
8792 case GF_OMP_TARGET_KIND_REGION:
8793 case GF_OMP_TARGET_KIND_UPDATE:
8794 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
8795 case GF_OMP_TARGET_KIND_OACC_KERNELS:
8796 case GF_OMP_TARGET_KIND_OACC_UPDATE:
8797 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
8798 data_region = false;
8799 break;
8800 case GF_OMP_TARGET_KIND_DATA:
8801 case GF_OMP_TARGET_KIND_OACC_DATA:
8802 data_region = true;
8803 break;
8804 default:
8805 gcc_unreachable ();
8806 }
8807
8808 child_fn = NULL_TREE;
8809 child_cfun = NULL;
8810 if (offloaded)
bc7bff74 8811 {
8812 child_fn = gimple_omp_target_child_fn (entry_stmt);
8813 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
8814 }
8815
ca4c3545 8816 /* Supported by expand_omp_taskreg, but not here. */
8817 if (child_cfun != NULL)
8818 gcc_checking_assert (!child_cfun->cfg);
8819 gcc_checking_assert (!gimple_in_ssa_p (cfun));
8820
bc7bff74 8821 entry_bb = region->entry;
8822 exit_bb = region->exit;
8823
ca4c3545 8824 if (offloaded)
bc7bff74 8825 {
8826 unsigned srcidx, dstidx, num;
8827
ca4c3545 8828 /* If the offloading region needs data sent from the parent
bc7bff74 8829 function, then the very first statement (except possible
ca4c3545 8830 tree profile counter updates) of the offloading body
bc7bff74 8831 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
8832 &.OMP_DATA_O is passed as an argument to the child function,
8833 we need to replace it with the argument as seen by the child
8834 function.
8835
8836 In most cases, this will end up being the identity assignment
ca4c3545 8837 .OMP_DATA_I = .OMP_DATA_I. However, if the offloading body had
bc7bff74 8838 a function call that has been inlined, the original PARM_DECL
8839 .OMP_DATA_I may have been converted into a different local
8840 variable. In which case, we need to keep the assignment. */
ca4c3545 8841 tree data_arg = gimple_omp_target_data_arg (entry_stmt);
8842 if (data_arg)
bc7bff74 8843 {
8844 basic_block entry_succ_bb = single_succ (entry_bb);
8845 gimple_stmt_iterator gsi;
8846 tree arg;
8847 gimple tgtcopy_stmt = NULL;
ca4c3545 8848 tree sender = TREE_VEC_ELT (data_arg, 0);
bc7bff74 8849
8850 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
8851 {
8852 gcc_assert (!gsi_end_p (gsi));
8853 stmt = gsi_stmt (gsi);
8854 if (gimple_code (stmt) != GIMPLE_ASSIGN)
8855 continue;
8856
8857 if (gimple_num_ops (stmt) == 2)
8858 {
8859 tree arg = gimple_assign_rhs1 (stmt);
8860
8861 /* We're ignoring the subcode because we're
8862 effectively doing a STRIP_NOPS. */
8863
8864 if (TREE_CODE (arg) == ADDR_EXPR
8865 && TREE_OPERAND (arg, 0) == sender)
8866 {
8867 tgtcopy_stmt = stmt;
8868 break;
8869 }
8870 }
8871 }
8872
8873 gcc_assert (tgtcopy_stmt != NULL);
8874 arg = DECL_ARGUMENTS (child_fn);
8875
8876 gcc_assert (gimple_assign_lhs (tgtcopy_stmt) == arg);
8877 gsi_remove (&gsi, true);
8878 }
8879
8880 /* Declare local variables needed in CHILD_CFUN. */
8881 block = DECL_INITIAL (child_fn);
8882 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
ca4c3545 8883 /* The gimplifier could record temporaries in the offloading block
bc7bff74 8884 rather than in containing function's local_decls chain,
8885 which would mean cgraph missed finalizing them. Do it now. */
8886 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
8887 if (TREE_CODE (t) == VAR_DECL
8888 && TREE_STATIC (t)
8889 && !DECL_EXTERNAL (t))
97221fd7 8890 varpool_node::finalize_decl (t);
bc7bff74 8891 DECL_SAVED_TREE (child_fn) = NULL;
8892 /* We'll create a CFG for child_fn, so no gimple body is needed. */
8893 gimple_set_body (child_fn, NULL);
8894 TREE_USED (block) = 1;
8895
8896 /* Reset DECL_CONTEXT on function arguments. */
8897 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
8898 DECL_CONTEXT (t) = child_fn;
8899
ca4c3545 8900 /* Split ENTRY_BB at GIMPLE_*,
bc7bff74 8901 so that it can be moved to the child function. */
8902 gsi = gsi_last_bb (entry_bb);
8903 stmt = gsi_stmt (gsi);
ca4c3545 8904 gcc_assert (stmt
8905 && gimple_code (stmt) == gimple_code (entry_stmt));
bc7bff74 8906 e = split_block (entry_bb, stmt);
923635e7 8907 gsi_remove (&gsi, true);
bc7bff74 8908 entry_bb = e->dest;
8909 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
8910
8911 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
8912 if (exit_bb)
8913 {
8914 gsi = gsi_last_bb (exit_bb);
8915 gcc_assert (!gsi_end_p (gsi)
8916 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
8917 stmt = gimple_build_return (NULL);
8918 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
8919 gsi_remove (&gsi, true);
8920 }
8921
ca4c3545 8922 /* Move the offloading region into CHILD_CFUN. */
bc7bff74 8923
8924 block = gimple_block (entry_stmt);
8925
8926 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
8927 if (exit_bb)
8928 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
8929 /* When the OMP expansion process cannot guarantee an up-to-date
8930 loop tree arrange for the child function to fixup loops. */
8931 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
8932 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
8933
8934 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
8935 num = vec_safe_length (child_cfun->local_decls);
8936 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
8937 {
8938 t = (*child_cfun->local_decls)[srcidx];
8939 if (DECL_CONTEXT (t) == cfun->decl)
8940 continue;
8941 if (srcidx != dstidx)
8942 (*child_cfun->local_decls)[dstidx] = t;
8943 dstidx++;
8944 }
8945 if (dstidx != num)
8946 vec_safe_truncate (child_cfun->local_decls, dstidx);
8947
8948 /* Inform the callgraph about the new function. */
613f2c38 8949 child_cfun->curr_properties = cfun->curr_properties;
8950 child_cfun->has_simduid_loops |= cfun->has_simduid_loops;
8951 child_cfun->has_force_vectorize_loops |= cfun->has_force_vectorize_loops;
6a77ed3d 8952 cgraph_node *node = cgraph_node::get_create (child_fn);
8953 node->parallelized_function = 1;
415d1b9a 8954 cgraph_node::add_new_function (child_fn, true);
bc7bff74 8955
7114ebdd 8956#ifdef ENABLE_OFFLOADING
dccabdd1 8957 /* Add the new function to the offload table. */
8958 vec_safe_push (offload_funcs, child_fn);
7114ebdd 8959#endif
dccabdd1 8960
bc7bff74 8961 /* Fix the callgraph edges for child_cfun. Those for cfun will be
8962 fixed in a following pass. */
8963 push_cfun (child_cfun);
35ee1c66 8964 cgraph_edge::rebuild_edges ();
bc7bff74 8965
7114ebdd 8966#ifdef ENABLE_OFFLOADING
b0c5e347 8967 /* Prevent IPA from removing child_fn as unreachable, since there are no
8968 refs from the parent function to child_fn in offload LTO mode. */
569b71d0 8969 cgraph_node::get (child_fn)->mark_force_output ();
7114ebdd 8970#endif
b0c5e347 8971
bc7bff74 8972 /* Some EH regions might become dead, see PR34608. If
8973 pass_cleanup_cfg isn't the first pass to happen with the
8974 new child, these dead EH edges might cause problems.
8975 Clean them up now. */
8976 if (flag_exceptions)
8977 {
8978 basic_block bb;
8979 bool changed = false;
8980
fc00614f 8981 FOR_EACH_BB_FN (bb, cfun)
bc7bff74 8982 changed |= gimple_purge_dead_eh_edges (bb);
8983 if (changed)
8984 cleanup_tree_cfg ();
8985 }
8986 pop_cfun ();
8987 }
8988
ca4c3545 8989 /* Emit a library call to launch the offloading region, or do data
bc7bff74 8990 transfers. */
8991 tree t1, t2, t3, t4, device, cond, c, clauses;
8992 enum built_in_function start_ix;
8993 location_t clause_loc;
8994
ca4c3545 8995 switch (gimple_omp_target_kind (entry_stmt))
8996 {
8997 case GF_OMP_TARGET_KIND_REGION:
8998 start_ix = BUILT_IN_GOMP_TARGET;
8999 break;
9000 case GF_OMP_TARGET_KIND_DATA:
9001 start_ix = BUILT_IN_GOMP_TARGET_DATA;
9002 break;
9003 case GF_OMP_TARGET_KIND_UPDATE:
9004 start_ix = BUILT_IN_GOMP_TARGET_UPDATE;
9005 break;
9006 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
9007 case GF_OMP_TARGET_KIND_OACC_KERNELS:
9008 start_ix = BUILT_IN_GOACC_PARALLEL;
9009 break;
9010 case GF_OMP_TARGET_KIND_OACC_DATA:
9011 start_ix = BUILT_IN_GOACC_DATA_START;
9012 break;
9013 case GF_OMP_TARGET_KIND_OACC_UPDATE:
9014 start_ix = BUILT_IN_GOACC_UPDATE;
9015 break;
9016 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
9017 start_ix = BUILT_IN_GOACC_ENTER_EXIT_DATA;
9018 break;
9019 default:
9020 gcc_unreachable ();
9021 }
bc7bff74 9022
ca4c3545 9023 clauses = gimple_omp_target_clauses (entry_stmt);
bc7bff74 9024
ca4c3545 9025 /* By default, the value of DEVICE is GOMP_DEVICE_ICV (let runtime
9026 library choose) and there is no conditional. */
bc7bff74 9027 cond = NULL_TREE;
ca4c3545 9028 device = build_int_cst (integer_type_node, GOMP_DEVICE_ICV);
bc7bff74 9029
9030 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
9031 if (c)
9032 cond = OMP_CLAUSE_IF_EXPR (c);
9033
9034 c = find_omp_clause (clauses, OMP_CLAUSE_DEVICE);
9035 if (c)
9036 {
ca4c3545 9037 /* Even if we pass it to all library function calls, it is currently only
9038 defined/used for the OpenMP target ones. */
9039 gcc_checking_assert (start_ix == BUILT_IN_GOMP_TARGET
9040 || start_ix == BUILT_IN_GOMP_TARGET_DATA
9041 || start_ix == BUILT_IN_GOMP_TARGET_UPDATE);
9042
bc7bff74 9043 device = OMP_CLAUSE_DEVICE_ID (c);
9044 clause_loc = OMP_CLAUSE_LOCATION (c);
9045 }
9046 else
9047 clause_loc = gimple_location (entry_stmt);
9048
9049 /* Ensure 'device' is of the correct type. */
9050 device = fold_convert_loc (clause_loc, integer_type_node, device);
9051
9052 /* If we found the clause 'if (cond)', build
ca4c3545 9053 (cond ? device : GOMP_DEVICE_HOST_FALLBACK). */
bc7bff74 9054 if (cond)
9055 {
9056 cond = gimple_boolify (cond);
9057
9058 basic_block cond_bb, then_bb, else_bb;
9059 edge e;
9060 tree tmp_var;
9061
f9e245b2 9062 tmp_var = create_tmp_var (TREE_TYPE (device));
ca4c3545 9063 if (offloaded)
4302d619 9064 e = split_block_after_labels (new_bb);
ca4c3545 9065 else
bc7bff74 9066 {
9067 gsi = gsi_last_bb (new_bb);
9068 gsi_prev (&gsi);
9069 e = split_block (new_bb, gsi_stmt (gsi));
9070 }
bc7bff74 9071 cond_bb = e->src;
9072 new_bb = e->dest;
9073 remove_edge (e);
9074
9075 then_bb = create_empty_bb (cond_bb);
9076 else_bb = create_empty_bb (then_bb);
9077 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
9078 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
9079
9080 stmt = gimple_build_cond_empty (cond);
9081 gsi = gsi_last_bb (cond_bb);
9082 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
9083
9084 gsi = gsi_start_bb (then_bb);
9085 stmt = gimple_build_assign (tmp_var, device);
9086 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
9087
9088 gsi = gsi_start_bb (else_bb);
9089 stmt = gimple_build_assign (tmp_var,
ca4c3545 9090 build_int_cst (integer_type_node,
9091 GOMP_DEVICE_HOST_FALLBACK));
bc7bff74 9092 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
9093
9094 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
9095 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
b3083327 9096 add_bb_to_loop (then_bb, cond_bb->loop_father);
9097 add_bb_to_loop (else_bb, cond_bb->loop_father);
bc7bff74 9098 make_edge (then_bb, new_bb, EDGE_FALLTHRU);
9099 make_edge (else_bb, new_bb, EDGE_FALLTHRU);
9100
9101 device = tmp_var;
9102 }
9103
9104 gsi = gsi_last_bb (new_bb);
9105 t = gimple_omp_target_data_arg (entry_stmt);
9106 if (t == NULL)
9107 {
9108 t1 = size_zero_node;
9109 t2 = build_zero_cst (ptr_type_node);
9110 t3 = t2;
9111 t4 = t2;
9112 }
9113 else
9114 {
9115 t1 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t, 1))));
9116 t1 = size_binop (PLUS_EXPR, t1, size_int (1));
9117 t2 = build_fold_addr_expr (TREE_VEC_ELT (t, 0));
9118 t3 = build_fold_addr_expr (TREE_VEC_ELT (t, 1));
9119 t4 = build_fold_addr_expr (TREE_VEC_ELT (t, 2));
9120 }
9121
9122 gimple g;
ca4c3545 9123 /* The maximum number used by any start_ix, without varargs. */
02c05c9b 9124 auto_vec<tree, 11> args;
9125 args.quick_push (device);
ca4c3545 9126 if (offloaded)
02c05c9b 9127 args.quick_push (build_fold_addr_expr (child_fn));
dc19c8fd 9128 switch (start_ix)
9129 {
9130 case BUILT_IN_GOMP_TARGET:
9131 case BUILT_IN_GOMP_TARGET_DATA:
9132 case BUILT_IN_GOMP_TARGET_UPDATE:
9133 /* This const void * is part of the current ABI, but we're not actually
9134 using it. */
02c05c9b 9135 args.quick_push (build_zero_cst (ptr_type_node));
dc19c8fd 9136 break;
9137 case BUILT_IN_GOACC_DATA_START:
9138 case BUILT_IN_GOACC_ENTER_EXIT_DATA:
9139 case BUILT_IN_GOACC_PARALLEL:
9140 case BUILT_IN_GOACC_UPDATE:
9141 break;
9142 default:
9143 gcc_unreachable ();
9144 }
02c05c9b 9145 args.quick_push (t1);
9146 args.quick_push (t2);
9147 args.quick_push (t3);
9148 args.quick_push (t4);
ca4c3545 9149 switch (start_ix)
9150 {
9151 case BUILT_IN_GOACC_DATA_START:
9152 case BUILT_IN_GOMP_TARGET:
9153 case BUILT_IN_GOMP_TARGET_DATA:
9154 case BUILT_IN_GOMP_TARGET_UPDATE:
9155 break;
9156 case BUILT_IN_GOACC_PARALLEL:
9157 {
9158 tree t_num_gangs, t_num_workers, t_vector_length;
9159
9160 /* Default values for num_gangs, num_workers, and vector_length. */
9161 t_num_gangs = t_num_workers = t_vector_length
9162 = fold_convert_loc (gimple_location (entry_stmt),
9163 integer_type_node, integer_one_node);
9164 /* ..., but if present, use the value specified by the respective
9165 clause, making sure that are of the correct type. */
9166 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_GANGS);
9167 if (c)
9168 t_num_gangs = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9169 integer_type_node,
9170 OMP_CLAUSE_NUM_GANGS_EXPR (c));
9171 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_WORKERS);
9172 if (c)
9173 t_num_workers = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9174 integer_type_node,
9175 OMP_CLAUSE_NUM_WORKERS_EXPR (c));
9176 c = find_omp_clause (clauses, OMP_CLAUSE_VECTOR_LENGTH);
9177 if (c)
9178 t_vector_length = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9179 integer_type_node,
9180 OMP_CLAUSE_VECTOR_LENGTH_EXPR (c));
02c05c9b 9181 args.quick_push (t_num_gangs);
9182 args.quick_push (t_num_workers);
9183 args.quick_push (t_vector_length);
ca4c3545 9184 }
9185 /* FALLTHRU */
9186 case BUILT_IN_GOACC_ENTER_EXIT_DATA:
9187 case BUILT_IN_GOACC_UPDATE:
9188 {
9189 tree t_async;
9190 int t_wait_idx;
9191
9192 /* Default values for t_async. */
9193 t_async = fold_convert_loc (gimple_location (entry_stmt),
9194 integer_type_node,
9195 build_int_cst (integer_type_node,
9196 GOMP_ASYNC_SYNC));
9197 /* ..., but if present, use the value specified by the respective
9198 clause, making sure that is of the correct type. */
9199 c = find_omp_clause (clauses, OMP_CLAUSE_ASYNC);
9200 if (c)
9201 t_async = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9202 integer_type_node,
9203 OMP_CLAUSE_ASYNC_EXPR (c));
9204
02c05c9b 9205 args.quick_push (t_async);
ca4c3545 9206 /* Save the index, and... */
02c05c9b 9207 t_wait_idx = args.length ();
ca4c3545 9208 /* ... push a default value. */
02c05c9b 9209 args.quick_push (fold_convert_loc (gimple_location (entry_stmt),
9210 integer_type_node,
9211 integer_zero_node));
ca4c3545 9212 c = find_omp_clause (clauses, OMP_CLAUSE_WAIT);
9213 if (c)
9214 {
9215 int n = 0;
9216
9217 for (; c; c = OMP_CLAUSE_CHAIN (c))
9218 {
9219 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_WAIT)
9220 {
02c05c9b 9221 args.safe_push (fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9222 integer_type_node,
9223 OMP_CLAUSE_WAIT_EXPR (c)));
ca4c3545 9224 n++;
9225 }
9226 }
9227
9228 /* Now that we know the number, replace the default value. */
02c05c9b 9229 args.ordered_remove (t_wait_idx);
9230 args.quick_insert (t_wait_idx,
9231 fold_convert_loc (gimple_location (entry_stmt),
9232 integer_type_node,
9233 build_int_cst (integer_type_node, n)));
ca4c3545 9234 }
9235 }
9236 break;
9237 default:
9238 gcc_unreachable ();
bc7bff74 9239 }
ca4c3545 9240
02c05c9b 9241 g = gimple_build_call_vec (builtin_decl_explicit (start_ix), args);
bc7bff74 9242 gimple_set_location (g, gimple_location (entry_stmt));
9243 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
ca4c3545 9244 if (!offloaded)
bc7bff74 9245 {
9246 g = gsi_stmt (gsi);
9247 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_TARGET);
9248 gsi_remove (&gsi, true);
9249 }
ca4c3545 9250 if (data_region
9251 && region->exit)
bc7bff74 9252 {
9253 gsi = gsi_last_bb (region->exit);
9254 g = gsi_stmt (gsi);
9255 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_RETURN);
9256 gsi_remove (&gsi, true);
9257 }
9258}
9259
9260
9261/* Expand the parallel region tree rooted at REGION. Expansion
9262 proceeds in depth-first order. Innermost regions are expanded
9263 first. This way, parallel regions that require a new function to
75a70cf9 9264 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
773c5ba7 9265 internal dependencies in their body. */
9266
9267static void
9268expand_omp (struct omp_region *region)
9269{
9270 while (region)
9271 {
1d22f541 9272 location_t saved_location;
bc7bff74 9273 gimple inner_stmt = NULL;
1d22f541 9274
d1d5b012 9275 /* First, determine whether this is a combined parallel+workshare
9276 region. */
75a70cf9 9277 if (region->type == GIMPLE_OMP_PARALLEL)
d1d5b012 9278 determine_parallel_type (region);
9279
bc7bff74 9280 if (region->type == GIMPLE_OMP_FOR
9281 && gimple_omp_for_combined_p (last_stmt (region->entry)))
9282 inner_stmt = last_stmt (region->inner->entry);
9283
773c5ba7 9284 if (region->inner)
9285 expand_omp (region->inner);
9286
1d22f541 9287 saved_location = input_location;
75a70cf9 9288 if (gimple_has_location (last_stmt (region->entry)))
9289 input_location = gimple_location (last_stmt (region->entry));
1d22f541 9290
61e47ac8 9291 switch (region->type)
773c5ba7 9292 {
75a70cf9 9293 case GIMPLE_OMP_PARALLEL:
9294 case GIMPLE_OMP_TASK:
fd6481cf 9295 expand_omp_taskreg (region);
9296 break;
9297
75a70cf9 9298 case GIMPLE_OMP_FOR:
bc7bff74 9299 expand_omp_for (region, inner_stmt);
61e47ac8 9300 break;
773c5ba7 9301
75a70cf9 9302 case GIMPLE_OMP_SECTIONS:
61e47ac8 9303 expand_omp_sections (region);
9304 break;
773c5ba7 9305
75a70cf9 9306 case GIMPLE_OMP_SECTION:
61e47ac8 9307 /* Individual omp sections are handled together with their
75a70cf9 9308 parent GIMPLE_OMP_SECTIONS region. */
61e47ac8 9309 break;
773c5ba7 9310
75a70cf9 9311 case GIMPLE_OMP_SINGLE:
61e47ac8 9312 expand_omp_single (region);
9313 break;
773c5ba7 9314
75a70cf9 9315 case GIMPLE_OMP_MASTER:
bc7bff74 9316 case GIMPLE_OMP_TASKGROUP:
75a70cf9 9317 case GIMPLE_OMP_ORDERED:
9318 case GIMPLE_OMP_CRITICAL:
bc7bff74 9319 case GIMPLE_OMP_TEAMS:
61e47ac8 9320 expand_omp_synch (region);
9321 break;
773c5ba7 9322
75a70cf9 9323 case GIMPLE_OMP_ATOMIC_LOAD:
cb7f680b 9324 expand_omp_atomic (region);
9325 break;
9326
bc7bff74 9327 case GIMPLE_OMP_TARGET:
9328 expand_omp_target (region);
9329 break;
9330
61e47ac8 9331 default:
9332 gcc_unreachable ();
9333 }
cc5982dc 9334
1d22f541 9335 input_location = saved_location;
773c5ba7 9336 region = region->next;
9337 }
9338}
9339
9340
9341/* Helper for build_omp_regions. Scan the dominator tree starting at
28c92cbb 9342 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
9343 true, the function ends once a single tree is built (otherwise, whole
9344 forest of OMP constructs may be built). */
773c5ba7 9345
9346static void
28c92cbb 9347build_omp_regions_1 (basic_block bb, struct omp_region *parent,
9348 bool single_tree)
773c5ba7 9349{
75a70cf9 9350 gimple_stmt_iterator gsi;
9351 gimple stmt;
773c5ba7 9352 basic_block son;
9353
75a70cf9 9354 gsi = gsi_last_bb (bb);
9355 if (!gsi_end_p (gsi) && is_gimple_omp (gsi_stmt (gsi)))
773c5ba7 9356 {
9357 struct omp_region *region;
75a70cf9 9358 enum gimple_code code;
773c5ba7 9359
75a70cf9 9360 stmt = gsi_stmt (gsi);
9361 code = gimple_code (stmt);
9362 if (code == GIMPLE_OMP_RETURN)
773c5ba7 9363 {
9364 /* STMT is the return point out of region PARENT. Mark it
9365 as the exit point and make PARENT the immediately
9366 enclosing region. */
9367 gcc_assert (parent);
9368 region = parent;
61e47ac8 9369 region->exit = bb;
773c5ba7 9370 parent = parent->outer;
773c5ba7 9371 }
75a70cf9 9372 else if (code == GIMPLE_OMP_ATOMIC_STORE)
cb7f680b 9373 {
75a70cf9 9374 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
9375 GIMPLE_OMP_RETURN, but matches with
9376 GIMPLE_OMP_ATOMIC_LOAD. */
cb7f680b 9377 gcc_assert (parent);
75a70cf9 9378 gcc_assert (parent->type == GIMPLE_OMP_ATOMIC_LOAD);
cb7f680b 9379 region = parent;
9380 region->exit = bb;
9381 parent = parent->outer;
9382 }
75a70cf9 9383 else if (code == GIMPLE_OMP_CONTINUE)
61e47ac8 9384 {
9385 gcc_assert (parent);
9386 parent->cont = bb;
9387 }
75a70cf9 9388 else if (code == GIMPLE_OMP_SECTIONS_SWITCH)
ac6e3339 9389 {
75a70cf9 9390 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
9391 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
ac6e3339 9392 }
773c5ba7 9393 else
9394 {
61e47ac8 9395 region = new_omp_region (bb, code, parent);
ca4c3545 9396 /* Otherwise... */
9397 if (code == GIMPLE_OMP_TARGET)
9398 {
9399 switch (gimple_omp_target_kind (stmt))
9400 {
9401 case GF_OMP_TARGET_KIND_REGION:
9402 case GF_OMP_TARGET_KIND_DATA:
9403 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
9404 case GF_OMP_TARGET_KIND_OACC_KERNELS:
9405 case GF_OMP_TARGET_KIND_OACC_DATA:
9406 break;
9407 case GF_OMP_TARGET_KIND_UPDATE:
9408 case GF_OMP_TARGET_KIND_OACC_UPDATE:
9409 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
9410 /* ..., other than for those stand-alone directives... */
9411 region = NULL;
9412 break;
9413 default:
9414 gcc_unreachable ();
9415 }
9416 }
9417 /* ..., this directive becomes the parent for a new region. */
9418 if (region)
9419 parent = region;
773c5ba7 9420 }
773c5ba7 9421 }
9422
28c92cbb 9423 if (single_tree && !parent)
9424 return;
9425
773c5ba7 9426 for (son = first_dom_son (CDI_DOMINATORS, bb);
9427 son;
9428 son = next_dom_son (CDI_DOMINATORS, son))
28c92cbb 9429 build_omp_regions_1 (son, parent, single_tree);
9430}
9431
9432/* Builds the tree of OMP regions rooted at ROOT, storing it to
9433 root_omp_region. */
9434
9435static void
9436build_omp_regions_root (basic_block root)
9437{
9438 gcc_assert (root_omp_region == NULL);
9439 build_omp_regions_1 (root, NULL, true);
9440 gcc_assert (root_omp_region != NULL);
773c5ba7 9441}
9442
28c92cbb 9443/* Expands omp construct (and its subconstructs) starting in HEAD. */
9444
9445void
9446omp_expand_local (basic_block head)
9447{
9448 build_omp_regions_root (head);
9449 if (dump_file && (dump_flags & TDF_DETAILS))
9450 {
9451 fprintf (dump_file, "\nOMP region tree\n\n");
9452 dump_omp_region (dump_file, root_omp_region, 0);
9453 fprintf (dump_file, "\n");
9454 }
9455
9456 remove_exit_barriers (root_omp_region);
9457 expand_omp (root_omp_region);
9458
9459 free_omp_regions ();
9460}
773c5ba7 9461
9462/* Scan the CFG and build a tree of OMP regions. Return the root of
9463 the OMP region tree. */
9464
9465static void
9466build_omp_regions (void)
9467{
61e47ac8 9468 gcc_assert (root_omp_region == NULL);
773c5ba7 9469 calculate_dominance_info (CDI_DOMINATORS);
34154e27 9470 build_omp_regions_1 (ENTRY_BLOCK_PTR_FOR_FN (cfun), NULL, false);
773c5ba7 9471}
9472
773c5ba7 9473/* Main entry point for expanding OMP-GIMPLE into runtime calls. */
9474
2a1990e9 9475static unsigned int
773c5ba7 9476execute_expand_omp (void)
9477{
9478 build_omp_regions ();
9479
61e47ac8 9480 if (!root_omp_region)
9481 return 0;
773c5ba7 9482
61e47ac8 9483 if (dump_file)
9484 {
9485 fprintf (dump_file, "\nOMP region tree\n\n");
9486 dump_omp_region (dump_file, root_omp_region, 0);
9487 fprintf (dump_file, "\n");
773c5ba7 9488 }
61e47ac8 9489
9490 remove_exit_barriers (root_omp_region);
9491
9492 expand_omp (root_omp_region);
9493
61e47ac8 9494 cleanup_tree_cfg ();
9495
9496 free_omp_regions ();
9497
2a1990e9 9498 return 0;
773c5ba7 9499}
9500
79acaae1 9501/* OMP expansion -- the default pass, run before creation of SSA form. */
9502
cbe8bda8 9503namespace {
9504
9505const pass_data pass_data_expand_omp =
9506{
9507 GIMPLE_PASS, /* type */
9508 "ompexp", /* name */
9509 OPTGROUP_NONE, /* optinfo_flags */
cbe8bda8 9510 TV_NONE, /* tv_id */
9511 PROP_gimple_any, /* properties_required */
8917c50b 9512 PROP_gimple_eomp, /* properties_provided */
cbe8bda8 9513 0, /* properties_destroyed */
9514 0, /* todo_flags_start */
9515 0, /* todo_flags_finish */
773c5ba7 9516};
cbe8bda8 9517
9518class pass_expand_omp : public gimple_opt_pass
9519{
9520public:
9af5ce0c 9521 pass_expand_omp (gcc::context *ctxt)
9522 : gimple_opt_pass (pass_data_expand_omp, ctxt)
cbe8bda8 9523 {}
9524
9525 /* opt_pass methods: */
8917c50b 9526 virtual unsigned int execute (function *)
31315c24 9527 {
ca4c3545 9528 bool gate = ((flag_cilkplus != 0 || flag_openacc != 0 || flag_openmp != 0
9529 || flag_openmp_simd != 0)
9530 && !seen_error ());
31315c24 9531
8917c50b 9532 /* This pass always runs, to provide PROP_gimple_eomp.
ca4c3545 9533 But often, there is nothing to do. */
8917c50b 9534 if (!gate)
9535 return 0;
9536
9537 return execute_expand_omp ();
9538 }
cbe8bda8 9539
9540}; // class pass_expand_omp
9541
9542} // anon namespace
9543
9544gimple_opt_pass *
9545make_pass_expand_omp (gcc::context *ctxt)
9546{
9547 return new pass_expand_omp (ctxt);
9548}
8917c50b 9549
9550namespace {
9551
9552const pass_data pass_data_expand_omp_ssa =
9553{
9554 GIMPLE_PASS, /* type */
9555 "ompexpssa", /* name */
9556 OPTGROUP_NONE, /* optinfo_flags */
9557 TV_NONE, /* tv_id */
9558 PROP_cfg | PROP_ssa, /* properties_required */
9559 PROP_gimple_eomp, /* properties_provided */
9560 0, /* properties_destroyed */
9561 0, /* todo_flags_start */
9562 TODO_cleanup_cfg | TODO_rebuild_alias, /* todo_flags_finish */
9563};
9564
9565class pass_expand_omp_ssa : public gimple_opt_pass
9566{
9567public:
9568 pass_expand_omp_ssa (gcc::context *ctxt)
9569 : gimple_opt_pass (pass_data_expand_omp_ssa, ctxt)
9570 {}
9571
9572 /* opt_pass methods: */
9573 virtual bool gate (function *fun)
9574 {
9575 return !(fun->curr_properties & PROP_gimple_eomp);
9576 }
9577 virtual unsigned int execute (function *) { return execute_expand_omp (); }
9578
9579}; // class pass_expand_omp_ssa
9580
9581} // anon namespace
9582
9583gimple_opt_pass *
9584make_pass_expand_omp_ssa (gcc::context *ctxt)
9585{
9586 return new pass_expand_omp_ssa (ctxt);
9587}
773c5ba7 9588\f
ca4c3545 9589/* Routines to lower OMP directives into OMP-GIMPLE. */
9590
9591/* Helper function to preform, potentially COMPLEX_TYPE, operation and
9592 convert it to gimple. */
9593static void
9594oacc_gimple_assign (tree dest, tree_code op, tree src, gimple_seq *seq)
9595{
9596 gimple stmt;
9597
9598 if (TREE_CODE (TREE_TYPE (dest)) != COMPLEX_TYPE)
9599 {
9600 stmt = gimple_build_assign (dest, op, dest, src);
9601 gimple_seq_add_stmt (seq, stmt);
9602 return;
9603 }
9604
9605 tree t = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9606 tree rdest = fold_build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (dest)), dest);
9607 gimplify_assign (t, rdest, seq);
9608 rdest = t;
9609
9610 t = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9611 tree idest = fold_build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (dest)), dest);
9612 gimplify_assign (t, idest, seq);
9613 idest = t;
9614
9615 t = create_tmp_var (TREE_TYPE (TREE_TYPE (src)));
9616 tree rsrc = fold_build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (src)), src);
9617 gimplify_assign (t, rsrc, seq);
9618 rsrc = t;
9619
9620 t = create_tmp_var (TREE_TYPE (TREE_TYPE (src)));
9621 tree isrc = fold_build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (src)), src);
9622 gimplify_assign (t, isrc, seq);
9623 isrc = t;
9624
9625 tree r = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9626 tree i = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9627 tree result;
9628
9629 if (op == PLUS_EXPR)
9630 {
9631 stmt = gimple_build_assign (r, op, rdest, rsrc);
9632 gimple_seq_add_stmt (seq, stmt);
9633
9634 stmt = gimple_build_assign (i, op, idest, isrc);
9635 gimple_seq_add_stmt (seq, stmt);
9636 }
9637 else if (op == MULT_EXPR)
9638 {
9639 /* Let x = a + ib = dest, y = c + id = src.
9640 x * y = (ac - bd) + i(ad + bc) */
9641 tree ac = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9642 tree bd = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9643 tree ad = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9644 tree bc = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9645
9646 stmt = gimple_build_assign (ac, MULT_EXPR, rdest, rsrc);
9647 gimple_seq_add_stmt (seq, stmt);
9648
9649 stmt = gimple_build_assign (bd, MULT_EXPR, idest, isrc);
9650 gimple_seq_add_stmt (seq, stmt);
9651
9652 stmt = gimple_build_assign (r, MINUS_EXPR, ac, bd);
9653 gimple_seq_add_stmt (seq, stmt);
9654
9655 stmt = gimple_build_assign (ad, MULT_EXPR, rdest, isrc);
9656 gimple_seq_add_stmt (seq, stmt);
9657
9658 stmt = gimple_build_assign (bd, MULT_EXPR, idest, rsrc);
9659 gimple_seq_add_stmt (seq, stmt);
9660
9661 stmt = gimple_build_assign (i, PLUS_EXPR, ad, bc);
9662 gimple_seq_add_stmt (seq, stmt);
9663 }
9664 else
9665 gcc_unreachable ();
9666
9667 result = build2 (COMPLEX_EXPR, TREE_TYPE (dest), r, i);
9668 gimplify_assign (dest, result, seq);
9669}
9670
9671/* Helper function to initialize local data for the reduction arrays.
9672 The reduction arrays need to be placed inside the calling function
9673 for accelerators, or else the host won't be able to preform the final
9674 reduction. */
9675
9676static void
9677oacc_initialize_reduction_data (tree clauses, tree nthreads,
9678 gimple_seq *stmt_seqp, omp_context *ctx)
9679{
9680 tree c, t, oc;
9681 gimple stmt;
9682 omp_context *octx;
9683
9684 /* Find the innermost OpenACC parallel context. */
9685 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET
9686 && (gimple_omp_target_kind (ctx->stmt)
9687 == GF_OMP_TARGET_KIND_OACC_PARALLEL))
9688 octx = ctx;
9689 else
9690 octx = ctx->outer;
9691 gcc_checking_assert (gimple_code (octx->stmt) == GIMPLE_OMP_TARGET
9692 && (gimple_omp_target_kind (octx->stmt)
9693 == GF_OMP_TARGET_KIND_OACC_PARALLEL));
9694
9695 /* Extract the clauses. */
9696 oc = gimple_omp_target_clauses (octx->stmt);
9697
9698 /* Find the last outer clause. */
9699 for (; oc && OMP_CLAUSE_CHAIN (oc); oc = OMP_CLAUSE_CHAIN (oc))
9700 ;
9701
9702 /* Allocate arrays for each reduction variable. */
9703 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9704 {
9705 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
9706 continue;
9707
9708 tree var = OMP_CLAUSE_DECL (c);
9709 tree type = get_base_type (var);
9710 tree array = lookup_oacc_reduction (oacc_get_reduction_array_id (var),
9711 ctx);
9712 tree size, call;
9713
9714 /* Calculate size of the reduction array. */
9715 t = create_tmp_var (TREE_TYPE (nthreads));
9716 stmt = gimple_build_assign (t, MULT_EXPR, nthreads,
9717 fold_convert (TREE_TYPE (nthreads),
9718 TYPE_SIZE_UNIT (type)));
9719 gimple_seq_add_stmt (stmt_seqp, stmt);
9720
9721 size = create_tmp_var (sizetype);
9722 gimplify_assign (size, fold_build1 (NOP_EXPR, sizetype, t), stmt_seqp);
9723
9724 /* Now allocate memory for it. */
9725 call = unshare_expr (builtin_decl_explicit (BUILT_IN_ALLOCA));
9726 stmt = gimple_build_call (call, 1, size);
9727 gimple_call_set_lhs (stmt, array);
9728 gimple_seq_add_stmt (stmt_seqp, stmt);
9729
9730 /* Map this array into the accelerator. */
9731
9732 /* Add the reduction array to the list of clauses. */
9733 tree x = array;
9734 t = build_omp_clause (gimple_location (ctx->stmt), OMP_CLAUSE_MAP);
9735 OMP_CLAUSE_SET_MAP_KIND (t, GOMP_MAP_FORCE_FROM);
9736 OMP_CLAUSE_DECL (t) = x;
9737 OMP_CLAUSE_CHAIN (t) = NULL;
9738 if (oc)
9739 OMP_CLAUSE_CHAIN (oc) = t;
9740 else
9741 gimple_omp_target_set_clauses (as_a <gomp_target *> (octx->stmt), t);
9742 OMP_CLAUSE_SIZE (t) = size;
9743 oc = t;
9744 }
9745}
9746
9747/* Helper function to process the array of partial reductions. Nthreads
9748 indicates the number of threads. Unfortunately, GOACC_GET_NUM_THREADS
9749 cannot be used here, because nthreads on the host may be different than
9750 on the accelerator. */
9751
9752static void
9753oacc_finalize_reduction_data (tree clauses, tree nthreads,
9754 gimple_seq *stmt_seqp, omp_context *ctx)
9755{
9756 tree c, x, var, array, loop_header, loop_body, loop_exit, type;
9757 gimple stmt;
9758
9759 /* Create for loop.
9760
9761 let var = the original reduction variable
9762 let array = reduction variable array
9763
9764 for (i = 0; i < nthreads; i++)
9765 var op= array[i]
9766 */
9767
9768 loop_header = create_artificial_label (UNKNOWN_LOCATION);
9769 loop_body = create_artificial_label (UNKNOWN_LOCATION);
9770 loop_exit = create_artificial_label (UNKNOWN_LOCATION);
9771
9772 /* Create and initialize an index variable. */
9773 tree ix = create_tmp_var (sizetype);
9774 gimplify_assign (ix, fold_build1 (NOP_EXPR, sizetype, integer_zero_node),
9775 stmt_seqp);
9776
9777 /* Insert the loop header label here. */
9778 gimple_seq_add_stmt (stmt_seqp, gimple_build_label (loop_header));
9779
9780 /* Exit loop if ix >= nthreads. */
9781 x = create_tmp_var (sizetype);
9782 gimplify_assign (x, fold_build1 (NOP_EXPR, sizetype, nthreads), stmt_seqp);
9783 stmt = gimple_build_cond (GE_EXPR, ix, x, loop_exit, loop_body);
9784 gimple_seq_add_stmt (stmt_seqp, stmt);
9785
9786 /* Insert the loop body label here. */
9787 gimple_seq_add_stmt (stmt_seqp, gimple_build_label (loop_body));
9788
9789 /* Collapse each reduction array, one element at a time. */
9790 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9791 {
9792 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
9793 continue;
9794
9795 tree_code reduction_code = OMP_CLAUSE_REDUCTION_CODE (c);
9796
9797 /* reduction(-:var) sums up the partial results, so it acts
9798 identically to reduction(+:var). */
9799 if (reduction_code == MINUS_EXPR)
9800 reduction_code = PLUS_EXPR;
9801
9802 /* Set up reduction variable var. */
9803 var = OMP_CLAUSE_DECL (c);
9804 type = get_base_type (var);
9805 array = lookup_oacc_reduction (oacc_get_reduction_array_id
9806 (OMP_CLAUSE_DECL (c)), ctx);
9807
9808 /* Calculate the array offset. */
9809 tree offset = create_tmp_var (sizetype);
9810 gimplify_assign (offset, TYPE_SIZE_UNIT (type), stmt_seqp);
9811 stmt = gimple_build_assign (offset, MULT_EXPR, offset, ix);
9812 gimple_seq_add_stmt (stmt_seqp, stmt);
9813
9814 tree ptr = create_tmp_var (TREE_TYPE (array));
9815 stmt = gimple_build_assign (ptr, POINTER_PLUS_EXPR, array, offset);
9816 gimple_seq_add_stmt (stmt_seqp, stmt);
9817
9818 /* Extract array[ix] into mem. */
9819 tree mem = create_tmp_var (type);
9820 gimplify_assign (mem, build_simple_mem_ref (ptr), stmt_seqp);
9821
9822 /* Find the original reduction variable. */
9823 if (is_reference (var))
9824 var = build_simple_mem_ref (var);
9825
9826 tree t = create_tmp_var (type);
9827
9828 x = lang_hooks.decls.omp_clause_assign_op (c, t, var);
9829 gimplify_and_add (unshare_expr(x), stmt_seqp);
9830
9831 /* var = var op mem */
9832 switch (OMP_CLAUSE_REDUCTION_CODE (c))
9833 {
9834 case TRUTH_ANDIF_EXPR:
9835 case TRUTH_ORIF_EXPR:
9836 t = fold_build2 (OMP_CLAUSE_REDUCTION_CODE (c), integer_type_node,
9837 t, mem);
9838 gimplify_and_add (t, stmt_seqp);
9839 break;
9840 default:
9841 /* The lhs isn't a gimple_reg when var is COMPLEX_TYPE. */
9842 oacc_gimple_assign (t, OMP_CLAUSE_REDUCTION_CODE (c), mem,
9843 stmt_seqp);
9844 }
9845
9846 t = fold_build1 (NOP_EXPR, TREE_TYPE (var), t);
9847 x = lang_hooks.decls.omp_clause_assign_op (c, var, t);
9848 gimplify_and_add (unshare_expr(x), stmt_seqp);
9849 }
9850
9851 /* Increment the induction variable. */
9852 tree one = fold_build1 (NOP_EXPR, sizetype, integer_one_node);
9853 stmt = gimple_build_assign (ix, PLUS_EXPR, ix, one);
9854 gimple_seq_add_stmt (stmt_seqp, stmt);
9855
9856 /* Go back to the top of the loop. */
9857 gimple_seq_add_stmt (stmt_seqp, gimple_build_goto (loop_header));
9858
9859 /* Place the loop exit label here. */
9860 gimple_seq_add_stmt (stmt_seqp, gimple_build_label (loop_exit));
9861}
9862
9863/* Scan through all of the gimple stmts searching for an OMP_FOR_EXPR, and
9864 scan that for reductions. */
9865
9866static void
9867oacc_process_reduction_data (gimple_seq *body, gimple_seq *in_stmt_seqp,
9868 gimple_seq *out_stmt_seqp, omp_context *ctx)
9869{
9870 gimple_stmt_iterator gsi;
9871 gimple_seq inner = NULL;
9872
9873 /* A collapse clause may have inserted a new bind block. */
9874 gsi = gsi_start (*body);
9875 while (!gsi_end_p (gsi))
9876 {
9877 gimple stmt = gsi_stmt (gsi);
9878 if (gbind *bind_stmt = dyn_cast <gbind *> (stmt))
9879 {
9880 inner = gimple_bind_body (bind_stmt);
9881 body = &inner;
9882 gsi = gsi_start (*body);
9883 }
9884 else if (dyn_cast <gomp_for *> (stmt))
9885 break;
9886 else
9887 gsi_next (&gsi);
9888 }
9889
9890 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
9891 {
9892 tree clauses, nthreads, t, c, acc_device, acc_device_host, call,
9893 enter, exit;
9894 bool reduction_found = false;
9895
9896 gimple stmt = gsi_stmt (gsi);
9897
9898 switch (gimple_code (stmt))
9899 {
9900 case GIMPLE_OMP_FOR:
9901 clauses = gimple_omp_for_clauses (stmt);
9902
9903 /* Search for a reduction clause. */
9904 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9905 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
9906 {
9907 reduction_found = true;
9908 break;
9909 }
9910
9911 if (!reduction_found)
9912 break;
9913
9914 ctx = maybe_lookup_ctx (stmt);
9915 t = NULL_TREE;
9916
9917 /* Extract the number of threads. */
9918 nthreads = create_tmp_var (sizetype);
9919 t = oacc_max_threads (ctx);
9920 gimplify_assign (nthreads, t, in_stmt_seqp);
9921
9922 /* Determine if this is kernel will be executed on the host. */
9923 call = builtin_decl_explicit (BUILT_IN_ACC_GET_DEVICE_TYPE);
9924 acc_device = create_tmp_var (integer_type_node, ".acc_device_type");
9925 stmt = gimple_build_call (call, 0);
9926 gimple_call_set_lhs (stmt, acc_device);
9927 gimple_seq_add_stmt (in_stmt_seqp, stmt);
9928
9929 /* Set nthreads = 1 for ACC_DEVICE_TYPE=host. */
9930 acc_device_host = create_tmp_var (integer_type_node,
9931 ".acc_device_host");
9932 gimplify_assign (acc_device_host,
9933 build_int_cst (integer_type_node,
9934 GOMP_DEVICE_HOST),
9935 in_stmt_seqp);
9936
9937 enter = create_artificial_label (UNKNOWN_LOCATION);
9938 exit = create_artificial_label (UNKNOWN_LOCATION);
9939
9940 stmt = gimple_build_cond (EQ_EXPR, acc_device, acc_device_host,
9941 enter, exit);
9942 gimple_seq_add_stmt (in_stmt_seqp, stmt);
9943 gimple_seq_add_stmt (in_stmt_seqp, gimple_build_label (enter));
9944 gimplify_assign (nthreads, fold_build1 (NOP_EXPR, sizetype,
9945 integer_one_node),
9946 in_stmt_seqp);
9947 gimple_seq_add_stmt (in_stmt_seqp, gimple_build_label (exit));
9948
9949 /* Also, set nthreads = 1 for ACC_DEVICE_TYPE=host_nonshm. */
9950 gimplify_assign (acc_device_host,
9951 build_int_cst (integer_type_node,
9952 GOMP_DEVICE_HOST_NONSHM),
9953 in_stmt_seqp);
9954
9955 enter = create_artificial_label (UNKNOWN_LOCATION);
9956 exit = create_artificial_label (UNKNOWN_LOCATION);
9957
9958 stmt = gimple_build_cond (EQ_EXPR, acc_device, acc_device_host,
9959 enter, exit);
9960 gimple_seq_add_stmt (in_stmt_seqp, stmt);
9961 gimple_seq_add_stmt (in_stmt_seqp, gimple_build_label (enter));
9962 gimplify_assign (nthreads, fold_build1 (NOP_EXPR, sizetype,
9963 integer_one_node),
9964 in_stmt_seqp);
9965 gimple_seq_add_stmt (in_stmt_seqp, gimple_build_label (exit));
9966
9967 oacc_initialize_reduction_data (clauses, nthreads, in_stmt_seqp,
9968 ctx);
9969 oacc_finalize_reduction_data (clauses, nthreads, out_stmt_seqp, ctx);
9970 break;
9971 default:
9972 // Scan for other directives which support reduction here.
9973 break;
9974 }
9975 }
9976}
773c5ba7 9977
bc7bff74 9978/* If ctx is a worksharing context inside of a cancellable parallel
9979 region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
9980 and conditional branch to parallel's cancel_label to handle
9981 cancellation in the implicit barrier. */
9982
9983static void
9984maybe_add_implicit_barrier_cancel (omp_context *ctx, gimple_seq *body)
9985{
9986 gimple omp_return = gimple_seq_last_stmt (*body);
9987 gcc_assert (gimple_code (omp_return) == GIMPLE_OMP_RETURN);
9988 if (gimple_omp_return_nowait_p (omp_return))
9989 return;
9990 if (ctx->outer
9991 && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_PARALLEL
9992 && ctx->outer->cancellable)
9993 {
15b28553 9994 tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL);
9995 tree c_bool_type = TREE_TYPE (TREE_TYPE (fndecl));
f9e245b2 9996 tree lhs = create_tmp_var (c_bool_type);
bc7bff74 9997 gimple_omp_return_set_lhs (omp_return, lhs);
9998 tree fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
15b28553 9999 gimple g = gimple_build_cond (NE_EXPR, lhs,
10000 fold_convert (c_bool_type,
10001 boolean_false_node),
bc7bff74 10002 ctx->outer->cancel_label, fallthru_label);
10003 gimple_seq_add_stmt (body, g);
10004 gimple_seq_add_stmt (body, gimple_build_label (fallthru_label));
10005 }
10006}
10007
75a70cf9 10008/* Lower the OpenMP sections directive in the current statement in GSI_P.
10009 CTX is the enclosing OMP context for the current statement. */
773c5ba7 10010
10011static void
75a70cf9 10012lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
773c5ba7 10013{
75a70cf9 10014 tree block, control;
10015 gimple_stmt_iterator tgsi;
1a91d914 10016 gomp_sections *stmt;
10017 gimple t;
10018 gbind *new_stmt, *bind;
e3a19533 10019 gimple_seq ilist, dlist, olist, new_body;
773c5ba7 10020
1a91d914 10021 stmt = as_a <gomp_sections *> (gsi_stmt (*gsi_p));
773c5ba7 10022
8a4a28a8 10023 push_gimplify_context ();
773c5ba7 10024
10025 dlist = NULL;
10026 ilist = NULL;
75a70cf9 10027 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
bc7bff74 10028 &ilist, &dlist, ctx, NULL);
773c5ba7 10029
e3a19533 10030 new_body = gimple_omp_body (stmt);
10031 gimple_omp_set_body (stmt, NULL);
10032 tgsi = gsi_start (new_body);
10033 for (; !gsi_end_p (tgsi); gsi_next (&tgsi))
773c5ba7 10034 {
10035 omp_context *sctx;
75a70cf9 10036 gimple sec_start;
773c5ba7 10037
75a70cf9 10038 sec_start = gsi_stmt (tgsi);
773c5ba7 10039 sctx = maybe_lookup_ctx (sec_start);
10040 gcc_assert (sctx);
10041
e3a19533 10042 lower_omp (gimple_omp_body_ptr (sec_start), sctx);
10043 gsi_insert_seq_after (&tgsi, gimple_omp_body (sec_start),
10044 GSI_CONTINUE_LINKING);
75a70cf9 10045 gimple_omp_set_body (sec_start, NULL);
773c5ba7 10046
e3a19533 10047 if (gsi_one_before_end_p (tgsi))
773c5ba7 10048 {
75a70cf9 10049 gimple_seq l = NULL;
10050 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
773c5ba7 10051 &l, ctx);
e3a19533 10052 gsi_insert_seq_after (&tgsi, l, GSI_CONTINUE_LINKING);
75a70cf9 10053 gimple_omp_section_set_last (sec_start);
773c5ba7 10054 }
48e1416a 10055
e3a19533 10056 gsi_insert_after (&tgsi, gimple_build_omp_return (false),
10057 GSI_CONTINUE_LINKING);
773c5ba7 10058 }
1e8e9920 10059
10060 block = make_node (BLOCK);
e3a19533 10061 bind = gimple_build_bind (NULL, new_body, block);
1e8e9920 10062
75a70cf9 10063 olist = NULL;
10064 lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist, ctx);
773c5ba7 10065
1d22f541 10066 block = make_node (BLOCK);
75a70cf9 10067 new_stmt = gimple_build_bind (NULL, NULL, block);
e3a19533 10068 gsi_replace (gsi_p, new_stmt, true);
773c5ba7 10069
1d22f541 10070 pop_gimplify_context (new_stmt);
75a70cf9 10071 gimple_bind_append_vars (new_stmt, ctx->block_vars);
10072 BLOCK_VARS (block) = gimple_bind_vars (bind);
1d22f541 10073 if (BLOCK_VARS (block))
10074 TREE_USED (block) = 1;
10075
75a70cf9 10076 new_body = NULL;
10077 gimple_seq_add_seq (&new_body, ilist);
10078 gimple_seq_add_stmt (&new_body, stmt);
10079 gimple_seq_add_stmt (&new_body, gimple_build_omp_sections_switch ());
10080 gimple_seq_add_stmt (&new_body, bind);
61e47ac8 10081
ac6e3339 10082 control = create_tmp_var (unsigned_type_node, ".section");
75a70cf9 10083 t = gimple_build_omp_continue (control, control);
10084 gimple_omp_sections_set_control (stmt, control);
10085 gimple_seq_add_stmt (&new_body, t);
61e47ac8 10086
75a70cf9 10087 gimple_seq_add_seq (&new_body, olist);
bc7bff74 10088 if (ctx->cancellable)
10089 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
75a70cf9 10090 gimple_seq_add_seq (&new_body, dlist);
773c5ba7 10091
75a70cf9 10092 new_body = maybe_catch_exception (new_body);
aade31a0 10093
75a70cf9 10094 t = gimple_build_omp_return
10095 (!!find_omp_clause (gimple_omp_sections_clauses (stmt),
10096 OMP_CLAUSE_NOWAIT));
10097 gimple_seq_add_stmt (&new_body, t);
bc7bff74 10098 maybe_add_implicit_barrier_cancel (ctx, &new_body);
61e47ac8 10099
75a70cf9 10100 gimple_bind_set_body (new_stmt, new_body);
1e8e9920 10101}
10102
10103
773c5ba7 10104/* A subroutine of lower_omp_single. Expand the simple form of
75a70cf9 10105 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
1e8e9920 10106
10107 if (GOMP_single_start ())
10108 BODY;
10109 [ GOMP_barrier (); ] -> unless 'nowait' is present.
773c5ba7 10110
10111 FIXME. It may be better to delay expanding the logic of this until
10112 pass_expand_omp. The expanded logic may make the job more difficult
10113 to a synchronization analysis pass. */
1e8e9920 10114
10115static void
1a91d914 10116lower_omp_single_simple (gomp_single *single_stmt, gimple_seq *pre_p)
1e8e9920 10117{
e60a6f7b 10118 location_t loc = gimple_location (single_stmt);
10119 tree tlabel = create_artificial_label (loc);
10120 tree flabel = create_artificial_label (loc);
75a70cf9 10121 gimple call, cond;
10122 tree lhs, decl;
10123
b9a16870 10124 decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START);
f9e245b2 10125 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)));
75a70cf9 10126 call = gimple_build_call (decl, 0);
10127 gimple_call_set_lhs (call, lhs);
10128 gimple_seq_add_stmt (pre_p, call);
10129
10130 cond = gimple_build_cond (EQ_EXPR, lhs,
389dd41b 10131 fold_convert_loc (loc, TREE_TYPE (lhs),
10132 boolean_true_node),
75a70cf9 10133 tlabel, flabel);
10134 gimple_seq_add_stmt (pre_p, cond);
10135 gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
10136 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
10137 gimple_seq_add_stmt (pre_p, gimple_build_label (flabel));
1e8e9920 10138}
10139
773c5ba7 10140
10141/* A subroutine of lower_omp_single. Expand the simple form of
75a70cf9 10142 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
1e8e9920 10143
10144 #pragma omp single copyprivate (a, b, c)
10145
10146 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
10147
10148 {
10149 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
10150 {
10151 BODY;
10152 copyout.a = a;
10153 copyout.b = b;
10154 copyout.c = c;
10155 GOMP_single_copy_end (&copyout);
10156 }
10157 else
10158 {
10159 a = copyout_p->a;
10160 b = copyout_p->b;
10161 c = copyout_p->c;
10162 }
10163 GOMP_barrier ();
10164 }
773c5ba7 10165
10166 FIXME. It may be better to delay expanding the logic of this until
10167 pass_expand_omp. The expanded logic may make the job more difficult
10168 to a synchronization analysis pass. */
1e8e9920 10169
10170static void
1a91d914 10171lower_omp_single_copy (gomp_single *single_stmt, gimple_seq *pre_p,
10172 omp_context *ctx)
1e8e9920 10173{
b9a16870 10174 tree ptr_type, t, l0, l1, l2, bfn_decl;
75a70cf9 10175 gimple_seq copyin_seq;
e60a6f7b 10176 location_t loc = gimple_location (single_stmt);
1e8e9920 10177
10178 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
10179
10180 ptr_type = build_pointer_type (ctx->record_type);
10181 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
10182
e60a6f7b 10183 l0 = create_artificial_label (loc);
10184 l1 = create_artificial_label (loc);
10185 l2 = create_artificial_label (loc);
1e8e9920 10186
b9a16870 10187 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START);
10188 t = build_call_expr_loc (loc, bfn_decl, 0);
389dd41b 10189 t = fold_convert_loc (loc, ptr_type, t);
75a70cf9 10190 gimplify_assign (ctx->receiver_decl, t, pre_p);
1e8e9920 10191
10192 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
10193 build_int_cst (ptr_type, 0));
10194 t = build3 (COND_EXPR, void_type_node, t,
10195 build_and_jump (&l0), build_and_jump (&l1));
10196 gimplify_and_add (t, pre_p);
10197
75a70cf9 10198 gimple_seq_add_stmt (pre_p, gimple_build_label (l0));
1e8e9920 10199
75a70cf9 10200 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
1e8e9920 10201
10202 copyin_seq = NULL;
75a70cf9 10203 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
1e8e9920 10204 &copyin_seq, ctx);
10205
389dd41b 10206 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
b9a16870 10207 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END);
10208 t = build_call_expr_loc (loc, bfn_decl, 1, t);
1e8e9920 10209 gimplify_and_add (t, pre_p);
10210
10211 t = build_and_jump (&l2);
10212 gimplify_and_add (t, pre_p);
10213
75a70cf9 10214 gimple_seq_add_stmt (pre_p, gimple_build_label (l1));
1e8e9920 10215
75a70cf9 10216 gimple_seq_add_seq (pre_p, copyin_seq);
1e8e9920 10217
75a70cf9 10218 gimple_seq_add_stmt (pre_p, gimple_build_label (l2));
1e8e9920 10219}
10220
773c5ba7 10221
1e8e9920 10222/* Expand code for an OpenMP single directive. */
10223
10224static void
75a70cf9 10225lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
1e8e9920 10226{
75a70cf9 10227 tree block;
1a91d914 10228 gimple t;
10229 gomp_single *single_stmt = as_a <gomp_single *> (gsi_stmt (*gsi_p));
10230 gbind *bind;
bc7bff74 10231 gimple_seq bind_body, bind_body_tail = NULL, dlist;
1e8e9920 10232
8a4a28a8 10233 push_gimplify_context ();
1e8e9920 10234
e3a19533 10235 block = make_node (BLOCK);
10236 bind = gimple_build_bind (NULL, NULL, block);
10237 gsi_replace (gsi_p, bind, true);
75a70cf9 10238 bind_body = NULL;
e3a19533 10239 dlist = NULL;
75a70cf9 10240 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt),
bc7bff74 10241 &bind_body, &dlist, ctx, NULL);
e3a19533 10242 lower_omp (gimple_omp_body_ptr (single_stmt), ctx);
1e8e9920 10243
75a70cf9 10244 gimple_seq_add_stmt (&bind_body, single_stmt);
1e8e9920 10245
10246 if (ctx->record_type)
75a70cf9 10247 lower_omp_single_copy (single_stmt, &bind_body, ctx);
1e8e9920 10248 else
75a70cf9 10249 lower_omp_single_simple (single_stmt, &bind_body);
10250
10251 gimple_omp_set_body (single_stmt, NULL);
1e8e9920 10252
75a70cf9 10253 gimple_seq_add_seq (&bind_body, dlist);
61e47ac8 10254
75a70cf9 10255 bind_body = maybe_catch_exception (bind_body);
61e47ac8 10256
48e1416a 10257 t = gimple_build_omp_return
75a70cf9 10258 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt),
10259 OMP_CLAUSE_NOWAIT));
bc7bff74 10260 gimple_seq_add_stmt (&bind_body_tail, t);
10261 maybe_add_implicit_barrier_cancel (ctx, &bind_body_tail);
10262 if (ctx->record_type)
10263 {
10264 gimple_stmt_iterator gsi = gsi_start (bind_body_tail);
10265 tree clobber = build_constructor (ctx->record_type, NULL);
10266 TREE_THIS_VOLATILE (clobber) = 1;
10267 gsi_insert_after (&gsi, gimple_build_assign (ctx->sender_decl,
10268 clobber), GSI_SAME_STMT);
10269 }
10270 gimple_seq_add_seq (&bind_body, bind_body_tail);
e3a19533 10271 gimple_bind_set_body (bind, bind_body);
61e47ac8 10272
1e8e9920 10273 pop_gimplify_context (bind);
773c5ba7 10274
75a70cf9 10275 gimple_bind_append_vars (bind, ctx->block_vars);
10276 BLOCK_VARS (block) = ctx->block_vars;
1d22f541 10277 if (BLOCK_VARS (block))
10278 TREE_USED (block) = 1;
1e8e9920 10279}
10280
773c5ba7 10281
1e8e9920 10282/* Expand code for an OpenMP master directive. */
10283
10284static void
75a70cf9 10285lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
1e8e9920 10286{
b9a16870 10287 tree block, lab = NULL, x, bfn_decl;
1a91d914 10288 gimple stmt = gsi_stmt (*gsi_p);
10289 gbind *bind;
389dd41b 10290 location_t loc = gimple_location (stmt);
75a70cf9 10291 gimple_seq tseq;
1e8e9920 10292
8a4a28a8 10293 push_gimplify_context ();
1e8e9920 10294
10295 block = make_node (BLOCK);
e3a19533 10296 bind = gimple_build_bind (NULL, NULL, block);
10297 gsi_replace (gsi_p, bind, true);
10298 gimple_bind_add_stmt (bind, stmt);
61e47ac8 10299
b9a16870 10300 bfn_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
10301 x = build_call_expr_loc (loc, bfn_decl, 0);
1e8e9920 10302 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
10303 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
75a70cf9 10304 tseq = NULL;
10305 gimplify_and_add (x, &tseq);
10306 gimple_bind_add_seq (bind, tseq);
1e8e9920 10307
e3a19533 10308 lower_omp (gimple_omp_body_ptr (stmt), ctx);
75a70cf9 10309 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
10310 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10311 gimple_omp_set_body (stmt, NULL);
1e8e9920 10312
75a70cf9 10313 gimple_bind_add_stmt (bind, gimple_build_label (lab));
61e47ac8 10314
75a70cf9 10315 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
61e47ac8 10316
1e8e9920 10317 pop_gimplify_context (bind);
773c5ba7 10318
75a70cf9 10319 gimple_bind_append_vars (bind, ctx->block_vars);
10320 BLOCK_VARS (block) = ctx->block_vars;
1e8e9920 10321}
10322
773c5ba7 10323
bc7bff74 10324/* Expand code for an OpenMP taskgroup directive. */
10325
10326static void
10327lower_omp_taskgroup (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10328{
1a91d914 10329 gimple stmt = gsi_stmt (*gsi_p);
10330 gcall *x;
10331 gbind *bind;
bc7bff74 10332 tree block = make_node (BLOCK);
10333
10334 bind = gimple_build_bind (NULL, NULL, block);
10335 gsi_replace (gsi_p, bind, true);
10336 gimple_bind_add_stmt (bind, stmt);
10337
10338 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START),
10339 0);
10340 gimple_bind_add_stmt (bind, x);
10341
10342 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10343 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10344 gimple_omp_set_body (stmt, NULL);
10345
10346 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
10347
10348 gimple_bind_append_vars (bind, ctx->block_vars);
10349 BLOCK_VARS (block) = ctx->block_vars;
10350}
10351
10352
1e8e9920 10353/* Expand code for an OpenMP ordered directive. */
10354
10355static void
75a70cf9 10356lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
1e8e9920 10357{
75a70cf9 10358 tree block;
1a91d914 10359 gimple stmt = gsi_stmt (*gsi_p);
10360 gcall *x;
10361 gbind *bind;
1e8e9920 10362
8a4a28a8 10363 push_gimplify_context ();
1e8e9920 10364
10365 block = make_node (BLOCK);
e3a19533 10366 bind = gimple_build_bind (NULL, NULL, block);
10367 gsi_replace (gsi_p, bind, true);
10368 gimple_bind_add_stmt (bind, stmt);
61e47ac8 10369
b9a16870 10370 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START),
10371 0);
75a70cf9 10372 gimple_bind_add_stmt (bind, x);
1e8e9920 10373
e3a19533 10374 lower_omp (gimple_omp_body_ptr (stmt), ctx);
75a70cf9 10375 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
10376 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10377 gimple_omp_set_body (stmt, NULL);
1e8e9920 10378
b9a16870 10379 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END), 0);
75a70cf9 10380 gimple_bind_add_stmt (bind, x);
61e47ac8 10381
75a70cf9 10382 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
61e47ac8 10383
1e8e9920 10384 pop_gimplify_context (bind);
773c5ba7 10385
75a70cf9 10386 gimple_bind_append_vars (bind, ctx->block_vars);
10387 BLOCK_VARS (block) = gimple_bind_vars (bind);
1e8e9920 10388}
10389
1e8e9920 10390
75a70cf9 10391/* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
1e8e9920 10392 substitution of a couple of function calls. But in the NAMED case,
10393 requires that languages coordinate a symbol name. It is therefore
10394 best put here in common code. */
10395
d4786b13 10396static GTY(()) hash_map<tree, tree> *critical_name_mutexes;
1e8e9920 10397
10398static void
75a70cf9 10399lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
1e8e9920 10400{
75a70cf9 10401 tree block;
10402 tree name, lock, unlock;
1a91d914 10403 gomp_critical *stmt = as_a <gomp_critical *> (gsi_stmt (*gsi_p));
10404 gbind *bind;
389dd41b 10405 location_t loc = gimple_location (stmt);
75a70cf9 10406 gimple_seq tbody;
1e8e9920 10407
75a70cf9 10408 name = gimple_omp_critical_name (stmt);
1e8e9920 10409 if (name)
10410 {
c2f47e15 10411 tree decl;
1e8e9920 10412
10413 if (!critical_name_mutexes)
d4786b13 10414 critical_name_mutexes = hash_map<tree, tree>::create_ggc (10);
1e8e9920 10415
d4786b13 10416 tree *n = critical_name_mutexes->get (name);
1e8e9920 10417 if (n == NULL)
10418 {
10419 char *new_str;
10420
f9e245b2 10421 decl = create_tmp_var_raw (ptr_type_node);
1e8e9920 10422
10423 new_str = ACONCAT ((".gomp_critical_user_",
10424 IDENTIFIER_POINTER (name), NULL));
10425 DECL_NAME (decl) = get_identifier (new_str);
10426 TREE_PUBLIC (decl) = 1;
10427 TREE_STATIC (decl) = 1;
10428 DECL_COMMON (decl) = 1;
10429 DECL_ARTIFICIAL (decl) = 1;
10430 DECL_IGNORED_P (decl) = 1;
b0c5e347 10431
97221fd7 10432 varpool_node::finalize_decl (decl);
1e8e9920 10433
d4786b13 10434 critical_name_mutexes->put (name, decl);
1e8e9920 10435 }
10436 else
d4786b13 10437 decl = *n;
1e8e9920 10438
ca4c3545 10439 /* If '#pragma omp critical' is inside offloaded region or
351fb0ce 10440 inside function marked as offloadable, the symbol must be
10441 marked as offloadable too. */
10442 omp_context *octx;
10443 if (cgraph_node::get (current_function_decl)->offloadable)
10444 varpool_node::get_create (decl)->offloadable = 1;
10445 else
10446 for (octx = ctx->outer; octx; octx = octx->outer)
ca4c3545 10447 if (is_gimple_omp_offloaded (octx->stmt))
351fb0ce 10448 {
10449 varpool_node::get_create (decl)->offloadable = 1;
10450 break;
10451 }
10452
b9a16870 10453 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START);
389dd41b 10454 lock = build_call_expr_loc (loc, lock, 1, build_fold_addr_expr_loc (loc, decl));
1e8e9920 10455
b9a16870 10456 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END);
389dd41b 10457 unlock = build_call_expr_loc (loc, unlock, 1,
10458 build_fold_addr_expr_loc (loc, decl));
1e8e9920 10459 }
10460 else
10461 {
b9a16870 10462 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START);
389dd41b 10463 lock = build_call_expr_loc (loc, lock, 0);
1e8e9920 10464
b9a16870 10465 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END);
389dd41b 10466 unlock = build_call_expr_loc (loc, unlock, 0);
1e8e9920 10467 }
10468
8a4a28a8 10469 push_gimplify_context ();
1e8e9920 10470
10471 block = make_node (BLOCK);
e3a19533 10472 bind = gimple_build_bind (NULL, NULL, block);
10473 gsi_replace (gsi_p, bind, true);
10474 gimple_bind_add_stmt (bind, stmt);
61e47ac8 10475
75a70cf9 10476 tbody = gimple_bind_body (bind);
10477 gimplify_and_add (lock, &tbody);
10478 gimple_bind_set_body (bind, tbody);
1e8e9920 10479
e3a19533 10480 lower_omp (gimple_omp_body_ptr (stmt), ctx);
75a70cf9 10481 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
10482 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10483 gimple_omp_set_body (stmt, NULL);
1e8e9920 10484
75a70cf9 10485 tbody = gimple_bind_body (bind);
10486 gimplify_and_add (unlock, &tbody);
10487 gimple_bind_set_body (bind, tbody);
61e47ac8 10488
75a70cf9 10489 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
1e8e9920 10490
10491 pop_gimplify_context (bind);
75a70cf9 10492 gimple_bind_append_vars (bind, ctx->block_vars);
10493 BLOCK_VARS (block) = gimple_bind_vars (bind);
773c5ba7 10494}
10495
10496
10497/* A subroutine of lower_omp_for. Generate code to emit the predicate
10498 for a lastprivate clause. Given a loop control predicate of (V
10499 cond N2), we gate the clause on (!(V cond N2)). The lowered form
1e4afe3c 10500 is appended to *DLIST, iterator initialization is appended to
10501 *BODY_P. */
773c5ba7 10502
10503static void
75a70cf9 10504lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
10505 gimple_seq *dlist, struct omp_context *ctx)
773c5ba7 10506{
75a70cf9 10507 tree clauses, cond, vinit;
773c5ba7 10508 enum tree_code cond_code;
75a70cf9 10509 gimple_seq stmts;
48e1416a 10510
fd6481cf 10511 cond_code = fd->loop.cond_code;
773c5ba7 10512 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
10513
10514 /* When possible, use a strict equality expression. This can let VRP
10515 type optimizations deduce the value and remove a copy. */
e913b5cd 10516 if (tree_fits_shwi_p (fd->loop.step))
773c5ba7 10517 {
e913b5cd 10518 HOST_WIDE_INT step = tree_to_shwi (fd->loop.step);
773c5ba7 10519 if (step == 1 || step == -1)
10520 cond_code = EQ_EXPR;
10521 }
10522
d7729e26 10523 tree n2 = fd->loop.n2;
10524 if (fd->collapse > 1
10525 && TREE_CODE (n2) != INTEGER_CST
10526 && gimple_omp_for_combined_into_p (fd->for_stmt)
10527 && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_FOR)
10528 {
10529 gomp_for *gfor = as_a <gomp_for *> (ctx->outer->stmt);
10530 if (gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_FOR)
10531 {
10532 struct omp_for_data outer_fd;
10533 extract_omp_for_data (gfor, &outer_fd, NULL);
10534 n2 = fold_convert (TREE_TYPE (n2), outer_fd.loop.n2);
10535 }
10536 }
10537 cond = build2 (cond_code, boolean_type_node, fd->loop.v, n2);
773c5ba7 10538
75a70cf9 10539 clauses = gimple_omp_for_clauses (fd->for_stmt);
1e4afe3c 10540 stmts = NULL;
10541 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
75a70cf9 10542 if (!gimple_seq_empty_p (stmts))
1e4afe3c 10543 {
75a70cf9 10544 gimple_seq_add_seq (&stmts, *dlist);
fd6481cf 10545 *dlist = stmts;
1e4afe3c 10546
10547 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
fd6481cf 10548 vinit = fd->loop.n1;
1e4afe3c 10549 if (cond_code == EQ_EXPR
e913b5cd 10550 && tree_fits_shwi_p (fd->loop.n2)
fd6481cf 10551 && ! integer_zerop (fd->loop.n2))
10552 vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0);
3d483a94 10553 else
10554 vinit = unshare_expr (vinit);
1e4afe3c 10555
10556 /* Initialize the iterator variable, so that threads that don't execute
10557 any iterations don't execute the lastprivate clauses by accident. */
75a70cf9 10558 gimplify_assign (fd->loop.v, vinit, body_p);
1e4afe3c 10559 }
773c5ba7 10560}
10561
10562
ca4c3545 10563/* Lower code for an OMP loop directive. */
773c5ba7 10564
10565static void
75a70cf9 10566lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
773c5ba7 10567{
75a70cf9 10568 tree *rhs_p, block;
bc7bff74 10569 struct omp_for_data fd, *fdp = NULL;
1a91d914 10570 gomp_for *stmt = as_a <gomp_for *> (gsi_stmt (*gsi_p));
10571 gbind *new_stmt;
f018d957 10572 gimple_seq omp_for_body, body, dlist;
75a70cf9 10573 size_t i;
773c5ba7 10574
8a4a28a8 10575 push_gimplify_context ();
773c5ba7 10576
e3a19533 10577 lower_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
773c5ba7 10578
1d22f541 10579 block = make_node (BLOCK);
75a70cf9 10580 new_stmt = gimple_build_bind (NULL, NULL, block);
e3a19533 10581 /* Replace at gsi right away, so that 'stmt' is no member
10582 of a sequence anymore as we're going to add to to a different
10583 one below. */
10584 gsi_replace (gsi_p, new_stmt, true);
1d22f541 10585
773c5ba7 10586 /* Move declaration of temporaries in the loop body before we make
10587 it go away. */
75a70cf9 10588 omp_for_body = gimple_omp_body (stmt);
10589 if (!gimple_seq_empty_p (omp_for_body)
10590 && gimple_code (gimple_seq_first_stmt (omp_for_body)) == GIMPLE_BIND)
10591 {
1a91d914 10592 gbind *inner_bind
10593 = as_a <gbind *> (gimple_seq_first_stmt (omp_for_body));
6d5a8d89 10594 tree vars = gimple_bind_vars (inner_bind);
75a70cf9 10595 gimple_bind_append_vars (new_stmt, vars);
6d5a8d89 10596 /* bind_vars/BLOCK_VARS are being moved to new_stmt/block, don't
10597 keep them on the inner_bind and it's block. */
10598 gimple_bind_set_vars (inner_bind, NULL_TREE);
10599 if (gimple_bind_block (inner_bind))
10600 BLOCK_VARS (gimple_bind_block (inner_bind)) = NULL_TREE;
75a70cf9 10601 }
773c5ba7 10602
bc7bff74 10603 if (gimple_omp_for_combined_into_p (stmt))
10604 {
10605 extract_omp_for_data (stmt, &fd, NULL);
10606 fdp = &fd;
10607
10608 /* We need two temporaries with fd.loop.v type (istart/iend)
10609 and then (fd.collapse - 1) temporaries with the same
10610 type for count2 ... countN-1 vars if not constant. */
10611 size_t count = 2;
10612 tree type = fd.iter_type;
10613 if (fd.collapse > 1
10614 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
10615 count += fd.collapse - 1;
10616 bool parallel_for = gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR;
10617 tree outerc = NULL, *pc = gimple_omp_for_clauses_ptr (stmt);
10618 tree clauses = *pc;
10619 if (parallel_for)
10620 outerc
10621 = find_omp_clause (gimple_omp_parallel_clauses (ctx->outer->stmt),
10622 OMP_CLAUSE__LOOPTEMP_);
10623 for (i = 0; i < count; i++)
10624 {
10625 tree temp;
10626 if (parallel_for)
10627 {
10628 gcc_assert (outerc);
10629 temp = lookup_decl (OMP_CLAUSE_DECL (outerc), ctx->outer);
10630 outerc = find_omp_clause (OMP_CLAUSE_CHAIN (outerc),
10631 OMP_CLAUSE__LOOPTEMP_);
10632 }
10633 else
691447ab 10634 {
f9e245b2 10635 temp = create_tmp_var (type);
691447ab 10636 insert_decl_map (&ctx->outer->cb, temp, temp);
10637 }
bc7bff74 10638 *pc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
10639 OMP_CLAUSE_DECL (*pc) = temp;
10640 pc = &OMP_CLAUSE_CHAIN (*pc);
10641 }
10642 *pc = clauses;
10643 }
10644
75a70cf9 10645 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
773c5ba7 10646 dlist = NULL;
75a70cf9 10647 body = NULL;
bc7bff74 10648 lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx,
10649 fdp);
75a70cf9 10650 gimple_seq_add_seq (&body, gimple_omp_for_pre_body (stmt));
773c5ba7 10651
3d483a94 10652 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10653
773c5ba7 10654 /* Lower the header expressions. At this point, we can assume that
10655 the header is of the form:
10656
10657 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
10658
10659 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
10660 using the .omp_data_s mapping, if needed. */
75a70cf9 10661 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
fd6481cf 10662 {
75a70cf9 10663 rhs_p = gimple_omp_for_initial_ptr (stmt, i);
fd6481cf 10664 if (!is_gimple_min_invariant (*rhs_p))
75a70cf9 10665 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
fd6481cf 10666
75a70cf9 10667 rhs_p = gimple_omp_for_final_ptr (stmt, i);
fd6481cf 10668 if (!is_gimple_min_invariant (*rhs_p))
75a70cf9 10669 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
fd6481cf 10670
75a70cf9 10671 rhs_p = &TREE_OPERAND (gimple_omp_for_incr (stmt, i), 1);
fd6481cf 10672 if (!is_gimple_min_invariant (*rhs_p))
75a70cf9 10673 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
fd6481cf 10674 }
773c5ba7 10675
10676 /* Once lowered, extract the bounds and clauses. */
fd6481cf 10677 extract_omp_for_data (stmt, &fd, NULL);
773c5ba7 10678
75a70cf9 10679 lower_omp_for_lastprivate (&fd, &body, &dlist, ctx);
773c5ba7 10680
75a70cf9 10681 gimple_seq_add_stmt (&body, stmt);
10682 gimple_seq_add_seq (&body, gimple_omp_body (stmt));
61e47ac8 10683
75a70cf9 10684 gimple_seq_add_stmt (&body, gimple_build_omp_continue (fd.loop.v,
10685 fd.loop.v));
61e47ac8 10686
773c5ba7 10687 /* After the loop, add exit clauses. */
75a70cf9 10688 lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, ctx);
bc7bff74 10689
10690 if (ctx->cancellable)
10691 gimple_seq_add_stmt (&body, gimple_build_label (ctx->cancel_label));
10692
75a70cf9 10693 gimple_seq_add_seq (&body, dlist);
773c5ba7 10694
75a70cf9 10695 body = maybe_catch_exception (body);
aade31a0 10696
61e47ac8 10697 /* Region exit marker goes at the end of the loop body. */
75a70cf9 10698 gimple_seq_add_stmt (&body, gimple_build_omp_return (fd.have_nowait));
bc7bff74 10699 maybe_add_implicit_barrier_cancel (ctx, &body);
1d22f541 10700 pop_gimplify_context (new_stmt);
75a70cf9 10701
10702 gimple_bind_append_vars (new_stmt, ctx->block_vars);
10703 BLOCK_VARS (block) = gimple_bind_vars (new_stmt);
1d22f541 10704 if (BLOCK_VARS (block))
10705 TREE_USED (block) = 1;
773c5ba7 10706
75a70cf9 10707 gimple_bind_set_body (new_stmt, body);
10708 gimple_omp_set_body (stmt, NULL);
10709 gimple_omp_for_set_pre_body (stmt, NULL);
1e8e9920 10710}
10711
48e1416a 10712/* Callback for walk_stmts. Check if the current statement only contains
a7dfc4fe 10713 GIMPLE_OMP_FOR or GIMPLE_OMP_SECTIONS. */
de7ef844 10714
10715static tree
75a70cf9 10716check_combined_parallel (gimple_stmt_iterator *gsi_p,
10717 bool *handled_ops_p,
10718 struct walk_stmt_info *wi)
de7ef844 10719{
4077bf7a 10720 int *info = (int *) wi->info;
75a70cf9 10721 gimple stmt = gsi_stmt (*gsi_p);
de7ef844 10722
75a70cf9 10723 *handled_ops_p = true;
10724 switch (gimple_code (stmt))
de7ef844 10725 {
75a70cf9 10726 WALK_SUBSTMTS;
10727
10728 case GIMPLE_OMP_FOR:
10729 case GIMPLE_OMP_SECTIONS:
de7ef844 10730 *info = *info == 0 ? 1 : -1;
10731 break;
10732 default:
10733 *info = -1;
10734 break;
10735 }
10736 return NULL;
10737}
773c5ba7 10738
fd6481cf 10739struct omp_taskcopy_context
10740{
10741 /* This field must be at the beginning, as we do "inheritance": Some
10742 callback functions for tree-inline.c (e.g., omp_copy_decl)
10743 receive a copy_body_data pointer that is up-casted to an
10744 omp_context pointer. */
10745 copy_body_data cb;
10746 omp_context *ctx;
10747};
10748
10749static tree
10750task_copyfn_copy_decl (tree var, copy_body_data *cb)
10751{
10752 struct omp_taskcopy_context *tcctx = (struct omp_taskcopy_context *) cb;
10753
10754 if (splay_tree_lookup (tcctx->ctx->sfield_map, (splay_tree_key) var))
f9e245b2 10755 return create_tmp_var (TREE_TYPE (var));
fd6481cf 10756
10757 return var;
10758}
10759
10760static tree
10761task_copyfn_remap_type (struct omp_taskcopy_context *tcctx, tree orig_type)
10762{
10763 tree name, new_fields = NULL, type, f;
10764
10765 type = lang_hooks.types.make_type (RECORD_TYPE);
10766 name = DECL_NAME (TYPE_NAME (orig_type));
e60a6f7b 10767 name = build_decl (gimple_location (tcctx->ctx->stmt),
10768 TYPE_DECL, name, type);
fd6481cf 10769 TYPE_NAME (type) = name;
10770
10771 for (f = TYPE_FIELDS (orig_type); f ; f = TREE_CHAIN (f))
10772 {
10773 tree new_f = copy_node (f);
10774 DECL_CONTEXT (new_f) = type;
10775 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &tcctx->cb);
10776 TREE_CHAIN (new_f) = new_fields;
75a70cf9 10777 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &tcctx->cb, NULL);
10778 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r, &tcctx->cb, NULL);
10779 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
10780 &tcctx->cb, NULL);
fd6481cf 10781 new_fields = new_f;
06ecf488 10782 tcctx->cb.decl_map->put (f, new_f);
fd6481cf 10783 }
10784 TYPE_FIELDS (type) = nreverse (new_fields);
10785 layout_type (type);
10786 return type;
10787}
10788
10789/* Create task copyfn. */
10790
10791static void
1a91d914 10792create_task_copyfn (gomp_task *task_stmt, omp_context *ctx)
fd6481cf 10793{
10794 struct function *child_cfun;
10795 tree child_fn, t, c, src, dst, f, sf, arg, sarg, decl;
10796 tree record_type, srecord_type, bind, list;
10797 bool record_needs_remap = false, srecord_needs_remap = false;
10798 splay_tree_node n;
10799 struct omp_taskcopy_context tcctx;
389dd41b 10800 location_t loc = gimple_location (task_stmt);
fd6481cf 10801
75a70cf9 10802 child_fn = gimple_omp_task_copy_fn (task_stmt);
fd6481cf 10803 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
10804 gcc_assert (child_cfun->cfg == NULL);
fd6481cf 10805 DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
10806
10807 /* Reset DECL_CONTEXT on function arguments. */
1767a056 10808 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
fd6481cf 10809 DECL_CONTEXT (t) = child_fn;
10810
10811 /* Populate the function. */
8a4a28a8 10812 push_gimplify_context ();
9078126c 10813 push_cfun (child_cfun);
fd6481cf 10814
10815 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
10816 TREE_SIDE_EFFECTS (bind) = 1;
10817 list = NULL;
10818 DECL_SAVED_TREE (child_fn) = bind;
75a70cf9 10819 DECL_SOURCE_LOCATION (child_fn) = gimple_location (task_stmt);
fd6481cf 10820
10821 /* Remap src and dst argument types if needed. */
10822 record_type = ctx->record_type;
10823 srecord_type = ctx->srecord_type;
1767a056 10824 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
fd6481cf 10825 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
10826 {
10827 record_needs_remap = true;
10828 break;
10829 }
1767a056 10830 for (f = TYPE_FIELDS (srecord_type); f ; f = DECL_CHAIN (f))
fd6481cf 10831 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
10832 {
10833 srecord_needs_remap = true;
10834 break;
10835 }
10836
10837 if (record_needs_remap || srecord_needs_remap)
10838 {
10839 memset (&tcctx, '\0', sizeof (tcctx));
10840 tcctx.cb.src_fn = ctx->cb.src_fn;
10841 tcctx.cb.dst_fn = child_fn;
415d1b9a 10842 tcctx.cb.src_node = cgraph_node::get (tcctx.cb.src_fn);
53f79206 10843 gcc_checking_assert (tcctx.cb.src_node);
fd6481cf 10844 tcctx.cb.dst_node = tcctx.cb.src_node;
10845 tcctx.cb.src_cfun = ctx->cb.src_cfun;
10846 tcctx.cb.copy_decl = task_copyfn_copy_decl;
e38def9c 10847 tcctx.cb.eh_lp_nr = 0;
fd6481cf 10848 tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
06ecf488 10849 tcctx.cb.decl_map = new hash_map<tree, tree>;
fd6481cf 10850 tcctx.ctx = ctx;
10851
10852 if (record_needs_remap)
10853 record_type = task_copyfn_remap_type (&tcctx, record_type);
10854 if (srecord_needs_remap)
10855 srecord_type = task_copyfn_remap_type (&tcctx, srecord_type);
10856 }
10857 else
10858 tcctx.cb.decl_map = NULL;
10859
fd6481cf 10860 arg = DECL_ARGUMENTS (child_fn);
10861 TREE_TYPE (arg) = build_pointer_type (record_type);
1767a056 10862 sarg = DECL_CHAIN (arg);
fd6481cf 10863 TREE_TYPE (sarg) = build_pointer_type (srecord_type);
10864
10865 /* First pass: initialize temporaries used in record_type and srecord_type
10866 sizes and field offsets. */
10867 if (tcctx.cb.decl_map)
75a70cf9 10868 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
fd6481cf 10869 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
10870 {
10871 tree *p;
10872
10873 decl = OMP_CLAUSE_DECL (c);
06ecf488 10874 p = tcctx.cb.decl_map->get (decl);
fd6481cf 10875 if (p == NULL)
10876 continue;
10877 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
10878 sf = (tree) n->value;
06ecf488 10879 sf = *tcctx.cb.decl_map->get (sf);
182cf5a9 10880 src = build_simple_mem_ref_loc (loc, sarg);
445d06b6 10881 src = omp_build_component_ref (src, sf);
75a70cf9 10882 t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
fd6481cf 10883 append_to_statement_list (t, &list);
10884 }
10885
10886 /* Second pass: copy shared var pointers and copy construct non-VLA
10887 firstprivate vars. */
75a70cf9 10888 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
fd6481cf 10889 switch (OMP_CLAUSE_CODE (c))
10890 {
10891 case OMP_CLAUSE_SHARED:
10892 decl = OMP_CLAUSE_DECL (c);
10893 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
10894 if (n == NULL)
10895 break;
10896 f = (tree) n->value;
10897 if (tcctx.cb.decl_map)
06ecf488 10898 f = *tcctx.cb.decl_map->get (f);
fd6481cf 10899 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
10900 sf = (tree) n->value;
10901 if (tcctx.cb.decl_map)
06ecf488 10902 sf = *tcctx.cb.decl_map->get (sf);
182cf5a9 10903 src = build_simple_mem_ref_loc (loc, sarg);
445d06b6 10904 src = omp_build_component_ref (src, sf);
182cf5a9 10905 dst = build_simple_mem_ref_loc (loc, arg);
445d06b6 10906 dst = omp_build_component_ref (dst, f);
75a70cf9 10907 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
fd6481cf 10908 append_to_statement_list (t, &list);
10909 break;
10910 case OMP_CLAUSE_FIRSTPRIVATE:
10911 decl = OMP_CLAUSE_DECL (c);
10912 if (is_variable_sized (decl))
10913 break;
10914 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
10915 if (n == NULL)
10916 break;
10917 f = (tree) n->value;
10918 if (tcctx.cb.decl_map)
06ecf488 10919 f = *tcctx.cb.decl_map->get (f);
fd6481cf 10920 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
10921 if (n != NULL)
10922 {
10923 sf = (tree) n->value;
10924 if (tcctx.cb.decl_map)
06ecf488 10925 sf = *tcctx.cb.decl_map->get (sf);
182cf5a9 10926 src = build_simple_mem_ref_loc (loc, sarg);
445d06b6 10927 src = omp_build_component_ref (src, sf);
fd6481cf 10928 if (use_pointer_for_field (decl, NULL) || is_reference (decl))
182cf5a9 10929 src = build_simple_mem_ref_loc (loc, src);
fd6481cf 10930 }
10931 else
10932 src = decl;
182cf5a9 10933 dst = build_simple_mem_ref_loc (loc, arg);
445d06b6 10934 dst = omp_build_component_ref (dst, f);
fd6481cf 10935 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
10936 append_to_statement_list (t, &list);
10937 break;
10938 case OMP_CLAUSE_PRIVATE:
10939 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c))
10940 break;
10941 decl = OMP_CLAUSE_DECL (c);
10942 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
10943 f = (tree) n->value;
10944 if (tcctx.cb.decl_map)
06ecf488 10945 f = *tcctx.cb.decl_map->get (f);
fd6481cf 10946 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
10947 if (n != NULL)
10948 {
10949 sf = (tree) n->value;
10950 if (tcctx.cb.decl_map)
06ecf488 10951 sf = *tcctx.cb.decl_map->get (sf);
182cf5a9 10952 src = build_simple_mem_ref_loc (loc, sarg);
445d06b6 10953 src = omp_build_component_ref (src, sf);
fd6481cf 10954 if (use_pointer_for_field (decl, NULL))
182cf5a9 10955 src = build_simple_mem_ref_loc (loc, src);
fd6481cf 10956 }
10957 else
10958 src = decl;
182cf5a9 10959 dst = build_simple_mem_ref_loc (loc, arg);
445d06b6 10960 dst = omp_build_component_ref (dst, f);
75a70cf9 10961 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
fd6481cf 10962 append_to_statement_list (t, &list);
10963 break;
10964 default:
10965 break;
10966 }
10967
10968 /* Last pass: handle VLA firstprivates. */
10969 if (tcctx.cb.decl_map)
75a70cf9 10970 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
fd6481cf 10971 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
10972 {
10973 tree ind, ptr, df;
10974
10975 decl = OMP_CLAUSE_DECL (c);
10976 if (!is_variable_sized (decl))
10977 continue;
10978 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
10979 if (n == NULL)
10980 continue;
10981 f = (tree) n->value;
06ecf488 10982 f = *tcctx.cb.decl_map->get (f);
fd6481cf 10983 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
10984 ind = DECL_VALUE_EXPR (decl);
10985 gcc_assert (TREE_CODE (ind) == INDIRECT_REF);
10986 gcc_assert (DECL_P (TREE_OPERAND (ind, 0)));
10987 n = splay_tree_lookup (ctx->sfield_map,
10988 (splay_tree_key) TREE_OPERAND (ind, 0));
10989 sf = (tree) n->value;
06ecf488 10990 sf = *tcctx.cb.decl_map->get (sf);
182cf5a9 10991 src = build_simple_mem_ref_loc (loc, sarg);
445d06b6 10992 src = omp_build_component_ref (src, sf);
182cf5a9 10993 src = build_simple_mem_ref_loc (loc, src);
10994 dst = build_simple_mem_ref_loc (loc, arg);
445d06b6 10995 dst = omp_build_component_ref (dst, f);
fd6481cf 10996 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
10997 append_to_statement_list (t, &list);
10998 n = splay_tree_lookup (ctx->field_map,
10999 (splay_tree_key) TREE_OPERAND (ind, 0));
11000 df = (tree) n->value;
06ecf488 11001 df = *tcctx.cb.decl_map->get (df);
182cf5a9 11002 ptr = build_simple_mem_ref_loc (loc, arg);
445d06b6 11003 ptr = omp_build_component_ref (ptr, df);
75a70cf9 11004 t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
389dd41b 11005 build_fold_addr_expr_loc (loc, dst));
fd6481cf 11006 append_to_statement_list (t, &list);
11007 }
11008
11009 t = build1 (RETURN_EXPR, void_type_node, NULL);
11010 append_to_statement_list (t, &list);
11011
11012 if (tcctx.cb.decl_map)
06ecf488 11013 delete tcctx.cb.decl_map;
fd6481cf 11014 pop_gimplify_context (NULL);
11015 BIND_EXPR_BODY (bind) = list;
11016 pop_cfun ();
fd6481cf 11017}
11018
bc7bff74 11019static void
11020lower_depend_clauses (gimple stmt, gimple_seq *iseq, gimple_seq *oseq)
11021{
11022 tree c, clauses;
11023 gimple g;
11024 size_t n_in = 0, n_out = 0, idx = 2, i;
11025
11026 clauses = find_omp_clause (gimple_omp_task_clauses (stmt),
11027 OMP_CLAUSE_DEPEND);
11028 gcc_assert (clauses);
11029 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
11030 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
11031 switch (OMP_CLAUSE_DEPEND_KIND (c))
11032 {
11033 case OMP_CLAUSE_DEPEND_IN:
11034 n_in++;
11035 break;
11036 case OMP_CLAUSE_DEPEND_OUT:
11037 case OMP_CLAUSE_DEPEND_INOUT:
11038 n_out++;
11039 break;
11040 default:
11041 gcc_unreachable ();
11042 }
11043 tree type = build_array_type_nelts (ptr_type_node, n_in + n_out + 2);
f9e245b2 11044 tree array = create_tmp_var (type);
bc7bff74 11045 tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
11046 NULL_TREE);
11047 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_in + n_out));
11048 gimple_seq_add_stmt (iseq, g);
11049 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
11050 NULL_TREE);
11051 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_out));
11052 gimple_seq_add_stmt (iseq, g);
11053 for (i = 0; i < 2; i++)
11054 {
11055 if ((i ? n_in : n_out) == 0)
11056 continue;
11057 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
11058 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
11059 && ((OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_IN) ^ i))
11060 {
11061 tree t = OMP_CLAUSE_DECL (c);
11062 t = fold_convert (ptr_type_node, t);
11063 gimplify_expr (&t, iseq, NULL, is_gimple_val, fb_rvalue);
11064 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (idx++),
11065 NULL_TREE, NULL_TREE);
11066 g = gimple_build_assign (r, t);
11067 gimple_seq_add_stmt (iseq, g);
11068 }
11069 }
11070 tree *p = gimple_omp_task_clauses_ptr (stmt);
11071 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
11072 OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
11073 OMP_CLAUSE_CHAIN (c) = *p;
11074 *p = c;
11075 tree clobber = build_constructor (type, NULL);
11076 TREE_THIS_VOLATILE (clobber) = 1;
11077 g = gimple_build_assign (array, clobber);
11078 gimple_seq_add_stmt (oseq, g);
11079}
11080
75a70cf9 11081/* Lower the OpenMP parallel or task directive in the current statement
11082 in GSI_P. CTX holds context information for the directive. */
773c5ba7 11083
11084static void
75a70cf9 11085lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
773c5ba7 11086{
75a70cf9 11087 tree clauses;
11088 tree child_fn, t;
11089 gimple stmt = gsi_stmt (*gsi_p);
1a91d914 11090 gbind *par_bind, *bind, *dep_bind = NULL;
bc7bff74 11091 gimple_seq par_body, olist, ilist, par_olist, par_rlist, par_ilist, new_body;
389dd41b 11092 location_t loc = gimple_location (stmt);
773c5ba7 11093
75a70cf9 11094 clauses = gimple_omp_taskreg_clauses (stmt);
1a91d914 11095 par_bind
11096 = as_a <gbind *> (gimple_seq_first_stmt (gimple_omp_body (stmt)));
75a70cf9 11097 par_body = gimple_bind_body (par_bind);
773c5ba7 11098 child_fn = ctx->cb.dst_fn;
75a70cf9 11099 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
11100 && !gimple_omp_parallel_combined_p (stmt))
de7ef844 11101 {
11102 struct walk_stmt_info wi;
11103 int ws_num = 0;
11104
11105 memset (&wi, 0, sizeof (wi));
de7ef844 11106 wi.info = &ws_num;
11107 wi.val_only = true;
75a70cf9 11108 walk_gimple_seq (par_body, check_combined_parallel, NULL, &wi);
de7ef844 11109 if (ws_num == 1)
75a70cf9 11110 gimple_omp_parallel_set_combined_p (stmt, true);
de7ef844 11111 }
bc7bff74 11112 gimple_seq dep_ilist = NULL;
11113 gimple_seq dep_olist = NULL;
11114 if (gimple_code (stmt) == GIMPLE_OMP_TASK
11115 && find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
11116 {
8a4a28a8 11117 push_gimplify_context ();
bc7bff74 11118 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
11119 lower_depend_clauses (stmt, &dep_ilist, &dep_olist);
11120 }
11121
fd6481cf 11122 if (ctx->srecord_type)
1a91d914 11123 create_task_copyfn (as_a <gomp_task *> (stmt), ctx);
773c5ba7 11124
8a4a28a8 11125 push_gimplify_context ();
773c5ba7 11126
75a70cf9 11127 par_olist = NULL;
11128 par_ilist = NULL;
bc7bff74 11129 par_rlist = NULL;
11130 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx, NULL);
e3a19533 11131 lower_omp (&par_body, ctx);
75a70cf9 11132 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL)
bc7bff74 11133 lower_reduction_clauses (clauses, &par_rlist, ctx);
773c5ba7 11134
11135 /* Declare all the variables created by mapping and the variables
11136 declared in the scope of the parallel body. */
11137 record_vars_into (ctx->block_vars, child_fn);
75a70cf9 11138 record_vars_into (gimple_bind_vars (par_bind), child_fn);
773c5ba7 11139
11140 if (ctx->record_type)
11141 {
fd6481cf 11142 ctx->sender_decl
11143 = create_tmp_var (ctx->srecord_type ? ctx->srecord_type
11144 : ctx->record_type, ".omp_data_o");
84bfaaeb 11145 DECL_NAMELESS (ctx->sender_decl) = 1;
86f2ad37 11146 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
75a70cf9 11147 gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl);
773c5ba7 11148 }
11149
75a70cf9 11150 olist = NULL;
11151 ilist = NULL;
773c5ba7 11152 lower_send_clauses (clauses, &ilist, &olist, ctx);
11153 lower_send_shared_vars (&ilist, &olist, ctx);
11154
bc7bff74 11155 if (ctx->record_type)
11156 {
11157 tree clobber = build_constructor (TREE_TYPE (ctx->sender_decl), NULL);
11158 TREE_THIS_VOLATILE (clobber) = 1;
11159 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
11160 clobber));
11161 }
11162
773c5ba7 11163 /* Once all the expansions are done, sequence all the different
75a70cf9 11164 fragments inside gimple_omp_body. */
773c5ba7 11165
75a70cf9 11166 new_body = NULL;
773c5ba7 11167
11168 if (ctx->record_type)
11169 {
389dd41b 11170 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
cc6b725b 11171 /* fixup_child_record_type might have changed receiver_decl's type. */
389dd41b 11172 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
75a70cf9 11173 gimple_seq_add_stmt (&new_body,
11174 gimple_build_assign (ctx->receiver_decl, t));
773c5ba7 11175 }
11176
75a70cf9 11177 gimple_seq_add_seq (&new_body, par_ilist);
11178 gimple_seq_add_seq (&new_body, par_body);
bc7bff74 11179 gimple_seq_add_seq (&new_body, par_rlist);
11180 if (ctx->cancellable)
11181 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
75a70cf9 11182 gimple_seq_add_seq (&new_body, par_olist);
11183 new_body = maybe_catch_exception (new_body);
b25f70fd 11184 if (gimple_code (stmt) == GIMPLE_OMP_TASK)
11185 gimple_seq_add_stmt (&new_body,
11186 gimple_build_omp_continue (integer_zero_node,
11187 integer_zero_node));
75a70cf9 11188 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
11189 gimple_omp_set_body (stmt, new_body);
773c5ba7 11190
75a70cf9 11191 bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
bc7bff74 11192 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
11193 gimple_bind_add_seq (bind, ilist);
11194 gimple_bind_add_stmt (bind, stmt);
11195 gimple_bind_add_seq (bind, olist);
11196
11197 pop_gimplify_context (NULL);
11198
11199 if (dep_bind)
11200 {
11201 gimple_bind_add_seq (dep_bind, dep_ilist);
11202 gimple_bind_add_stmt (dep_bind, bind);
11203 gimple_bind_add_seq (dep_bind, dep_olist);
11204 pop_gimplify_context (dep_bind);
11205 }
11206}
11207
ca4c3545 11208/* Lower the GIMPLE_OMP_TARGET in the current statement
bc7bff74 11209 in GSI_P. CTX holds context information for the directive. */
11210
11211static void
11212lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
11213{
11214 tree clauses;
11215 tree child_fn, t, c;
1a91d914 11216 gomp_target *stmt = as_a <gomp_target *> (gsi_stmt (*gsi_p));
ca4c3545 11217 gbind *tgt_bind, *bind;
11218 gimple_seq tgt_body, olist, ilist, orlist, irlist, new_body;
bc7bff74 11219 location_t loc = gimple_location (stmt);
ca4c3545 11220 bool offloaded, data_region;
bc7bff74 11221 unsigned int map_cnt = 0;
11222
ca4c3545 11223 offloaded = is_gimple_omp_offloaded (stmt);
11224 switch (gimple_omp_target_kind (stmt))
11225 {
11226 case GF_OMP_TARGET_KIND_REGION:
11227 case GF_OMP_TARGET_KIND_UPDATE:
11228 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
11229 case GF_OMP_TARGET_KIND_OACC_KERNELS:
11230 case GF_OMP_TARGET_KIND_OACC_UPDATE:
11231 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
11232 data_region = false;
11233 break;
11234 case GF_OMP_TARGET_KIND_DATA:
11235 case GF_OMP_TARGET_KIND_OACC_DATA:
11236 data_region = true;
11237 break;
11238 default:
11239 gcc_unreachable ();
11240 }
11241
bc7bff74 11242 clauses = gimple_omp_target_clauses (stmt);
ca4c3545 11243
11244 tgt_bind = NULL;
11245 tgt_body = NULL;
11246 if (offloaded)
bc7bff74 11247 {
1a91d914 11248 tgt_bind = gimple_seq_first_stmt_as_a_bind (gimple_omp_body (stmt));
bc7bff74 11249 tgt_body = gimple_bind_body (tgt_bind);
11250 }
ca4c3545 11251 else if (data_region)
bc7bff74 11252 tgt_body = gimple_omp_body (stmt);
11253 child_fn = ctx->cb.dst_fn;
11254
8a4a28a8 11255 push_gimplify_context ();
bc7bff74 11256
ca4c3545 11257 irlist = NULL;
11258 orlist = NULL;
11259 if (offloaded
11260 && is_gimple_omp_oacc (stmt))
11261 oacc_process_reduction_data (&tgt_body, &irlist, &orlist, ctx);
11262
bc7bff74 11263 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
11264 switch (OMP_CLAUSE_CODE (c))
11265 {
11266 tree var, x;
11267
11268 default:
11269 break;
11270 case OMP_CLAUSE_MAP:
ca4c3545 11271#ifdef ENABLE_CHECKING
11272 /* First check what we're prepared to handle in the following. */
11273 switch (OMP_CLAUSE_MAP_KIND (c))
11274 {
11275 case GOMP_MAP_ALLOC:
11276 case GOMP_MAP_TO:
11277 case GOMP_MAP_FROM:
11278 case GOMP_MAP_TOFROM:
11279 case GOMP_MAP_POINTER:
11280 case GOMP_MAP_TO_PSET:
11281 break;
11282 case GOMP_MAP_FORCE_ALLOC:
11283 case GOMP_MAP_FORCE_TO:
11284 case GOMP_MAP_FORCE_FROM:
11285 case GOMP_MAP_FORCE_TOFROM:
11286 case GOMP_MAP_FORCE_PRESENT:
11287 case GOMP_MAP_FORCE_DEALLOC:
11288 case GOMP_MAP_FORCE_DEVICEPTR:
11289 gcc_assert (is_gimple_omp_oacc (stmt));
11290 break;
11291 default:
11292 gcc_unreachable ();
11293 }
11294#endif
11295 /* FALLTHRU */
bc7bff74 11296 case OMP_CLAUSE_TO:
11297 case OMP_CLAUSE_FROM:
11298 var = OMP_CLAUSE_DECL (c);
11299 if (!DECL_P (var))
11300 {
11301 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
11302 || !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
11303 map_cnt++;
11304 continue;
11305 }
11306
11307 if (DECL_SIZE (var)
11308 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
11309 {
11310 tree var2 = DECL_VALUE_EXPR (var);
11311 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
11312 var2 = TREE_OPERAND (var2, 0);
11313 gcc_assert (DECL_P (var2));
11314 var = var2;
11315 }
11316
11317 if (!maybe_lookup_field (var, ctx))
11318 continue;
11319
ca4c3545 11320 if (offloaded)
bc7bff74 11321 {
11322 x = build_receiver_ref (var, true, ctx);
11323 tree new_var = lookup_decl (var, ctx);
ca4c3545 11324 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
bc7bff74 11325 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
11326 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
11327 x = build_simple_mem_ref (x);
11328 SET_DECL_VALUE_EXPR (new_var, x);
11329 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
11330 }
11331 map_cnt++;
11332 }
11333
ca4c3545 11334 if (offloaded)
bc7bff74 11335 {
11336 target_nesting_level++;
11337 lower_omp (&tgt_body, ctx);
11338 target_nesting_level--;
11339 }
ca4c3545 11340 else if (data_region)
bc7bff74 11341 lower_omp (&tgt_body, ctx);
11342
ca4c3545 11343 if (offloaded)
bc7bff74 11344 {
11345 /* Declare all the variables created by mapping and the variables
11346 declared in the scope of the target body. */
11347 record_vars_into (ctx->block_vars, child_fn);
11348 record_vars_into (gimple_bind_vars (tgt_bind), child_fn);
11349 }
11350
11351 olist = NULL;
11352 ilist = NULL;
11353 if (ctx->record_type)
11354 {
11355 ctx->sender_decl
11356 = create_tmp_var (ctx->record_type, ".omp_data_arr");
11357 DECL_NAMELESS (ctx->sender_decl) = 1;
11358 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
11359 t = make_tree_vec (3);
11360 TREE_VEC_ELT (t, 0) = ctx->sender_decl;
11361 TREE_VEC_ELT (t, 1)
11362 = create_tmp_var (build_array_type_nelts (size_type_node, map_cnt),
11363 ".omp_data_sizes");
11364 DECL_NAMELESS (TREE_VEC_ELT (t, 1)) = 1;
11365 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 1)) = 1;
11366 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 1;
ca4c3545 11367 tree tkind_type;
11368 int talign_shift;
11369 if (is_gimple_omp_oacc (stmt))
11370 {
11371 tkind_type = short_unsigned_type_node;
11372 talign_shift = 8;
11373 }
11374 else
11375 {
11376 tkind_type = unsigned_char_type_node;
11377 talign_shift = 3;
11378 }
bc7bff74 11379 TREE_VEC_ELT (t, 2)
ca4c3545 11380 = create_tmp_var (build_array_type_nelts (tkind_type, map_cnt),
bc7bff74 11381 ".omp_data_kinds");
11382 DECL_NAMELESS (TREE_VEC_ELT (t, 2)) = 1;
11383 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 2)) = 1;
11384 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 1;
11385 gimple_omp_target_set_data_arg (stmt, t);
11386
11387 vec<constructor_elt, va_gc> *vsize;
11388 vec<constructor_elt, va_gc> *vkind;
11389 vec_alloc (vsize, map_cnt);
11390 vec_alloc (vkind, map_cnt);
11391 unsigned int map_idx = 0;
11392
11393 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
11394 switch (OMP_CLAUSE_CODE (c))
11395 {
11396 tree ovar, nc;
11397
11398 default:
11399 break;
11400 case OMP_CLAUSE_MAP:
11401 case OMP_CLAUSE_TO:
11402 case OMP_CLAUSE_FROM:
11403 nc = c;
11404 ovar = OMP_CLAUSE_DECL (c);
11405 if (!DECL_P (ovar))
11406 {
11407 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
11408 && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
11409 {
11410 gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c))
11411 == get_base_address (ovar));
11412 nc = OMP_CLAUSE_CHAIN (c);
11413 ovar = OMP_CLAUSE_DECL (nc);
11414 }
11415 else
11416 {
11417 tree x = build_sender_ref (ovar, ctx);
11418 tree v
11419 = build_fold_addr_expr_with_type (ovar, ptr_type_node);
11420 gimplify_assign (x, v, &ilist);
11421 nc = NULL_TREE;
11422 }
11423 }
11424 else
11425 {
11426 if (DECL_SIZE (ovar)
11427 && TREE_CODE (DECL_SIZE (ovar)) != INTEGER_CST)
11428 {
11429 tree ovar2 = DECL_VALUE_EXPR (ovar);
11430 gcc_assert (TREE_CODE (ovar2) == INDIRECT_REF);
11431 ovar2 = TREE_OPERAND (ovar2, 0);
11432 gcc_assert (DECL_P (ovar2));
11433 ovar = ovar2;
11434 }
11435 if (!maybe_lookup_field (ovar, ctx))
11436 continue;
11437 }
11438
4f3b8d78 11439 unsigned int talign = TYPE_ALIGN_UNIT (TREE_TYPE (ovar));
11440 if (DECL_P (ovar) && DECL_ALIGN_UNIT (ovar) > talign)
11441 talign = DECL_ALIGN_UNIT (ovar);
bc7bff74 11442 if (nc)
11443 {
11444 tree var = lookup_decl_in_outer_ctx (ovar, ctx);
11445 tree x = build_sender_ref (ovar, ctx);
ca4c3545 11446 if (maybe_lookup_oacc_reduction (var, ctx))
11447 {
11448 gcc_checking_assert (offloaded
11449 && is_gimple_omp_oacc (stmt));
11450 gimplify_assign (x, var, &ilist);
11451 }
11452 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
11453 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
11454 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
11455 && TREE_CODE (TREE_TYPE (ovar)) == ARRAY_TYPE)
bc7bff74 11456 {
ca4c3545 11457 gcc_assert (offloaded);
bc7bff74 11458 tree avar
f9e245b2 11459 = create_tmp_var (TREE_TYPE (TREE_TYPE (x)));
bc7bff74 11460 mark_addressable (avar);
11461 gimplify_assign (avar, build_fold_addr_expr (var), &ilist);
4f3b8d78 11462 talign = DECL_ALIGN_UNIT (avar);
bc7bff74 11463 avar = build_fold_addr_expr (avar);
11464 gimplify_assign (x, avar, &ilist);
11465 }
11466 else if (is_gimple_reg (var))
11467 {
ca4c3545 11468 gcc_assert (offloaded);
f9e245b2 11469 tree avar = create_tmp_var (TREE_TYPE (var));
bc7bff74 11470 mark_addressable (avar);
ca4c3545 11471 enum gomp_map_kind map_kind = OMP_CLAUSE_MAP_KIND (c);
11472 if (GOMP_MAP_COPY_TO_P (map_kind)
11473 || map_kind == GOMP_MAP_POINTER
11474 || map_kind == GOMP_MAP_TO_PSET
11475 || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
bc7bff74 11476 gimplify_assign (avar, var, &ilist);
11477 avar = build_fold_addr_expr (avar);
11478 gimplify_assign (x, avar, &ilist);
ca4c3545 11479 if ((GOMP_MAP_COPY_FROM_P (map_kind)
11480 || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
bc7bff74 11481 && !TYPE_READONLY (TREE_TYPE (var)))
11482 {
11483 x = build_sender_ref (ovar, ctx);
11484 x = build_simple_mem_ref (x);
11485 gimplify_assign (var, x, &olist);
11486 }
11487 }
11488 else
11489 {
11490 var = build_fold_addr_expr (var);
11491 gimplify_assign (x, var, &ilist);
11492 }
11493 }
11494 tree s = OMP_CLAUSE_SIZE (c);
11495 if (s == NULL_TREE)
11496 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
11497 s = fold_convert (size_type_node, s);
11498 tree purpose = size_int (map_idx++);
11499 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
11500 if (TREE_CODE (s) != INTEGER_CST)
11501 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
11502
ca4c3545 11503 unsigned HOST_WIDE_INT tkind;
bc7bff74 11504 switch (OMP_CLAUSE_CODE (c))
11505 {
11506 case OMP_CLAUSE_MAP:
11507 tkind = OMP_CLAUSE_MAP_KIND (c);
11508 break;
11509 case OMP_CLAUSE_TO:
ca4c3545 11510 tkind = GOMP_MAP_TO;
bc7bff74 11511 break;
11512 case OMP_CLAUSE_FROM:
ca4c3545 11513 tkind = GOMP_MAP_FROM;
bc7bff74 11514 break;
11515 default:
11516 gcc_unreachable ();
11517 }
ca4c3545 11518 gcc_checking_assert (tkind
11519 < (HOST_WIDE_INT_C (1U) << talign_shift));
bc7bff74 11520 talign = ceil_log2 (talign);
ca4c3545 11521 tkind |= talign << talign_shift;
11522 gcc_checking_assert (tkind
11523 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
bc7bff74 11524 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
ca4c3545 11525 build_int_cstu (tkind_type, tkind));
bc7bff74 11526 if (nc && nc != c)
11527 c = nc;
11528 }
11529
11530 gcc_assert (map_idx == map_cnt);
11531
11532 DECL_INITIAL (TREE_VEC_ELT (t, 1))
11533 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)), vsize);
11534 DECL_INITIAL (TREE_VEC_ELT (t, 2))
11535 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 2)), vkind);
11536 if (!TREE_STATIC (TREE_VEC_ELT (t, 1)))
11537 {
11538 gimple_seq initlist = NULL;
11539 force_gimple_operand (build1 (DECL_EXPR, void_type_node,
11540 TREE_VEC_ELT (t, 1)),
11541 &initlist, true, NULL_TREE);
11542 gimple_seq_add_seq (&ilist, initlist);
d8e1e68d 11543
11544 tree clobber = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)),
11545 NULL);
11546 TREE_THIS_VOLATILE (clobber) = 1;
11547 gimple_seq_add_stmt (&olist,
11548 gimple_build_assign (TREE_VEC_ELT (t, 1),
11549 clobber));
bc7bff74 11550 }
11551
11552 tree clobber = build_constructor (ctx->record_type, NULL);
11553 TREE_THIS_VOLATILE (clobber) = 1;
11554 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
11555 clobber));
11556 }
11557
11558 /* Once all the expansions are done, sequence all the different
11559 fragments inside gimple_omp_body. */
11560
11561 new_body = NULL;
11562
ca4c3545 11563 if (offloaded
11564 && ctx->record_type)
bc7bff74 11565 {
11566 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
11567 /* fixup_child_record_type might have changed receiver_decl's type. */
11568 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
11569 gimple_seq_add_stmt (&new_body,
11570 gimple_build_assign (ctx->receiver_decl, t));
11571 }
11572
ca4c3545 11573 if (offloaded)
bc7bff74 11574 {
11575 gimple_seq_add_seq (&new_body, tgt_body);
11576 new_body = maybe_catch_exception (new_body);
11577 }
ca4c3545 11578 else if (data_region)
bc7bff74 11579 new_body = tgt_body;
ca4c3545 11580 if (offloaded || data_region)
bc7bff74 11581 {
11582 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
11583 gimple_omp_set_body (stmt, new_body);
11584 }
11585
11586 bind = gimple_build_bind (NULL, NULL,
11587 tgt_bind ? gimple_bind_block (tgt_bind)
11588 : NULL_TREE);
75a70cf9 11589 gsi_replace (gsi_p, bind, true);
ca4c3545 11590 gimple_bind_add_seq (bind, irlist);
e3a19533 11591 gimple_bind_add_seq (bind, ilist);
11592 gimple_bind_add_stmt (bind, stmt);
11593 gimple_bind_add_seq (bind, olist);
ca4c3545 11594 gimple_bind_add_seq (bind, orlist);
773c5ba7 11595
75a70cf9 11596 pop_gimplify_context (NULL);
773c5ba7 11597}
11598
bc7bff74 11599/* Expand code for an OpenMP teams directive. */
11600
11601static void
11602lower_omp_teams (gimple_stmt_iterator *gsi_p, omp_context *ctx)
11603{
1a91d914 11604 gomp_teams *teams_stmt = as_a <gomp_teams *> (gsi_stmt (*gsi_p));
8a4a28a8 11605 push_gimplify_context ();
bc7bff74 11606
11607 tree block = make_node (BLOCK);
1a91d914 11608 gbind *bind = gimple_build_bind (NULL, NULL, block);
bc7bff74 11609 gsi_replace (gsi_p, bind, true);
11610 gimple_seq bind_body = NULL;
11611 gimple_seq dlist = NULL;
11612 gimple_seq olist = NULL;
11613
11614 tree num_teams = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
11615 OMP_CLAUSE_NUM_TEAMS);
11616 if (num_teams == NULL_TREE)
11617 num_teams = build_int_cst (unsigned_type_node, 0);
11618 else
11619 {
11620 num_teams = OMP_CLAUSE_NUM_TEAMS_EXPR (num_teams);
11621 num_teams = fold_convert (unsigned_type_node, num_teams);
11622 gimplify_expr (&num_teams, &bind_body, NULL, is_gimple_val, fb_rvalue);
11623 }
11624 tree thread_limit = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
11625 OMP_CLAUSE_THREAD_LIMIT);
11626 if (thread_limit == NULL_TREE)
11627 thread_limit = build_int_cst (unsigned_type_node, 0);
11628 else
11629 {
11630 thread_limit = OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit);
11631 thread_limit = fold_convert (unsigned_type_node, thread_limit);
11632 gimplify_expr (&thread_limit, &bind_body, NULL, is_gimple_val,
11633 fb_rvalue);
11634 }
11635
11636 lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt),
11637 &bind_body, &dlist, ctx, NULL);
11638 lower_omp (gimple_omp_body_ptr (teams_stmt), ctx);
11639 lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt), &olist, ctx);
11640 gimple_seq_add_stmt (&bind_body, teams_stmt);
11641
11642 location_t loc = gimple_location (teams_stmt);
11643 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TEAMS);
11644 gimple call = gimple_build_call (decl, 2, num_teams, thread_limit);
11645 gimple_set_location (call, loc);
11646 gimple_seq_add_stmt (&bind_body, call);
11647
11648 gimple_seq_add_seq (&bind_body, gimple_omp_body (teams_stmt));
11649 gimple_omp_set_body (teams_stmt, NULL);
11650 gimple_seq_add_seq (&bind_body, olist);
11651 gimple_seq_add_seq (&bind_body, dlist);
11652 gimple_seq_add_stmt (&bind_body, gimple_build_omp_return (true));
11653 gimple_bind_set_body (bind, bind_body);
11654
11655 pop_gimplify_context (bind);
11656
11657 gimple_bind_append_vars (bind, ctx->block_vars);
11658 BLOCK_VARS (block) = ctx->block_vars;
11659 if (BLOCK_VARS (block))
11660 TREE_USED (block) = 1;
11661}
11662
11663
a4890dc9 11664/* Callback for lower_omp_1. Return non-NULL if *tp needs to be
75a70cf9 11665 regimplified. If DATA is non-NULL, lower_omp_1 is outside
ca4c3545 11666 of OMP context, but with task_shared_vars set. */
46515c92 11667
11668static tree
75a70cf9 11669lower_omp_regimplify_p (tree *tp, int *walk_subtrees,
11670 void *data)
46515c92 11671{
a4890dc9 11672 tree t = *tp;
46515c92 11673
a4890dc9 11674 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
75a70cf9 11675 if (TREE_CODE (t) == VAR_DECL && data == NULL && DECL_HAS_VALUE_EXPR_P (t))
9f49e155 11676 return t;
11677
11678 if (task_shared_vars
11679 && DECL_P (t)
11680 && bitmap_bit_p (task_shared_vars, DECL_UID (t)))
a4890dc9 11681 return t;
46515c92 11682
a4890dc9 11683 /* If a global variable has been privatized, TREE_CONSTANT on
11684 ADDR_EXPR might be wrong. */
75a70cf9 11685 if (data == NULL && TREE_CODE (t) == ADDR_EXPR)
a4890dc9 11686 recompute_tree_invariant_for_addr_expr (t);
46515c92 11687
a4890dc9 11688 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
11689 return NULL_TREE;
46515c92 11690}
773c5ba7 11691
a4890dc9 11692static void
75a70cf9 11693lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
1e8e9920 11694{
75a70cf9 11695 gimple stmt = gsi_stmt (*gsi_p);
11696 struct walk_stmt_info wi;
1a91d914 11697 gcall *call_stmt;
1e8e9920 11698
75a70cf9 11699 if (gimple_has_location (stmt))
11700 input_location = gimple_location (stmt);
a4890dc9 11701
75a70cf9 11702 if (task_shared_vars)
11703 memset (&wi, '\0', sizeof (wi));
a4890dc9 11704
773c5ba7 11705 /* If we have issued syntax errors, avoid doing any heavy lifting.
ca4c3545 11706 Just replace the OMP directives with a NOP to avoid
773c5ba7 11707 confusing RTL expansion. */
852f689e 11708 if (seen_error () && is_gimple_omp (stmt))
773c5ba7 11709 {
75a70cf9 11710 gsi_replace (gsi_p, gimple_build_nop (), true);
a4890dc9 11711 return;
773c5ba7 11712 }
11713
75a70cf9 11714 switch (gimple_code (stmt))
1e8e9920 11715 {
75a70cf9 11716 case GIMPLE_COND:
1a91d914 11717 {
11718 gcond *cond_stmt = as_a <gcond *> (stmt);
11719 if ((ctx || task_shared_vars)
11720 && (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
11721 lower_omp_regimplify_p,
11722 ctx ? NULL : &wi, NULL)
11723 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
11724 lower_omp_regimplify_p,
11725 ctx ? NULL : &wi, NULL)))
11726 gimple_regimplify_operands (cond_stmt, gsi_p);
11727 }
a4890dc9 11728 break;
75a70cf9 11729 case GIMPLE_CATCH:
1a91d914 11730 lower_omp (gimple_catch_handler_ptr (as_a <gcatch *> (stmt)), ctx);
a4890dc9 11731 break;
75a70cf9 11732 case GIMPLE_EH_FILTER:
e3a19533 11733 lower_omp (gimple_eh_filter_failure_ptr (stmt), ctx);
a4890dc9 11734 break;
75a70cf9 11735 case GIMPLE_TRY:
e3a19533 11736 lower_omp (gimple_try_eval_ptr (stmt), ctx);
11737 lower_omp (gimple_try_cleanup_ptr (stmt), ctx);
a4890dc9 11738 break;
35215227 11739 case GIMPLE_TRANSACTION:
1a91d914 11740 lower_omp (gimple_transaction_body_ptr (
11741 as_a <gtransaction *> (stmt)),
11742 ctx);
35215227 11743 break;
75a70cf9 11744 case GIMPLE_BIND:
1a91d914 11745 lower_omp (gimple_bind_body_ptr (as_a <gbind *> (stmt)), ctx);
a4890dc9 11746 break;
75a70cf9 11747 case GIMPLE_OMP_PARALLEL:
11748 case GIMPLE_OMP_TASK:
11749 ctx = maybe_lookup_ctx (stmt);
bc7bff74 11750 gcc_assert (ctx);
11751 if (ctx->cancellable)
11752 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
75a70cf9 11753 lower_omp_taskreg (gsi_p, ctx);
a4890dc9 11754 break;
75a70cf9 11755 case GIMPLE_OMP_FOR:
11756 ctx = maybe_lookup_ctx (stmt);
1e8e9920 11757 gcc_assert (ctx);
bc7bff74 11758 if (ctx->cancellable)
11759 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
75a70cf9 11760 lower_omp_for (gsi_p, ctx);
1e8e9920 11761 break;
75a70cf9 11762 case GIMPLE_OMP_SECTIONS:
11763 ctx = maybe_lookup_ctx (stmt);
1e8e9920 11764 gcc_assert (ctx);
bc7bff74 11765 if (ctx->cancellable)
11766 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
75a70cf9 11767 lower_omp_sections (gsi_p, ctx);
1e8e9920 11768 break;
75a70cf9 11769 case GIMPLE_OMP_SINGLE:
11770 ctx = maybe_lookup_ctx (stmt);
1e8e9920 11771 gcc_assert (ctx);
75a70cf9 11772 lower_omp_single (gsi_p, ctx);
1e8e9920 11773 break;
75a70cf9 11774 case GIMPLE_OMP_MASTER:
11775 ctx = maybe_lookup_ctx (stmt);
1e8e9920 11776 gcc_assert (ctx);
75a70cf9 11777 lower_omp_master (gsi_p, ctx);
1e8e9920 11778 break;
bc7bff74 11779 case GIMPLE_OMP_TASKGROUP:
11780 ctx = maybe_lookup_ctx (stmt);
11781 gcc_assert (ctx);
11782 lower_omp_taskgroup (gsi_p, ctx);
11783 break;
75a70cf9 11784 case GIMPLE_OMP_ORDERED:
11785 ctx = maybe_lookup_ctx (stmt);
1e8e9920 11786 gcc_assert (ctx);
75a70cf9 11787 lower_omp_ordered (gsi_p, ctx);
1e8e9920 11788 break;
75a70cf9 11789 case GIMPLE_OMP_CRITICAL:
11790 ctx = maybe_lookup_ctx (stmt);
1e8e9920 11791 gcc_assert (ctx);
75a70cf9 11792 lower_omp_critical (gsi_p, ctx);
11793 break;
11794 case GIMPLE_OMP_ATOMIC_LOAD:
11795 if ((ctx || task_shared_vars)
1a91d914 11796 && walk_tree (gimple_omp_atomic_load_rhs_ptr (
11797 as_a <gomp_atomic_load *> (stmt)),
75a70cf9 11798 lower_omp_regimplify_p, ctx ? NULL : &wi, NULL))
11799 gimple_regimplify_operands (stmt, gsi_p);
1e8e9920 11800 break;
bc7bff74 11801 case GIMPLE_OMP_TARGET:
11802 ctx = maybe_lookup_ctx (stmt);
11803 gcc_assert (ctx);
11804 lower_omp_target (gsi_p, ctx);
11805 break;
11806 case GIMPLE_OMP_TEAMS:
11807 ctx = maybe_lookup_ctx (stmt);
11808 gcc_assert (ctx);
11809 lower_omp_teams (gsi_p, ctx);
11810 break;
11811 case GIMPLE_CALL:
11812 tree fndecl;
1a91d914 11813 call_stmt = as_a <gcall *> (stmt);
11814 fndecl = gimple_call_fndecl (call_stmt);
bc7bff74 11815 if (fndecl
11816 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
11817 switch (DECL_FUNCTION_CODE (fndecl))
11818 {
11819 case BUILT_IN_GOMP_BARRIER:
11820 if (ctx == NULL)
11821 break;
11822 /* FALLTHRU */
11823 case BUILT_IN_GOMP_CANCEL:
11824 case BUILT_IN_GOMP_CANCELLATION_POINT:
11825 omp_context *cctx;
11826 cctx = ctx;
11827 if (gimple_code (cctx->stmt) == GIMPLE_OMP_SECTION)
11828 cctx = cctx->outer;
1a91d914 11829 gcc_assert (gimple_call_lhs (call_stmt) == NULL_TREE);
bc7bff74 11830 if (!cctx->cancellable)
11831 {
11832 if (DECL_FUNCTION_CODE (fndecl)
11833 == BUILT_IN_GOMP_CANCELLATION_POINT)
11834 {
11835 stmt = gimple_build_nop ();
11836 gsi_replace (gsi_p, stmt, false);
11837 }
11838 break;
11839 }
bc7bff74 11840 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
11841 {
11842 fndecl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL);
1a91d914 11843 gimple_call_set_fndecl (call_stmt, fndecl);
11844 gimple_call_set_fntype (call_stmt, TREE_TYPE (fndecl));
bc7bff74 11845 }
15b28553 11846 tree lhs;
f9e245b2 11847 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (fndecl)));
1a91d914 11848 gimple_call_set_lhs (call_stmt, lhs);
bc7bff74 11849 tree fallthru_label;
11850 fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
11851 gimple g;
11852 g = gimple_build_label (fallthru_label);
11853 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
15b28553 11854 g = gimple_build_cond (NE_EXPR, lhs,
11855 fold_convert (TREE_TYPE (lhs),
11856 boolean_false_node),
bc7bff74 11857 cctx->cancel_label, fallthru_label);
11858 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
11859 break;
11860 default:
11861 break;
11862 }
11863 /* FALLTHRU */
a4890dc9 11864 default:
fd6481cf 11865 if ((ctx || task_shared_vars)
75a70cf9 11866 && walk_gimple_op (stmt, lower_omp_regimplify_p,
11867 ctx ? NULL : &wi))
ef8cfd4d 11868 {
11869 /* Just remove clobbers, this should happen only if we have
11870 "privatized" local addressable variables in SIMD regions,
11871 the clobber isn't needed in that case and gimplifying address
11872 of the ARRAY_REF into a pointer and creating MEM_REF based
11873 clobber would create worse code than we get with the clobber
11874 dropped. */
11875 if (gimple_clobber_p (stmt))
11876 {
11877 gsi_replace (gsi_p, gimple_build_nop (), true);
11878 break;
11879 }
11880 gimple_regimplify_operands (stmt, gsi_p);
11881 }
1e8e9920 11882 break;
1e8e9920 11883 }
1e8e9920 11884}
11885
11886static void
e3a19533 11887lower_omp (gimple_seq *body, omp_context *ctx)
1e8e9920 11888{
1d22f541 11889 location_t saved_location = input_location;
e3a19533 11890 gimple_stmt_iterator gsi;
11891 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
75a70cf9 11892 lower_omp_1 (&gsi, ctx);
ca4c3545 11893 /* During gimplification, we haven't folded statments inside offloading
c3a81971 11894 or taskreg regions (gimplify.c:maybe_fold_stmt); do that now. */
11895 if (target_nesting_level || taskreg_nesting_level)
bc7bff74 11896 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
11897 fold_stmt (&gsi);
1d22f541 11898 input_location = saved_location;
1e8e9920 11899}
11900\f
11901/* Main entry point. */
11902
2a1990e9 11903static unsigned int
1e8e9920 11904execute_lower_omp (void)
11905{
75a70cf9 11906 gimple_seq body;
37eaded9 11907 int i;
11908 omp_context *ctx;
75a70cf9 11909
41709826 11910 /* This pass always runs, to provide PROP_gimple_lomp.
ca4c3545 11911 But often, there is nothing to do. */
11912 if (flag_cilkplus == 0 && flag_openacc == 0 && flag_openmp == 0
11913 && flag_openmp_simd == 0)
41709826 11914 return 0;
11915
1e8e9920 11916 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
11917 delete_omp_context);
11918
75a70cf9 11919 body = gimple_body (current_function_decl);
ab129075 11920 scan_omp (&body, NULL);
fd6481cf 11921 gcc_assert (taskreg_nesting_level == 0);
37eaded9 11922 FOR_EACH_VEC_ELT (taskreg_contexts, i, ctx)
11923 finish_taskreg_scan (ctx);
11924 taskreg_contexts.release ();
1e8e9920 11925
11926 if (all_contexts->root)
fd6481cf 11927 {
11928 if (task_shared_vars)
8a4a28a8 11929 push_gimplify_context ();
e3a19533 11930 lower_omp (&body, NULL);
fd6481cf 11931 if (task_shared_vars)
11932 pop_gimplify_context (NULL);
11933 }
1e8e9920 11934
773c5ba7 11935 if (all_contexts)
11936 {
11937 splay_tree_delete (all_contexts);
11938 all_contexts = NULL;
11939 }
fd6481cf 11940 BITMAP_FREE (task_shared_vars);
2a1990e9 11941 return 0;
1e8e9920 11942}
11943
cbe8bda8 11944namespace {
11945
11946const pass_data pass_data_lower_omp =
11947{
11948 GIMPLE_PASS, /* type */
11949 "omplower", /* name */
11950 OPTGROUP_NONE, /* optinfo_flags */
cbe8bda8 11951 TV_NONE, /* tv_id */
11952 PROP_gimple_any, /* properties_required */
11953 PROP_gimple_lomp, /* properties_provided */
11954 0, /* properties_destroyed */
11955 0, /* todo_flags_start */
11956 0, /* todo_flags_finish */
1e8e9920 11957};
cbe8bda8 11958
11959class pass_lower_omp : public gimple_opt_pass
11960{
11961public:
9af5ce0c 11962 pass_lower_omp (gcc::context *ctxt)
11963 : gimple_opt_pass (pass_data_lower_omp, ctxt)
cbe8bda8 11964 {}
11965
11966 /* opt_pass methods: */
65b0537f 11967 virtual unsigned int execute (function *) { return execute_lower_omp (); }
cbe8bda8 11968
11969}; // class pass_lower_omp
11970
11971} // anon namespace
11972
11973gimple_opt_pass *
11974make_pass_lower_omp (gcc::context *ctxt)
11975{
11976 return new pass_lower_omp (ctxt);
11977}
1e8e9920 11978\f
ca4c3545 11979/* The following is a utility to diagnose structured block violations.
61e47ac8 11980 It is not part of the "omplower" pass, as that's invoked too late. It
11981 should be invoked by the respective front ends after gimplification. */
1e8e9920 11982
11983static splay_tree all_labels;
11984
11985/* Check for mismatched contexts and generate an error if needed. Return
11986 true if an error is detected. */
11987
11988static bool
75a70cf9 11989diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
11990 gimple branch_ctx, gimple label_ctx)
1e8e9920 11991{
ca4c3545 11992 gcc_checking_assert (!branch_ctx || is_gimple_omp (branch_ctx));
11993 gcc_checking_assert (!label_ctx || is_gimple_omp (label_ctx));
11994
75a70cf9 11995 if (label_ctx == branch_ctx)
1e8e9920 11996 return false;
11997
ca4c3545 11998 const char* kind = NULL;
11999
12000 if (flag_cilkplus)
12001 {
12002 if ((branch_ctx
12003 && gimple_code (branch_ctx) == GIMPLE_OMP_FOR
12004 && gimple_omp_for_kind (branch_ctx) == GF_OMP_FOR_KIND_CILKSIMD)
12005 || (label_ctx
12006 && gimple_code (label_ctx) == GIMPLE_OMP_FOR
12007 && gimple_omp_for_kind (label_ctx) == GF_OMP_FOR_KIND_CILKSIMD))
12008 kind = "Cilk Plus";
12009 }
12010 if (flag_openacc)
12011 {
12012 if ((branch_ctx && is_gimple_omp_oacc (branch_ctx))
12013 || (label_ctx && is_gimple_omp_oacc (label_ctx)))
12014 {
12015 gcc_checking_assert (kind == NULL);
12016 kind = "OpenACC";
12017 }
12018 }
12019 if (kind == NULL)
12020 {
12021 gcc_checking_assert (flag_openmp);
12022 kind = "OpenMP";
12023 }
48e1416a 12024
75a70cf9 12025 /*
12026 Previously we kept track of the label's entire context in diagnose_sb_[12]
12027 so we could traverse it and issue a correct "exit" or "enter" error
12028 message upon a structured block violation.
12029
12030 We built the context by building a list with tree_cons'ing, but there is
12031 no easy counterpart in gimple tuples. It seems like far too much work
12032 for issuing exit/enter error messages. If someone really misses the
12033 distinct error message... patches welcome.
12034 */
48e1416a 12035
75a70cf9 12036#if 0
1e8e9920 12037 /* Try to avoid confusing the user by producing and error message
f0b5f617 12038 with correct "exit" or "enter" verbiage. We prefer "exit"
1e8e9920 12039 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
12040 if (branch_ctx == NULL)
12041 exit_p = false;
12042 else
12043 {
12044 while (label_ctx)
12045 {
12046 if (TREE_VALUE (label_ctx) == branch_ctx)
12047 {
12048 exit_p = false;
12049 break;
12050 }
12051 label_ctx = TREE_CHAIN (label_ctx);
12052 }
12053 }
12054
12055 if (exit_p)
ca4c3545 12056 error ("invalid exit from %s structured block", kind);
1e8e9920 12057 else
ca4c3545 12058 error ("invalid entry to %s structured block", kind);
75a70cf9 12059#endif
1e8e9920 12060
75a70cf9 12061 /* If it's obvious we have an invalid entry, be specific about the error. */
12062 if (branch_ctx == NULL)
ca4c3545 12063 error ("invalid entry to %s structured block", kind);
75a70cf9 12064 else
f2697631 12065 {
12066 /* Otherwise, be vague and lazy, but efficient. */
ca4c3545 12067 error ("invalid branch to/from %s structured block", kind);
f2697631 12068 }
75a70cf9 12069
12070 gsi_replace (gsi_p, gimple_build_nop (), false);
1e8e9920 12071 return true;
12072}
12073
ca4c3545 12074/* Pass 1: Create a minimal tree of structured blocks, and record
75a70cf9 12075 where each label is found. */
1e8e9920 12076
12077static tree
75a70cf9 12078diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
12079 struct walk_stmt_info *wi)
1e8e9920 12080{
75a70cf9 12081 gimple context = (gimple) wi->info;
12082 gimple inner_context;
12083 gimple stmt = gsi_stmt (*gsi_p);
1e8e9920 12084
75a70cf9 12085 *handled_ops_p = true;
12086
ca4c3545 12087 switch (gimple_code (stmt))
1e8e9920 12088 {
75a70cf9 12089 WALK_SUBSTMTS;
48e1416a 12090
75a70cf9 12091 case GIMPLE_OMP_PARALLEL:
12092 case GIMPLE_OMP_TASK:
12093 case GIMPLE_OMP_SECTIONS:
12094 case GIMPLE_OMP_SINGLE:
12095 case GIMPLE_OMP_SECTION:
12096 case GIMPLE_OMP_MASTER:
12097 case GIMPLE_OMP_ORDERED:
12098 case GIMPLE_OMP_CRITICAL:
bc7bff74 12099 case GIMPLE_OMP_TARGET:
12100 case GIMPLE_OMP_TEAMS:
12101 case GIMPLE_OMP_TASKGROUP:
75a70cf9 12102 /* The minimal context here is just the current OMP construct. */
12103 inner_context = stmt;
1e8e9920 12104 wi->info = inner_context;
75a70cf9 12105 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
1e8e9920 12106 wi->info = context;
12107 break;
12108
75a70cf9 12109 case GIMPLE_OMP_FOR:
12110 inner_context = stmt;
1e8e9920 12111 wi->info = inner_context;
75a70cf9 12112 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
12113 walk them. */
12114 walk_gimple_seq (gimple_omp_for_pre_body (stmt),
12115 diagnose_sb_1, NULL, wi);
12116 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
1e8e9920 12117 wi->info = context;
12118 break;
12119
75a70cf9 12120 case GIMPLE_LABEL:
1a91d914 12121 splay_tree_insert (all_labels,
12122 (splay_tree_key) gimple_label_label (
12123 as_a <glabel *> (stmt)),
1e8e9920 12124 (splay_tree_value) context);
12125 break;
12126
12127 default:
12128 break;
12129 }
12130
12131 return NULL_TREE;
12132}
12133
12134/* Pass 2: Check each branch and see if its context differs from that of
12135 the destination label's context. */
12136
12137static tree
75a70cf9 12138diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
12139 struct walk_stmt_info *wi)
1e8e9920 12140{
75a70cf9 12141 gimple context = (gimple) wi->info;
1e8e9920 12142 splay_tree_node n;
75a70cf9 12143 gimple stmt = gsi_stmt (*gsi_p);
1e8e9920 12144
75a70cf9 12145 *handled_ops_p = true;
12146
12147 switch (gimple_code (stmt))
1e8e9920 12148 {
75a70cf9 12149 WALK_SUBSTMTS;
12150
12151 case GIMPLE_OMP_PARALLEL:
12152 case GIMPLE_OMP_TASK:
12153 case GIMPLE_OMP_SECTIONS:
12154 case GIMPLE_OMP_SINGLE:
12155 case GIMPLE_OMP_SECTION:
12156 case GIMPLE_OMP_MASTER:
12157 case GIMPLE_OMP_ORDERED:
12158 case GIMPLE_OMP_CRITICAL:
bc7bff74 12159 case GIMPLE_OMP_TARGET:
12160 case GIMPLE_OMP_TEAMS:
12161 case GIMPLE_OMP_TASKGROUP:
75a70cf9 12162 wi->info = stmt;
e3a19533 12163 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
1e8e9920 12164 wi->info = context;
12165 break;
12166
75a70cf9 12167 case GIMPLE_OMP_FOR:
12168 wi->info = stmt;
12169 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
12170 walk them. */
e3a19533 12171 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt),
12172 diagnose_sb_2, NULL, wi);
12173 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
1e8e9920 12174 wi->info = context;
12175 break;
12176
0e1818e7 12177 case GIMPLE_COND:
12178 {
1a91d914 12179 gcond *cond_stmt = as_a <gcond *> (stmt);
12180 tree lab = gimple_cond_true_label (cond_stmt);
0e1818e7 12181 if (lab)
12182 {
12183 n = splay_tree_lookup (all_labels,
12184 (splay_tree_key) lab);
12185 diagnose_sb_0 (gsi_p, context,
12186 n ? (gimple) n->value : NULL);
12187 }
1a91d914 12188 lab = gimple_cond_false_label (cond_stmt);
0e1818e7 12189 if (lab)
12190 {
12191 n = splay_tree_lookup (all_labels,
12192 (splay_tree_key) lab);
12193 diagnose_sb_0 (gsi_p, context,
12194 n ? (gimple) n->value : NULL);
12195 }
12196 }
12197 break;
12198
75a70cf9 12199 case GIMPLE_GOTO:
1e8e9920 12200 {
75a70cf9 12201 tree lab = gimple_goto_dest (stmt);
1e8e9920 12202 if (TREE_CODE (lab) != LABEL_DECL)
12203 break;
12204
12205 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
75a70cf9 12206 diagnose_sb_0 (gsi_p, context, n ? (gimple) n->value : NULL);
1e8e9920 12207 }
12208 break;
12209
75a70cf9 12210 case GIMPLE_SWITCH:
1e8e9920 12211 {
1a91d914 12212 gswitch *switch_stmt = as_a <gswitch *> (stmt);
75a70cf9 12213 unsigned int i;
1a91d914 12214 for (i = 0; i < gimple_switch_num_labels (switch_stmt); ++i)
1e8e9920 12215 {
1a91d914 12216 tree lab = CASE_LABEL (gimple_switch_label (switch_stmt, i));
1e8e9920 12217 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
75a70cf9 12218 if (n && diagnose_sb_0 (gsi_p, context, (gimple) n->value))
1e8e9920 12219 break;
12220 }
12221 }
12222 break;
12223
75a70cf9 12224 case GIMPLE_RETURN:
12225 diagnose_sb_0 (gsi_p, context, NULL);
1e8e9920 12226 break;
12227
12228 default:
12229 break;
12230 }
12231
12232 return NULL_TREE;
12233}
12234
ca4c3545 12235/* Called from tree-cfg.c::make_edges to create cfg edges for all relevant
12236 GIMPLE_* codes. */
7740abd8 12237bool
b2c0e0b7 12238make_gimple_omp_edges (basic_block bb, struct omp_region **region,
12239 int *region_idx)
7740abd8 12240{
12241 gimple last = last_stmt (bb);
12242 enum gimple_code code = gimple_code (last);
12243 struct omp_region *cur_region = *region;
12244 bool fallthru = false;
12245
12246 switch (code)
12247 {
12248 case GIMPLE_OMP_PARALLEL:
12249 case GIMPLE_OMP_TASK:
12250 case GIMPLE_OMP_FOR:
12251 case GIMPLE_OMP_SINGLE:
12252 case GIMPLE_OMP_TEAMS:
12253 case GIMPLE_OMP_MASTER:
12254 case GIMPLE_OMP_TASKGROUP:
12255 case GIMPLE_OMP_ORDERED:
12256 case GIMPLE_OMP_CRITICAL:
12257 case GIMPLE_OMP_SECTION:
12258 cur_region = new_omp_region (bb, code, cur_region);
12259 fallthru = true;
12260 break;
12261
12262 case GIMPLE_OMP_TARGET:
12263 cur_region = new_omp_region (bb, code, cur_region);
12264 fallthru = true;
ca4c3545 12265 switch (gimple_omp_target_kind (last))
12266 {
12267 case GF_OMP_TARGET_KIND_REGION:
12268 case GF_OMP_TARGET_KIND_DATA:
12269 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
12270 case GF_OMP_TARGET_KIND_OACC_KERNELS:
12271 case GF_OMP_TARGET_KIND_OACC_DATA:
12272 break;
12273 case GF_OMP_TARGET_KIND_UPDATE:
12274 case GF_OMP_TARGET_KIND_OACC_UPDATE:
12275 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
12276 cur_region = cur_region->outer;
12277 break;
12278 default:
12279 gcc_unreachable ();
12280 }
7740abd8 12281 break;
12282
12283 case GIMPLE_OMP_SECTIONS:
12284 cur_region = new_omp_region (bb, code, cur_region);
12285 fallthru = true;
12286 break;
12287
12288 case GIMPLE_OMP_SECTIONS_SWITCH:
12289 fallthru = false;
12290 break;
12291
12292 case GIMPLE_OMP_ATOMIC_LOAD:
12293 case GIMPLE_OMP_ATOMIC_STORE:
12294 fallthru = true;
12295 break;
12296
12297 case GIMPLE_OMP_RETURN:
12298 /* In the case of a GIMPLE_OMP_SECTION, the edge will go
12299 somewhere other than the next block. This will be
12300 created later. */
12301 cur_region->exit = bb;
b25f70fd 12302 if (cur_region->type == GIMPLE_OMP_TASK)
12303 /* Add an edge corresponding to not scheduling the task
12304 immediately. */
12305 make_edge (cur_region->entry, bb, EDGE_ABNORMAL);
7740abd8 12306 fallthru = cur_region->type != GIMPLE_OMP_SECTION;
12307 cur_region = cur_region->outer;
12308 break;
12309
12310 case GIMPLE_OMP_CONTINUE:
12311 cur_region->cont = bb;
12312 switch (cur_region->type)
12313 {
12314 case GIMPLE_OMP_FOR:
12315 /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
12316 succs edges as abnormal to prevent splitting
12317 them. */
12318 single_succ_edge (cur_region->entry)->flags |= EDGE_ABNORMAL;
12319 /* Make the loopback edge. */
12320 make_edge (bb, single_succ (cur_region->entry),
12321 EDGE_ABNORMAL);
12322
12323 /* Create an edge from GIMPLE_OMP_FOR to exit, which
12324 corresponds to the case that the body of the loop
12325 is not executed at all. */
12326 make_edge (cur_region->entry, bb->next_bb, EDGE_ABNORMAL);
12327 make_edge (bb, bb->next_bb, EDGE_FALLTHRU | EDGE_ABNORMAL);
12328 fallthru = false;
12329 break;
12330
12331 case GIMPLE_OMP_SECTIONS:
12332 /* Wire up the edges into and out of the nested sections. */
12333 {
12334 basic_block switch_bb = single_succ (cur_region->entry);
12335
12336 struct omp_region *i;
12337 for (i = cur_region->inner; i ; i = i->next)
12338 {
12339 gcc_assert (i->type == GIMPLE_OMP_SECTION);
12340 make_edge (switch_bb, i->entry, 0);
12341 make_edge (i->exit, bb, EDGE_FALLTHRU);
12342 }
12343
12344 /* Make the loopback edge to the block with
12345 GIMPLE_OMP_SECTIONS_SWITCH. */
12346 make_edge (bb, switch_bb, 0);
12347
12348 /* Make the edge from the switch to exit. */
12349 make_edge (switch_bb, bb->next_bb, 0);
12350 fallthru = false;
12351 }
12352 break;
12353
b25f70fd 12354 case GIMPLE_OMP_TASK:
12355 fallthru = true;
12356 break;
12357
7740abd8 12358 default:
12359 gcc_unreachable ();
12360 }
12361 break;
12362
12363 default:
12364 gcc_unreachable ();
12365 }
12366
12367 if (*region != cur_region)
b2c0e0b7 12368 {
12369 *region = cur_region;
12370 if (cur_region)
12371 *region_idx = cur_region->entry->index;
12372 else
12373 *region_idx = 0;
12374 }
7740abd8 12375
12376 return fallthru;
12377}
12378
bfec3452 12379static unsigned int
12380diagnose_omp_structured_block_errors (void)
1e8e9920 12381{
1e8e9920 12382 struct walk_stmt_info wi;
bfec3452 12383 gimple_seq body = gimple_body (current_function_decl);
1e8e9920 12384
12385 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
12386
12387 memset (&wi, 0, sizeof (wi));
75a70cf9 12388 walk_gimple_seq (body, diagnose_sb_1, NULL, &wi);
1e8e9920 12389
12390 memset (&wi, 0, sizeof (wi));
1e8e9920 12391 wi.want_locations = true;
e3a19533 12392 walk_gimple_seq_mod (&body, diagnose_sb_2, NULL, &wi);
12393
12394 gimple_set_body (current_function_decl, body);
1e8e9920 12395
12396 splay_tree_delete (all_labels);
12397 all_labels = NULL;
12398
bfec3452 12399 return 0;
1e8e9920 12400}
12401
cbe8bda8 12402namespace {
12403
12404const pass_data pass_data_diagnose_omp_blocks =
12405{
12406 GIMPLE_PASS, /* type */
12407 "*diagnose_omp_blocks", /* name */
12408 OPTGROUP_NONE, /* optinfo_flags */
cbe8bda8 12409 TV_NONE, /* tv_id */
12410 PROP_gimple_any, /* properties_required */
12411 0, /* properties_provided */
12412 0, /* properties_destroyed */
12413 0, /* todo_flags_start */
12414 0, /* todo_flags_finish */
bfec3452 12415};
12416
cbe8bda8 12417class pass_diagnose_omp_blocks : public gimple_opt_pass
12418{
12419public:
9af5ce0c 12420 pass_diagnose_omp_blocks (gcc::context *ctxt)
12421 : gimple_opt_pass (pass_data_diagnose_omp_blocks, ctxt)
cbe8bda8 12422 {}
12423
12424 /* opt_pass methods: */
ca4c3545 12425 virtual bool gate (function *)
12426 {
12427 return flag_cilkplus || flag_openacc || flag_openmp;
12428 }
65b0537f 12429 virtual unsigned int execute (function *)
12430 {
12431 return diagnose_omp_structured_block_errors ();
12432 }
cbe8bda8 12433
12434}; // class pass_diagnose_omp_blocks
12435
12436} // anon namespace
12437
12438gimple_opt_pass *
12439make_pass_diagnose_omp_blocks (gcc::context *ctxt)
12440{
12441 return new pass_diagnose_omp_blocks (ctxt);
12442}
d09768a4 12443\f
12444/* SIMD clone supporting code. */
12445
12446/* Allocate a fresh `simd_clone' and return it. NARGS is the number
12447 of arguments to reserve space for. */
12448
12449static struct cgraph_simd_clone *
12450simd_clone_struct_alloc (int nargs)
12451{
12452 struct cgraph_simd_clone *clone_info;
12453 size_t len = (sizeof (struct cgraph_simd_clone)
12454 + nargs * sizeof (struct cgraph_simd_clone_arg));
12455 clone_info = (struct cgraph_simd_clone *)
ea7d8c7a 12456 ggc_internal_cleared_alloc (len);
d09768a4 12457 return clone_info;
12458}
12459
12460/* Make a copy of the `struct cgraph_simd_clone' in FROM to TO. */
12461
12462static inline void
12463simd_clone_struct_copy (struct cgraph_simd_clone *to,
12464 struct cgraph_simd_clone *from)
12465{
12466 memcpy (to, from, (sizeof (struct cgraph_simd_clone)
46c0fd4b 12467 + ((from->nargs - from->inbranch)
12468 * sizeof (struct cgraph_simd_clone_arg))));
d09768a4 12469}
12470
12471/* Return vector of parameter types of function FNDECL. This uses
12472 TYPE_ARG_TYPES if available, otherwise falls back to types of
12473 DECL_ARGUMENTS types. */
12474
12475vec<tree>
12476simd_clone_vector_of_formal_parm_types (tree fndecl)
12477{
12478 if (TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
12479 return ipa_get_vector_of_formal_parm_types (TREE_TYPE (fndecl));
12480 vec<tree> args = ipa_get_vector_of_formal_parms (fndecl);
12481 unsigned int i;
12482 tree arg;
12483 FOR_EACH_VEC_ELT (args, i, arg)
12484 args[i] = TREE_TYPE (args[i]);
12485 return args;
12486}
12487
12488/* Given a simd function in NODE, extract the simd specific
12489 information from the OMP clauses passed in CLAUSES, and return
12490 the struct cgraph_simd_clone * if it should be cloned. *INBRANCH_SPECIFIED
12491 is set to TRUE if the `inbranch' or `notinbranch' clause specified,
12492 otherwise set to FALSE. */
12493
12494static struct cgraph_simd_clone *
12495simd_clone_clauses_extract (struct cgraph_node *node, tree clauses,
12496 bool *inbranch_specified)
12497{
12498 vec<tree> args = simd_clone_vector_of_formal_parm_types (node->decl);
12499 tree t;
12500 int n;
12501 *inbranch_specified = false;
12502
12503 n = args.length ();
12504 if (n > 0 && args.last () == void_type_node)
12505 n--;
12506
12507 /* To distinguish from an OpenMP simd clone, Cilk Plus functions to
12508 be cloned have a distinctive artificial label in addition to "omp
12509 declare simd". */
12510 bool cilk_clone
a89e6c15 12511 = (flag_cilkplus
74acc703 12512 && lookup_attribute ("cilk simd function",
d09768a4 12513 DECL_ATTRIBUTES (node->decl)));
12514
12515 /* Allocate one more than needed just in case this is an in-branch
12516 clone which will require a mask argument. */
12517 struct cgraph_simd_clone *clone_info = simd_clone_struct_alloc (n + 1);
12518 clone_info->nargs = n;
12519 clone_info->cilk_elemental = cilk_clone;
12520
12521 if (!clauses)
12522 {
12523 args.release ();
12524 return clone_info;
12525 }
12526 clauses = TREE_VALUE (clauses);
12527 if (!clauses || TREE_CODE (clauses) != OMP_CLAUSE)
12528 return clone_info;
12529
12530 for (t = clauses; t; t = OMP_CLAUSE_CHAIN (t))
12531 {
12532 switch (OMP_CLAUSE_CODE (t))
12533 {
12534 case OMP_CLAUSE_INBRANCH:
12535 clone_info->inbranch = 1;
12536 *inbranch_specified = true;
12537 break;
12538 case OMP_CLAUSE_NOTINBRANCH:
12539 clone_info->inbranch = 0;
12540 *inbranch_specified = true;
12541 break;
12542 case OMP_CLAUSE_SIMDLEN:
12543 clone_info->simdlen
12544 = TREE_INT_CST_LOW (OMP_CLAUSE_SIMDLEN_EXPR (t));
12545 break;
12546 case OMP_CLAUSE_LINEAR:
12547 {
12548 tree decl = OMP_CLAUSE_DECL (t);
12549 tree step = OMP_CLAUSE_LINEAR_STEP (t);
12550 int argno = TREE_INT_CST_LOW (decl);
12551 if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (t))
12552 {
12553 clone_info->args[argno].arg_type
12554 = SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP;
12555 clone_info->args[argno].linear_step = tree_to_shwi (step);
12556 gcc_assert (clone_info->args[argno].linear_step >= 0
12557 && clone_info->args[argno].linear_step < n);
12558 }
12559 else
12560 {
12561 if (POINTER_TYPE_P (args[argno]))
12562 step = fold_convert (ssizetype, step);
12563 if (!tree_fits_shwi_p (step))
12564 {
12565 warning_at (OMP_CLAUSE_LOCATION (t), 0,
12566 "ignoring large linear step");
12567 args.release ();
12568 return NULL;
12569 }
12570 else if (integer_zerop (step))
12571 {
12572 warning_at (OMP_CLAUSE_LOCATION (t), 0,
12573 "ignoring zero linear step");
12574 args.release ();
12575 return NULL;
12576 }
12577 else
12578 {
12579 clone_info->args[argno].arg_type
12580 = SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP;
12581 clone_info->args[argno].linear_step = tree_to_shwi (step);
12582 }
12583 }
12584 break;
12585 }
12586 case OMP_CLAUSE_UNIFORM:
12587 {
12588 tree decl = OMP_CLAUSE_DECL (t);
12589 int argno = tree_to_uhwi (decl);
12590 clone_info->args[argno].arg_type
12591 = SIMD_CLONE_ARG_TYPE_UNIFORM;
12592 break;
12593 }
12594 case OMP_CLAUSE_ALIGNED:
12595 {
12596 tree decl = OMP_CLAUSE_DECL (t);
12597 int argno = tree_to_uhwi (decl);
12598 clone_info->args[argno].alignment
12599 = TREE_INT_CST_LOW (OMP_CLAUSE_ALIGNED_ALIGNMENT (t));
12600 break;
12601 }
12602 default:
12603 break;
12604 }
12605 }
12606 args.release ();
12607 return clone_info;
12608}
12609
12610/* Given a SIMD clone in NODE, calculate the characteristic data
12611 type and return the coresponding type. The characteristic data
12612 type is computed as described in the Intel Vector ABI. */
12613
12614static tree
12615simd_clone_compute_base_data_type (struct cgraph_node *node,
12616 struct cgraph_simd_clone *clone_info)
12617{
12618 tree type = integer_type_node;
12619 tree fndecl = node->decl;
12620
12621 /* a) For non-void function, the characteristic data type is the
12622 return type. */
12623 if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) != VOID_TYPE)
12624 type = TREE_TYPE (TREE_TYPE (fndecl));
12625
12626 /* b) If the function has any non-uniform, non-linear parameters,
12627 then the characteristic data type is the type of the first
12628 such parameter. */
12629 else
12630 {
12631 vec<tree> map = simd_clone_vector_of_formal_parm_types (fndecl);
12632 for (unsigned int i = 0; i < clone_info->nargs; ++i)
12633 if (clone_info->args[i].arg_type == SIMD_CLONE_ARG_TYPE_VECTOR)
12634 {
12635 type = map[i];
12636 break;
12637 }
12638 map.release ();
12639 }
12640
12641 /* c) If the characteristic data type determined by a) or b) above
12642 is struct, union, or class type which is pass-by-value (except
12643 for the type that maps to the built-in complex data type), the
12644 characteristic data type is int. */
12645 if (RECORD_OR_UNION_TYPE_P (type)
12646 && !aggregate_value_p (type, NULL)
12647 && TREE_CODE (type) != COMPLEX_TYPE)
12648 return integer_type_node;
12649
12650 /* d) If none of the above three classes is applicable, the
12651 characteristic data type is int. */
12652
12653 return type;
12654
12655 /* e) For Intel Xeon Phi native and offload compilation, if the
12656 resulting characteristic data type is 8-bit or 16-bit integer
12657 data type, the characteristic data type is int. */
12658 /* Well, we don't handle Xeon Phi yet. */
12659}
12660
12661static tree
12662simd_clone_mangle (struct cgraph_node *node,
12663 struct cgraph_simd_clone *clone_info)
12664{
12665 char vecsize_mangle = clone_info->vecsize_mangle;
12666 char mask = clone_info->inbranch ? 'M' : 'N';
12667 unsigned int simdlen = clone_info->simdlen;
12668 unsigned int n;
12669 pretty_printer pp;
12670
12671 gcc_assert (vecsize_mangle && simdlen);
12672
12673 pp_string (&pp, "_ZGV");
12674 pp_character (&pp, vecsize_mangle);
12675 pp_character (&pp, mask);
12676 pp_decimal_int (&pp, simdlen);
12677
12678 for (n = 0; n < clone_info->nargs; ++n)
12679 {
12680 struct cgraph_simd_clone_arg arg = clone_info->args[n];
12681
12682 if (arg.arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM)
12683 pp_character (&pp, 'u');
12684 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
12685 {
12686 gcc_assert (arg.linear_step != 0);
12687 pp_character (&pp, 'l');
12688 if (arg.linear_step > 1)
12689 pp_unsigned_wide_integer (&pp, arg.linear_step);
12690 else if (arg.linear_step < 0)
12691 {
12692 pp_character (&pp, 'n');
12693 pp_unsigned_wide_integer (&pp, (-(unsigned HOST_WIDE_INT)
12694 arg.linear_step));
12695 }
12696 }
12697 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP)
12698 {
12699 pp_character (&pp, 's');
12700 pp_unsigned_wide_integer (&pp, arg.linear_step);
12701 }
12702 else
12703 pp_character (&pp, 'v');
12704 if (arg.alignment)
12705 {
12706 pp_character (&pp, 'a');
12707 pp_decimal_int (&pp, arg.alignment);
12708 }
12709 }
12710
12711 pp_underscore (&pp);
4e4baaad 12712 const char *str = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl));
12713 if (*str == '*')
12714 ++str;
12715 pp_string (&pp, str);
12716 str = pp_formatted_text (&pp);
d09768a4 12717
12718 /* If there already is a SIMD clone with the same mangled name, don't
12719 add another one. This can happen e.g. for
12720 #pragma omp declare simd
12721 #pragma omp declare simd simdlen(8)
12722 int foo (int, int);
12723 if the simdlen is assumed to be 8 for the first one, etc. */
12724 for (struct cgraph_node *clone = node->simd_clones; clone;
12725 clone = clone->simdclone->next_clone)
12726 if (strcmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (clone->decl)),
12727 str) == 0)
12728 return NULL_TREE;
12729
12730 return get_identifier (str);
12731}
12732
12733/* Create a simd clone of OLD_NODE and return it. */
12734
12735static struct cgraph_node *
12736simd_clone_create (struct cgraph_node *old_node)
12737{
12738 struct cgraph_node *new_node;
12739 if (old_node->definition)
ea0695f9 12740 {
415d1b9a 12741 if (!old_node->has_gimple_body_p ())
ea0695f9 12742 return NULL;
415d1b9a 12743 old_node->get_body ();
12744 new_node = old_node->create_version_clone_with_body (vNULL, NULL, NULL,
12745 false, NULL, NULL,
12746 "simdclone");
ea0695f9 12747 }
d09768a4 12748 else
12749 {
12750 tree old_decl = old_node->decl;
12751 tree new_decl = copy_node (old_node->decl);
12752 DECL_NAME (new_decl) = clone_function_name (old_decl, "simdclone");
12753 SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl));
12754 SET_DECL_RTL (new_decl, NULL);
12755 DECL_STATIC_CONSTRUCTOR (new_decl) = 0;
12756 DECL_STATIC_DESTRUCTOR (new_decl) = 0;
415d1b9a 12757 new_node = old_node->create_version_clone (new_decl, vNULL, NULL);
35ee1c66 12758 symtab->call_cgraph_insertion_hooks (new_node);
d09768a4 12759 }
12760 if (new_node == NULL)
12761 return new_node;
12762
12763 TREE_PUBLIC (new_node->decl) = TREE_PUBLIC (old_node->decl);
12764
12765 /* The function cgraph_function_versioning () will force the new
12766 symbol local. Undo this, and inherit external visability from
12767 the old node. */
12768 new_node->local.local = old_node->local.local;
12769 new_node->externally_visible = old_node->externally_visible;
12770
12771 return new_node;
12772}
12773
12774/* Adjust the return type of the given function to its appropriate
12775 vector counterpart. Returns a simd array to be used throughout the
12776 function as a return value. */
12777
12778static tree
12779simd_clone_adjust_return_type (struct cgraph_node *node)
12780{
12781 tree fndecl = node->decl;
12782 tree orig_rettype = TREE_TYPE (TREE_TYPE (fndecl));
12783 unsigned int veclen;
12784 tree t;
12785
12786 /* Adjust the function return type. */
12787 if (orig_rettype == void_type_node)
12788 return NULL_TREE;
12789 TREE_TYPE (fndecl) = build_distinct_type_copy (TREE_TYPE (fndecl));
fdf7662c 12790 t = TREE_TYPE (TREE_TYPE (fndecl));
12791 if (INTEGRAL_TYPE_P (t) || POINTER_TYPE_P (t))
d09768a4 12792 veclen = node->simdclone->vecsize_int;
12793 else
12794 veclen = node->simdclone->vecsize_float;
fdf7662c 12795 veclen /= GET_MODE_BITSIZE (TYPE_MODE (t));
d09768a4 12796 if (veclen > node->simdclone->simdlen)
12797 veclen = node->simdclone->simdlen;
fdf7662c 12798 if (POINTER_TYPE_P (t))
12799 t = pointer_sized_int_node;
d09768a4 12800 if (veclen == node->simdclone->simdlen)
fdf7662c 12801 t = build_vector_type (t, node->simdclone->simdlen);
d09768a4 12802 else
12803 {
fdf7662c 12804 t = build_vector_type (t, veclen);
d09768a4 12805 t = build_array_type_nelts (t, node->simdclone->simdlen / veclen);
d09768a4 12806 }
fdf7662c 12807 TREE_TYPE (TREE_TYPE (fndecl)) = t;
d09768a4 12808 if (!node->definition)
12809 return NULL_TREE;
12810
12811 t = DECL_RESULT (fndecl);
12812 /* Adjust the DECL_RESULT. */
12813 gcc_assert (TREE_TYPE (t) != void_type_node);
12814 TREE_TYPE (t) = TREE_TYPE (TREE_TYPE (fndecl));
12815 relayout_decl (t);
12816
12817 tree atype = build_array_type_nelts (orig_rettype,
12818 node->simdclone->simdlen);
12819 if (veclen != node->simdclone->simdlen)
12820 return build1 (VIEW_CONVERT_EXPR, atype, t);
12821
12822 /* Set up a SIMD array to use as the return value. */
12823 tree retval = create_tmp_var_raw (atype, "retval");
12824 gimple_add_tmp_var (retval);
12825 return retval;
12826}
12827
12828/* Each vector argument has a corresponding array to be used locally
12829 as part of the eventual loop. Create such temporary array and
12830 return it.
12831
12832 PREFIX is the prefix to be used for the temporary.
12833
12834 TYPE is the inner element type.
12835
12836 SIMDLEN is the number of elements. */
12837
12838static tree
12839create_tmp_simd_array (const char *prefix, tree type, int simdlen)
12840{
12841 tree atype = build_array_type_nelts (type, simdlen);
12842 tree avar = create_tmp_var_raw (atype, prefix);
12843 gimple_add_tmp_var (avar);
12844 return avar;
12845}
12846
12847/* Modify the function argument types to their corresponding vector
12848 counterparts if appropriate. Also, create one array for each simd
12849 argument to be used locally when using the function arguments as
12850 part of the loop.
12851
12852 NODE is the function whose arguments are to be adjusted.
12853
12854 Returns an adjustment vector that will be filled describing how the
12855 argument types will be adjusted. */
12856
12857static ipa_parm_adjustment_vec
12858simd_clone_adjust_argument_types (struct cgraph_node *node)
12859{
12860 vec<tree> args;
12861 ipa_parm_adjustment_vec adjustments;
12862
12863 if (node->definition)
12864 args = ipa_get_vector_of_formal_parms (node->decl);
12865 else
12866 args = simd_clone_vector_of_formal_parm_types (node->decl);
12867 adjustments.create (args.length ());
12868 unsigned i, j, veclen;
12869 struct ipa_parm_adjustment adj;
12870 for (i = 0; i < node->simdclone->nargs; ++i)
12871 {
12872 memset (&adj, 0, sizeof (adj));
12873 tree parm = args[i];
12874 tree parm_type = node->definition ? TREE_TYPE (parm) : parm;
12875 adj.base_index = i;
12876 adj.base = parm;
12877
12878 node->simdclone->args[i].orig_arg = node->definition ? parm : NULL_TREE;
12879 node->simdclone->args[i].orig_type = parm_type;
12880
12881 if (node->simdclone->args[i].arg_type != SIMD_CLONE_ARG_TYPE_VECTOR)
12882 {
12883 /* No adjustment necessary for scalar arguments. */
12884 adj.op = IPA_PARM_OP_COPY;
12885 }
12886 else
12887 {
12888 if (INTEGRAL_TYPE_P (parm_type) || POINTER_TYPE_P (parm_type))
12889 veclen = node->simdclone->vecsize_int;
12890 else
12891 veclen = node->simdclone->vecsize_float;
12892 veclen /= GET_MODE_BITSIZE (TYPE_MODE (parm_type));
12893 if (veclen > node->simdclone->simdlen)
12894 veclen = node->simdclone->simdlen;
12895 adj.arg_prefix = "simd";
fdf7662c 12896 if (POINTER_TYPE_P (parm_type))
12897 adj.type = build_vector_type (pointer_sized_int_node, veclen);
12898 else
12899 adj.type = build_vector_type (parm_type, veclen);
d09768a4 12900 node->simdclone->args[i].vector_type = adj.type;
12901 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
12902 {
12903 adjustments.safe_push (adj);
12904 if (j == veclen)
12905 {
12906 memset (&adj, 0, sizeof (adj));
12907 adj.op = IPA_PARM_OP_NEW;
12908 adj.arg_prefix = "simd";
12909 adj.base_index = i;
12910 adj.type = node->simdclone->args[i].vector_type;
12911 }
12912 }
12913
12914 if (node->definition)
12915 node->simdclone->args[i].simd_array
12916 = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm)),
12917 parm_type, node->simdclone->simdlen);
12918 }
12919 adjustments.safe_push (adj);
12920 }
12921
12922 if (node->simdclone->inbranch)
12923 {
12924 tree base_type
12925 = simd_clone_compute_base_data_type (node->simdclone->origin,
12926 node->simdclone);
12927
12928 memset (&adj, 0, sizeof (adj));
12929 adj.op = IPA_PARM_OP_NEW;
12930 adj.arg_prefix = "mask";
12931
12932 adj.base_index = i;
12933 if (INTEGRAL_TYPE_P (base_type) || POINTER_TYPE_P (base_type))
12934 veclen = node->simdclone->vecsize_int;
12935 else
12936 veclen = node->simdclone->vecsize_float;
12937 veclen /= GET_MODE_BITSIZE (TYPE_MODE (base_type));
12938 if (veclen > node->simdclone->simdlen)
12939 veclen = node->simdclone->simdlen;
fdf7662c 12940 if (POINTER_TYPE_P (base_type))
12941 adj.type = build_vector_type (pointer_sized_int_node, veclen);
12942 else
12943 adj.type = build_vector_type (base_type, veclen);
d09768a4 12944 adjustments.safe_push (adj);
12945
12946 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
12947 adjustments.safe_push (adj);
12948
12949 /* We have previously allocated one extra entry for the mask. Use
12950 it and fill it. */
12951 struct cgraph_simd_clone *sc = node->simdclone;
12952 sc->nargs++;
12953 if (node->definition)
12954 {
12955 sc->args[i].orig_arg
12956 = build_decl (UNKNOWN_LOCATION, PARM_DECL, NULL, base_type);
12957 sc->args[i].simd_array
12958 = create_tmp_simd_array ("mask", base_type, sc->simdlen);
12959 }
12960 sc->args[i].orig_type = base_type;
12961 sc->args[i].arg_type = SIMD_CLONE_ARG_TYPE_MASK;
12962 }
12963
12964 if (node->definition)
12965 ipa_modify_formal_parameters (node->decl, adjustments);
12966 else
12967 {
12968 tree new_arg_types = NULL_TREE, new_reversed;
12969 bool last_parm_void = false;
12970 if (args.length () > 0 && args.last () == void_type_node)
12971 last_parm_void = true;
12972
12973 gcc_assert (TYPE_ARG_TYPES (TREE_TYPE (node->decl)));
12974 j = adjustments.length ();
12975 for (i = 0; i < j; i++)
12976 {
12977 struct ipa_parm_adjustment *adj = &adjustments[i];
12978 tree ptype;
12979 if (adj->op == IPA_PARM_OP_COPY)
12980 ptype = args[adj->base_index];
12981 else
12982 ptype = adj->type;
12983 new_arg_types = tree_cons (NULL_TREE, ptype, new_arg_types);
12984 }
12985 new_reversed = nreverse (new_arg_types);
12986 if (last_parm_void)
12987 {
12988 if (new_reversed)
12989 TREE_CHAIN (new_arg_types) = void_list_node;
12990 else
12991 new_reversed = void_list_node;
12992 }
12993
12994 tree new_type = build_distinct_type_copy (TREE_TYPE (node->decl));
12995 TYPE_ARG_TYPES (new_type) = new_reversed;
12996 TREE_TYPE (node->decl) = new_type;
12997
12998 adjustments.release ();
12999 }
13000 args.release ();
13001 return adjustments;
13002}
13003
13004/* Initialize and copy the function arguments in NODE to their
13005 corresponding local simd arrays. Returns a fresh gimple_seq with
13006 the instruction sequence generated. */
13007
13008static gimple_seq
13009simd_clone_init_simd_arrays (struct cgraph_node *node,
13010 ipa_parm_adjustment_vec adjustments)
13011{
13012 gimple_seq seq = NULL;
13013 unsigned i = 0, j = 0, k;
13014
13015 for (tree arg = DECL_ARGUMENTS (node->decl);
13016 arg;
13017 arg = DECL_CHAIN (arg), i++, j++)
13018 {
13019 if (adjustments[j].op == IPA_PARM_OP_COPY)
13020 continue;
13021
13022 node->simdclone->args[i].vector_arg = arg;
13023
13024 tree array = node->simdclone->args[i].simd_array;
13025 if (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg)) == node->simdclone->simdlen)
13026 {
13027 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
13028 tree ptr = build_fold_addr_expr (array);
13029 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
13030 build_int_cst (ptype, 0));
13031 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
13032 gimplify_and_add (t, &seq);
13033 }
13034 else
13035 {
13036 unsigned int simdlen = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg));
13037 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
13038 for (k = 0; k < node->simdclone->simdlen; k += simdlen)
13039 {
13040 tree ptr = build_fold_addr_expr (array);
13041 int elemsize;
13042 if (k)
13043 {
13044 arg = DECL_CHAIN (arg);
13045 j++;
13046 }
13047 elemsize
13048 = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg))));
13049 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
13050 build_int_cst (ptype, k * elemsize));
13051 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
13052 gimplify_and_add (t, &seq);
13053 }
13054 }
13055 }
13056 return seq;
13057}
13058
13059/* Callback info for ipa_simd_modify_stmt_ops below. */
13060
13061struct modify_stmt_info {
13062 ipa_parm_adjustment_vec adjustments;
13063 gimple stmt;
13064 /* True if the parent statement was modified by
13065 ipa_simd_modify_stmt_ops. */
13066 bool modified;
13067};
13068
13069/* Callback for walk_gimple_op.
13070
13071 Adjust operands from a given statement as specified in the
13072 adjustments vector in the callback data. */
13073
13074static tree
13075ipa_simd_modify_stmt_ops (tree *tp, int *walk_subtrees, void *data)
13076{
13077 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
2d78e89f 13078 struct modify_stmt_info *info = (struct modify_stmt_info *) wi->info;
13079 tree *orig_tp = tp;
13080 if (TREE_CODE (*tp) == ADDR_EXPR)
13081 tp = &TREE_OPERAND (*tp, 0);
13082 struct ipa_parm_adjustment *cand = NULL;
13083 if (TREE_CODE (*tp) == PARM_DECL)
13084 cand = ipa_get_adjustment_candidate (&tp, NULL, info->adjustments, true);
13085 else
d09768a4 13086 {
d09768a4 13087 if (TYPE_P (*tp))
13088 *walk_subtrees = 0;
d09768a4 13089 }
d09768a4 13090
2d78e89f 13091 tree repl = NULL_TREE;
13092 if (cand)
13093 repl = unshare_expr (cand->new_decl);
13094 else
d09768a4 13095 {
2d78e89f 13096 if (tp != orig_tp)
13097 {
13098 *walk_subtrees = 0;
13099 bool modified = info->modified;
13100 info->modified = false;
13101 walk_tree (tp, ipa_simd_modify_stmt_ops, wi, wi->pset);
13102 if (!info->modified)
13103 {
13104 info->modified = modified;
13105 return NULL_TREE;
13106 }
13107 info->modified = modified;
13108 repl = *tp;
13109 }
13110 else
13111 return NULL_TREE;
d09768a4 13112 }
2d78e89f 13113
13114 if (tp != orig_tp)
d09768a4 13115 {
2d78e89f 13116 repl = build_fold_addr_expr (repl);
9c1dd4d9 13117 gimple stmt;
13118 if (is_gimple_debug (info->stmt))
13119 {
13120 tree vexpr = make_node (DEBUG_EXPR_DECL);
13121 stmt = gimple_build_debug_source_bind (vexpr, repl, NULL);
13122 DECL_ARTIFICIAL (vexpr) = 1;
13123 TREE_TYPE (vexpr) = TREE_TYPE (repl);
13124 DECL_MODE (vexpr) = TYPE_MODE (TREE_TYPE (repl));
13125 repl = vexpr;
13126 }
13127 else
13128 {
f9e245b2 13129 stmt = gimple_build_assign (make_ssa_name (TREE_TYPE (repl)), repl);
9c1dd4d9 13130 repl = gimple_assign_lhs (stmt);
13131 }
2d78e89f 13132 gimple_stmt_iterator gsi = gsi_for_stmt (info->stmt);
d09768a4 13133 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
2d78e89f 13134 *orig_tp = repl;
d09768a4 13135 }
2d78e89f 13136 else if (!useless_type_conversion_p (TREE_TYPE (*tp), TREE_TYPE (repl)))
d09768a4 13137 {
13138 tree vce = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (*tp), repl);
13139 *tp = vce;
13140 }
13141 else
13142 *tp = repl;
13143
13144 info->modified = true;
d09768a4 13145 return NULL_TREE;
13146}
13147
13148/* Traverse the function body and perform all modifications as
13149 described in ADJUSTMENTS. At function return, ADJUSTMENTS will be
13150 modified such that the replacement/reduction value will now be an
13151 offset into the corresponding simd_array.
13152
13153 This function will replace all function argument uses with their
13154 corresponding simd array elements, and ajust the return values
13155 accordingly. */
13156
13157static void
13158ipa_simd_modify_function_body (struct cgraph_node *node,
13159 ipa_parm_adjustment_vec adjustments,
13160 tree retval_array, tree iter)
13161{
13162 basic_block bb;
2d78e89f 13163 unsigned int i, j, l;
d09768a4 13164
13165 /* Re-use the adjustments array, but this time use it to replace
13166 every function argument use to an offset into the corresponding
13167 simd_array. */
13168 for (i = 0, j = 0; i < node->simdclone->nargs; ++i, ++j)
13169 {
13170 if (!node->simdclone->args[i].vector_arg)
13171 continue;
13172
13173 tree basetype = TREE_TYPE (node->simdclone->args[i].orig_arg);
13174 tree vectype = TREE_TYPE (node->simdclone->args[i].vector_arg);
13175 adjustments[j].new_decl
13176 = build4 (ARRAY_REF,
13177 basetype,
13178 node->simdclone->args[i].simd_array,
13179 iter,
13180 NULL_TREE, NULL_TREE);
13181 if (adjustments[j].op == IPA_PARM_OP_NONE
13182 && TYPE_VECTOR_SUBPARTS (vectype) < node->simdclone->simdlen)
13183 j += node->simdclone->simdlen / TYPE_VECTOR_SUBPARTS (vectype) - 1;
13184 }
13185
2d78e89f 13186 l = adjustments.length ();
13187 for (i = 1; i < num_ssa_names; i++)
13188 {
13189 tree name = ssa_name (i);
13190 if (name
13191 && SSA_NAME_VAR (name)
13192 && TREE_CODE (SSA_NAME_VAR (name)) == PARM_DECL)
13193 {
13194 for (j = 0; j < l; j++)
13195 if (SSA_NAME_VAR (name) == adjustments[j].base
13196 && adjustments[j].new_decl)
13197 {
13198 tree base_var;
13199 if (adjustments[j].new_ssa_base == NULL_TREE)
13200 {
13201 base_var
13202 = copy_var_decl (adjustments[j].base,
13203 DECL_NAME (adjustments[j].base),
13204 TREE_TYPE (adjustments[j].base));
13205 adjustments[j].new_ssa_base = base_var;
13206 }
13207 else
13208 base_var = adjustments[j].new_ssa_base;
13209 if (SSA_NAME_IS_DEFAULT_DEF (name))
13210 {
13211 bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
13212 gimple_stmt_iterator gsi = gsi_after_labels (bb);
13213 tree new_decl = unshare_expr (adjustments[j].new_decl);
13214 set_ssa_default_def (cfun, adjustments[j].base, NULL_TREE);
13215 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
13216 SSA_NAME_IS_DEFAULT_DEF (name) = 0;
13217 gimple stmt = gimple_build_assign (name, new_decl);
13218 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
13219 }
13220 else
13221 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
13222 }
13223 }
13224 }
13225
d09768a4 13226 struct modify_stmt_info info;
13227 info.adjustments = adjustments;
13228
13229 FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl))
13230 {
13231 gimple_stmt_iterator gsi;
13232
13233 gsi = gsi_start_bb (bb);
13234 while (!gsi_end_p (gsi))
13235 {
13236 gimple stmt = gsi_stmt (gsi);
13237 info.stmt = stmt;
13238 struct walk_stmt_info wi;
13239
13240 memset (&wi, 0, sizeof (wi));
13241 info.modified = false;
13242 wi.info = &info;
13243 walk_gimple_op (stmt, ipa_simd_modify_stmt_ops, &wi);
13244
1a91d914 13245 if (greturn *return_stmt = dyn_cast <greturn *> (stmt))
d09768a4 13246 {
1a91d914 13247 tree retval = gimple_return_retval (return_stmt);
d09768a4 13248 if (!retval)
13249 {
13250 gsi_remove (&gsi, true);
13251 continue;
13252 }
13253
13254 /* Replace `return foo' with `retval_array[iter] = foo'. */
13255 tree ref = build4 (ARRAY_REF, TREE_TYPE (retval),
13256 retval_array, iter, NULL, NULL);
13257 stmt = gimple_build_assign (ref, retval);
13258 gsi_replace (&gsi, stmt, true);
13259 info.modified = true;
13260 }
13261
13262 if (info.modified)
13263 {
13264 update_stmt (stmt);
13265 if (maybe_clean_eh_stmt (stmt))
13266 gimple_purge_dead_eh_edges (gimple_bb (stmt));
13267 }
13268 gsi_next (&gsi);
13269 }
13270 }
13271}
13272
13273/* Adjust the argument types in NODE to their appropriate vector
13274 counterparts. */
13275
13276static void
13277simd_clone_adjust (struct cgraph_node *node)
13278{
13279 push_cfun (DECL_STRUCT_FUNCTION (node->decl));
13280
13281 targetm.simd_clone.adjust (node);
13282
13283 tree retval = simd_clone_adjust_return_type (node);
13284 ipa_parm_adjustment_vec adjustments
13285 = simd_clone_adjust_argument_types (node);
13286
13287 push_gimplify_context ();
13288
13289 gimple_seq seq = simd_clone_init_simd_arrays (node, adjustments);
13290
13291 /* Adjust all uses of vector arguments accordingly. Adjust all
13292 return values accordingly. */
13293 tree iter = create_tmp_var (unsigned_type_node, "iter");
f9e245b2 13294 tree iter1 = make_ssa_name (iter);
13295 tree iter2 = make_ssa_name (iter);
d09768a4 13296 ipa_simd_modify_function_body (node, adjustments, retval, iter1);
13297
13298 /* Initialize the iteration variable. */
13299 basic_block entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
13300 basic_block body_bb = split_block_after_labels (entry_bb)->dest;
13301 gimple_stmt_iterator gsi = gsi_after_labels (entry_bb);
13302 /* Insert the SIMD array and iv initialization at function
13303 entry. */
13304 gsi_insert_seq_before (&gsi, seq, GSI_NEW_STMT);
13305
13306 pop_gimplify_context (NULL);
13307
13308 /* Create a new BB right before the original exit BB, to hold the
13309 iteration increment and the condition/branch. */
13310 basic_block orig_exit = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), 0)->src;
13311 basic_block incr_bb = create_empty_bb (orig_exit);
343ee723 13312 add_bb_to_loop (incr_bb, body_bb->loop_father);
d09768a4 13313 /* The succ of orig_exit was EXIT_BLOCK_PTR_FOR_FN (cfun), with an empty
13314 flag. Set it now to be a FALLTHRU_EDGE. */
13315 gcc_assert (EDGE_COUNT (orig_exit->succs) == 1);
13316 EDGE_SUCC (orig_exit, 0)->flags |= EDGE_FALLTHRU;
13317 for (unsigned i = 0;
13318 i < EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds); ++i)
13319 {
13320 edge e = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), i);
13321 redirect_edge_succ (e, incr_bb);
13322 }
13323 edge e = make_edge (incr_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
13324 e->probability = REG_BR_PROB_BASE;
13325 gsi = gsi_last_bb (incr_bb);
e9cf809e 13326 gimple g = gimple_build_assign (iter2, PLUS_EXPR, iter1,
13327 build_int_cst (unsigned_type_node, 1));
d09768a4 13328 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13329
13330 /* Mostly annotate the loop for the vectorizer (the rest is done below). */
13331 struct loop *loop = alloc_loop ();
4c73695b 13332 cfun->has_force_vectorize_loops = true;
d09768a4 13333 loop->safelen = node->simdclone->simdlen;
4c73695b 13334 loop->force_vectorize = true;
d09768a4 13335 loop->header = body_bb;
d09768a4 13336
13337 /* Branch around the body if the mask applies. */
13338 if (node->simdclone->inbranch)
13339 {
13340 gimple_stmt_iterator gsi = gsi_last_bb (loop->header);
13341 tree mask_array
13342 = node->simdclone->args[node->simdclone->nargs - 1].simd_array;
f9e245b2 13343 tree mask = make_ssa_name (TREE_TYPE (TREE_TYPE (mask_array)));
d09768a4 13344 tree aref = build4 (ARRAY_REF,
13345 TREE_TYPE (TREE_TYPE (mask_array)),
13346 mask_array, iter1,
13347 NULL, NULL);
13348 g = gimple_build_assign (mask, aref);
13349 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13350 int bitsize = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (aref)));
13351 if (!INTEGRAL_TYPE_P (TREE_TYPE (aref)))
13352 {
13353 aref = build1 (VIEW_CONVERT_EXPR,
13354 build_nonstandard_integer_type (bitsize, 0), mask);
f9e245b2 13355 mask = make_ssa_name (TREE_TYPE (aref));
d09768a4 13356 g = gimple_build_assign (mask, aref);
13357 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13358 }
13359
13360 g = gimple_build_cond (EQ_EXPR, mask, build_zero_cst (TREE_TYPE (mask)),
13361 NULL, NULL);
13362 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13363 make_edge (loop->header, incr_bb, EDGE_TRUE_VALUE);
13364 FALLTHRU_EDGE (loop->header)->flags = EDGE_FALSE_VALUE;
13365 }
13366
13367 /* Generate the condition. */
13368 g = gimple_build_cond (LT_EXPR,
13369 iter2,
13370 build_int_cst (unsigned_type_node,
13371 node->simdclone->simdlen),
13372 NULL, NULL);
13373 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13374 e = split_block (incr_bb, gsi_stmt (gsi));
13375 basic_block latch_bb = e->dest;
343ee723 13376 basic_block new_exit_bb;
4302d619 13377 new_exit_bb = split_block_after_labels (latch_bb)->dest;
d09768a4 13378 loop->latch = latch_bb;
13379
13380 redirect_edge_succ (FALLTHRU_EDGE (latch_bb), body_bb);
13381
13382 make_edge (incr_bb, new_exit_bb, EDGE_FALSE_VALUE);
13383 /* The successor of incr_bb is already pointing to latch_bb; just
13384 change the flags.
13385 make_edge (incr_bb, latch_bb, EDGE_TRUE_VALUE); */
13386 FALLTHRU_EDGE (incr_bb)->flags = EDGE_TRUE_VALUE;
13387
1a91d914 13388 gphi *phi = create_phi_node (iter1, body_bb);
d09768a4 13389 edge preheader_edge = find_edge (entry_bb, body_bb);
13390 edge latch_edge = single_succ_edge (latch_bb);
13391 add_phi_arg (phi, build_zero_cst (unsigned_type_node), preheader_edge,
13392 UNKNOWN_LOCATION);
13393 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
13394
13395 /* Generate the new return. */
13396 gsi = gsi_last_bb (new_exit_bb);
13397 if (retval
13398 && TREE_CODE (retval) == VIEW_CONVERT_EXPR
13399 && TREE_CODE (TREE_OPERAND (retval, 0)) == RESULT_DECL)
13400 retval = TREE_OPERAND (retval, 0);
13401 else if (retval)
13402 {
13403 retval = build1 (VIEW_CONVERT_EXPR,
13404 TREE_TYPE (TREE_TYPE (node->decl)),
13405 retval);
13406 retval = force_gimple_operand_gsi (&gsi, retval, true, NULL,
13407 false, GSI_CONTINUE_LINKING);
13408 }
13409 g = gimple_build_return (retval);
13410 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13411
13412 /* Handle aligned clauses by replacing default defs of the aligned
13413 uniform args with __builtin_assume_aligned (arg_N(D), alignment)
13414 lhs. Handle linear by adding PHIs. */
13415 for (unsigned i = 0; i < node->simdclone->nargs; i++)
97a82d40 13416 if (node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
13417 && (TREE_ADDRESSABLE (node->simdclone->args[i].orig_arg)
13418 || !is_gimple_reg_type
13419 (TREE_TYPE (node->simdclone->args[i].orig_arg))))
13420 {
13421 tree orig_arg = node->simdclone->args[i].orig_arg;
13422 if (is_gimple_reg_type (TREE_TYPE (orig_arg)))
13423 iter1 = make_ssa_name (TREE_TYPE (orig_arg));
13424 else
13425 {
13426 iter1 = create_tmp_var_raw (TREE_TYPE (orig_arg));
13427 gimple_add_tmp_var (iter1);
13428 }
13429 gsi = gsi_after_labels (entry_bb);
13430 g = gimple_build_assign (iter1, orig_arg);
13431 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
13432 gsi = gsi_after_labels (body_bb);
13433 g = gimple_build_assign (orig_arg, iter1);
13434 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
13435 }
13436 else if (node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
13437 && DECL_BY_REFERENCE (node->simdclone->args[i].orig_arg)
13438 && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
13439 == REFERENCE_TYPE
13440 && TREE_ADDRESSABLE
13441 (TREE_TYPE (TREE_TYPE (node->simdclone->args[i].orig_arg))))
13442 {
13443 tree orig_arg = node->simdclone->args[i].orig_arg;
13444 tree def = ssa_default_def (cfun, orig_arg);
13445 if (def && !has_zero_uses (def))
13446 {
13447 iter1 = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (orig_arg)));
13448 gimple_add_tmp_var (iter1);
13449 gsi = gsi_after_labels (entry_bb);
13450 g = gimple_build_assign (iter1, build_simple_mem_ref (def));
13451 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
13452 gsi = gsi_after_labels (body_bb);
13453 g = gimple_build_assign (build_simple_mem_ref (def), iter1);
13454 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
13455 }
13456 }
13457 else if (node->simdclone->args[i].alignment
13458 && node->simdclone->args[i].arg_type
13459 == SIMD_CLONE_ARG_TYPE_UNIFORM
13460 && (node->simdclone->args[i].alignment
13461 & (node->simdclone->args[i].alignment - 1)) == 0
13462 && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
13463 == POINTER_TYPE)
d09768a4 13464 {
13465 unsigned int alignment = node->simdclone->args[i].alignment;
13466 tree orig_arg = node->simdclone->args[i].orig_arg;
13467 tree def = ssa_default_def (cfun, orig_arg);
6db33a3d 13468 if (def && !has_zero_uses (def))
d09768a4 13469 {
13470 tree fn = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
13471 gimple_seq seq = NULL;
13472 bool need_cvt = false;
1a91d914 13473 gcall *call
d09768a4 13474 = gimple_build_call (fn, 2, def, size_int (alignment));
13475 g = call;
13476 if (!useless_type_conversion_p (TREE_TYPE (orig_arg),
13477 ptr_type_node))
13478 need_cvt = true;
f9e245b2 13479 tree t = make_ssa_name (need_cvt ? ptr_type_node : orig_arg);
d09768a4 13480 gimple_call_set_lhs (g, t);
13481 gimple_seq_add_stmt_without_update (&seq, g);
13482 if (need_cvt)
13483 {
f9e245b2 13484 t = make_ssa_name (orig_arg);
e9cf809e 13485 g = gimple_build_assign (t, NOP_EXPR, gimple_call_lhs (g));
d09768a4 13486 gimple_seq_add_stmt_without_update (&seq, g);
13487 }
13488 gsi_insert_seq_on_edge_immediate
13489 (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)), seq);
13490
13491 entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
13492 int freq = compute_call_stmt_bb_frequency (current_function_decl,
13493 entry_bb);
415d1b9a 13494 node->create_edge (cgraph_node::get_create (fn),
13495 call, entry_bb->count, freq);
d09768a4 13496
13497 imm_use_iterator iter;
13498 use_operand_p use_p;
13499 gimple use_stmt;
13500 tree repl = gimple_get_lhs (g);
13501 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
13502 if (is_gimple_debug (use_stmt) || use_stmt == call)
13503 continue;
13504 else
13505 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
13506 SET_USE (use_p, repl);
13507 }
13508 }
13509 else if (node->simdclone->args[i].arg_type
13510 == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
13511 {
13512 tree orig_arg = node->simdclone->args[i].orig_arg;
d09768a4 13513 gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
13514 || POINTER_TYPE_P (TREE_TYPE (orig_arg)));
97a82d40 13515 tree def = NULL_TREE;
13516 if (TREE_ADDRESSABLE (orig_arg))
13517 {
13518 def = make_ssa_name (TREE_TYPE (orig_arg));
13519 iter1 = make_ssa_name (TREE_TYPE (orig_arg));
13520 iter2 = make_ssa_name (TREE_TYPE (orig_arg));
13521 gsi = gsi_after_labels (entry_bb);
13522 g = gimple_build_assign (def, orig_arg);
13523 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
13524 }
13525 else
13526 {
13527 def = ssa_default_def (cfun, orig_arg);
13528 if (!def || has_zero_uses (def))
13529 def = NULL_TREE;
13530 else
13531 {
13532 iter1 = make_ssa_name (orig_arg);
13533 iter2 = make_ssa_name (orig_arg);
13534 }
13535 }
13536 if (def)
d09768a4 13537 {
d09768a4 13538 phi = create_phi_node (iter1, body_bb);
13539 add_phi_arg (phi, def, preheader_edge, UNKNOWN_LOCATION);
13540 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
13541 enum tree_code code = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
13542 ? PLUS_EXPR : POINTER_PLUS_EXPR;
13543 tree addtype = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
13544 ? TREE_TYPE (orig_arg) : sizetype;
13545 tree addcst
13546 = build_int_cst (addtype, node->simdclone->args[i].linear_step);
e9cf809e 13547 g = gimple_build_assign (iter2, code, iter1, addcst);
d09768a4 13548 gsi = gsi_last_bb (incr_bb);
13549 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
13550
13551 imm_use_iterator iter;
13552 use_operand_p use_p;
13553 gimple use_stmt;
97a82d40 13554 if (TREE_ADDRESSABLE (orig_arg))
13555 {
13556 gsi = gsi_after_labels (body_bb);
13557 g = gimple_build_assign (orig_arg, iter1);
13558 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
13559 }
13560 else
13561 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
13562 if (use_stmt == phi)
13563 continue;
13564 else
13565 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
13566 SET_USE (use_p, iter1);
d09768a4 13567 }
13568 }
13569
13570 calculate_dominance_info (CDI_DOMINATORS);
13571 add_loop (loop, loop->header->loop_father);
13572 update_ssa (TODO_update_ssa);
13573
13574 pop_cfun ();
13575}
13576
13577/* If the function in NODE is tagged as an elemental SIMD function,
13578 create the appropriate SIMD clones. */
13579
13580static void
13581expand_simd_clones (struct cgraph_node *node)
13582{
d09768a4 13583 tree attr = lookup_attribute ("omp declare simd",
13584 DECL_ATTRIBUTES (node->decl));
ea0695f9 13585 if (attr == NULL_TREE
13586 || node->global.inlined_to
13587 || lookup_attribute ("noclone", DECL_ATTRIBUTES (node->decl)))
d09768a4 13588 return;
ea0695f9 13589
d09768a4 13590 /* Ignore
13591 #pragma omp declare simd
13592 extern int foo ();
13593 in C, there we don't know the argument types at all. */
13594 if (!node->definition
13595 && TYPE_ARG_TYPES (TREE_TYPE (node->decl)) == NULL_TREE)
13596 return;
13597
13598 do
13599 {
13600 /* Start with parsing the "omp declare simd" attribute(s). */
13601 bool inbranch_clause_specified;
13602 struct cgraph_simd_clone *clone_info
13603 = simd_clone_clauses_extract (node, TREE_VALUE (attr),
13604 &inbranch_clause_specified);
13605 if (clone_info == NULL)
13606 continue;
13607
13608 int orig_simdlen = clone_info->simdlen;
13609 tree base_type = simd_clone_compute_base_data_type (node, clone_info);
13610 /* The target can return 0 (no simd clones should be created),
13611 1 (just one ISA of simd clones should be created) or higher
13612 count of ISA variants. In that case, clone_info is initialized
13613 for the first ISA variant. */
13614 int count
13615 = targetm.simd_clone.compute_vecsize_and_simdlen (node, clone_info,
13616 base_type, 0);
13617 if (count == 0)
13618 continue;
13619
13620 /* Loop over all COUNT ISA variants, and if !INBRANCH_CLAUSE_SPECIFIED,
13621 also create one inbranch and one !inbranch clone of it. */
13622 for (int i = 0; i < count * 2; i++)
13623 {
13624 struct cgraph_simd_clone *clone = clone_info;
13625 if (inbranch_clause_specified && (i & 1) != 0)
13626 continue;
13627
13628 if (i != 0)
13629 {
13630 clone = simd_clone_struct_alloc (clone_info->nargs
d09768a4 13631 + ((i & 1) != 0));
13632 simd_clone_struct_copy (clone, clone_info);
13633 /* Undo changes targetm.simd_clone.compute_vecsize_and_simdlen
13634 and simd_clone_adjust_argument_types did to the first
13635 clone's info. */
13636 clone->nargs -= clone_info->inbranch;
13637 clone->simdlen = orig_simdlen;
13638 /* And call the target hook again to get the right ISA. */
13639 targetm.simd_clone.compute_vecsize_and_simdlen (node, clone,
13640 base_type,
13641 i / 2);
13642 if ((i & 1) != 0)
13643 clone->inbranch = 1;
13644 }
13645
13646 /* simd_clone_mangle might fail if such a clone has been created
13647 already. */
13648 tree id = simd_clone_mangle (node, clone);
13649 if (id == NULL_TREE)
13650 continue;
13651
13652 /* Only when we are sure we want to create the clone actually
13653 clone the function (or definitions) or create another
13654 extern FUNCTION_DECL (for prototypes without definitions). */
13655 struct cgraph_node *n = simd_clone_create (node);
13656 if (n == NULL)
13657 continue;
13658
13659 n->simdclone = clone;
13660 clone->origin = node;
13661 clone->next_clone = NULL;
13662 if (node->simd_clones == NULL)
13663 {
13664 clone->prev_clone = n;
13665 node->simd_clones = n;
13666 }
13667 else
13668 {
13669 clone->prev_clone = node->simd_clones->simdclone->prev_clone;
13670 clone->prev_clone->simdclone->next_clone = n;
13671 node->simd_clones->simdclone->prev_clone = n;
13672 }
35ee1c66 13673 symtab->change_decl_assembler_name (n->decl, id);
d09768a4 13674 /* And finally adjust the return type, parameters and for
13675 definitions also function body. */
13676 if (node->definition)
13677 simd_clone_adjust (n);
13678 else
13679 {
13680 simd_clone_adjust_return_type (n);
13681 simd_clone_adjust_argument_types (n);
13682 }
13683 }
13684 }
13685 while ((attr = lookup_attribute ("omp declare simd", TREE_CHAIN (attr))));
13686}
13687
13688/* Entry point for IPA simd clone creation pass. */
13689
13690static unsigned int
13691ipa_omp_simd_clone (void)
13692{
13693 struct cgraph_node *node;
13694 FOR_EACH_FUNCTION (node)
13695 expand_simd_clones (node);
13696 return 0;
13697}
13698
13699namespace {
13700
13701const pass_data pass_data_omp_simd_clone =
13702{
13703 SIMPLE_IPA_PASS, /* type */
13704 "simdclone", /* name */
13705 OPTGROUP_NONE, /* optinfo_flags */
d09768a4 13706 TV_NONE, /* tv_id */
13707 ( PROP_ssa | PROP_cfg ), /* properties_required */
13708 0, /* properties_provided */
13709 0, /* properties_destroyed */
13710 0, /* todo_flags_start */
13711 0, /* todo_flags_finish */
13712};
13713
13714class pass_omp_simd_clone : public simple_ipa_opt_pass
13715{
13716public:
13717 pass_omp_simd_clone(gcc::context *ctxt)
13718 : simple_ipa_opt_pass(pass_data_omp_simd_clone, ctxt)
13719 {}
13720
13721 /* opt_pass methods: */
31315c24 13722 virtual bool gate (function *);
65b0537f 13723 virtual unsigned int execute (function *) { return ipa_omp_simd_clone (); }
d09768a4 13724};
13725
31315c24 13726bool
13727pass_omp_simd_clone::gate (function *)
13728{
13729 return ((flag_openmp || flag_openmp_simd
13730 || flag_cilkplus
13731 || (in_lto_p && !flag_wpa))
13732 && (targetm.simd_clone.compute_vecsize_and_simdlen != NULL));
13733}
13734
d09768a4 13735} // anon namespace
13736
13737simple_ipa_opt_pass *
13738make_pass_omp_simd_clone (gcc::context *ctxt)
13739{
13740 return new pass_omp_simd_clone (ctxt);
13741}
cbe8bda8 13742
dccabdd1 13743/* Helper function for omp_finish_file routine. Takes decls from V_DECLS and
13744 adds their addresses and sizes to constructor-vector V_CTOR. */
13745static void
13746add_decls_addresses_to_decl_constructor (vec<tree, va_gc> *v_decls,
13747 vec<constructor_elt, va_gc> *v_ctor)
13748{
13749 unsigned len = vec_safe_length (v_decls);
13750 for (unsigned i = 0; i < len; i++)
13751 {
13752 tree it = (*v_decls)[i];
13753 bool is_function = TREE_CODE (it) != VAR_DECL;
13754
13755 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE, build_fold_addr_expr (it));
13756 if (!is_function)
13757 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE,
13758 fold_convert (const_ptr_type_node,
13759 DECL_SIZE_UNIT (it)));
13760 }
13761}
13762
13763/* Create new symbols containing (address, size) pairs for global variables,
13764 marked with "omp declare target" attribute, as well as addresses for the
ca4c3545 13765 functions, which are outlined offloading regions. */
dccabdd1 13766void
13767omp_finish_file (void)
13768{
13769 unsigned num_funcs = vec_safe_length (offload_funcs);
13770 unsigned num_vars = vec_safe_length (offload_vars);
13771
13772 if (num_funcs == 0 && num_vars == 0)
13773 return;
13774
13775 if (targetm_common.have_named_sections)
13776 {
13777 vec<constructor_elt, va_gc> *v_f, *v_v;
13778 vec_alloc (v_f, num_funcs);
13779 vec_alloc (v_v, num_vars * 2);
13780
13781 add_decls_addresses_to_decl_constructor (offload_funcs, v_f);
13782 add_decls_addresses_to_decl_constructor (offload_vars, v_v);
13783
13784 tree vars_decl_type = build_array_type_nelts (pointer_sized_int_node,
13785 num_vars * 2);
13786 tree funcs_decl_type = build_array_type_nelts (pointer_sized_int_node,
13787 num_funcs);
13788 TYPE_ALIGN (vars_decl_type) = TYPE_ALIGN (pointer_sized_int_node);
13789 TYPE_ALIGN (funcs_decl_type) = TYPE_ALIGN (pointer_sized_int_node);
13790 tree ctor_v = build_constructor (vars_decl_type, v_v);
13791 tree ctor_f = build_constructor (funcs_decl_type, v_f);
13792 TREE_CONSTANT (ctor_v) = TREE_CONSTANT (ctor_f) = 1;
13793 TREE_STATIC (ctor_v) = TREE_STATIC (ctor_f) = 1;
13794 tree funcs_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
13795 get_identifier (".offload_func_table"),
13796 funcs_decl_type);
13797 tree vars_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
13798 get_identifier (".offload_var_table"),
13799 vars_decl_type);
13800 TREE_STATIC (funcs_decl) = TREE_STATIC (vars_decl) = 1;
13801 /* Do not align tables more than TYPE_ALIGN (pointer_sized_int_node),
13802 otherwise a joint table in a binary will contain padding between
13803 tables from multiple object files. */
13804 DECL_USER_ALIGN (funcs_decl) = DECL_USER_ALIGN (vars_decl) = 1;
13805 DECL_ALIGN (funcs_decl) = TYPE_ALIGN (funcs_decl_type);
13806 DECL_ALIGN (vars_decl) = TYPE_ALIGN (vars_decl_type);
13807 DECL_INITIAL (funcs_decl) = ctor_f;
13808 DECL_INITIAL (vars_decl) = ctor_v;
13809 set_decl_section_name (funcs_decl, OFFLOAD_FUNC_TABLE_SECTION_NAME);
13810 set_decl_section_name (vars_decl, OFFLOAD_VAR_TABLE_SECTION_NAME);
13811
13812 varpool_node::finalize_decl (vars_decl);
13813 varpool_node::finalize_decl (funcs_decl);
7114ebdd 13814 }
dccabdd1 13815 else
13816 {
13817 for (unsigned i = 0; i < num_funcs; i++)
13818 {
13819 tree it = (*offload_funcs)[i];
13820 targetm.record_offload_symbol (it);
13821 }
13822 for (unsigned i = 0; i < num_vars; i++)
13823 {
13824 tree it = (*offload_vars)[i];
13825 targetm.record_offload_symbol (it);
13826 }
13827 }
13828}
13829
1e8e9920 13830#include "gt-omp-low.h"