]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/omp-low.c
PR c++/66571
[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"
28#include "tm.h"
b20a8bb4 29#include "alias.h"
30#include "symtab.h"
1e8e9920 31#include "tree.h"
b20a8bb4 32#include "fold-const.h"
9ed99284 33#include "stringpool.h"
34#include "stor-layout.h"
1e8e9920 35#include "rtl.h"
94ea8568 36#include "predict.h"
94ea8568 37#include "hard-reg-set.h"
94ea8568 38#include "function.h"
39#include "dominance.h"
40#include "cfg.h"
41#include "cfganal.h"
bc61cadb 42#include "basic-block.h"
43#include "tree-ssa-alias.h"
44#include "internal-fn.h"
45#include "gimple-fold.h"
46#include "gimple-expr.h"
75a70cf9 47#include "gimple.h"
a8783bee 48#include "gimplify.h"
dcf1a1ec 49#include "gimple-iterator.h"
e795d6e1 50#include "gimplify-me.h"
dcf1a1ec 51#include "gimple-walk.h"
75a70cf9 52#include "tree-iterator.h"
1e8e9920 53#include "tree-inline.h"
54#include "langhooks.h"
852f689e 55#include "diagnostic-core.h"
073c1fd5 56#include "gimple-ssa.h"
1140c305 57#include "plugin-api.h"
58#include "ipa-ref.h"
073c1fd5 59#include "cgraph.h"
60#include "tree-cfg.h"
61#include "tree-phinodes.h"
62#include "ssa-iterators.h"
63#include "tree-ssanames.h"
64#include "tree-into-ssa.h"
d53441c8 65#include "flags.h"
d53441c8 66#include "insn-config.h"
67#include "expmed.h"
68#include "dojump.h"
69#include "explow.h"
70#include "calls.h"
71#include "emit-rtl.h"
72#include "varasm.h"
73#include "stmt.h"
9ed99284 74#include "expr.h"
073c1fd5 75#include "tree-dfa.h"
69ee5dbb 76#include "tree-ssa.h"
1e8e9920 77#include "tree-pass.h"
1e8e9920 78#include "except.h"
e3022db7 79#include "splay-tree.h"
34517c64 80#include "insn-codes.h"
cb7f680b 81#include "optabs.h"
82#include "cfgloop.h"
3d483a94 83#include "target.h"
dccabdd1 84#include "common/common-target.h"
7740abd8 85#include "omp-low.h"
424a4a92 86#include "gimple-low.h"
87#include "tree-cfgcleanup.h"
d09768a4 88#include "pretty-print.h"
1140c305 89#include "alloc-pool.h"
2cc80ac3 90#include "symbol-summary.h"
d09768a4 91#include "ipa-prop.h"
e797f49f 92#include "tree-nested.h"
d09768a4 93#include "tree-eh.h"
40750995 94#include "cilk.h"
b0c5e347 95#include "context.h"
dccabdd1 96#include "lto-section-names.h"
ca4c3545 97#include "gomp-constants.h"
1e8e9920 98
75a70cf9 99
ca4c3545 100/* Lowering of OMP parallel and workshare constructs proceeds in two
1e8e9920 101 phases. The first phase scans the function looking for OMP statements
102 and then for variables that must be replaced to satisfy data sharing
103 clauses. The second phase expands code for the constructs, as well as
334ec2d8 104 re-gimplifying things when variables have been replaced with complex
1e8e9920 105 expressions.
106
d134bccc 107 Final code generation is done by pass_expand_omp. The flowgraph is
ca4c3545 108 scanned for regions which are then moved to a new
109 function, to be invoked by the thread library, or offloaded. */
1e8e9920 110
ca4c3545 111/* OMP region information. Every parallel and workshare
7740abd8 112 directive is enclosed between two markers, the OMP_* directive
113 and a corresponding OMP_RETURN statement. */
114
115struct omp_region
116{
117 /* The enclosing region. */
118 struct omp_region *outer;
119
120 /* First child region. */
121 struct omp_region *inner;
122
123 /* Next peer region. */
124 struct omp_region *next;
125
126 /* Block containing the omp directive as its last stmt. */
127 basic_block entry;
128
129 /* Block containing the OMP_RETURN as its last stmt. */
130 basic_block exit;
131
132 /* Block containing the OMP_CONTINUE as its last stmt. */
133 basic_block cont;
134
135 /* If this is a combined parallel+workshare region, this is a list
136 of additional arguments needed by the combined parallel+workshare
137 library call. */
138 vec<tree, va_gc> *ws_args;
139
140 /* The code for the omp directive of this region. */
141 enum gimple_code type;
142
143 /* Schedule kind, only used for OMP_FOR type regions. */
144 enum omp_clause_schedule_kind sched_kind;
145
146 /* True if this is a combined parallel+workshare region. */
147 bool is_combined_parallel;
148};
149
ca4c3545 150/* Levels of parallelism as defined by OpenACC. Increasing numbers
151 correspond to deeper loop nesting levels. */
152#define MASK_GANG 1
153#define MASK_WORKER 2
154#define MASK_VECTOR 4
155
1e8e9920 156/* Context structure. Used to store information about each parallel
157 directive in the code. */
158
159typedef struct omp_context
160{
161 /* This field must be at the beginning, as we do "inheritance": Some
162 callback functions for tree-inline.c (e.g., omp_copy_decl)
163 receive a copy_body_data pointer that is up-casted to an
164 omp_context pointer. */
165 copy_body_data cb;
166
167 /* The tree of contexts corresponding to the encountered constructs. */
168 struct omp_context *outer;
75a70cf9 169 gimple stmt;
1e8e9920 170
48e1416a 171 /* Map variables to fields in a structure that allows communication
1e8e9920 172 between sending and receiving threads. */
173 splay_tree field_map;
174 tree record_type;
175 tree sender_decl;
176 tree receiver_decl;
177
fd6481cf 178 /* These are used just by task contexts, if task firstprivate fn is
179 needed. srecord_type is used to communicate from the thread
180 that encountered the task construct to task firstprivate fn,
181 record_type is allocated by GOMP_task, initialized by task firstprivate
182 fn and passed to the task body fn. */
183 splay_tree sfield_map;
184 tree srecord_type;
185
1e8e9920 186 /* A chain of variables to add to the top-level block surrounding the
187 construct. In the case of a parallel, this is in the child function. */
188 tree block_vars;
189
ca4c3545 190 /* A map of reduction pointer variables. For accelerators, each
191 reduction variable is replaced with an array. Each thread, in turn,
192 is assigned to a slot on that array. */
193 splay_tree reduction_map;
194
bc7bff74 195 /* Label to which GOMP_cancel{,llation_point} and explicit and implicit
196 barriers should jump to during omplower pass. */
197 tree cancel_label;
198
1e8e9920 199 /* What to do with variables with implicitly determined sharing
200 attributes. */
201 enum omp_clause_default_kind default_kind;
202
203 /* Nesting depth of this context. Used to beautify error messages re
204 invalid gotos. The outermost ctx is depth 1, with depth 0 being
205 reserved for the main body of the function. */
206 int depth;
207
1e8e9920 208 /* True if this parallel directive is nested within another. */
209 bool is_nested;
bc7bff74 210
211 /* True if this construct can be cancelled. */
212 bool cancellable;
ca4c3545 213
214 /* For OpenACC loops, a mask of gang, worker and vector used at
215 levels below this one. */
216 int gwv_below;
217 /* For OpenACC loops, a mask of gang, worker and vector used at
218 this level and above. For parallel and kernels clauses, a mask
219 indicating which of num_gangs/num_workers/num_vectors was used. */
220 int gwv_this;
1e8e9920 221} omp_context;
222
ca4c3545 223/* A structure holding the elements of:
224 for (V = N1; V cond N2; V += STEP) [...] */
1e8e9920 225
fd6481cf 226struct omp_for_data_loop
227{
228 tree v, n1, n2, step;
229 enum tree_code cond_code;
230};
231
773c5ba7 232/* A structure describing the main elements of a parallel loop. */
1e8e9920 233
773c5ba7 234struct omp_for_data
1e8e9920 235{
fd6481cf 236 struct omp_for_data_loop loop;
75a70cf9 237 tree chunk_size;
1a91d914 238 gomp_for *for_stmt;
fd6481cf 239 tree pre, iter_type;
240 int collapse;
1e8e9920 241 bool have_nowait, have_ordered;
242 enum omp_clause_schedule_kind sched_kind;
fd6481cf 243 struct omp_for_data_loop *loops;
1e8e9920 244};
245
773c5ba7 246
1e8e9920 247static splay_tree all_contexts;
fd6481cf 248static int taskreg_nesting_level;
bc7bff74 249static int target_nesting_level;
7740abd8 250static struct omp_region *root_omp_region;
fd6481cf 251static bitmap task_shared_vars;
37eaded9 252static vec<omp_context *> taskreg_contexts;
1e8e9920 253
ab129075 254static void scan_omp (gimple_seq *, omp_context *);
75a70cf9 255static tree scan_omp_1_op (tree *, int *, void *);
256
257#define WALK_SUBSTMTS \
258 case GIMPLE_BIND: \
259 case GIMPLE_TRY: \
260 case GIMPLE_CATCH: \
261 case GIMPLE_EH_FILTER: \
4c0315d0 262 case GIMPLE_TRANSACTION: \
75a70cf9 263 /* The sub-statements for these should be walked. */ \
264 *handled_ops_p = false; \
265 break;
266
ca4c3545 267/* Helper function to get the name of the array containing the partial
268 reductions for OpenACC reductions. */
269static const char *
270oacc_get_reduction_array_id (tree node)
271{
272 const char *id = IDENTIFIER_POINTER (DECL_NAME (node));
273 int len = strlen ("OACC") + strlen (id);
274 char *temp_name = XALLOCAVEC (char, len + 1);
275 snprintf (temp_name, len + 1, "OACC%s", id);
276 return IDENTIFIER_POINTER (get_identifier (temp_name));
277}
278
279/* Determine the number of threads OpenACC threads used to determine the
280 size of the array of partial reductions. Currently, this is num_gangs
281 * vector_length. This value may be different than GOACC_GET_NUM_THREADS,
282 because it is independed of the device used. */
283
284static tree
285oacc_max_threads (omp_context *ctx)
286{
287 tree nthreads, vector_length, gangs, clauses;
288
289 gangs = fold_convert (sizetype, integer_one_node);
290 vector_length = gangs;
291
292 /* The reduction clause may be nested inside a loop directive.
293 Scan for the innermost vector_length clause. */
294 for (omp_context *oc = ctx; oc; oc = oc->outer)
295 {
296 if (gimple_code (oc->stmt) != GIMPLE_OMP_TARGET
297 || (gimple_omp_target_kind (oc->stmt)
298 != GF_OMP_TARGET_KIND_OACC_PARALLEL))
299 continue;
300
301 clauses = gimple_omp_target_clauses (oc->stmt);
302
303 vector_length = find_omp_clause (clauses, OMP_CLAUSE_VECTOR_LENGTH);
304 if (vector_length)
305 vector_length = fold_convert_loc (OMP_CLAUSE_LOCATION (vector_length),
306 sizetype,
307 OMP_CLAUSE_VECTOR_LENGTH_EXPR
308 (vector_length));
309 else
310 vector_length = fold_convert (sizetype, integer_one_node);
311
312 gangs = find_omp_clause (clauses, OMP_CLAUSE_NUM_GANGS);
313 if (gangs)
314 gangs = fold_convert_loc (OMP_CLAUSE_LOCATION (gangs), sizetype,
315 OMP_CLAUSE_NUM_GANGS_EXPR (gangs));
316 else
317 gangs = fold_convert (sizetype, integer_one_node);
318
319 break;
320 }
321
322 nthreads = fold_build2 (MULT_EXPR, sizetype, gangs, vector_length);
323
324 return nthreads;
325}
326
dccabdd1 327/* Holds offload tables with decls. */
328vec<tree, va_gc> *offload_funcs, *offload_vars;
329
75a70cf9 330/* Convenience function for calling scan_omp_1_op on tree operands. */
331
332static inline tree
333scan_omp_op (tree *tp, omp_context *ctx)
334{
335 struct walk_stmt_info wi;
336
337 memset (&wi, 0, sizeof (wi));
338 wi.info = ctx;
339 wi.want_locations = true;
340
341 return walk_tree (tp, scan_omp_1_op, &wi, NULL);
342}
343
e3a19533 344static void lower_omp (gimple_seq *, omp_context *);
f49d7bb5 345static tree lookup_decl_in_outer_ctx (tree, omp_context *);
346static tree maybe_lookup_decl_in_outer_ctx (tree, omp_context *);
1e8e9920 347
ca4c3545 348/* Find an OMP clause of type KIND within CLAUSES. */
1e8e9920 349
79acaae1 350tree
590c3166 351find_omp_clause (tree clauses, enum omp_clause_code kind)
1e8e9920 352{
353 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
55d6e7cd 354 if (OMP_CLAUSE_CODE (clauses) == kind)
1e8e9920 355 return clauses;
356
357 return NULL_TREE;
358}
359
360/* Return true if CTX is for an omp parallel. */
361
362static inline bool
363is_parallel_ctx (omp_context *ctx)
364{
75a70cf9 365 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL;
1e8e9920 366}
367
773c5ba7 368
fd6481cf 369/* Return true if CTX is for an omp task. */
370
371static inline bool
372is_task_ctx (omp_context *ctx)
373{
75a70cf9 374 return gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
fd6481cf 375}
376
377
378/* Return true if CTX is for an omp parallel or omp task. */
379
380static inline bool
381is_taskreg_ctx (omp_context *ctx)
382{
75a70cf9 383 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL
384 || gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
fd6481cf 385}
386
387
773c5ba7 388/* Return true if REGION is a combined parallel+workshare region. */
1e8e9920 389
390static inline bool
773c5ba7 391is_combined_parallel (struct omp_region *region)
392{
393 return region->is_combined_parallel;
394}
395
396
397/* Extract the header elements of parallel loop FOR_STMT and store
398 them into *FD. */
399
400static void
1a91d914 401extract_omp_for_data (gomp_for *for_stmt, struct omp_for_data *fd,
fd6481cf 402 struct omp_for_data_loop *loops)
773c5ba7 403{
fd6481cf 404 tree t, var, *collapse_iter, *collapse_count;
405 tree count = NULL_TREE, iter_type = long_integer_type_node;
406 struct omp_for_data_loop *loop;
407 int i;
408 struct omp_for_data_loop dummy_loop;
389dd41b 409 location_t loc = gimple_location (for_stmt);
10c55644 410 bool simd = gimple_omp_for_kind (for_stmt) & GF_OMP_FOR_SIMD;
bc7bff74 411 bool distribute = gimple_omp_for_kind (for_stmt)
412 == GF_OMP_FOR_KIND_DISTRIBUTE;
773c5ba7 413
414 fd->for_stmt = for_stmt;
415 fd->pre = NULL;
75a70cf9 416 fd->collapse = gimple_omp_for_collapse (for_stmt);
fd6481cf 417 if (fd->collapse > 1)
418 fd->loops = loops;
419 else
420 fd->loops = &fd->loop;
773c5ba7 421
bc7bff74 422 fd->have_nowait = distribute || simd;
423 fd->have_ordered = false;
773c5ba7 424 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
425 fd->chunk_size = NULL_TREE;
40750995 426 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
427 fd->sched_kind = OMP_CLAUSE_SCHEDULE_CILKFOR;
fd6481cf 428 collapse_iter = NULL;
429 collapse_count = NULL;
773c5ba7 430
75a70cf9 431 for (t = gimple_omp_for_clauses (for_stmt); t ; t = OMP_CLAUSE_CHAIN (t))
55d6e7cd 432 switch (OMP_CLAUSE_CODE (t))
773c5ba7 433 {
434 case OMP_CLAUSE_NOWAIT:
435 fd->have_nowait = true;
436 break;
437 case OMP_CLAUSE_ORDERED:
438 fd->have_ordered = true;
439 break;
440 case OMP_CLAUSE_SCHEDULE:
bc7bff74 441 gcc_assert (!distribute);
773c5ba7 442 fd->sched_kind = OMP_CLAUSE_SCHEDULE_KIND (t);
443 fd->chunk_size = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t);
444 break;
bc7bff74 445 case OMP_CLAUSE_DIST_SCHEDULE:
446 gcc_assert (distribute);
447 fd->chunk_size = OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (t);
448 break;
fd6481cf 449 case OMP_CLAUSE_COLLAPSE:
450 if (fd->collapse > 1)
451 {
452 collapse_iter = &OMP_CLAUSE_COLLAPSE_ITERVAR (t);
453 collapse_count = &OMP_CLAUSE_COLLAPSE_COUNT (t);
454 }
757abb46 455 break;
773c5ba7 456 default:
457 break;
458 }
459
fd6481cf 460 /* FIXME: for now map schedule(auto) to schedule(static).
461 There should be analysis to determine whether all iterations
462 are approximately the same amount of work (then schedule(static)
bde357c8 463 is best) or if it varies (then schedule(dynamic,N) is better). */
fd6481cf 464 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_AUTO)
465 {
466 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
467 gcc_assert (fd->chunk_size == NULL);
468 }
469 gcc_assert (fd->collapse == 1 || collapse_iter != NULL);
773c5ba7 470 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
471 gcc_assert (fd->chunk_size == NULL);
472 else if (fd->chunk_size == NULL)
473 {
474 /* We only need to compute a default chunk size for ordered
475 static loops and dynamic loops. */
fd6481cf 476 if (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
bc7bff74 477 || fd->have_ordered)
773c5ba7 478 fd->chunk_size = (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
479 ? integer_zero_node : integer_one_node;
480 }
fd6481cf 481
482 for (i = 0; i < fd->collapse; i++)
483 {
484 if (fd->collapse == 1)
485 loop = &fd->loop;
486 else if (loops != NULL)
487 loop = loops + i;
488 else
489 loop = &dummy_loop;
490
75a70cf9 491 loop->v = gimple_omp_for_index (for_stmt, i);
fd6481cf 492 gcc_assert (SSA_VAR_P (loop->v));
493 gcc_assert (TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
494 || TREE_CODE (TREE_TYPE (loop->v)) == POINTER_TYPE);
495 var = TREE_CODE (loop->v) == SSA_NAME ? SSA_NAME_VAR (loop->v) : loop->v;
75a70cf9 496 loop->n1 = gimple_omp_for_initial (for_stmt, i);
fd6481cf 497
75a70cf9 498 loop->cond_code = gimple_omp_for_cond (for_stmt, i);
499 loop->n2 = gimple_omp_for_final (for_stmt, i);
fd6481cf 500 switch (loop->cond_code)
501 {
502 case LT_EXPR:
503 case GT_EXPR:
504 break;
f2697631 505 case NE_EXPR:
506 gcc_assert (gimple_omp_for_kind (for_stmt)
40750995 507 == GF_OMP_FOR_KIND_CILKSIMD
508 || (gimple_omp_for_kind (for_stmt)
509 == GF_OMP_FOR_KIND_CILKFOR));
f2697631 510 break;
fd6481cf 511 case LE_EXPR:
512 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
2cc66f2a 513 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, 1);
fd6481cf 514 else
389dd41b 515 loop->n2 = fold_build2_loc (loc,
516 PLUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
fd6481cf 517 build_int_cst (TREE_TYPE (loop->n2), 1));
518 loop->cond_code = LT_EXPR;
519 break;
520 case GE_EXPR:
521 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
2cc66f2a 522 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, -1);
fd6481cf 523 else
389dd41b 524 loop->n2 = fold_build2_loc (loc,
525 MINUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
fd6481cf 526 build_int_cst (TREE_TYPE (loop->n2), 1));
527 loop->cond_code = GT_EXPR;
528 break;
529 default:
530 gcc_unreachable ();
531 }
532
75a70cf9 533 t = gimple_omp_for_incr (for_stmt, i);
fd6481cf 534 gcc_assert (TREE_OPERAND (t, 0) == var);
535 switch (TREE_CODE (t))
536 {
537 case PLUS_EXPR:
fd6481cf 538 loop->step = TREE_OPERAND (t, 1);
539 break;
85d86b55 540 case POINTER_PLUS_EXPR:
541 loop->step = fold_convert (ssizetype, TREE_OPERAND (t, 1));
542 break;
fd6481cf 543 case MINUS_EXPR:
544 loop->step = TREE_OPERAND (t, 1);
389dd41b 545 loop->step = fold_build1_loc (loc,
546 NEGATE_EXPR, TREE_TYPE (loop->step),
fd6481cf 547 loop->step);
548 break;
549 default:
550 gcc_unreachable ();
551 }
552
bc7bff74 553 if (simd
554 || (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
555 && !fd->have_ordered))
3d483a94 556 {
557 if (fd->collapse == 1)
558 iter_type = TREE_TYPE (loop->v);
559 else if (i == 0
560 || TYPE_PRECISION (iter_type)
561 < TYPE_PRECISION (TREE_TYPE (loop->v)))
562 iter_type
563 = build_nonstandard_integer_type
bc7bff74 564 (TYPE_PRECISION (TREE_TYPE (loop->v)), 1);
3d483a94 565 }
566 else if (iter_type != long_long_unsigned_type_node)
fd6481cf 567 {
568 if (POINTER_TYPE_P (TREE_TYPE (loop->v)))
569 iter_type = long_long_unsigned_type_node;
570 else if (TYPE_UNSIGNED (TREE_TYPE (loop->v))
571 && TYPE_PRECISION (TREE_TYPE (loop->v))
572 >= TYPE_PRECISION (iter_type))
573 {
574 tree n;
575
576 if (loop->cond_code == LT_EXPR)
389dd41b 577 n = fold_build2_loc (loc,
578 PLUS_EXPR, TREE_TYPE (loop->v),
fd6481cf 579 loop->n2, loop->step);
580 else
581 n = loop->n1;
582 if (TREE_CODE (n) != INTEGER_CST
583 || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type), n))
584 iter_type = long_long_unsigned_type_node;
585 }
586 else if (TYPE_PRECISION (TREE_TYPE (loop->v))
587 > TYPE_PRECISION (iter_type))
588 {
589 tree n1, n2;
590
591 if (loop->cond_code == LT_EXPR)
592 {
593 n1 = loop->n1;
389dd41b 594 n2 = fold_build2_loc (loc,
595 PLUS_EXPR, TREE_TYPE (loop->v),
fd6481cf 596 loop->n2, loop->step);
597 }
598 else
599 {
389dd41b 600 n1 = fold_build2_loc (loc,
601 MINUS_EXPR, TREE_TYPE (loop->v),
fd6481cf 602 loop->n2, loop->step);
603 n2 = loop->n1;
604 }
605 if (TREE_CODE (n1) != INTEGER_CST
606 || TREE_CODE (n2) != INTEGER_CST
607 || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type), n1)
608 || !tree_int_cst_lt (n2, TYPE_MAX_VALUE (iter_type)))
609 iter_type = long_long_unsigned_type_node;
610 }
611 }
612
613 if (collapse_count && *collapse_count == NULL)
614 {
8e6b4515 615 t = fold_binary (loop->cond_code, boolean_type_node,
616 fold_convert (TREE_TYPE (loop->v), loop->n1),
617 fold_convert (TREE_TYPE (loop->v), loop->n2));
618 if (t && integer_zerop (t))
619 count = build_zero_cst (long_long_unsigned_type_node);
620 else if ((i == 0 || count != NULL_TREE)
621 && TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
622 && TREE_CONSTANT (loop->n1)
623 && TREE_CONSTANT (loop->n2)
624 && TREE_CODE (loop->step) == INTEGER_CST)
fd6481cf 625 {
626 tree itype = TREE_TYPE (loop->v);
627
628 if (POINTER_TYPE_P (itype))
3cea8318 629 itype = signed_type_for (itype);
fd6481cf 630 t = build_int_cst (itype, (loop->cond_code == LT_EXPR ? -1 : 1));
389dd41b 631 t = fold_build2_loc (loc,
632 PLUS_EXPR, itype,
633 fold_convert_loc (loc, itype, loop->step), t);
634 t = fold_build2_loc (loc, PLUS_EXPR, itype, t,
635 fold_convert_loc (loc, itype, loop->n2));
636 t = fold_build2_loc (loc, MINUS_EXPR, itype, t,
637 fold_convert_loc (loc, itype, loop->n1));
fd6481cf 638 if (TYPE_UNSIGNED (itype) && loop->cond_code == GT_EXPR)
389dd41b 639 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype,
640 fold_build1_loc (loc, NEGATE_EXPR, itype, t),
641 fold_build1_loc (loc, NEGATE_EXPR, itype,
642 fold_convert_loc (loc, itype,
643 loop->step)));
fd6481cf 644 else
389dd41b 645 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, t,
646 fold_convert_loc (loc, itype, loop->step));
647 t = fold_convert_loc (loc, long_long_unsigned_type_node, t);
fd6481cf 648 if (count != NULL_TREE)
389dd41b 649 count = fold_build2_loc (loc,
650 MULT_EXPR, long_long_unsigned_type_node,
fd6481cf 651 count, t);
652 else
653 count = t;
654 if (TREE_CODE (count) != INTEGER_CST)
655 count = NULL_TREE;
656 }
8e6b4515 657 else if (count && !integer_zerop (count))
fd6481cf 658 count = NULL_TREE;
659 }
660 }
661
3d483a94 662 if (count
bc7bff74 663 && !simd
664 && (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
665 || fd->have_ordered))
fd6481cf 666 {
667 if (!tree_int_cst_lt (count, TYPE_MAX_VALUE (long_integer_type_node)))
668 iter_type = long_long_unsigned_type_node;
669 else
670 iter_type = long_integer_type_node;
671 }
672 else if (collapse_iter && *collapse_iter != NULL)
673 iter_type = TREE_TYPE (*collapse_iter);
674 fd->iter_type = iter_type;
675 if (collapse_iter && *collapse_iter == NULL)
676 *collapse_iter = create_tmp_var (iter_type, ".iter");
677 if (collapse_count && *collapse_count == NULL)
678 {
679 if (count)
389dd41b 680 *collapse_count = fold_convert_loc (loc, iter_type, count);
fd6481cf 681 else
682 *collapse_count = create_tmp_var (iter_type, ".count");
683 }
684
685 if (fd->collapse > 1)
686 {
687 fd->loop.v = *collapse_iter;
688 fd->loop.n1 = build_int_cst (TREE_TYPE (fd->loop.v), 0);
689 fd->loop.n2 = *collapse_count;
690 fd->loop.step = build_int_cst (TREE_TYPE (fd->loop.v), 1);
691 fd->loop.cond_code = LT_EXPR;
692 }
ca4c3545 693
694 /* For OpenACC loops, force a chunk size of one, as this avoids the default
695 scheduling where several subsequent iterations are being executed by the
696 same thread. */
697 if (gimple_omp_for_kind (for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
698 {
699 gcc_assert (fd->chunk_size == NULL_TREE);
700 fd->chunk_size = build_int_cst (TREE_TYPE (fd->loop.v), 1);
701 }
773c5ba7 702}
703
704
705/* Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB
706 is the immediate dominator of PAR_ENTRY_BB, return true if there
707 are no data dependencies that would prevent expanding the parallel
708 directive at PAR_ENTRY_BB as a combined parallel+workshare region.
709
710 When expanding a combined parallel+workshare region, the call to
711 the child function may need additional arguments in the case of
75a70cf9 712 GIMPLE_OMP_FOR regions. In some cases, these arguments are
713 computed out of variables passed in from the parent to the child
714 via 'struct .omp_data_s'. For instance:
773c5ba7 715
716 #pragma omp parallel for schedule (guided, i * 4)
717 for (j ...)
718
719 Is lowered into:
720
721 # BLOCK 2 (PAR_ENTRY_BB)
722 .omp_data_o.i = i;
723 #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
48e1416a 724
773c5ba7 725 # BLOCK 3 (WS_ENTRY_BB)
726 .omp_data_i = &.omp_data_o;
727 D.1667 = .omp_data_i->i;
728 D.1598 = D.1667 * 4;
729 #pragma omp for schedule (guided, D.1598)
730
731 When we outline the parallel region, the call to the child function
732 'bar.omp_fn.0' will need the value D.1598 in its argument list, but
733 that value is computed *after* the call site. So, in principle we
734 cannot do the transformation.
735
736 To see whether the code in WS_ENTRY_BB blocks the combined
737 parallel+workshare call, we collect all the variables used in the
75a70cf9 738 GIMPLE_OMP_FOR header check whether they appear on the LHS of any
773c5ba7 739 statement in WS_ENTRY_BB. If so, then we cannot emit the combined
740 call.
741
742 FIXME. If we had the SSA form built at this point, we could merely
743 hoist the code in block 3 into block 2 and be done with it. But at
744 this point we don't have dataflow information and though we could
745 hack something up here, it is really not worth the aggravation. */
746
747static bool
f018d957 748workshare_safe_to_combine_p (basic_block ws_entry_bb)
773c5ba7 749{
750 struct omp_for_data fd;
f018d957 751 gimple ws_stmt = last_stmt (ws_entry_bb);
773c5ba7 752
75a70cf9 753 if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
773c5ba7 754 return true;
755
75a70cf9 756 gcc_assert (gimple_code (ws_stmt) == GIMPLE_OMP_FOR);
773c5ba7 757
1a91d914 758 extract_omp_for_data (as_a <gomp_for *> (ws_stmt), &fd, NULL);
fd6481cf 759
760 if (fd.collapse > 1 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
761 return false;
762 if (fd.iter_type != long_integer_type_node)
763 return false;
773c5ba7 764
765 /* FIXME. We give up too easily here. If any of these arguments
766 are not constants, they will likely involve variables that have
767 been mapped into fields of .omp_data_s for sharing with the child
768 function. With appropriate data flow, it would be possible to
769 see through this. */
fd6481cf 770 if (!is_gimple_min_invariant (fd.loop.n1)
771 || !is_gimple_min_invariant (fd.loop.n2)
772 || !is_gimple_min_invariant (fd.loop.step)
773c5ba7 773 || (fd.chunk_size && !is_gimple_min_invariant (fd.chunk_size)))
774 return false;
775
776 return true;
777}
778
779
780/* Collect additional arguments needed to emit a combined
781 parallel+workshare call. WS_STMT is the workshare directive being
782 expanded. */
783
f1f41a6c 784static vec<tree, va_gc> *
bc7bff74 785get_ws_args_for (gimple par_stmt, gimple ws_stmt)
773c5ba7 786{
787 tree t;
389dd41b 788 location_t loc = gimple_location (ws_stmt);
f1f41a6c 789 vec<tree, va_gc> *ws_args;
773c5ba7 790
1a91d914 791 if (gomp_for *for_stmt = dyn_cast <gomp_for *> (ws_stmt))
773c5ba7 792 {
793 struct omp_for_data fd;
bc7bff74 794 tree n1, n2;
773c5ba7 795
1a91d914 796 extract_omp_for_data (for_stmt, &fd, NULL);
bc7bff74 797 n1 = fd.loop.n1;
798 n2 = fd.loop.n2;
799
1a91d914 800 if (gimple_omp_for_combined_into_p (for_stmt))
bc7bff74 801 {
802 tree innerc
803 = find_omp_clause (gimple_omp_parallel_clauses (par_stmt),
804 OMP_CLAUSE__LOOPTEMP_);
805 gcc_assert (innerc);
806 n1 = OMP_CLAUSE_DECL (innerc);
807 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
808 OMP_CLAUSE__LOOPTEMP_);
809 gcc_assert (innerc);
810 n2 = OMP_CLAUSE_DECL (innerc);
811 }
773c5ba7 812
f1f41a6c 813 vec_alloc (ws_args, 3 + (fd.chunk_size != 0));
773c5ba7 814
bc7bff74 815 t = fold_convert_loc (loc, long_integer_type_node, n1);
f1f41a6c 816 ws_args->quick_push (t);
773c5ba7 817
bc7bff74 818 t = fold_convert_loc (loc, long_integer_type_node, n2);
f1f41a6c 819 ws_args->quick_push (t);
773c5ba7 820
414c3a2c 821 t = fold_convert_loc (loc, long_integer_type_node, fd.loop.step);
f1f41a6c 822 ws_args->quick_push (t);
414c3a2c 823
824 if (fd.chunk_size)
825 {
826 t = fold_convert_loc (loc, long_integer_type_node, fd.chunk_size);
f1f41a6c 827 ws_args->quick_push (t);
414c3a2c 828 }
773c5ba7 829
830 return ws_args;
831 }
75a70cf9 832 else if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
773c5ba7 833 {
ac6e3339 834 /* Number of sections is equal to the number of edges from the
75a70cf9 835 GIMPLE_OMP_SECTIONS_SWITCH statement, except for the one to
836 the exit of the sections region. */
837 basic_block bb = single_succ (gimple_bb (ws_stmt));
ac6e3339 838 t = build_int_cst (unsigned_type_node, EDGE_COUNT (bb->succs) - 1);
f1f41a6c 839 vec_alloc (ws_args, 1);
840 ws_args->quick_push (t);
414c3a2c 841 return ws_args;
773c5ba7 842 }
843
844 gcc_unreachable ();
845}
846
847
848/* Discover whether REGION is a combined parallel+workshare region. */
849
850static void
851determine_parallel_type (struct omp_region *region)
1e8e9920 852{
773c5ba7 853 basic_block par_entry_bb, par_exit_bb;
854 basic_block ws_entry_bb, ws_exit_bb;
855
03ed154b 856 if (region == NULL || region->inner == NULL
ac6e3339 857 || region->exit == NULL || region->inner->exit == NULL
858 || region->inner->cont == NULL)
773c5ba7 859 return;
860
861 /* We only support parallel+for and parallel+sections. */
75a70cf9 862 if (region->type != GIMPLE_OMP_PARALLEL
863 || (region->inner->type != GIMPLE_OMP_FOR
864 && region->inner->type != GIMPLE_OMP_SECTIONS))
773c5ba7 865 return;
866
867 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
868 WS_EXIT_BB -> PAR_EXIT_BB. */
61e47ac8 869 par_entry_bb = region->entry;
870 par_exit_bb = region->exit;
871 ws_entry_bb = region->inner->entry;
872 ws_exit_bb = region->inner->exit;
773c5ba7 873
874 if (single_succ (par_entry_bb) == ws_entry_bb
875 && single_succ (ws_exit_bb) == par_exit_bb
f018d957 876 && workshare_safe_to_combine_p (ws_entry_bb)
75a70cf9 877 && (gimple_omp_parallel_combined_p (last_stmt (par_entry_bb))
de7ef844 878 || (last_and_only_stmt (ws_entry_bb)
879 && last_and_only_stmt (par_exit_bb))))
773c5ba7 880 {
bc7bff74 881 gimple par_stmt = last_stmt (par_entry_bb);
75a70cf9 882 gimple ws_stmt = last_stmt (ws_entry_bb);
61e47ac8 883
75a70cf9 884 if (region->inner->type == GIMPLE_OMP_FOR)
773c5ba7 885 {
886 /* If this is a combined parallel loop, we need to determine
887 whether or not to use the combined library calls. There
888 are two cases where we do not apply the transformation:
889 static loops and any kind of ordered loop. In the first
890 case, we already open code the loop so there is no need
891 to do anything else. In the latter case, the combined
892 parallel loop call would still need extra synchronization
893 to implement ordered semantics, so there would not be any
894 gain in using the combined call. */
75a70cf9 895 tree clauses = gimple_omp_for_clauses (ws_stmt);
773c5ba7 896 tree c = find_omp_clause (clauses, OMP_CLAUSE_SCHEDULE);
897 if (c == NULL
898 || OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_STATIC
899 || find_omp_clause (clauses, OMP_CLAUSE_ORDERED))
900 {
901 region->is_combined_parallel = false;
902 region->inner->is_combined_parallel = false;
903 return;
904 }
905 }
906
907 region->is_combined_parallel = true;
908 region->inner->is_combined_parallel = true;
bc7bff74 909 region->ws_args = get_ws_args_for (par_stmt, ws_stmt);
773c5ba7 910 }
1e8e9920 911}
912
773c5ba7 913
1e8e9920 914/* Return true if EXPR is variable sized. */
915
916static inline bool
1f1872fd 917is_variable_sized (const_tree expr)
1e8e9920 918{
919 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr)));
920}
921
922/* Return true if DECL is a reference type. */
923
924static inline bool
925is_reference (tree decl)
926{
927 return lang_hooks.decls.omp_privatize_by_reference (decl);
928}
929
ca4c3545 930/* Return the type of a decl. If the decl is reference type,
931 return its base type. */
932static inline tree
933get_base_type (tree decl)
934{
935 tree type = TREE_TYPE (decl);
936 if (is_reference (decl))
937 type = TREE_TYPE (type);
938 return type;
939}
940
941/* Lookup variables. The "maybe" form
1e8e9920 942 allows for the variable form to not have been entered, otherwise we
943 assert that the variable must have been entered. */
944
945static inline tree
946lookup_decl (tree var, omp_context *ctx)
947{
06ecf488 948 tree *n = ctx->cb.decl_map->get (var);
e3022db7 949 return *n;
1e8e9920 950}
951
952static inline tree
e8a588af 953maybe_lookup_decl (const_tree var, omp_context *ctx)
1e8e9920 954{
06ecf488 955 tree *n = ctx->cb.decl_map->get (const_cast<tree> (var));
e3022db7 956 return n ? *n : NULL_TREE;
1e8e9920 957}
958
959static inline tree
960lookup_field (tree var, omp_context *ctx)
961{
962 splay_tree_node n;
963 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
964 return (tree) n->value;
965}
966
fd6481cf 967static inline tree
968lookup_sfield (tree var, omp_context *ctx)
969{
970 splay_tree_node n;
971 n = splay_tree_lookup (ctx->sfield_map
972 ? ctx->sfield_map : ctx->field_map,
973 (splay_tree_key) var);
974 return (tree) n->value;
975}
976
1e8e9920 977static inline tree
978maybe_lookup_field (tree var, omp_context *ctx)
979{
980 splay_tree_node n;
981 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
982 return n ? (tree) n->value : NULL_TREE;
983}
984
ca4c3545 985static inline tree
986lookup_oacc_reduction (const char *id, omp_context *ctx)
987{
988 splay_tree_node n;
989 n = splay_tree_lookup (ctx->reduction_map, (splay_tree_key) id);
990 return (tree) n->value;
991}
992
993static inline tree
994maybe_lookup_oacc_reduction (tree var, omp_context *ctx)
995{
996 splay_tree_node n = NULL;
997 if (ctx->reduction_map)
998 n = splay_tree_lookup (ctx->reduction_map, (splay_tree_key) var);
999 return n ? (tree) n->value : NULL_TREE;
1000}
1001
e8a588af 1002/* Return true if DECL should be copied by pointer. SHARED_CTX is
1003 the parallel context if DECL is to be shared. */
1e8e9920 1004
1005static bool
fd6481cf 1006use_pointer_for_field (tree decl, omp_context *shared_ctx)
1e8e9920 1007{
1008 if (AGGREGATE_TYPE_P (TREE_TYPE (decl)))
1009 return true;
1010
554f2707 1011 /* We can only use copy-in/copy-out semantics for shared variables
1e8e9920 1012 when we know the value is not accessible from an outer scope. */
e8a588af 1013 if (shared_ctx)
1e8e9920 1014 {
ca4c3545 1015 gcc_assert (!is_gimple_omp_oacc (shared_ctx->stmt));
1016
1e8e9920 1017 /* ??? Trivially accessible from anywhere. But why would we even
1018 be passing an address in this case? Should we simply assert
1019 this to be false, or should we have a cleanup pass that removes
1020 these from the list of mappings? */
1021 if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
1022 return true;
1023
1024 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
1025 without analyzing the expression whether or not its location
1026 is accessible to anyone else. In the case of nested parallel
1027 regions it certainly may be. */
df2c34fc 1028 if (TREE_CODE (decl) != RESULT_DECL && DECL_HAS_VALUE_EXPR_P (decl))
1e8e9920 1029 return true;
1030
1031 /* Do not use copy-in/copy-out for variables that have their
1032 address taken. */
1033 if (TREE_ADDRESSABLE (decl))
1034 return true;
e8a588af 1035
b8214689 1036 /* lower_send_shared_vars only uses copy-in, but not copy-out
1037 for these. */
1038 if (TREE_READONLY (decl)
1039 || ((TREE_CODE (decl) == RESULT_DECL
1040 || TREE_CODE (decl) == PARM_DECL)
1041 && DECL_BY_REFERENCE (decl)))
1042 return false;
1043
e8a588af 1044 /* Disallow copy-in/out in nested parallel if
1045 decl is shared in outer parallel, otherwise
1046 each thread could store the shared variable
1047 in its own copy-in location, making the
1048 variable no longer really shared. */
b8214689 1049 if (shared_ctx->is_nested)
e8a588af 1050 {
1051 omp_context *up;
1052
1053 for (up = shared_ctx->outer; up; up = up->outer)
0cb159ec 1054 if (is_taskreg_ctx (up) && maybe_lookup_decl (decl, up))
e8a588af 1055 break;
1056
0cb159ec 1057 if (up)
e8a588af 1058 {
1059 tree c;
1060
75a70cf9 1061 for (c = gimple_omp_taskreg_clauses (up->stmt);
e8a588af 1062 c; c = OMP_CLAUSE_CHAIN (c))
1063 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
1064 && OMP_CLAUSE_DECL (c) == decl)
1065 break;
1066
1067 if (c)
784ad964 1068 goto maybe_mark_addressable_and_ret;
e8a588af 1069 }
1070 }
fd6481cf 1071
b8214689 1072 /* For tasks avoid using copy-in/out. As tasks can be
fd6481cf 1073 deferred or executed in different thread, when GOMP_task
1074 returns, the task hasn't necessarily terminated. */
b8214689 1075 if (is_task_ctx (shared_ctx))
fd6481cf 1076 {
784ad964 1077 tree outer;
1078 maybe_mark_addressable_and_ret:
1079 outer = maybe_lookup_decl_in_outer_ctx (decl, shared_ctx);
fd6481cf 1080 if (is_gimple_reg (outer))
1081 {
1082 /* Taking address of OUTER in lower_send_shared_vars
1083 might need regimplification of everything that uses the
1084 variable. */
1085 if (!task_shared_vars)
1086 task_shared_vars = BITMAP_ALLOC (NULL);
1087 bitmap_set_bit (task_shared_vars, DECL_UID (outer));
1088 TREE_ADDRESSABLE (outer) = 1;
1089 }
1090 return true;
1091 }
1e8e9920 1092 }
1093
1094 return false;
1095}
1096
79acaae1 1097/* Construct a new automatic decl similar to VAR. */
1098
1099static tree
1100omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx)
1101{
1102 tree copy = copy_var_decl (var, name, type);
1103
1104 DECL_CONTEXT (copy) = current_function_decl;
1767a056 1105 DECL_CHAIN (copy) = ctx->block_vars;
1e8e9920 1106 ctx->block_vars = copy;
1107
1108 return copy;
1109}
1110
1111static tree
1112omp_copy_decl_1 (tree var, omp_context *ctx)
1113{
1114 return omp_copy_decl_2 (var, DECL_NAME (var), TREE_TYPE (var), ctx);
1115}
1116
445d06b6 1117/* Build COMPONENT_REF and set TREE_THIS_VOLATILE and TREE_READONLY on it
1118 as appropriate. */
1119static tree
1120omp_build_component_ref (tree obj, tree field)
1121{
1122 tree ret = build3 (COMPONENT_REF, TREE_TYPE (field), obj, field, NULL);
1123 if (TREE_THIS_VOLATILE (field))
1124 TREE_THIS_VOLATILE (ret) |= 1;
1125 if (TREE_READONLY (field))
1126 TREE_READONLY (ret) |= 1;
1127 return ret;
1128}
1129
1e8e9920 1130/* Build tree nodes to access the field for VAR on the receiver side. */
1131
1132static tree
1133build_receiver_ref (tree var, bool by_ref, omp_context *ctx)
1134{
1135 tree x, field = lookup_field (var, ctx);
1136
1137 /* If the receiver record type was remapped in the child function,
1138 remap the field into the new record type. */
1139 x = maybe_lookup_field (field, ctx);
1140 if (x != NULL)
1141 field = x;
1142
182cf5a9 1143 x = build_simple_mem_ref (ctx->receiver_decl);
445d06b6 1144 x = omp_build_component_ref (x, field);
1e8e9920 1145 if (by_ref)
182cf5a9 1146 x = build_simple_mem_ref (x);
1e8e9920 1147
1148 return x;
1149}
1150
1151/* Build tree nodes to access VAR in the scope outer to CTX. In the case
1152 of a parallel, this is a component reference; for workshare constructs
1153 this is some variable. */
1154
1155static tree
1156build_outer_var_ref (tree var, omp_context *ctx)
1157{
1158 tree x;
1159
f49d7bb5 1160 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx)))
1e8e9920 1161 x = var;
1162 else if (is_variable_sized (var))
1163 {
1164 x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
1165 x = build_outer_var_ref (x, ctx);
182cf5a9 1166 x = build_simple_mem_ref (x);
1e8e9920 1167 }
fd6481cf 1168 else if (is_taskreg_ctx (ctx))
1e8e9920 1169 {
e8a588af 1170 bool by_ref = use_pointer_for_field (var, NULL);
1e8e9920 1171 x = build_receiver_ref (var, by_ref, ctx);
1172 }
3d483a94 1173 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
10c55644 1174 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3d483a94 1175 {
1176 /* #pragma omp simd isn't a worksharing construct, and can reference even
1177 private vars in its linear etc. clauses. */
1178 x = NULL_TREE;
1179 if (ctx->outer && is_taskreg_ctx (ctx))
1180 x = lookup_decl (var, ctx->outer);
1181 else if (ctx->outer)
84cb1020 1182 x = maybe_lookup_decl_in_outer_ctx (var, ctx);
3d483a94 1183 if (x == NULL_TREE)
1184 x = var;
1185 }
1e8e9920 1186 else if (ctx->outer)
1187 x = lookup_decl (var, ctx->outer);
9438af57 1188 else if (is_reference (var))
1189 /* This can happen with orphaned constructs. If var is reference, it is
1190 possible it is shared and as such valid. */
1191 x = var;
1e8e9920 1192 else
1193 gcc_unreachable ();
1194
1195 if (is_reference (var))
182cf5a9 1196 x = build_simple_mem_ref (x);
1e8e9920 1197
1198 return x;
1199}
1200
1201/* Build tree nodes to access the field for VAR on the sender side. */
1202
1203static tree
1204build_sender_ref (tree var, omp_context *ctx)
1205{
fd6481cf 1206 tree field = lookup_sfield (var, ctx);
445d06b6 1207 return omp_build_component_ref (ctx->sender_decl, field);
1e8e9920 1208}
1209
1210/* Add a new field for VAR inside the structure CTX->SENDER_DECL. */
1211
1212static void
fd6481cf 1213install_var_field (tree var, bool by_ref, int mask, omp_context *ctx)
1e8e9920 1214{
fd6481cf 1215 tree field, type, sfield = NULL_TREE;
1e8e9920 1216
fd6481cf 1217 gcc_assert ((mask & 1) == 0
1218 || !splay_tree_lookup (ctx->field_map, (splay_tree_key) var));
1219 gcc_assert ((mask & 2) == 0 || !ctx->sfield_map
1220 || !splay_tree_lookup (ctx->sfield_map, (splay_tree_key) var));
ca4c3545 1221 gcc_assert ((mask & 3) == 3
1222 || !is_gimple_omp_oacc (ctx->stmt));
1e8e9920 1223
1224 type = TREE_TYPE (var);
bc7bff74 1225 if (mask & 4)
1226 {
1227 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
1228 type = build_pointer_type (build_pointer_type (type));
1229 }
1230 else if (by_ref)
1e8e9920 1231 type = build_pointer_type (type);
fd6481cf 1232 else if ((mask & 3) == 1 && is_reference (var))
1233 type = TREE_TYPE (type);
1e8e9920 1234
e60a6f7b 1235 field = build_decl (DECL_SOURCE_LOCATION (var),
1236 FIELD_DECL, DECL_NAME (var), type);
1e8e9920 1237
1238 /* Remember what variable this field was created for. This does have a
1239 side effect of making dwarf2out ignore this member, so for helpful
1240 debugging we clear it later in delete_omp_context. */
1241 DECL_ABSTRACT_ORIGIN (field) = var;
fd6481cf 1242 if (type == TREE_TYPE (var))
1243 {
1244 DECL_ALIGN (field) = DECL_ALIGN (var);
1245 DECL_USER_ALIGN (field) = DECL_USER_ALIGN (var);
1246 TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (var);
1247 }
1248 else
1249 DECL_ALIGN (field) = TYPE_ALIGN (type);
1e8e9920 1250
fd6481cf 1251 if ((mask & 3) == 3)
1252 {
1253 insert_field_into_struct (ctx->record_type, field);
1254 if (ctx->srecord_type)
1255 {
e60a6f7b 1256 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1257 FIELD_DECL, DECL_NAME (var), type);
fd6481cf 1258 DECL_ABSTRACT_ORIGIN (sfield) = var;
1259 DECL_ALIGN (sfield) = DECL_ALIGN (field);
1260 DECL_USER_ALIGN (sfield) = DECL_USER_ALIGN (field);
1261 TREE_THIS_VOLATILE (sfield) = TREE_THIS_VOLATILE (field);
1262 insert_field_into_struct (ctx->srecord_type, sfield);
1263 }
1264 }
1265 else
1266 {
1267 if (ctx->srecord_type == NULL_TREE)
1268 {
1269 tree t;
1270
1271 ctx->srecord_type = lang_hooks.types.make_type (RECORD_TYPE);
1272 ctx->sfield_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1273 for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
1274 {
e60a6f7b 1275 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1276 FIELD_DECL, DECL_NAME (t), TREE_TYPE (t));
fd6481cf 1277 DECL_ABSTRACT_ORIGIN (sfield) = DECL_ABSTRACT_ORIGIN (t);
1278 insert_field_into_struct (ctx->srecord_type, sfield);
1279 splay_tree_insert (ctx->sfield_map,
1280 (splay_tree_key) DECL_ABSTRACT_ORIGIN (t),
1281 (splay_tree_value) sfield);
1282 }
1283 }
1284 sfield = field;
1285 insert_field_into_struct ((mask & 1) ? ctx->record_type
1286 : ctx->srecord_type, field);
1287 }
1e8e9920 1288
fd6481cf 1289 if (mask & 1)
1290 splay_tree_insert (ctx->field_map, (splay_tree_key) var,
1291 (splay_tree_value) field);
1292 if ((mask & 2) && ctx->sfield_map)
1293 splay_tree_insert (ctx->sfield_map, (splay_tree_key) var,
1294 (splay_tree_value) sfield);
1e8e9920 1295}
1296
1297static tree
1298install_var_local (tree var, omp_context *ctx)
1299{
1300 tree new_var = omp_copy_decl_1 (var, ctx);
1301 insert_decl_map (&ctx->cb, var, new_var);
1302 return new_var;
1303}
1304
1305/* Adjust the replacement for DECL in CTX for the new context. This means
1306 copying the DECL_VALUE_EXPR, and fixing up the type. */
1307
1308static void
1309fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug)
1310{
1311 tree new_decl, size;
1312
1313 new_decl = lookup_decl (decl, ctx);
1314
1315 TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb);
1316
1317 if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug)
1318 && DECL_HAS_VALUE_EXPR_P (decl))
1319 {
1320 tree ve = DECL_VALUE_EXPR (decl);
75a70cf9 1321 walk_tree (&ve, copy_tree_body_r, &ctx->cb, NULL);
1e8e9920 1322 SET_DECL_VALUE_EXPR (new_decl, ve);
1323 DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
1324 }
1325
1326 if (!TREE_CONSTANT (DECL_SIZE (new_decl)))
1327 {
1328 size = remap_decl (DECL_SIZE (decl), &ctx->cb);
1329 if (size == error_mark_node)
1330 size = TYPE_SIZE (TREE_TYPE (new_decl));
1331 DECL_SIZE (new_decl) = size;
1332
1333 size = remap_decl (DECL_SIZE_UNIT (decl), &ctx->cb);
1334 if (size == error_mark_node)
1335 size = TYPE_SIZE_UNIT (TREE_TYPE (new_decl));
1336 DECL_SIZE_UNIT (new_decl) = size;
1337 }
1338}
1339
1340/* The callback for remap_decl. Search all containing contexts for a
1341 mapping of the variable; this avoids having to duplicate the splay
1342 tree ahead of time. We know a mapping doesn't already exist in the
1343 given context. Create new mappings to implement default semantics. */
1344
1345static tree
1346omp_copy_decl (tree var, copy_body_data *cb)
1347{
1348 omp_context *ctx = (omp_context *) cb;
1349 tree new_var;
1350
1e8e9920 1351 if (TREE_CODE (var) == LABEL_DECL)
1352 {
e60a6f7b 1353 new_var = create_artificial_label (DECL_SOURCE_LOCATION (var));
773c5ba7 1354 DECL_CONTEXT (new_var) = current_function_decl;
1e8e9920 1355 insert_decl_map (&ctx->cb, var, new_var);
1356 return new_var;
1357 }
1358
fd6481cf 1359 while (!is_taskreg_ctx (ctx))
1e8e9920 1360 {
1361 ctx = ctx->outer;
1362 if (ctx == NULL)
1363 return var;
1364 new_var = maybe_lookup_decl (var, ctx);
1365 if (new_var)
1366 return new_var;
1367 }
1368
f49d7bb5 1369 if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn)
1370 return var;
1371
1e8e9920 1372 return error_mark_node;
1373}
1374
773c5ba7 1375
773c5ba7 1376/* Debugging dumps for parallel regions. */
1377void dump_omp_region (FILE *, struct omp_region *, int);
1378void debug_omp_region (struct omp_region *);
1379void debug_all_omp_regions (void);
1380
1381/* Dump the parallel region tree rooted at REGION. */
1382
1383void
1384dump_omp_region (FILE *file, struct omp_region *region, int indent)
1385{
61e47ac8 1386 fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index,
75a70cf9 1387 gimple_code_name[region->type]);
773c5ba7 1388
1389 if (region->inner)
1390 dump_omp_region (file, region->inner, indent + 4);
1391
61e47ac8 1392 if (region->cont)
1393 {
75a70cf9 1394 fprintf (file, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent, "",
61e47ac8 1395 region->cont->index);
1396 }
48e1416a 1397
773c5ba7 1398 if (region->exit)
75a70cf9 1399 fprintf (file, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent, "",
61e47ac8 1400 region->exit->index);
773c5ba7 1401 else
61e47ac8 1402 fprintf (file, "%*s[no exit marker]\n", indent, "");
773c5ba7 1403
1404 if (region->next)
61e47ac8 1405 dump_omp_region (file, region->next, indent);
773c5ba7 1406}
1407
4b987fac 1408DEBUG_FUNCTION void
773c5ba7 1409debug_omp_region (struct omp_region *region)
1410{
1411 dump_omp_region (stderr, region, 0);
1412}
1413
4b987fac 1414DEBUG_FUNCTION void
773c5ba7 1415debug_all_omp_regions (void)
1416{
1417 dump_omp_region (stderr, root_omp_region, 0);
1418}
1419
1420
1421/* Create a new parallel region starting at STMT inside region PARENT. */
1422
7740abd8 1423static struct omp_region *
75a70cf9 1424new_omp_region (basic_block bb, enum gimple_code type,
1425 struct omp_region *parent)
773c5ba7 1426{
4077bf7a 1427 struct omp_region *region = XCNEW (struct omp_region);
773c5ba7 1428
1429 region->outer = parent;
61e47ac8 1430 region->entry = bb;
1431 region->type = type;
773c5ba7 1432
1433 if (parent)
1434 {
1435 /* This is a nested region. Add it to the list of inner
1436 regions in PARENT. */
1437 region->next = parent->inner;
1438 parent->inner = region;
1439 }
61e47ac8 1440 else
773c5ba7 1441 {
1442 /* This is a toplevel region. Add it to the list of toplevel
1443 regions in ROOT_OMP_REGION. */
1444 region->next = root_omp_region;
1445 root_omp_region = region;
1446 }
61e47ac8 1447
1448 return region;
1449}
1450
1451/* Release the memory associated with the region tree rooted at REGION. */
1452
1453static void
1454free_omp_region_1 (struct omp_region *region)
1455{
1456 struct omp_region *i, *n;
1457
1458 for (i = region->inner; i ; i = n)
773c5ba7 1459 {
61e47ac8 1460 n = i->next;
1461 free_omp_region_1 (i);
773c5ba7 1462 }
1463
61e47ac8 1464 free (region);
1465}
773c5ba7 1466
61e47ac8 1467/* Release the memory for the entire omp region tree. */
1468
1469void
1470free_omp_regions (void)
1471{
1472 struct omp_region *r, *n;
1473 for (r = root_omp_region; r ; r = n)
1474 {
1475 n = r->next;
1476 free_omp_region_1 (r);
1477 }
1478 root_omp_region = NULL;
773c5ba7 1479}
1480
1481
1e8e9920 1482/* Create a new context, with OUTER_CTX being the surrounding context. */
1483
1484static omp_context *
75a70cf9 1485new_omp_context (gimple stmt, omp_context *outer_ctx)
1e8e9920 1486{
1487 omp_context *ctx = XCNEW (omp_context);
1488
1489 splay_tree_insert (all_contexts, (splay_tree_key) stmt,
1490 (splay_tree_value) ctx);
1491 ctx->stmt = stmt;
1492
1493 if (outer_ctx)
1494 {
1495 ctx->outer = outer_ctx;
1496 ctx->cb = outer_ctx->cb;
1497 ctx->cb.block = NULL;
1498 ctx->depth = outer_ctx->depth + 1;
ca4c3545 1499 ctx->reduction_map = outer_ctx->reduction_map;
1e8e9920 1500 }
1501 else
1502 {
1503 ctx->cb.src_fn = current_function_decl;
1504 ctx->cb.dst_fn = current_function_decl;
415d1b9a 1505 ctx->cb.src_node = cgraph_node::get (current_function_decl);
53f79206 1506 gcc_checking_assert (ctx->cb.src_node);
1e8e9920 1507 ctx->cb.dst_node = ctx->cb.src_node;
1508 ctx->cb.src_cfun = cfun;
1509 ctx->cb.copy_decl = omp_copy_decl;
e38def9c 1510 ctx->cb.eh_lp_nr = 0;
1e8e9920 1511 ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
1512 ctx->depth = 1;
1513 }
1514
06ecf488 1515 ctx->cb.decl_map = new hash_map<tree, tree>;
1e8e9920 1516
1517 return ctx;
1518}
1519
75a70cf9 1520static gimple_seq maybe_catch_exception (gimple_seq);
f6430caa 1521
1522/* Finalize task copyfn. */
1523
1524static void
1a91d914 1525finalize_task_copyfn (gomp_task *task_stmt)
f6430caa 1526{
1527 struct function *child_cfun;
9078126c 1528 tree child_fn;
e3a19533 1529 gimple_seq seq = NULL, new_seq;
1a91d914 1530 gbind *bind;
f6430caa 1531
75a70cf9 1532 child_fn = gimple_omp_task_copy_fn (task_stmt);
f6430caa 1533 if (child_fn == NULL_TREE)
1534 return;
1535
1536 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
82b40354 1537 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
f6430caa 1538
f6430caa 1539 push_cfun (child_cfun);
7e3aae05 1540 bind = gimplify_body (child_fn, false);
75a70cf9 1541 gimple_seq_add_stmt (&seq, bind);
1542 new_seq = maybe_catch_exception (seq);
1543 if (new_seq != seq)
1544 {
1545 bind = gimple_build_bind (NULL, new_seq, NULL);
e3a19533 1546 seq = NULL;
75a70cf9 1547 gimple_seq_add_stmt (&seq, bind);
1548 }
1549 gimple_set_body (child_fn, seq);
f6430caa 1550 pop_cfun ();
f6430caa 1551
82b40354 1552 /* Inform the callgraph about the new function. */
47300487 1553 cgraph_node *node = cgraph_node::get_create (child_fn);
1554 node->parallelized_function = 1;
415d1b9a 1555 cgraph_node::add_new_function (child_fn, false);
f6430caa 1556}
1557
1e8e9920 1558/* Destroy a omp_context data structures. Called through the splay tree
1559 value delete callback. */
1560
1561static void
1562delete_omp_context (splay_tree_value value)
1563{
1564 omp_context *ctx = (omp_context *) value;
1565
06ecf488 1566 delete ctx->cb.decl_map;
1e8e9920 1567
1568 if (ctx->field_map)
1569 splay_tree_delete (ctx->field_map);
fd6481cf 1570 if (ctx->sfield_map)
1571 splay_tree_delete (ctx->sfield_map);
42d49354 1572 /* Reduction map is copied to nested contexts, so only delete it in the
1573 owner. */
ca4c3545 1574 if (ctx->reduction_map
42d49354 1575 && gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET
1576 && is_gimple_omp_offloaded (ctx->stmt)
1577 && is_gimple_omp_oacc (ctx->stmt))
ca4c3545 1578 splay_tree_delete (ctx->reduction_map);
1e8e9920 1579
1580 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
1581 it produces corrupt debug information. */
1582 if (ctx->record_type)
1583 {
1584 tree t;
1767a056 1585 for (t = TYPE_FIELDS (ctx->record_type); t ; t = DECL_CHAIN (t))
1e8e9920 1586 DECL_ABSTRACT_ORIGIN (t) = NULL;
1587 }
fd6481cf 1588 if (ctx->srecord_type)
1589 {
1590 tree t;
1767a056 1591 for (t = TYPE_FIELDS (ctx->srecord_type); t ; t = DECL_CHAIN (t))
fd6481cf 1592 DECL_ABSTRACT_ORIGIN (t) = NULL;
1593 }
1e8e9920 1594
f6430caa 1595 if (is_task_ctx (ctx))
1a91d914 1596 finalize_task_copyfn (as_a <gomp_task *> (ctx->stmt));
f6430caa 1597
1e8e9920 1598 XDELETE (ctx);
1599}
1600
1601/* Fix up RECEIVER_DECL with a type that has been remapped to the child
1602 context. */
1603
1604static void
1605fixup_child_record_type (omp_context *ctx)
1606{
1607 tree f, type = ctx->record_type;
1608
1609 /* ??? It isn't sufficient to just call remap_type here, because
1610 variably_modified_type_p doesn't work the way we expect for
1611 record types. Testing each field for whether it needs remapping
1612 and creating a new record by hand works, however. */
1767a056 1613 for (f = TYPE_FIELDS (type); f ; f = DECL_CHAIN (f))
1e8e9920 1614 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
1615 break;
1616 if (f)
1617 {
1618 tree name, new_fields = NULL;
1619
1620 type = lang_hooks.types.make_type (RECORD_TYPE);
1621 name = DECL_NAME (TYPE_NAME (ctx->record_type));
e60a6f7b 1622 name = build_decl (DECL_SOURCE_LOCATION (ctx->receiver_decl),
1623 TYPE_DECL, name, type);
1e8e9920 1624 TYPE_NAME (type) = name;
1625
1767a056 1626 for (f = TYPE_FIELDS (ctx->record_type); f ; f = DECL_CHAIN (f))
1e8e9920 1627 {
1628 tree new_f = copy_node (f);
1629 DECL_CONTEXT (new_f) = type;
1630 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
1767a056 1631 DECL_CHAIN (new_f) = new_fields;
75a70cf9 1632 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &ctx->cb, NULL);
1633 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r,
1634 &ctx->cb, NULL);
1635 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
1636 &ctx->cb, NULL);
1e8e9920 1637 new_fields = new_f;
1638
1639 /* Arrange to be able to look up the receiver field
1640 given the sender field. */
1641 splay_tree_insert (ctx->field_map, (splay_tree_key) f,
1642 (splay_tree_value) new_f);
1643 }
1644 TYPE_FIELDS (type) = nreverse (new_fields);
1645 layout_type (type);
1646 }
1647
5455b100 1648 TREE_TYPE (ctx->receiver_decl)
1649 = build_qualified_type (build_reference_type (type), TYPE_QUAL_RESTRICT);
1e8e9920 1650}
1651
1652/* Instantiate decls as necessary in CTX to satisfy the data sharing
1653 specified by CLAUSES. */
1654
1655static void
1656scan_sharing_clauses (tree clauses, omp_context *ctx)
1657{
1658 tree c, decl;
1659 bool scan_array_reductions = false;
1660
1661 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1662 {
1663 bool by_ref;
1664
55d6e7cd 1665 switch (OMP_CLAUSE_CODE (c))
1e8e9920 1666 {
1667 case OMP_CLAUSE_PRIVATE:
1668 decl = OMP_CLAUSE_DECL (c);
fd6481cf 1669 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
1670 goto do_private;
1671 else if (!is_variable_sized (decl))
1e8e9920 1672 install_var_local (decl, ctx);
1673 break;
1674
1675 case OMP_CLAUSE_SHARED:
5fddcf34 1676 decl = OMP_CLAUSE_DECL (c);
bc7bff74 1677 /* Ignore shared directives in teams construct. */
1678 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
5fddcf34 1679 {
1680 /* Global variables don't need to be copied,
1681 the receiver side will use them directly. */
1682 tree odecl = maybe_lookup_decl_in_outer_ctx (decl, ctx);
1683 if (is_global_var (odecl))
1684 break;
1685 insert_decl_map (&ctx->cb, decl, odecl);
1686 break;
1687 }
fd6481cf 1688 gcc_assert (is_taskreg_ctx (ctx));
e7327393 1689 gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl))
1690 || !is_variable_sized (decl));
f49d7bb5 1691 /* Global variables don't need to be copied,
1692 the receiver side will use them directly. */
1693 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1694 break;
fd6481cf 1695 by_ref = use_pointer_for_field (decl, ctx);
1e8e9920 1696 if (! TREE_READONLY (decl)
1697 || TREE_ADDRESSABLE (decl)
1698 || by_ref
1699 || is_reference (decl))
1700 {
fd6481cf 1701 install_var_field (decl, by_ref, 3, ctx);
1e8e9920 1702 install_var_local (decl, ctx);
1703 break;
1704 }
1705 /* We don't need to copy const scalar vars back. */
55d6e7cd 1706 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
1e8e9920 1707 goto do_private;
1708
1709 case OMP_CLAUSE_LASTPRIVATE:
1710 /* Let the corresponding firstprivate clause create
1711 the variable. */
1712 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1713 break;
1714 /* FALLTHRU */
1715
1716 case OMP_CLAUSE_FIRSTPRIVATE:
ca4c3545 1717 if (is_gimple_omp_oacc (ctx->stmt))
1718 {
1719 sorry ("clause not supported yet");
1720 break;
1721 }
1722 /* FALLTHRU */
1e8e9920 1723 case OMP_CLAUSE_REDUCTION:
3d483a94 1724 case OMP_CLAUSE_LINEAR:
1e8e9920 1725 decl = OMP_CLAUSE_DECL (c);
1726 do_private:
1727 if (is_variable_sized (decl))
1e8e9920 1728 {
fd6481cf 1729 if (is_task_ctx (ctx))
1730 install_var_field (decl, false, 1, ctx);
1731 break;
1732 }
1733 else if (is_taskreg_ctx (ctx))
1734 {
1735 bool global
1736 = is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx));
e8a588af 1737 by_ref = use_pointer_for_field (decl, NULL);
fd6481cf 1738
1739 if (is_task_ctx (ctx)
1740 && (global || by_ref || is_reference (decl)))
1741 {
1742 install_var_field (decl, false, 1, ctx);
1743 if (!global)
1744 install_var_field (decl, by_ref, 2, ctx);
1745 }
1746 else if (!global)
1747 install_var_field (decl, by_ref, 3, ctx);
1e8e9920 1748 }
1749 install_var_local (decl, ctx);
ca4c3545 1750 if (is_gimple_omp_oacc (ctx->stmt)
1751 && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
1752 {
1753 /* Create a decl for the reduction array. */
1754 tree var = OMP_CLAUSE_DECL (c);
1755 tree type = get_base_type (var);
1756 tree ptype = build_pointer_type (type);
1757 tree array = create_tmp_var (ptype,
1758 oacc_get_reduction_array_id (var));
1759 omp_context *c = (ctx->field_map ? ctx : ctx->outer);
1760 install_var_field (array, true, 3, c);
1761 install_var_local (array, c);
1762
1763 /* Insert it into the current context. */
1764 splay_tree_insert (ctx->reduction_map, (splay_tree_key)
1765 oacc_get_reduction_array_id (var),
1766 (splay_tree_value) array);
1767 splay_tree_insert (ctx->reduction_map,
1768 (splay_tree_key) array,
1769 (splay_tree_value) array);
1770 }
1e8e9920 1771 break;
1772
bc7bff74 1773 case OMP_CLAUSE__LOOPTEMP_:
1774 gcc_assert (is_parallel_ctx (ctx));
1775 decl = OMP_CLAUSE_DECL (c);
1776 install_var_field (decl, false, 3, ctx);
1777 install_var_local (decl, ctx);
1778 break;
1779
1e8e9920 1780 case OMP_CLAUSE_COPYPRIVATE:
1e8e9920 1781 case OMP_CLAUSE_COPYIN:
1782 decl = OMP_CLAUSE_DECL (c);
e8a588af 1783 by_ref = use_pointer_for_field (decl, NULL);
fd6481cf 1784 install_var_field (decl, by_ref, 3, ctx);
1e8e9920 1785 break;
1786
1787 case OMP_CLAUSE_DEFAULT:
1788 ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
1789 break;
1790
2169f33b 1791 case OMP_CLAUSE_FINAL:
1e8e9920 1792 case OMP_CLAUSE_IF:
1793 case OMP_CLAUSE_NUM_THREADS:
bc7bff74 1794 case OMP_CLAUSE_NUM_TEAMS:
1795 case OMP_CLAUSE_THREAD_LIMIT:
1796 case OMP_CLAUSE_DEVICE:
1e8e9920 1797 case OMP_CLAUSE_SCHEDULE:
bc7bff74 1798 case OMP_CLAUSE_DIST_SCHEDULE:
1799 case OMP_CLAUSE_DEPEND:
40750995 1800 case OMP_CLAUSE__CILK_FOR_COUNT_:
ca4c3545 1801 case OMP_CLAUSE_NUM_GANGS:
1802 case OMP_CLAUSE_NUM_WORKERS:
1803 case OMP_CLAUSE_VECTOR_LENGTH:
1e8e9920 1804 if (ctx->outer)
75a70cf9 1805 scan_omp_op (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
1e8e9920 1806 break;
1807
bc7bff74 1808 case OMP_CLAUSE_TO:
1809 case OMP_CLAUSE_FROM:
1810 case OMP_CLAUSE_MAP:
1811 if (ctx->outer)
1812 scan_omp_op (&OMP_CLAUSE_SIZE (c), ctx->outer);
1813 decl = OMP_CLAUSE_DECL (c);
1814 /* Global variables with "omp declare target" attribute
1815 don't need to be copied, the receiver side will use them
1816 directly. */
1817 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1818 && DECL_P (decl)
1819 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
b0c5e347 1820 && varpool_node::get_create (decl)->offloadable)
bc7bff74 1821 break;
1822 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
ca4c3545 1823 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER)
bc7bff74 1824 {
ca4c3545 1825 /* Ignore GOMP_MAP_POINTER kind for arrays in regions that are
1826 not offloaded; there is nothing to map for those. */
1827 if (!is_gimple_omp_offloaded (ctx->stmt)
c1a114c2 1828 && !POINTER_TYPE_P (TREE_TYPE (decl))
1829 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
bc7bff74 1830 break;
1831 }
1832 if (DECL_P (decl))
1833 {
1834 if (DECL_SIZE (decl)
1835 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1836 {
1837 tree decl2 = DECL_VALUE_EXPR (decl);
1838 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1839 decl2 = TREE_OPERAND (decl2, 0);
1840 gcc_assert (DECL_P (decl2));
1841 install_var_field (decl2, true, 3, ctx);
1842 install_var_local (decl2, ctx);
1843 install_var_local (decl, ctx);
1844 }
1845 else
1846 {
1847 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
ca4c3545 1848 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
bc7bff74 1849 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
1850 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1851 install_var_field (decl, true, 7, ctx);
1852 else
1853 install_var_field (decl, true, 3, ctx);
ca4c3545 1854 if (is_gimple_omp_offloaded (ctx->stmt))
bc7bff74 1855 install_var_local (decl, ctx);
1856 }
1857 }
1858 else
1859 {
1860 tree base = get_base_address (decl);
1861 tree nc = OMP_CLAUSE_CHAIN (c);
1862 if (DECL_P (base)
1863 && nc != NULL_TREE
1864 && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
1865 && OMP_CLAUSE_DECL (nc) == base
ca4c3545 1866 && OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_POINTER
bc7bff74 1867 && integer_zerop (OMP_CLAUSE_SIZE (nc)))
1868 {
1869 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c) = 1;
1870 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (nc) = 1;
1871 }
1872 else
1873 {
691447ab 1874 if (ctx->outer)
1875 {
1876 scan_omp_op (&OMP_CLAUSE_DECL (c), ctx->outer);
1877 decl = OMP_CLAUSE_DECL (c);
1878 }
bc7bff74 1879 gcc_assert (!splay_tree_lookup (ctx->field_map,
1880 (splay_tree_key) decl));
1881 tree field
1882 = build_decl (OMP_CLAUSE_LOCATION (c),
1883 FIELD_DECL, NULL_TREE, ptr_type_node);
1884 DECL_ALIGN (field) = TYPE_ALIGN (ptr_type_node);
1885 insert_field_into_struct (ctx->record_type, field);
1886 splay_tree_insert (ctx->field_map, (splay_tree_key) decl,
1887 (splay_tree_value) field);
1888 }
1889 }
1890 break;
1891
1e8e9920 1892 case OMP_CLAUSE_NOWAIT:
1893 case OMP_CLAUSE_ORDERED:
fd6481cf 1894 case OMP_CLAUSE_COLLAPSE:
1895 case OMP_CLAUSE_UNTIED:
2169f33b 1896 case OMP_CLAUSE_MERGEABLE:
bc7bff74 1897 case OMP_CLAUSE_PROC_BIND:
3d483a94 1898 case OMP_CLAUSE_SAFELEN:
ca4c3545 1899 case OMP_CLAUSE_ASYNC:
1900 case OMP_CLAUSE_WAIT:
1901 case OMP_CLAUSE_GANG:
1902 case OMP_CLAUSE_WORKER:
1903 case OMP_CLAUSE_VECTOR:
1e8e9920 1904 break;
1905
bc7bff74 1906 case OMP_CLAUSE_ALIGNED:
1907 decl = OMP_CLAUSE_DECL (c);
1908 if (is_global_var (decl)
1909 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1910 install_var_local (decl, ctx);
1911 break;
1912
ca4c3545 1913 case OMP_CLAUSE_DEVICE_RESIDENT:
1914 case OMP_CLAUSE_USE_DEVICE:
1915 case OMP_CLAUSE__CACHE_:
1916 case OMP_CLAUSE_INDEPENDENT:
1917 case OMP_CLAUSE_AUTO:
1918 case OMP_CLAUSE_SEQ:
1919 sorry ("Clause not supported yet");
1920 break;
1921
1e8e9920 1922 default:
1923 gcc_unreachable ();
1924 }
1925 }
1926
1927 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1928 {
55d6e7cd 1929 switch (OMP_CLAUSE_CODE (c))
1e8e9920 1930 {
1931 case OMP_CLAUSE_LASTPRIVATE:
1932 /* Let the corresponding firstprivate clause create
1933 the variable. */
75a70cf9 1934 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
fd6481cf 1935 scan_array_reductions = true;
1e8e9920 1936 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1937 break;
1938 /* FALLTHRU */
1939
1e8e9920 1940 case OMP_CLAUSE_FIRSTPRIVATE:
ca4c3545 1941 if (is_gimple_omp_oacc (ctx->stmt))
1942 {
1943 sorry ("clause not supported yet");
1944 break;
1945 }
1946 /* FALLTHRU */
1947 case OMP_CLAUSE_PRIVATE:
1e8e9920 1948 case OMP_CLAUSE_REDUCTION:
3d483a94 1949 case OMP_CLAUSE_LINEAR:
1e8e9920 1950 decl = OMP_CLAUSE_DECL (c);
1951 if (is_variable_sized (decl))
1952 install_var_local (decl, ctx);
1953 fixup_remapped_decl (decl, ctx,
55d6e7cd 1954 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
1e8e9920 1955 && OMP_CLAUSE_PRIVATE_DEBUG (c));
55d6e7cd 1956 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1e8e9920 1957 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1958 scan_array_reductions = true;
2b536a17 1959 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
1960 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
1961 scan_array_reductions = true;
1e8e9920 1962 break;
1963
1964 case OMP_CLAUSE_SHARED:
bc7bff74 1965 /* Ignore shared directives in teams construct. */
1966 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1967 break;
1e8e9920 1968 decl = OMP_CLAUSE_DECL (c);
f49d7bb5 1969 if (! is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1970 fixup_remapped_decl (decl, ctx, false);
1e8e9920 1971 break;
1972
bc7bff74 1973 case OMP_CLAUSE_MAP:
ca4c3545 1974 if (!is_gimple_omp_offloaded (ctx->stmt))
bc7bff74 1975 break;
1976 decl = OMP_CLAUSE_DECL (c);
1977 if (DECL_P (decl)
1978 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
b0c5e347 1979 && varpool_node::get_create (decl)->offloadable)
bc7bff74 1980 break;
1981 if (DECL_P (decl))
1982 {
ca4c3545 1983 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
bc7bff74 1984 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
1985 && !COMPLETE_TYPE_P (TREE_TYPE (decl)))
1986 {
1987 tree new_decl = lookup_decl (decl, ctx);
1988 TREE_TYPE (new_decl)
1989 = remap_type (TREE_TYPE (decl), &ctx->cb);
1990 }
1991 else if (DECL_SIZE (decl)
1992 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1993 {
1994 tree decl2 = DECL_VALUE_EXPR (decl);
1995 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1996 decl2 = TREE_OPERAND (decl2, 0);
1997 gcc_assert (DECL_P (decl2));
1998 fixup_remapped_decl (decl2, ctx, false);
1999 fixup_remapped_decl (decl, ctx, true);
2000 }
2001 else
2002 fixup_remapped_decl (decl, ctx, false);
2003 }
2004 break;
2005
1e8e9920 2006 case OMP_CLAUSE_COPYPRIVATE:
2007 case OMP_CLAUSE_COPYIN:
2008 case OMP_CLAUSE_DEFAULT:
2009 case OMP_CLAUSE_IF:
2010 case OMP_CLAUSE_NUM_THREADS:
bc7bff74 2011 case OMP_CLAUSE_NUM_TEAMS:
2012 case OMP_CLAUSE_THREAD_LIMIT:
2013 case OMP_CLAUSE_DEVICE:
1e8e9920 2014 case OMP_CLAUSE_SCHEDULE:
bc7bff74 2015 case OMP_CLAUSE_DIST_SCHEDULE:
1e8e9920 2016 case OMP_CLAUSE_NOWAIT:
2017 case OMP_CLAUSE_ORDERED:
fd6481cf 2018 case OMP_CLAUSE_COLLAPSE:
2019 case OMP_CLAUSE_UNTIED:
2169f33b 2020 case OMP_CLAUSE_FINAL:
2021 case OMP_CLAUSE_MERGEABLE:
bc7bff74 2022 case OMP_CLAUSE_PROC_BIND:
3d483a94 2023 case OMP_CLAUSE_SAFELEN:
bc7bff74 2024 case OMP_CLAUSE_ALIGNED:
2025 case OMP_CLAUSE_DEPEND:
2026 case OMP_CLAUSE__LOOPTEMP_:
2027 case OMP_CLAUSE_TO:
2028 case OMP_CLAUSE_FROM:
40750995 2029 case OMP_CLAUSE__CILK_FOR_COUNT_:
ca4c3545 2030 case OMP_CLAUSE_ASYNC:
2031 case OMP_CLAUSE_WAIT:
2032 case OMP_CLAUSE_NUM_GANGS:
2033 case OMP_CLAUSE_NUM_WORKERS:
2034 case OMP_CLAUSE_VECTOR_LENGTH:
2035 case OMP_CLAUSE_GANG:
2036 case OMP_CLAUSE_WORKER:
2037 case OMP_CLAUSE_VECTOR:
2038 break;
2039
2040 case OMP_CLAUSE_DEVICE_RESIDENT:
2041 case OMP_CLAUSE_USE_DEVICE:
2042 case OMP_CLAUSE__CACHE_:
2043 case OMP_CLAUSE_INDEPENDENT:
2044 case OMP_CLAUSE_AUTO:
2045 case OMP_CLAUSE_SEQ:
2046 sorry ("Clause not supported yet");
1e8e9920 2047 break;
2048
2049 default:
2050 gcc_unreachable ();
2051 }
2052 }
2053
ca4c3545 2054 gcc_checking_assert (!scan_array_reductions
2055 || !is_gimple_omp_oacc (ctx->stmt));
1e8e9920 2056 if (scan_array_reductions)
2057 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
55d6e7cd 2058 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1e8e9920 2059 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2060 {
ab129075 2061 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
2062 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
1e8e9920 2063 }
fd6481cf 2064 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
75a70cf9 2065 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
ab129075 2066 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
2b536a17 2067 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
2068 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
2069 scan_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
1e8e9920 2070}
2071
40750995 2072/* Create a new name for omp child function. Returns an identifier. If
2073 IS_CILK_FOR is true then the suffix for the child function is
2074 "_cilk_for_fn." */
1e8e9920 2075
1e8e9920 2076static tree
40750995 2077create_omp_child_function_name (bool task_copy, bool is_cilk_for)
1e8e9920 2078{
40750995 2079 if (is_cilk_for)
2080 return clone_function_name (current_function_decl, "_cilk_for_fn");
2081 return clone_function_name (current_function_decl,
2082 task_copy ? "_omp_cpyfn" : "_omp_fn");
2083}
2084
2085/* Returns the type of the induction variable for the child function for
2086 _Cilk_for and the types for _high and _low variables based on TYPE. */
2087
2088static tree
2089cilk_for_check_loop_diff_type (tree type)
2090{
2091 if (TYPE_PRECISION (type) <= TYPE_PRECISION (uint32_type_node))
2092 {
2093 if (TYPE_UNSIGNED (type))
2094 return uint32_type_node;
2095 else
2096 return integer_type_node;
2097 }
2098 else
2099 {
2100 if (TYPE_UNSIGNED (type))
2101 return uint64_type_node;
2102 else
2103 return long_long_integer_type_node;
2104 }
1e8e9920 2105}
2106
2107/* Build a decl for the omp child function. It'll not contain a body
2108 yet, just the bare decl. */
2109
2110static void
fd6481cf 2111create_omp_child_function (omp_context *ctx, bool task_copy)
1e8e9920 2112{
2113 tree decl, type, name, t;
2114
40750995 2115 tree cilk_for_count
2116 = (flag_cilkplus && gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2117 ? find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
2118 OMP_CLAUSE__CILK_FOR_COUNT_) : NULL_TREE;
2119 tree cilk_var_type = NULL_TREE;
2120
2121 name = create_omp_child_function_name (task_copy,
2122 cilk_for_count != NULL_TREE);
fd6481cf 2123 if (task_copy)
2124 type = build_function_type_list (void_type_node, ptr_type_node,
2125 ptr_type_node, NULL_TREE);
40750995 2126 else if (cilk_for_count)
2127 {
2128 type = TREE_TYPE (OMP_CLAUSE_OPERAND (cilk_for_count, 0));
2129 cilk_var_type = cilk_for_check_loop_diff_type (type);
2130 type = build_function_type_list (void_type_node, ptr_type_node,
2131 cilk_var_type, cilk_var_type, NULL_TREE);
2132 }
fd6481cf 2133 else
2134 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
1e8e9920 2135
40750995 2136 decl = build_decl (gimple_location (ctx->stmt), FUNCTION_DECL, name, type);
1e8e9920 2137
ca4c3545 2138 gcc_checking_assert (!is_gimple_omp_oacc (ctx->stmt)
2139 || !task_copy);
fd6481cf 2140 if (!task_copy)
2141 ctx->cb.dst_fn = decl;
2142 else
75a70cf9 2143 gimple_omp_task_set_copy_fn (ctx->stmt, decl);
1e8e9920 2144
2145 TREE_STATIC (decl) = 1;
2146 TREE_USED (decl) = 1;
2147 DECL_ARTIFICIAL (decl) = 1;
2148 DECL_IGNORED_P (decl) = 0;
2149 TREE_PUBLIC (decl) = 0;
2150 DECL_UNINLINABLE (decl) = 1;
2151 DECL_EXTERNAL (decl) = 0;
2152 DECL_CONTEXT (decl) = NULL_TREE;
773c5ba7 2153 DECL_INITIAL (decl) = make_node (BLOCK);
b0c5e347 2154 if (cgraph_node::get (current_function_decl)->offloadable)
2155 cgraph_node::get_create (decl)->offloadable = 1;
bc7bff74 2156 else
2157 {
2158 omp_context *octx;
2159 for (octx = ctx; octx; octx = octx->outer)
ca4c3545 2160 if (is_gimple_omp_offloaded (octx->stmt))
bc7bff74 2161 {
b0c5e347 2162 cgraph_node::get_create (decl)->offloadable = 1;
7114ebdd 2163#ifdef ENABLE_OFFLOADING
b0c5e347 2164 g->have_offload = true;
7114ebdd 2165#endif
bc7bff74 2166 break;
2167 }
2168 }
1e8e9920 2169
ec12b31a 2170 if (cgraph_node::get_create (decl)->offloadable
2171 && !lookup_attribute ("omp declare target",
2172 DECL_ATTRIBUTES (current_function_decl)))
2173 DECL_ATTRIBUTES (decl)
2174 = tree_cons (get_identifier ("omp target entrypoint"),
2175 NULL_TREE, DECL_ATTRIBUTES (decl));
2176
e60a6f7b 2177 t = build_decl (DECL_SOURCE_LOCATION (decl),
2178 RESULT_DECL, NULL_TREE, void_type_node);
1e8e9920 2179 DECL_ARTIFICIAL (t) = 1;
2180 DECL_IGNORED_P (t) = 1;
8e5b4ed6 2181 DECL_CONTEXT (t) = decl;
1e8e9920 2182 DECL_RESULT (decl) = t;
2183
40750995 2184 /* _Cilk_for's child function requires two extra parameters called
2185 __low and __high that are set the by Cilk runtime when it calls this
2186 function. */
2187 if (cilk_for_count)
2188 {
2189 t = build_decl (DECL_SOURCE_LOCATION (decl),
2190 PARM_DECL, get_identifier ("__high"), cilk_var_type);
2191 DECL_ARTIFICIAL (t) = 1;
2192 DECL_NAMELESS (t) = 1;
2193 DECL_ARG_TYPE (t) = ptr_type_node;
2194 DECL_CONTEXT (t) = current_function_decl;
2195 TREE_USED (t) = 1;
2196 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2197 DECL_ARGUMENTS (decl) = t;
2198
2199 t = build_decl (DECL_SOURCE_LOCATION (decl),
2200 PARM_DECL, get_identifier ("__low"), cilk_var_type);
2201 DECL_ARTIFICIAL (t) = 1;
2202 DECL_NAMELESS (t) = 1;
2203 DECL_ARG_TYPE (t) = ptr_type_node;
2204 DECL_CONTEXT (t) = current_function_decl;
2205 TREE_USED (t) = 1;
2206 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2207 DECL_ARGUMENTS (decl) = t;
2208 }
2209
2210 tree data_name = get_identifier (".omp_data_i");
2211 t = build_decl (DECL_SOURCE_LOCATION (decl), PARM_DECL, data_name,
2212 ptr_type_node);
1e8e9920 2213 DECL_ARTIFICIAL (t) = 1;
84bfaaeb 2214 DECL_NAMELESS (t) = 1;
1e8e9920 2215 DECL_ARG_TYPE (t) = ptr_type_node;
773c5ba7 2216 DECL_CONTEXT (t) = current_function_decl;
1e8e9920 2217 TREE_USED (t) = 1;
40750995 2218 if (cilk_for_count)
2219 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
1e8e9920 2220 DECL_ARGUMENTS (decl) = t;
fd6481cf 2221 if (!task_copy)
2222 ctx->receiver_decl = t;
2223 else
2224 {
e60a6f7b 2225 t = build_decl (DECL_SOURCE_LOCATION (decl),
2226 PARM_DECL, get_identifier (".omp_data_o"),
fd6481cf 2227 ptr_type_node);
2228 DECL_ARTIFICIAL (t) = 1;
84bfaaeb 2229 DECL_NAMELESS (t) = 1;
fd6481cf 2230 DECL_ARG_TYPE (t) = ptr_type_node;
2231 DECL_CONTEXT (t) = current_function_decl;
2232 TREE_USED (t) = 1;
86f2ad37 2233 TREE_ADDRESSABLE (t) = 1;
1767a056 2234 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
fd6481cf 2235 DECL_ARGUMENTS (decl) = t;
2236 }
1e8e9920 2237
48e1416a 2238 /* Allocate memory for the function structure. The call to
773c5ba7 2239 allocate_struct_function clobbers CFUN, so we need to restore
1e8e9920 2240 it afterward. */
87d4aa85 2241 push_struct_function (decl);
75a70cf9 2242 cfun->function_end_locus = gimple_location (ctx->stmt);
87d4aa85 2243 pop_cfun ();
1e8e9920 2244}
2245
bc7bff74 2246/* Callback for walk_gimple_seq. Check if combined parallel
2247 contains gimple_omp_for_combined_into_p OMP_FOR. */
2248
2249static tree
2250find_combined_for (gimple_stmt_iterator *gsi_p,
2251 bool *handled_ops_p,
2252 struct walk_stmt_info *wi)
2253{
2254 gimple stmt = gsi_stmt (*gsi_p);
2255
2256 *handled_ops_p = true;
2257 switch (gimple_code (stmt))
2258 {
2259 WALK_SUBSTMTS;
2260
2261 case GIMPLE_OMP_FOR:
2262 if (gimple_omp_for_combined_into_p (stmt)
2263 && gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR)
2264 {
2265 wi->info = stmt;
2266 return integer_zero_node;
2267 }
2268 break;
2269 default:
2270 break;
2271 }
2272 return NULL;
2273}
2274
1e8e9920 2275/* Scan an OpenMP parallel directive. */
2276
2277static void
75a70cf9 2278scan_omp_parallel (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
1e8e9920 2279{
2280 omp_context *ctx;
2281 tree name;
1a91d914 2282 gomp_parallel *stmt = as_a <gomp_parallel *> (gsi_stmt (*gsi));
1e8e9920 2283
2284 /* Ignore parallel directives with empty bodies, unless there
2285 are copyin clauses. */
2286 if (optimize > 0
75a70cf9 2287 && empty_body_p (gimple_omp_body (stmt))
2288 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
2289 OMP_CLAUSE_COPYIN) == NULL)
1e8e9920 2290 {
75a70cf9 2291 gsi_replace (gsi, gimple_build_nop (), false);
1e8e9920 2292 return;
2293 }
2294
bc7bff74 2295 if (gimple_omp_parallel_combined_p (stmt))
2296 {
bc7bff74 2297 struct walk_stmt_info wi;
2298
2299 memset (&wi, 0, sizeof (wi));
2300 wi.val_only = true;
2301 walk_gimple_seq (gimple_omp_body (stmt),
2302 find_combined_for, NULL, &wi);
1a91d914 2303 if (wi.info)
bc7bff74 2304 {
1a91d914 2305 gomp_for *for_stmt = as_a <gomp_for *> ((gimple) wi.info);
bc7bff74 2306 struct omp_for_data fd;
2307 extract_omp_for_data (for_stmt, &fd, NULL);
2308 /* We need two temporaries with fd.loop.v type (istart/iend)
2309 and then (fd.collapse - 1) temporaries with the same
2310 type for count2 ... countN-1 vars if not constant. */
2311 size_t count = 2, i;
2312 tree type = fd.iter_type;
2313 if (fd.collapse > 1
2314 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
2315 count += fd.collapse - 1;
2316 for (i = 0; i < count; i++)
2317 {
f9e245b2 2318 tree temp = create_tmp_var (type);
bc7bff74 2319 tree c = build_omp_clause (UNKNOWN_LOCATION,
2320 OMP_CLAUSE__LOOPTEMP_);
691447ab 2321 insert_decl_map (&outer_ctx->cb, temp, temp);
bc7bff74 2322 OMP_CLAUSE_DECL (c) = temp;
2323 OMP_CLAUSE_CHAIN (c) = gimple_omp_parallel_clauses (stmt);
2324 gimple_omp_parallel_set_clauses (stmt, c);
2325 }
2326 }
2327 }
2328
75a70cf9 2329 ctx = new_omp_context (stmt, outer_ctx);
37eaded9 2330 taskreg_contexts.safe_push (ctx);
fd6481cf 2331 if (taskreg_nesting_level > 1)
773c5ba7 2332 ctx->is_nested = true;
1e8e9920 2333 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1e8e9920 2334 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2335 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
1e8e9920 2336 name = create_tmp_var_name (".omp_data_s");
e60a6f7b 2337 name = build_decl (gimple_location (stmt),
2338 TYPE_DECL, name, ctx->record_type);
84bfaaeb 2339 DECL_ARTIFICIAL (name) = 1;
2340 DECL_NAMELESS (name) = 1;
1e8e9920 2341 TYPE_NAME (ctx->record_type) = name;
240131b5 2342 TYPE_ARTIFICIAL (ctx->record_type) = 1;
fd6481cf 2343 create_omp_child_function (ctx, false);
75a70cf9 2344 gimple_omp_parallel_set_child_fn (stmt, ctx->cb.dst_fn);
1e8e9920 2345
75a70cf9 2346 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt), ctx);
ab129075 2347 scan_omp (gimple_omp_body_ptr (stmt), ctx);
1e8e9920 2348
2349 if (TYPE_FIELDS (ctx->record_type) == NULL)
2350 ctx->record_type = ctx->receiver_decl = NULL;
1e8e9920 2351}
2352
fd6481cf 2353/* Scan an OpenMP task directive. */
2354
2355static void
75a70cf9 2356scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
fd6481cf 2357{
2358 omp_context *ctx;
75a70cf9 2359 tree name, t;
1a91d914 2360 gomp_task *stmt = as_a <gomp_task *> (gsi_stmt (*gsi));
fd6481cf 2361
2362 /* Ignore task directives with empty bodies. */
2363 if (optimize > 0
75a70cf9 2364 && empty_body_p (gimple_omp_body (stmt)))
fd6481cf 2365 {
75a70cf9 2366 gsi_replace (gsi, gimple_build_nop (), false);
fd6481cf 2367 return;
2368 }
2369
75a70cf9 2370 ctx = new_omp_context (stmt, outer_ctx);
37eaded9 2371 taskreg_contexts.safe_push (ctx);
fd6481cf 2372 if (taskreg_nesting_level > 1)
2373 ctx->is_nested = true;
2374 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2375 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2376 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2377 name = create_tmp_var_name (".omp_data_s");
e60a6f7b 2378 name = build_decl (gimple_location (stmt),
2379 TYPE_DECL, name, ctx->record_type);
84bfaaeb 2380 DECL_ARTIFICIAL (name) = 1;
2381 DECL_NAMELESS (name) = 1;
fd6481cf 2382 TYPE_NAME (ctx->record_type) = name;
240131b5 2383 TYPE_ARTIFICIAL (ctx->record_type) = 1;
fd6481cf 2384 create_omp_child_function (ctx, false);
75a70cf9 2385 gimple_omp_task_set_child_fn (stmt, ctx->cb.dst_fn);
fd6481cf 2386
75a70cf9 2387 scan_sharing_clauses (gimple_omp_task_clauses (stmt), ctx);
fd6481cf 2388
2389 if (ctx->srecord_type)
2390 {
2391 name = create_tmp_var_name (".omp_data_a");
e60a6f7b 2392 name = build_decl (gimple_location (stmt),
2393 TYPE_DECL, name, ctx->srecord_type);
84bfaaeb 2394 DECL_ARTIFICIAL (name) = 1;
2395 DECL_NAMELESS (name) = 1;
fd6481cf 2396 TYPE_NAME (ctx->srecord_type) = name;
240131b5 2397 TYPE_ARTIFICIAL (ctx->srecord_type) = 1;
fd6481cf 2398 create_omp_child_function (ctx, true);
2399 }
2400
ab129075 2401 scan_omp (gimple_omp_body_ptr (stmt), ctx);
fd6481cf 2402
2403 if (TYPE_FIELDS (ctx->record_type) == NULL)
2404 {
2405 ctx->record_type = ctx->receiver_decl = NULL;
75a70cf9 2406 t = build_int_cst (long_integer_type_node, 0);
2407 gimple_omp_task_set_arg_size (stmt, t);
2408 t = build_int_cst (long_integer_type_node, 1);
2409 gimple_omp_task_set_arg_align (stmt, t);
fd6481cf 2410 }
37eaded9 2411}
2412
2413
2414/* If any decls have been made addressable during scan_omp,
2415 adjust their fields if needed, and layout record types
2416 of parallel/task constructs. */
2417
2418static void
2419finish_taskreg_scan (omp_context *ctx)
2420{
2421 if (ctx->record_type == NULL_TREE)
2422 return;
2423
2424 /* If any task_shared_vars were needed, verify all
2425 OMP_CLAUSE_SHARED clauses on GIMPLE_OMP_{PARALLEL,TASK}
2426 statements if use_pointer_for_field hasn't changed
2427 because of that. If it did, update field types now. */
2428 if (task_shared_vars)
2429 {
2430 tree c;
2431
2432 for (c = gimple_omp_taskreg_clauses (ctx->stmt);
2433 c; c = OMP_CLAUSE_CHAIN (c))
2434 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED)
2435 {
2436 tree decl = OMP_CLAUSE_DECL (c);
2437
2438 /* Global variables don't need to be copied,
2439 the receiver side will use them directly. */
2440 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
2441 continue;
2442 if (!bitmap_bit_p (task_shared_vars, DECL_UID (decl))
2443 || !use_pointer_for_field (decl, ctx))
2444 continue;
2445 tree field = lookup_field (decl, ctx);
2446 if (TREE_CODE (TREE_TYPE (field)) == POINTER_TYPE
2447 && TREE_TYPE (TREE_TYPE (field)) == TREE_TYPE (decl))
2448 continue;
2449 TREE_TYPE (field) = build_pointer_type (TREE_TYPE (decl));
2450 TREE_THIS_VOLATILE (field) = 0;
2451 DECL_USER_ALIGN (field) = 0;
2452 DECL_ALIGN (field) = TYPE_ALIGN (TREE_TYPE (field));
2453 if (TYPE_ALIGN (ctx->record_type) < DECL_ALIGN (field))
2454 TYPE_ALIGN (ctx->record_type) = DECL_ALIGN (field);
2455 if (ctx->srecord_type)
2456 {
2457 tree sfield = lookup_sfield (decl, ctx);
2458 TREE_TYPE (sfield) = TREE_TYPE (field);
2459 TREE_THIS_VOLATILE (sfield) = 0;
2460 DECL_USER_ALIGN (sfield) = 0;
2461 DECL_ALIGN (sfield) = DECL_ALIGN (field);
2462 if (TYPE_ALIGN (ctx->srecord_type) < DECL_ALIGN (sfield))
2463 TYPE_ALIGN (ctx->srecord_type) = DECL_ALIGN (sfield);
2464 }
2465 }
2466 }
2467
2468 if (gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2469 {
2470 layout_type (ctx->record_type);
2471 fixup_child_record_type (ctx);
2472 }
fd6481cf 2473 else
2474 {
37eaded9 2475 location_t loc = gimple_location (ctx->stmt);
fd6481cf 2476 tree *p, vla_fields = NULL_TREE, *q = &vla_fields;
2477 /* Move VLA fields to the end. */
2478 p = &TYPE_FIELDS (ctx->record_type);
2479 while (*p)
2480 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p))
2481 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p))))
2482 {
2483 *q = *p;
2484 *p = TREE_CHAIN (*p);
2485 TREE_CHAIN (*q) = NULL_TREE;
2486 q = &TREE_CHAIN (*q);
2487 }
2488 else
1767a056 2489 p = &DECL_CHAIN (*p);
fd6481cf 2490 *p = vla_fields;
2491 layout_type (ctx->record_type);
2492 fixup_child_record_type (ctx);
2493 if (ctx->srecord_type)
2494 layout_type (ctx->srecord_type);
37eaded9 2495 tree t = fold_convert_loc (loc, long_integer_type_node,
2496 TYPE_SIZE_UNIT (ctx->record_type));
2497 gimple_omp_task_set_arg_size (ctx->stmt, t);
75a70cf9 2498 t = build_int_cst (long_integer_type_node,
fd6481cf 2499 TYPE_ALIGN_UNIT (ctx->record_type));
37eaded9 2500 gimple_omp_task_set_arg_align (ctx->stmt, t);
fd6481cf 2501 }
2502}
2503
1e8e9920 2504
ca4c3545 2505static omp_context *
2506enclosing_target_ctx (omp_context *ctx)
2507{
2508 while (ctx != NULL
2509 && gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET)
2510 ctx = ctx->outer;
2511 gcc_assert (ctx != NULL);
2512 return ctx;
2513}
2514
2515static bool
2516oacc_loop_or_target_p (gimple stmt)
2517{
2518 enum gimple_code outer_type = gimple_code (stmt);
2519 return ((outer_type == GIMPLE_OMP_TARGET
2520 && ((gimple_omp_target_kind (stmt)
2521 == GF_OMP_TARGET_KIND_OACC_PARALLEL)
2522 || (gimple_omp_target_kind (stmt)
2523 == GF_OMP_TARGET_KIND_OACC_KERNELS)))
2524 || (outer_type == GIMPLE_OMP_FOR
2525 && gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_OACC_LOOP));
2526}
2527
2528/* Scan a GIMPLE_OMP_FOR. */
1e8e9920 2529
2530static void
1a91d914 2531scan_omp_for (gomp_for *stmt, omp_context *outer_ctx)
1e8e9920 2532{
ca4c3545 2533 enum gimple_code outer_type = GIMPLE_ERROR_MARK;
773c5ba7 2534 omp_context *ctx;
75a70cf9 2535 size_t i;
ca4c3545 2536 tree clauses = gimple_omp_for_clauses (stmt);
2537
2538 if (outer_ctx)
2539 outer_type = gimple_code (outer_ctx->stmt);
1e8e9920 2540
773c5ba7 2541 ctx = new_omp_context (stmt, outer_ctx);
1e8e9920 2542
ca4c3545 2543 if (is_gimple_omp_oacc (stmt))
2544 {
2545 if (outer_ctx && outer_type == GIMPLE_OMP_FOR)
2546 ctx->gwv_this = outer_ctx->gwv_this;
2547 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2548 {
2549 int val;
2550 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_GANG)
2551 val = MASK_GANG;
2552 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_WORKER)
2553 val = MASK_WORKER;
2554 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_VECTOR)
2555 val = MASK_VECTOR;
2556 else
2557 continue;
2558 ctx->gwv_this |= val;
2559 if (!outer_ctx)
2560 {
2561 /* Skip; not nested inside a region. */
2562 continue;
2563 }
2564 if (!oacc_loop_or_target_p (outer_ctx->stmt))
2565 {
2566 /* Skip; not nested inside an OpenACC region. */
2567 continue;
2568 }
2569 if (outer_type == GIMPLE_OMP_FOR)
2570 outer_ctx->gwv_below |= val;
2571 if (OMP_CLAUSE_OPERAND (c, 0) != NULL_TREE)
2572 {
2573 omp_context *enclosing = enclosing_target_ctx (outer_ctx);
2574 if (gimple_omp_target_kind (enclosing->stmt)
2575 == GF_OMP_TARGET_KIND_OACC_PARALLEL)
2576 error_at (gimple_location (stmt),
2577 "no arguments allowed to gang, worker and vector clauses inside parallel");
2578 }
2579 }
2580 }
2581
2582 scan_sharing_clauses (clauses, ctx);
1e8e9920 2583
ab129075 2584 scan_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
75a70cf9 2585 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
fd6481cf 2586 {
75a70cf9 2587 scan_omp_op (gimple_omp_for_index_ptr (stmt, i), ctx);
2588 scan_omp_op (gimple_omp_for_initial_ptr (stmt, i), ctx);
2589 scan_omp_op (gimple_omp_for_final_ptr (stmt, i), ctx);
2590 scan_omp_op (gimple_omp_for_incr_ptr (stmt, i), ctx);
fd6481cf 2591 }
ab129075 2592 scan_omp (gimple_omp_body_ptr (stmt), ctx);
ca4c3545 2593
2594 if (is_gimple_omp_oacc (stmt))
2595 {
2596 if (ctx->gwv_this & ctx->gwv_below)
2597 error_at (gimple_location (stmt),
2598 "gang, worker and vector may occur only once in a loop nest");
2599 else if (ctx->gwv_below != 0
2600 && ctx->gwv_this > ctx->gwv_below)
2601 error_at (gimple_location (stmt),
2602 "gang, worker and vector must occur in this order in a loop nest");
2603 if (outer_ctx && outer_type == GIMPLE_OMP_FOR)
2604 outer_ctx->gwv_below |= ctx->gwv_below;
2605 }
1e8e9920 2606}
2607
2608/* Scan an OpenMP sections directive. */
2609
2610static void
1a91d914 2611scan_omp_sections (gomp_sections *stmt, omp_context *outer_ctx)
1e8e9920 2612{
1e8e9920 2613 omp_context *ctx;
2614
2615 ctx = new_omp_context (stmt, outer_ctx);
75a70cf9 2616 scan_sharing_clauses (gimple_omp_sections_clauses (stmt), ctx);
ab129075 2617 scan_omp (gimple_omp_body_ptr (stmt), ctx);
1e8e9920 2618}
2619
2620/* Scan an OpenMP single directive. */
2621
2622static void
1a91d914 2623scan_omp_single (gomp_single *stmt, omp_context *outer_ctx)
1e8e9920 2624{
1e8e9920 2625 omp_context *ctx;
2626 tree name;
2627
2628 ctx = new_omp_context (stmt, outer_ctx);
2629 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2630 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2631 name = create_tmp_var_name (".omp_copy_s");
e60a6f7b 2632 name = build_decl (gimple_location (stmt),
2633 TYPE_DECL, name, ctx->record_type);
1e8e9920 2634 TYPE_NAME (ctx->record_type) = name;
2635
75a70cf9 2636 scan_sharing_clauses (gimple_omp_single_clauses (stmt), ctx);
ab129075 2637 scan_omp (gimple_omp_body_ptr (stmt), ctx);
1e8e9920 2638
2639 if (TYPE_FIELDS (ctx->record_type) == NULL)
2640 ctx->record_type = NULL;
2641 else
2642 layout_type (ctx->record_type);
2643}
2644
ca4c3545 2645/* Scan a GIMPLE_OMP_TARGET. */
bc7bff74 2646
2647static void
1a91d914 2648scan_omp_target (gomp_target *stmt, omp_context *outer_ctx)
bc7bff74 2649{
2650 omp_context *ctx;
2651 tree name;
ca4c3545 2652 bool offloaded = is_gimple_omp_offloaded (stmt);
2653 tree clauses = gimple_omp_target_clauses (stmt);
bc7bff74 2654
2655 ctx = new_omp_context (stmt, outer_ctx);
2656 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2657 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2658 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2659 name = create_tmp_var_name (".omp_data_t");
2660 name = build_decl (gimple_location (stmt),
2661 TYPE_DECL, name, ctx->record_type);
2662 DECL_ARTIFICIAL (name) = 1;
2663 DECL_NAMELESS (name) = 1;
2664 TYPE_NAME (ctx->record_type) = name;
240131b5 2665 TYPE_ARTIFICIAL (ctx->record_type) = 1;
ca4c3545 2666 if (offloaded)
bc7bff74 2667 {
ca4c3545 2668 if (is_gimple_omp_oacc (stmt))
2669 ctx->reduction_map = splay_tree_new (splay_tree_compare_pointers,
2670 0, 0);
2671
bc7bff74 2672 create_omp_child_function (ctx, false);
2673 gimple_omp_target_set_child_fn (stmt, ctx->cb.dst_fn);
2674 }
2675
ca4c3545 2676 if (is_gimple_omp_oacc (stmt))
2677 {
2678 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2679 {
2680 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NUM_GANGS)
2681 ctx->gwv_this |= MASK_GANG;
2682 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NUM_WORKERS)
2683 ctx->gwv_this |= MASK_WORKER;
2684 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_VECTOR_LENGTH)
2685 ctx->gwv_this |= MASK_VECTOR;
2686 }
2687 }
2688
2689 scan_sharing_clauses (clauses, ctx);
bc7bff74 2690 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2691
2692 if (TYPE_FIELDS (ctx->record_type) == NULL)
2693 ctx->record_type = ctx->receiver_decl = NULL;
2694 else
2695 {
2696 TYPE_FIELDS (ctx->record_type)
2697 = nreverse (TYPE_FIELDS (ctx->record_type));
2698#ifdef ENABLE_CHECKING
2699 tree field;
2700 unsigned int align = DECL_ALIGN (TYPE_FIELDS (ctx->record_type));
2701 for (field = TYPE_FIELDS (ctx->record_type);
2702 field;
2703 field = DECL_CHAIN (field))
2704 gcc_assert (DECL_ALIGN (field) == align);
2705#endif
2706 layout_type (ctx->record_type);
ca4c3545 2707 if (offloaded)
bc7bff74 2708 fixup_child_record_type (ctx);
2709 }
2710}
2711
2712/* Scan an OpenMP teams directive. */
2713
2714static void
1a91d914 2715scan_omp_teams (gomp_teams *stmt, omp_context *outer_ctx)
bc7bff74 2716{
2717 omp_context *ctx = new_omp_context (stmt, outer_ctx);
2718 scan_sharing_clauses (gimple_omp_teams_clauses (stmt), ctx);
2719 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2720}
1e8e9920 2721
ca4c3545 2722/* Check nesting restrictions. */
ab129075 2723static bool
2724check_omp_nesting_restrictions (gimple stmt, omp_context *ctx)
c1d127dd 2725{
ca4c3545 2726 /* No nesting of non-OpenACC STMT (that is, an OpenMP one, or a GOMP builtin)
2727 inside an OpenACC CTX. */
2728 if (!(is_gimple_omp (stmt)
2729 && is_gimple_omp_oacc (stmt)))
2730 {
2731 for (omp_context *ctx_ = ctx; ctx_ != NULL; ctx_ = ctx_->outer)
2732 if (is_gimple_omp (ctx_->stmt)
2733 && is_gimple_omp_oacc (ctx_->stmt))
2734 {
2735 error_at (gimple_location (stmt),
2736 "non-OpenACC construct inside of OpenACC region");
2737 return false;
2738 }
2739 }
2740
3d483a94 2741 if (ctx != NULL)
2742 {
2743 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
10c55644 2744 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3d483a94 2745 {
2746 error_at (gimple_location (stmt),
2747 "OpenMP constructs may not be nested inside simd region");
2748 return false;
2749 }
bc7bff74 2750 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
2751 {
2752 if ((gimple_code (stmt) != GIMPLE_OMP_FOR
2753 || (gimple_omp_for_kind (stmt)
2754 != GF_OMP_FOR_KIND_DISTRIBUTE))
2755 && gimple_code (stmt) != GIMPLE_OMP_PARALLEL)
2756 {
2757 error_at (gimple_location (stmt),
2758 "only distribute or parallel constructs are allowed to "
2759 "be closely nested inside teams construct");
2760 return false;
2761 }
2762 }
3d483a94 2763 }
75a70cf9 2764 switch (gimple_code (stmt))
c1d127dd 2765 {
75a70cf9 2766 case GIMPLE_OMP_FOR:
10c55644 2767 if (gimple_omp_for_kind (stmt) & GF_OMP_FOR_SIMD)
3d483a94 2768 return true;
bc7bff74 2769 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
2770 {
2771 if (ctx != NULL && gimple_code (ctx->stmt) != GIMPLE_OMP_TEAMS)
2772 {
2773 error_at (gimple_location (stmt),
2774 "distribute construct must be closely nested inside "
2775 "teams construct");
2776 return false;
2777 }
2778 return true;
2779 }
2780 /* FALLTHRU */
2781 case GIMPLE_CALL:
2782 if (is_gimple_call (stmt)
2783 && (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2784 == BUILT_IN_GOMP_CANCEL
2785 || DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2786 == BUILT_IN_GOMP_CANCELLATION_POINT))
2787 {
2788 const char *bad = NULL;
2789 const char *kind = NULL;
2790 if (ctx == NULL)
2791 {
2792 error_at (gimple_location (stmt), "orphaned %qs construct",
2793 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2794 == BUILT_IN_GOMP_CANCEL
2795 ? "#pragma omp cancel"
2796 : "#pragma omp cancellation point");
2797 return false;
2798 }
6b409616 2799 switch (tree_fits_shwi_p (gimple_call_arg (stmt, 0))
2800 ? tree_to_shwi (gimple_call_arg (stmt, 0))
bc7bff74 2801 : 0)
2802 {
2803 case 1:
2804 if (gimple_code (ctx->stmt) != GIMPLE_OMP_PARALLEL)
2805 bad = "#pragma omp parallel";
2806 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2807 == BUILT_IN_GOMP_CANCEL
2808 && !integer_zerop (gimple_call_arg (stmt, 1)))
2809 ctx->cancellable = true;
2810 kind = "parallel";
2811 break;
2812 case 2:
2813 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
2814 || gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR)
2815 bad = "#pragma omp for";
2816 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2817 == BUILT_IN_GOMP_CANCEL
2818 && !integer_zerop (gimple_call_arg (stmt, 1)))
2819 {
2820 ctx->cancellable = true;
2821 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2822 OMP_CLAUSE_NOWAIT))
2823 warning_at (gimple_location (stmt), 0,
2824 "%<#pragma omp cancel for%> inside "
2825 "%<nowait%> for construct");
2826 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2827 OMP_CLAUSE_ORDERED))
2828 warning_at (gimple_location (stmt), 0,
2829 "%<#pragma omp cancel for%> inside "
2830 "%<ordered%> for construct");
2831 }
2832 kind = "for";
2833 break;
2834 case 4:
2835 if (gimple_code (ctx->stmt) != GIMPLE_OMP_SECTIONS
2836 && gimple_code (ctx->stmt) != GIMPLE_OMP_SECTION)
2837 bad = "#pragma omp sections";
2838 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2839 == BUILT_IN_GOMP_CANCEL
2840 && !integer_zerop (gimple_call_arg (stmt, 1)))
2841 {
2842 if (gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS)
2843 {
2844 ctx->cancellable = true;
2845 if (find_omp_clause (gimple_omp_sections_clauses
2846 (ctx->stmt),
2847 OMP_CLAUSE_NOWAIT))
2848 warning_at (gimple_location (stmt), 0,
2849 "%<#pragma omp cancel sections%> inside "
2850 "%<nowait%> sections construct");
2851 }
2852 else
2853 {
2854 gcc_assert (ctx->outer
2855 && gimple_code (ctx->outer->stmt)
2856 == GIMPLE_OMP_SECTIONS);
2857 ctx->outer->cancellable = true;
2858 if (find_omp_clause (gimple_omp_sections_clauses
2859 (ctx->outer->stmt),
2860 OMP_CLAUSE_NOWAIT))
2861 warning_at (gimple_location (stmt), 0,
2862 "%<#pragma omp cancel sections%> inside "
2863 "%<nowait%> sections construct");
2864 }
2865 }
2866 kind = "sections";
2867 break;
2868 case 8:
2869 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TASK)
2870 bad = "#pragma omp task";
2871 else
2872 ctx->cancellable = true;
2873 kind = "taskgroup";
2874 break;
2875 default:
2876 error_at (gimple_location (stmt), "invalid arguments");
2877 return false;
2878 }
2879 if (bad)
2880 {
2881 error_at (gimple_location (stmt),
2882 "%<%s %s%> construct not closely nested inside of %qs",
2883 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2884 == BUILT_IN_GOMP_CANCEL
2885 ? "#pragma omp cancel"
2886 : "#pragma omp cancellation point", kind, bad);
2887 return false;
2888 }
2889 }
3d483a94 2890 /* FALLTHRU */
75a70cf9 2891 case GIMPLE_OMP_SECTIONS:
2892 case GIMPLE_OMP_SINGLE:
c1d127dd 2893 for (; ctx != NULL; ctx = ctx->outer)
75a70cf9 2894 switch (gimple_code (ctx->stmt))
c1d127dd 2895 {
75a70cf9 2896 case GIMPLE_OMP_FOR:
2897 case GIMPLE_OMP_SECTIONS:
2898 case GIMPLE_OMP_SINGLE:
2899 case GIMPLE_OMP_ORDERED:
2900 case GIMPLE_OMP_MASTER:
2901 case GIMPLE_OMP_TASK:
bc7bff74 2902 case GIMPLE_OMP_CRITICAL:
75a70cf9 2903 if (is_gimple_call (stmt))
fd6481cf 2904 {
bc7bff74 2905 if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2906 != BUILT_IN_GOMP_BARRIER)
2907 return true;
ab129075 2908 error_at (gimple_location (stmt),
2909 "barrier region may not be closely nested inside "
2910 "of work-sharing, critical, ordered, master or "
2911 "explicit task region");
2912 return false;
fd6481cf 2913 }
ab129075 2914 error_at (gimple_location (stmt),
2915 "work-sharing region may not be closely nested inside "
2916 "of work-sharing, critical, ordered, master or explicit "
2917 "task region");
2918 return false;
75a70cf9 2919 case GIMPLE_OMP_PARALLEL:
ab129075 2920 return true;
c1d127dd 2921 default:
2922 break;
2923 }
2924 break;
75a70cf9 2925 case GIMPLE_OMP_MASTER:
c1d127dd 2926 for (; ctx != NULL; ctx = ctx->outer)
75a70cf9 2927 switch (gimple_code (ctx->stmt))
c1d127dd 2928 {
75a70cf9 2929 case GIMPLE_OMP_FOR:
2930 case GIMPLE_OMP_SECTIONS:
2931 case GIMPLE_OMP_SINGLE:
2932 case GIMPLE_OMP_TASK:
ab129075 2933 error_at (gimple_location (stmt),
2934 "master region may not be closely nested inside "
2935 "of work-sharing or explicit task region");
2936 return false;
75a70cf9 2937 case GIMPLE_OMP_PARALLEL:
ab129075 2938 return true;
c1d127dd 2939 default:
2940 break;
2941 }
2942 break;
75a70cf9 2943 case GIMPLE_OMP_ORDERED:
c1d127dd 2944 for (; ctx != NULL; ctx = ctx->outer)
75a70cf9 2945 switch (gimple_code (ctx->stmt))
c1d127dd 2946 {
75a70cf9 2947 case GIMPLE_OMP_CRITICAL:
2948 case GIMPLE_OMP_TASK:
ab129075 2949 error_at (gimple_location (stmt),
2950 "ordered region may not be closely nested inside "
2951 "of critical or explicit task region");
2952 return false;
75a70cf9 2953 case GIMPLE_OMP_FOR:
2954 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
c1d127dd 2955 OMP_CLAUSE_ORDERED) == NULL)
ab129075 2956 {
2957 error_at (gimple_location (stmt),
2958 "ordered region must be closely nested inside "
c1d127dd 2959 "a loop region with an ordered clause");
ab129075 2960 return false;
2961 }
2962 return true;
75a70cf9 2963 case GIMPLE_OMP_PARALLEL:
bc7bff74 2964 error_at (gimple_location (stmt),
2965 "ordered region must be closely nested inside "
2966 "a loop region with an ordered clause");
2967 return false;
c1d127dd 2968 default:
2969 break;
2970 }
2971 break;
75a70cf9 2972 case GIMPLE_OMP_CRITICAL:
1a91d914 2973 {
2974 tree this_stmt_name
2975 = gimple_omp_critical_name (as_a <gomp_critical *> (stmt));
2976 for (; ctx != NULL; ctx = ctx->outer)
2977 if (gomp_critical *other_crit
2978 = dyn_cast <gomp_critical *> (ctx->stmt))
2979 if (this_stmt_name == gimple_omp_critical_name (other_crit))
2980 {
2981 error_at (gimple_location (stmt),
2982 "critical region may not be nested inside a critical "
2983 "region with the same name");
2984 return false;
2985 }
2986 }
c1d127dd 2987 break;
bc7bff74 2988 case GIMPLE_OMP_TEAMS:
2989 if (ctx == NULL
2990 || gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET
2991 || gimple_omp_target_kind (ctx->stmt) != GF_OMP_TARGET_KIND_REGION)
2992 {
2993 error_at (gimple_location (stmt),
2994 "teams construct not closely nested inside of target "
2995 "region");
2996 return false;
2997 }
2998 break;
691447ab 2999 case GIMPLE_OMP_TARGET:
3000 for (; ctx != NULL; ctx = ctx->outer)
ca4c3545 3001 {
3002 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET)
3003 {
3004 if (is_gimple_omp (stmt)
3005 && is_gimple_omp_oacc (stmt)
3006 && is_gimple_omp (ctx->stmt))
3007 {
3008 error_at (gimple_location (stmt),
3009 "OpenACC construct inside of non-OpenACC region");
3010 return false;
3011 }
3012 continue;
3013 }
3014
3015 const char *stmt_name, *ctx_stmt_name;
3016 switch (gimple_omp_target_kind (stmt))
3017 {
3018 case GF_OMP_TARGET_KIND_REGION: stmt_name = "target"; break;
3019 case GF_OMP_TARGET_KIND_DATA: stmt_name = "target data"; break;
3020 case GF_OMP_TARGET_KIND_UPDATE: stmt_name = "target update"; break;
3021 case GF_OMP_TARGET_KIND_OACC_PARALLEL: stmt_name = "parallel"; break;
3022 case GF_OMP_TARGET_KIND_OACC_KERNELS: stmt_name = "kernels"; break;
3023 case GF_OMP_TARGET_KIND_OACC_DATA: stmt_name = "data"; break;
3024 case GF_OMP_TARGET_KIND_OACC_UPDATE: stmt_name = "update"; break;
3025 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA: stmt_name = "enter/exit data"; break;
3026 default: gcc_unreachable ();
3027 }
3028 switch (gimple_omp_target_kind (ctx->stmt))
3029 {
3030 case GF_OMP_TARGET_KIND_REGION: ctx_stmt_name = "target"; break;
3031 case GF_OMP_TARGET_KIND_DATA: ctx_stmt_name = "target data"; break;
3032 case GF_OMP_TARGET_KIND_OACC_PARALLEL: ctx_stmt_name = "parallel"; break;
3033 case GF_OMP_TARGET_KIND_OACC_KERNELS: ctx_stmt_name = "kernels"; break;
3034 case GF_OMP_TARGET_KIND_OACC_DATA: ctx_stmt_name = "data"; break;
3035 default: gcc_unreachable ();
3036 }
3037
3038 /* OpenACC/OpenMP mismatch? */
3039 if (is_gimple_omp_oacc (stmt)
3040 != is_gimple_omp_oacc (ctx->stmt))
3041 {
3042 error_at (gimple_location (stmt),
3043 "%s %s construct inside of %s %s region",
3044 (is_gimple_omp_oacc (stmt)
3045 ? "OpenACC" : "OpenMP"), stmt_name,
3046 (is_gimple_omp_oacc (ctx->stmt)
3047 ? "OpenACC" : "OpenMP"), ctx_stmt_name);
3048 return false;
3049 }
3050 if (is_gimple_omp_offloaded (ctx->stmt))
3051 {
3052 /* No GIMPLE_OMP_TARGET inside offloaded OpenACC CTX. */
3053 if (is_gimple_omp_oacc (ctx->stmt))
3054 {
3055 error_at (gimple_location (stmt),
3056 "%s construct inside of %s region",
3057 stmt_name, ctx_stmt_name);
3058 return false;
3059 }
3060 else
3061 {
3062 gcc_checking_assert (!is_gimple_omp_oacc (stmt));
3063 warning_at (gimple_location (stmt), 0,
3064 "%s construct inside of %s region",
3065 stmt_name, ctx_stmt_name);
3066 }
3067 }
3068 }
691447ab 3069 break;
c1d127dd 3070 default:
3071 break;
3072 }
ab129075 3073 return true;
c1d127dd 3074}
3075
3076
75a70cf9 3077/* Helper function scan_omp.
3078
3079 Callback for walk_tree or operators in walk_gimple_stmt used to
ca4c3545 3080 scan for OMP directives in TP. */
1e8e9920 3081
3082static tree
75a70cf9 3083scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
1e8e9920 3084{
4077bf7a 3085 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
3086 omp_context *ctx = (omp_context *) wi->info;
1e8e9920 3087 tree t = *tp;
3088
75a70cf9 3089 switch (TREE_CODE (t))
3090 {
3091 case VAR_DECL:
3092 case PARM_DECL:
3093 case LABEL_DECL:
3094 case RESULT_DECL:
3095 if (ctx)
3096 *tp = remap_decl (t, &ctx->cb);
3097 break;
3098
3099 default:
3100 if (ctx && TYPE_P (t))
3101 *tp = remap_type (t, &ctx->cb);
3102 else if (!DECL_P (t))
7cf869dd 3103 {
3104 *walk_subtrees = 1;
3105 if (ctx)
182cf5a9 3106 {
3107 tree tem = remap_type (TREE_TYPE (t), &ctx->cb);
3108 if (tem != TREE_TYPE (t))
3109 {
3110 if (TREE_CODE (t) == INTEGER_CST)
e913b5cd 3111 *tp = wide_int_to_tree (tem, t);
182cf5a9 3112 else
3113 TREE_TYPE (t) = tem;
3114 }
3115 }
7cf869dd 3116 }
75a70cf9 3117 break;
3118 }
3119
3120 return NULL_TREE;
3121}
3122
f2697631 3123/* Return true if FNDECL is a setjmp or a longjmp. */
3124
3125static bool
3126setjmp_or_longjmp_p (const_tree fndecl)
3127{
3128 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
3129 && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_SETJMP
3130 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LONGJMP))
3131 return true;
3132
3133 tree declname = DECL_NAME (fndecl);
3134 if (!declname)
3135 return false;
3136 const char *name = IDENTIFIER_POINTER (declname);
3137 return !strcmp (name, "setjmp") || !strcmp (name, "longjmp");
3138}
3139
75a70cf9 3140
3141/* Helper function for scan_omp.
3142
ca4c3545 3143 Callback for walk_gimple_stmt used to scan for OMP directives in
75a70cf9 3144 the current statement in GSI. */
3145
3146static tree
3147scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
3148 struct walk_stmt_info *wi)
3149{
3150 gimple stmt = gsi_stmt (*gsi);
3151 omp_context *ctx = (omp_context *) wi->info;
3152
3153 if (gimple_has_location (stmt))
3154 input_location = gimple_location (stmt);
1e8e9920 3155
ca4c3545 3156 /* Check the nesting restrictions. */
bc7bff74 3157 bool remove = false;
3158 if (is_gimple_omp (stmt))
3159 remove = !check_omp_nesting_restrictions (stmt, ctx);
3160 else if (is_gimple_call (stmt))
3161 {
3162 tree fndecl = gimple_call_fndecl (stmt);
f2697631 3163 if (fndecl)
3164 {
3165 if (setjmp_or_longjmp_p (fndecl)
3166 && ctx
3167 && gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
10c55644 3168 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
f2697631 3169 {
3170 remove = true;
3171 error_at (gimple_location (stmt),
3172 "setjmp/longjmp inside simd construct");
3173 }
3174 else if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
3175 switch (DECL_FUNCTION_CODE (fndecl))
3176 {
3177 case BUILT_IN_GOMP_BARRIER:
3178 case BUILT_IN_GOMP_CANCEL:
3179 case BUILT_IN_GOMP_CANCELLATION_POINT:
3180 case BUILT_IN_GOMP_TASKYIELD:
3181 case BUILT_IN_GOMP_TASKWAIT:
3182 case BUILT_IN_GOMP_TASKGROUP_START:
3183 case BUILT_IN_GOMP_TASKGROUP_END:
3184 remove = !check_omp_nesting_restrictions (stmt, ctx);
3185 break;
3186 default:
3187 break;
3188 }
3189 }
bc7bff74 3190 }
3191 if (remove)
3192 {
3193 stmt = gimple_build_nop ();
3194 gsi_replace (gsi, stmt, false);
fd6481cf 3195 }
c1d127dd 3196
75a70cf9 3197 *handled_ops_p = true;
3198
3199 switch (gimple_code (stmt))
1e8e9920 3200 {
75a70cf9 3201 case GIMPLE_OMP_PARALLEL:
fd6481cf 3202 taskreg_nesting_level++;
75a70cf9 3203 scan_omp_parallel (gsi, ctx);
fd6481cf 3204 taskreg_nesting_level--;
3205 break;
3206
75a70cf9 3207 case GIMPLE_OMP_TASK:
fd6481cf 3208 taskreg_nesting_level++;
75a70cf9 3209 scan_omp_task (gsi, ctx);
fd6481cf 3210 taskreg_nesting_level--;
1e8e9920 3211 break;
3212
75a70cf9 3213 case GIMPLE_OMP_FOR:
1a91d914 3214 scan_omp_for (as_a <gomp_for *> (stmt), ctx);
1e8e9920 3215 break;
3216
75a70cf9 3217 case GIMPLE_OMP_SECTIONS:
1a91d914 3218 scan_omp_sections (as_a <gomp_sections *> (stmt), ctx);
1e8e9920 3219 break;
3220
75a70cf9 3221 case GIMPLE_OMP_SINGLE:
1a91d914 3222 scan_omp_single (as_a <gomp_single *> (stmt), ctx);
1e8e9920 3223 break;
3224
75a70cf9 3225 case GIMPLE_OMP_SECTION:
3226 case GIMPLE_OMP_MASTER:
bc7bff74 3227 case GIMPLE_OMP_TASKGROUP:
75a70cf9 3228 case GIMPLE_OMP_ORDERED:
3229 case GIMPLE_OMP_CRITICAL:
3230 ctx = new_omp_context (stmt, ctx);
ab129075 3231 scan_omp (gimple_omp_body_ptr (stmt), ctx);
1e8e9920 3232 break;
3233
bc7bff74 3234 case GIMPLE_OMP_TARGET:
1a91d914 3235 scan_omp_target (as_a <gomp_target *> (stmt), ctx);
bc7bff74 3236 break;
3237
3238 case GIMPLE_OMP_TEAMS:
1a91d914 3239 scan_omp_teams (as_a <gomp_teams *> (stmt), ctx);
bc7bff74 3240 break;
3241
75a70cf9 3242 case GIMPLE_BIND:
1e8e9920 3243 {
3244 tree var;
1e8e9920 3245
75a70cf9 3246 *handled_ops_p = false;
3247 if (ctx)
1a91d914 3248 for (var = gimple_bind_vars (as_a <gbind *> (stmt));
3249 var ;
3250 var = DECL_CHAIN (var))
75a70cf9 3251 insert_decl_map (&ctx->cb, var, var);
1e8e9920 3252 }
3253 break;
1e8e9920 3254 default:
75a70cf9 3255 *handled_ops_p = false;
1e8e9920 3256 break;
3257 }
3258
3259 return NULL_TREE;
3260}
3261
3262
75a70cf9 3263/* Scan all the statements starting at the current statement. CTX
ca4c3545 3264 contains context information about the OMP directives and
75a70cf9 3265 clauses found during the scan. */
1e8e9920 3266
3267static void
ab129075 3268scan_omp (gimple_seq *body_p, omp_context *ctx)
1e8e9920 3269{
3270 location_t saved_location;
3271 struct walk_stmt_info wi;
3272
3273 memset (&wi, 0, sizeof (wi));
1e8e9920 3274 wi.info = ctx;
1e8e9920 3275 wi.want_locations = true;
3276
3277 saved_location = input_location;
ab129075 3278 walk_gimple_seq_mod (body_p, scan_omp_1_stmt, scan_omp_1_op, &wi);
1e8e9920 3279 input_location = saved_location;
3280}
3281\f
3282/* Re-gimplification and code generation routines. */
3283
3284/* Build a call to GOMP_barrier. */
3285
bc7bff74 3286static gimple
3287build_omp_barrier (tree lhs)
3288{
3289 tree fndecl = builtin_decl_explicit (lhs ? BUILT_IN_GOMP_BARRIER_CANCEL
3290 : BUILT_IN_GOMP_BARRIER);
1a91d914 3291 gcall *g = gimple_build_call (fndecl, 0);
bc7bff74 3292 if (lhs)
3293 gimple_call_set_lhs (g, lhs);
3294 return g;
1e8e9920 3295}
3296
3297/* If a context was created for STMT when it was scanned, return it. */
3298
3299static omp_context *
75a70cf9 3300maybe_lookup_ctx (gimple stmt)
1e8e9920 3301{
3302 splay_tree_node n;
3303 n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
3304 return n ? (omp_context *) n->value : NULL;
3305}
3306
773c5ba7 3307
3308/* Find the mapping for DECL in CTX or the immediately enclosing
3309 context that has a mapping for DECL.
3310
3311 If CTX is a nested parallel directive, we may have to use the decl
3312 mappings created in CTX's parent context. Suppose that we have the
3313 following parallel nesting (variable UIDs showed for clarity):
3314
3315 iD.1562 = 0;
3316 #omp parallel shared(iD.1562) -> outer parallel
3317 iD.1562 = iD.1562 + 1;
3318
3319 #omp parallel shared (iD.1562) -> inner parallel
3320 iD.1562 = iD.1562 - 1;
3321
3322 Each parallel structure will create a distinct .omp_data_s structure
3323 for copying iD.1562 in/out of the directive:
3324
3325 outer parallel .omp_data_s.1.i -> iD.1562
3326 inner parallel .omp_data_s.2.i -> iD.1562
3327
3328 A shared variable mapping will produce a copy-out operation before
3329 the parallel directive and a copy-in operation after it. So, in
3330 this case we would have:
3331
3332 iD.1562 = 0;
3333 .omp_data_o.1.i = iD.1562;
3334 #omp parallel shared(iD.1562) -> outer parallel
3335 .omp_data_i.1 = &.omp_data_o.1
3336 .omp_data_i.1->i = .omp_data_i.1->i + 1;
3337
3338 .omp_data_o.2.i = iD.1562; -> **
3339 #omp parallel shared(iD.1562) -> inner parallel
3340 .omp_data_i.2 = &.omp_data_o.2
3341 .omp_data_i.2->i = .omp_data_i.2->i - 1;
3342
3343
3344 ** This is a problem. The symbol iD.1562 cannot be referenced
3345 inside the body of the outer parallel region. But since we are
3346 emitting this copy operation while expanding the inner parallel
3347 directive, we need to access the CTX structure of the outer
3348 parallel directive to get the correct mapping:
3349
3350 .omp_data_o.2.i = .omp_data_i.1->i
3351
3352 Since there may be other workshare or parallel directives enclosing
3353 the parallel directive, it may be necessary to walk up the context
3354 parent chain. This is not a problem in general because nested
3355 parallelism happens only rarely. */
3356
3357static tree
3358lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
3359{
3360 tree t;
3361 omp_context *up;
3362
773c5ba7 3363 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
3364 t = maybe_lookup_decl (decl, up);
3365
87b31375 3366 gcc_assert (!ctx->is_nested || t || is_global_var (decl));
773c5ba7 3367
c37594c7 3368 return t ? t : decl;
773c5ba7 3369}
3370
3371
f49d7bb5 3372/* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
3373 in outer contexts. */
3374
3375static tree
3376maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
3377{
3378 tree t = NULL;
3379 omp_context *up;
3380
87b31375 3381 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
3382 t = maybe_lookup_decl (decl, up);
f49d7bb5 3383
3384 return t ? t : decl;
3385}
3386
3387
1e8e9920 3388/* Construct the initialization value for reduction CLAUSE. */
3389
3390tree
3391omp_reduction_init (tree clause, tree type)
3392{
389dd41b 3393 location_t loc = OMP_CLAUSE_LOCATION (clause);
1e8e9920 3394 switch (OMP_CLAUSE_REDUCTION_CODE (clause))
3395 {
3396 case PLUS_EXPR:
3397 case MINUS_EXPR:
3398 case BIT_IOR_EXPR:
3399 case BIT_XOR_EXPR:
3400 case TRUTH_OR_EXPR:
3401 case TRUTH_ORIF_EXPR:
3402 case TRUTH_XOR_EXPR:
3403 case NE_EXPR:
385f3f36 3404 return build_zero_cst (type);
1e8e9920 3405
3406 case MULT_EXPR:
3407 case TRUTH_AND_EXPR:
3408 case TRUTH_ANDIF_EXPR:
3409 case EQ_EXPR:
389dd41b 3410 return fold_convert_loc (loc, type, integer_one_node);
1e8e9920 3411
3412 case BIT_AND_EXPR:
389dd41b 3413 return fold_convert_loc (loc, type, integer_minus_one_node);
1e8e9920 3414
3415 case MAX_EXPR:
3416 if (SCALAR_FLOAT_TYPE_P (type))
3417 {
3418 REAL_VALUE_TYPE max, min;
fe994837 3419 if (HONOR_INFINITIES (type))
1e8e9920 3420 {
3421 real_inf (&max);
3422 real_arithmetic (&min, NEGATE_EXPR, &max, NULL);
3423 }
3424 else
3425 real_maxval (&min, 1, TYPE_MODE (type));
3426 return build_real (type, min);
3427 }
3428 else
3429 {
3430 gcc_assert (INTEGRAL_TYPE_P (type));
3431 return TYPE_MIN_VALUE (type);
3432 }
3433
3434 case MIN_EXPR:
3435 if (SCALAR_FLOAT_TYPE_P (type))
3436 {
3437 REAL_VALUE_TYPE max;
fe994837 3438 if (HONOR_INFINITIES (type))
1e8e9920 3439 real_inf (&max);
3440 else
3441 real_maxval (&max, 0, TYPE_MODE (type));
3442 return build_real (type, max);
3443 }
3444 else
3445 {
3446 gcc_assert (INTEGRAL_TYPE_P (type));
3447 return TYPE_MAX_VALUE (type);
3448 }
3449
3450 default:
3451 gcc_unreachable ();
3452 }
3453}
3454
bc7bff74 3455/* Return alignment to be assumed for var in CLAUSE, which should be
3456 OMP_CLAUSE_ALIGNED. */
3457
3458static tree
3459omp_clause_aligned_alignment (tree clause)
3460{
3461 if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause))
3462 return OMP_CLAUSE_ALIGNED_ALIGNMENT (clause);
3463
3464 /* Otherwise return implementation defined alignment. */
3465 unsigned int al = 1;
3754d046 3466 machine_mode mode, vmode;
bc7bff74 3467 int vs = targetm.vectorize.autovectorize_vector_sizes ();
3468 if (vs)
3469 vs = 1 << floor_log2 (vs);
3470 static enum mode_class classes[]
3471 = { MODE_INT, MODE_VECTOR_INT, MODE_FLOAT, MODE_VECTOR_FLOAT };
3472 for (int i = 0; i < 4; i += 2)
3473 for (mode = GET_CLASS_NARROWEST_MODE (classes[i]);
3474 mode != VOIDmode;
3475 mode = GET_MODE_WIDER_MODE (mode))
3476 {
3477 vmode = targetm.vectorize.preferred_simd_mode (mode);
3478 if (GET_MODE_CLASS (vmode) != classes[i + 1])
3479 continue;
3480 while (vs
3481 && GET_MODE_SIZE (vmode) < vs
3482 && GET_MODE_2XWIDER_MODE (vmode) != VOIDmode)
3483 vmode = GET_MODE_2XWIDER_MODE (vmode);
3484
3485 tree type = lang_hooks.types.type_for_mode (mode, 1);
3486 if (type == NULL_TREE || TYPE_MODE (type) != mode)
3487 continue;
3488 type = build_vector_type (type, GET_MODE_SIZE (vmode)
3489 / GET_MODE_SIZE (mode));
3490 if (TYPE_MODE (type) != vmode)
3491 continue;
3492 if (TYPE_ALIGN_UNIT (type) > al)
3493 al = TYPE_ALIGN_UNIT (type);
3494 }
3495 return build_int_cst (integer_type_node, al);
3496}
3497
3d483a94 3498/* Return maximum possible vectorization factor for the target. */
3499
3500static int
3501omp_max_vf (void)
3502{
3503 if (!optimize
3504 || optimize_debug
ad45e43e 3505 || !flag_tree_loop_optimize
043115ec 3506 || (!flag_tree_loop_vectorize
3507 && (global_options_set.x_flag_tree_loop_vectorize
3508 || global_options_set.x_flag_tree_vectorize)))
3d483a94 3509 return 1;
3510
3511 int vs = targetm.vectorize.autovectorize_vector_sizes ();
3512 if (vs)
3513 {
3514 vs = 1 << floor_log2 (vs);
3515 return vs;
3516 }
3754d046 3517 machine_mode vqimode = targetm.vectorize.preferred_simd_mode (QImode);
3d483a94 3518 if (GET_MODE_CLASS (vqimode) == MODE_VECTOR_INT)
3519 return GET_MODE_NUNITS (vqimode);
3520 return 1;
3521}
3522
3523/* Helper function of lower_rec_input_clauses, used for #pragma omp simd
3524 privatization. */
3525
3526static bool
3527lower_rec_simd_input_clauses (tree new_var, omp_context *ctx, int &max_vf,
3528 tree &idx, tree &lane, tree &ivar, tree &lvar)
3529{
3530 if (max_vf == 0)
3531 {
3532 max_vf = omp_max_vf ();
3533 if (max_vf > 1)
3534 {
3535 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3536 OMP_CLAUSE_SAFELEN);
c3f3b68d 3537 if (c && TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) != INTEGER_CST)
3538 max_vf = 1;
3539 else if (c && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
3540 max_vf) == -1)
d85a2013 3541 max_vf = tree_to_shwi (OMP_CLAUSE_SAFELEN_EXPR (c));
3d483a94 3542 }
3543 if (max_vf > 1)
3544 {
f9e245b2 3545 idx = create_tmp_var (unsigned_type_node);
3546 lane = create_tmp_var (unsigned_type_node);
3d483a94 3547 }
3548 }
3549 if (max_vf == 1)
3550 return false;
3551
3552 tree atype = build_array_type_nelts (TREE_TYPE (new_var), max_vf);
f9e245b2 3553 tree avar = create_tmp_var_raw (atype);
3d483a94 3554 if (TREE_ADDRESSABLE (new_var))
3555 TREE_ADDRESSABLE (avar) = 1;
3556 DECL_ATTRIBUTES (avar)
3557 = tree_cons (get_identifier ("omp simd array"), NULL,
3558 DECL_ATTRIBUTES (avar));
3559 gimple_add_tmp_var (avar);
3560 ivar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, idx,
3561 NULL_TREE, NULL_TREE);
3562 lvar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, lane,
3563 NULL_TREE, NULL_TREE);
bc7bff74 3564 if (DECL_P (new_var))
3565 {
3566 SET_DECL_VALUE_EXPR (new_var, lvar);
3567 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3568 }
3d483a94 3569 return true;
3570}
3571
2712b6de 3572/* Helper function of lower_rec_input_clauses. For a reference
3573 in simd reduction, add an underlying variable it will reference. */
3574
3575static void
3576handle_simd_reference (location_t loc, tree new_vard, gimple_seq *ilist)
3577{
3578 tree z = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard)));
3579 if (TREE_CONSTANT (z))
3580 {
3581 const char *name = NULL;
3582 if (DECL_NAME (new_vard))
3583 name = IDENTIFIER_POINTER (DECL_NAME (new_vard));
3584
3585 z = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_vard)), name);
3586 gimple_add_tmp_var (z);
3587 TREE_ADDRESSABLE (z) = 1;
3588 z = build_fold_addr_expr_loc (loc, z);
3589 gimplify_assign (new_vard, z, ilist);
3590 }
3591}
3592
1e8e9920 3593/* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
3594 from the receiver (aka child) side and initializers for REFERENCE_TYPE
3595 private variables. Initialization statements go in ILIST, while calls
3596 to destructors go in DLIST. */
3597
3598static void
75a70cf9 3599lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
bc7bff74 3600 omp_context *ctx, struct omp_for_data *fd)
1e8e9920 3601{
c2f47e15 3602 tree c, dtor, copyin_seq, x, ptr;
1e8e9920 3603 bool copyin_by_ref = false;
f49d7bb5 3604 bool lastprivate_firstprivate = false;
bc7bff74 3605 bool reduction_omp_orig_ref = false;
1e8e9920 3606 int pass;
3d483a94 3607 bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
10c55644 3608 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD);
3d483a94 3609 int max_vf = 0;
3610 tree lane = NULL_TREE, idx = NULL_TREE;
3611 tree ivar = NULL_TREE, lvar = NULL_TREE;
3612 gimple_seq llist[2] = { NULL, NULL };
1e8e9920 3613
1e8e9920 3614 copyin_seq = NULL;
3615
3d483a94 3616 /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
3617 with data sharing clauses referencing variable sized vars. That
3618 is unnecessarily hard to support and very unlikely to result in
3619 vectorized code anyway. */
3620 if (is_simd)
3621 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3622 switch (OMP_CLAUSE_CODE (c))
3623 {
9580cb79 3624 case OMP_CLAUSE_LINEAR:
3625 if (OMP_CLAUSE_LINEAR_ARRAY (c))
3626 max_vf = 1;
3627 /* FALLTHRU */
3d483a94 3628 case OMP_CLAUSE_REDUCTION:
3d483a94 3629 case OMP_CLAUSE_PRIVATE:
3630 case OMP_CLAUSE_FIRSTPRIVATE:
3631 case OMP_CLAUSE_LASTPRIVATE:
3d483a94 3632 if (is_variable_sized (OMP_CLAUSE_DECL (c)))
3633 max_vf = 1;
3634 break;
3635 default:
3636 continue;
3637 }
3638
1e8e9920 3639 /* Do all the fixed sized types in the first pass, and the variable sized
3640 types in the second pass. This makes sure that the scalar arguments to
48e1416a 3641 the variable sized types are processed before we use them in the
1e8e9920 3642 variable sized operations. */
3643 for (pass = 0; pass < 2; ++pass)
3644 {
3645 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3646 {
55d6e7cd 3647 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
1e8e9920 3648 tree var, new_var;
3649 bool by_ref;
389dd41b 3650 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
1e8e9920 3651
3652 switch (c_kind)
3653 {
3654 case OMP_CLAUSE_PRIVATE:
3655 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
3656 continue;
3657 break;
3658 case OMP_CLAUSE_SHARED:
bc7bff74 3659 /* Ignore shared directives in teams construct. */
3660 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3661 continue;
f49d7bb5 3662 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
3663 {
3664 gcc_assert (is_global_var (OMP_CLAUSE_DECL (c)));
3665 continue;
3666 }
1e8e9920 3667 case OMP_CLAUSE_FIRSTPRIVATE:
1e8e9920 3668 case OMP_CLAUSE_COPYIN:
bc7bff74 3669 case OMP_CLAUSE_LINEAR:
3670 break;
1e8e9920 3671 case OMP_CLAUSE_REDUCTION:
bc7bff74 3672 if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
3673 reduction_omp_orig_ref = true;
1e8e9920 3674 break;
bc7bff74 3675 case OMP_CLAUSE__LOOPTEMP_:
3676 /* Handle _looptemp_ clauses only on parallel. */
3677 if (fd)
3678 continue;
3d483a94 3679 break;
df2c34fc 3680 case OMP_CLAUSE_LASTPRIVATE:
f49d7bb5 3681 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3682 {
3683 lastprivate_firstprivate = true;
3684 if (pass != 0)
3685 continue;
3686 }
cf5f881f 3687 /* Even without corresponding firstprivate, if
3688 decl is Fortran allocatable, it needs outer var
3689 reference. */
3690 else if (pass == 0
3691 && lang_hooks.decls.omp_private_outer_ref
3692 (OMP_CLAUSE_DECL (c)))
3693 lastprivate_firstprivate = true;
df2c34fc 3694 break;
bc7bff74 3695 case OMP_CLAUSE_ALIGNED:
3696 if (pass == 0)
3697 continue;
3698 var = OMP_CLAUSE_DECL (c);
3699 if (TREE_CODE (TREE_TYPE (var)) == POINTER_TYPE
3700 && !is_global_var (var))
3701 {
3702 new_var = maybe_lookup_decl (var, ctx);
3703 if (new_var == NULL_TREE)
3704 new_var = maybe_lookup_decl_in_outer_ctx (var, ctx);
3705 x = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3706 x = build_call_expr_loc (clause_loc, x, 2, new_var,
3707 omp_clause_aligned_alignment (c));
3708 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3709 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
3710 gimplify_and_add (x, ilist);
3711 }
3712 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
3713 && is_global_var (var))
3714 {
3715 tree ptype = build_pointer_type (TREE_TYPE (var)), t, t2;
3716 new_var = lookup_decl (var, ctx);
3717 t = maybe_lookup_decl_in_outer_ctx (var, ctx);
3718 t = build_fold_addr_expr_loc (clause_loc, t);
3719 t2 = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3720 t = build_call_expr_loc (clause_loc, t2, 2, t,
3721 omp_clause_aligned_alignment (c));
3722 t = fold_convert_loc (clause_loc, ptype, t);
f9e245b2 3723 x = create_tmp_var (ptype);
bc7bff74 3724 t = build2 (MODIFY_EXPR, ptype, x, t);
3725 gimplify_and_add (t, ilist);
3726 t = build_simple_mem_ref_loc (clause_loc, x);
3727 SET_DECL_VALUE_EXPR (new_var, t);
3728 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3729 }
3730 continue;
1e8e9920 3731 default:
3732 continue;
3733 }
3734
3735 new_var = var = OMP_CLAUSE_DECL (c);
3736 if (c_kind != OMP_CLAUSE_COPYIN)
3737 new_var = lookup_decl (var, ctx);
3738
3739 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
3740 {
3741 if (pass != 0)
3742 continue;
3743 }
1e8e9920 3744 else if (is_variable_sized (var))
3745 {
773c5ba7 3746 /* For variable sized types, we need to allocate the
3747 actual storage here. Call alloca and store the
3748 result in the pointer decl that we created elsewhere. */
1e8e9920 3749 if (pass == 0)
3750 continue;
3751
fd6481cf 3752 if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
3753 {
1a91d914 3754 gcall *stmt;
b9a16870 3755 tree tmp, atmp;
75a70cf9 3756
fd6481cf 3757 ptr = DECL_VALUE_EXPR (new_var);
3758 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
3759 ptr = TREE_OPERAND (ptr, 0);
3760 gcc_assert (DECL_P (ptr));
3761 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
75a70cf9 3762
3763 /* void *tmp = __builtin_alloca */
b9a16870 3764 atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3765 stmt = gimple_build_call (atmp, 1, x);
f9e245b2 3766 tmp = create_tmp_var_raw (ptr_type_node);
75a70cf9 3767 gimple_add_tmp_var (tmp);
3768 gimple_call_set_lhs (stmt, tmp);
3769
3770 gimple_seq_add_stmt (ilist, stmt);
3771
389dd41b 3772 x = fold_convert_loc (clause_loc, TREE_TYPE (ptr), tmp);
75a70cf9 3773 gimplify_assign (ptr, x, ilist);
fd6481cf 3774 }
1e8e9920 3775 }
1e8e9920 3776 else if (is_reference (var))
3777 {
773c5ba7 3778 /* For references that are being privatized for Fortran,
3779 allocate new backing storage for the new pointer
3780 variable. This allows us to avoid changing all the
3781 code that expects a pointer to something that expects
bc7bff74 3782 a direct variable. */
1e8e9920 3783 if (pass == 0)
3784 continue;
3785
3786 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
fd6481cf 3787 if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx))
3788 {
3789 x = build_receiver_ref (var, false, ctx);
389dd41b 3790 x = build_fold_addr_expr_loc (clause_loc, x);
fd6481cf 3791 }
3792 else if (TREE_CONSTANT (x))
1e8e9920 3793 {
2712b6de 3794 /* For reduction in SIMD loop, defer adding the
3795 initialization of the reference, because if we decide
3796 to use SIMD array for it, the initilization could cause
3797 expansion ICE. */
3798 if (c_kind == OMP_CLAUSE_REDUCTION && is_simd)
09d1c205 3799 x = NULL_TREE;
3800 else
3801 {
3802 const char *name = NULL;
3803 if (DECL_NAME (var))
3804 name = IDENTIFIER_POINTER (DECL_NAME (new_var));
3805
3806 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
3807 name);
3808 gimple_add_tmp_var (x);
3809 TREE_ADDRESSABLE (x) = 1;
3810 x = build_fold_addr_expr_loc (clause_loc, x);
3811 }
1e8e9920 3812 }
3813 else
3814 {
b9a16870 3815 tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3816 x = build_call_expr_loc (clause_loc, atmp, 1, x);
1e8e9920 3817 }
3818
09d1c205 3819 if (x)
3820 {
3821 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3822 gimplify_assign (new_var, x, ilist);
3823 }
1e8e9920 3824
182cf5a9 3825 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
1e8e9920 3826 }
3827 else if (c_kind == OMP_CLAUSE_REDUCTION
3828 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3829 {
3830 if (pass == 0)
3831 continue;
3832 }
3833 else if (pass != 0)
3834 continue;
3835
55d6e7cd 3836 switch (OMP_CLAUSE_CODE (c))
1e8e9920 3837 {
3838 case OMP_CLAUSE_SHARED:
bc7bff74 3839 /* Ignore shared directives in teams construct. */
3840 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3841 continue;
f49d7bb5 3842 /* Shared global vars are just accessed directly. */
3843 if (is_global_var (new_var))
3844 break;
1e8e9920 3845 /* Set up the DECL_VALUE_EXPR for shared variables now. This
3846 needs to be delayed until after fixup_child_record_type so
3847 that we get the correct type during the dereference. */
e8a588af 3848 by_ref = use_pointer_for_field (var, ctx);
1e8e9920 3849 x = build_receiver_ref (var, by_ref, ctx);
3850 SET_DECL_VALUE_EXPR (new_var, x);
3851 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3852
3853 /* ??? If VAR is not passed by reference, and the variable
3854 hasn't been initialized yet, then we'll get a warning for
3855 the store into the omp_data_s structure. Ideally, we'd be
48e1416a 3856 able to notice this and not store anything at all, but
1e8e9920 3857 we're generating code too early. Suppress the warning. */
3858 if (!by_ref)
3859 TREE_NO_WARNING (var) = 1;
3860 break;
3861
3862 case OMP_CLAUSE_LASTPRIVATE:
3863 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3864 break;
3865 /* FALLTHRU */
3866
3867 case OMP_CLAUSE_PRIVATE:
fd6481cf 3868 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE)
3869 x = build_outer_var_ref (var, ctx);
3870 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
3871 {
3872 if (is_task_ctx (ctx))
3873 x = build_receiver_ref (var, false, ctx);
3874 else
3875 x = build_outer_var_ref (var, ctx);
3876 }
3877 else
3878 x = NULL;
3d483a94 3879 do_private:
bc7bff74 3880 tree nx;
3881 nx = lang_hooks.decls.omp_clause_default_ctor (c, new_var, x);
3d483a94 3882 if (is_simd)
3883 {
3884 tree y = lang_hooks.decls.omp_clause_dtor (c, new_var);
bc7bff74 3885 if ((TREE_ADDRESSABLE (new_var) || nx || y
3d483a94 3886 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
3887 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3888 idx, lane, ivar, lvar))
3889 {
bc7bff74 3890 if (nx)
3d483a94 3891 x = lang_hooks.decls.omp_clause_default_ctor
3892 (c, unshare_expr (ivar), x);
bc7bff74 3893 if (nx && x)
3d483a94 3894 gimplify_and_add (x, &llist[0]);
3895 if (y)
3896 {
3897 y = lang_hooks.decls.omp_clause_dtor (c, ivar);
3898 if (y)
3899 {
3900 gimple_seq tseq = NULL;
3901
3902 dtor = y;
3903 gimplify_stmt (&dtor, &tseq);
3904 gimple_seq_add_seq (&llist[1], tseq);
3905 }
3906 }
3907 break;
3908 }
3909 }
bc7bff74 3910 if (nx)
3911 gimplify_and_add (nx, ilist);
1e8e9920 3912 /* FALLTHRU */
3913
3914 do_dtor:
3915 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
3916 if (x)
3917 {
75a70cf9 3918 gimple_seq tseq = NULL;
3919
1e8e9920 3920 dtor = x;
75a70cf9 3921 gimplify_stmt (&dtor, &tseq);
e3a19533 3922 gimple_seq_add_seq (dlist, tseq);
1e8e9920 3923 }
3924 break;
3925
3d483a94 3926 case OMP_CLAUSE_LINEAR:
3927 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c))
3928 goto do_firstprivate;
3929 if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
3930 x = NULL;
3931 else
3932 x = build_outer_var_ref (var, ctx);
3933 goto do_private;
3934
1e8e9920 3935 case OMP_CLAUSE_FIRSTPRIVATE:
fd6481cf 3936 if (is_task_ctx (ctx))
3937 {
3938 if (is_reference (var) || is_variable_sized (var))
3939 goto do_dtor;
3940 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var,
3941 ctx))
3942 || use_pointer_for_field (var, NULL))
3943 {
3944 x = build_receiver_ref (var, false, ctx);
3945 SET_DECL_VALUE_EXPR (new_var, x);
3946 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3947 goto do_dtor;
3948 }
3949 }
3d483a94 3950 do_firstprivate:
1e8e9920 3951 x = build_outer_var_ref (var, ctx);
3d483a94 3952 if (is_simd)
3953 {
bc7bff74 3954 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3955 && gimple_omp_for_combined_into_p (ctx->stmt))
3956 {
9580cb79 3957 tree t = OMP_CLAUSE_LINEAR_STEP (c);
3958 tree stept = TREE_TYPE (t);
3959 tree ct = find_omp_clause (clauses,
3960 OMP_CLAUSE__LOOPTEMP_);
3961 gcc_assert (ct);
3962 tree l = OMP_CLAUSE_DECL (ct);
e471cc6f 3963 tree n1 = fd->loop.n1;
3964 tree step = fd->loop.step;
3965 tree itype = TREE_TYPE (l);
3966 if (POINTER_TYPE_P (itype))
3967 itype = signed_type_for (itype);
3968 l = fold_build2 (MINUS_EXPR, itype, l, n1);
3969 if (TYPE_UNSIGNED (itype)
3970 && fd->loop.cond_code == GT_EXPR)
3971 l = fold_build2 (TRUNC_DIV_EXPR, itype,
3972 fold_build1 (NEGATE_EXPR, itype, l),
3973 fold_build1 (NEGATE_EXPR,
3974 itype, step));
3975 else
3976 l = fold_build2 (TRUNC_DIV_EXPR, itype, l, step);
bc7bff74 3977 t = fold_build2 (MULT_EXPR, stept,
3978 fold_convert (stept, l), t);
9580cb79 3979
3980 if (OMP_CLAUSE_LINEAR_ARRAY (c))
3981 {
3982 x = lang_hooks.decls.omp_clause_linear_ctor
3983 (c, new_var, x, t);
3984 gimplify_and_add (x, ilist);
3985 goto do_dtor;
3986 }
3987
bc7bff74 3988 if (POINTER_TYPE_P (TREE_TYPE (x)))
3989 x = fold_build2 (POINTER_PLUS_EXPR,
3990 TREE_TYPE (x), x, t);
3991 else
3992 x = fold_build2 (PLUS_EXPR, TREE_TYPE (x), x, t);
3993 }
3994
3d483a94 3995 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
3996 || TREE_ADDRESSABLE (new_var))
3997 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3998 idx, lane, ivar, lvar))
3999 {
4000 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR)
4001 {
f9e245b2 4002 tree iv = create_tmp_var (TREE_TYPE (new_var));
3d483a94 4003 x = lang_hooks.decls.omp_clause_copy_ctor (c, iv, x);
4004 gimplify_and_add (x, ilist);
4005 gimple_stmt_iterator gsi
4006 = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
1a91d914 4007 gassign *g
3d483a94 4008 = gimple_build_assign (unshare_expr (lvar), iv);
4009 gsi_insert_before_without_update (&gsi, g,
4010 GSI_SAME_STMT);
9580cb79 4011 tree t = OMP_CLAUSE_LINEAR_STEP (c);
3d483a94 4012 enum tree_code code = PLUS_EXPR;
4013 if (POINTER_TYPE_P (TREE_TYPE (new_var)))
4014 code = POINTER_PLUS_EXPR;
e9cf809e 4015 g = gimple_build_assign (iv, code, iv, t);
3d483a94 4016 gsi_insert_before_without_update (&gsi, g,
4017 GSI_SAME_STMT);
4018 break;
4019 }
4020 x = lang_hooks.decls.omp_clause_copy_ctor
4021 (c, unshare_expr (ivar), x);
4022 gimplify_and_add (x, &llist[0]);
4023 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
4024 if (x)
4025 {
4026 gimple_seq tseq = NULL;
4027
4028 dtor = x;
4029 gimplify_stmt (&dtor, &tseq);
4030 gimple_seq_add_seq (&llist[1], tseq);
4031 }
4032 break;
4033 }
4034 }
1e8e9920 4035 x = lang_hooks.decls.omp_clause_copy_ctor (c, new_var, x);
4036 gimplify_and_add (x, ilist);
4037 goto do_dtor;
1e8e9920 4038
bc7bff74 4039 case OMP_CLAUSE__LOOPTEMP_:
4040 gcc_assert (is_parallel_ctx (ctx));
4041 x = build_outer_var_ref (var, ctx);
4042 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
4043 gimplify_and_add (x, ilist);
4044 break;
4045
1e8e9920 4046 case OMP_CLAUSE_COPYIN:
e8a588af 4047 by_ref = use_pointer_for_field (var, NULL);
1e8e9920 4048 x = build_receiver_ref (var, by_ref, ctx);
4049 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
4050 append_to_statement_list (x, &copyin_seq);
4051 copyin_by_ref |= by_ref;
4052 break;
4053
4054 case OMP_CLAUSE_REDUCTION:
4055 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4056 {
fd6481cf 4057 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
bc7bff74 4058 gimple tseq;
fd6481cf 4059 x = build_outer_var_ref (var, ctx);
4060
bc7bff74 4061 if (is_reference (var)
4062 && !useless_type_conversion_p (TREE_TYPE (placeholder),
4063 TREE_TYPE (x)))
389dd41b 4064 x = build_fold_addr_expr_loc (clause_loc, x);
fd6481cf 4065 SET_DECL_VALUE_EXPR (placeholder, x);
4066 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
bc7bff74 4067 tree new_vard = new_var;
4068 if (is_reference (var))
4069 {
4070 gcc_assert (TREE_CODE (new_var) == MEM_REF);
4071 new_vard = TREE_OPERAND (new_var, 0);
4072 gcc_assert (DECL_P (new_vard));
4073 }
3d483a94 4074 if (is_simd
4075 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4076 idx, lane, ivar, lvar))
4077 {
bc7bff74 4078 if (new_vard == new_var)
4079 {
4080 gcc_assert (DECL_VALUE_EXPR (new_var) == lvar);
4081 SET_DECL_VALUE_EXPR (new_var, ivar);
4082 }
4083 else
4084 {
4085 SET_DECL_VALUE_EXPR (new_vard,
4086 build_fold_addr_expr (ivar));
4087 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
4088 }
4089 x = lang_hooks.decls.omp_clause_default_ctor
4090 (c, unshare_expr (ivar),
4091 build_outer_var_ref (var, ctx));
4092 if (x)
4093 gimplify_and_add (x, &llist[0]);
4094 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
4095 {
4096 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
4097 lower_omp (&tseq, ctx);
4098 gimple_seq_add_seq (&llist[0], tseq);
4099 }
4100 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
4101 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
4102 lower_omp (&tseq, ctx);
4103 gimple_seq_add_seq (&llist[1], tseq);
4104 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4105 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
4106 if (new_vard == new_var)
4107 SET_DECL_VALUE_EXPR (new_var, lvar);
4108 else
4109 SET_DECL_VALUE_EXPR (new_vard,
4110 build_fold_addr_expr (lvar));
4111 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
4112 if (x)
4113 {
4114 tseq = NULL;
4115 dtor = x;
4116 gimplify_stmt (&dtor, &tseq);
4117 gimple_seq_add_seq (&llist[1], tseq);
4118 }
4119 break;
4120 }
09d1c205 4121 /* If this is a reference to constant size reduction var
4122 with placeholder, we haven't emitted the initializer
4123 for it because it is undesirable if SIMD arrays are used.
4124 But if they aren't used, we need to emit the deferred
4125 initialization now. */
4126 else if (is_reference (var) && is_simd)
2712b6de 4127 handle_simd_reference (clause_loc, new_vard, ilist);
bc7bff74 4128 x = lang_hooks.decls.omp_clause_default_ctor
cf5f881f 4129 (c, unshare_expr (new_var),
4130 build_outer_var_ref (var, ctx));
bc7bff74 4131 if (x)
4132 gimplify_and_add (x, ilist);
4133 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
4134 {
4135 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
4136 lower_omp (&tseq, ctx);
4137 gimple_seq_add_seq (ilist, tseq);
4138 }
75a70cf9 4139 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
bc7bff74 4140 if (is_simd)
4141 {
4142 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
4143 lower_omp (&tseq, ctx);
4144 gimple_seq_add_seq (dlist, tseq);
4145 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4146 }
fd6481cf 4147 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
bc7bff74 4148 goto do_dtor;
1e8e9920 4149 }
4150 else
4151 {
4152 x = omp_reduction_init (c, TREE_TYPE (new_var));
4153 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
c22ad515 4154 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
4155
4156 /* reduction(-:var) sums up the partial results, so it
4157 acts identically to reduction(+:var). */
4158 if (code == MINUS_EXPR)
4159 code = PLUS_EXPR;
4160
2712b6de 4161 tree new_vard = new_var;
4162 if (is_simd && is_reference (var))
4163 {
4164 gcc_assert (TREE_CODE (new_var) == MEM_REF);
4165 new_vard = TREE_OPERAND (new_var, 0);
4166 gcc_assert (DECL_P (new_vard));
4167 }
3d483a94 4168 if (is_simd
4169 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4170 idx, lane, ivar, lvar))
4171 {
3d483a94 4172 tree ref = build_outer_var_ref (var, ctx);
4173
4174 gimplify_assign (unshare_expr (ivar), x, &llist[0]);
4175
3d483a94 4176 x = build2 (code, TREE_TYPE (ref), ref, ivar);
4177 ref = build_outer_var_ref (var, ctx);
4178 gimplify_assign (ref, x, &llist[1]);
2712b6de 4179
4180 if (new_vard != new_var)
4181 {
4182 SET_DECL_VALUE_EXPR (new_vard,
4183 build_fold_addr_expr (lvar));
4184 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
4185 }
3d483a94 4186 }
4187 else
4188 {
2712b6de 4189 if (is_reference (var) && is_simd)
4190 handle_simd_reference (clause_loc, new_vard, ilist);
3d483a94 4191 gimplify_assign (new_var, x, ilist);
4192 if (is_simd)
c22ad515 4193 {
4194 tree ref = build_outer_var_ref (var, ctx);
4195
4196 x = build2 (code, TREE_TYPE (ref), ref, new_var);
4197 ref = build_outer_var_ref (var, ctx);
4198 gimplify_assign (ref, x, dlist);
4199 }
3d483a94 4200 }
1e8e9920 4201 }
4202 break;
4203
4204 default:
4205 gcc_unreachable ();
4206 }
4207 }
4208 }
4209
3d483a94 4210 if (lane)
4211 {
4212 tree uid = create_tmp_var (ptr_type_node, "simduid");
8e1a382d 4213 /* Don't want uninit warnings on simduid, it is always uninitialized,
4214 but we use it not for the value, but for the DECL_UID only. */
4215 TREE_NO_WARNING (uid) = 1;
3d483a94 4216 gimple g
4217 = gimple_build_call_internal (IFN_GOMP_SIMD_LANE, 1, uid);
4218 gimple_call_set_lhs (g, lane);
4219 gimple_stmt_iterator gsi = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
4220 gsi_insert_before_without_update (&gsi, g, GSI_SAME_STMT);
4221 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SIMDUID_);
4222 OMP_CLAUSE__SIMDUID__DECL (c) = uid;
4223 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
4224 gimple_omp_for_set_clauses (ctx->stmt, c);
e9cf809e 4225 g = gimple_build_assign (lane, INTEGER_CST,
4226 build_int_cst (unsigned_type_node, 0));
3d483a94 4227 gimple_seq_add_stmt (ilist, g);
4228 for (int i = 0; i < 2; i++)
4229 if (llist[i])
4230 {
f9e245b2 4231 tree vf = create_tmp_var (unsigned_type_node);
3d483a94 4232 g = gimple_build_call_internal (IFN_GOMP_SIMD_VF, 1, uid);
4233 gimple_call_set_lhs (g, vf);
4234 gimple_seq *seq = i == 0 ? ilist : dlist;
4235 gimple_seq_add_stmt (seq, g);
4236 tree t = build_int_cst (unsigned_type_node, 0);
e9cf809e 4237 g = gimple_build_assign (idx, INTEGER_CST, t);
3d483a94 4238 gimple_seq_add_stmt (seq, g);
4239 tree body = create_artificial_label (UNKNOWN_LOCATION);
4240 tree header = create_artificial_label (UNKNOWN_LOCATION);
4241 tree end = create_artificial_label (UNKNOWN_LOCATION);
4242 gimple_seq_add_stmt (seq, gimple_build_goto (header));
4243 gimple_seq_add_stmt (seq, gimple_build_label (body));
4244 gimple_seq_add_seq (seq, llist[i]);
4245 t = build_int_cst (unsigned_type_node, 1);
e9cf809e 4246 g = gimple_build_assign (idx, PLUS_EXPR, idx, t);
3d483a94 4247 gimple_seq_add_stmt (seq, g);
4248 gimple_seq_add_stmt (seq, gimple_build_label (header));
4249 g = gimple_build_cond (LT_EXPR, idx, vf, body, end);
4250 gimple_seq_add_stmt (seq, g);
4251 gimple_seq_add_stmt (seq, gimple_build_label (end));
4252 }
4253 }
4254
1e8e9920 4255 /* The copyin sequence is not to be executed by the main thread, since
4256 that would result in self-copies. Perhaps not visible to scalars,
4257 but it certainly is to C++ operator=. */
4258 if (copyin_seq)
4259 {
b9a16870 4260 x = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM),
4261 0);
1e8e9920 4262 x = build2 (NE_EXPR, boolean_type_node, x,
4263 build_int_cst (TREE_TYPE (x), 0));
4264 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
4265 gimplify_and_add (x, ilist);
4266 }
4267
4268 /* If any copyin variable is passed by reference, we must ensure the
4269 master thread doesn't modify it before it is copied over in all
f49d7bb5 4270 threads. Similarly for variables in both firstprivate and
4271 lastprivate clauses we need to ensure the lastprivate copying
bc7bff74 4272 happens after firstprivate copying in all threads. And similarly
4273 for UDRs if initializer expression refers to omp_orig. */
4274 if (copyin_by_ref || lastprivate_firstprivate || reduction_omp_orig_ref)
3d483a94 4275 {
4276 /* Don't add any barrier for #pragma omp simd or
4277 #pragma omp distribute. */
4278 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
7c01fa6c 4279 || gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_FOR)
bc7bff74 4280 gimple_seq_add_stmt (ilist, build_omp_barrier (NULL_TREE));
3d483a94 4281 }
4282
4283 /* If max_vf is non-zero, then we can use only a vectorization factor
4284 up to the max_vf we chose. So stick it into the safelen clause. */
4285 if (max_vf)
4286 {
4287 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
4288 OMP_CLAUSE_SAFELEN);
4289 if (c == NULL_TREE
c3f3b68d 4290 || (TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) == INTEGER_CST
4291 && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
4292 max_vf) == 1))
3d483a94 4293 {
4294 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_SAFELEN);
4295 OMP_CLAUSE_SAFELEN_EXPR (c) = build_int_cst (integer_type_node,
4296 max_vf);
4297 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
4298 gimple_omp_for_set_clauses (ctx->stmt, c);
4299 }
4300 }
1e8e9920 4301}
4302
773c5ba7 4303
1e8e9920 4304/* Generate code to implement the LASTPRIVATE clauses. This is used for
4305 both parallel and workshare constructs. PREDICATE may be NULL if it's
4306 always true. */
4307
4308static void
75a70cf9 4309lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
bc7bff74 4310 omp_context *ctx)
1e8e9920 4311{
3d483a94 4312 tree x, c, label = NULL, orig_clauses = clauses;
fd6481cf 4313 bool par_clauses = false;
3d483a94 4314 tree simduid = NULL, lastlane = NULL;
1e8e9920 4315
3d483a94 4316 /* Early exit if there are no lastprivate or linear clauses. */
4317 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
4318 if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LASTPRIVATE
4319 || (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LINEAR
4320 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses)))
4321 break;
1e8e9920 4322 if (clauses == NULL)
4323 {
4324 /* If this was a workshare clause, see if it had been combined
4325 with its parallel. In that case, look for the clauses on the
4326 parallel statement itself. */
4327 if (is_parallel_ctx (ctx))
4328 return;
4329
4330 ctx = ctx->outer;
4331 if (ctx == NULL || !is_parallel_ctx (ctx))
4332 return;
4333
75a70cf9 4334 clauses = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
1e8e9920 4335 OMP_CLAUSE_LASTPRIVATE);
4336 if (clauses == NULL)
4337 return;
fd6481cf 4338 par_clauses = true;
1e8e9920 4339 }
4340
75a70cf9 4341 if (predicate)
4342 {
1a91d914 4343 gcond *stmt;
75a70cf9 4344 tree label_true, arm1, arm2;
4345
e60a6f7b 4346 label = create_artificial_label (UNKNOWN_LOCATION);
4347 label_true = create_artificial_label (UNKNOWN_LOCATION);
75a70cf9 4348 arm1 = TREE_OPERAND (predicate, 0);
4349 arm2 = TREE_OPERAND (predicate, 1);
4350 gimplify_expr (&arm1, stmt_list, NULL, is_gimple_val, fb_rvalue);
4351 gimplify_expr (&arm2, stmt_list, NULL, is_gimple_val, fb_rvalue);
4352 stmt = gimple_build_cond (TREE_CODE (predicate), arm1, arm2,
4353 label_true, label);
4354 gimple_seq_add_stmt (stmt_list, stmt);
4355 gimple_seq_add_stmt (stmt_list, gimple_build_label (label_true));
4356 }
1e8e9920 4357
3d483a94 4358 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
10c55644 4359 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3d483a94 4360 {
4361 simduid = find_omp_clause (orig_clauses, OMP_CLAUSE__SIMDUID_);
4362 if (simduid)
4363 simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
4364 }
4365
fd6481cf 4366 for (c = clauses; c ;)
1e8e9920 4367 {
4368 tree var, new_var;
389dd41b 4369 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
1e8e9920 4370
3d483a94 4371 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
4372 || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
4373 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
fd6481cf 4374 {
4375 var = OMP_CLAUSE_DECL (c);
4376 new_var = lookup_decl (var, ctx);
1e8e9920 4377
3d483a94 4378 if (simduid && DECL_HAS_VALUE_EXPR_P (new_var))
4379 {
4380 tree val = DECL_VALUE_EXPR (new_var);
4381 if (TREE_CODE (val) == ARRAY_REF
4382 && VAR_P (TREE_OPERAND (val, 0))
4383 && lookup_attribute ("omp simd array",
4384 DECL_ATTRIBUTES (TREE_OPERAND (val,
4385 0))))
4386 {
4387 if (lastlane == NULL)
4388 {
f9e245b2 4389 lastlane = create_tmp_var (unsigned_type_node);
1a91d914 4390 gcall *g
3d483a94 4391 = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE,
4392 2, simduid,
4393 TREE_OPERAND (val, 1));
4394 gimple_call_set_lhs (g, lastlane);
4395 gimple_seq_add_stmt (stmt_list, g);
4396 }
4397 new_var = build4 (ARRAY_REF, TREE_TYPE (val),
4398 TREE_OPERAND (val, 0), lastlane,
4399 NULL_TREE, NULL_TREE);
4400 }
4401 }
4402
4403 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
4404 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
75a70cf9 4405 {
e3a19533 4406 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
75a70cf9 4407 gimple_seq_add_seq (stmt_list,
4408 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
3d483a94 4409 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) = NULL;
75a70cf9 4410 }
2b536a17 4411 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
4412 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
4413 {
4414 lower_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
4415 gimple_seq_add_seq (stmt_list,
4416 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c));
4417 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c) = NULL;
4418 }
1e8e9920 4419
fd6481cf 4420 x = build_outer_var_ref (var, ctx);
4421 if (is_reference (var))
182cf5a9 4422 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
fd6481cf 4423 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
75a70cf9 4424 gimplify_and_add (x, stmt_list);
fd6481cf 4425 }
4426 c = OMP_CLAUSE_CHAIN (c);
4427 if (c == NULL && !par_clauses)
4428 {
4429 /* If this was a workshare clause, see if it had been combined
4430 with its parallel. In that case, continue looking for the
4431 clauses also on the parallel statement itself. */
4432 if (is_parallel_ctx (ctx))
4433 break;
4434
4435 ctx = ctx->outer;
4436 if (ctx == NULL || !is_parallel_ctx (ctx))
4437 break;
4438
75a70cf9 4439 c = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
fd6481cf 4440 OMP_CLAUSE_LASTPRIVATE);
4441 par_clauses = true;
4442 }
1e8e9920 4443 }
4444
75a70cf9 4445 if (label)
4446 gimple_seq_add_stmt (stmt_list, gimple_build_label (label));
1e8e9920 4447}
4448
ca4c3545 4449static void
4450oacc_lower_reduction_var_helper (gimple_seq *stmt_seqp, omp_context *ctx,
4451 tree tid, tree var, tree new_var)
4452{
4453 /* The atomic add at the end of the sum creates unnecessary
4454 write contention on accelerators. To work around this,
4455 create an array to store the partial reductions. Later, in
4456 lower_omp_for (for openacc), the values of array will be
4457 combined. */
4458
4459 tree t = NULL_TREE, array, x;
4460 tree type = get_base_type (var);
4461 gimple stmt;
4462
4463 /* Now insert the partial reductions into the array. */
4464
4465 /* Find the reduction array. */
4466
4467 tree ptype = build_pointer_type (type);
4468
4469 t = lookup_oacc_reduction (oacc_get_reduction_array_id (var), ctx);
4470 t = build_receiver_ref (t, false, ctx->outer);
4471
4472 array = create_tmp_var (ptype);
4473 gimplify_assign (array, t, stmt_seqp);
4474
4475 tree ptr = create_tmp_var (TREE_TYPE (array));
4476
4477 /* Find the reduction array. */
4478
4479 /* testing a unary conversion. */
4480 tree offset = create_tmp_var (sizetype);
4481 gimplify_assign (offset, TYPE_SIZE_UNIT (type),
4482 stmt_seqp);
4483 t = create_tmp_var (sizetype);
4484 gimplify_assign (t, unshare_expr (fold_build1 (NOP_EXPR, sizetype, tid)),
4485 stmt_seqp);
4486 stmt = gimple_build_assign (offset, MULT_EXPR, offset, t);
4487 gimple_seq_add_stmt (stmt_seqp, stmt);
4488
4489 /* Offset expression. Does the POINTER_PLUS_EXPR take care
4490 of adding sizeof(var) to the array? */
4491 ptr = create_tmp_var (ptype);
4492 stmt = gimple_build_assign (unshare_expr (ptr), POINTER_PLUS_EXPR, array,
4493 offset);
4494 gimple_seq_add_stmt (stmt_seqp, stmt);
4495
4496 /* Move the local sum to gfc$sum[i]. */
4497 x = unshare_expr (build_simple_mem_ref (ptr));
4498 stmt = gimplify_assign (x, new_var, stmt_seqp);
4499}
773c5ba7 4500
1e8e9920 4501/* Generate code to implement the REDUCTION clauses. */
4502
4503static void
75a70cf9 4504lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
1e8e9920 4505{
75a70cf9 4506 gimple_seq sub_seq = NULL;
4507 gimple stmt;
ca4c3545 4508 tree x, c, tid = NULL_TREE;
1e8e9920 4509 int count = 0;
4510
3d483a94 4511 /* SIMD reductions are handled in lower_rec_input_clauses. */
4512 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
10c55644 4513 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3d483a94 4514 return;
4515
1e8e9920 4516 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
4517 update in that case, otherwise use a lock. */
4518 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
55d6e7cd 4519 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
1e8e9920 4520 {
4521 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4522 {
bc7bff74 4523 /* Never use OMP_ATOMIC for array reductions or UDRs. */
1e8e9920 4524 count = -1;
4525 break;
4526 }
4527 count++;
4528 }
4529
4530 if (count == 0)
4531 return;
4532
ca4c3545 4533 /* Initialize thread info for OpenACC. */
4534 if (is_gimple_omp_oacc (ctx->stmt))
4535 {
4536 /* Get the current thread id. */
4537 tree call = builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM);
4538 tid = create_tmp_var (TREE_TYPE (TREE_TYPE (call)));
4539 gimple stmt = gimple_build_call (call, 0);
4540 gimple_call_set_lhs (stmt, tid);
4541 gimple_seq_add_stmt (stmt_seqp, stmt);
4542 }
4543
1e8e9920 4544 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4545 {
4546 tree var, ref, new_var;
4547 enum tree_code code;
389dd41b 4548 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
1e8e9920 4549
55d6e7cd 4550 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
1e8e9920 4551 continue;
4552
4553 var = OMP_CLAUSE_DECL (c);
4554 new_var = lookup_decl (var, ctx);
4555 if (is_reference (var))
182cf5a9 4556 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
1e8e9920 4557 ref = build_outer_var_ref (var, ctx);
4558 code = OMP_CLAUSE_REDUCTION_CODE (c);
773c5ba7 4559
4560 /* reduction(-:var) sums up the partial results, so it acts
4561 identically to reduction(+:var). */
1e8e9920 4562 if (code == MINUS_EXPR)
4563 code = PLUS_EXPR;
4564
ca4c3545 4565 if (is_gimple_omp_oacc (ctx->stmt))
4566 {
4567 gcc_checking_assert (!OMP_CLAUSE_REDUCTION_PLACEHOLDER (c));
4568
4569 oacc_lower_reduction_var_helper (stmt_seqp, ctx, tid, var, new_var);
4570 }
4571 else if (count == 1)
1e8e9920 4572 {
389dd41b 4573 tree addr = build_fold_addr_expr_loc (clause_loc, ref);
1e8e9920 4574
4575 addr = save_expr (addr);
4576 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
389dd41b 4577 x = fold_build2_loc (clause_loc, code, TREE_TYPE (ref), ref, new_var);
1e8e9920 4578 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
75a70cf9 4579 gimplify_and_add (x, stmt_seqp);
1e8e9920 4580 return;
4581 }
ca4c3545 4582 else if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1e8e9920 4583 {
4584 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
4585
bc7bff74 4586 if (is_reference (var)
4587 && !useless_type_conversion_p (TREE_TYPE (placeholder),
4588 TREE_TYPE (ref)))
389dd41b 4589 ref = build_fold_addr_expr_loc (clause_loc, ref);
1e8e9920 4590 SET_DECL_VALUE_EXPR (placeholder, ref);
4591 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
e3a19533 4592 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
75a70cf9 4593 gimple_seq_add_seq (&sub_seq, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
4594 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
1e8e9920 4595 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
4596 }
4597 else
4598 {
4599 x = build2 (code, TREE_TYPE (ref), ref, new_var);
4600 ref = build_outer_var_ref (var, ctx);
75a70cf9 4601 gimplify_assign (ref, x, &sub_seq);
1e8e9920 4602 }
4603 }
4604
ca4c3545 4605 if (is_gimple_omp_oacc (ctx->stmt))
4606 return;
4607
b9a16870 4608 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START),
4609 0);
75a70cf9 4610 gimple_seq_add_stmt (stmt_seqp, stmt);
1e8e9920 4611
75a70cf9 4612 gimple_seq_add_seq (stmt_seqp, sub_seq);
1e8e9920 4613
b9a16870 4614 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END),
4615 0);
75a70cf9 4616 gimple_seq_add_stmt (stmt_seqp, stmt);
1e8e9920 4617}
4618
773c5ba7 4619
1e8e9920 4620/* Generate code to implement the COPYPRIVATE clauses. */
4621
4622static void
75a70cf9 4623lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist,
1e8e9920 4624 omp_context *ctx)
4625{
4626 tree c;
4627
4628 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4629 {
cb561506 4630 tree var, new_var, ref, x;
1e8e9920 4631 bool by_ref;
389dd41b 4632 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
1e8e9920 4633
55d6e7cd 4634 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
1e8e9920 4635 continue;
4636
4637 var = OMP_CLAUSE_DECL (c);
e8a588af 4638 by_ref = use_pointer_for_field (var, NULL);
1e8e9920 4639
4640 ref = build_sender_ref (var, ctx);
cb561506 4641 x = new_var = lookup_decl_in_outer_ctx (var, ctx);
4642 if (by_ref)
4643 {
4644 x = build_fold_addr_expr_loc (clause_loc, new_var);
4645 x = fold_convert_loc (clause_loc, TREE_TYPE (ref), x);
4646 }
75a70cf9 4647 gimplify_assign (ref, x, slist);
1e8e9920 4648
cb561506 4649 ref = build_receiver_ref (var, false, ctx);
4650 if (by_ref)
4651 {
4652 ref = fold_convert_loc (clause_loc,
4653 build_pointer_type (TREE_TYPE (new_var)),
4654 ref);
4655 ref = build_fold_indirect_ref_loc (clause_loc, ref);
4656 }
1e8e9920 4657 if (is_reference (var))
4658 {
cb561506 4659 ref = fold_convert_loc (clause_loc, TREE_TYPE (new_var), ref);
182cf5a9 4660 ref = build_simple_mem_ref_loc (clause_loc, ref);
4661 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
1e8e9920 4662 }
cb561506 4663 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, ref);
1e8e9920 4664 gimplify_and_add (x, rlist);
4665 }
4666}
4667
773c5ba7 4668
1e8e9920 4669/* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
4670 and REDUCTION from the sender (aka parent) side. */
4671
4672static void
75a70cf9 4673lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
4674 omp_context *ctx)
1e8e9920 4675{
4676 tree c;
4677
4678 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4679 {
773c5ba7 4680 tree val, ref, x, var;
1e8e9920 4681 bool by_ref, do_in = false, do_out = false;
389dd41b 4682 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
1e8e9920 4683
55d6e7cd 4684 switch (OMP_CLAUSE_CODE (c))
1e8e9920 4685 {
fd6481cf 4686 case OMP_CLAUSE_PRIVATE:
4687 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
4688 break;
4689 continue;
1e8e9920 4690 case OMP_CLAUSE_FIRSTPRIVATE:
4691 case OMP_CLAUSE_COPYIN:
4692 case OMP_CLAUSE_LASTPRIVATE:
4693 case OMP_CLAUSE_REDUCTION:
bc7bff74 4694 case OMP_CLAUSE__LOOPTEMP_:
1e8e9920 4695 break;
4696 default:
4697 continue;
4698 }
4699
87b31375 4700 val = OMP_CLAUSE_DECL (c);
4701 var = lookup_decl_in_outer_ctx (val, ctx);
773c5ba7 4702
f49d7bb5 4703 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
4704 && is_global_var (var))
4705 continue;
1e8e9920 4706 if (is_variable_sized (val))
4707 continue;
e8a588af 4708 by_ref = use_pointer_for_field (val, NULL);
1e8e9920 4709
55d6e7cd 4710 switch (OMP_CLAUSE_CODE (c))
1e8e9920 4711 {
fd6481cf 4712 case OMP_CLAUSE_PRIVATE:
1e8e9920 4713 case OMP_CLAUSE_FIRSTPRIVATE:
4714 case OMP_CLAUSE_COPYIN:
bc7bff74 4715 case OMP_CLAUSE__LOOPTEMP_:
1e8e9920 4716 do_in = true;
4717 break;
4718
4719 case OMP_CLAUSE_LASTPRIVATE:
4720 if (by_ref || is_reference (val))
4721 {
4722 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4723 continue;
4724 do_in = true;
4725 }
4726 else
fd6481cf 4727 {
4728 do_out = true;
4729 if (lang_hooks.decls.omp_private_outer_ref (val))
4730 do_in = true;
4731 }
1e8e9920 4732 break;
4733
4734 case OMP_CLAUSE_REDUCTION:
4735 do_in = true;
4736 do_out = !(by_ref || is_reference (val));
4737 break;
4738
4739 default:
4740 gcc_unreachable ();
4741 }
4742
4743 if (do_in)
4744 {
4745 ref = build_sender_ref (val, ctx);
389dd41b 4746 x = by_ref ? build_fold_addr_expr_loc (clause_loc, var) : var;
75a70cf9 4747 gimplify_assign (ref, x, ilist);
fd6481cf 4748 if (is_task_ctx (ctx))
4749 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref, 1)) = NULL;
1e8e9920 4750 }
773c5ba7 4751
1e8e9920 4752 if (do_out)
4753 {
4754 ref = build_sender_ref (val, ctx);
75a70cf9 4755 gimplify_assign (var, ref, olist);
1e8e9920 4756 }
4757 }
4758}
4759
75a70cf9 4760/* Generate code to implement SHARED from the sender (aka parent)
4761 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
4762 list things that got automatically shared. */
1e8e9920 4763
4764static void
75a70cf9 4765lower_send_shared_vars (gimple_seq *ilist, gimple_seq *olist, omp_context *ctx)
1e8e9920 4766{
fd6481cf 4767 tree var, ovar, nvar, f, x, record_type;
1e8e9920 4768
4769 if (ctx->record_type == NULL)
4770 return;
773c5ba7 4771
fd6481cf 4772 record_type = ctx->srecord_type ? ctx->srecord_type : ctx->record_type;
1767a056 4773 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
1e8e9920 4774 {
4775 ovar = DECL_ABSTRACT_ORIGIN (f);
4776 nvar = maybe_lookup_decl (ovar, ctx);
4777 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
4778 continue;
4779
773c5ba7 4780 /* If CTX is a nested parallel directive. Find the immediately
4781 enclosing parallel or workshare construct that contains a
4782 mapping for OVAR. */
87b31375 4783 var = lookup_decl_in_outer_ctx (ovar, ctx);
773c5ba7 4784
e8a588af 4785 if (use_pointer_for_field (ovar, ctx))
1e8e9920 4786 {
4787 x = build_sender_ref (ovar, ctx);
773c5ba7 4788 var = build_fold_addr_expr (var);
75a70cf9 4789 gimplify_assign (x, var, ilist);
1e8e9920 4790 }
4791 else
4792 {
4793 x = build_sender_ref (ovar, ctx);
75a70cf9 4794 gimplify_assign (x, var, ilist);
1e8e9920 4795
d2263ebb 4796 if (!TREE_READONLY (var)
4797 /* We don't need to receive a new reference to a result
4798 or parm decl. In fact we may not store to it as we will
4799 invalidate any pending RSO and generate wrong gimple
4800 during inlining. */
4801 && !((TREE_CODE (var) == RESULT_DECL
4802 || TREE_CODE (var) == PARM_DECL)
4803 && DECL_BY_REFERENCE (var)))
fd6481cf 4804 {
4805 x = build_sender_ref (ovar, ctx);
75a70cf9 4806 gimplify_assign (var, x, olist);
fd6481cf 4807 }
1e8e9920 4808 }
4809 }
4810}
4811
75a70cf9 4812
4813/* A convenience function to build an empty GIMPLE_COND with just the
4814 condition. */
4815
1a91d914 4816static gcond *
75a70cf9 4817gimple_build_cond_empty (tree cond)
4818{
4819 enum tree_code pred_code;
4820 tree lhs, rhs;
4821
4822 gimple_cond_get_ops_from_tree (cond, &pred_code, &lhs, &rhs);
4823 return gimple_build_cond (pred_code, lhs, rhs, NULL_TREE, NULL_TREE);
4824}
4825
4826
48e1416a 4827/* Build the function calls to GOMP_parallel_start etc to actually
773c5ba7 4828 generate the parallel operation. REGION is the parallel region
4829 being expanded. BB is the block where to insert the code. WS_ARGS
4830 will be set if this is a call to a combined parallel+workshare
4831 construct, it contains the list of additional arguments needed by
4832 the workshare construct. */
1e8e9920 4833
4834static void
61e47ac8 4835expand_parallel_call (struct omp_region *region, basic_block bb,
1a91d914 4836 gomp_parallel *entry_stmt,
4837 vec<tree, va_gc> *ws_args)
1e8e9920 4838{
bc7bff74 4839 tree t, t1, t2, val, cond, c, clauses, flags;
75a70cf9 4840 gimple_stmt_iterator gsi;
4841 gimple stmt;
b9a16870 4842 enum built_in_function start_ix;
4843 int start_ix2;
389dd41b 4844 location_t clause_loc;
f1f41a6c 4845 vec<tree, va_gc> *args;
773c5ba7 4846
75a70cf9 4847 clauses = gimple_omp_parallel_clauses (entry_stmt);
773c5ba7 4848
bc7bff74 4849 /* Determine what flavor of GOMP_parallel we will be
773c5ba7 4850 emitting. */
bc7bff74 4851 start_ix = BUILT_IN_GOMP_PARALLEL;
773c5ba7 4852 if (is_combined_parallel (region))
4853 {
61e47ac8 4854 switch (region->inner->type)
773c5ba7 4855 {
75a70cf9 4856 case GIMPLE_OMP_FOR:
fd6481cf 4857 gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
bc7bff74 4858 start_ix2 = ((int)BUILT_IN_GOMP_PARALLEL_LOOP_STATIC
b9a16870 4859 + (region->inner->sched_kind
4860 == OMP_CLAUSE_SCHEDULE_RUNTIME
4861 ? 3 : region->inner->sched_kind));
4862 start_ix = (enum built_in_function)start_ix2;
61e47ac8 4863 break;
75a70cf9 4864 case GIMPLE_OMP_SECTIONS:
bc7bff74 4865 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS;
61e47ac8 4866 break;
4867 default:
4868 gcc_unreachable ();
773c5ba7 4869 }
773c5ba7 4870 }
1e8e9920 4871
4872 /* By default, the value of NUM_THREADS is zero (selected at run time)
4873 and there is no conditional. */
4874 cond = NULL_TREE;
4875 val = build_int_cst (unsigned_type_node, 0);
bc7bff74 4876 flags = build_int_cst (unsigned_type_node, 0);
1e8e9920 4877
4878 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
4879 if (c)
4880 cond = OMP_CLAUSE_IF_EXPR (c);
4881
4882 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
4883 if (c)
389dd41b 4884 {
4885 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
4886 clause_loc = OMP_CLAUSE_LOCATION (c);
4887 }
4888 else
4889 clause_loc = gimple_location (entry_stmt);
1e8e9920 4890
bc7bff74 4891 c = find_omp_clause (clauses, OMP_CLAUSE_PROC_BIND);
4892 if (c)
4893 flags = build_int_cst (unsigned_type_node, OMP_CLAUSE_PROC_BIND_KIND (c));
4894
1e8e9920 4895 /* Ensure 'val' is of the correct type. */
389dd41b 4896 val = fold_convert_loc (clause_loc, unsigned_type_node, val);
1e8e9920 4897
4898 /* If we found the clause 'if (cond)', build either
4899 (cond != 0) or (cond ? val : 1u). */
4900 if (cond)
4901 {
773c5ba7 4902 cond = gimple_boolify (cond);
4903
1e8e9920 4904 if (integer_zerop (val))
389dd41b 4905 val = fold_build2_loc (clause_loc,
4906 EQ_EXPR, unsigned_type_node, cond,
79acaae1 4907 build_int_cst (TREE_TYPE (cond), 0));
1e8e9920 4908 else
773c5ba7 4909 {
4910 basic_block cond_bb, then_bb, else_bb;
79acaae1 4911 edge e, e_then, e_else;
75a70cf9 4912 tree tmp_then, tmp_else, tmp_join, tmp_var;
79acaae1 4913
f9e245b2 4914 tmp_var = create_tmp_var (TREE_TYPE (val));
79acaae1 4915 if (gimple_in_ssa_p (cfun))
4916 {
f9e245b2 4917 tmp_then = make_ssa_name (tmp_var);
4918 tmp_else = make_ssa_name (tmp_var);
4919 tmp_join = make_ssa_name (tmp_var);
79acaae1 4920 }
4921 else
4922 {
4923 tmp_then = tmp_var;
4924 tmp_else = tmp_var;
4925 tmp_join = tmp_var;
4926 }
773c5ba7 4927
4302d619 4928 e = split_block_after_labels (bb);
773c5ba7 4929 cond_bb = e->src;
4930 bb = e->dest;
4931 remove_edge (e);
4932
4933 then_bb = create_empty_bb (cond_bb);
4934 else_bb = create_empty_bb (then_bb);
79acaae1 4935 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
4936 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
773c5ba7 4937
75a70cf9 4938 stmt = gimple_build_cond_empty (cond);
4939 gsi = gsi_start_bb (cond_bb);
4940 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
773c5ba7 4941
75a70cf9 4942 gsi = gsi_start_bb (then_bb);
4943 stmt = gimple_build_assign (tmp_then, val);
4944 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
773c5ba7 4945
75a70cf9 4946 gsi = gsi_start_bb (else_bb);
4947 stmt = gimple_build_assign
4948 (tmp_else, build_int_cst (unsigned_type_node, 1));
4949 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
773c5ba7 4950
4951 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
4952 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
b3083327 4953 add_bb_to_loop (then_bb, cond_bb->loop_father);
4954 add_bb_to_loop (else_bb, cond_bb->loop_father);
79acaae1 4955 e_then = make_edge (then_bb, bb, EDGE_FALLTHRU);
4956 e_else = make_edge (else_bb, bb, EDGE_FALLTHRU);
773c5ba7 4957
79acaae1 4958 if (gimple_in_ssa_p (cfun))
4959 {
1a91d914 4960 gphi *phi = create_phi_node (tmp_join, bb);
60d535d2 4961 add_phi_arg (phi, tmp_then, e_then, UNKNOWN_LOCATION);
4962 add_phi_arg (phi, tmp_else, e_else, UNKNOWN_LOCATION);
79acaae1 4963 }
4964
4965 val = tmp_join;
773c5ba7 4966 }
4967
75a70cf9 4968 gsi = gsi_start_bb (bb);
4969 val = force_gimple_operand_gsi (&gsi, val, true, NULL_TREE,
4970 false, GSI_CONTINUE_LINKING);
1e8e9920 4971 }
4972
75a70cf9 4973 gsi = gsi_last_bb (bb);
4974 t = gimple_omp_parallel_data_arg (entry_stmt);
1e8e9920 4975 if (t == NULL)
c2f47e15 4976 t1 = null_pointer_node;
1e8e9920 4977 else
c2f47e15 4978 t1 = build_fold_addr_expr (t);
75a70cf9 4979 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
773c5ba7 4980
bc7bff74 4981 vec_alloc (args, 4 + vec_safe_length (ws_args));
f1f41a6c 4982 args->quick_push (t2);
4983 args->quick_push (t1);
4984 args->quick_push (val);
4985 if (ws_args)
4986 args->splice (*ws_args);
bc7bff74 4987 args->quick_push (flags);
414c3a2c 4988
4989 t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
b9a16870 4990 builtin_decl_explicit (start_ix), args);
773c5ba7 4991
75a70cf9 4992 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4993 false, GSI_CONTINUE_LINKING);
1e8e9920 4994}
4995
40750995 4996/* Insert a function call whose name is FUNC_NAME with the information from
4997 ENTRY_STMT into the basic_block BB. */
4998
4999static void
1a91d914 5000expand_cilk_for_call (basic_block bb, gomp_parallel *entry_stmt,
40750995 5001 vec <tree, va_gc> *ws_args)
5002{
5003 tree t, t1, t2;
5004 gimple_stmt_iterator gsi;
5005 vec <tree, va_gc> *args;
5006
5007 gcc_assert (vec_safe_length (ws_args) == 2);
5008 tree func_name = (*ws_args)[0];
5009 tree grain = (*ws_args)[1];
5010
5011 tree clauses = gimple_omp_parallel_clauses (entry_stmt);
5012 tree count = find_omp_clause (clauses, OMP_CLAUSE__CILK_FOR_COUNT_);
5013 gcc_assert (count != NULL_TREE);
5014 count = OMP_CLAUSE_OPERAND (count, 0);
5015
5016 gsi = gsi_last_bb (bb);
5017 t = gimple_omp_parallel_data_arg (entry_stmt);
5018 if (t == NULL)
5019 t1 = null_pointer_node;
5020 else
5021 t1 = build_fold_addr_expr (t);
5022 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
5023
5024 vec_alloc (args, 4);
5025 args->quick_push (t2);
5026 args->quick_push (t1);
5027 args->quick_push (count);
5028 args->quick_push (grain);
5029 t = build_call_expr_loc_vec (UNKNOWN_LOCATION, func_name, args);
5030
5031 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, false,
5032 GSI_CONTINUE_LINKING);
5033}
773c5ba7 5034
fd6481cf 5035/* Build the function call to GOMP_task to actually
5036 generate the task operation. BB is the block where to insert the code. */
5037
5038static void
1a91d914 5039expand_task_call (basic_block bb, gomp_task *entry_stmt)
fd6481cf 5040{
bc7bff74 5041 tree t, t1, t2, t3, flags, cond, c, c2, clauses, depend;
75a70cf9 5042 gimple_stmt_iterator gsi;
389dd41b 5043 location_t loc = gimple_location (entry_stmt);
fd6481cf 5044
75a70cf9 5045 clauses = gimple_omp_task_clauses (entry_stmt);
fd6481cf 5046
fd6481cf 5047 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
5048 if (c)
5049 cond = gimple_boolify (OMP_CLAUSE_IF_EXPR (c));
5050 else
5051 cond = boolean_true_node;
5052
5053 c = find_omp_clause (clauses, OMP_CLAUSE_UNTIED);
2169f33b 5054 c2 = find_omp_clause (clauses, OMP_CLAUSE_MERGEABLE);
bc7bff74 5055 depend = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
2169f33b 5056 flags = build_int_cst (unsigned_type_node,
bc7bff74 5057 (c ? 1 : 0) + (c2 ? 4 : 0) + (depend ? 8 : 0));
2169f33b 5058
5059 c = find_omp_clause (clauses, OMP_CLAUSE_FINAL);
5060 if (c)
5061 {
5062 c = gimple_boolify (OMP_CLAUSE_FINAL_EXPR (c));
5063 c = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, c,
5064 build_int_cst (unsigned_type_node, 2),
5065 build_int_cst (unsigned_type_node, 0));
5066 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node, flags, c);
5067 }
bc7bff74 5068 if (depend)
5069 depend = OMP_CLAUSE_DECL (depend);
5070 else
5071 depend = build_int_cst (ptr_type_node, 0);
fd6481cf 5072
75a70cf9 5073 gsi = gsi_last_bb (bb);
5074 t = gimple_omp_task_data_arg (entry_stmt);
fd6481cf 5075 if (t == NULL)
5076 t2 = null_pointer_node;
5077 else
389dd41b 5078 t2 = build_fold_addr_expr_loc (loc, t);
5079 t1 = build_fold_addr_expr_loc (loc, gimple_omp_task_child_fn (entry_stmt));
75a70cf9 5080 t = gimple_omp_task_copy_fn (entry_stmt);
fd6481cf 5081 if (t == NULL)
5082 t3 = null_pointer_node;
5083 else
389dd41b 5084 t3 = build_fold_addr_expr_loc (loc, t);
fd6481cf 5085
b9a16870 5086 t = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK),
bc7bff74 5087 8, t1, t2, t3,
75a70cf9 5088 gimple_omp_task_arg_size (entry_stmt),
bc7bff74 5089 gimple_omp_task_arg_align (entry_stmt), cond, flags,
5090 depend);
fd6481cf 5091
75a70cf9 5092 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5093 false, GSI_CONTINUE_LINKING);
fd6481cf 5094}
5095
5096
75a70cf9 5097/* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
5098 catch handler and return it. This prevents programs from violating the
5099 structured block semantics with throws. */
1e8e9920 5100
75a70cf9 5101static gimple_seq
5102maybe_catch_exception (gimple_seq body)
1e8e9920 5103{
e38def9c 5104 gimple g;
5105 tree decl;
1e8e9920 5106
5107 if (!flag_exceptions)
75a70cf9 5108 return body;
1e8e9920 5109
596981c8 5110 if (lang_hooks.eh_protect_cleanup_actions != NULL)
5111 decl = lang_hooks.eh_protect_cleanup_actions ();
1e8e9920 5112 else
b9a16870 5113 decl = builtin_decl_explicit (BUILT_IN_TRAP);
75a70cf9 5114
e38def9c 5115 g = gimple_build_eh_must_not_throw (decl);
5116 g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g),
75a70cf9 5117 GIMPLE_TRY_CATCH);
1e8e9920 5118
e38def9c 5119 return gimple_seq_alloc_with_stmt (g);
1e8e9920 5120}
5121
773c5ba7 5122/* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
1e8e9920 5123
773c5ba7 5124static tree
f1f41a6c 5125vec2chain (vec<tree, va_gc> *v)
1e8e9920 5126{
2ab2ce89 5127 tree chain = NULL_TREE, t;
5128 unsigned ix;
1e8e9920 5129
f1f41a6c 5130 FOR_EACH_VEC_SAFE_ELT_REVERSE (v, ix, t)
773c5ba7 5131 {
1767a056 5132 DECL_CHAIN (t) = chain;
2ab2ce89 5133 chain = t;
773c5ba7 5134 }
1e8e9920 5135
2ab2ce89 5136 return chain;
773c5ba7 5137}
1e8e9920 5138
1e8e9920 5139
773c5ba7 5140/* Remove barriers in REGION->EXIT's block. Note that this is only
75a70cf9 5141 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
5142 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
5143 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
773c5ba7 5144 removed. */
1e8e9920 5145
773c5ba7 5146static void
5147remove_exit_barrier (struct omp_region *region)
5148{
75a70cf9 5149 gimple_stmt_iterator gsi;
773c5ba7 5150 basic_block exit_bb;
61e47ac8 5151 edge_iterator ei;
5152 edge e;
75a70cf9 5153 gimple stmt;
4a04f4b4 5154 int any_addressable_vars = -1;
1e8e9920 5155
61e47ac8 5156 exit_bb = region->exit;
1e8e9920 5157
5056ba1a 5158 /* If the parallel region doesn't return, we don't have REGION->EXIT
5159 block at all. */
5160 if (! exit_bb)
5161 return;
5162
75a70cf9 5163 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
5164 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
61e47ac8 5165 statements that can appear in between are extremely limited -- no
5166 memory operations at all. Here, we allow nothing at all, so the
75a70cf9 5167 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
5168 gsi = gsi_last_bb (exit_bb);
5169 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
5170 gsi_prev (&gsi);
5171 if (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
773c5ba7 5172 return;
1e8e9920 5173
61e47ac8 5174 FOR_EACH_EDGE (e, ei, exit_bb->preds)
5175 {
75a70cf9 5176 gsi = gsi_last_bb (e->src);
5177 if (gsi_end_p (gsi))
61e47ac8 5178 continue;
75a70cf9 5179 stmt = gsi_stmt (gsi);
4a04f4b4 5180 if (gimple_code (stmt) == GIMPLE_OMP_RETURN
5181 && !gimple_omp_return_nowait_p (stmt))
5182 {
5183 /* OpenMP 3.0 tasks unfortunately prevent this optimization
5184 in many cases. If there could be tasks queued, the barrier
5185 might be needed to let the tasks run before some local
5186 variable of the parallel that the task uses as shared
5187 runs out of scope. The task can be spawned either
5188 from within current function (this would be easy to check)
5189 or from some function it calls and gets passed an address
5190 of such a variable. */
5191 if (any_addressable_vars < 0)
5192 {
1a91d914 5193 gomp_parallel *parallel_stmt
5194 = as_a <gomp_parallel *> (last_stmt (region->entry));
4a04f4b4 5195 tree child_fun = gimple_omp_parallel_child_fn (parallel_stmt);
2ab2ce89 5196 tree local_decls, block, decl;
5197 unsigned ix;
4a04f4b4 5198
5199 any_addressable_vars = 0;
2ab2ce89 5200 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun), ix, decl)
5201 if (TREE_ADDRESSABLE (decl))
4a04f4b4 5202 {
5203 any_addressable_vars = 1;
5204 break;
5205 }
5206 for (block = gimple_block (stmt);
5207 !any_addressable_vars
5208 && block
5209 && TREE_CODE (block) == BLOCK;
5210 block = BLOCK_SUPERCONTEXT (block))
5211 {
5212 for (local_decls = BLOCK_VARS (block);
5213 local_decls;
1767a056 5214 local_decls = DECL_CHAIN (local_decls))
4a04f4b4 5215 if (TREE_ADDRESSABLE (local_decls))
5216 {
5217 any_addressable_vars = 1;
5218 break;
5219 }
5220 if (block == gimple_block (parallel_stmt))
5221 break;
5222 }
5223 }
5224 if (!any_addressable_vars)
5225 gimple_omp_return_set_nowait (stmt);
5226 }
61e47ac8 5227 }
1e8e9920 5228}
5229
61e47ac8 5230static void
5231remove_exit_barriers (struct omp_region *region)
5232{
75a70cf9 5233 if (region->type == GIMPLE_OMP_PARALLEL)
61e47ac8 5234 remove_exit_barrier (region);
5235
5236 if (region->inner)
5237 {
5238 region = region->inner;
5239 remove_exit_barriers (region);
5240 while (region->next)
5241 {
5242 region = region->next;
5243 remove_exit_barriers (region);
5244 }
5245 }
5246}
773c5ba7 5247
658b4427 5248/* Optimize omp_get_thread_num () and omp_get_num_threads ()
5249 calls. These can't be declared as const functions, but
5250 within one parallel body they are constant, so they can be
5251 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
fd6481cf 5252 which are declared const. Similarly for task body, except
5253 that in untied task omp_get_thread_num () can change at any task
5254 scheduling point. */
658b4427 5255
5256static void
75a70cf9 5257optimize_omp_library_calls (gimple entry_stmt)
658b4427 5258{
5259 basic_block bb;
75a70cf9 5260 gimple_stmt_iterator gsi;
b9a16870 5261 tree thr_num_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
5262 tree thr_num_id = DECL_ASSEMBLER_NAME (thr_num_tree);
5263 tree num_thr_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
5264 tree num_thr_id = DECL_ASSEMBLER_NAME (num_thr_tree);
75a70cf9 5265 bool untied_task = (gimple_code (entry_stmt) == GIMPLE_OMP_TASK
5266 && find_omp_clause (gimple_omp_task_clauses (entry_stmt),
fd6481cf 5267 OMP_CLAUSE_UNTIED) != NULL);
658b4427 5268
fc00614f 5269 FOR_EACH_BB_FN (bb, cfun)
75a70cf9 5270 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
658b4427 5271 {
75a70cf9 5272 gimple call = gsi_stmt (gsi);
658b4427 5273 tree decl;
5274
75a70cf9 5275 if (is_gimple_call (call)
5276 && (decl = gimple_call_fndecl (call))
658b4427 5277 && DECL_EXTERNAL (decl)
5278 && TREE_PUBLIC (decl)
5279 && DECL_INITIAL (decl) == NULL)
5280 {
5281 tree built_in;
5282
5283 if (DECL_NAME (decl) == thr_num_id)
fd6481cf 5284 {
5285 /* In #pragma omp task untied omp_get_thread_num () can change
5286 during the execution of the task region. */
5287 if (untied_task)
5288 continue;
b9a16870 5289 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
fd6481cf 5290 }
658b4427 5291 else if (DECL_NAME (decl) == num_thr_id)
b9a16870 5292 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
658b4427 5293 else
5294 continue;
5295
5296 if (DECL_ASSEMBLER_NAME (decl) != DECL_ASSEMBLER_NAME (built_in)
75a70cf9 5297 || gimple_call_num_args (call) != 0)
658b4427 5298 continue;
5299
5300 if (flag_exceptions && !TREE_NOTHROW (decl))
5301 continue;
5302
5303 if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
1ea6a73c 5304 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl)),
5305 TREE_TYPE (TREE_TYPE (built_in))))
658b4427 5306 continue;
5307
0acacf9e 5308 gimple_call_set_fndecl (call, built_in);
658b4427 5309 }
5310 }
5311}
5312
8e6b4515 5313/* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
5314 regimplified. */
5315
5316static tree
5317expand_omp_regimplify_p (tree *tp, int *walk_subtrees, void *)
5318{
5319 tree t = *tp;
5320
5321 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
5322 if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t))
5323 return t;
5324
5325 if (TREE_CODE (t) == ADDR_EXPR)
5326 recompute_tree_invariant_for_addr_expr (t);
5327
5328 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
5329 return NULL_TREE;
5330}
5331
3d483a94 5332/* Prepend TO = FROM assignment before *GSI_P. */
5333
5334static void
5335expand_omp_build_assign (gimple_stmt_iterator *gsi_p, tree to, tree from)
5336{
5337 bool simple_p = DECL_P (to) && TREE_ADDRESSABLE (to);
5338 from = force_gimple_operand_gsi (gsi_p, from, simple_p, NULL_TREE,
5339 true, GSI_SAME_STMT);
5340 gimple stmt = gimple_build_assign (to, from);
5341 gsi_insert_before (gsi_p, stmt, GSI_SAME_STMT);
5342 if (walk_tree (&from, expand_omp_regimplify_p, NULL, NULL)
5343 || walk_tree (&to, expand_omp_regimplify_p, NULL, NULL))
5344 {
5345 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
5346 gimple_regimplify_operands (stmt, &gsi);
5347 }
5348}
5349
fd6481cf 5350/* Expand the OpenMP parallel or task directive starting at REGION. */
1e8e9920 5351
5352static void
fd6481cf 5353expand_omp_taskreg (struct omp_region *region)
1e8e9920 5354{
773c5ba7 5355 basic_block entry_bb, exit_bb, new_bb;
87d4aa85 5356 struct function *child_cfun;
414c3a2c 5357 tree child_fn, block, t;
75a70cf9 5358 gimple_stmt_iterator gsi;
5359 gimple entry_stmt, stmt;
773c5ba7 5360 edge e;
f1f41a6c 5361 vec<tree, va_gc> *ws_args;
773c5ba7 5362
61e47ac8 5363 entry_stmt = last_stmt (region->entry);
75a70cf9 5364 child_fn = gimple_omp_taskreg_child_fn (entry_stmt);
773c5ba7 5365 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
773c5ba7 5366
61e47ac8 5367 entry_bb = region->entry;
b25f70fd 5368 if (gimple_code (entry_stmt) == GIMPLE_OMP_TASK)
5369 exit_bb = region->cont;
5370 else
5371 exit_bb = region->exit;
773c5ba7 5372
40750995 5373 bool is_cilk_for
5374 = (flag_cilkplus
5375 && gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL
5376 && find_omp_clause (gimple_omp_parallel_clauses (entry_stmt),
5377 OMP_CLAUSE__CILK_FOR_COUNT_) != NULL_TREE);
5378
5379 if (is_cilk_for)
5380 /* If it is a _Cilk_for statement, it is modelled *like* a parallel for,
5381 and the inner statement contains the name of the built-in function
5382 and grain. */
5383 ws_args = region->inner->ws_args;
5384 else if (is_combined_parallel (region))
61e47ac8 5385 ws_args = region->ws_args;
773c5ba7 5386 else
414c3a2c 5387 ws_args = NULL;
1e8e9920 5388
61e47ac8 5389 if (child_cfun->cfg)
1e8e9920 5390 {
773c5ba7 5391 /* Due to inlining, it may happen that we have already outlined
5392 the region, in which case all we need to do is make the
5393 sub-graph unreachable and emit the parallel call. */
5394 edge entry_succ_e, exit_succ_e;
773c5ba7 5395
5396 entry_succ_e = single_succ_edge (entry_bb);
773c5ba7 5397
75a70cf9 5398 gsi = gsi_last_bb (entry_bb);
5399 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_PARALLEL
5400 || gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_TASK);
5401 gsi_remove (&gsi, true);
773c5ba7 5402
5403 new_bb = entry_bb;
03ed154b 5404 if (exit_bb)
5405 {
5406 exit_succ_e = single_succ_edge (exit_bb);
5407 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
5408 }
79acaae1 5409 remove_edge_and_dominated_blocks (entry_succ_e);
1e8e9920 5410 }
773c5ba7 5411 else
5412 {
501bdd19 5413 unsigned srcidx, dstidx, num;
2ab2ce89 5414
773c5ba7 5415 /* If the parallel region needs data sent from the parent
3480139d 5416 function, then the very first statement (except possible
5417 tree profile counter updates) of the parallel body
773c5ba7 5418 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
5419 &.OMP_DATA_O is passed as an argument to the child function,
5420 we need to replace it with the argument as seen by the child
5421 function.
5422
5423 In most cases, this will end up being the identity assignment
5424 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
5425 a function call that has been inlined, the original PARM_DECL
5426 .OMP_DATA_I may have been converted into a different local
5427 variable. In which case, we need to keep the assignment. */
75a70cf9 5428 if (gimple_omp_taskreg_data_arg (entry_stmt))
773c5ba7 5429 {
b25f70fd 5430 basic_block entry_succ_bb
5431 = single_succ_p (entry_bb) ? single_succ (entry_bb)
5432 : FALLTHRU_EDGE (entry_bb)->dest;
75a70cf9 5433 tree arg, narg;
5434 gimple parcopy_stmt = NULL;
1e8e9920 5435
75a70cf9 5436 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
3480139d 5437 {
75a70cf9 5438 gimple stmt;
3480139d 5439
75a70cf9 5440 gcc_assert (!gsi_end_p (gsi));
5441 stmt = gsi_stmt (gsi);
5442 if (gimple_code (stmt) != GIMPLE_ASSIGN)
cc6b725b 5443 continue;
5444
75a70cf9 5445 if (gimple_num_ops (stmt) == 2)
3480139d 5446 {
75a70cf9 5447 tree arg = gimple_assign_rhs1 (stmt);
5448
5449 /* We're ignore the subcode because we're
5450 effectively doing a STRIP_NOPS. */
5451
5452 if (TREE_CODE (arg) == ADDR_EXPR
5453 && TREE_OPERAND (arg, 0)
5454 == gimple_omp_taskreg_data_arg (entry_stmt))
5455 {
5456 parcopy_stmt = stmt;
5457 break;
5458 }
3480139d 5459 }
5460 }
79acaae1 5461
75a70cf9 5462 gcc_assert (parcopy_stmt != NULL);
79acaae1 5463 arg = DECL_ARGUMENTS (child_fn);
5464
5465 if (!gimple_in_ssa_p (cfun))
5466 {
75a70cf9 5467 if (gimple_assign_lhs (parcopy_stmt) == arg)
5468 gsi_remove (&gsi, true);
79acaae1 5469 else
75a70cf9 5470 {
5471 /* ?? Is setting the subcode really necessary ?? */
5472 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (arg));
5473 gimple_assign_set_rhs1 (parcopy_stmt, arg);
5474 }
79acaae1 5475 }
5476 else
5477 {
5478 /* If we are in ssa form, we must load the value from the default
5479 definition of the argument. That should not be defined now,
5480 since the argument is not used uninitialized. */
c6dfe037 5481 gcc_assert (ssa_default_def (cfun, arg) == NULL);
75a70cf9 5482 narg = make_ssa_name (arg, gimple_build_nop ());
c6dfe037 5483 set_ssa_default_def (cfun, arg, narg);
75a70cf9 5484 /* ?? Is setting the subcode really necessary ?? */
5485 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (narg));
5486 gimple_assign_set_rhs1 (parcopy_stmt, narg);
79acaae1 5487 update_stmt (parcopy_stmt);
5488 }
773c5ba7 5489 }
5490
5491 /* Declare local variables needed in CHILD_CFUN. */
5492 block = DECL_INITIAL (child_fn);
2ab2ce89 5493 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
e1a7ccb9 5494 /* The gimplifier could record temporaries in parallel/task block
5495 rather than in containing function's local_decls chain,
5496 which would mean cgraph missed finalizing them. Do it now. */
1767a056 5497 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
e1a7ccb9 5498 if (TREE_CODE (t) == VAR_DECL
5499 && TREE_STATIC (t)
5500 && !DECL_EXTERNAL (t))
97221fd7 5501 varpool_node::finalize_decl (t);
75a70cf9 5502 DECL_SAVED_TREE (child_fn) = NULL;
e3a19533 5503 /* We'll create a CFG for child_fn, so no gimple body is needed. */
5504 gimple_set_body (child_fn, NULL);
1d22f541 5505 TREE_USED (block) = 1;
773c5ba7 5506
79acaae1 5507 /* Reset DECL_CONTEXT on function arguments. */
1767a056 5508 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
773c5ba7 5509 DECL_CONTEXT (t) = child_fn;
5510
75a70cf9 5511 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
5512 so that it can be moved to the child function. */
5513 gsi = gsi_last_bb (entry_bb);
5514 stmt = gsi_stmt (gsi);
5515 gcc_assert (stmt && (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
5516 || gimple_code (stmt) == GIMPLE_OMP_TASK));
75a70cf9 5517 e = split_block (entry_bb, stmt);
923635e7 5518 gsi_remove (&gsi, true);
773c5ba7 5519 entry_bb = e->dest;
b25f70fd 5520 edge e2 = NULL;
5521 if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
5522 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
5523 else
5524 {
5525 e2 = make_edge (e->src, BRANCH_EDGE (entry_bb)->dest, EDGE_ABNORMAL);
5526 gcc_assert (e2->dest == region->exit);
5527 remove_edge (BRANCH_EDGE (entry_bb));
5528 set_immediate_dominator (CDI_DOMINATORS, e2->dest, e->src);
5529 gsi = gsi_last_bb (region->exit);
5530 gcc_assert (!gsi_end_p (gsi)
5531 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
5532 gsi_remove (&gsi, true);
5533 }
773c5ba7 5534
b25f70fd 5535 /* Convert GIMPLE_OMP_{RETURN,CONTINUE} into a RETURN_EXPR. */
5056ba1a 5536 if (exit_bb)
5537 {
75a70cf9 5538 gsi = gsi_last_bb (exit_bb);
5539 gcc_assert (!gsi_end_p (gsi)
b25f70fd 5540 && (gimple_code (gsi_stmt (gsi))
5541 == (e2 ? GIMPLE_OMP_CONTINUE : GIMPLE_OMP_RETURN)));
75a70cf9 5542 stmt = gimple_build_return (NULL);
5543 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
5544 gsi_remove (&gsi, true);
5056ba1a 5545 }
79acaae1 5546
5547 /* Move the parallel region into CHILD_CFUN. */
48e1416a 5548
79acaae1 5549 if (gimple_in_ssa_p (cfun))
5550 {
bcaa2770 5551 init_tree_ssa (child_cfun);
5084b2e4 5552 init_ssa_operands (child_cfun);
5553 child_cfun->gimple_df->in_ssa_p = true;
1d22f541 5554 block = NULL_TREE;
79acaae1 5555 }
1d22f541 5556 else
75a70cf9 5557 block = gimple_block (entry_stmt);
1d22f541 5558
5559 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
79acaae1 5560 if (exit_bb)
5561 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
b25f70fd 5562 if (e2)
5563 {
5564 basic_block dest_bb = e2->dest;
5565 if (!exit_bb)
5566 make_edge (new_bb, dest_bb, EDGE_FALLTHRU);
5567 remove_edge (e2);
5568 set_immediate_dominator (CDI_DOMINATORS, dest_bb, new_bb);
5569 }
04c2922b 5570 /* When the OMP expansion process cannot guarantee an up-to-date
5571 loop tree arrange for the child function to fixup loops. */
5572 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
5573 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
79acaae1 5574
1d22f541 5575 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
f1f41a6c 5576 num = vec_safe_length (child_cfun->local_decls);
501bdd19 5577 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
5578 {
f1f41a6c 5579 t = (*child_cfun->local_decls)[srcidx];
501bdd19 5580 if (DECL_CONTEXT (t) == cfun->decl)
5581 continue;
5582 if (srcidx != dstidx)
f1f41a6c 5583 (*child_cfun->local_decls)[dstidx] = t;
501bdd19 5584 dstidx++;
5585 }
5586 if (dstidx != num)
f1f41a6c 5587 vec_safe_truncate (child_cfun->local_decls, dstidx);
1d22f541 5588
79acaae1 5589 /* Inform the callgraph about the new function. */
9918db44 5590 child_cfun->curr_properties = cfun->curr_properties;
5591 child_cfun->has_simduid_loops |= cfun->has_simduid_loops;
5592 child_cfun->has_force_vectorize_loops |= cfun->has_force_vectorize_loops;
47300487 5593 cgraph_node *node = cgraph_node::get_create (child_fn);
5594 node->parallelized_function = 1;
415d1b9a 5595 cgraph_node::add_new_function (child_fn, true);
79acaae1 5596
5597 /* Fix the callgraph edges for child_cfun. Those for cfun will be
5598 fixed in a following pass. */
5599 push_cfun (child_cfun);
658b4427 5600 if (optimize)
fd6481cf 5601 optimize_omp_library_calls (entry_stmt);
35ee1c66 5602 cgraph_edge::rebuild_edges ();
fbe86b1b 5603
5604 /* Some EH regions might become dead, see PR34608. If
5605 pass_cleanup_cfg isn't the first pass to happen with the
5606 new child, these dead EH edges might cause problems.
5607 Clean them up now. */
5608 if (flag_exceptions)
5609 {
5610 basic_block bb;
fbe86b1b 5611 bool changed = false;
5612
fc00614f 5613 FOR_EACH_BB_FN (bb, cfun)
75a70cf9 5614 changed |= gimple_purge_dead_eh_edges (bb);
fbe86b1b 5615 if (changed)
5616 cleanup_tree_cfg ();
fbe86b1b 5617 }
dd277d48 5618 if (gimple_in_ssa_p (cfun))
5619 update_ssa (TODO_update_ssa);
79acaae1 5620 pop_cfun ();
773c5ba7 5621 }
48e1416a 5622
773c5ba7 5623 /* Emit a library call to launch the children threads. */
40750995 5624 if (is_cilk_for)
1a91d914 5625 expand_cilk_for_call (new_bb,
5626 as_a <gomp_parallel *> (entry_stmt), ws_args);
40750995 5627 else if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
1a91d914 5628 expand_parallel_call (region, new_bb,
5629 as_a <gomp_parallel *> (entry_stmt), ws_args);
fd6481cf 5630 else
1a91d914 5631 expand_task_call (new_bb, as_a <gomp_task *> (entry_stmt));
083152fb 5632 if (gimple_in_ssa_p (cfun))
5633 update_ssa (TODO_update_ssa_only_virtuals);
1e8e9920 5634}
5635
773c5ba7 5636
3d483a94 5637/* Helper function for expand_omp_{for_*,simd}. If this is the outermost
5638 of the combined collapse > 1 loop constructs, generate code like:
5639 if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
5640 if (cond3 is <)
5641 adj = STEP3 - 1;
5642 else
5643 adj = STEP3 + 1;
5644 count3 = (adj + N32 - N31) / STEP3;
5645 if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
5646 if (cond2 is <)
5647 adj = STEP2 - 1;
5648 else
5649 adj = STEP2 + 1;
5650 count2 = (adj + N22 - N21) / STEP2;
5651 if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
5652 if (cond1 is <)
5653 adj = STEP1 - 1;
5654 else
5655 adj = STEP1 + 1;
5656 count1 = (adj + N12 - N11) / STEP1;
5657 count = count1 * count2 * count3;
5658 Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
5659 count = 0;
bc7bff74 5660 and set ZERO_ITER_BB to that bb. If this isn't the outermost
5661 of the combined loop constructs, just initialize COUNTS array
5662 from the _looptemp_ clauses. */
3d483a94 5663
5664/* NOTE: It *could* be better to moosh all of the BBs together,
5665 creating one larger BB with all the computation and the unexpected
5666 jump at the end. I.e.
5667
5668 bool zero3, zero2, zero1, zero;
5669
5670 zero3 = N32 c3 N31;
5671 count3 = (N32 - N31) /[cl] STEP3;
5672 zero2 = N22 c2 N21;
5673 count2 = (N22 - N21) /[cl] STEP2;
5674 zero1 = N12 c1 N11;
5675 count1 = (N12 - N11) /[cl] STEP1;
5676 zero = zero3 || zero2 || zero1;
5677 count = count1 * count2 * count3;
5678 if (__builtin_expect(zero, false)) goto zero_iter_bb;
5679
5680 After all, we expect the zero=false, and thus we expect to have to
5681 evaluate all of the comparison expressions, so short-circuiting
5682 oughtn't be a win. Since the condition isn't protecting a
5683 denominator, we're not concerned about divide-by-zero, so we can
5684 fully evaluate count even if a numerator turned out to be wrong.
5685
5686 It seems like putting this all together would create much better
5687 scheduling opportunities, and less pressure on the chip's branch
5688 predictor. */
5689
5690static void
5691expand_omp_for_init_counts (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
5692 basic_block &entry_bb, tree *counts,
5693 basic_block &zero_iter_bb, int &first_zero_iter,
5694 basic_block &l2_dom_bb)
5695{
5696 tree t, type = TREE_TYPE (fd->loop.v);
3d483a94 5697 edge e, ne;
5698 int i;
5699
5700 /* Collapsed loops need work for expansion into SSA form. */
5701 gcc_assert (!gimple_in_ssa_p (cfun));
5702
bc7bff74 5703 if (gimple_omp_for_combined_into_p (fd->for_stmt)
5704 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
5705 {
5706 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5707 isn't supposed to be handled, as the inner loop doesn't
5708 use it. */
5709 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
5710 OMP_CLAUSE__LOOPTEMP_);
5711 gcc_assert (innerc);
5712 for (i = 0; i < fd->collapse; i++)
5713 {
5714 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5715 OMP_CLAUSE__LOOPTEMP_);
5716 gcc_assert (innerc);
5717 if (i)
5718 counts[i] = OMP_CLAUSE_DECL (innerc);
5719 else
5720 counts[0] = NULL_TREE;
5721 }
5722 return;
5723 }
5724
3d483a94 5725 for (i = 0; i < fd->collapse; i++)
5726 {
5727 tree itype = TREE_TYPE (fd->loops[i].v);
5728
5729 if (SSA_VAR_P (fd->loop.n2)
5730 && ((t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
5731 fold_convert (itype, fd->loops[i].n1),
5732 fold_convert (itype, fd->loops[i].n2)))
5733 == NULL_TREE || !integer_onep (t)))
5734 {
1a91d914 5735 gcond *cond_stmt;
3d483a94 5736 tree n1, n2;
5737 n1 = fold_convert (itype, unshare_expr (fd->loops[i].n1));
5738 n1 = force_gimple_operand_gsi (gsi, n1, true, NULL_TREE,
5739 true, GSI_SAME_STMT);
5740 n2 = fold_convert (itype, unshare_expr (fd->loops[i].n2));
5741 n2 = force_gimple_operand_gsi (gsi, n2, true, NULL_TREE,
5742 true, GSI_SAME_STMT);
1a91d914 5743 cond_stmt = gimple_build_cond (fd->loops[i].cond_code, n1, n2,
5744 NULL_TREE, NULL_TREE);
5745 gsi_insert_before (gsi, cond_stmt, GSI_SAME_STMT);
5746 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
3d483a94 5747 expand_omp_regimplify_p, NULL, NULL)
1a91d914 5748 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
3d483a94 5749 expand_omp_regimplify_p, NULL, NULL))
5750 {
1a91d914 5751 *gsi = gsi_for_stmt (cond_stmt);
5752 gimple_regimplify_operands (cond_stmt, gsi);
3d483a94 5753 }
1a91d914 5754 e = split_block (entry_bb, cond_stmt);
3d483a94 5755 if (zero_iter_bb == NULL)
5756 {
1a91d914 5757 gassign *assign_stmt;
3d483a94 5758 first_zero_iter = i;
5759 zero_iter_bb = create_empty_bb (entry_bb);
b3083327 5760 add_bb_to_loop (zero_iter_bb, entry_bb->loop_father);
3d483a94 5761 *gsi = gsi_after_labels (zero_iter_bb);
1a91d914 5762 assign_stmt = gimple_build_assign (fd->loop.n2,
5763 build_zero_cst (type));
5764 gsi_insert_before (gsi, assign_stmt, GSI_SAME_STMT);
3d483a94 5765 set_immediate_dominator (CDI_DOMINATORS, zero_iter_bb,
5766 entry_bb);
5767 }
5768 ne = make_edge (entry_bb, zero_iter_bb, EDGE_FALSE_VALUE);
5769 ne->probability = REG_BR_PROB_BASE / 2000 - 1;
5770 e->flags = EDGE_TRUE_VALUE;
5771 e->probability = REG_BR_PROB_BASE - ne->probability;
5772 if (l2_dom_bb == NULL)
5773 l2_dom_bb = entry_bb;
5774 entry_bb = e->dest;
5775 *gsi = gsi_last_bb (entry_bb);
5776 }
5777
5778 if (POINTER_TYPE_P (itype))
5779 itype = signed_type_for (itype);
5780 t = build_int_cst (itype, (fd->loops[i].cond_code == LT_EXPR
5781 ? -1 : 1));
5782 t = fold_build2 (PLUS_EXPR, itype,
5783 fold_convert (itype, fd->loops[i].step), t);
5784 t = fold_build2 (PLUS_EXPR, itype, t,
5785 fold_convert (itype, fd->loops[i].n2));
5786 t = fold_build2 (MINUS_EXPR, itype, t,
5787 fold_convert (itype, fd->loops[i].n1));
5788 /* ?? We could probably use CEIL_DIV_EXPR instead of
5789 TRUNC_DIV_EXPR and adjusting by hand. Unless we can't
5790 generate the same code in the end because generically we
5791 don't know that the values involved must be negative for
5792 GT?? */
5793 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
5794 t = fold_build2 (TRUNC_DIV_EXPR, itype,
5795 fold_build1 (NEGATE_EXPR, itype, t),
5796 fold_build1 (NEGATE_EXPR, itype,
5797 fold_convert (itype,
5798 fd->loops[i].step)));
5799 else
5800 t = fold_build2 (TRUNC_DIV_EXPR, itype, t,
5801 fold_convert (itype, fd->loops[i].step));
5802 t = fold_convert (type, t);
5803 if (TREE_CODE (t) == INTEGER_CST)
5804 counts[i] = t;
5805 else
5806 {
5807 counts[i] = create_tmp_reg (type, ".count");
5808 expand_omp_build_assign (gsi, counts[i], t);
5809 }
5810 if (SSA_VAR_P (fd->loop.n2))
5811 {
5812 if (i == 0)
5813 t = counts[0];
5814 else
5815 t = fold_build2 (MULT_EXPR, type, fd->loop.n2, counts[i]);
5816 expand_omp_build_assign (gsi, fd->loop.n2, t);
5817 }
5818 }
5819}
5820
5821
5822/* Helper function for expand_omp_{for_*,simd}. Generate code like:
5823 T = V;
5824 V3 = N31 + (T % count3) * STEP3;
5825 T = T / count3;
5826 V2 = N21 + (T % count2) * STEP2;
5827 T = T / count2;
5828 V1 = N11 + T * STEP1;
bc7bff74 5829 if this loop doesn't have an inner loop construct combined with it.
5830 If it does have an inner loop construct combined with it and the
5831 iteration count isn't known constant, store values from counts array
5832 into its _looptemp_ temporaries instead. */
3d483a94 5833
5834static void
5835expand_omp_for_init_vars (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
bc7bff74 5836 tree *counts, gimple inner_stmt, tree startvar)
3d483a94 5837{
5838 int i;
bc7bff74 5839 if (gimple_omp_for_combined_p (fd->for_stmt))
5840 {
5841 /* If fd->loop.n2 is constant, then no propagation of the counts
5842 is needed, they are constant. */
5843 if (TREE_CODE (fd->loop.n2) == INTEGER_CST)
5844 return;
5845
5846 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
5847 ? gimple_omp_parallel_clauses (inner_stmt)
5848 : gimple_omp_for_clauses (inner_stmt);
5849 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5850 isn't supposed to be handled, as the inner loop doesn't
5851 use it. */
5852 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
5853 gcc_assert (innerc);
5854 for (i = 0; i < fd->collapse; i++)
5855 {
5856 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5857 OMP_CLAUSE__LOOPTEMP_);
5858 gcc_assert (innerc);
5859 if (i)
5860 {
5861 tree tem = OMP_CLAUSE_DECL (innerc);
5862 tree t = fold_convert (TREE_TYPE (tem), counts[i]);
5863 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5864 false, GSI_CONTINUE_LINKING);
1a91d914 5865 gassign *stmt = gimple_build_assign (tem, t);
bc7bff74 5866 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5867 }
5868 }
5869 return;
5870 }
5871
3d483a94 5872 tree type = TREE_TYPE (fd->loop.v);
5873 tree tem = create_tmp_reg (type, ".tem");
1a91d914 5874 gassign *stmt = gimple_build_assign (tem, startvar);
3d483a94 5875 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5876
5877 for (i = fd->collapse - 1; i >= 0; i--)
5878 {
5879 tree vtype = TREE_TYPE (fd->loops[i].v), itype, t;
5880 itype = vtype;
5881 if (POINTER_TYPE_P (vtype))
5882 itype = signed_type_for (vtype);
5883 if (i != 0)
5884 t = fold_build2 (TRUNC_MOD_EXPR, type, tem, counts[i]);
5885 else
5886 t = tem;
5887 t = fold_convert (itype, t);
5888 t = fold_build2 (MULT_EXPR, itype, t,
5889 fold_convert (itype, fd->loops[i].step));
5890 if (POINTER_TYPE_P (vtype))
5891 t = fold_build_pointer_plus (fd->loops[i].n1, t);
5892 else
5893 t = fold_build2 (PLUS_EXPR, itype, fd->loops[i].n1, t);
5894 t = force_gimple_operand_gsi (gsi, t,
5895 DECL_P (fd->loops[i].v)
5896 && TREE_ADDRESSABLE (fd->loops[i].v),
5897 NULL_TREE, false,
5898 GSI_CONTINUE_LINKING);
5899 stmt = gimple_build_assign (fd->loops[i].v, t);
5900 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5901 if (i != 0)
5902 {
5903 t = fold_build2 (TRUNC_DIV_EXPR, type, tem, counts[i]);
5904 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5905 false, GSI_CONTINUE_LINKING);
5906 stmt = gimple_build_assign (tem, t);
5907 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5908 }
5909 }
5910}
5911
5912
5913/* Helper function for expand_omp_for_*. Generate code like:
5914 L10:
5915 V3 += STEP3;
5916 if (V3 cond3 N32) goto BODY_BB; else goto L11;
5917 L11:
5918 V3 = N31;
5919 V2 += STEP2;
5920 if (V2 cond2 N22) goto BODY_BB; else goto L12;
5921 L12:
5922 V2 = N21;
5923 V1 += STEP1;
5924 goto BODY_BB; */
5925
5926static basic_block
5927extract_omp_for_update_vars (struct omp_for_data *fd, basic_block cont_bb,
5928 basic_block body_bb)
5929{
5930 basic_block last_bb, bb, collapse_bb = NULL;
5931 int i;
5932 gimple_stmt_iterator gsi;
5933 edge e;
5934 tree t;
5935 gimple stmt;
5936
5937 last_bb = cont_bb;
5938 for (i = fd->collapse - 1; i >= 0; i--)
5939 {
5940 tree vtype = TREE_TYPE (fd->loops[i].v);
5941
5942 bb = create_empty_bb (last_bb);
b3083327 5943 add_bb_to_loop (bb, last_bb->loop_father);
3d483a94 5944 gsi = gsi_start_bb (bb);
5945
5946 if (i < fd->collapse - 1)
5947 {
5948 e = make_edge (last_bb, bb, EDGE_FALSE_VALUE);
5949 e->probability = REG_BR_PROB_BASE / 8;
5950
5951 t = fd->loops[i + 1].n1;
5952 t = force_gimple_operand_gsi (&gsi, t,
5953 DECL_P (fd->loops[i + 1].v)
5954 && TREE_ADDRESSABLE (fd->loops[i
5955 + 1].v),
5956 NULL_TREE, false,
5957 GSI_CONTINUE_LINKING);
5958 stmt = gimple_build_assign (fd->loops[i + 1].v, t);
5959 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5960 }
5961 else
5962 collapse_bb = bb;
5963
5964 set_immediate_dominator (CDI_DOMINATORS, bb, last_bb);
5965
5966 if (POINTER_TYPE_P (vtype))
5967 t = fold_build_pointer_plus (fd->loops[i].v, fd->loops[i].step);
5968 else
5969 t = fold_build2 (PLUS_EXPR, vtype, fd->loops[i].v, fd->loops[i].step);
5970 t = force_gimple_operand_gsi (&gsi, t,
5971 DECL_P (fd->loops[i].v)
5972 && TREE_ADDRESSABLE (fd->loops[i].v),
5973 NULL_TREE, false, GSI_CONTINUE_LINKING);
5974 stmt = gimple_build_assign (fd->loops[i].v, t);
5975 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5976
5977 if (i > 0)
5978 {
5979 t = fd->loops[i].n2;
5980 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5981 false, GSI_CONTINUE_LINKING);
5982 tree v = fd->loops[i].v;
5983 if (DECL_P (v) && TREE_ADDRESSABLE (v))
5984 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
5985 false, GSI_CONTINUE_LINKING);
5986 t = fold_build2 (fd->loops[i].cond_code, boolean_type_node, v, t);
5987 stmt = gimple_build_cond_empty (t);
5988 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5989 e = make_edge (bb, body_bb, EDGE_TRUE_VALUE);
5990 e->probability = REG_BR_PROB_BASE * 7 / 8;
5991 }
5992 else
5993 make_edge (bb, body_bb, EDGE_FALLTHRU);
5994 last_bb = bb;
5995 }
5996
5997 return collapse_bb;
5998}
5999
6000
773c5ba7 6001/* A subroutine of expand_omp_for. Generate code for a parallel
1e8e9920 6002 loop with any schedule. Given parameters:
6003
6004 for (V = N1; V cond N2; V += STEP) BODY;
6005
6006 where COND is "<" or ">", we generate pseudocode
6007
6008 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
773c5ba7 6009 if (more) goto L0; else goto L3;
1e8e9920 6010 L0:
6011 V = istart0;
6012 iend = iend0;
6013 L1:
6014 BODY;
6015 V += STEP;
773c5ba7 6016 if (V cond iend) goto L1; else goto L2;
1e8e9920 6017 L2:
773c5ba7 6018 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
6019 L3:
1e8e9920 6020
773c5ba7 6021 If this is a combined omp parallel loop, instead of the call to
fd6481cf 6022 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
bc7bff74 6023 If this is gimple_omp_for_combined_p loop, then instead of assigning
6024 V and iend in L0 we assign the first two _looptemp_ clause decls of the
6025 inner GIMPLE_OMP_FOR and V += STEP; and
6026 if (V cond iend) goto L1; else goto L2; are removed.
fd6481cf 6027
6028 For collapsed loops, given parameters:
6029 collapse(3)
6030 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
6031 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
6032 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
6033 BODY;
6034
6035 we generate pseudocode
6036
8e6b4515 6037 if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
fd6481cf 6038 if (cond3 is <)
6039 adj = STEP3 - 1;
6040 else
6041 adj = STEP3 + 1;
6042 count3 = (adj + N32 - N31) / STEP3;
8e6b4515 6043 if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
fd6481cf 6044 if (cond2 is <)
6045 adj = STEP2 - 1;
6046 else
6047 adj = STEP2 + 1;
6048 count2 = (adj + N22 - N21) / STEP2;
8e6b4515 6049 if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
fd6481cf 6050 if (cond1 is <)
6051 adj = STEP1 - 1;
6052 else
6053 adj = STEP1 + 1;
6054 count1 = (adj + N12 - N11) / STEP1;
6055 count = count1 * count2 * count3;
8e6b4515 6056 goto Z1;
6057 Z0:
6058 count = 0;
6059 Z1:
fd6481cf 6060 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
6061 if (more) goto L0; else goto L3;
6062 L0:
6063 V = istart0;
6064 T = V;
6065 V3 = N31 + (T % count3) * STEP3;
6066 T = T / count3;
6067 V2 = N21 + (T % count2) * STEP2;
6068 T = T / count2;
6069 V1 = N11 + T * STEP1;
6070 iend = iend0;
6071 L1:
6072 BODY;
6073 V += 1;
6074 if (V < iend) goto L10; else goto L2;
6075 L10:
6076 V3 += STEP3;
6077 if (V3 cond3 N32) goto L1; else goto L11;
6078 L11:
6079 V3 = N31;
6080 V2 += STEP2;
6081 if (V2 cond2 N22) goto L1; else goto L12;
6082 L12:
6083 V2 = N21;
6084 V1 += STEP1;
6085 goto L1;
6086 L2:
6087 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
6088 L3:
6089
6090 */
1e8e9920 6091
61e47ac8 6092static void
773c5ba7 6093expand_omp_for_generic (struct omp_region *region,
6094 struct omp_for_data *fd,
1e8e9920 6095 enum built_in_function start_fn,
bc7bff74 6096 enum built_in_function next_fn,
6097 gimple inner_stmt)
1e8e9920 6098{
75a70cf9 6099 tree type, istart0, iend0, iend;
fd6481cf 6100 tree t, vmain, vback, bias = NULL_TREE;
6101 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, collapse_bb;
03ed154b 6102 basic_block l2_bb = NULL, l3_bb = NULL;
75a70cf9 6103 gimple_stmt_iterator gsi;
1a91d914 6104 gassign *assign_stmt;
773c5ba7 6105 bool in_combined_parallel = is_combined_parallel (region);
ac6e3339 6106 bool broken_loop = region->cont == NULL;
79acaae1 6107 edge e, ne;
fd6481cf 6108 tree *counts = NULL;
6109 int i;
ac6e3339 6110
6111 gcc_assert (!broken_loop || !in_combined_parallel);
fd6481cf 6112 gcc_assert (fd->iter_type == long_integer_type_node
6113 || !in_combined_parallel);
1e8e9920 6114
fd6481cf 6115 type = TREE_TYPE (fd->loop.v);
6116 istart0 = create_tmp_var (fd->iter_type, ".istart0");
6117 iend0 = create_tmp_var (fd->iter_type, ".iend0");
6d63fc03 6118 TREE_ADDRESSABLE (istart0) = 1;
6119 TREE_ADDRESSABLE (iend0) = 1;
1e8e9920 6120
fd6481cf 6121 /* See if we need to bias by LLONG_MIN. */
6122 if (fd->iter_type == long_long_unsigned_type_node
6123 && TREE_CODE (type) == INTEGER_TYPE
6124 && !TYPE_UNSIGNED (type))
6125 {
6126 tree n1, n2;
6127
6128 if (fd->loop.cond_code == LT_EXPR)
6129 {
6130 n1 = fd->loop.n1;
6131 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
6132 }
6133 else
6134 {
6135 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
6136 n2 = fd->loop.n1;
6137 }
6138 if (TREE_CODE (n1) != INTEGER_CST
6139 || TREE_CODE (n2) != INTEGER_CST
6140 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
6141 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
6142 }
6143
61e47ac8 6144 entry_bb = region->entry;
03ed154b 6145 cont_bb = region->cont;
fd6481cf 6146 collapse_bb = NULL;
ac6e3339 6147 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
6148 gcc_assert (broken_loop
6149 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
6150 l0_bb = split_edge (FALLTHRU_EDGE (entry_bb));
6151 l1_bb = single_succ (l0_bb);
6152 if (!broken_loop)
03ed154b 6153 {
6154 l2_bb = create_empty_bb (cont_bb);
ac6e3339 6155 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb);
6156 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
03ed154b 6157 }
ac6e3339 6158 else
6159 l2_bb = NULL;
6160 l3_bb = BRANCH_EDGE (entry_bb)->dest;
6161 exit_bb = region->exit;
773c5ba7 6162
75a70cf9 6163 gsi = gsi_last_bb (entry_bb);
fd6481cf 6164
75a70cf9 6165 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
fd6481cf 6166 if (fd->collapse > 1)
6167 {
8e6b4515 6168 int first_zero_iter = -1;
3d483a94 6169 basic_block zero_iter_bb = NULL, l2_dom_bb = NULL;
8e6b4515 6170
3d483a94 6171 counts = XALLOCAVEC (tree, fd->collapse);
6172 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6173 zero_iter_bb, first_zero_iter,
6174 l2_dom_bb);
fd6481cf 6175
8e6b4515 6176 if (zero_iter_bb)
6177 {
6178 /* Some counts[i] vars might be uninitialized if
6179 some loop has zero iterations. But the body shouldn't
6180 be executed in that case, so just avoid uninit warnings. */
6181 for (i = first_zero_iter; i < fd->collapse; i++)
6182 if (SSA_VAR_P (counts[i]))
6183 TREE_NO_WARNING (counts[i]) = 1;
6184 gsi_prev (&gsi);
6185 e = split_block (entry_bb, gsi_stmt (gsi));
6186 entry_bb = e->dest;
6187 make_edge (zero_iter_bb, entry_bb, EDGE_FALLTHRU);
6188 gsi = gsi_last_bb (entry_bb);
6189 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
6190 get_immediate_dominator (CDI_DOMINATORS,
6191 zero_iter_bb));
6192 }
fd6481cf 6193 }
79acaae1 6194 if (in_combined_parallel)
6195 {
6196 /* In a combined parallel loop, emit a call to
6197 GOMP_loop_foo_next. */
b9a16870 6198 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
79acaae1 6199 build_fold_addr_expr (istart0),
6200 build_fold_addr_expr (iend0));
6201 }
6202 else
1e8e9920 6203 {
c2f47e15 6204 tree t0, t1, t2, t3, t4;
773c5ba7 6205 /* If this is not a combined parallel loop, emit a call to
6206 GOMP_loop_foo_start in ENTRY_BB. */
c2f47e15 6207 t4 = build_fold_addr_expr (iend0);
6208 t3 = build_fold_addr_expr (istart0);
fd6481cf 6209 t2 = fold_convert (fd->iter_type, fd->loop.step);
3d483a94 6210 t1 = fd->loop.n2;
6211 t0 = fd->loop.n1;
bc7bff74 6212 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6213 {
6214 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6215 OMP_CLAUSE__LOOPTEMP_);
6216 gcc_assert (innerc);
6217 t0 = OMP_CLAUSE_DECL (innerc);
6218 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6219 OMP_CLAUSE__LOOPTEMP_);
6220 gcc_assert (innerc);
6221 t1 = OMP_CLAUSE_DECL (innerc);
6222 }
3d483a94 6223 if (POINTER_TYPE_P (TREE_TYPE (t0))
6224 && TYPE_PRECISION (TREE_TYPE (t0))
6225 != TYPE_PRECISION (fd->iter_type))
c799f233 6226 {
6227 /* Avoid casting pointers to integer of a different size. */
3cea8318 6228 tree itype = signed_type_for (type);
3d483a94 6229 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
6230 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
c799f233 6231 }
6232 else
6233 {
3d483a94 6234 t1 = fold_convert (fd->iter_type, t1);
6235 t0 = fold_convert (fd->iter_type, t0);
c799f233 6236 }
fd6481cf 6237 if (bias)
1e8e9920 6238 {
fd6481cf 6239 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
6240 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
6241 }
6242 if (fd->iter_type == long_integer_type_node)
6243 {
6244 if (fd->chunk_size)
6245 {
6246 t = fold_convert (fd->iter_type, fd->chunk_size);
b9a16870 6247 t = build_call_expr (builtin_decl_explicit (start_fn),
6248 6, t0, t1, t2, t, t3, t4);
fd6481cf 6249 }
6250 else
b9a16870 6251 t = build_call_expr (builtin_decl_explicit (start_fn),
6252 5, t0, t1, t2, t3, t4);
1e8e9920 6253 }
c2f47e15 6254 else
fd6481cf 6255 {
6256 tree t5;
6257 tree c_bool_type;
b9a16870 6258 tree bfn_decl;
fd6481cf 6259
6260 /* The GOMP_loop_ull_*start functions have additional boolean
6261 argument, true for < loops and false for > loops.
6262 In Fortran, the C bool type can be different from
6263 boolean_type_node. */
b9a16870 6264 bfn_decl = builtin_decl_explicit (start_fn);
6265 c_bool_type = TREE_TYPE (TREE_TYPE (bfn_decl));
fd6481cf 6266 t5 = build_int_cst (c_bool_type,
6267 fd->loop.cond_code == LT_EXPR ? 1 : 0);
6268 if (fd->chunk_size)
6269 {
b9a16870 6270 tree bfn_decl = builtin_decl_explicit (start_fn);
fd6481cf 6271 t = fold_convert (fd->iter_type, fd->chunk_size);
b9a16870 6272 t = build_call_expr (bfn_decl, 7, t5, t0, t1, t2, t, t3, t4);
fd6481cf 6273 }
6274 else
b9a16870 6275 t = build_call_expr (builtin_decl_explicit (start_fn),
6276 6, t5, t0, t1, t2, t3, t4);
fd6481cf 6277 }
1e8e9920 6278 }
fd6481cf 6279 if (TREE_TYPE (t) != boolean_type_node)
6280 t = fold_build2 (NE_EXPR, boolean_type_node,
6281 t, build_int_cst (TREE_TYPE (t), 0));
75a70cf9 6282 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6283 true, GSI_SAME_STMT);
6284 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
79acaae1 6285
75a70cf9 6286 /* Remove the GIMPLE_OMP_FOR statement. */
6287 gsi_remove (&gsi, true);
1e8e9920 6288
773c5ba7 6289 /* Iteration setup for sequential loop goes in L0_BB. */
3d483a94 6290 tree startvar = fd->loop.v;
6291 tree endvar = NULL_TREE;
6292
bc7bff74 6293 if (gimple_omp_for_combined_p (fd->for_stmt))
6294 {
6295 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_FOR
6296 && gimple_omp_for_kind (inner_stmt)
6297 == GF_OMP_FOR_KIND_SIMD);
6298 tree innerc = find_omp_clause (gimple_omp_for_clauses (inner_stmt),
6299 OMP_CLAUSE__LOOPTEMP_);
6300 gcc_assert (innerc);
6301 startvar = OMP_CLAUSE_DECL (innerc);
6302 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6303 OMP_CLAUSE__LOOPTEMP_);
6304 gcc_assert (innerc);
6305 endvar = OMP_CLAUSE_DECL (innerc);
6306 }
6307
75a70cf9 6308 gsi = gsi_start_bb (l0_bb);
1efcacec 6309 t = istart0;
fd6481cf 6310 if (bias)
1efcacec 6311 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
3d483a94 6312 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
6313 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
6314 t = fold_convert (TREE_TYPE (startvar), t);
4abecb72 6315 t = force_gimple_operand_gsi (&gsi, t,
3d483a94 6316 DECL_P (startvar)
6317 && TREE_ADDRESSABLE (startvar),
4abecb72 6318 NULL_TREE, false, GSI_CONTINUE_LINKING);
1a91d914 6319 assign_stmt = gimple_build_assign (startvar, t);
6320 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
1e8e9920 6321
1efcacec 6322 t = iend0;
fd6481cf 6323 if (bias)
1efcacec 6324 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
3d483a94 6325 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
6326 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
6327 t = fold_convert (TREE_TYPE (startvar), t);
75a70cf9 6328 iend = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6329 false, GSI_CONTINUE_LINKING);
3d483a94 6330 if (endvar)
fd6481cf 6331 {
1a91d914 6332 assign_stmt = gimple_build_assign (endvar, iend);
6333 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
d44f2f7c 6334 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (iend)))
1a91d914 6335 assign_stmt = gimple_build_assign (fd->loop.v, iend);
d44f2f7c 6336 else
e9cf809e 6337 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, iend);
1a91d914 6338 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
fd6481cf 6339 }
3d483a94 6340 if (fd->collapse > 1)
bc7bff74 6341 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
773c5ba7 6342
ac6e3339 6343 if (!broken_loop)
03ed154b 6344 {
ac6e3339 6345 /* Code to control the increment and predicate for the sequential
6346 loop goes in the CONT_BB. */
75a70cf9 6347 gsi = gsi_last_bb (cont_bb);
1a91d914 6348 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
6349 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
6350 vmain = gimple_omp_continue_control_use (cont_stmt);
6351 vback = gimple_omp_continue_control_def (cont_stmt);
79acaae1 6352
bc7bff74 6353 if (!gimple_omp_for_combined_p (fd->for_stmt))
3d483a94 6354 {
6355 if (POINTER_TYPE_P (type))
6356 t = fold_build_pointer_plus (vmain, fd->loop.step);
6357 else
6358 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
6359 t = force_gimple_operand_gsi (&gsi, t,
6360 DECL_P (vback)
6361 && TREE_ADDRESSABLE (vback),
6362 NULL_TREE, true, GSI_SAME_STMT);
1a91d914 6363 assign_stmt = gimple_build_assign (vback, t);
6364 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
3d483a94 6365
6366 t = build2 (fd->loop.cond_code, boolean_type_node,
6367 DECL_P (vback) && TREE_ADDRESSABLE (vback) ? t : vback,
6368 iend);
1a91d914 6369 gcond *cond_stmt = gimple_build_cond_empty (t);
6370 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
3d483a94 6371 }
773c5ba7 6372
75a70cf9 6373 /* Remove GIMPLE_OMP_CONTINUE. */
6374 gsi_remove (&gsi, true);
773c5ba7 6375
bc7bff74 6376 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
3d483a94 6377 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, l1_bb);
fd6481cf 6378
ac6e3339 6379 /* Emit code to get the next parallel iteration in L2_BB. */
75a70cf9 6380 gsi = gsi_start_bb (l2_bb);
773c5ba7 6381
b9a16870 6382 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
ac6e3339 6383 build_fold_addr_expr (istart0),
6384 build_fold_addr_expr (iend0));
75a70cf9 6385 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6386 false, GSI_CONTINUE_LINKING);
fd6481cf 6387 if (TREE_TYPE (t) != boolean_type_node)
6388 t = fold_build2 (NE_EXPR, boolean_type_node,
6389 t, build_int_cst (TREE_TYPE (t), 0));
1a91d914 6390 gcond *cond_stmt = gimple_build_cond_empty (t);
6391 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
ac6e3339 6392 }
1e8e9920 6393
61e47ac8 6394 /* Add the loop cleanup function. */
75a70cf9 6395 gsi = gsi_last_bb (exit_bb);
6396 if (gimple_omp_return_nowait_p (gsi_stmt (gsi)))
b9a16870 6397 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
bc7bff74 6398 else if (gimple_omp_return_lhs (gsi_stmt (gsi)))
6399 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL);
61e47ac8 6400 else
b9a16870 6401 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END);
1a91d914 6402 gcall *call_stmt = gimple_build_call (t, 0);
bc7bff74 6403 if (gimple_omp_return_lhs (gsi_stmt (gsi)))
1a91d914 6404 gimple_call_set_lhs (call_stmt, gimple_omp_return_lhs (gsi_stmt (gsi)));
6405 gsi_insert_after (&gsi, call_stmt, GSI_SAME_STMT);
75a70cf9 6406 gsi_remove (&gsi, true);
773c5ba7 6407
6408 /* Connect the new blocks. */
79acaae1 6409 find_edge (entry_bb, l0_bb)->flags = EDGE_TRUE_VALUE;
6410 find_edge (entry_bb, l3_bb)->flags = EDGE_FALSE_VALUE;
1e8e9920 6411
ac6e3339 6412 if (!broken_loop)
6413 {
75a70cf9 6414 gimple_seq phis;
6415
79acaae1 6416 e = find_edge (cont_bb, l3_bb);
6417 ne = make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
6418
75a70cf9 6419 phis = phi_nodes (l3_bb);
6420 for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi))
6421 {
6422 gimple phi = gsi_stmt (gsi);
6423 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, ne),
6424 PHI_ARG_DEF_FROM_EDGE (phi, e));
6425 }
79acaae1 6426 remove_edge (e);
6427
ac6e3339 6428 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
b3083327 6429 add_bb_to_loop (l2_bb, cont_bb->loop_father);
3d483a94 6430 e = find_edge (cont_bb, l1_bb);
bc7bff74 6431 if (gimple_omp_for_combined_p (fd->for_stmt))
6432 {
6433 remove_edge (e);
6434 e = NULL;
6435 }
3d483a94 6436 else if (fd->collapse > 1)
fd6481cf 6437 {
fd6481cf 6438 remove_edge (e);
6439 e = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6440 }
6441 else
3d483a94 6442 e->flags = EDGE_TRUE_VALUE;
6443 if (e)
fd6481cf 6444 {
3d483a94 6445 e->probability = REG_BR_PROB_BASE * 7 / 8;
6446 find_edge (cont_bb, l2_bb)->probability = REG_BR_PROB_BASE / 8;
6447 }
6448 else
6449 {
6450 e = find_edge (cont_bb, l2_bb);
6451 e->flags = EDGE_FALLTHRU;
fd6481cf 6452 }
ac6e3339 6453 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
79acaae1 6454
6455 set_immediate_dominator (CDI_DOMINATORS, l2_bb,
6456 recompute_dominator (CDI_DOMINATORS, l2_bb));
6457 set_immediate_dominator (CDI_DOMINATORS, l3_bb,
6458 recompute_dominator (CDI_DOMINATORS, l3_bb));
6459 set_immediate_dominator (CDI_DOMINATORS, l0_bb,
6460 recompute_dominator (CDI_DOMINATORS, l0_bb));
6461 set_immediate_dominator (CDI_DOMINATORS, l1_bb,
6462 recompute_dominator (CDI_DOMINATORS, l1_bb));
04c2922b 6463
6464 struct loop *outer_loop = alloc_loop ();
6465 outer_loop->header = l0_bb;
6466 outer_loop->latch = l2_bb;
6467 add_loop (outer_loop, l0_bb->loop_father);
6468
bc7bff74 6469 if (!gimple_omp_for_combined_p (fd->for_stmt))
3d483a94 6470 {
6471 struct loop *loop = alloc_loop ();
6472 loop->header = l1_bb;
6473 /* The loop may have multiple latches. */
6474 add_loop (loop, outer_loop);
6475 }
ac6e3339 6476 }
1e8e9920 6477}
6478
6479
773c5ba7 6480/* A subroutine of expand_omp_for. Generate code for a parallel
6481 loop with static schedule and no specified chunk size. Given
6482 parameters:
1e8e9920 6483
6484 for (V = N1; V cond N2; V += STEP) BODY;
6485
6486 where COND is "<" or ">", we generate pseudocode
6487
8e6b4515 6488 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
1e8e9920 6489 if (cond is <)
6490 adj = STEP - 1;
6491 else
6492 adj = STEP + 1;
fd6481cf 6493 if ((__typeof (V)) -1 > 0 && cond is >)
6494 n = -(adj + N2 - N1) / -STEP;
6495 else
6496 n = (adj + N2 - N1) / STEP;
1e8e9920 6497 q = n / nthreads;
31712e83 6498 tt = n % nthreads;
6499 if (threadid < tt) goto L3; else goto L4;
6500 L3:
6501 tt = 0;
6502 q = q + 1;
6503 L4:
6504 s0 = q * threadid + tt;
6505 e0 = s0 + q;
79acaae1 6506 V = s0 * STEP + N1;
1e8e9920 6507 if (s0 >= e0) goto L2; else goto L0;
6508 L0:
1e8e9920 6509 e = e0 * STEP + N1;
6510 L1:
6511 BODY;
6512 V += STEP;
6513 if (V cond e) goto L1;
1e8e9920 6514 L2:
6515*/
6516
61e47ac8 6517static void
773c5ba7 6518expand_omp_for_static_nochunk (struct omp_region *region,
bc7bff74 6519 struct omp_for_data *fd,
6520 gimple inner_stmt)
1e8e9920 6521{
31712e83 6522 tree n, q, s0, e0, e, t, tt, nthreads, threadid;
fd6481cf 6523 tree type, itype, vmain, vback;
31712e83 6524 basic_block entry_bb, second_bb, third_bb, exit_bb, seq_start_bb;
bc7bff74 6525 basic_block body_bb, cont_bb, collapse_bb = NULL;
61e47ac8 6526 basic_block fin_bb;
75a70cf9 6527 gimple_stmt_iterator gsi;
31712e83 6528 edge ep;
bc7bff74 6529 bool broken_loop = region->cont == NULL;
6530 tree *counts = NULL;
6531 tree n1, n2, step;
1e8e9920 6532
ca4c3545 6533 gcc_checking_assert ((gimple_omp_for_kind (fd->for_stmt)
6534 != GF_OMP_FOR_KIND_OACC_LOOP)
6535 || !inner_stmt);
6536
fd6481cf 6537 itype = type = TREE_TYPE (fd->loop.v);
6538 if (POINTER_TYPE_P (type))
3cea8318 6539 itype = signed_type_for (type);
1e8e9920 6540
61e47ac8 6541 entry_bb = region->entry;
61e47ac8 6542 cont_bb = region->cont;
ac6e3339 6543 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
bc7bff74 6544 fin_bb = BRANCH_EDGE (entry_bb)->dest;
6545 gcc_assert (broken_loop
6546 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
ac6e3339 6547 seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb));
6548 body_bb = single_succ (seq_start_bb);
bc7bff74 6549 if (!broken_loop)
6550 {
6551 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
6552 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6553 }
61e47ac8 6554 exit_bb = region->exit;
6555
773c5ba7 6556 /* Iteration space partitioning goes in ENTRY_BB. */
75a70cf9 6557 gsi = gsi_last_bb (entry_bb);
6558 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
61e47ac8 6559
bc7bff74 6560 if (fd->collapse > 1)
6561 {
6562 int first_zero_iter = -1;
6563 basic_block l2_dom_bb = NULL;
6564
6565 counts = XALLOCAVEC (tree, fd->collapse);
6566 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6567 fin_bb, first_zero_iter,
6568 l2_dom_bb);
6569 t = NULL_TREE;
6570 }
6571 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
6572 t = integer_one_node;
6573 else
6574 t = fold_binary (fd->loop.cond_code, boolean_type_node,
6575 fold_convert (type, fd->loop.n1),
6576 fold_convert (type, fd->loop.n2));
6577 if (fd->collapse == 1
6578 && TYPE_UNSIGNED (type)
8e6b4515 6579 && (t == NULL_TREE || !integer_onep (t)))
6580 {
8e6b4515 6581 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
6582 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
6583 true, GSI_SAME_STMT);
6584 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
6585 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
6586 true, GSI_SAME_STMT);
1a91d914 6587 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
6588 NULL_TREE, NULL_TREE);
6589 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
6590 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
8e6b4515 6591 expand_omp_regimplify_p, NULL, NULL)
1a91d914 6592 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
8e6b4515 6593 expand_omp_regimplify_p, NULL, NULL))
6594 {
1a91d914 6595 gsi = gsi_for_stmt (cond_stmt);
6596 gimple_regimplify_operands (cond_stmt, &gsi);
8e6b4515 6597 }
1a91d914 6598 ep = split_block (entry_bb, cond_stmt);
8e6b4515 6599 ep->flags = EDGE_TRUE_VALUE;
6600 entry_bb = ep->dest;
6601 ep->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
6602 ep = make_edge (ep->src, fin_bb, EDGE_FALSE_VALUE);
6603 ep->probability = REG_BR_PROB_BASE / 2000 - 1;
6604 if (gimple_in_ssa_p (cfun))
6605 {
6606 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
1a91d914 6607 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
6608 !gsi_end_p (gpi); gsi_next (&gpi))
8e6b4515 6609 {
1a91d914 6610 gphi *phi = gpi.phi ();
8e6b4515 6611 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
6612 ep, UNKNOWN_LOCATION);
6613 }
6614 }
6615 gsi = gsi_last_bb (entry_bb);
6616 }
6617
ca4c3545 6618 switch (gimple_omp_for_kind (fd->for_stmt))
6619 {
6620 case GF_OMP_FOR_KIND_FOR:
6621 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
6622 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
6623 break;
6624 case GF_OMP_FOR_KIND_DISTRIBUTE:
6625 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
6626 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
6627 break;
6628 case GF_OMP_FOR_KIND_OACC_LOOP:
6629 nthreads = builtin_decl_explicit (BUILT_IN_GOACC_GET_NUM_THREADS);
6630 threadid = builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM);
6631 break;
6632 default:
6633 gcc_unreachable ();
6634 }
6635 nthreads = build_call_expr (nthreads, 0);
6636 nthreads = fold_convert (itype, nthreads);
6637 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
75a70cf9 6638 true, GSI_SAME_STMT);
ca4c3545 6639 threadid = build_call_expr (threadid, 0);
6640 threadid = fold_convert (itype, threadid);
6641 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
75a70cf9 6642 true, GSI_SAME_STMT);
1e8e9920 6643
bc7bff74 6644 n1 = fd->loop.n1;
6645 n2 = fd->loop.n2;
6646 step = fd->loop.step;
6647 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6648 {
6649 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6650 OMP_CLAUSE__LOOPTEMP_);
6651 gcc_assert (innerc);
6652 n1 = OMP_CLAUSE_DECL (innerc);
6653 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6654 OMP_CLAUSE__LOOPTEMP_);
6655 gcc_assert (innerc);
6656 n2 = OMP_CLAUSE_DECL (innerc);
6657 }
6658 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
6659 true, NULL_TREE, true, GSI_SAME_STMT);
6660 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
6661 true, NULL_TREE, true, GSI_SAME_STMT);
6662 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
6663 true, NULL_TREE, true, GSI_SAME_STMT);
fd6481cf 6664
6665 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
bc7bff74 6666 t = fold_build2 (PLUS_EXPR, itype, step, t);
6667 t = fold_build2 (PLUS_EXPR, itype, t, n2);
6668 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
fd6481cf 6669 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
6670 t = fold_build2 (TRUNC_DIV_EXPR, itype,
6671 fold_build1 (NEGATE_EXPR, itype, t),
bc7bff74 6672 fold_build1 (NEGATE_EXPR, itype, step));
fd6481cf 6673 else
bc7bff74 6674 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
fd6481cf 6675 t = fold_convert (itype, t);
75a70cf9 6676 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
1e8e9920 6677
072f7ab1 6678 q = create_tmp_reg (itype, "q");
fd6481cf 6679 t = fold_build2 (TRUNC_DIV_EXPR, itype, n, nthreads);
31712e83 6680 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
6681 gsi_insert_before (&gsi, gimple_build_assign (q, t), GSI_SAME_STMT);
6682
072f7ab1 6683 tt = create_tmp_reg (itype, "tt");
31712e83 6684 t = fold_build2 (TRUNC_MOD_EXPR, itype, n, nthreads);
6685 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
6686 gsi_insert_before (&gsi, gimple_build_assign (tt, t), GSI_SAME_STMT);
1e8e9920 6687
31712e83 6688 t = build2 (LT_EXPR, boolean_type_node, threadid, tt);
1a91d914 6689 gcond *cond_stmt = gimple_build_cond_empty (t);
6690 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
31712e83 6691
1a91d914 6692 second_bb = split_block (entry_bb, cond_stmt)->dest;
31712e83 6693 gsi = gsi_last_bb (second_bb);
6694 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6695
6696 gsi_insert_before (&gsi, gimple_build_assign (tt, build_int_cst (itype, 0)),
6697 GSI_SAME_STMT);
1a91d914 6698 gassign *assign_stmt
e9cf809e 6699 = gimple_build_assign (q, PLUS_EXPR, q, build_int_cst (itype, 1));
1a91d914 6700 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
31712e83 6701
1a91d914 6702 third_bb = split_block (second_bb, assign_stmt)->dest;
31712e83 6703 gsi = gsi_last_bb (third_bb);
6704 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
1e8e9920 6705
fd6481cf 6706 t = build2 (MULT_EXPR, itype, q, threadid);
31712e83 6707 t = build2 (PLUS_EXPR, itype, t, tt);
75a70cf9 6708 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
1e8e9920 6709
fd6481cf 6710 t = fold_build2 (PLUS_EXPR, itype, s0, q);
75a70cf9 6711 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
79acaae1 6712
1e8e9920 6713 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
75a70cf9 6714 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
773c5ba7 6715
75a70cf9 6716 /* Remove the GIMPLE_OMP_FOR statement. */
6717 gsi_remove (&gsi, true);
773c5ba7 6718
6719 /* Setup code for sequential iteration goes in SEQ_START_BB. */
75a70cf9 6720 gsi = gsi_start_bb (seq_start_bb);
1e8e9920 6721
bc7bff74 6722 tree startvar = fd->loop.v;
6723 tree endvar = NULL_TREE;
6724
6725 if (gimple_omp_for_combined_p (fd->for_stmt))
6726 {
6727 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
6728 ? gimple_omp_parallel_clauses (inner_stmt)
6729 : gimple_omp_for_clauses (inner_stmt);
6730 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
6731 gcc_assert (innerc);
6732 startvar = OMP_CLAUSE_DECL (innerc);
6733 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6734 OMP_CLAUSE__LOOPTEMP_);
6735 gcc_assert (innerc);
6736 endvar = OMP_CLAUSE_DECL (innerc);
6737 }
fd6481cf 6738 t = fold_convert (itype, s0);
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);
4abecb72 6745 t = force_gimple_operand_gsi (&gsi, t,
bc7bff74 6746 DECL_P (startvar)
6747 && TREE_ADDRESSABLE (startvar),
4abecb72 6748 NULL_TREE, false, GSI_CONTINUE_LINKING);
1a91d914 6749 assign_stmt = gimple_build_assign (startvar, t);
6750 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
48e1416a 6751
fd6481cf 6752 t = fold_convert (itype, e0);
bc7bff74 6753 t = fold_build2 (MULT_EXPR, itype, t, step);
fd6481cf 6754 if (POINTER_TYPE_P (type))
bc7bff74 6755 t = fold_build_pointer_plus (n1, t);
fd6481cf 6756 else
bc7bff74 6757 t = fold_build2 (PLUS_EXPR, type, t, n1);
6758 t = fold_convert (TREE_TYPE (startvar), t);
75a70cf9 6759 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6760 false, GSI_CONTINUE_LINKING);
bc7bff74 6761 if (endvar)
6762 {
1a91d914 6763 assign_stmt = gimple_build_assign (endvar, e);
6764 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
d44f2f7c 6765 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
1a91d914 6766 assign_stmt = gimple_build_assign (fd->loop.v, e);
d44f2f7c 6767 else
e9cf809e 6768 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
1a91d914 6769 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
bc7bff74 6770 }
6771 if (fd->collapse > 1)
6772 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
1e8e9920 6773
bc7bff74 6774 if (!broken_loop)
6775 {
6776 /* The code controlling the sequential loop replaces the
6777 GIMPLE_OMP_CONTINUE. */
6778 gsi = gsi_last_bb (cont_bb);
1a91d914 6779 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
6780 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
6781 vmain = gimple_omp_continue_control_use (cont_stmt);
6782 vback = gimple_omp_continue_control_def (cont_stmt);
79acaae1 6783
bc7bff74 6784 if (!gimple_omp_for_combined_p (fd->for_stmt))
6785 {
6786 if (POINTER_TYPE_P (type))
6787 t = fold_build_pointer_plus (vmain, step);
6788 else
6789 t = fold_build2 (PLUS_EXPR, type, vmain, step);
6790 t = force_gimple_operand_gsi (&gsi, t,
6791 DECL_P (vback)
6792 && TREE_ADDRESSABLE (vback),
6793 NULL_TREE, true, GSI_SAME_STMT);
1a91d914 6794 assign_stmt = gimple_build_assign (vback, t);
6795 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
79acaae1 6796
bc7bff74 6797 t = build2 (fd->loop.cond_code, boolean_type_node,
6798 DECL_P (vback) && TREE_ADDRESSABLE (vback)
6799 ? t : vback, e);
6800 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6801 }
1e8e9920 6802
bc7bff74 6803 /* Remove the GIMPLE_OMP_CONTINUE statement. */
6804 gsi_remove (&gsi, true);
6805
6806 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
6807 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
6808 }
773c5ba7 6809
75a70cf9 6810 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
6811 gsi = gsi_last_bb (exit_bb);
6812 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
bc7bff74 6813 {
6814 t = gimple_omp_return_lhs (gsi_stmt (gsi));
ca4c3545 6815 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
6816 gcc_checking_assert (t == NULL_TREE);
6817 else
6818 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
bc7bff74 6819 }
75a70cf9 6820 gsi_remove (&gsi, true);
773c5ba7 6821
6822 /* Connect all the blocks. */
31712e83 6823 ep = make_edge (entry_bb, third_bb, EDGE_FALSE_VALUE);
6824 ep->probability = REG_BR_PROB_BASE / 4 * 3;
6825 ep = find_edge (entry_bb, second_bb);
6826 ep->flags = EDGE_TRUE_VALUE;
6827 ep->probability = REG_BR_PROB_BASE / 4;
6828 find_edge (third_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
6829 find_edge (third_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
79acaae1 6830
bc7bff74 6831 if (!broken_loop)
6832 {
6833 ep = find_edge (cont_bb, body_bb);
6834 if (gimple_omp_for_combined_p (fd->for_stmt))
6835 {
6836 remove_edge (ep);
6837 ep = NULL;
6838 }
6839 else if (fd->collapse > 1)
6840 {
6841 remove_edge (ep);
6842 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6843 }
6844 else
6845 ep->flags = EDGE_TRUE_VALUE;
6846 find_edge (cont_bb, fin_bb)->flags
6847 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
6848 }
48e1416a 6849
31712e83 6850 set_immediate_dominator (CDI_DOMINATORS, second_bb, entry_bb);
6851 set_immediate_dominator (CDI_DOMINATORS, third_bb, entry_bb);
6852 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, third_bb);
bc7bff74 6853
79acaae1 6854 set_immediate_dominator (CDI_DOMINATORS, body_bb,
6855 recompute_dominator (CDI_DOMINATORS, body_bb));
6856 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
6857 recompute_dominator (CDI_DOMINATORS, fin_bb));
04c2922b 6858
bc7bff74 6859 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
6860 {
6861 struct loop *loop = alloc_loop ();
6862 loop->header = body_bb;
6863 if (collapse_bb == NULL)
6864 loop->latch = cont_bb;
6865 add_loop (loop, body_bb->loop_father);
6866 }
1e8e9920 6867}
6868
773c5ba7 6869
6870/* A subroutine of expand_omp_for. Generate code for a parallel
6871 loop with static schedule and a specified chunk size. Given
6872 parameters:
1e8e9920 6873
6874 for (V = N1; V cond N2; V += STEP) BODY;
6875
6876 where COND is "<" or ">", we generate pseudocode
6877
8e6b4515 6878 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
1e8e9920 6879 if (cond is <)
6880 adj = STEP - 1;
6881 else
6882 adj = STEP + 1;
fd6481cf 6883 if ((__typeof (V)) -1 > 0 && cond is >)
6884 n = -(adj + N2 - N1) / -STEP;
6885 else
6886 n = (adj + N2 - N1) / STEP;
1e8e9920 6887 trip = 0;
79acaae1 6888 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
6889 here so that V is defined
6890 if the loop is not entered
1e8e9920 6891 L0:
6892 s0 = (trip * nthreads + threadid) * CHUNK;
6893 e0 = min(s0 + CHUNK, n);
6894 if (s0 < n) goto L1; else goto L4;
6895 L1:
6896 V = s0 * STEP + N1;
6897 e = e0 * STEP + N1;
6898 L2:
6899 BODY;
6900 V += STEP;
6901 if (V cond e) goto L2; else goto L3;
6902 L3:
6903 trip += 1;
6904 goto L0;
6905 L4:
1e8e9920 6906*/
6907
61e47ac8 6908static void
bc7bff74 6909expand_omp_for_static_chunk (struct omp_region *region,
6910 struct omp_for_data *fd, gimple inner_stmt)
1e8e9920 6911{
75a70cf9 6912 tree n, s0, e0, e, t;
79acaae1 6913 tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
93481288 6914 tree type, itype, vmain, vback, vextra;
773c5ba7 6915 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
bc7bff74 6916 basic_block trip_update_bb = NULL, cont_bb, collapse_bb = NULL, fin_bb;
93481288 6917 gimple_stmt_iterator gsi;
75a70cf9 6918 edge se;
bc7bff74 6919 bool broken_loop = region->cont == NULL;
6920 tree *counts = NULL;
6921 tree n1, n2, step;
1e8e9920 6922
ca4c3545 6923 gcc_checking_assert ((gimple_omp_for_kind (fd->for_stmt)
6924 != GF_OMP_FOR_KIND_OACC_LOOP)
6925 || !inner_stmt);
6926
fd6481cf 6927 itype = type = TREE_TYPE (fd->loop.v);
6928 if (POINTER_TYPE_P (type))
3cea8318 6929 itype = signed_type_for (type);
1e8e9920 6930
61e47ac8 6931 entry_bb = region->entry;
ac6e3339 6932 se = split_block (entry_bb, last_stmt (entry_bb));
6933 entry_bb = se->src;
6934 iter_part_bb = se->dest;
61e47ac8 6935 cont_bb = region->cont;
ac6e3339 6936 gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
bc7bff74 6937 fin_bb = BRANCH_EDGE (iter_part_bb)->dest;
6938 gcc_assert (broken_loop
6939 || fin_bb == FALLTHRU_EDGE (cont_bb)->dest);
ac6e3339 6940 seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
6941 body_bb = single_succ (seq_start_bb);
bc7bff74 6942 if (!broken_loop)
6943 {
6944 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
6945 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6946 trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
6947 }
61e47ac8 6948 exit_bb = region->exit;
773c5ba7 6949
773c5ba7 6950 /* Trip and adjustment setup goes in ENTRY_BB. */
93481288 6951 gsi = gsi_last_bb (entry_bb);
6952 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
773c5ba7 6953
bc7bff74 6954 if (fd->collapse > 1)
6955 {
6956 int first_zero_iter = -1;
6957 basic_block l2_dom_bb = NULL;
6958
6959 counts = XALLOCAVEC (tree, fd->collapse);
93481288 6960 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
bc7bff74 6961 fin_bb, first_zero_iter,
6962 l2_dom_bb);
6963 t = NULL_TREE;
6964 }
6965 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
6966 t = integer_one_node;
6967 else
6968 t = fold_binary (fd->loop.cond_code, boolean_type_node,
6969 fold_convert (type, fd->loop.n1),
6970 fold_convert (type, fd->loop.n2));
6971 if (fd->collapse == 1
6972 && TYPE_UNSIGNED (type)
8e6b4515 6973 && (t == NULL_TREE || !integer_onep (t)))
6974 {
8e6b4515 6975 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
93481288 6976 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
8e6b4515 6977 true, GSI_SAME_STMT);
6978 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
93481288 6979 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
8e6b4515 6980 true, GSI_SAME_STMT);
1a91d914 6981 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
6982 NULL_TREE, NULL_TREE);
6983 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
6984 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
8e6b4515 6985 expand_omp_regimplify_p, NULL, NULL)
1a91d914 6986 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
8e6b4515 6987 expand_omp_regimplify_p, NULL, NULL))
6988 {
1a91d914 6989 gsi = gsi_for_stmt (cond_stmt);
6990 gimple_regimplify_operands (cond_stmt, &gsi);
8e6b4515 6991 }
1a91d914 6992 se = split_block (entry_bb, cond_stmt);
8e6b4515 6993 se->flags = EDGE_TRUE_VALUE;
6994 entry_bb = se->dest;
6995 se->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
6996 se = make_edge (se->src, fin_bb, EDGE_FALSE_VALUE);
6997 se->probability = REG_BR_PROB_BASE / 2000 - 1;
6998 if (gimple_in_ssa_p (cfun))
6999 {
7000 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
1a91d914 7001 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
7002 !gsi_end_p (gpi); gsi_next (&gpi))
8e6b4515 7003 {
1a91d914 7004 gphi *phi = gpi.phi ();
8e6b4515 7005 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
7006 se, UNKNOWN_LOCATION);
7007 }
7008 }
93481288 7009 gsi = gsi_last_bb (entry_bb);
8e6b4515 7010 }
7011
ca4c3545 7012 switch (gimple_omp_for_kind (fd->for_stmt))
7013 {
7014 case GF_OMP_FOR_KIND_FOR:
7015 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
7016 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
7017 break;
7018 case GF_OMP_FOR_KIND_DISTRIBUTE:
7019 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
7020 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
7021 break;
7022 case GF_OMP_FOR_KIND_OACC_LOOP:
7023 nthreads = builtin_decl_explicit (BUILT_IN_GOACC_GET_NUM_THREADS);
7024 threadid = builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM);
7025 break;
7026 default:
7027 gcc_unreachable ();
7028 }
7029 nthreads = build_call_expr (nthreads, 0);
7030 nthreads = fold_convert (itype, nthreads);
7031 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
75a70cf9 7032 true, GSI_SAME_STMT);
ca4c3545 7033 threadid = build_call_expr (threadid, 0);
7034 threadid = fold_convert (itype, threadid);
7035 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
75a70cf9 7036 true, GSI_SAME_STMT);
79acaae1 7037
bc7bff74 7038 n1 = fd->loop.n1;
7039 n2 = fd->loop.n2;
7040 step = fd->loop.step;
7041 if (gimple_omp_for_combined_into_p (fd->for_stmt))
7042 {
7043 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7044 OMP_CLAUSE__LOOPTEMP_);
7045 gcc_assert (innerc);
7046 n1 = OMP_CLAUSE_DECL (innerc);
7047 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7048 OMP_CLAUSE__LOOPTEMP_);
7049 gcc_assert (innerc);
7050 n2 = OMP_CLAUSE_DECL (innerc);
7051 }
93481288 7052 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
bc7bff74 7053 true, NULL_TREE, true, GSI_SAME_STMT);
93481288 7054 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
bc7bff74 7055 true, NULL_TREE, true, GSI_SAME_STMT);
93481288 7056 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
bc7bff74 7057 true, NULL_TREE, true, GSI_SAME_STMT);
79acaae1 7058 fd->chunk_size
93481288 7059 = force_gimple_operand_gsi (&gsi, fold_convert (itype, fd->chunk_size),
75a70cf9 7060 true, NULL_TREE, true, GSI_SAME_STMT);
fd6481cf 7061
7062 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
bc7bff74 7063 t = fold_build2 (PLUS_EXPR, itype, step, t);
7064 t = fold_build2 (PLUS_EXPR, itype, t, n2);
7065 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
fd6481cf 7066 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
7067 t = fold_build2 (TRUNC_DIV_EXPR, itype,
7068 fold_build1 (NEGATE_EXPR, itype, t),
bc7bff74 7069 fold_build1 (NEGATE_EXPR, itype, step));
fd6481cf 7070 else
bc7bff74 7071 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
fd6481cf 7072 t = fold_convert (itype, t);
93481288 7073 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
75a70cf9 7074 true, GSI_SAME_STMT);
79acaae1 7075
083152fb 7076 trip_var = create_tmp_reg (itype, ".trip");
79acaae1 7077 if (gimple_in_ssa_p (cfun))
7078 {
f9e245b2 7079 trip_init = make_ssa_name (trip_var);
7080 trip_main = make_ssa_name (trip_var);
7081 trip_back = make_ssa_name (trip_var);
79acaae1 7082 }
1e8e9920 7083 else
79acaae1 7084 {
7085 trip_init = trip_var;
7086 trip_main = trip_var;
7087 trip_back = trip_var;
7088 }
1e8e9920 7089
1a91d914 7090 gassign *assign_stmt
7091 = gimple_build_assign (trip_init, build_int_cst (itype, 0));
7092 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
773c5ba7 7093
fd6481cf 7094 t = fold_build2 (MULT_EXPR, itype, threadid, fd->chunk_size);
bc7bff74 7095 t = fold_build2 (MULT_EXPR, itype, t, step);
fd6481cf 7096 if (POINTER_TYPE_P (type))
bc7bff74 7097 t = fold_build_pointer_plus (n1, t);
fd6481cf 7098 else
bc7bff74 7099 t = fold_build2 (PLUS_EXPR, type, t, n1);
93481288 7100 vextra = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7101 true, GSI_SAME_STMT);
79acaae1 7102
75a70cf9 7103 /* Remove the GIMPLE_OMP_FOR. */
93481288 7104 gsi_remove (&gsi, true);
773c5ba7 7105
7106 /* Iteration space partitioning goes in ITER_PART_BB. */
93481288 7107 gsi = gsi_last_bb (iter_part_bb);
1e8e9920 7108
fd6481cf 7109 t = fold_build2 (MULT_EXPR, itype, trip_main, nthreads);
7110 t = fold_build2 (PLUS_EXPR, itype, t, threadid);
7111 t = fold_build2 (MULT_EXPR, itype, t, fd->chunk_size);
93481288 7112 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
75a70cf9 7113 false, GSI_CONTINUE_LINKING);
1e8e9920 7114
fd6481cf 7115 t = fold_build2 (PLUS_EXPR, itype, s0, fd->chunk_size);
7116 t = fold_build2 (MIN_EXPR, itype, t, n);
93481288 7117 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
75a70cf9 7118 false, GSI_CONTINUE_LINKING);
1e8e9920 7119
7120 t = build2 (LT_EXPR, boolean_type_node, s0, n);
93481288 7121 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_CONTINUE_LINKING);
773c5ba7 7122
7123 /* Setup code for sequential iteration goes in SEQ_START_BB. */
93481288 7124 gsi = gsi_start_bb (seq_start_bb);
1e8e9920 7125
bc7bff74 7126 tree startvar = fd->loop.v;
7127 tree endvar = NULL_TREE;
7128
7129 if (gimple_omp_for_combined_p (fd->for_stmt))
7130 {
7131 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
7132 ? gimple_omp_parallel_clauses (inner_stmt)
7133 : gimple_omp_for_clauses (inner_stmt);
7134 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
7135 gcc_assert (innerc);
7136 startvar = OMP_CLAUSE_DECL (innerc);
7137 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7138 OMP_CLAUSE__LOOPTEMP_);
7139 gcc_assert (innerc);
7140 endvar = OMP_CLAUSE_DECL (innerc);
7141 }
7142
fd6481cf 7143 t = fold_convert (itype, s0);
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 t = force_gimple_operand_gsi (&gsi, t,
bc7bff74 7151 DECL_P (startvar)
7152 && TREE_ADDRESSABLE (startvar),
4abecb72 7153 NULL_TREE, false, GSI_CONTINUE_LINKING);
1a91d914 7154 assign_stmt = gimple_build_assign (startvar, t);
7155 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
1e8e9920 7156
fd6481cf 7157 t = fold_convert (itype, e0);
bc7bff74 7158 t = fold_build2 (MULT_EXPR, itype, t, step);
fd6481cf 7159 if (POINTER_TYPE_P (type))
bc7bff74 7160 t = fold_build_pointer_plus (n1, t);
fd6481cf 7161 else
bc7bff74 7162 t = fold_build2 (PLUS_EXPR, type, t, n1);
7163 t = fold_convert (TREE_TYPE (startvar), t);
93481288 7164 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
75a70cf9 7165 false, GSI_CONTINUE_LINKING);
bc7bff74 7166 if (endvar)
7167 {
1a91d914 7168 assign_stmt = gimple_build_assign (endvar, e);
7169 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
d44f2f7c 7170 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
1a91d914 7171 assign_stmt = gimple_build_assign (fd->loop.v, e);
d44f2f7c 7172 else
e9cf809e 7173 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
1a91d914 7174 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
bc7bff74 7175 }
7176 if (fd->collapse > 1)
93481288 7177 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
bc7bff74 7178
7179 if (!broken_loop)
7180 {
7181 /* The code controlling the sequential loop goes in CONT_BB,
7182 replacing the GIMPLE_OMP_CONTINUE. */
93481288 7183 gsi = gsi_last_bb (cont_bb);
1a91d914 7184 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
7185 vmain = gimple_omp_continue_control_use (cont_stmt);
7186 vback = gimple_omp_continue_control_def (cont_stmt);
1e8e9920 7187
bc7bff74 7188 if (!gimple_omp_for_combined_p (fd->for_stmt))
7189 {
7190 if (POINTER_TYPE_P (type))
93481288 7191 t = fold_build_pointer_plus (vmain, step);
bc7bff74 7192 else
93481288 7193 t = fold_build2 (PLUS_EXPR, type, vmain, step);
7194 if (DECL_P (vback) && TREE_ADDRESSABLE (vback))
7195 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
bc7bff74 7196 true, GSI_SAME_STMT);
1a91d914 7197 assign_stmt = gimple_build_assign (vback, t);
7198 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
79acaae1 7199
bc7bff74 7200 t = build2 (fd->loop.cond_code, boolean_type_node,
93481288 7201 DECL_P (vback) && TREE_ADDRESSABLE (vback)
7202 ? t : vback, e);
7203 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
bc7bff74 7204 }
79acaae1 7205
bc7bff74 7206 /* Remove GIMPLE_OMP_CONTINUE. */
93481288 7207 gsi_remove (&gsi, true);
48e1416a 7208
bc7bff74 7209 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
7210 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
773c5ba7 7211
bc7bff74 7212 /* Trip update code goes into TRIP_UPDATE_BB. */
93481288 7213 gsi = gsi_start_bb (trip_update_bb);
1e8e9920 7214
bc7bff74 7215 t = build_int_cst (itype, 1);
7216 t = build2 (PLUS_EXPR, itype, trip_main, t);
1a91d914 7217 assign_stmt = gimple_build_assign (trip_back, t);
7218 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
bc7bff74 7219 }
1e8e9920 7220
75a70cf9 7221 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
93481288 7222 gsi = gsi_last_bb (exit_bb);
7223 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
bc7bff74 7224 {
93481288 7225 t = gimple_omp_return_lhs (gsi_stmt (gsi));
ca4c3545 7226 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
7227 gcc_checking_assert (t == NULL_TREE);
7228 else
7229 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
bc7bff74 7230 }
93481288 7231 gsi_remove (&gsi, true);
1e8e9920 7232
773c5ba7 7233 /* Connect the new blocks. */
ac6e3339 7234 find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
7235 find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
79acaae1 7236
bc7bff74 7237 if (!broken_loop)
7238 {
7239 se = find_edge (cont_bb, body_bb);
7240 if (gimple_omp_for_combined_p (fd->for_stmt))
7241 {
7242 remove_edge (se);
7243 se = NULL;
7244 }
7245 else if (fd->collapse > 1)
7246 {
7247 remove_edge (se);
7248 se = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
7249 }
7250 else
7251 se->flags = EDGE_TRUE_VALUE;
7252 find_edge (cont_bb, trip_update_bb)->flags
7253 = se ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
79acaae1 7254
bc7bff74 7255 redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb);
7256 }
79acaae1 7257
7258 if (gimple_in_ssa_p (cfun))
7259 {
1a91d914 7260 gphi_iterator psi;
7261 gphi *phi;
75a70cf9 7262 edge re, ene;
75a70cf9 7263 edge_var_map *vm;
7264 size_t i;
7265
bc7bff74 7266 gcc_assert (fd->collapse == 1 && !broken_loop);
7267
79acaae1 7268 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
7269 remove arguments of the phi nodes in fin_bb. We need to create
7270 appropriate phi nodes in iter_part_bb instead. */
7271 se = single_pred_edge (fin_bb);
7272 re = single_succ_edge (trip_update_bb);
06ecf488 7273 vec<edge_var_map> *head = redirect_edge_var_map_vector (re);
79acaae1 7274 ene = single_succ_edge (entry_bb);
7275
75a70cf9 7276 psi = gsi_start_phis (fin_bb);
f1f41a6c 7277 for (i = 0; !gsi_end_p (psi) && head->iterate (i, &vm);
75a70cf9 7278 gsi_next (&psi), ++i)
79acaae1 7279 {
1a91d914 7280 gphi *nphi;
efbcb6de 7281 source_location locus;
75a70cf9 7282
1a91d914 7283 phi = psi.phi ();
75a70cf9 7284 t = gimple_phi_result (phi);
7285 gcc_assert (t == redirect_edge_var_map_result (vm));
79acaae1 7286 nphi = create_phi_node (t, iter_part_bb);
79acaae1 7287
7288 t = PHI_ARG_DEF_FROM_EDGE (phi, se);
efbcb6de 7289 locus = gimple_phi_arg_location_from_edge (phi, se);
7290
fd6481cf 7291 /* A special case -- fd->loop.v is not yet computed in
93481288 7292 iter_part_bb, we need to use vextra instead. */
fd6481cf 7293 if (t == fd->loop.v)
93481288 7294 t = vextra;
60d535d2 7295 add_phi_arg (nphi, t, ene, locus);
efbcb6de 7296 locus = redirect_edge_var_map_location (vm);
60d535d2 7297 add_phi_arg (nphi, redirect_edge_var_map_def (vm), re, locus);
75a70cf9 7298 }
a6f1094f 7299 gcc_assert (gsi_end_p (psi) && i == head->length ());
75a70cf9 7300 redirect_edge_var_map_clear (re);
7301 while (1)
7302 {
7303 psi = gsi_start_phis (fin_bb);
7304 if (gsi_end_p (psi))
7305 break;
7306 remove_phi_node (&psi, false);
79acaae1 7307 }
79acaae1 7308
7309 /* Make phi node for trip. */
7310 phi = create_phi_node (trip_main, iter_part_bb);
efbcb6de 7311 add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb),
60d535d2 7312 UNKNOWN_LOCATION);
efbcb6de 7313 add_phi_arg (phi, trip_init, single_succ_edge (entry_bb),
60d535d2 7314 UNKNOWN_LOCATION);
79acaae1 7315 }
7316
bc7bff74 7317 if (!broken_loop)
7318 set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
79acaae1 7319 set_immediate_dominator (CDI_DOMINATORS, iter_part_bb,
7320 recompute_dominator (CDI_DOMINATORS, iter_part_bb));
7321 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
7322 recompute_dominator (CDI_DOMINATORS, fin_bb));
7323 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb,
7324 recompute_dominator (CDI_DOMINATORS, seq_start_bb));
7325 set_immediate_dominator (CDI_DOMINATORS, body_bb,
7326 recompute_dominator (CDI_DOMINATORS, body_bb));
04c2922b 7327
bc7bff74 7328 if (!broken_loop)
7329 {
7330 struct loop *trip_loop = alloc_loop ();
7331 trip_loop->header = iter_part_bb;
7332 trip_loop->latch = trip_update_bb;
7333 add_loop (trip_loop, iter_part_bb->loop_father);
04c2922b 7334
bc7bff74 7335 if (!gimple_omp_for_combined_p (fd->for_stmt))
7336 {
7337 struct loop *loop = alloc_loop ();
7338 loop->header = body_bb;
33ee4d72 7339 if (collapse_bb == NULL)
7340 loop->latch = cont_bb;
bc7bff74 7341 add_loop (loop, trip_loop);
7342 }
7343 }
1e8e9920 7344}
7345
40750995 7346/* A subroutine of expand_omp_for. Generate code for _Cilk_for loop.
7347 Given parameters:
7348 for (V = N1; V cond N2; V += STEP) BODY;
7349
7350 where COND is "<" or ">" or "!=", we generate pseudocode
7351
7352 for (ind_var = low; ind_var < high; ind_var++)
7353 {
7354 V = n1 + (ind_var * STEP)
7355
7356 <BODY>
7357 }
7358
7359 In the above pseudocode, low and high are function parameters of the
7360 child function. In the function below, we are inserting a temp.
7361 variable that will be making a call to two OMP functions that will not be
7362 found in the body of _Cilk_for (since OMP_FOR cannot be mixed
7363 with _Cilk_for). These functions are replaced with low and high
7364 by the function that handles taskreg. */
7365
7366
7367static void
7368expand_cilk_for (struct omp_region *region, struct omp_for_data *fd)
7369{
7370 bool broken_loop = region->cont == NULL;
7371 basic_block entry_bb = region->entry;
7372 basic_block cont_bb = region->cont;
7373
7374 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
7375 gcc_assert (broken_loop
7376 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
7377 basic_block l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
7378 basic_block l1_bb, l2_bb;
7379
7380 if (!broken_loop)
7381 {
7382 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
7383 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
7384 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
7385 l2_bb = BRANCH_EDGE (entry_bb)->dest;
7386 }
7387 else
7388 {
7389 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
7390 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
7391 l2_bb = single_succ (l1_bb);
7392 }
7393 basic_block exit_bb = region->exit;
7394 basic_block l2_dom_bb = NULL;
7395
7396 gimple_stmt_iterator gsi = gsi_last_bb (entry_bb);
7397
7398 /* Below statements until the "tree high_val = ..." are pseudo statements
7399 used to pass information to be used by expand_omp_taskreg.
7400 low_val and high_val will be replaced by the __low and __high
7401 parameter from the child function.
7402
7403 The call_exprs part is a place-holder, it is mainly used
7404 to distinctly identify to the top-level part that this is
7405 where we should put low and high (reasoning given in header
7406 comment). */
7407
7408 tree child_fndecl
1a91d914 7409 = gimple_omp_parallel_child_fn (
7410 as_a <gomp_parallel *> (last_stmt (region->outer->entry)));
40750995 7411 tree t, low_val = NULL_TREE, high_val = NULL_TREE;
7412 for (t = DECL_ARGUMENTS (child_fndecl); t; t = TREE_CHAIN (t))
7413 {
7414 if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__high"))
7415 high_val = t;
7416 else if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__low"))
7417 low_val = t;
7418 }
7419 gcc_assert (low_val && high_val);
7420
7421 tree type = TREE_TYPE (low_val);
7422 tree ind_var = create_tmp_reg (type, "__cilk_ind_var");
7423 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
7424
7425 /* Not needed in SSA form right now. */
7426 gcc_assert (!gimple_in_ssa_p (cfun));
7427 if (l2_dom_bb == NULL)
7428 l2_dom_bb = l1_bb;
7429
7430 tree n1 = low_val;
7431 tree n2 = high_val;
7432
7433 gimple stmt = gimple_build_assign (ind_var, n1);
7434
7435 /* Replace the GIMPLE_OMP_FOR statement. */
7436 gsi_replace (&gsi, stmt, true);
7437
7438 if (!broken_loop)
7439 {
7440 /* Code to control the increment goes in the CONT_BB. */
7441 gsi = gsi_last_bb (cont_bb);
7442 stmt = gsi_stmt (gsi);
7443 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
e9cf809e 7444 stmt = gimple_build_assign (ind_var, PLUS_EXPR, ind_var,
7445 build_one_cst (type));
40750995 7446
7447 /* Replace GIMPLE_OMP_CONTINUE. */
7448 gsi_replace (&gsi, stmt, true);
7449 }
7450
7451 /* Emit the condition in L1_BB. */
7452 gsi = gsi_after_labels (l1_bb);
7453 t = fold_build2 (MULT_EXPR, TREE_TYPE (fd->loop.step),
7454 fold_convert (TREE_TYPE (fd->loop.step), ind_var),
7455 fd->loop.step);
7456 if (POINTER_TYPE_P (TREE_TYPE (fd->loop.n1)))
7457 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (fd->loop.n1),
7458 fd->loop.n1, fold_convert (sizetype, t));
7459 else
7460 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loop.n1),
7461 fd->loop.n1, fold_convert (TREE_TYPE (fd->loop.n1), t));
7462 t = fold_convert (TREE_TYPE (fd->loop.v), t);
7463 expand_omp_build_assign (&gsi, fd->loop.v, t);
7464
7465 /* The condition is always '<' since the runtime will fill in the low
7466 and high values. */
7467 stmt = gimple_build_cond (LT_EXPR, ind_var, n2, NULL_TREE, NULL_TREE);
7468 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
7469
7470 /* Remove GIMPLE_OMP_RETURN. */
7471 gsi = gsi_last_bb (exit_bb);
7472 gsi_remove (&gsi, true);
7473
7474 /* Connect the new blocks. */
7475 remove_edge (FALLTHRU_EDGE (entry_bb));
7476
7477 edge e, ne;
7478 if (!broken_loop)
7479 {
7480 remove_edge (BRANCH_EDGE (entry_bb));
7481 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
7482
7483 e = BRANCH_EDGE (l1_bb);
7484 ne = FALLTHRU_EDGE (l1_bb);
7485 e->flags = EDGE_TRUE_VALUE;
7486 }
7487 else
7488 {
7489 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7490
7491 ne = single_succ_edge (l1_bb);
7492 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
7493
7494 }
7495 ne->flags = EDGE_FALSE_VALUE;
7496 e->probability = REG_BR_PROB_BASE * 7 / 8;
7497 ne->probability = REG_BR_PROB_BASE / 8;
7498
7499 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
7500 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
7501 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
7502
7503 if (!broken_loop)
7504 {
7505 struct loop *loop = alloc_loop ();
7506 loop->header = l1_bb;
7507 loop->latch = cont_bb;
7508 add_loop (loop, l1_bb->loop_father);
7509 loop->safelen = INT_MAX;
7510 }
7511
7512 /* Pick the correct library function based on the precision of the
7513 induction variable type. */
7514 tree lib_fun = NULL_TREE;
7515 if (TYPE_PRECISION (type) == 32)
7516 lib_fun = cilk_for_32_fndecl;
7517 else if (TYPE_PRECISION (type) == 64)
7518 lib_fun = cilk_for_64_fndecl;
7519 else
7520 gcc_unreachable ();
7521
7522 gcc_assert (fd->sched_kind == OMP_CLAUSE_SCHEDULE_CILKFOR);
7523
7524 /* WS_ARGS contains the library function flavor to call:
7525 __libcilkrts_cilk_for_64 or __libcilkrts_cilk_for_32), and the
7526 user-defined grain value. If the user does not define one, then zero
7527 is passed in by the parser. */
7528 vec_alloc (region->ws_args, 2);
7529 region->ws_args->quick_push (lib_fun);
7530 region->ws_args->quick_push (fd->chunk_size);
7531}
bc7bff74 7532
3d483a94 7533/* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
7534 loop. Given parameters:
7535
7536 for (V = N1; V cond N2; V += STEP) BODY;
7537
7538 where COND is "<" or ">", we generate pseudocode
7539
7540 V = N1;
7541 goto L1;
7542 L0:
7543 BODY;
7544 V += STEP;
7545 L1:
7546 if (V cond N2) goto L0; else goto L2;
7547 L2:
7548
7549 For collapsed loops, given parameters:
7550 collapse(3)
7551 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
7552 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
7553 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
7554 BODY;
7555
7556 we generate pseudocode
7557
7558 if (cond3 is <)
7559 adj = STEP3 - 1;
7560 else
7561 adj = STEP3 + 1;
7562 count3 = (adj + N32 - N31) / STEP3;
7563 if (cond2 is <)
7564 adj = STEP2 - 1;
7565 else
7566 adj = STEP2 + 1;
7567 count2 = (adj + N22 - N21) / STEP2;
7568 if (cond1 is <)
7569 adj = STEP1 - 1;
7570 else
7571 adj = STEP1 + 1;
7572 count1 = (adj + N12 - N11) / STEP1;
7573 count = count1 * count2 * count3;
7574 V = 0;
7575 V1 = N11;
7576 V2 = N21;
7577 V3 = N31;
7578 goto L1;
7579 L0:
7580 BODY;
7581 V += 1;
7582 V3 += STEP3;
7583 V2 += (V3 cond3 N32) ? 0 : STEP2;
7584 V3 = (V3 cond3 N32) ? V3 : N31;
7585 V1 += (V2 cond2 N22) ? 0 : STEP1;
7586 V2 = (V2 cond2 N22) ? V2 : N21;
7587 L1:
7588 if (V < count) goto L0; else goto L2;
7589 L2:
7590
7591 */
7592
7593static void
7594expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
7595{
7596 tree type, t;
7597 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, l2_bb, l2_dom_bb;
7598 gimple_stmt_iterator gsi;
7599 gimple stmt;
1a91d914 7600 gcond *cond_stmt;
3d483a94 7601 bool broken_loop = region->cont == NULL;
7602 edge e, ne;
7603 tree *counts = NULL;
7604 int i;
7605 tree safelen = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7606 OMP_CLAUSE_SAFELEN);
7607 tree simduid = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7608 OMP_CLAUSE__SIMDUID_);
bc7bff74 7609 tree n1, n2;
3d483a94 7610
7611 type = TREE_TYPE (fd->loop.v);
7612 entry_bb = region->entry;
7613 cont_bb = region->cont;
7614 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
7615 gcc_assert (broken_loop
7616 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
7617 l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
7618 if (!broken_loop)
7619 {
7620 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
7621 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
7622 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
7623 l2_bb = BRANCH_EDGE (entry_bb)->dest;
7624 }
7625 else
7626 {
7627 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
7628 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
7629 l2_bb = single_succ (l1_bb);
7630 }
7631 exit_bb = region->exit;
7632 l2_dom_bb = NULL;
7633
7634 gsi = gsi_last_bb (entry_bb);
7635
7636 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
7637 /* Not needed in SSA form right now. */
7638 gcc_assert (!gimple_in_ssa_p (cfun));
7639 if (fd->collapse > 1)
7640 {
7641 int first_zero_iter = -1;
7642 basic_block zero_iter_bb = l2_bb;
7643
7644 counts = XALLOCAVEC (tree, fd->collapse);
7645 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
7646 zero_iter_bb, first_zero_iter,
7647 l2_dom_bb);
7648 }
7649 if (l2_dom_bb == NULL)
7650 l2_dom_bb = l1_bb;
7651
bc7bff74 7652 n1 = fd->loop.n1;
3d483a94 7653 n2 = fd->loop.n2;
bc7bff74 7654 if (gimple_omp_for_combined_into_p (fd->for_stmt))
7655 {
7656 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7657 OMP_CLAUSE__LOOPTEMP_);
7658 gcc_assert (innerc);
7659 n1 = OMP_CLAUSE_DECL (innerc);
7660 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7661 OMP_CLAUSE__LOOPTEMP_);
7662 gcc_assert (innerc);
7663 n2 = OMP_CLAUSE_DECL (innerc);
7664 expand_omp_build_assign (&gsi, fd->loop.v,
7665 fold_convert (type, n1));
7666 if (fd->collapse > 1)
7667 {
7668 gsi_prev (&gsi);
7669 expand_omp_for_init_vars (fd, &gsi, counts, NULL, n1);
7670 gsi_next (&gsi);
7671 }
7672 }
3d483a94 7673 else
7674 {
7675 expand_omp_build_assign (&gsi, fd->loop.v,
7676 fold_convert (type, fd->loop.n1));
7677 if (fd->collapse > 1)
7678 for (i = 0; i < fd->collapse; i++)
7679 {
7680 tree itype = TREE_TYPE (fd->loops[i].v);
7681 if (POINTER_TYPE_P (itype))
7682 itype = signed_type_for (itype);
7683 t = fold_convert (TREE_TYPE (fd->loops[i].v), fd->loops[i].n1);
7684 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7685 }
7686 }
7687
7688 /* Remove the GIMPLE_OMP_FOR statement. */
7689 gsi_remove (&gsi, true);
7690
7691 if (!broken_loop)
7692 {
7693 /* Code to control the increment goes in the CONT_BB. */
7694 gsi = gsi_last_bb (cont_bb);
7695 stmt = gsi_stmt (gsi);
7696 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
7697
7698 if (POINTER_TYPE_P (type))
7699 t = fold_build_pointer_plus (fd->loop.v, fd->loop.step);
7700 else
7701 t = fold_build2 (PLUS_EXPR, type, fd->loop.v, fd->loop.step);
7702 expand_omp_build_assign (&gsi, fd->loop.v, t);
7703
7704 if (fd->collapse > 1)
7705 {
7706 i = fd->collapse - 1;
7707 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
7708 {
7709 t = fold_convert (sizetype, fd->loops[i].step);
7710 t = fold_build_pointer_plus (fd->loops[i].v, t);
7711 }
7712 else
7713 {
7714 t = fold_convert (TREE_TYPE (fd->loops[i].v),
7715 fd->loops[i].step);
7716 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
7717 fd->loops[i].v, t);
7718 }
7719 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7720
7721 for (i = fd->collapse - 1; i > 0; i--)
7722 {
7723 tree itype = TREE_TYPE (fd->loops[i].v);
7724 tree itype2 = TREE_TYPE (fd->loops[i - 1].v);
7725 if (POINTER_TYPE_P (itype2))
7726 itype2 = signed_type_for (itype2);
7727 t = build3 (COND_EXPR, itype2,
7728 build2 (fd->loops[i].cond_code, boolean_type_node,
7729 fd->loops[i].v,
7730 fold_convert (itype, fd->loops[i].n2)),
7731 build_int_cst (itype2, 0),
7732 fold_convert (itype2, fd->loops[i - 1].step));
7733 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i - 1].v)))
7734 t = fold_build_pointer_plus (fd->loops[i - 1].v, t);
7735 else
7736 t = fold_build2 (PLUS_EXPR, itype2, fd->loops[i - 1].v, t);
7737 expand_omp_build_assign (&gsi, fd->loops[i - 1].v, t);
7738
7739 t = build3 (COND_EXPR, itype,
7740 build2 (fd->loops[i].cond_code, boolean_type_node,
7741 fd->loops[i].v,
7742 fold_convert (itype, fd->loops[i].n2)),
7743 fd->loops[i].v,
7744 fold_convert (itype, fd->loops[i].n1));
7745 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7746 }
7747 }
7748
7749 /* Remove GIMPLE_OMP_CONTINUE. */
7750 gsi_remove (&gsi, true);
7751 }
7752
7753 /* Emit the condition in L1_BB. */
7754 gsi = gsi_start_bb (l1_bb);
7755
7756 t = fold_convert (type, n2);
7757 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7758 false, GSI_CONTINUE_LINKING);
7759 t = build2 (fd->loop.cond_code, boolean_type_node, fd->loop.v, t);
1a91d914 7760 cond_stmt = gimple_build_cond_empty (t);
7761 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
7762 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt), expand_omp_regimplify_p,
3d483a94 7763 NULL, NULL)
1a91d914 7764 || walk_tree (gimple_cond_rhs_ptr (cond_stmt), expand_omp_regimplify_p,
3d483a94 7765 NULL, NULL))
7766 {
1a91d914 7767 gsi = gsi_for_stmt (cond_stmt);
7768 gimple_regimplify_operands (cond_stmt, &gsi);
3d483a94 7769 }
7770
7771 /* Remove GIMPLE_OMP_RETURN. */
7772 gsi = gsi_last_bb (exit_bb);
7773 gsi_remove (&gsi, true);
7774
7775 /* Connect the new blocks. */
7776 remove_edge (FALLTHRU_EDGE (entry_bb));
7777
7778 if (!broken_loop)
7779 {
7780 remove_edge (BRANCH_EDGE (entry_bb));
7781 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
7782
7783 e = BRANCH_EDGE (l1_bb);
7784 ne = FALLTHRU_EDGE (l1_bb);
7785 e->flags = EDGE_TRUE_VALUE;
7786 }
7787 else
7788 {
7789 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7790
7791 ne = single_succ_edge (l1_bb);
7792 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
7793
7794 }
7795 ne->flags = EDGE_FALSE_VALUE;
7796 e->probability = REG_BR_PROB_BASE * 7 / 8;
7797 ne->probability = REG_BR_PROB_BASE / 8;
7798
7799 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
7800 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
7801 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
7802
7803 if (!broken_loop)
7804 {
7805 struct loop *loop = alloc_loop ();
7806 loop->header = l1_bb;
33ee4d72 7807 loop->latch = cont_bb;
3d483a94 7808 add_loop (loop, l1_bb->loop_father);
7809 if (safelen == NULL_TREE)
7810 loop->safelen = INT_MAX;
7811 else
7812 {
7813 safelen = OMP_CLAUSE_SAFELEN_EXPR (safelen);
c3f3b68d 7814 if (TREE_CODE (safelen) != INTEGER_CST)
7815 loop->safelen = 0;
7816 else if (!tree_fits_uhwi_p (safelen)
7817 || tree_to_uhwi (safelen) > INT_MAX)
3d483a94 7818 loop->safelen = INT_MAX;
7819 else
d85a2013 7820 loop->safelen = tree_to_uhwi (safelen);
3d483a94 7821 if (loop->safelen == 1)
7822 loop->safelen = 0;
7823 }
7824 if (simduid)
7825 {
7826 loop->simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
7827 cfun->has_simduid_loops = true;
7828 }
043115ec 7829 /* If not -fno-tree-loop-vectorize, hint that we want to vectorize
3d483a94 7830 the loop. */
043115ec 7831 if ((flag_tree_loop_vectorize
7832 || (!global_options_set.x_flag_tree_loop_vectorize
7833 && !global_options_set.x_flag_tree_vectorize))
ad45e43e 7834 && flag_tree_loop_optimize
3d483a94 7835 && loop->safelen > 1)
7836 {
4c73695b 7837 loop->force_vectorize = true;
7838 cfun->has_force_vectorize_loops = true;
3d483a94 7839 }
7840 }
9918db44 7841 else if (simduid)
7842 cfun->has_simduid_loops = true;
3d483a94 7843}
7844
1e8e9920 7845
ca4c3545 7846/* Expand the OMP loop defined by REGION. */
1e8e9920 7847
773c5ba7 7848static void
bc7bff74 7849expand_omp_for (struct omp_region *region, gimple inner_stmt)
773c5ba7 7850{
7851 struct omp_for_data fd;
fd6481cf 7852 struct omp_for_data_loop *loops;
1e8e9920 7853
fd6481cf 7854 loops
7855 = (struct omp_for_data_loop *)
75a70cf9 7856 alloca (gimple_omp_for_collapse (last_stmt (region->entry))
fd6481cf 7857 * sizeof (struct omp_for_data_loop));
1a91d914 7858 extract_omp_for_data (as_a <gomp_for *> (last_stmt (region->entry)),
7859 &fd, loops);
f77459c5 7860 region->sched_kind = fd.sched_kind;
1e8e9920 7861
b3a3ddec 7862 gcc_assert (EDGE_COUNT (region->entry->succs) == 2);
7863 BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
7864 FALLTHRU_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
7865 if (region->cont)
7866 {
7867 gcc_assert (EDGE_COUNT (region->cont->succs) == 2);
7868 BRANCH_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
7869 FALLTHRU_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
7870 }
04c2922b 7871 else
75de4aa2 7872 /* If there isn't a continue then this is a degerate case where
04c2922b 7873 the introduction of abnormal edges during lowering will prevent
7874 original loops from being detected. Fix that up. */
7875 loops_state_set (LOOPS_NEED_FIXUP);
b3a3ddec 7876
10c55644 7877 if (gimple_omp_for_kind (fd.for_stmt) & GF_OMP_FOR_SIMD)
3d483a94 7878 expand_omp_simd (region, &fd);
40750995 7879 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
7880 expand_cilk_for (region, &fd);
3d483a94 7881 else if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
bc7bff74 7882 && !fd.have_ordered)
1e8e9920 7883 {
7884 if (fd.chunk_size == NULL)
bc7bff74 7885 expand_omp_for_static_nochunk (region, &fd, inner_stmt);
1e8e9920 7886 else
bc7bff74 7887 expand_omp_for_static_chunk (region, &fd, inner_stmt);
1e8e9920 7888 }
7889 else
7890 {
fd6481cf 7891 int fn_index, start_ix, next_ix;
7892
3d483a94 7893 gcc_assert (gimple_omp_for_kind (fd.for_stmt)
7894 == GF_OMP_FOR_KIND_FOR);
0416ca72 7895 if (fd.chunk_size == NULL
7896 && fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
7897 fd.chunk_size = integer_zero_node;
fd6481cf 7898 gcc_assert (fd.sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
7899 fn_index = (fd.sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
75a70cf9 7900 ? 3 : fd.sched_kind;
fd6481cf 7901 fn_index += fd.have_ordered * 4;
b9a16870 7902 start_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_START) + fn_index;
7903 next_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT) + fn_index;
fd6481cf 7904 if (fd.iter_type == long_long_unsigned_type_node)
7905 {
b9a16870 7906 start_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
7907 - (int)BUILT_IN_GOMP_LOOP_STATIC_START);
7908 next_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
7909 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT);
fd6481cf 7910 }
b9c74b4d 7911 expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
bc7bff74 7912 (enum built_in_function) next_ix, inner_stmt);
1e8e9920 7913 }
28c92cbb 7914
083152fb 7915 if (gimple_in_ssa_p (cfun))
7916 update_ssa (TODO_update_ssa_only_virtuals);
1e8e9920 7917}
7918
1e8e9920 7919
7920/* Expand code for an OpenMP sections directive. In pseudo code, we generate
7921
1e8e9920 7922 v = GOMP_sections_start (n);
7923 L0:
7924 switch (v)
7925 {
7926 case 0:
7927 goto L2;
7928 case 1:
7929 section 1;
7930 goto L1;
7931 case 2:
7932 ...
7933 case n:
7934 ...
1e8e9920 7935 default:
7936 abort ();
7937 }
7938 L1:
7939 v = GOMP_sections_next ();
7940 goto L0;
7941 L2:
7942 reduction;
7943
773c5ba7 7944 If this is a combined parallel sections, replace the call to
79acaae1 7945 GOMP_sections_start with call to GOMP_sections_next. */
1e8e9920 7946
7947static void
773c5ba7 7948expand_omp_sections (struct omp_region *region)
1e8e9920 7949{
f018d957 7950 tree t, u, vin = NULL, vmain, vnext, l2;
75a70cf9 7951 unsigned len;
ac6e3339 7952 basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
75a70cf9 7953 gimple_stmt_iterator si, switch_si;
1a91d914 7954 gomp_sections *sections_stmt;
7955 gimple stmt;
7956 gomp_continue *cont;
9884aaf8 7957 edge_iterator ei;
7958 edge e;
61e47ac8 7959 struct omp_region *inner;
75a70cf9 7960 unsigned i, casei;
ac6e3339 7961 bool exit_reachable = region->cont != NULL;
1e8e9920 7962
d244d9de 7963 gcc_assert (region->exit != NULL);
61e47ac8 7964 entry_bb = region->entry;
ac6e3339 7965 l0_bb = single_succ (entry_bb);
61e47ac8 7966 l1_bb = region->cont;
ac6e3339 7967 l2_bb = region->exit;
d244d9de 7968 if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
7969 l2 = gimple_block_label (l2_bb);
7970 else
03ed154b 7971 {
d244d9de 7972 /* This can happen if there are reductions. */
7973 len = EDGE_COUNT (l0_bb->succs);
7974 gcc_assert (len > 0);
7975 e = EDGE_SUCC (l0_bb, len - 1);
7976 si = gsi_last_bb (e->dest);
7977 l2 = NULL_TREE;
7978 if (gsi_end_p (si)
7979 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
7980 l2 = gimple_block_label (e->dest);
9884aaf8 7981 else
d244d9de 7982 FOR_EACH_EDGE (e, ei, l0_bb->succs)
7983 {
7984 si = gsi_last_bb (e->dest);
7985 if (gsi_end_p (si)
7986 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
9884aaf8 7987 {
d244d9de 7988 l2 = gimple_block_label (e->dest);
7989 break;
9884aaf8 7990 }
d244d9de 7991 }
03ed154b 7992 }
d244d9de 7993 if (exit_reachable)
7994 default_bb = create_empty_bb (l1_bb->prev_bb);
03ed154b 7995 else
d244d9de 7996 default_bb = create_empty_bb (l0_bb);
773c5ba7 7997
7998 /* We will build a switch() with enough cases for all the
75a70cf9 7999 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
773c5ba7 8000 and a default case to abort if something goes wrong. */
ac6e3339 8001 len = EDGE_COUNT (l0_bb->succs);
75a70cf9 8002
f1f41a6c 8003 /* Use vec::quick_push on label_vec throughout, since we know the size
75a70cf9 8004 in advance. */
c2078b80 8005 auto_vec<tree> label_vec (len);
1e8e9920 8006
61e47ac8 8007 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
75a70cf9 8008 GIMPLE_OMP_SECTIONS statement. */
8009 si = gsi_last_bb (entry_bb);
1a91d914 8010 sections_stmt = as_a <gomp_sections *> (gsi_stmt (si));
75a70cf9 8011 gcc_assert (gimple_code (sections_stmt) == GIMPLE_OMP_SECTIONS);
8012 vin = gimple_omp_sections_control (sections_stmt);
773c5ba7 8013 if (!is_combined_parallel (region))
1e8e9920 8014 {
773c5ba7 8015 /* If we are not inside a combined parallel+sections region,
8016 call GOMP_sections_start. */
39cb6d68 8017 t = build_int_cst (unsigned_type_node, len - 1);
b9a16870 8018 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START);
75a70cf9 8019 stmt = gimple_build_call (u, 1, t);
1e8e9920 8020 }
79acaae1 8021 else
8022 {
8023 /* Otherwise, call GOMP_sections_next. */
b9a16870 8024 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
75a70cf9 8025 stmt = gimple_build_call (u, 0);
79acaae1 8026 }
75a70cf9 8027 gimple_call_set_lhs (stmt, vin);
8028 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
8029 gsi_remove (&si, true);
8030
8031 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
8032 L0_BB. */
8033 switch_si = gsi_last_bb (l0_bb);
8034 gcc_assert (gimple_code (gsi_stmt (switch_si)) == GIMPLE_OMP_SECTIONS_SWITCH);
79acaae1 8035 if (exit_reachable)
8036 {
1a91d914 8037 cont = as_a <gomp_continue *> (last_stmt (l1_bb));
75a70cf9 8038 gcc_assert (gimple_code (cont) == GIMPLE_OMP_CONTINUE);
8039 vmain = gimple_omp_continue_control_use (cont);
8040 vnext = gimple_omp_continue_control_def (cont);
79acaae1 8041 }
8042 else
8043 {
8044 vmain = vin;
8045 vnext = NULL_TREE;
8046 }
1e8e9920 8047
d244d9de 8048 t = build_case_label (build_int_cst (unsigned_type_node, 0), NULL, l2);
f1f41a6c 8049 label_vec.quick_push (t);
d244d9de 8050 i = 1;
03ed154b 8051
75a70cf9 8052 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
ac6e3339 8053 for (inner = region->inner, casei = 1;
8054 inner;
8055 inner = inner->next, i++, casei++)
1e8e9920 8056 {
773c5ba7 8057 basic_block s_entry_bb, s_exit_bb;
8058
9884aaf8 8059 /* Skip optional reduction region. */
75a70cf9 8060 if (inner->type == GIMPLE_OMP_ATOMIC_LOAD)
9884aaf8 8061 {
8062 --i;
8063 --casei;
8064 continue;
8065 }
8066
61e47ac8 8067 s_entry_bb = inner->entry;
8068 s_exit_bb = inner->exit;
1e8e9920 8069
75a70cf9 8070 t = gimple_block_label (s_entry_bb);
ac6e3339 8071 u = build_int_cst (unsigned_type_node, casei);
b6e3dd65 8072 u = build_case_label (u, NULL, t);
f1f41a6c 8073 label_vec.quick_push (u);
61e47ac8 8074
75a70cf9 8075 si = gsi_last_bb (s_entry_bb);
8076 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SECTION);
8077 gcc_assert (i < len || gimple_omp_section_last_p (gsi_stmt (si)));
8078 gsi_remove (&si, true);
61e47ac8 8079 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
03ed154b 8080
8081 if (s_exit_bb == NULL)
8082 continue;
8083
75a70cf9 8084 si = gsi_last_bb (s_exit_bb);
8085 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
8086 gsi_remove (&si, true);
03ed154b 8087
773c5ba7 8088 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
1e8e9920 8089 }
8090
773c5ba7 8091 /* Error handling code goes in DEFAULT_BB. */
75a70cf9 8092 t = gimple_block_label (default_bb);
b6e3dd65 8093 u = build_case_label (NULL, NULL, t);
61e47ac8 8094 make_edge (l0_bb, default_bb, 0);
b3083327 8095 add_bb_to_loop (default_bb, current_loops->tree_root);
1e8e9920 8096
49a70175 8097 stmt = gimple_build_switch (vmain, u, label_vec);
75a70cf9 8098 gsi_insert_after (&switch_si, stmt, GSI_SAME_STMT);
8099 gsi_remove (&switch_si, true);
75a70cf9 8100
8101 si = gsi_start_bb (default_bb);
b9a16870 8102 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
75a70cf9 8103 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
773c5ba7 8104
ac6e3339 8105 if (exit_reachable)
03ed154b 8106 {
b9a16870 8107 tree bfn_decl;
8108
ac6e3339 8109 /* Code to get the next section goes in L1_BB. */
75a70cf9 8110 si = gsi_last_bb (l1_bb);
8111 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
1e8e9920 8112
b9a16870 8113 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
8114 stmt = gimple_build_call (bfn_decl, 0);
75a70cf9 8115 gimple_call_set_lhs (stmt, vnext);
8116 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
8117 gsi_remove (&si, true);
773c5ba7 8118
ac6e3339 8119 single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
03ed154b 8120 }
773c5ba7 8121
d244d9de 8122 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
8123 si = gsi_last_bb (l2_bb);
8124 if (gimple_omp_return_nowait_p (gsi_stmt (si)))
8125 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
bc7bff74 8126 else if (gimple_omp_return_lhs (gsi_stmt (si)))
8127 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL);
d244d9de 8128 else
8129 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
8130 stmt = gimple_build_call (t, 0);
bc7bff74 8131 if (gimple_omp_return_lhs (gsi_stmt (si)))
8132 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (si)));
d244d9de 8133 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
8134 gsi_remove (&si, true);
8135
79acaae1 8136 set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
773c5ba7 8137}
1e8e9920 8138
1e8e9920 8139
61e47ac8 8140/* Expand code for an OpenMP single directive. We've already expanded
8141 much of the code, here we simply place the GOMP_barrier call. */
8142
8143static void
8144expand_omp_single (struct omp_region *region)
8145{
8146 basic_block entry_bb, exit_bb;
75a70cf9 8147 gimple_stmt_iterator si;
61e47ac8 8148
8149 entry_bb = region->entry;
8150 exit_bb = region->exit;
8151
75a70cf9 8152 si = gsi_last_bb (entry_bb);
75a70cf9 8153 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE);
8154 gsi_remove (&si, true);
61e47ac8 8155 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
8156
75a70cf9 8157 si = gsi_last_bb (exit_bb);
bc7bff74 8158 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
8159 {
8160 tree t = gimple_omp_return_lhs (gsi_stmt (si));
8161 gsi_insert_after (&si, build_omp_barrier (t), GSI_SAME_STMT);
8162 }
75a70cf9 8163 gsi_remove (&si, true);
61e47ac8 8164 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
8165}
8166
8167
8168/* Generic expansion for OpenMP synchronization directives: master,
8169 ordered and critical. All we need to do here is remove the entry
8170 and exit markers for REGION. */
773c5ba7 8171
8172static void
8173expand_omp_synch (struct omp_region *region)
8174{
8175 basic_block entry_bb, exit_bb;
75a70cf9 8176 gimple_stmt_iterator si;
773c5ba7 8177
61e47ac8 8178 entry_bb = region->entry;
8179 exit_bb = region->exit;
773c5ba7 8180
75a70cf9 8181 si = gsi_last_bb (entry_bb);
8182 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE
8183 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASTER
bc7bff74 8184 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TASKGROUP
75a70cf9 8185 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ORDERED
bc7bff74 8186 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CRITICAL
8187 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TEAMS);
75a70cf9 8188 gsi_remove (&si, true);
773c5ba7 8189 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
8190
03ed154b 8191 if (exit_bb)
8192 {
75a70cf9 8193 si = gsi_last_bb (exit_bb);
8194 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
8195 gsi_remove (&si, true);
03ed154b 8196 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
8197 }
773c5ba7 8198}
1e8e9920 8199
2169f33b 8200/* A subroutine of expand_omp_atomic. Attempt to implement the atomic
8201 operation as a normal volatile load. */
8202
8203static bool
3ec11c49 8204expand_omp_atomic_load (basic_block load_bb, tree addr,
8205 tree loaded_val, int index)
2169f33b 8206{
3ec11c49 8207 enum built_in_function tmpbase;
8208 gimple_stmt_iterator gsi;
8209 basic_block store_bb;
8210 location_t loc;
8211 gimple stmt;
8212 tree decl, call, type, itype;
8213
8214 gsi = gsi_last_bb (load_bb);
8215 stmt = gsi_stmt (gsi);
8216 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
8217 loc = gimple_location (stmt);
8218
8219 /* ??? If the target does not implement atomic_load_optab[mode], and mode
8220 is smaller than word size, then expand_atomic_load assumes that the load
8221 is atomic. We could avoid the builtin entirely in this case. */
8222
8223 tmpbase = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
8224 decl = builtin_decl_explicit (tmpbase);
8225 if (decl == NULL_TREE)
8226 return false;
8227
8228 type = TREE_TYPE (loaded_val);
8229 itype = TREE_TYPE (TREE_TYPE (decl));
8230
8231 call = build_call_expr_loc (loc, decl, 2, addr,
bc7bff74 8232 build_int_cst (NULL,
8233 gimple_omp_atomic_seq_cst_p (stmt)
8234 ? MEMMODEL_SEQ_CST
8235 : MEMMODEL_RELAXED));
3ec11c49 8236 if (!useless_type_conversion_p (type, itype))
8237 call = fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
8238 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
8239
8240 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
8241 gsi_remove (&gsi, true);
8242
8243 store_bb = single_succ (load_bb);
8244 gsi = gsi_last_bb (store_bb);
8245 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
8246 gsi_remove (&gsi, true);
8247
8248 if (gimple_in_ssa_p (cfun))
8249 update_ssa (TODO_update_ssa_no_phi);
8250
8251 return true;
2169f33b 8252}
8253
8254/* A subroutine of expand_omp_atomic. Attempt to implement the atomic
8255 operation as a normal volatile store. */
8256
8257static bool
3ec11c49 8258expand_omp_atomic_store (basic_block load_bb, tree addr,
8259 tree loaded_val, tree stored_val, int index)
2169f33b 8260{
3ec11c49 8261 enum built_in_function tmpbase;
8262 gimple_stmt_iterator gsi;
8263 basic_block store_bb = single_succ (load_bb);
8264 location_t loc;
8265 gimple stmt;
8266 tree decl, call, type, itype;
3754d046 8267 machine_mode imode;
3ec11c49 8268 bool exchange;
8269
8270 gsi = gsi_last_bb (load_bb);
8271 stmt = gsi_stmt (gsi);
8272 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
8273
8274 /* If the load value is needed, then this isn't a store but an exchange. */
8275 exchange = gimple_omp_atomic_need_value_p (stmt);
8276
8277 gsi = gsi_last_bb (store_bb);
8278 stmt = gsi_stmt (gsi);
8279 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE);
8280 loc = gimple_location (stmt);
8281
8282 /* ??? If the target does not implement atomic_store_optab[mode], and mode
8283 is smaller than word size, then expand_atomic_store assumes that the store
8284 is atomic. We could avoid the builtin entirely in this case. */
8285
8286 tmpbase = (exchange ? BUILT_IN_ATOMIC_EXCHANGE_N : BUILT_IN_ATOMIC_STORE_N);
8287 tmpbase = (enum built_in_function) ((int) tmpbase + index + 1);
8288 decl = builtin_decl_explicit (tmpbase);
8289 if (decl == NULL_TREE)
8290 return false;
8291
8292 type = TREE_TYPE (stored_val);
8293
8294 /* Dig out the type of the function's second argument. */
8295 itype = TREE_TYPE (decl);
8296 itype = TYPE_ARG_TYPES (itype);
8297 itype = TREE_CHAIN (itype);
8298 itype = TREE_VALUE (itype);
8299 imode = TYPE_MODE (itype);
8300
8301 if (exchange && !can_atomic_exchange_p (imode, true))
8302 return false;
8303
8304 if (!useless_type_conversion_p (itype, type))
8305 stored_val = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, stored_val);
8306 call = build_call_expr_loc (loc, decl, 3, addr, stored_val,
bc7bff74 8307 build_int_cst (NULL,
8308 gimple_omp_atomic_seq_cst_p (stmt)
8309 ? MEMMODEL_SEQ_CST
8310 : MEMMODEL_RELAXED));
3ec11c49 8311 if (exchange)
8312 {
8313 if (!useless_type_conversion_p (type, itype))
8314 call = build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
8315 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
8316 }
8317
8318 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
8319 gsi_remove (&gsi, true);
8320
8321 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
8322 gsi = gsi_last_bb (load_bb);
8323 gsi_remove (&gsi, true);
8324
8325 if (gimple_in_ssa_p (cfun))
8326 update_ssa (TODO_update_ssa_no_phi);
8327
8328 return true;
2169f33b 8329}
8330
cb7f680b 8331/* A subroutine of expand_omp_atomic. Attempt to implement the atomic
1cd6e20d 8332 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
cb7f680b 8333 size of the data type, and thus usable to find the index of the builtin
8334 decl. Returns false if the expression is not of the proper form. */
8335
8336static bool
8337expand_omp_atomic_fetch_op (basic_block load_bb,
8338 tree addr, tree loaded_val,
8339 tree stored_val, int index)
8340{
b9a16870 8341 enum built_in_function oldbase, newbase, tmpbase;
cb7f680b 8342 tree decl, itype, call;
2169f33b 8343 tree lhs, rhs;
cb7f680b 8344 basic_block store_bb = single_succ (load_bb);
75a70cf9 8345 gimple_stmt_iterator gsi;
8346 gimple stmt;
389dd41b 8347 location_t loc;
1cd6e20d 8348 enum tree_code code;
2169f33b 8349 bool need_old, need_new;
3754d046 8350 machine_mode imode;
bc7bff74 8351 bool seq_cst;
cb7f680b 8352
8353 /* We expect to find the following sequences:
48e1416a 8354
cb7f680b 8355 load_bb:
75a70cf9 8356 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
cb7f680b 8357
8358 store_bb:
8359 val = tmp OP something; (or: something OP tmp)
48e1416a 8360 GIMPLE_OMP_STORE (val)
cb7f680b 8361
48e1416a 8362 ???FIXME: Allow a more flexible sequence.
cb7f680b 8363 Perhaps use data flow to pick the statements.
48e1416a 8364
cb7f680b 8365 */
8366
75a70cf9 8367 gsi = gsi_after_labels (store_bb);
8368 stmt = gsi_stmt (gsi);
389dd41b 8369 loc = gimple_location (stmt);
75a70cf9 8370 if (!is_gimple_assign (stmt))
cb7f680b 8371 return false;
75a70cf9 8372 gsi_next (&gsi);
8373 if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE)
cb7f680b 8374 return false;
2169f33b 8375 need_new = gimple_omp_atomic_need_value_p (gsi_stmt (gsi));
8376 need_old = gimple_omp_atomic_need_value_p (last_stmt (load_bb));
bc7bff74 8377 seq_cst = gimple_omp_atomic_seq_cst_p (last_stmt (load_bb));
2169f33b 8378 gcc_checking_assert (!need_old || !need_new);
cb7f680b 8379
75a70cf9 8380 if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
cb7f680b 8381 return false;
8382
cb7f680b 8383 /* Check for one of the supported fetch-op operations. */
1cd6e20d 8384 code = gimple_assign_rhs_code (stmt);
8385 switch (code)
cb7f680b 8386 {
8387 case PLUS_EXPR:
8388 case POINTER_PLUS_EXPR:
1cd6e20d 8389 oldbase = BUILT_IN_ATOMIC_FETCH_ADD_N;
8390 newbase = BUILT_IN_ATOMIC_ADD_FETCH_N;
cb7f680b 8391 break;
8392 case MINUS_EXPR:
1cd6e20d 8393 oldbase = BUILT_IN_ATOMIC_FETCH_SUB_N;
8394 newbase = BUILT_IN_ATOMIC_SUB_FETCH_N;
cb7f680b 8395 break;
8396 case BIT_AND_EXPR:
1cd6e20d 8397 oldbase = BUILT_IN_ATOMIC_FETCH_AND_N;
8398 newbase = BUILT_IN_ATOMIC_AND_FETCH_N;
cb7f680b 8399 break;
8400 case BIT_IOR_EXPR:
1cd6e20d 8401 oldbase = BUILT_IN_ATOMIC_FETCH_OR_N;
8402 newbase = BUILT_IN_ATOMIC_OR_FETCH_N;
cb7f680b 8403 break;
8404 case BIT_XOR_EXPR:
1cd6e20d 8405 oldbase = BUILT_IN_ATOMIC_FETCH_XOR_N;
8406 newbase = BUILT_IN_ATOMIC_XOR_FETCH_N;
cb7f680b 8407 break;
8408 default:
8409 return false;
8410 }
1cd6e20d 8411
cb7f680b 8412 /* Make sure the expression is of the proper form. */
75a70cf9 8413 if (operand_equal_p (gimple_assign_rhs1 (stmt), loaded_val, 0))
8414 rhs = gimple_assign_rhs2 (stmt);
8415 else if (commutative_tree_code (gimple_assign_rhs_code (stmt))
8416 && operand_equal_p (gimple_assign_rhs2 (stmt), loaded_val, 0))
8417 rhs = gimple_assign_rhs1 (stmt);
cb7f680b 8418 else
8419 return false;
8420
b9a16870 8421 tmpbase = ((enum built_in_function)
8422 ((need_new ? newbase : oldbase) + index + 1));
8423 decl = builtin_decl_explicit (tmpbase);
0f94f46b 8424 if (decl == NULL_TREE)
8425 return false;
cb7f680b 8426 itype = TREE_TYPE (TREE_TYPE (decl));
1cd6e20d 8427 imode = TYPE_MODE (itype);
cb7f680b 8428
1cd6e20d 8429 /* We could test all of the various optabs involved, but the fact of the
8430 matter is that (with the exception of i486 vs i586 and xadd) all targets
8431 that support any atomic operaton optab also implements compare-and-swap.
8432 Let optabs.c take care of expanding any compare-and-swap loop. */
29139cdc 8433 if (!can_compare_and_swap_p (imode, true))
cb7f680b 8434 return false;
8435
75a70cf9 8436 gsi = gsi_last_bb (load_bb);
8437 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
1cd6e20d 8438
8439 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
8440 It only requires that the operation happen atomically. Thus we can
8441 use the RELAXED memory model. */
8442 call = build_call_expr_loc (loc, decl, 3, addr,
8443 fold_convert_loc (loc, itype, rhs),
bc7bff74 8444 build_int_cst (NULL,
8445 seq_cst ? MEMMODEL_SEQ_CST
8446 : MEMMODEL_RELAXED));
1cd6e20d 8447
2169f33b 8448 if (need_old || need_new)
8449 {
8450 lhs = need_old ? loaded_val : stored_val;
8451 call = fold_convert_loc (loc, TREE_TYPE (lhs), call);
8452 call = build2_loc (loc, MODIFY_EXPR, void_type_node, lhs, call);
8453 }
8454 else
8455 call = fold_convert_loc (loc, void_type_node, call);
75a70cf9 8456 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
8457 gsi_remove (&gsi, true);
cb7f680b 8458
75a70cf9 8459 gsi = gsi_last_bb (store_bb);
8460 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
8461 gsi_remove (&gsi, true);
8462 gsi = gsi_last_bb (store_bb);
8463 gsi_remove (&gsi, true);
cb7f680b 8464
8465 if (gimple_in_ssa_p (cfun))
8466 update_ssa (TODO_update_ssa_no_phi);
8467
8468 return true;
8469}
8470
8471/* A subroutine of expand_omp_atomic. Implement the atomic operation as:
8472
8473 oldval = *addr;
8474 repeat:
8475 newval = rhs; // with oldval replacing *addr in rhs
8476 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
8477 if (oldval != newval)
8478 goto repeat;
8479
8480 INDEX is log2 of the size of the data type, and thus usable to find the
8481 index of the builtin decl. */
8482
8483static bool
8484expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
8485 tree addr, tree loaded_val, tree stored_val,
8486 int index)
8487{
790368c5 8488 tree loadedi, storedi, initial, new_storedi, old_vali;
cb7f680b 8489 tree type, itype, cmpxchg, iaddr;
75a70cf9 8490 gimple_stmt_iterator si;
cb7f680b 8491 basic_block loop_header = single_succ (load_bb);
75a70cf9 8492 gimple phi, stmt;
cb7f680b 8493 edge e;
b9a16870 8494 enum built_in_function fncode;
cb7f680b 8495
1cd6e20d 8496 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
8497 order to use the RELAXED memory model effectively. */
b9a16870 8498 fncode = (enum built_in_function)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
8499 + index + 1);
8500 cmpxchg = builtin_decl_explicit (fncode);
0f94f46b 8501 if (cmpxchg == NULL_TREE)
8502 return false;
cb7f680b 8503 type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
8504 itype = TREE_TYPE (TREE_TYPE (cmpxchg));
8505
29139cdc 8506 if (!can_compare_and_swap_p (TYPE_MODE (itype), true))
cb7f680b 8507 return false;
8508
75a70cf9 8509 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
8510 si = gsi_last_bb (load_bb);
8511 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
8512
790368c5 8513 /* For floating-point values, we'll need to view-convert them to integers
8514 so that we can perform the atomic compare and swap. Simplify the
8515 following code by always setting up the "i"ntegral variables. */
8516 if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
8517 {
75a70cf9 8518 tree iaddr_val;
8519
072f7ab1 8520 iaddr = create_tmp_reg (build_pointer_type_for_mode (itype, ptr_mode,
f9e245b2 8521 true));
75a70cf9 8522 iaddr_val
8523 = force_gimple_operand_gsi (&si,
8524 fold_convert (TREE_TYPE (iaddr), addr),
8525 false, NULL_TREE, true, GSI_SAME_STMT);
8526 stmt = gimple_build_assign (iaddr, iaddr_val);
8527 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
f9e245b2 8528 loadedi = create_tmp_var (itype);
790368c5 8529 if (gimple_in_ssa_p (cfun))
f9e245b2 8530 loadedi = make_ssa_name (loadedi);
790368c5 8531 }
8532 else
8533 {
8534 iaddr = addr;
8535 loadedi = loaded_val;
8536 }
75a70cf9 8537
2ed72821 8538 fncode = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
8539 tree loaddecl = builtin_decl_explicit (fncode);
8540 if (loaddecl)
8541 initial
8542 = fold_convert (TREE_TYPE (TREE_TYPE (iaddr)),
8543 build_call_expr (loaddecl, 2, iaddr,
8544 build_int_cst (NULL_TREE,
8545 MEMMODEL_RELAXED)));
8546 else
8547 initial = build2 (MEM_REF, TREE_TYPE (TREE_TYPE (iaddr)), iaddr,
8548 build_int_cst (TREE_TYPE (iaddr), 0));
8549
182cf5a9 8550 initial
2ed72821 8551 = force_gimple_operand_gsi (&si, initial, true, NULL_TREE, true,
8552 GSI_SAME_STMT);
790368c5 8553
8554 /* Move the value to the LOADEDI temporary. */
cb7f680b 8555 if (gimple_in_ssa_p (cfun))
8556 {
75a70cf9 8557 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header)));
790368c5 8558 phi = create_phi_node (loadedi, loop_header);
cb7f680b 8559 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)),
8560 initial);
8561 }
8562 else
75a70cf9 8563 gsi_insert_before (&si,
8564 gimple_build_assign (loadedi, initial),
8565 GSI_SAME_STMT);
790368c5 8566 if (loadedi != loaded_val)
8567 {
75a70cf9 8568 gimple_stmt_iterator gsi2;
8569 tree x;
790368c5 8570
8571 x = build1 (VIEW_CONVERT_EXPR, type, loadedi);
75a70cf9 8572 gsi2 = gsi_start_bb (loop_header);
790368c5 8573 if (gimple_in_ssa_p (cfun))
8574 {
1a91d914 8575 gassign *stmt;
75a70cf9 8576 x = force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
8577 true, GSI_SAME_STMT);
8578 stmt = gimple_build_assign (loaded_val, x);
8579 gsi_insert_before (&gsi2, stmt, GSI_SAME_STMT);
790368c5 8580 }
8581 else
8582 {
75a70cf9 8583 x = build2 (MODIFY_EXPR, TREE_TYPE (loaded_val), loaded_val, x);
8584 force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
8585 true, GSI_SAME_STMT);
790368c5 8586 }
8587 }
75a70cf9 8588 gsi_remove (&si, true);
cb7f680b 8589
75a70cf9 8590 si = gsi_last_bb (store_bb);
8591 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
cb7f680b 8592
790368c5 8593 if (iaddr == addr)
8594 storedi = stored_val;
cb7f680b 8595 else
790368c5 8596 storedi =
75a70cf9 8597 force_gimple_operand_gsi (&si,
790368c5 8598 build1 (VIEW_CONVERT_EXPR, itype,
8599 stored_val), true, NULL_TREE, true,
75a70cf9 8600 GSI_SAME_STMT);
cb7f680b 8601
8602 /* Build the compare&swap statement. */
8603 new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi);
75a70cf9 8604 new_storedi = force_gimple_operand_gsi (&si,
87f9ffa4 8605 fold_convert (TREE_TYPE (loadedi),
8606 new_storedi),
cb7f680b 8607 true, NULL_TREE,
75a70cf9 8608 true, GSI_SAME_STMT);
cb7f680b 8609
8610 if (gimple_in_ssa_p (cfun))
8611 old_vali = loadedi;
8612 else
8613 {
f9e245b2 8614 old_vali = create_tmp_var (TREE_TYPE (loadedi));
75a70cf9 8615 stmt = gimple_build_assign (old_vali, loadedi);
8616 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
cb7f680b 8617
75a70cf9 8618 stmt = gimple_build_assign (loadedi, new_storedi);
8619 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
cb7f680b 8620 }
8621
8622 /* Note that we always perform the comparison as an integer, even for
48e1416a 8623 floating point. This allows the atomic operation to properly
cb7f680b 8624 succeed even with NaNs and -0.0. */
75a70cf9 8625 stmt = gimple_build_cond_empty
8626 (build2 (NE_EXPR, boolean_type_node,
8627 new_storedi, old_vali));
8628 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
cb7f680b 8629
8630 /* Update cfg. */
8631 e = single_succ_edge (store_bb);
8632 e->flags &= ~EDGE_FALLTHRU;
8633 e->flags |= EDGE_FALSE_VALUE;
8634
8635 e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE);
8636
790368c5 8637 /* Copy the new value to loadedi (we already did that before the condition
cb7f680b 8638 if we are not in SSA). */
8639 if (gimple_in_ssa_p (cfun))
8640 {
75a70cf9 8641 phi = gimple_seq_first_stmt (phi_nodes (loop_header));
790368c5 8642 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), new_storedi);
cb7f680b 8643 }
8644
75a70cf9 8645 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
8646 gsi_remove (&si, true);
cb7f680b 8647
04c2922b 8648 struct loop *loop = alloc_loop ();
8649 loop->header = loop_header;
5f037457 8650 loop->latch = store_bb;
04c2922b 8651 add_loop (loop, loop_header->loop_father);
8652
cb7f680b 8653 if (gimple_in_ssa_p (cfun))
8654 update_ssa (TODO_update_ssa_no_phi);
8655
8656 return true;
8657}
8658
8659/* A subroutine of expand_omp_atomic. Implement the atomic operation as:
8660
8661 GOMP_atomic_start ();
8662 *addr = rhs;
8663 GOMP_atomic_end ();
8664
8665 The result is not globally atomic, but works so long as all parallel
8666 references are within #pragma omp atomic directives. According to
8667 responses received from omp@openmp.org, appears to be within spec.
8668 Which makes sense, since that's how several other compilers handle
48e1416a 8669 this situation as well.
75a70cf9 8670 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
8671 expanding. STORED_VAL is the operand of the matching
8672 GIMPLE_OMP_ATOMIC_STORE.
cb7f680b 8673
48e1416a 8674 We replace
8675 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
cb7f680b 8676 loaded_val = *addr;
8677
8678 and replace
3ec11c49 8679 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
48e1416a 8680 *addr = stored_val;
cb7f680b 8681*/
8682
8683static bool
8684expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
8685 tree addr, tree loaded_val, tree stored_val)
8686{
75a70cf9 8687 gimple_stmt_iterator si;
1a91d914 8688 gassign *stmt;
cb7f680b 8689 tree t;
8690
75a70cf9 8691 si = gsi_last_bb (load_bb);
8692 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
cb7f680b 8693
b9a16870 8694 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
414c3a2c 8695 t = build_call_expr (t, 0);
75a70cf9 8696 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
cb7f680b 8697
182cf5a9 8698 stmt = gimple_build_assign (loaded_val, build_simple_mem_ref (addr));
75a70cf9 8699 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8700 gsi_remove (&si, true);
cb7f680b 8701
75a70cf9 8702 si = gsi_last_bb (store_bb);
8703 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
cb7f680b 8704
182cf5a9 8705 stmt = gimple_build_assign (build_simple_mem_ref (unshare_expr (addr)),
8706 stored_val);
75a70cf9 8707 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
cb7f680b 8708
b9a16870 8709 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
414c3a2c 8710 t = build_call_expr (t, 0);
75a70cf9 8711 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
8712 gsi_remove (&si, true);
cb7f680b 8713
8714 if (gimple_in_ssa_p (cfun))
8715 update_ssa (TODO_update_ssa_no_phi);
8716 return true;
8717}
8718
48e1416a 8719/* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
8720 using expand_omp_atomic_fetch_op. If it failed, we try to
cb7f680b 8721 call expand_omp_atomic_pipeline, and if it fails too, the
8722 ultimate fallback is wrapping the operation in a mutex
48e1416a 8723 (expand_omp_atomic_mutex). REGION is the atomic region built
8724 by build_omp_regions_1(). */
cb7f680b 8725
8726static void
8727expand_omp_atomic (struct omp_region *region)
8728{
8729 basic_block load_bb = region->entry, store_bb = region->exit;
1a91d914 8730 gomp_atomic_load *load = as_a <gomp_atomic_load *> (last_stmt (load_bb));
8731 gomp_atomic_store *store = as_a <gomp_atomic_store *> (last_stmt (store_bb));
75a70cf9 8732 tree loaded_val = gimple_omp_atomic_load_lhs (load);
8733 tree addr = gimple_omp_atomic_load_rhs (load);
8734 tree stored_val = gimple_omp_atomic_store_val (store);
cb7f680b 8735 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
8736 HOST_WIDE_INT index;
8737
8738 /* Make sure the type is one of the supported sizes. */
e913b5cd 8739 index = tree_to_uhwi (TYPE_SIZE_UNIT (type));
cb7f680b 8740 index = exact_log2 (index);
8741 if (index >= 0 && index <= 4)
8742 {
8743 unsigned int align = TYPE_ALIGN_UNIT (type);
8744
8745 /* __sync builtins require strict data alignment. */
dcf7024c 8746 if (exact_log2 (align) >= index)
cb7f680b 8747 {
3ec11c49 8748 /* Atomic load. */
2169f33b 8749 if (loaded_val == stored_val
8750 && (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
8751 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
8752 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
3ec11c49 8753 && expand_omp_atomic_load (load_bb, addr, loaded_val, index))
2169f33b 8754 return;
8755
3ec11c49 8756 /* Atomic store. */
2169f33b 8757 if ((GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
8758 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
8759 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
8760 && store_bb == single_succ (load_bb)
8761 && first_stmt (store_bb) == store
3ec11c49 8762 && expand_omp_atomic_store (load_bb, addr, loaded_val,
8763 stored_val, index))
2169f33b 8764 return;
8765
cb7f680b 8766 /* When possible, use specialized atomic update functions. */
8767 if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
3ec11c49 8768 && store_bb == single_succ (load_bb)
8769 && expand_omp_atomic_fetch_op (load_bb, addr,
8770 loaded_val, stored_val, index))
8771 return;
cb7f680b 8772
8773 /* If we don't have specialized __sync builtins, try and implement
8774 as a compare and swap loop. */
8775 if (expand_omp_atomic_pipeline (load_bb, store_bb, addr,
8776 loaded_val, stored_val, index))
8777 return;
8778 }
8779 }
8780
8781 /* The ultimate fallback is wrapping the operation in a mutex. */
8782 expand_omp_atomic_mutex (load_bb, store_bb, addr, loaded_val, stored_val);
8783}
8784
1e8e9920 8785
ca4c3545 8786/* Expand the GIMPLE_OMP_TARGET starting at REGION. */
773c5ba7 8787
8788static void
bc7bff74 8789expand_omp_target (struct omp_region *region)
773c5ba7 8790{
bc7bff74 8791 basic_block entry_bb, exit_bb, new_bb;
ca4c3545 8792 struct function *child_cfun;
8793 tree child_fn, block, t;
bc7bff74 8794 gimple_stmt_iterator gsi;
1a91d914 8795 gomp_target *entry_stmt;
8796 gimple stmt;
bc7bff74 8797 edge e;
ca4c3545 8798 bool offloaded, data_region;
bc7bff74 8799
1a91d914 8800 entry_stmt = as_a <gomp_target *> (last_stmt (region->entry));
bc7bff74 8801 new_bb = region->entry;
ca4c3545 8802
8803 offloaded = is_gimple_omp_offloaded (entry_stmt);
8804 switch (gimple_omp_target_kind (entry_stmt))
8805 {
8806 case GF_OMP_TARGET_KIND_REGION:
8807 case GF_OMP_TARGET_KIND_UPDATE:
8808 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
8809 case GF_OMP_TARGET_KIND_OACC_KERNELS:
8810 case GF_OMP_TARGET_KIND_OACC_UPDATE:
8811 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
8812 data_region = false;
8813 break;
8814 case GF_OMP_TARGET_KIND_DATA:
8815 case GF_OMP_TARGET_KIND_OACC_DATA:
8816 data_region = true;
8817 break;
8818 default:
8819 gcc_unreachable ();
8820 }
8821
8822 child_fn = NULL_TREE;
8823 child_cfun = NULL;
8824 if (offloaded)
bc7bff74 8825 {
8826 child_fn = gimple_omp_target_child_fn (entry_stmt);
8827 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
8828 }
8829
ca4c3545 8830 /* Supported by expand_omp_taskreg, but not here. */
8831 if (child_cfun != NULL)
8832 gcc_checking_assert (!child_cfun->cfg);
8833 gcc_checking_assert (!gimple_in_ssa_p (cfun));
8834
bc7bff74 8835 entry_bb = region->entry;
8836 exit_bb = region->exit;
8837
ca4c3545 8838 if (offloaded)
bc7bff74 8839 {
8840 unsigned srcidx, dstidx, num;
8841
ca4c3545 8842 /* If the offloading region needs data sent from the parent
bc7bff74 8843 function, then the very first statement (except possible
ca4c3545 8844 tree profile counter updates) of the offloading body
bc7bff74 8845 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
8846 &.OMP_DATA_O is passed as an argument to the child function,
8847 we need to replace it with the argument as seen by the child
8848 function.
8849
8850 In most cases, this will end up being the identity assignment
ca4c3545 8851 .OMP_DATA_I = .OMP_DATA_I. However, if the offloading body had
bc7bff74 8852 a function call that has been inlined, the original PARM_DECL
8853 .OMP_DATA_I may have been converted into a different local
8854 variable. In which case, we need to keep the assignment. */
ca4c3545 8855 tree data_arg = gimple_omp_target_data_arg (entry_stmt);
8856 if (data_arg)
bc7bff74 8857 {
8858 basic_block entry_succ_bb = single_succ (entry_bb);
8859 gimple_stmt_iterator gsi;
8860 tree arg;
8861 gimple tgtcopy_stmt = NULL;
ca4c3545 8862 tree sender = TREE_VEC_ELT (data_arg, 0);
bc7bff74 8863
8864 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
8865 {
8866 gcc_assert (!gsi_end_p (gsi));
8867 stmt = gsi_stmt (gsi);
8868 if (gimple_code (stmt) != GIMPLE_ASSIGN)
8869 continue;
8870
8871 if (gimple_num_ops (stmt) == 2)
8872 {
8873 tree arg = gimple_assign_rhs1 (stmt);
8874
8875 /* We're ignoring the subcode because we're
8876 effectively doing a STRIP_NOPS. */
8877
8878 if (TREE_CODE (arg) == ADDR_EXPR
8879 && TREE_OPERAND (arg, 0) == sender)
8880 {
8881 tgtcopy_stmt = stmt;
8882 break;
8883 }
8884 }
8885 }
8886
8887 gcc_assert (tgtcopy_stmt != NULL);
8888 arg = DECL_ARGUMENTS (child_fn);
8889
8890 gcc_assert (gimple_assign_lhs (tgtcopy_stmt) == arg);
8891 gsi_remove (&gsi, true);
8892 }
8893
8894 /* Declare local variables needed in CHILD_CFUN. */
8895 block = DECL_INITIAL (child_fn);
8896 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
ca4c3545 8897 /* The gimplifier could record temporaries in the offloading block
bc7bff74 8898 rather than in containing function's local_decls chain,
8899 which would mean cgraph missed finalizing them. Do it now. */
8900 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
8901 if (TREE_CODE (t) == VAR_DECL
8902 && TREE_STATIC (t)
8903 && !DECL_EXTERNAL (t))
97221fd7 8904 varpool_node::finalize_decl (t);
bc7bff74 8905 DECL_SAVED_TREE (child_fn) = NULL;
8906 /* We'll create a CFG for child_fn, so no gimple body is needed. */
8907 gimple_set_body (child_fn, NULL);
8908 TREE_USED (block) = 1;
8909
8910 /* Reset DECL_CONTEXT on function arguments. */
8911 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
8912 DECL_CONTEXT (t) = child_fn;
8913
ca4c3545 8914 /* Split ENTRY_BB at GIMPLE_*,
bc7bff74 8915 so that it can be moved to the child function. */
8916 gsi = gsi_last_bb (entry_bb);
8917 stmt = gsi_stmt (gsi);
ca4c3545 8918 gcc_assert (stmt
8919 && gimple_code (stmt) == gimple_code (entry_stmt));
bc7bff74 8920 e = split_block (entry_bb, stmt);
923635e7 8921 gsi_remove (&gsi, true);
bc7bff74 8922 entry_bb = e->dest;
8923 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
8924
8925 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
8926 if (exit_bb)
8927 {
8928 gsi = gsi_last_bb (exit_bb);
8929 gcc_assert (!gsi_end_p (gsi)
8930 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
8931 stmt = gimple_build_return (NULL);
8932 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
8933 gsi_remove (&gsi, true);
8934 }
8935
ca4c3545 8936 /* Move the offloading region into CHILD_CFUN. */
bc7bff74 8937
8938 block = gimple_block (entry_stmt);
8939
8940 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
8941 if (exit_bb)
8942 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
8943 /* When the OMP expansion process cannot guarantee an up-to-date
8944 loop tree arrange for the child function to fixup loops. */
8945 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
8946 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
8947
8948 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
8949 num = vec_safe_length (child_cfun->local_decls);
8950 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
8951 {
8952 t = (*child_cfun->local_decls)[srcidx];
8953 if (DECL_CONTEXT (t) == cfun->decl)
8954 continue;
8955 if (srcidx != dstidx)
8956 (*child_cfun->local_decls)[dstidx] = t;
8957 dstidx++;
8958 }
8959 if (dstidx != num)
8960 vec_safe_truncate (child_cfun->local_decls, dstidx);
8961
8962 /* Inform the callgraph about the new function. */
8963 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
6a77ed3d 8964 cgraph_node *node = cgraph_node::get_create (child_fn);
8965 node->parallelized_function = 1;
415d1b9a 8966 cgraph_node::add_new_function (child_fn, true);
bc7bff74 8967
7114ebdd 8968#ifdef ENABLE_OFFLOADING
dccabdd1 8969 /* Add the new function to the offload table. */
8970 vec_safe_push (offload_funcs, child_fn);
7114ebdd 8971#endif
dccabdd1 8972
bc7bff74 8973 /* Fix the callgraph edges for child_cfun. Those for cfun will be
8974 fixed in a following pass. */
8975 push_cfun (child_cfun);
35ee1c66 8976 cgraph_edge::rebuild_edges ();
bc7bff74 8977
7114ebdd 8978#ifdef ENABLE_OFFLOADING
b0c5e347 8979 /* Prevent IPA from removing child_fn as unreachable, since there are no
8980 refs from the parent function to child_fn in offload LTO mode. */
569b71d0 8981 cgraph_node::get (child_fn)->mark_force_output ();
7114ebdd 8982#endif
b0c5e347 8983
bc7bff74 8984 /* Some EH regions might become dead, see PR34608. If
8985 pass_cleanup_cfg isn't the first pass to happen with the
8986 new child, these dead EH edges might cause problems.
8987 Clean them up now. */
8988 if (flag_exceptions)
8989 {
8990 basic_block bb;
8991 bool changed = false;
8992
fc00614f 8993 FOR_EACH_BB_FN (bb, cfun)
bc7bff74 8994 changed |= gimple_purge_dead_eh_edges (bb);
8995 if (changed)
8996 cleanup_tree_cfg ();
8997 }
8998 pop_cfun ();
8999 }
9000
ca4c3545 9001 /* Emit a library call to launch the offloading region, or do data
bc7bff74 9002 transfers. */
9003 tree t1, t2, t3, t4, device, cond, c, clauses;
9004 enum built_in_function start_ix;
9005 location_t clause_loc;
9006
ca4c3545 9007 switch (gimple_omp_target_kind (entry_stmt))
9008 {
9009 case GF_OMP_TARGET_KIND_REGION:
9010 start_ix = BUILT_IN_GOMP_TARGET;
9011 break;
9012 case GF_OMP_TARGET_KIND_DATA:
9013 start_ix = BUILT_IN_GOMP_TARGET_DATA;
9014 break;
9015 case GF_OMP_TARGET_KIND_UPDATE:
9016 start_ix = BUILT_IN_GOMP_TARGET_UPDATE;
9017 break;
9018 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
9019 case GF_OMP_TARGET_KIND_OACC_KERNELS:
9020 start_ix = BUILT_IN_GOACC_PARALLEL;
9021 break;
9022 case GF_OMP_TARGET_KIND_OACC_DATA:
9023 start_ix = BUILT_IN_GOACC_DATA_START;
9024 break;
9025 case GF_OMP_TARGET_KIND_OACC_UPDATE:
9026 start_ix = BUILT_IN_GOACC_UPDATE;
9027 break;
9028 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
9029 start_ix = BUILT_IN_GOACC_ENTER_EXIT_DATA;
9030 break;
9031 default:
9032 gcc_unreachable ();
9033 }
bc7bff74 9034
ca4c3545 9035 clauses = gimple_omp_target_clauses (entry_stmt);
bc7bff74 9036
ca4c3545 9037 /* By default, the value of DEVICE is GOMP_DEVICE_ICV (let runtime
9038 library choose) and there is no conditional. */
bc7bff74 9039 cond = NULL_TREE;
ca4c3545 9040 device = build_int_cst (integer_type_node, GOMP_DEVICE_ICV);
bc7bff74 9041
9042 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
9043 if (c)
9044 cond = OMP_CLAUSE_IF_EXPR (c);
9045
9046 c = find_omp_clause (clauses, OMP_CLAUSE_DEVICE);
9047 if (c)
9048 {
ca4c3545 9049 /* Even if we pass it to all library function calls, it is currently only
9050 defined/used for the OpenMP target ones. */
9051 gcc_checking_assert (start_ix == BUILT_IN_GOMP_TARGET
9052 || start_ix == BUILT_IN_GOMP_TARGET_DATA
9053 || start_ix == BUILT_IN_GOMP_TARGET_UPDATE);
9054
bc7bff74 9055 device = OMP_CLAUSE_DEVICE_ID (c);
9056 clause_loc = OMP_CLAUSE_LOCATION (c);
9057 }
9058 else
9059 clause_loc = gimple_location (entry_stmt);
9060
9061 /* Ensure 'device' is of the correct type. */
9062 device = fold_convert_loc (clause_loc, integer_type_node, device);
9063
9064 /* If we found the clause 'if (cond)', build
ca4c3545 9065 (cond ? device : GOMP_DEVICE_HOST_FALLBACK). */
bc7bff74 9066 if (cond)
9067 {
9068 cond = gimple_boolify (cond);
9069
9070 basic_block cond_bb, then_bb, else_bb;
9071 edge e;
9072 tree tmp_var;
9073
f9e245b2 9074 tmp_var = create_tmp_var (TREE_TYPE (device));
ca4c3545 9075 if (offloaded)
4302d619 9076 e = split_block_after_labels (new_bb);
ca4c3545 9077 else
bc7bff74 9078 {
9079 gsi = gsi_last_bb (new_bb);
9080 gsi_prev (&gsi);
9081 e = split_block (new_bb, gsi_stmt (gsi));
9082 }
bc7bff74 9083 cond_bb = e->src;
9084 new_bb = e->dest;
9085 remove_edge (e);
9086
9087 then_bb = create_empty_bb (cond_bb);
9088 else_bb = create_empty_bb (then_bb);
9089 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
9090 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
9091
9092 stmt = gimple_build_cond_empty (cond);
9093 gsi = gsi_last_bb (cond_bb);
9094 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
9095
9096 gsi = gsi_start_bb (then_bb);
9097 stmt = gimple_build_assign (tmp_var, device);
9098 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
9099
9100 gsi = gsi_start_bb (else_bb);
9101 stmt = gimple_build_assign (tmp_var,
ca4c3545 9102 build_int_cst (integer_type_node,
9103 GOMP_DEVICE_HOST_FALLBACK));
bc7bff74 9104 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
9105
9106 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
9107 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
b3083327 9108 add_bb_to_loop (then_bb, cond_bb->loop_father);
9109 add_bb_to_loop (else_bb, cond_bb->loop_father);
bc7bff74 9110 make_edge (then_bb, new_bb, EDGE_FALLTHRU);
9111 make_edge (else_bb, new_bb, EDGE_FALLTHRU);
9112
9113 device = tmp_var;
9114 }
9115
9116 gsi = gsi_last_bb (new_bb);
9117 t = gimple_omp_target_data_arg (entry_stmt);
9118 if (t == NULL)
9119 {
9120 t1 = size_zero_node;
9121 t2 = build_zero_cst (ptr_type_node);
9122 t3 = t2;
9123 t4 = t2;
9124 }
9125 else
9126 {
9127 t1 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t, 1))));
9128 t1 = size_binop (PLUS_EXPR, t1, size_int (1));
9129 t2 = build_fold_addr_expr (TREE_VEC_ELT (t, 0));
9130 t3 = build_fold_addr_expr (TREE_VEC_ELT (t, 1));
9131 t4 = build_fold_addr_expr (TREE_VEC_ELT (t, 2));
9132 }
9133
9134 gimple g;
ca4c3545 9135 /* The maximum number used by any start_ix, without varargs. */
02c05c9b 9136 auto_vec<tree, 11> args;
9137 args.quick_push (device);
ca4c3545 9138 if (offloaded)
02c05c9b 9139 args.quick_push (build_fold_addr_expr (child_fn));
dc19c8fd 9140 switch (start_ix)
9141 {
9142 case BUILT_IN_GOMP_TARGET:
9143 case BUILT_IN_GOMP_TARGET_DATA:
9144 case BUILT_IN_GOMP_TARGET_UPDATE:
9145 /* This const void * is part of the current ABI, but we're not actually
9146 using it. */
02c05c9b 9147 args.quick_push (build_zero_cst (ptr_type_node));
dc19c8fd 9148 break;
9149 case BUILT_IN_GOACC_DATA_START:
9150 case BUILT_IN_GOACC_ENTER_EXIT_DATA:
9151 case BUILT_IN_GOACC_PARALLEL:
9152 case BUILT_IN_GOACC_UPDATE:
9153 break;
9154 default:
9155 gcc_unreachable ();
9156 }
02c05c9b 9157 args.quick_push (t1);
9158 args.quick_push (t2);
9159 args.quick_push (t3);
9160 args.quick_push (t4);
ca4c3545 9161 switch (start_ix)
9162 {
9163 case BUILT_IN_GOACC_DATA_START:
9164 case BUILT_IN_GOMP_TARGET:
9165 case BUILT_IN_GOMP_TARGET_DATA:
9166 case BUILT_IN_GOMP_TARGET_UPDATE:
9167 break;
9168 case BUILT_IN_GOACC_PARALLEL:
9169 {
9170 tree t_num_gangs, t_num_workers, t_vector_length;
9171
9172 /* Default values for num_gangs, num_workers, and vector_length. */
9173 t_num_gangs = t_num_workers = t_vector_length
9174 = fold_convert_loc (gimple_location (entry_stmt),
9175 integer_type_node, integer_one_node);
9176 /* ..., but if present, use the value specified by the respective
9177 clause, making sure that are of the correct type. */
9178 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_GANGS);
9179 if (c)
9180 t_num_gangs = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9181 integer_type_node,
9182 OMP_CLAUSE_NUM_GANGS_EXPR (c));
9183 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_WORKERS);
9184 if (c)
9185 t_num_workers = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9186 integer_type_node,
9187 OMP_CLAUSE_NUM_WORKERS_EXPR (c));
9188 c = find_omp_clause (clauses, OMP_CLAUSE_VECTOR_LENGTH);
9189 if (c)
9190 t_vector_length = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9191 integer_type_node,
9192 OMP_CLAUSE_VECTOR_LENGTH_EXPR (c));
02c05c9b 9193 args.quick_push (t_num_gangs);
9194 args.quick_push (t_num_workers);
9195 args.quick_push (t_vector_length);
ca4c3545 9196 }
9197 /* FALLTHRU */
9198 case BUILT_IN_GOACC_ENTER_EXIT_DATA:
9199 case BUILT_IN_GOACC_UPDATE:
9200 {
9201 tree t_async;
9202 int t_wait_idx;
9203
9204 /* Default values for t_async. */
9205 t_async = fold_convert_loc (gimple_location (entry_stmt),
9206 integer_type_node,
9207 build_int_cst (integer_type_node,
9208 GOMP_ASYNC_SYNC));
9209 /* ..., but if present, use the value specified by the respective
9210 clause, making sure that is of the correct type. */
9211 c = find_omp_clause (clauses, OMP_CLAUSE_ASYNC);
9212 if (c)
9213 t_async = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9214 integer_type_node,
9215 OMP_CLAUSE_ASYNC_EXPR (c));
9216
02c05c9b 9217 args.quick_push (t_async);
ca4c3545 9218 /* Save the index, and... */
02c05c9b 9219 t_wait_idx = args.length ();
ca4c3545 9220 /* ... push a default value. */
02c05c9b 9221 args.quick_push (fold_convert_loc (gimple_location (entry_stmt),
9222 integer_type_node,
9223 integer_zero_node));
ca4c3545 9224 c = find_omp_clause (clauses, OMP_CLAUSE_WAIT);
9225 if (c)
9226 {
9227 int n = 0;
9228
9229 for (; c; c = OMP_CLAUSE_CHAIN (c))
9230 {
9231 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_WAIT)
9232 {
02c05c9b 9233 args.safe_push (fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9234 integer_type_node,
9235 OMP_CLAUSE_WAIT_EXPR (c)));
ca4c3545 9236 n++;
9237 }
9238 }
9239
9240 /* Now that we know the number, replace the default value. */
02c05c9b 9241 args.ordered_remove (t_wait_idx);
9242 args.quick_insert (t_wait_idx,
9243 fold_convert_loc (gimple_location (entry_stmt),
9244 integer_type_node,
9245 build_int_cst (integer_type_node, n)));
ca4c3545 9246 }
9247 }
9248 break;
9249 default:
9250 gcc_unreachable ();
bc7bff74 9251 }
ca4c3545 9252
02c05c9b 9253 g = gimple_build_call_vec (builtin_decl_explicit (start_ix), args);
bc7bff74 9254 gimple_set_location (g, gimple_location (entry_stmt));
9255 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
ca4c3545 9256 if (!offloaded)
bc7bff74 9257 {
9258 g = gsi_stmt (gsi);
9259 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_TARGET);
9260 gsi_remove (&gsi, true);
9261 }
ca4c3545 9262 if (data_region
9263 && region->exit)
bc7bff74 9264 {
9265 gsi = gsi_last_bb (region->exit);
9266 g = gsi_stmt (gsi);
9267 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_RETURN);
9268 gsi_remove (&gsi, true);
9269 }
9270}
9271
9272
9273/* Expand the parallel region tree rooted at REGION. Expansion
9274 proceeds in depth-first order. Innermost regions are expanded
9275 first. This way, parallel regions that require a new function to
75a70cf9 9276 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
773c5ba7 9277 internal dependencies in their body. */
9278
9279static void
9280expand_omp (struct omp_region *region)
9281{
9282 while (region)
9283 {
1d22f541 9284 location_t saved_location;
bc7bff74 9285 gimple inner_stmt = NULL;
1d22f541 9286
d1d5b012 9287 /* First, determine whether this is a combined parallel+workshare
9288 region. */
75a70cf9 9289 if (region->type == GIMPLE_OMP_PARALLEL)
d1d5b012 9290 determine_parallel_type (region);
9291
bc7bff74 9292 if (region->type == GIMPLE_OMP_FOR
9293 && gimple_omp_for_combined_p (last_stmt (region->entry)))
9294 inner_stmt = last_stmt (region->inner->entry);
9295
773c5ba7 9296 if (region->inner)
9297 expand_omp (region->inner);
9298
1d22f541 9299 saved_location = input_location;
75a70cf9 9300 if (gimple_has_location (last_stmt (region->entry)))
9301 input_location = gimple_location (last_stmt (region->entry));
1d22f541 9302
61e47ac8 9303 switch (region->type)
773c5ba7 9304 {
75a70cf9 9305 case GIMPLE_OMP_PARALLEL:
9306 case GIMPLE_OMP_TASK:
fd6481cf 9307 expand_omp_taskreg (region);
9308 break;
9309
75a70cf9 9310 case GIMPLE_OMP_FOR:
bc7bff74 9311 expand_omp_for (region, inner_stmt);
61e47ac8 9312 break;
773c5ba7 9313
75a70cf9 9314 case GIMPLE_OMP_SECTIONS:
61e47ac8 9315 expand_omp_sections (region);
9316 break;
773c5ba7 9317
75a70cf9 9318 case GIMPLE_OMP_SECTION:
61e47ac8 9319 /* Individual omp sections are handled together with their
75a70cf9 9320 parent GIMPLE_OMP_SECTIONS region. */
61e47ac8 9321 break;
773c5ba7 9322
75a70cf9 9323 case GIMPLE_OMP_SINGLE:
61e47ac8 9324 expand_omp_single (region);
9325 break;
773c5ba7 9326
75a70cf9 9327 case GIMPLE_OMP_MASTER:
bc7bff74 9328 case GIMPLE_OMP_TASKGROUP:
75a70cf9 9329 case GIMPLE_OMP_ORDERED:
9330 case GIMPLE_OMP_CRITICAL:
bc7bff74 9331 case GIMPLE_OMP_TEAMS:
61e47ac8 9332 expand_omp_synch (region);
9333 break;
773c5ba7 9334
75a70cf9 9335 case GIMPLE_OMP_ATOMIC_LOAD:
cb7f680b 9336 expand_omp_atomic (region);
9337 break;
9338
bc7bff74 9339 case GIMPLE_OMP_TARGET:
9340 expand_omp_target (region);
9341 break;
9342
61e47ac8 9343 default:
9344 gcc_unreachable ();
9345 }
cc5982dc 9346
1d22f541 9347 input_location = saved_location;
773c5ba7 9348 region = region->next;
9349 }
9350}
9351
9352
9353/* Helper for build_omp_regions. Scan the dominator tree starting at
28c92cbb 9354 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
9355 true, the function ends once a single tree is built (otherwise, whole
9356 forest of OMP constructs may be built). */
773c5ba7 9357
9358static void
28c92cbb 9359build_omp_regions_1 (basic_block bb, struct omp_region *parent,
9360 bool single_tree)
773c5ba7 9361{
75a70cf9 9362 gimple_stmt_iterator gsi;
9363 gimple stmt;
773c5ba7 9364 basic_block son;
9365
75a70cf9 9366 gsi = gsi_last_bb (bb);
9367 if (!gsi_end_p (gsi) && is_gimple_omp (gsi_stmt (gsi)))
773c5ba7 9368 {
9369 struct omp_region *region;
75a70cf9 9370 enum gimple_code code;
773c5ba7 9371
75a70cf9 9372 stmt = gsi_stmt (gsi);
9373 code = gimple_code (stmt);
9374 if (code == GIMPLE_OMP_RETURN)
773c5ba7 9375 {
9376 /* STMT is the return point out of region PARENT. Mark it
9377 as the exit point and make PARENT the immediately
9378 enclosing region. */
9379 gcc_assert (parent);
9380 region = parent;
61e47ac8 9381 region->exit = bb;
773c5ba7 9382 parent = parent->outer;
773c5ba7 9383 }
75a70cf9 9384 else if (code == GIMPLE_OMP_ATOMIC_STORE)
cb7f680b 9385 {
75a70cf9 9386 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
9387 GIMPLE_OMP_RETURN, but matches with
9388 GIMPLE_OMP_ATOMIC_LOAD. */
cb7f680b 9389 gcc_assert (parent);
75a70cf9 9390 gcc_assert (parent->type == GIMPLE_OMP_ATOMIC_LOAD);
cb7f680b 9391 region = parent;
9392 region->exit = bb;
9393 parent = parent->outer;
9394 }
75a70cf9 9395 else if (code == GIMPLE_OMP_CONTINUE)
61e47ac8 9396 {
9397 gcc_assert (parent);
9398 parent->cont = bb;
9399 }
75a70cf9 9400 else if (code == GIMPLE_OMP_SECTIONS_SWITCH)
ac6e3339 9401 {
75a70cf9 9402 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
9403 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
ac6e3339 9404 }
773c5ba7 9405 else
9406 {
61e47ac8 9407 region = new_omp_region (bb, code, parent);
ca4c3545 9408 /* Otherwise... */
9409 if (code == GIMPLE_OMP_TARGET)
9410 {
9411 switch (gimple_omp_target_kind (stmt))
9412 {
9413 case GF_OMP_TARGET_KIND_REGION:
9414 case GF_OMP_TARGET_KIND_DATA:
9415 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
9416 case GF_OMP_TARGET_KIND_OACC_KERNELS:
9417 case GF_OMP_TARGET_KIND_OACC_DATA:
9418 break;
9419 case GF_OMP_TARGET_KIND_UPDATE:
9420 case GF_OMP_TARGET_KIND_OACC_UPDATE:
9421 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
9422 /* ..., other than for those stand-alone directives... */
9423 region = NULL;
9424 break;
9425 default:
9426 gcc_unreachable ();
9427 }
9428 }
9429 /* ..., this directive becomes the parent for a new region. */
9430 if (region)
9431 parent = region;
773c5ba7 9432 }
773c5ba7 9433 }
9434
28c92cbb 9435 if (single_tree && !parent)
9436 return;
9437
773c5ba7 9438 for (son = first_dom_son (CDI_DOMINATORS, bb);
9439 son;
9440 son = next_dom_son (CDI_DOMINATORS, son))
28c92cbb 9441 build_omp_regions_1 (son, parent, single_tree);
9442}
9443
9444/* Builds the tree of OMP regions rooted at ROOT, storing it to
9445 root_omp_region. */
9446
9447static void
9448build_omp_regions_root (basic_block root)
9449{
9450 gcc_assert (root_omp_region == NULL);
9451 build_omp_regions_1 (root, NULL, true);
9452 gcc_assert (root_omp_region != NULL);
773c5ba7 9453}
9454
28c92cbb 9455/* Expands omp construct (and its subconstructs) starting in HEAD. */
9456
9457void
9458omp_expand_local (basic_block head)
9459{
9460 build_omp_regions_root (head);
9461 if (dump_file && (dump_flags & TDF_DETAILS))
9462 {
9463 fprintf (dump_file, "\nOMP region tree\n\n");
9464 dump_omp_region (dump_file, root_omp_region, 0);
9465 fprintf (dump_file, "\n");
9466 }
9467
9468 remove_exit_barriers (root_omp_region);
9469 expand_omp (root_omp_region);
9470
9471 free_omp_regions ();
9472}
773c5ba7 9473
9474/* Scan the CFG and build a tree of OMP regions. Return the root of
9475 the OMP region tree. */
9476
9477static void
9478build_omp_regions (void)
9479{
61e47ac8 9480 gcc_assert (root_omp_region == NULL);
773c5ba7 9481 calculate_dominance_info (CDI_DOMINATORS);
34154e27 9482 build_omp_regions_1 (ENTRY_BLOCK_PTR_FOR_FN (cfun), NULL, false);
773c5ba7 9483}
9484
773c5ba7 9485/* Main entry point for expanding OMP-GIMPLE into runtime calls. */
9486
2a1990e9 9487static unsigned int
773c5ba7 9488execute_expand_omp (void)
9489{
9490 build_omp_regions ();
9491
61e47ac8 9492 if (!root_omp_region)
9493 return 0;
773c5ba7 9494
61e47ac8 9495 if (dump_file)
9496 {
9497 fprintf (dump_file, "\nOMP region tree\n\n");
9498 dump_omp_region (dump_file, root_omp_region, 0);
9499 fprintf (dump_file, "\n");
773c5ba7 9500 }
61e47ac8 9501
9502 remove_exit_barriers (root_omp_region);
9503
9504 expand_omp (root_omp_region);
9505
61e47ac8 9506 cleanup_tree_cfg ();
9507
9508 free_omp_regions ();
9509
2a1990e9 9510 return 0;
773c5ba7 9511}
9512
79acaae1 9513/* OMP expansion -- the default pass, run before creation of SSA form. */
9514
cbe8bda8 9515namespace {
9516
9517const pass_data pass_data_expand_omp =
9518{
9519 GIMPLE_PASS, /* type */
9520 "ompexp", /* name */
9521 OPTGROUP_NONE, /* optinfo_flags */
cbe8bda8 9522 TV_NONE, /* tv_id */
9523 PROP_gimple_any, /* properties_required */
8917c50b 9524 PROP_gimple_eomp, /* properties_provided */
cbe8bda8 9525 0, /* properties_destroyed */
9526 0, /* todo_flags_start */
9527 0, /* todo_flags_finish */
773c5ba7 9528};
cbe8bda8 9529
9530class pass_expand_omp : public gimple_opt_pass
9531{
9532public:
9af5ce0c 9533 pass_expand_omp (gcc::context *ctxt)
9534 : gimple_opt_pass (pass_data_expand_omp, ctxt)
cbe8bda8 9535 {}
9536
9537 /* opt_pass methods: */
8917c50b 9538 virtual unsigned int execute (function *)
31315c24 9539 {
ca4c3545 9540 bool gate = ((flag_cilkplus != 0 || flag_openacc != 0 || flag_openmp != 0
9541 || flag_openmp_simd != 0)
9542 && !seen_error ());
31315c24 9543
8917c50b 9544 /* This pass always runs, to provide PROP_gimple_eomp.
ca4c3545 9545 But often, there is nothing to do. */
8917c50b 9546 if (!gate)
9547 return 0;
9548
9549 return execute_expand_omp ();
9550 }
cbe8bda8 9551
9552}; // class pass_expand_omp
9553
9554} // anon namespace
9555
9556gimple_opt_pass *
9557make_pass_expand_omp (gcc::context *ctxt)
9558{
9559 return new pass_expand_omp (ctxt);
9560}
8917c50b 9561
9562namespace {
9563
9564const pass_data pass_data_expand_omp_ssa =
9565{
9566 GIMPLE_PASS, /* type */
9567 "ompexpssa", /* name */
9568 OPTGROUP_NONE, /* optinfo_flags */
9569 TV_NONE, /* tv_id */
9570 PROP_cfg | PROP_ssa, /* properties_required */
9571 PROP_gimple_eomp, /* properties_provided */
9572 0, /* properties_destroyed */
9573 0, /* todo_flags_start */
9574 TODO_cleanup_cfg | TODO_rebuild_alias, /* todo_flags_finish */
9575};
9576
9577class pass_expand_omp_ssa : public gimple_opt_pass
9578{
9579public:
9580 pass_expand_omp_ssa (gcc::context *ctxt)
9581 : gimple_opt_pass (pass_data_expand_omp_ssa, ctxt)
9582 {}
9583
9584 /* opt_pass methods: */
9585 virtual bool gate (function *fun)
9586 {
9587 return !(fun->curr_properties & PROP_gimple_eomp);
9588 }
9589 virtual unsigned int execute (function *) { return execute_expand_omp (); }
9590
9591}; // class pass_expand_omp_ssa
9592
9593} // anon namespace
9594
9595gimple_opt_pass *
9596make_pass_expand_omp_ssa (gcc::context *ctxt)
9597{
9598 return new pass_expand_omp_ssa (ctxt);
9599}
773c5ba7 9600\f
ca4c3545 9601/* Routines to lower OMP directives into OMP-GIMPLE. */
9602
9603/* Helper function to preform, potentially COMPLEX_TYPE, operation and
9604 convert it to gimple. */
9605static void
9606oacc_gimple_assign (tree dest, tree_code op, tree src, gimple_seq *seq)
9607{
9608 gimple stmt;
9609
9610 if (TREE_CODE (TREE_TYPE (dest)) != COMPLEX_TYPE)
9611 {
9612 stmt = gimple_build_assign (dest, op, dest, src);
9613 gimple_seq_add_stmt (seq, stmt);
9614 return;
9615 }
9616
9617 tree t = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9618 tree rdest = fold_build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (dest)), dest);
9619 gimplify_assign (t, rdest, seq);
9620 rdest = t;
9621
9622 t = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9623 tree idest = fold_build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (dest)), dest);
9624 gimplify_assign (t, idest, seq);
9625 idest = t;
9626
9627 t = create_tmp_var (TREE_TYPE (TREE_TYPE (src)));
9628 tree rsrc = fold_build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (src)), src);
9629 gimplify_assign (t, rsrc, seq);
9630 rsrc = t;
9631
9632 t = create_tmp_var (TREE_TYPE (TREE_TYPE (src)));
9633 tree isrc = fold_build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (src)), src);
9634 gimplify_assign (t, isrc, seq);
9635 isrc = t;
9636
9637 tree r = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9638 tree i = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9639 tree result;
9640
9641 if (op == PLUS_EXPR)
9642 {
9643 stmt = gimple_build_assign (r, op, rdest, rsrc);
9644 gimple_seq_add_stmt (seq, stmt);
9645
9646 stmt = gimple_build_assign (i, op, idest, isrc);
9647 gimple_seq_add_stmt (seq, stmt);
9648 }
9649 else if (op == MULT_EXPR)
9650 {
9651 /* Let x = a + ib = dest, y = c + id = src.
9652 x * y = (ac - bd) + i(ad + bc) */
9653 tree ac = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9654 tree bd = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9655 tree ad = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9656 tree bc = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9657
9658 stmt = gimple_build_assign (ac, MULT_EXPR, rdest, rsrc);
9659 gimple_seq_add_stmt (seq, stmt);
9660
9661 stmt = gimple_build_assign (bd, MULT_EXPR, idest, isrc);
9662 gimple_seq_add_stmt (seq, stmt);
9663
9664 stmt = gimple_build_assign (r, MINUS_EXPR, ac, bd);
9665 gimple_seq_add_stmt (seq, stmt);
9666
9667 stmt = gimple_build_assign (ad, MULT_EXPR, rdest, isrc);
9668 gimple_seq_add_stmt (seq, stmt);
9669
9670 stmt = gimple_build_assign (bd, MULT_EXPR, idest, rsrc);
9671 gimple_seq_add_stmt (seq, stmt);
9672
9673 stmt = gimple_build_assign (i, PLUS_EXPR, ad, bc);
9674 gimple_seq_add_stmt (seq, stmt);
9675 }
9676 else
9677 gcc_unreachable ();
9678
9679 result = build2 (COMPLEX_EXPR, TREE_TYPE (dest), r, i);
9680 gimplify_assign (dest, result, seq);
9681}
9682
9683/* Helper function to initialize local data for the reduction arrays.
9684 The reduction arrays need to be placed inside the calling function
9685 for accelerators, or else the host won't be able to preform the final
9686 reduction. */
9687
9688static void
9689oacc_initialize_reduction_data (tree clauses, tree nthreads,
9690 gimple_seq *stmt_seqp, omp_context *ctx)
9691{
9692 tree c, t, oc;
9693 gimple stmt;
9694 omp_context *octx;
9695
9696 /* Find the innermost OpenACC parallel context. */
9697 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET
9698 && (gimple_omp_target_kind (ctx->stmt)
9699 == GF_OMP_TARGET_KIND_OACC_PARALLEL))
9700 octx = ctx;
9701 else
9702 octx = ctx->outer;
9703 gcc_checking_assert (gimple_code (octx->stmt) == GIMPLE_OMP_TARGET
9704 && (gimple_omp_target_kind (octx->stmt)
9705 == GF_OMP_TARGET_KIND_OACC_PARALLEL));
9706
9707 /* Extract the clauses. */
9708 oc = gimple_omp_target_clauses (octx->stmt);
9709
9710 /* Find the last outer clause. */
9711 for (; oc && OMP_CLAUSE_CHAIN (oc); oc = OMP_CLAUSE_CHAIN (oc))
9712 ;
9713
9714 /* Allocate arrays for each reduction variable. */
9715 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9716 {
9717 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
9718 continue;
9719
9720 tree var = OMP_CLAUSE_DECL (c);
9721 tree type = get_base_type (var);
9722 tree array = lookup_oacc_reduction (oacc_get_reduction_array_id (var),
9723 ctx);
9724 tree size, call;
9725
9726 /* Calculate size of the reduction array. */
9727 t = create_tmp_var (TREE_TYPE (nthreads));
9728 stmt = gimple_build_assign (t, MULT_EXPR, nthreads,
9729 fold_convert (TREE_TYPE (nthreads),
9730 TYPE_SIZE_UNIT (type)));
9731 gimple_seq_add_stmt (stmt_seqp, stmt);
9732
9733 size = create_tmp_var (sizetype);
9734 gimplify_assign (size, fold_build1 (NOP_EXPR, sizetype, t), stmt_seqp);
9735
9736 /* Now allocate memory for it. */
9737 call = unshare_expr (builtin_decl_explicit (BUILT_IN_ALLOCA));
9738 stmt = gimple_build_call (call, 1, size);
9739 gimple_call_set_lhs (stmt, array);
9740 gimple_seq_add_stmt (stmt_seqp, stmt);
9741
9742 /* Map this array into the accelerator. */
9743
9744 /* Add the reduction array to the list of clauses. */
9745 tree x = array;
9746 t = build_omp_clause (gimple_location (ctx->stmt), OMP_CLAUSE_MAP);
9747 OMP_CLAUSE_SET_MAP_KIND (t, GOMP_MAP_FORCE_FROM);
9748 OMP_CLAUSE_DECL (t) = x;
9749 OMP_CLAUSE_CHAIN (t) = NULL;
9750 if (oc)
9751 OMP_CLAUSE_CHAIN (oc) = t;
9752 else
9753 gimple_omp_target_set_clauses (as_a <gomp_target *> (octx->stmt), t);
9754 OMP_CLAUSE_SIZE (t) = size;
9755 oc = t;
9756 }
9757}
9758
9759/* Helper function to process the array of partial reductions. Nthreads
9760 indicates the number of threads. Unfortunately, GOACC_GET_NUM_THREADS
9761 cannot be used here, because nthreads on the host may be different than
9762 on the accelerator. */
9763
9764static void
9765oacc_finalize_reduction_data (tree clauses, tree nthreads,
9766 gimple_seq *stmt_seqp, omp_context *ctx)
9767{
9768 tree c, x, var, array, loop_header, loop_body, loop_exit, type;
9769 gimple stmt;
9770
9771 /* Create for loop.
9772
9773 let var = the original reduction variable
9774 let array = reduction variable array
9775
9776 for (i = 0; i < nthreads; i++)
9777 var op= array[i]
9778 */
9779
9780 loop_header = create_artificial_label (UNKNOWN_LOCATION);
9781 loop_body = create_artificial_label (UNKNOWN_LOCATION);
9782 loop_exit = create_artificial_label (UNKNOWN_LOCATION);
9783
9784 /* Create and initialize an index variable. */
9785 tree ix = create_tmp_var (sizetype);
9786 gimplify_assign (ix, fold_build1 (NOP_EXPR, sizetype, integer_zero_node),
9787 stmt_seqp);
9788
9789 /* Insert the loop header label here. */
9790 gimple_seq_add_stmt (stmt_seqp, gimple_build_label (loop_header));
9791
9792 /* Exit loop if ix >= nthreads. */
9793 x = create_tmp_var (sizetype);
9794 gimplify_assign (x, fold_build1 (NOP_EXPR, sizetype, nthreads), stmt_seqp);
9795 stmt = gimple_build_cond (GE_EXPR, ix, x, loop_exit, loop_body);
9796 gimple_seq_add_stmt (stmt_seqp, stmt);
9797
9798 /* Insert the loop body label here. */
9799 gimple_seq_add_stmt (stmt_seqp, gimple_build_label (loop_body));
9800
9801 /* Collapse each reduction array, one element at a time. */
9802 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9803 {
9804 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
9805 continue;
9806
9807 tree_code reduction_code = OMP_CLAUSE_REDUCTION_CODE (c);
9808
9809 /* reduction(-:var) sums up the partial results, so it acts
9810 identically to reduction(+:var). */
9811 if (reduction_code == MINUS_EXPR)
9812 reduction_code = PLUS_EXPR;
9813
9814 /* Set up reduction variable var. */
9815 var = OMP_CLAUSE_DECL (c);
9816 type = get_base_type (var);
9817 array = lookup_oacc_reduction (oacc_get_reduction_array_id
9818 (OMP_CLAUSE_DECL (c)), ctx);
9819
9820 /* Calculate the array offset. */
9821 tree offset = create_tmp_var (sizetype);
9822 gimplify_assign (offset, TYPE_SIZE_UNIT (type), stmt_seqp);
9823 stmt = gimple_build_assign (offset, MULT_EXPR, offset, ix);
9824 gimple_seq_add_stmt (stmt_seqp, stmt);
9825
9826 tree ptr = create_tmp_var (TREE_TYPE (array));
9827 stmt = gimple_build_assign (ptr, POINTER_PLUS_EXPR, array, offset);
9828 gimple_seq_add_stmt (stmt_seqp, stmt);
9829
9830 /* Extract array[ix] into mem. */
9831 tree mem = create_tmp_var (type);
9832 gimplify_assign (mem, build_simple_mem_ref (ptr), stmt_seqp);
9833
9834 /* Find the original reduction variable. */
9835 if (is_reference (var))
9836 var = build_simple_mem_ref (var);
9837
9838 tree t = create_tmp_var (type);
9839
9840 x = lang_hooks.decls.omp_clause_assign_op (c, t, var);
9841 gimplify_and_add (unshare_expr(x), stmt_seqp);
9842
9843 /* var = var op mem */
9844 switch (OMP_CLAUSE_REDUCTION_CODE (c))
9845 {
9846 case TRUTH_ANDIF_EXPR:
9847 case TRUTH_ORIF_EXPR:
9848 t = fold_build2 (OMP_CLAUSE_REDUCTION_CODE (c), integer_type_node,
9849 t, mem);
9850 gimplify_and_add (t, stmt_seqp);
9851 break;
9852 default:
9853 /* The lhs isn't a gimple_reg when var is COMPLEX_TYPE. */
9854 oacc_gimple_assign (t, OMP_CLAUSE_REDUCTION_CODE (c), mem,
9855 stmt_seqp);
9856 }
9857
9858 t = fold_build1 (NOP_EXPR, TREE_TYPE (var), t);
9859 x = lang_hooks.decls.omp_clause_assign_op (c, var, t);
9860 gimplify_and_add (unshare_expr(x), stmt_seqp);
9861 }
9862
9863 /* Increment the induction variable. */
9864 tree one = fold_build1 (NOP_EXPR, sizetype, integer_one_node);
9865 stmt = gimple_build_assign (ix, PLUS_EXPR, ix, one);
9866 gimple_seq_add_stmt (stmt_seqp, stmt);
9867
9868 /* Go back to the top of the loop. */
9869 gimple_seq_add_stmt (stmt_seqp, gimple_build_goto (loop_header));
9870
9871 /* Place the loop exit label here. */
9872 gimple_seq_add_stmt (stmt_seqp, gimple_build_label (loop_exit));
9873}
9874
9875/* Scan through all of the gimple stmts searching for an OMP_FOR_EXPR, and
9876 scan that for reductions. */
9877
9878static void
9879oacc_process_reduction_data (gimple_seq *body, gimple_seq *in_stmt_seqp,
9880 gimple_seq *out_stmt_seqp, omp_context *ctx)
9881{
9882 gimple_stmt_iterator gsi;
9883 gimple_seq inner = NULL;
9884
9885 /* A collapse clause may have inserted a new bind block. */
9886 gsi = gsi_start (*body);
9887 while (!gsi_end_p (gsi))
9888 {
9889 gimple stmt = gsi_stmt (gsi);
9890 if (gbind *bind_stmt = dyn_cast <gbind *> (stmt))
9891 {
9892 inner = gimple_bind_body (bind_stmt);
9893 body = &inner;
9894 gsi = gsi_start (*body);
9895 }
9896 else if (dyn_cast <gomp_for *> (stmt))
9897 break;
9898 else
9899 gsi_next (&gsi);
9900 }
9901
9902 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
9903 {
9904 tree clauses, nthreads, t, c, acc_device, acc_device_host, call,
9905 enter, exit;
9906 bool reduction_found = false;
9907
9908 gimple stmt = gsi_stmt (gsi);
9909
9910 switch (gimple_code (stmt))
9911 {
9912 case GIMPLE_OMP_FOR:
9913 clauses = gimple_omp_for_clauses (stmt);
9914
9915 /* Search for a reduction clause. */
9916 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9917 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
9918 {
9919 reduction_found = true;
9920 break;
9921 }
9922
9923 if (!reduction_found)
9924 break;
9925
9926 ctx = maybe_lookup_ctx (stmt);
9927 t = NULL_TREE;
9928
9929 /* Extract the number of threads. */
9930 nthreads = create_tmp_var (sizetype);
9931 t = oacc_max_threads (ctx);
9932 gimplify_assign (nthreads, t, in_stmt_seqp);
9933
9934 /* Determine if this is kernel will be executed on the host. */
9935 call = builtin_decl_explicit (BUILT_IN_ACC_GET_DEVICE_TYPE);
9936 acc_device = create_tmp_var (integer_type_node, ".acc_device_type");
9937 stmt = gimple_build_call (call, 0);
9938 gimple_call_set_lhs (stmt, acc_device);
9939 gimple_seq_add_stmt (in_stmt_seqp, stmt);
9940
9941 /* Set nthreads = 1 for ACC_DEVICE_TYPE=host. */
9942 acc_device_host = create_tmp_var (integer_type_node,
9943 ".acc_device_host");
9944 gimplify_assign (acc_device_host,
9945 build_int_cst (integer_type_node,
9946 GOMP_DEVICE_HOST),
9947 in_stmt_seqp);
9948
9949 enter = create_artificial_label (UNKNOWN_LOCATION);
9950 exit = create_artificial_label (UNKNOWN_LOCATION);
9951
9952 stmt = gimple_build_cond (EQ_EXPR, acc_device, acc_device_host,
9953 enter, exit);
9954 gimple_seq_add_stmt (in_stmt_seqp, stmt);
9955 gimple_seq_add_stmt (in_stmt_seqp, gimple_build_label (enter));
9956 gimplify_assign (nthreads, fold_build1 (NOP_EXPR, sizetype,
9957 integer_one_node),
9958 in_stmt_seqp);
9959 gimple_seq_add_stmt (in_stmt_seqp, gimple_build_label (exit));
9960
9961 /* Also, set nthreads = 1 for ACC_DEVICE_TYPE=host_nonshm. */
9962 gimplify_assign (acc_device_host,
9963 build_int_cst (integer_type_node,
9964 GOMP_DEVICE_HOST_NONSHM),
9965 in_stmt_seqp);
9966
9967 enter = create_artificial_label (UNKNOWN_LOCATION);
9968 exit = create_artificial_label (UNKNOWN_LOCATION);
9969
9970 stmt = gimple_build_cond (EQ_EXPR, acc_device, acc_device_host,
9971 enter, exit);
9972 gimple_seq_add_stmt (in_stmt_seqp, stmt);
9973 gimple_seq_add_stmt (in_stmt_seqp, gimple_build_label (enter));
9974 gimplify_assign (nthreads, fold_build1 (NOP_EXPR, sizetype,
9975 integer_one_node),
9976 in_stmt_seqp);
9977 gimple_seq_add_stmt (in_stmt_seqp, gimple_build_label (exit));
9978
9979 oacc_initialize_reduction_data (clauses, nthreads, in_stmt_seqp,
9980 ctx);
9981 oacc_finalize_reduction_data (clauses, nthreads, out_stmt_seqp, ctx);
9982 break;
9983 default:
9984 // Scan for other directives which support reduction here.
9985 break;
9986 }
9987 }
9988}
773c5ba7 9989
bc7bff74 9990/* If ctx is a worksharing context inside of a cancellable parallel
9991 region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
9992 and conditional branch to parallel's cancel_label to handle
9993 cancellation in the implicit barrier. */
9994
9995static void
9996maybe_add_implicit_barrier_cancel (omp_context *ctx, gimple_seq *body)
9997{
9998 gimple omp_return = gimple_seq_last_stmt (*body);
9999 gcc_assert (gimple_code (omp_return) == GIMPLE_OMP_RETURN);
10000 if (gimple_omp_return_nowait_p (omp_return))
10001 return;
10002 if (ctx->outer
10003 && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_PARALLEL
10004 && ctx->outer->cancellable)
10005 {
15b28553 10006 tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL);
10007 tree c_bool_type = TREE_TYPE (TREE_TYPE (fndecl));
f9e245b2 10008 tree lhs = create_tmp_var (c_bool_type);
bc7bff74 10009 gimple_omp_return_set_lhs (omp_return, lhs);
10010 tree fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
15b28553 10011 gimple g = gimple_build_cond (NE_EXPR, lhs,
10012 fold_convert (c_bool_type,
10013 boolean_false_node),
bc7bff74 10014 ctx->outer->cancel_label, fallthru_label);
10015 gimple_seq_add_stmt (body, g);
10016 gimple_seq_add_stmt (body, gimple_build_label (fallthru_label));
10017 }
10018}
10019
75a70cf9 10020/* Lower the OpenMP sections directive in the current statement in GSI_P.
10021 CTX is the enclosing OMP context for the current statement. */
773c5ba7 10022
10023static void
75a70cf9 10024lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
773c5ba7 10025{
75a70cf9 10026 tree block, control;
10027 gimple_stmt_iterator tgsi;
1a91d914 10028 gomp_sections *stmt;
10029 gimple t;
10030 gbind *new_stmt, *bind;
e3a19533 10031 gimple_seq ilist, dlist, olist, new_body;
773c5ba7 10032
1a91d914 10033 stmt = as_a <gomp_sections *> (gsi_stmt (*gsi_p));
773c5ba7 10034
8a4a28a8 10035 push_gimplify_context ();
773c5ba7 10036
10037 dlist = NULL;
10038 ilist = NULL;
75a70cf9 10039 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
bc7bff74 10040 &ilist, &dlist, ctx, NULL);
773c5ba7 10041
e3a19533 10042 new_body = gimple_omp_body (stmt);
10043 gimple_omp_set_body (stmt, NULL);
10044 tgsi = gsi_start (new_body);
10045 for (; !gsi_end_p (tgsi); gsi_next (&tgsi))
773c5ba7 10046 {
10047 omp_context *sctx;
75a70cf9 10048 gimple sec_start;
773c5ba7 10049
75a70cf9 10050 sec_start = gsi_stmt (tgsi);
773c5ba7 10051 sctx = maybe_lookup_ctx (sec_start);
10052 gcc_assert (sctx);
10053
e3a19533 10054 lower_omp (gimple_omp_body_ptr (sec_start), sctx);
10055 gsi_insert_seq_after (&tgsi, gimple_omp_body (sec_start),
10056 GSI_CONTINUE_LINKING);
75a70cf9 10057 gimple_omp_set_body (sec_start, NULL);
773c5ba7 10058
e3a19533 10059 if (gsi_one_before_end_p (tgsi))
773c5ba7 10060 {
75a70cf9 10061 gimple_seq l = NULL;
10062 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
773c5ba7 10063 &l, ctx);
e3a19533 10064 gsi_insert_seq_after (&tgsi, l, GSI_CONTINUE_LINKING);
75a70cf9 10065 gimple_omp_section_set_last (sec_start);
773c5ba7 10066 }
48e1416a 10067
e3a19533 10068 gsi_insert_after (&tgsi, gimple_build_omp_return (false),
10069 GSI_CONTINUE_LINKING);
773c5ba7 10070 }
1e8e9920 10071
10072 block = make_node (BLOCK);
e3a19533 10073 bind = gimple_build_bind (NULL, new_body, block);
1e8e9920 10074
75a70cf9 10075 olist = NULL;
10076 lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist, ctx);
773c5ba7 10077
1d22f541 10078 block = make_node (BLOCK);
75a70cf9 10079 new_stmt = gimple_build_bind (NULL, NULL, block);
e3a19533 10080 gsi_replace (gsi_p, new_stmt, true);
773c5ba7 10081
1d22f541 10082 pop_gimplify_context (new_stmt);
75a70cf9 10083 gimple_bind_append_vars (new_stmt, ctx->block_vars);
10084 BLOCK_VARS (block) = gimple_bind_vars (bind);
1d22f541 10085 if (BLOCK_VARS (block))
10086 TREE_USED (block) = 1;
10087
75a70cf9 10088 new_body = NULL;
10089 gimple_seq_add_seq (&new_body, ilist);
10090 gimple_seq_add_stmt (&new_body, stmt);
10091 gimple_seq_add_stmt (&new_body, gimple_build_omp_sections_switch ());
10092 gimple_seq_add_stmt (&new_body, bind);
61e47ac8 10093
ac6e3339 10094 control = create_tmp_var (unsigned_type_node, ".section");
75a70cf9 10095 t = gimple_build_omp_continue (control, control);
10096 gimple_omp_sections_set_control (stmt, control);
10097 gimple_seq_add_stmt (&new_body, t);
61e47ac8 10098
75a70cf9 10099 gimple_seq_add_seq (&new_body, olist);
bc7bff74 10100 if (ctx->cancellable)
10101 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
75a70cf9 10102 gimple_seq_add_seq (&new_body, dlist);
773c5ba7 10103
75a70cf9 10104 new_body = maybe_catch_exception (new_body);
aade31a0 10105
75a70cf9 10106 t = gimple_build_omp_return
10107 (!!find_omp_clause (gimple_omp_sections_clauses (stmt),
10108 OMP_CLAUSE_NOWAIT));
10109 gimple_seq_add_stmt (&new_body, t);
bc7bff74 10110 maybe_add_implicit_barrier_cancel (ctx, &new_body);
61e47ac8 10111
75a70cf9 10112 gimple_bind_set_body (new_stmt, new_body);
1e8e9920 10113}
10114
10115
773c5ba7 10116/* A subroutine of lower_omp_single. Expand the simple form of
75a70cf9 10117 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
1e8e9920 10118
10119 if (GOMP_single_start ())
10120 BODY;
10121 [ GOMP_barrier (); ] -> unless 'nowait' is present.
773c5ba7 10122
10123 FIXME. It may be better to delay expanding the logic of this until
10124 pass_expand_omp. The expanded logic may make the job more difficult
10125 to a synchronization analysis pass. */
1e8e9920 10126
10127static void
1a91d914 10128lower_omp_single_simple (gomp_single *single_stmt, gimple_seq *pre_p)
1e8e9920 10129{
e60a6f7b 10130 location_t loc = gimple_location (single_stmt);
10131 tree tlabel = create_artificial_label (loc);
10132 tree flabel = create_artificial_label (loc);
75a70cf9 10133 gimple call, cond;
10134 tree lhs, decl;
10135
b9a16870 10136 decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START);
f9e245b2 10137 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)));
75a70cf9 10138 call = gimple_build_call (decl, 0);
10139 gimple_call_set_lhs (call, lhs);
10140 gimple_seq_add_stmt (pre_p, call);
10141
10142 cond = gimple_build_cond (EQ_EXPR, lhs,
389dd41b 10143 fold_convert_loc (loc, TREE_TYPE (lhs),
10144 boolean_true_node),
75a70cf9 10145 tlabel, flabel);
10146 gimple_seq_add_stmt (pre_p, cond);
10147 gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
10148 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
10149 gimple_seq_add_stmt (pre_p, gimple_build_label (flabel));
1e8e9920 10150}
10151
773c5ba7 10152
10153/* A subroutine of lower_omp_single. Expand the simple form of
75a70cf9 10154 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
1e8e9920 10155
10156 #pragma omp single copyprivate (a, b, c)
10157
10158 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
10159
10160 {
10161 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
10162 {
10163 BODY;
10164 copyout.a = a;
10165 copyout.b = b;
10166 copyout.c = c;
10167 GOMP_single_copy_end (&copyout);
10168 }
10169 else
10170 {
10171 a = copyout_p->a;
10172 b = copyout_p->b;
10173 c = copyout_p->c;
10174 }
10175 GOMP_barrier ();
10176 }
773c5ba7 10177
10178 FIXME. It may be better to delay expanding the logic of this until
10179 pass_expand_omp. The expanded logic may make the job more difficult
10180 to a synchronization analysis pass. */
1e8e9920 10181
10182static void
1a91d914 10183lower_omp_single_copy (gomp_single *single_stmt, gimple_seq *pre_p,
10184 omp_context *ctx)
1e8e9920 10185{
b9a16870 10186 tree ptr_type, t, l0, l1, l2, bfn_decl;
75a70cf9 10187 gimple_seq copyin_seq;
e60a6f7b 10188 location_t loc = gimple_location (single_stmt);
1e8e9920 10189
10190 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
10191
10192 ptr_type = build_pointer_type (ctx->record_type);
10193 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
10194
e60a6f7b 10195 l0 = create_artificial_label (loc);
10196 l1 = create_artificial_label (loc);
10197 l2 = create_artificial_label (loc);
1e8e9920 10198
b9a16870 10199 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START);
10200 t = build_call_expr_loc (loc, bfn_decl, 0);
389dd41b 10201 t = fold_convert_loc (loc, ptr_type, t);
75a70cf9 10202 gimplify_assign (ctx->receiver_decl, t, pre_p);
1e8e9920 10203
10204 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
10205 build_int_cst (ptr_type, 0));
10206 t = build3 (COND_EXPR, void_type_node, t,
10207 build_and_jump (&l0), build_and_jump (&l1));
10208 gimplify_and_add (t, pre_p);
10209
75a70cf9 10210 gimple_seq_add_stmt (pre_p, gimple_build_label (l0));
1e8e9920 10211
75a70cf9 10212 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
1e8e9920 10213
10214 copyin_seq = NULL;
75a70cf9 10215 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
1e8e9920 10216 &copyin_seq, ctx);
10217
389dd41b 10218 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
b9a16870 10219 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END);
10220 t = build_call_expr_loc (loc, bfn_decl, 1, t);
1e8e9920 10221 gimplify_and_add (t, pre_p);
10222
10223 t = build_and_jump (&l2);
10224 gimplify_and_add (t, pre_p);
10225
75a70cf9 10226 gimple_seq_add_stmt (pre_p, gimple_build_label (l1));
1e8e9920 10227
75a70cf9 10228 gimple_seq_add_seq (pre_p, copyin_seq);
1e8e9920 10229
75a70cf9 10230 gimple_seq_add_stmt (pre_p, gimple_build_label (l2));
1e8e9920 10231}
10232
773c5ba7 10233
1e8e9920 10234/* Expand code for an OpenMP single directive. */
10235
10236static void
75a70cf9 10237lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
1e8e9920 10238{
75a70cf9 10239 tree block;
1a91d914 10240 gimple t;
10241 gomp_single *single_stmt = as_a <gomp_single *> (gsi_stmt (*gsi_p));
10242 gbind *bind;
bc7bff74 10243 gimple_seq bind_body, bind_body_tail = NULL, dlist;
1e8e9920 10244
8a4a28a8 10245 push_gimplify_context ();
1e8e9920 10246
e3a19533 10247 block = make_node (BLOCK);
10248 bind = gimple_build_bind (NULL, NULL, block);
10249 gsi_replace (gsi_p, bind, true);
75a70cf9 10250 bind_body = NULL;
e3a19533 10251 dlist = NULL;
75a70cf9 10252 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt),
bc7bff74 10253 &bind_body, &dlist, ctx, NULL);
e3a19533 10254 lower_omp (gimple_omp_body_ptr (single_stmt), ctx);
1e8e9920 10255
75a70cf9 10256 gimple_seq_add_stmt (&bind_body, single_stmt);
1e8e9920 10257
10258 if (ctx->record_type)
75a70cf9 10259 lower_omp_single_copy (single_stmt, &bind_body, ctx);
1e8e9920 10260 else
75a70cf9 10261 lower_omp_single_simple (single_stmt, &bind_body);
10262
10263 gimple_omp_set_body (single_stmt, NULL);
1e8e9920 10264
75a70cf9 10265 gimple_seq_add_seq (&bind_body, dlist);
61e47ac8 10266
75a70cf9 10267 bind_body = maybe_catch_exception (bind_body);
61e47ac8 10268
48e1416a 10269 t = gimple_build_omp_return
75a70cf9 10270 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt),
10271 OMP_CLAUSE_NOWAIT));
bc7bff74 10272 gimple_seq_add_stmt (&bind_body_tail, t);
10273 maybe_add_implicit_barrier_cancel (ctx, &bind_body_tail);
10274 if (ctx->record_type)
10275 {
10276 gimple_stmt_iterator gsi = gsi_start (bind_body_tail);
10277 tree clobber = build_constructor (ctx->record_type, NULL);
10278 TREE_THIS_VOLATILE (clobber) = 1;
10279 gsi_insert_after (&gsi, gimple_build_assign (ctx->sender_decl,
10280 clobber), GSI_SAME_STMT);
10281 }
10282 gimple_seq_add_seq (&bind_body, bind_body_tail);
e3a19533 10283 gimple_bind_set_body (bind, bind_body);
61e47ac8 10284
1e8e9920 10285 pop_gimplify_context (bind);
773c5ba7 10286
75a70cf9 10287 gimple_bind_append_vars (bind, ctx->block_vars);
10288 BLOCK_VARS (block) = ctx->block_vars;
1d22f541 10289 if (BLOCK_VARS (block))
10290 TREE_USED (block) = 1;
1e8e9920 10291}
10292
773c5ba7 10293
1e8e9920 10294/* Expand code for an OpenMP master directive. */
10295
10296static void
75a70cf9 10297lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
1e8e9920 10298{
b9a16870 10299 tree block, lab = NULL, x, bfn_decl;
1a91d914 10300 gimple stmt = gsi_stmt (*gsi_p);
10301 gbind *bind;
389dd41b 10302 location_t loc = gimple_location (stmt);
75a70cf9 10303 gimple_seq tseq;
1e8e9920 10304
8a4a28a8 10305 push_gimplify_context ();
1e8e9920 10306
10307 block = make_node (BLOCK);
e3a19533 10308 bind = gimple_build_bind (NULL, NULL, block);
10309 gsi_replace (gsi_p, bind, true);
10310 gimple_bind_add_stmt (bind, stmt);
61e47ac8 10311
b9a16870 10312 bfn_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
10313 x = build_call_expr_loc (loc, bfn_decl, 0);
1e8e9920 10314 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
10315 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
75a70cf9 10316 tseq = NULL;
10317 gimplify_and_add (x, &tseq);
10318 gimple_bind_add_seq (bind, tseq);
1e8e9920 10319
e3a19533 10320 lower_omp (gimple_omp_body_ptr (stmt), ctx);
75a70cf9 10321 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
10322 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10323 gimple_omp_set_body (stmt, NULL);
1e8e9920 10324
75a70cf9 10325 gimple_bind_add_stmt (bind, gimple_build_label (lab));
61e47ac8 10326
75a70cf9 10327 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
61e47ac8 10328
1e8e9920 10329 pop_gimplify_context (bind);
773c5ba7 10330
75a70cf9 10331 gimple_bind_append_vars (bind, ctx->block_vars);
10332 BLOCK_VARS (block) = ctx->block_vars;
1e8e9920 10333}
10334
773c5ba7 10335
bc7bff74 10336/* Expand code for an OpenMP taskgroup directive. */
10337
10338static void
10339lower_omp_taskgroup (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10340{
1a91d914 10341 gimple stmt = gsi_stmt (*gsi_p);
10342 gcall *x;
10343 gbind *bind;
bc7bff74 10344 tree block = make_node (BLOCK);
10345
10346 bind = gimple_build_bind (NULL, NULL, block);
10347 gsi_replace (gsi_p, bind, true);
10348 gimple_bind_add_stmt (bind, stmt);
10349
10350 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START),
10351 0);
10352 gimple_bind_add_stmt (bind, x);
10353
10354 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10355 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10356 gimple_omp_set_body (stmt, NULL);
10357
10358 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
10359
10360 gimple_bind_append_vars (bind, ctx->block_vars);
10361 BLOCK_VARS (block) = ctx->block_vars;
10362}
10363
10364
1e8e9920 10365/* Expand code for an OpenMP ordered directive. */
10366
10367static void
75a70cf9 10368lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
1e8e9920 10369{
75a70cf9 10370 tree block;
1a91d914 10371 gimple stmt = gsi_stmt (*gsi_p);
10372 gcall *x;
10373 gbind *bind;
1e8e9920 10374
8a4a28a8 10375 push_gimplify_context ();
1e8e9920 10376
10377 block = make_node (BLOCK);
e3a19533 10378 bind = gimple_build_bind (NULL, NULL, block);
10379 gsi_replace (gsi_p, bind, true);
10380 gimple_bind_add_stmt (bind, stmt);
61e47ac8 10381
b9a16870 10382 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START),
10383 0);
75a70cf9 10384 gimple_bind_add_stmt (bind, x);
1e8e9920 10385
e3a19533 10386 lower_omp (gimple_omp_body_ptr (stmt), ctx);
75a70cf9 10387 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
10388 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10389 gimple_omp_set_body (stmt, NULL);
1e8e9920 10390
b9a16870 10391 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END), 0);
75a70cf9 10392 gimple_bind_add_stmt (bind, x);
61e47ac8 10393
75a70cf9 10394 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
61e47ac8 10395
1e8e9920 10396 pop_gimplify_context (bind);
773c5ba7 10397
75a70cf9 10398 gimple_bind_append_vars (bind, ctx->block_vars);
10399 BLOCK_VARS (block) = gimple_bind_vars (bind);
1e8e9920 10400}
10401
1e8e9920 10402
75a70cf9 10403/* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
1e8e9920 10404 substitution of a couple of function calls. But in the NAMED case,
10405 requires that languages coordinate a symbol name. It is therefore
10406 best put here in common code. */
10407
d4786b13 10408static GTY(()) hash_map<tree, tree> *critical_name_mutexes;
1e8e9920 10409
10410static void
75a70cf9 10411lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
1e8e9920 10412{
75a70cf9 10413 tree block;
10414 tree name, lock, unlock;
1a91d914 10415 gomp_critical *stmt = as_a <gomp_critical *> (gsi_stmt (*gsi_p));
10416 gbind *bind;
389dd41b 10417 location_t loc = gimple_location (stmt);
75a70cf9 10418 gimple_seq tbody;
1e8e9920 10419
75a70cf9 10420 name = gimple_omp_critical_name (stmt);
1e8e9920 10421 if (name)
10422 {
c2f47e15 10423 tree decl;
1e8e9920 10424
10425 if (!critical_name_mutexes)
d4786b13 10426 critical_name_mutexes = hash_map<tree, tree>::create_ggc (10);
1e8e9920 10427
d4786b13 10428 tree *n = critical_name_mutexes->get (name);
1e8e9920 10429 if (n == NULL)
10430 {
10431 char *new_str;
10432
f9e245b2 10433 decl = create_tmp_var_raw (ptr_type_node);
1e8e9920 10434
10435 new_str = ACONCAT ((".gomp_critical_user_",
10436 IDENTIFIER_POINTER (name), NULL));
10437 DECL_NAME (decl) = get_identifier (new_str);
10438 TREE_PUBLIC (decl) = 1;
10439 TREE_STATIC (decl) = 1;
10440 DECL_COMMON (decl) = 1;
10441 DECL_ARTIFICIAL (decl) = 1;
10442 DECL_IGNORED_P (decl) = 1;
b0c5e347 10443
97221fd7 10444 varpool_node::finalize_decl (decl);
1e8e9920 10445
d4786b13 10446 critical_name_mutexes->put (name, decl);
1e8e9920 10447 }
10448 else
d4786b13 10449 decl = *n;
1e8e9920 10450
ca4c3545 10451 /* If '#pragma omp critical' is inside offloaded region or
351fb0ce 10452 inside function marked as offloadable, the symbol must be
10453 marked as offloadable too. */
10454 omp_context *octx;
10455 if (cgraph_node::get (current_function_decl)->offloadable)
10456 varpool_node::get_create (decl)->offloadable = 1;
10457 else
10458 for (octx = ctx->outer; octx; octx = octx->outer)
ca4c3545 10459 if (is_gimple_omp_offloaded (octx->stmt))
351fb0ce 10460 {
10461 varpool_node::get_create (decl)->offloadable = 1;
10462 break;
10463 }
10464
b9a16870 10465 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START);
389dd41b 10466 lock = build_call_expr_loc (loc, lock, 1, build_fold_addr_expr_loc (loc, decl));
1e8e9920 10467
b9a16870 10468 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END);
389dd41b 10469 unlock = build_call_expr_loc (loc, unlock, 1,
10470 build_fold_addr_expr_loc (loc, decl));
1e8e9920 10471 }
10472 else
10473 {
b9a16870 10474 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START);
389dd41b 10475 lock = build_call_expr_loc (loc, lock, 0);
1e8e9920 10476
b9a16870 10477 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END);
389dd41b 10478 unlock = build_call_expr_loc (loc, unlock, 0);
1e8e9920 10479 }
10480
8a4a28a8 10481 push_gimplify_context ();
1e8e9920 10482
10483 block = make_node (BLOCK);
e3a19533 10484 bind = gimple_build_bind (NULL, NULL, block);
10485 gsi_replace (gsi_p, bind, true);
10486 gimple_bind_add_stmt (bind, stmt);
61e47ac8 10487
75a70cf9 10488 tbody = gimple_bind_body (bind);
10489 gimplify_and_add (lock, &tbody);
10490 gimple_bind_set_body (bind, tbody);
1e8e9920 10491
e3a19533 10492 lower_omp (gimple_omp_body_ptr (stmt), ctx);
75a70cf9 10493 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
10494 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10495 gimple_omp_set_body (stmt, NULL);
1e8e9920 10496
75a70cf9 10497 tbody = gimple_bind_body (bind);
10498 gimplify_and_add (unlock, &tbody);
10499 gimple_bind_set_body (bind, tbody);
61e47ac8 10500
75a70cf9 10501 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
1e8e9920 10502
10503 pop_gimplify_context (bind);
75a70cf9 10504 gimple_bind_append_vars (bind, ctx->block_vars);
10505 BLOCK_VARS (block) = gimple_bind_vars (bind);
773c5ba7 10506}
10507
10508
10509/* A subroutine of lower_omp_for. Generate code to emit the predicate
10510 for a lastprivate clause. Given a loop control predicate of (V
10511 cond N2), we gate the clause on (!(V cond N2)). The lowered form
1e4afe3c 10512 is appended to *DLIST, iterator initialization is appended to
10513 *BODY_P. */
773c5ba7 10514
10515static void
75a70cf9 10516lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
10517 gimple_seq *dlist, struct omp_context *ctx)
773c5ba7 10518{
75a70cf9 10519 tree clauses, cond, vinit;
773c5ba7 10520 enum tree_code cond_code;
75a70cf9 10521 gimple_seq stmts;
48e1416a 10522
fd6481cf 10523 cond_code = fd->loop.cond_code;
773c5ba7 10524 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
10525
10526 /* When possible, use a strict equality expression. This can let VRP
10527 type optimizations deduce the value and remove a copy. */
e913b5cd 10528 if (tree_fits_shwi_p (fd->loop.step))
773c5ba7 10529 {
e913b5cd 10530 HOST_WIDE_INT step = tree_to_shwi (fd->loop.step);
773c5ba7 10531 if (step == 1 || step == -1)
10532 cond_code = EQ_EXPR;
10533 }
10534
d7729e26 10535 tree n2 = fd->loop.n2;
10536 if (fd->collapse > 1
10537 && TREE_CODE (n2) != INTEGER_CST
10538 && gimple_omp_for_combined_into_p (fd->for_stmt)
10539 && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_FOR)
10540 {
10541 gomp_for *gfor = as_a <gomp_for *> (ctx->outer->stmt);
10542 if (gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_FOR)
10543 {
10544 struct omp_for_data outer_fd;
10545 extract_omp_for_data (gfor, &outer_fd, NULL);
10546 n2 = fold_convert (TREE_TYPE (n2), outer_fd.loop.n2);
10547 }
10548 }
10549 cond = build2 (cond_code, boolean_type_node, fd->loop.v, n2);
773c5ba7 10550
75a70cf9 10551 clauses = gimple_omp_for_clauses (fd->for_stmt);
1e4afe3c 10552 stmts = NULL;
10553 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
75a70cf9 10554 if (!gimple_seq_empty_p (stmts))
1e4afe3c 10555 {
75a70cf9 10556 gimple_seq_add_seq (&stmts, *dlist);
fd6481cf 10557 *dlist = stmts;
1e4afe3c 10558
10559 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
fd6481cf 10560 vinit = fd->loop.n1;
1e4afe3c 10561 if (cond_code == EQ_EXPR
e913b5cd 10562 && tree_fits_shwi_p (fd->loop.n2)
fd6481cf 10563 && ! integer_zerop (fd->loop.n2))
10564 vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0);
3d483a94 10565 else
10566 vinit = unshare_expr (vinit);
1e4afe3c 10567
10568 /* Initialize the iterator variable, so that threads that don't execute
10569 any iterations don't execute the lastprivate clauses by accident. */
75a70cf9 10570 gimplify_assign (fd->loop.v, vinit, body_p);
1e4afe3c 10571 }
773c5ba7 10572}
10573
10574
ca4c3545 10575/* Lower code for an OMP loop directive. */
773c5ba7 10576
10577static void
75a70cf9 10578lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
773c5ba7 10579{
75a70cf9 10580 tree *rhs_p, block;
bc7bff74 10581 struct omp_for_data fd, *fdp = NULL;
1a91d914 10582 gomp_for *stmt = as_a <gomp_for *> (gsi_stmt (*gsi_p));
10583 gbind *new_stmt;
f018d957 10584 gimple_seq omp_for_body, body, dlist;
75a70cf9 10585 size_t i;
773c5ba7 10586
8a4a28a8 10587 push_gimplify_context ();
773c5ba7 10588
e3a19533 10589 lower_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
773c5ba7 10590
1d22f541 10591 block = make_node (BLOCK);
75a70cf9 10592 new_stmt = gimple_build_bind (NULL, NULL, block);
e3a19533 10593 /* Replace at gsi right away, so that 'stmt' is no member
10594 of a sequence anymore as we're going to add to to a different
10595 one below. */
10596 gsi_replace (gsi_p, new_stmt, true);
1d22f541 10597
773c5ba7 10598 /* Move declaration of temporaries in the loop body before we make
10599 it go away. */
75a70cf9 10600 omp_for_body = gimple_omp_body (stmt);
10601 if (!gimple_seq_empty_p (omp_for_body)
10602 && gimple_code (gimple_seq_first_stmt (omp_for_body)) == GIMPLE_BIND)
10603 {
1a91d914 10604 gbind *inner_bind
10605 = as_a <gbind *> (gimple_seq_first_stmt (omp_for_body));
6d5a8d89 10606 tree vars = gimple_bind_vars (inner_bind);
75a70cf9 10607 gimple_bind_append_vars (new_stmt, vars);
6d5a8d89 10608 /* bind_vars/BLOCK_VARS are being moved to new_stmt/block, don't
10609 keep them on the inner_bind and it's block. */
10610 gimple_bind_set_vars (inner_bind, NULL_TREE);
10611 if (gimple_bind_block (inner_bind))
10612 BLOCK_VARS (gimple_bind_block (inner_bind)) = NULL_TREE;
75a70cf9 10613 }
773c5ba7 10614
bc7bff74 10615 if (gimple_omp_for_combined_into_p (stmt))
10616 {
10617 extract_omp_for_data (stmt, &fd, NULL);
10618 fdp = &fd;
10619
10620 /* We need two temporaries with fd.loop.v type (istart/iend)
10621 and then (fd.collapse - 1) temporaries with the same
10622 type for count2 ... countN-1 vars if not constant. */
10623 size_t count = 2;
10624 tree type = fd.iter_type;
10625 if (fd.collapse > 1
10626 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
10627 count += fd.collapse - 1;
10628 bool parallel_for = gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR;
10629 tree outerc = NULL, *pc = gimple_omp_for_clauses_ptr (stmt);
10630 tree clauses = *pc;
10631 if (parallel_for)
10632 outerc
10633 = find_omp_clause (gimple_omp_parallel_clauses (ctx->outer->stmt),
10634 OMP_CLAUSE__LOOPTEMP_);
10635 for (i = 0; i < count; i++)
10636 {
10637 tree temp;
10638 if (parallel_for)
10639 {
10640 gcc_assert (outerc);
10641 temp = lookup_decl (OMP_CLAUSE_DECL (outerc), ctx->outer);
10642 outerc = find_omp_clause (OMP_CLAUSE_CHAIN (outerc),
10643 OMP_CLAUSE__LOOPTEMP_);
10644 }
10645 else
691447ab 10646 {
f9e245b2 10647 temp = create_tmp_var (type);
691447ab 10648 insert_decl_map (&ctx->outer->cb, temp, temp);
10649 }
bc7bff74 10650 *pc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
10651 OMP_CLAUSE_DECL (*pc) = temp;
10652 pc = &OMP_CLAUSE_CHAIN (*pc);
10653 }
10654 *pc = clauses;
10655 }
10656
75a70cf9 10657 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
773c5ba7 10658 dlist = NULL;
75a70cf9 10659 body = NULL;
bc7bff74 10660 lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx,
10661 fdp);
75a70cf9 10662 gimple_seq_add_seq (&body, gimple_omp_for_pre_body (stmt));
773c5ba7 10663
3d483a94 10664 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10665
773c5ba7 10666 /* Lower the header expressions. At this point, we can assume that
10667 the header is of the form:
10668
10669 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
10670
10671 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
10672 using the .omp_data_s mapping, if needed. */
75a70cf9 10673 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
fd6481cf 10674 {
75a70cf9 10675 rhs_p = gimple_omp_for_initial_ptr (stmt, i);
fd6481cf 10676 if (!is_gimple_min_invariant (*rhs_p))
75a70cf9 10677 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
fd6481cf 10678
75a70cf9 10679 rhs_p = gimple_omp_for_final_ptr (stmt, i);
fd6481cf 10680 if (!is_gimple_min_invariant (*rhs_p))
75a70cf9 10681 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
fd6481cf 10682
75a70cf9 10683 rhs_p = &TREE_OPERAND (gimple_omp_for_incr (stmt, i), 1);
fd6481cf 10684 if (!is_gimple_min_invariant (*rhs_p))
75a70cf9 10685 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
fd6481cf 10686 }
773c5ba7 10687
10688 /* Once lowered, extract the bounds and clauses. */
fd6481cf 10689 extract_omp_for_data (stmt, &fd, NULL);
773c5ba7 10690
75a70cf9 10691 lower_omp_for_lastprivate (&fd, &body, &dlist, ctx);
773c5ba7 10692
75a70cf9 10693 gimple_seq_add_stmt (&body, stmt);
10694 gimple_seq_add_seq (&body, gimple_omp_body (stmt));
61e47ac8 10695
75a70cf9 10696 gimple_seq_add_stmt (&body, gimple_build_omp_continue (fd.loop.v,
10697 fd.loop.v));
61e47ac8 10698
773c5ba7 10699 /* After the loop, add exit clauses. */
75a70cf9 10700 lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, ctx);
bc7bff74 10701
10702 if (ctx->cancellable)
10703 gimple_seq_add_stmt (&body, gimple_build_label (ctx->cancel_label));
10704
75a70cf9 10705 gimple_seq_add_seq (&body, dlist);
773c5ba7 10706
75a70cf9 10707 body = maybe_catch_exception (body);
aade31a0 10708
61e47ac8 10709 /* Region exit marker goes at the end of the loop body. */
75a70cf9 10710 gimple_seq_add_stmt (&body, gimple_build_omp_return (fd.have_nowait));
bc7bff74 10711 maybe_add_implicit_barrier_cancel (ctx, &body);
1d22f541 10712 pop_gimplify_context (new_stmt);
75a70cf9 10713
10714 gimple_bind_append_vars (new_stmt, ctx->block_vars);
10715 BLOCK_VARS (block) = gimple_bind_vars (new_stmt);
1d22f541 10716 if (BLOCK_VARS (block))
10717 TREE_USED (block) = 1;
773c5ba7 10718
75a70cf9 10719 gimple_bind_set_body (new_stmt, body);
10720 gimple_omp_set_body (stmt, NULL);
10721 gimple_omp_for_set_pre_body (stmt, NULL);
1e8e9920 10722}
10723
48e1416a 10724/* Callback for walk_stmts. Check if the current statement only contains
a7dfc4fe 10725 GIMPLE_OMP_FOR or GIMPLE_OMP_SECTIONS. */
de7ef844 10726
10727static tree
75a70cf9 10728check_combined_parallel (gimple_stmt_iterator *gsi_p,
10729 bool *handled_ops_p,
10730 struct walk_stmt_info *wi)
de7ef844 10731{
4077bf7a 10732 int *info = (int *) wi->info;
75a70cf9 10733 gimple stmt = gsi_stmt (*gsi_p);
de7ef844 10734
75a70cf9 10735 *handled_ops_p = true;
10736 switch (gimple_code (stmt))
de7ef844 10737 {
75a70cf9 10738 WALK_SUBSTMTS;
10739
10740 case GIMPLE_OMP_FOR:
10741 case GIMPLE_OMP_SECTIONS:
de7ef844 10742 *info = *info == 0 ? 1 : -1;
10743 break;
10744 default:
10745 *info = -1;
10746 break;
10747 }
10748 return NULL;
10749}
773c5ba7 10750
fd6481cf 10751struct omp_taskcopy_context
10752{
10753 /* This field must be at the beginning, as we do "inheritance": Some
10754 callback functions for tree-inline.c (e.g., omp_copy_decl)
10755 receive a copy_body_data pointer that is up-casted to an
10756 omp_context pointer. */
10757 copy_body_data cb;
10758 omp_context *ctx;
10759};
10760
10761static tree
10762task_copyfn_copy_decl (tree var, copy_body_data *cb)
10763{
10764 struct omp_taskcopy_context *tcctx = (struct omp_taskcopy_context *) cb;
10765
10766 if (splay_tree_lookup (tcctx->ctx->sfield_map, (splay_tree_key) var))
f9e245b2 10767 return create_tmp_var (TREE_TYPE (var));
fd6481cf 10768
10769 return var;
10770}
10771
10772static tree
10773task_copyfn_remap_type (struct omp_taskcopy_context *tcctx, tree orig_type)
10774{
10775 tree name, new_fields = NULL, type, f;
10776
10777 type = lang_hooks.types.make_type (RECORD_TYPE);
10778 name = DECL_NAME (TYPE_NAME (orig_type));
e60a6f7b 10779 name = build_decl (gimple_location (tcctx->ctx->stmt),
10780 TYPE_DECL, name, type);
fd6481cf 10781 TYPE_NAME (type) = name;
10782
10783 for (f = TYPE_FIELDS (orig_type); f ; f = TREE_CHAIN (f))
10784 {
10785 tree new_f = copy_node (f);
10786 DECL_CONTEXT (new_f) = type;
10787 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &tcctx->cb);
10788 TREE_CHAIN (new_f) = new_fields;
75a70cf9 10789 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &tcctx->cb, NULL);
10790 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r, &tcctx->cb, NULL);
10791 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
10792 &tcctx->cb, NULL);
fd6481cf 10793 new_fields = new_f;
06ecf488 10794 tcctx->cb.decl_map->put (f, new_f);
fd6481cf 10795 }
10796 TYPE_FIELDS (type) = nreverse (new_fields);
10797 layout_type (type);
10798 return type;
10799}
10800
10801/* Create task copyfn. */
10802
10803static void
1a91d914 10804create_task_copyfn (gomp_task *task_stmt, omp_context *ctx)
fd6481cf 10805{
10806 struct function *child_cfun;
10807 tree child_fn, t, c, src, dst, f, sf, arg, sarg, decl;
10808 tree record_type, srecord_type, bind, list;
10809 bool record_needs_remap = false, srecord_needs_remap = false;
10810 splay_tree_node n;
10811 struct omp_taskcopy_context tcctx;
389dd41b 10812 location_t loc = gimple_location (task_stmt);
fd6481cf 10813
75a70cf9 10814 child_fn = gimple_omp_task_copy_fn (task_stmt);
fd6481cf 10815 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
10816 gcc_assert (child_cfun->cfg == NULL);
fd6481cf 10817 DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
10818
10819 /* Reset DECL_CONTEXT on function arguments. */
1767a056 10820 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
fd6481cf 10821 DECL_CONTEXT (t) = child_fn;
10822
10823 /* Populate the function. */
8a4a28a8 10824 push_gimplify_context ();
9078126c 10825 push_cfun (child_cfun);
fd6481cf 10826
10827 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
10828 TREE_SIDE_EFFECTS (bind) = 1;
10829 list = NULL;
10830 DECL_SAVED_TREE (child_fn) = bind;
75a70cf9 10831 DECL_SOURCE_LOCATION (child_fn) = gimple_location (task_stmt);
fd6481cf 10832
10833 /* Remap src and dst argument types if needed. */
10834 record_type = ctx->record_type;
10835 srecord_type = ctx->srecord_type;
1767a056 10836 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
fd6481cf 10837 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
10838 {
10839 record_needs_remap = true;
10840 break;
10841 }
1767a056 10842 for (f = TYPE_FIELDS (srecord_type); f ; f = DECL_CHAIN (f))
fd6481cf 10843 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
10844 {
10845 srecord_needs_remap = true;
10846 break;
10847 }
10848
10849 if (record_needs_remap || srecord_needs_remap)
10850 {
10851 memset (&tcctx, '\0', sizeof (tcctx));
10852 tcctx.cb.src_fn = ctx->cb.src_fn;
10853 tcctx.cb.dst_fn = child_fn;
415d1b9a 10854 tcctx.cb.src_node = cgraph_node::get (tcctx.cb.src_fn);
53f79206 10855 gcc_checking_assert (tcctx.cb.src_node);
fd6481cf 10856 tcctx.cb.dst_node = tcctx.cb.src_node;
10857 tcctx.cb.src_cfun = ctx->cb.src_cfun;
10858 tcctx.cb.copy_decl = task_copyfn_copy_decl;
e38def9c 10859 tcctx.cb.eh_lp_nr = 0;
fd6481cf 10860 tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
06ecf488 10861 tcctx.cb.decl_map = new hash_map<tree, tree>;
fd6481cf 10862 tcctx.ctx = ctx;
10863
10864 if (record_needs_remap)
10865 record_type = task_copyfn_remap_type (&tcctx, record_type);
10866 if (srecord_needs_remap)
10867 srecord_type = task_copyfn_remap_type (&tcctx, srecord_type);
10868 }
10869 else
10870 tcctx.cb.decl_map = NULL;
10871
fd6481cf 10872 arg = DECL_ARGUMENTS (child_fn);
10873 TREE_TYPE (arg) = build_pointer_type (record_type);
1767a056 10874 sarg = DECL_CHAIN (arg);
fd6481cf 10875 TREE_TYPE (sarg) = build_pointer_type (srecord_type);
10876
10877 /* First pass: initialize temporaries used in record_type and srecord_type
10878 sizes and field offsets. */
10879 if (tcctx.cb.decl_map)
75a70cf9 10880 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
fd6481cf 10881 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
10882 {
10883 tree *p;
10884
10885 decl = OMP_CLAUSE_DECL (c);
06ecf488 10886 p = tcctx.cb.decl_map->get (decl);
fd6481cf 10887 if (p == NULL)
10888 continue;
10889 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
10890 sf = (tree) n->value;
06ecf488 10891 sf = *tcctx.cb.decl_map->get (sf);
182cf5a9 10892 src = build_simple_mem_ref_loc (loc, sarg);
445d06b6 10893 src = omp_build_component_ref (src, sf);
75a70cf9 10894 t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
fd6481cf 10895 append_to_statement_list (t, &list);
10896 }
10897
10898 /* Second pass: copy shared var pointers and copy construct non-VLA
10899 firstprivate vars. */
75a70cf9 10900 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
fd6481cf 10901 switch (OMP_CLAUSE_CODE (c))
10902 {
10903 case OMP_CLAUSE_SHARED:
10904 decl = OMP_CLAUSE_DECL (c);
10905 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
10906 if (n == NULL)
10907 break;
10908 f = (tree) n->value;
10909 if (tcctx.cb.decl_map)
06ecf488 10910 f = *tcctx.cb.decl_map->get (f);
fd6481cf 10911 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
10912 sf = (tree) n->value;
10913 if (tcctx.cb.decl_map)
06ecf488 10914 sf = *tcctx.cb.decl_map->get (sf);
182cf5a9 10915 src = build_simple_mem_ref_loc (loc, sarg);
445d06b6 10916 src = omp_build_component_ref (src, sf);
182cf5a9 10917 dst = build_simple_mem_ref_loc (loc, arg);
445d06b6 10918 dst = omp_build_component_ref (dst, f);
75a70cf9 10919 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
fd6481cf 10920 append_to_statement_list (t, &list);
10921 break;
10922 case OMP_CLAUSE_FIRSTPRIVATE:
10923 decl = OMP_CLAUSE_DECL (c);
10924 if (is_variable_sized (decl))
10925 break;
10926 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
10927 if (n == NULL)
10928 break;
10929 f = (tree) n->value;
10930 if (tcctx.cb.decl_map)
06ecf488 10931 f = *tcctx.cb.decl_map->get (f);
fd6481cf 10932 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
10933 if (n != NULL)
10934 {
10935 sf = (tree) n->value;
10936 if (tcctx.cb.decl_map)
06ecf488 10937 sf = *tcctx.cb.decl_map->get (sf);
182cf5a9 10938 src = build_simple_mem_ref_loc (loc, sarg);
445d06b6 10939 src = omp_build_component_ref (src, sf);
fd6481cf 10940 if (use_pointer_for_field (decl, NULL) || is_reference (decl))
182cf5a9 10941 src = build_simple_mem_ref_loc (loc, src);
fd6481cf 10942 }
10943 else
10944 src = decl;
182cf5a9 10945 dst = build_simple_mem_ref_loc (loc, arg);
445d06b6 10946 dst = omp_build_component_ref (dst, f);
fd6481cf 10947 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
10948 append_to_statement_list (t, &list);
10949 break;
10950 case OMP_CLAUSE_PRIVATE:
10951 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c))
10952 break;
10953 decl = OMP_CLAUSE_DECL (c);
10954 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
10955 f = (tree) n->value;
10956 if (tcctx.cb.decl_map)
06ecf488 10957 f = *tcctx.cb.decl_map->get (f);
fd6481cf 10958 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
10959 if (n != NULL)
10960 {
10961 sf = (tree) n->value;
10962 if (tcctx.cb.decl_map)
06ecf488 10963 sf = *tcctx.cb.decl_map->get (sf);
182cf5a9 10964 src = build_simple_mem_ref_loc (loc, sarg);
445d06b6 10965 src = omp_build_component_ref (src, sf);
fd6481cf 10966 if (use_pointer_for_field (decl, NULL))
182cf5a9 10967 src = build_simple_mem_ref_loc (loc, src);
fd6481cf 10968 }
10969 else
10970 src = decl;
182cf5a9 10971 dst = build_simple_mem_ref_loc (loc, arg);
445d06b6 10972 dst = omp_build_component_ref (dst, f);
75a70cf9 10973 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
fd6481cf 10974 append_to_statement_list (t, &list);
10975 break;
10976 default:
10977 break;
10978 }
10979
10980 /* Last pass: handle VLA firstprivates. */
10981 if (tcctx.cb.decl_map)
75a70cf9 10982 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
fd6481cf 10983 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
10984 {
10985 tree ind, ptr, df;
10986
10987 decl = OMP_CLAUSE_DECL (c);
10988 if (!is_variable_sized (decl))
10989 continue;
10990 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
10991 if (n == NULL)
10992 continue;
10993 f = (tree) n->value;
06ecf488 10994 f = *tcctx.cb.decl_map->get (f);
fd6481cf 10995 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
10996 ind = DECL_VALUE_EXPR (decl);
10997 gcc_assert (TREE_CODE (ind) == INDIRECT_REF);
10998 gcc_assert (DECL_P (TREE_OPERAND (ind, 0)));
10999 n = splay_tree_lookup (ctx->sfield_map,
11000 (splay_tree_key) TREE_OPERAND (ind, 0));
11001 sf = (tree) n->value;
06ecf488 11002 sf = *tcctx.cb.decl_map->get (sf);
182cf5a9 11003 src = build_simple_mem_ref_loc (loc, sarg);
445d06b6 11004 src = omp_build_component_ref (src, sf);
182cf5a9 11005 src = build_simple_mem_ref_loc (loc, src);
11006 dst = build_simple_mem_ref_loc (loc, arg);
445d06b6 11007 dst = omp_build_component_ref (dst, f);
fd6481cf 11008 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
11009 append_to_statement_list (t, &list);
11010 n = splay_tree_lookup (ctx->field_map,
11011 (splay_tree_key) TREE_OPERAND (ind, 0));
11012 df = (tree) n->value;
06ecf488 11013 df = *tcctx.cb.decl_map->get (df);
182cf5a9 11014 ptr = build_simple_mem_ref_loc (loc, arg);
445d06b6 11015 ptr = omp_build_component_ref (ptr, df);
75a70cf9 11016 t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
389dd41b 11017 build_fold_addr_expr_loc (loc, dst));
fd6481cf 11018 append_to_statement_list (t, &list);
11019 }
11020
11021 t = build1 (RETURN_EXPR, void_type_node, NULL);
11022 append_to_statement_list (t, &list);
11023
11024 if (tcctx.cb.decl_map)
06ecf488 11025 delete tcctx.cb.decl_map;
fd6481cf 11026 pop_gimplify_context (NULL);
11027 BIND_EXPR_BODY (bind) = list;
11028 pop_cfun ();
fd6481cf 11029}
11030
bc7bff74 11031static void
11032lower_depend_clauses (gimple stmt, gimple_seq *iseq, gimple_seq *oseq)
11033{
11034 tree c, clauses;
11035 gimple g;
11036 size_t n_in = 0, n_out = 0, idx = 2, i;
11037
11038 clauses = find_omp_clause (gimple_omp_task_clauses (stmt),
11039 OMP_CLAUSE_DEPEND);
11040 gcc_assert (clauses);
11041 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
11042 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
11043 switch (OMP_CLAUSE_DEPEND_KIND (c))
11044 {
11045 case OMP_CLAUSE_DEPEND_IN:
11046 n_in++;
11047 break;
11048 case OMP_CLAUSE_DEPEND_OUT:
11049 case OMP_CLAUSE_DEPEND_INOUT:
11050 n_out++;
11051 break;
11052 default:
11053 gcc_unreachable ();
11054 }
11055 tree type = build_array_type_nelts (ptr_type_node, n_in + n_out + 2);
f9e245b2 11056 tree array = create_tmp_var (type);
bc7bff74 11057 tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
11058 NULL_TREE);
11059 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_in + n_out));
11060 gimple_seq_add_stmt (iseq, g);
11061 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
11062 NULL_TREE);
11063 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_out));
11064 gimple_seq_add_stmt (iseq, g);
11065 for (i = 0; i < 2; i++)
11066 {
11067 if ((i ? n_in : n_out) == 0)
11068 continue;
11069 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
11070 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
11071 && ((OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_IN) ^ i))
11072 {
11073 tree t = OMP_CLAUSE_DECL (c);
11074 t = fold_convert (ptr_type_node, t);
11075 gimplify_expr (&t, iseq, NULL, is_gimple_val, fb_rvalue);
11076 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (idx++),
11077 NULL_TREE, NULL_TREE);
11078 g = gimple_build_assign (r, t);
11079 gimple_seq_add_stmt (iseq, g);
11080 }
11081 }
11082 tree *p = gimple_omp_task_clauses_ptr (stmt);
11083 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
11084 OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
11085 OMP_CLAUSE_CHAIN (c) = *p;
11086 *p = c;
11087 tree clobber = build_constructor (type, NULL);
11088 TREE_THIS_VOLATILE (clobber) = 1;
11089 g = gimple_build_assign (array, clobber);
11090 gimple_seq_add_stmt (oseq, g);
11091}
11092
75a70cf9 11093/* Lower the OpenMP parallel or task directive in the current statement
11094 in GSI_P. CTX holds context information for the directive. */
773c5ba7 11095
11096static void
75a70cf9 11097lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
773c5ba7 11098{
75a70cf9 11099 tree clauses;
11100 tree child_fn, t;
11101 gimple stmt = gsi_stmt (*gsi_p);
1a91d914 11102 gbind *par_bind, *bind, *dep_bind = NULL;
bc7bff74 11103 gimple_seq par_body, olist, ilist, par_olist, par_rlist, par_ilist, new_body;
389dd41b 11104 location_t loc = gimple_location (stmt);
773c5ba7 11105
75a70cf9 11106 clauses = gimple_omp_taskreg_clauses (stmt);
1a91d914 11107 par_bind
11108 = as_a <gbind *> (gimple_seq_first_stmt (gimple_omp_body (stmt)));
75a70cf9 11109 par_body = gimple_bind_body (par_bind);
773c5ba7 11110 child_fn = ctx->cb.dst_fn;
75a70cf9 11111 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
11112 && !gimple_omp_parallel_combined_p (stmt))
de7ef844 11113 {
11114 struct walk_stmt_info wi;
11115 int ws_num = 0;
11116
11117 memset (&wi, 0, sizeof (wi));
de7ef844 11118 wi.info = &ws_num;
11119 wi.val_only = true;
75a70cf9 11120 walk_gimple_seq (par_body, check_combined_parallel, NULL, &wi);
de7ef844 11121 if (ws_num == 1)
75a70cf9 11122 gimple_omp_parallel_set_combined_p (stmt, true);
de7ef844 11123 }
bc7bff74 11124 gimple_seq dep_ilist = NULL;
11125 gimple_seq dep_olist = NULL;
11126 if (gimple_code (stmt) == GIMPLE_OMP_TASK
11127 && find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
11128 {
8a4a28a8 11129 push_gimplify_context ();
bc7bff74 11130 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
11131 lower_depend_clauses (stmt, &dep_ilist, &dep_olist);
11132 }
11133
fd6481cf 11134 if (ctx->srecord_type)
1a91d914 11135 create_task_copyfn (as_a <gomp_task *> (stmt), ctx);
773c5ba7 11136
8a4a28a8 11137 push_gimplify_context ();
773c5ba7 11138
75a70cf9 11139 par_olist = NULL;
11140 par_ilist = NULL;
bc7bff74 11141 par_rlist = NULL;
11142 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx, NULL);
e3a19533 11143 lower_omp (&par_body, ctx);
75a70cf9 11144 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL)
bc7bff74 11145 lower_reduction_clauses (clauses, &par_rlist, ctx);
773c5ba7 11146
11147 /* Declare all the variables created by mapping and the variables
11148 declared in the scope of the parallel body. */
11149 record_vars_into (ctx->block_vars, child_fn);
75a70cf9 11150 record_vars_into (gimple_bind_vars (par_bind), child_fn);
773c5ba7 11151
11152 if (ctx->record_type)
11153 {
fd6481cf 11154 ctx->sender_decl
11155 = create_tmp_var (ctx->srecord_type ? ctx->srecord_type
11156 : ctx->record_type, ".omp_data_o");
84bfaaeb 11157 DECL_NAMELESS (ctx->sender_decl) = 1;
86f2ad37 11158 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
75a70cf9 11159 gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl);
773c5ba7 11160 }
11161
75a70cf9 11162 olist = NULL;
11163 ilist = NULL;
773c5ba7 11164 lower_send_clauses (clauses, &ilist, &olist, ctx);
11165 lower_send_shared_vars (&ilist, &olist, ctx);
11166
bc7bff74 11167 if (ctx->record_type)
11168 {
11169 tree clobber = build_constructor (TREE_TYPE (ctx->sender_decl), NULL);
11170 TREE_THIS_VOLATILE (clobber) = 1;
11171 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
11172 clobber));
11173 }
11174
773c5ba7 11175 /* Once all the expansions are done, sequence all the different
75a70cf9 11176 fragments inside gimple_omp_body. */
773c5ba7 11177
75a70cf9 11178 new_body = NULL;
773c5ba7 11179
11180 if (ctx->record_type)
11181 {
389dd41b 11182 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
cc6b725b 11183 /* fixup_child_record_type might have changed receiver_decl's type. */
389dd41b 11184 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
75a70cf9 11185 gimple_seq_add_stmt (&new_body,
11186 gimple_build_assign (ctx->receiver_decl, t));
773c5ba7 11187 }
11188
75a70cf9 11189 gimple_seq_add_seq (&new_body, par_ilist);
11190 gimple_seq_add_seq (&new_body, par_body);
bc7bff74 11191 gimple_seq_add_seq (&new_body, par_rlist);
11192 if (ctx->cancellable)
11193 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
75a70cf9 11194 gimple_seq_add_seq (&new_body, par_olist);
11195 new_body = maybe_catch_exception (new_body);
b25f70fd 11196 if (gimple_code (stmt) == GIMPLE_OMP_TASK)
11197 gimple_seq_add_stmt (&new_body,
11198 gimple_build_omp_continue (integer_zero_node,
11199 integer_zero_node));
75a70cf9 11200 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
11201 gimple_omp_set_body (stmt, new_body);
773c5ba7 11202
75a70cf9 11203 bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
bc7bff74 11204 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
11205 gimple_bind_add_seq (bind, ilist);
11206 gimple_bind_add_stmt (bind, stmt);
11207 gimple_bind_add_seq (bind, olist);
11208
11209 pop_gimplify_context (NULL);
11210
11211 if (dep_bind)
11212 {
11213 gimple_bind_add_seq (dep_bind, dep_ilist);
11214 gimple_bind_add_stmt (dep_bind, bind);
11215 gimple_bind_add_seq (dep_bind, dep_olist);
11216 pop_gimplify_context (dep_bind);
11217 }
11218}
11219
ca4c3545 11220/* Lower the GIMPLE_OMP_TARGET in the current statement
bc7bff74 11221 in GSI_P. CTX holds context information for the directive. */
11222
11223static void
11224lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
11225{
11226 tree clauses;
11227 tree child_fn, t, c;
1a91d914 11228 gomp_target *stmt = as_a <gomp_target *> (gsi_stmt (*gsi_p));
ca4c3545 11229 gbind *tgt_bind, *bind;
11230 gimple_seq tgt_body, olist, ilist, orlist, irlist, new_body;
bc7bff74 11231 location_t loc = gimple_location (stmt);
ca4c3545 11232 bool offloaded, data_region;
bc7bff74 11233 unsigned int map_cnt = 0;
11234
ca4c3545 11235 offloaded = is_gimple_omp_offloaded (stmt);
11236 switch (gimple_omp_target_kind (stmt))
11237 {
11238 case GF_OMP_TARGET_KIND_REGION:
11239 case GF_OMP_TARGET_KIND_UPDATE:
11240 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
11241 case GF_OMP_TARGET_KIND_OACC_KERNELS:
11242 case GF_OMP_TARGET_KIND_OACC_UPDATE:
11243 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
11244 data_region = false;
11245 break;
11246 case GF_OMP_TARGET_KIND_DATA:
11247 case GF_OMP_TARGET_KIND_OACC_DATA:
11248 data_region = true;
11249 break;
11250 default:
11251 gcc_unreachable ();
11252 }
11253
bc7bff74 11254 clauses = gimple_omp_target_clauses (stmt);
ca4c3545 11255
11256 tgt_bind = NULL;
11257 tgt_body = NULL;
11258 if (offloaded)
bc7bff74 11259 {
1a91d914 11260 tgt_bind = gimple_seq_first_stmt_as_a_bind (gimple_omp_body (stmt));
bc7bff74 11261 tgt_body = gimple_bind_body (tgt_bind);
11262 }
ca4c3545 11263 else if (data_region)
bc7bff74 11264 tgt_body = gimple_omp_body (stmt);
11265 child_fn = ctx->cb.dst_fn;
11266
8a4a28a8 11267 push_gimplify_context ();
bc7bff74 11268
ca4c3545 11269 irlist = NULL;
11270 orlist = NULL;
11271 if (offloaded
11272 && is_gimple_omp_oacc (stmt))
11273 oacc_process_reduction_data (&tgt_body, &irlist, &orlist, ctx);
11274
bc7bff74 11275 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
11276 switch (OMP_CLAUSE_CODE (c))
11277 {
11278 tree var, x;
11279
11280 default:
11281 break;
11282 case OMP_CLAUSE_MAP:
ca4c3545 11283#ifdef ENABLE_CHECKING
11284 /* First check what we're prepared to handle in the following. */
11285 switch (OMP_CLAUSE_MAP_KIND (c))
11286 {
11287 case GOMP_MAP_ALLOC:
11288 case GOMP_MAP_TO:
11289 case GOMP_MAP_FROM:
11290 case GOMP_MAP_TOFROM:
11291 case GOMP_MAP_POINTER:
11292 case GOMP_MAP_TO_PSET:
11293 break;
11294 case GOMP_MAP_FORCE_ALLOC:
11295 case GOMP_MAP_FORCE_TO:
11296 case GOMP_MAP_FORCE_FROM:
11297 case GOMP_MAP_FORCE_TOFROM:
11298 case GOMP_MAP_FORCE_PRESENT:
11299 case GOMP_MAP_FORCE_DEALLOC:
11300 case GOMP_MAP_FORCE_DEVICEPTR:
11301 gcc_assert (is_gimple_omp_oacc (stmt));
11302 break;
11303 default:
11304 gcc_unreachable ();
11305 }
11306#endif
11307 /* FALLTHRU */
bc7bff74 11308 case OMP_CLAUSE_TO:
11309 case OMP_CLAUSE_FROM:
11310 var = OMP_CLAUSE_DECL (c);
11311 if (!DECL_P (var))
11312 {
11313 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
11314 || !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
11315 map_cnt++;
11316 continue;
11317 }
11318
11319 if (DECL_SIZE (var)
11320 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
11321 {
11322 tree var2 = DECL_VALUE_EXPR (var);
11323 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
11324 var2 = TREE_OPERAND (var2, 0);
11325 gcc_assert (DECL_P (var2));
11326 var = var2;
11327 }
11328
11329 if (!maybe_lookup_field (var, ctx))
11330 continue;
11331
ca4c3545 11332 if (offloaded)
bc7bff74 11333 {
11334 x = build_receiver_ref (var, true, ctx);
11335 tree new_var = lookup_decl (var, ctx);
ca4c3545 11336 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
bc7bff74 11337 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
11338 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
11339 x = build_simple_mem_ref (x);
11340 SET_DECL_VALUE_EXPR (new_var, x);
11341 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
11342 }
11343 map_cnt++;
11344 }
11345
ca4c3545 11346 if (offloaded)
bc7bff74 11347 {
11348 target_nesting_level++;
11349 lower_omp (&tgt_body, ctx);
11350 target_nesting_level--;
11351 }
ca4c3545 11352 else if (data_region)
bc7bff74 11353 lower_omp (&tgt_body, ctx);
11354
ca4c3545 11355 if (offloaded)
bc7bff74 11356 {
11357 /* Declare all the variables created by mapping and the variables
11358 declared in the scope of the target body. */
11359 record_vars_into (ctx->block_vars, child_fn);
11360 record_vars_into (gimple_bind_vars (tgt_bind), child_fn);
11361 }
11362
11363 olist = NULL;
11364 ilist = NULL;
11365 if (ctx->record_type)
11366 {
11367 ctx->sender_decl
11368 = create_tmp_var (ctx->record_type, ".omp_data_arr");
11369 DECL_NAMELESS (ctx->sender_decl) = 1;
11370 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
11371 t = make_tree_vec (3);
11372 TREE_VEC_ELT (t, 0) = ctx->sender_decl;
11373 TREE_VEC_ELT (t, 1)
11374 = create_tmp_var (build_array_type_nelts (size_type_node, map_cnt),
11375 ".omp_data_sizes");
11376 DECL_NAMELESS (TREE_VEC_ELT (t, 1)) = 1;
11377 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 1)) = 1;
11378 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 1;
ca4c3545 11379 tree tkind_type;
11380 int talign_shift;
11381 if (is_gimple_omp_oacc (stmt))
11382 {
11383 tkind_type = short_unsigned_type_node;
11384 talign_shift = 8;
11385 }
11386 else
11387 {
11388 tkind_type = unsigned_char_type_node;
11389 talign_shift = 3;
11390 }
bc7bff74 11391 TREE_VEC_ELT (t, 2)
ca4c3545 11392 = create_tmp_var (build_array_type_nelts (tkind_type, map_cnt),
bc7bff74 11393 ".omp_data_kinds");
11394 DECL_NAMELESS (TREE_VEC_ELT (t, 2)) = 1;
11395 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 2)) = 1;
11396 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 1;
11397 gimple_omp_target_set_data_arg (stmt, t);
11398
11399 vec<constructor_elt, va_gc> *vsize;
11400 vec<constructor_elt, va_gc> *vkind;
11401 vec_alloc (vsize, map_cnt);
11402 vec_alloc (vkind, map_cnt);
11403 unsigned int map_idx = 0;
11404
11405 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
11406 switch (OMP_CLAUSE_CODE (c))
11407 {
11408 tree ovar, nc;
11409
11410 default:
11411 break;
11412 case OMP_CLAUSE_MAP:
11413 case OMP_CLAUSE_TO:
11414 case OMP_CLAUSE_FROM:
11415 nc = c;
11416 ovar = OMP_CLAUSE_DECL (c);
11417 if (!DECL_P (ovar))
11418 {
11419 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
11420 && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
11421 {
11422 gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c))
11423 == get_base_address (ovar));
11424 nc = OMP_CLAUSE_CHAIN (c);
11425 ovar = OMP_CLAUSE_DECL (nc);
11426 }
11427 else
11428 {
11429 tree x = build_sender_ref (ovar, ctx);
11430 tree v
11431 = build_fold_addr_expr_with_type (ovar, ptr_type_node);
11432 gimplify_assign (x, v, &ilist);
11433 nc = NULL_TREE;
11434 }
11435 }
11436 else
11437 {
11438 if (DECL_SIZE (ovar)
11439 && TREE_CODE (DECL_SIZE (ovar)) != INTEGER_CST)
11440 {
11441 tree ovar2 = DECL_VALUE_EXPR (ovar);
11442 gcc_assert (TREE_CODE (ovar2) == INDIRECT_REF);
11443 ovar2 = TREE_OPERAND (ovar2, 0);
11444 gcc_assert (DECL_P (ovar2));
11445 ovar = ovar2;
11446 }
11447 if (!maybe_lookup_field (ovar, ctx))
11448 continue;
11449 }
11450
4f3b8d78 11451 unsigned int talign = TYPE_ALIGN_UNIT (TREE_TYPE (ovar));
11452 if (DECL_P (ovar) && DECL_ALIGN_UNIT (ovar) > talign)
11453 talign = DECL_ALIGN_UNIT (ovar);
bc7bff74 11454 if (nc)
11455 {
11456 tree var = lookup_decl_in_outer_ctx (ovar, ctx);
11457 tree x = build_sender_ref (ovar, ctx);
ca4c3545 11458 if (maybe_lookup_oacc_reduction (var, ctx))
11459 {
11460 gcc_checking_assert (offloaded
11461 && is_gimple_omp_oacc (stmt));
11462 gimplify_assign (x, var, &ilist);
11463 }
11464 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
11465 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
11466 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
11467 && TREE_CODE (TREE_TYPE (ovar)) == ARRAY_TYPE)
bc7bff74 11468 {
ca4c3545 11469 gcc_assert (offloaded);
bc7bff74 11470 tree avar
f9e245b2 11471 = create_tmp_var (TREE_TYPE (TREE_TYPE (x)));
bc7bff74 11472 mark_addressable (avar);
11473 gimplify_assign (avar, build_fold_addr_expr (var), &ilist);
4f3b8d78 11474 talign = DECL_ALIGN_UNIT (avar);
bc7bff74 11475 avar = build_fold_addr_expr (avar);
11476 gimplify_assign (x, avar, &ilist);
11477 }
11478 else if (is_gimple_reg (var))
11479 {
ca4c3545 11480 gcc_assert (offloaded);
f9e245b2 11481 tree avar = create_tmp_var (TREE_TYPE (var));
bc7bff74 11482 mark_addressable (avar);
ca4c3545 11483 enum gomp_map_kind map_kind = OMP_CLAUSE_MAP_KIND (c);
11484 if (GOMP_MAP_COPY_TO_P (map_kind)
11485 || map_kind == GOMP_MAP_POINTER
11486 || map_kind == GOMP_MAP_TO_PSET
11487 || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
bc7bff74 11488 gimplify_assign (avar, var, &ilist);
11489 avar = build_fold_addr_expr (avar);
11490 gimplify_assign (x, avar, &ilist);
ca4c3545 11491 if ((GOMP_MAP_COPY_FROM_P (map_kind)
11492 || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
bc7bff74 11493 && !TYPE_READONLY (TREE_TYPE (var)))
11494 {
11495 x = build_sender_ref (ovar, ctx);
11496 x = build_simple_mem_ref (x);
11497 gimplify_assign (var, x, &olist);
11498 }
11499 }
11500 else
11501 {
11502 var = build_fold_addr_expr (var);
11503 gimplify_assign (x, var, &ilist);
11504 }
11505 }
11506 tree s = OMP_CLAUSE_SIZE (c);
11507 if (s == NULL_TREE)
11508 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
11509 s = fold_convert (size_type_node, s);
11510 tree purpose = size_int (map_idx++);
11511 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
11512 if (TREE_CODE (s) != INTEGER_CST)
11513 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
11514
ca4c3545 11515 unsigned HOST_WIDE_INT tkind;
bc7bff74 11516 switch (OMP_CLAUSE_CODE (c))
11517 {
11518 case OMP_CLAUSE_MAP:
11519 tkind = OMP_CLAUSE_MAP_KIND (c);
11520 break;
11521 case OMP_CLAUSE_TO:
ca4c3545 11522 tkind = GOMP_MAP_TO;
bc7bff74 11523 break;
11524 case OMP_CLAUSE_FROM:
ca4c3545 11525 tkind = GOMP_MAP_FROM;
bc7bff74 11526 break;
11527 default:
11528 gcc_unreachable ();
11529 }
ca4c3545 11530 gcc_checking_assert (tkind
11531 < (HOST_WIDE_INT_C (1U) << talign_shift));
bc7bff74 11532 talign = ceil_log2 (talign);
ca4c3545 11533 tkind |= talign << talign_shift;
11534 gcc_checking_assert (tkind
11535 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
bc7bff74 11536 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
ca4c3545 11537 build_int_cstu (tkind_type, tkind));
bc7bff74 11538 if (nc && nc != c)
11539 c = nc;
11540 }
11541
11542 gcc_assert (map_idx == map_cnt);
11543
11544 DECL_INITIAL (TREE_VEC_ELT (t, 1))
11545 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)), vsize);
11546 DECL_INITIAL (TREE_VEC_ELT (t, 2))
11547 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 2)), vkind);
11548 if (!TREE_STATIC (TREE_VEC_ELT (t, 1)))
11549 {
11550 gimple_seq initlist = NULL;
11551 force_gimple_operand (build1 (DECL_EXPR, void_type_node,
11552 TREE_VEC_ELT (t, 1)),
11553 &initlist, true, NULL_TREE);
11554 gimple_seq_add_seq (&ilist, initlist);
d8e1e68d 11555
11556 tree clobber = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)),
11557 NULL);
11558 TREE_THIS_VOLATILE (clobber) = 1;
11559 gimple_seq_add_stmt (&olist,
11560 gimple_build_assign (TREE_VEC_ELT (t, 1),
11561 clobber));
bc7bff74 11562 }
11563
11564 tree clobber = build_constructor (ctx->record_type, NULL);
11565 TREE_THIS_VOLATILE (clobber) = 1;
11566 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
11567 clobber));
11568 }
11569
11570 /* Once all the expansions are done, sequence all the different
11571 fragments inside gimple_omp_body. */
11572
11573 new_body = NULL;
11574
ca4c3545 11575 if (offloaded
11576 && ctx->record_type)
bc7bff74 11577 {
11578 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
11579 /* fixup_child_record_type might have changed receiver_decl's type. */
11580 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
11581 gimple_seq_add_stmt (&new_body,
11582 gimple_build_assign (ctx->receiver_decl, t));
11583 }
11584
ca4c3545 11585 if (offloaded)
bc7bff74 11586 {
11587 gimple_seq_add_seq (&new_body, tgt_body);
11588 new_body = maybe_catch_exception (new_body);
11589 }
ca4c3545 11590 else if (data_region)
bc7bff74 11591 new_body = tgt_body;
ca4c3545 11592 if (offloaded || data_region)
bc7bff74 11593 {
11594 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
11595 gimple_omp_set_body (stmt, new_body);
11596 }
11597
11598 bind = gimple_build_bind (NULL, NULL,
11599 tgt_bind ? gimple_bind_block (tgt_bind)
11600 : NULL_TREE);
75a70cf9 11601 gsi_replace (gsi_p, bind, true);
ca4c3545 11602 gimple_bind_add_seq (bind, irlist);
e3a19533 11603 gimple_bind_add_seq (bind, ilist);
11604 gimple_bind_add_stmt (bind, stmt);
11605 gimple_bind_add_seq (bind, olist);
ca4c3545 11606 gimple_bind_add_seq (bind, orlist);
773c5ba7 11607
75a70cf9 11608 pop_gimplify_context (NULL);
773c5ba7 11609}
11610
bc7bff74 11611/* Expand code for an OpenMP teams directive. */
11612
11613static void
11614lower_omp_teams (gimple_stmt_iterator *gsi_p, omp_context *ctx)
11615{
1a91d914 11616 gomp_teams *teams_stmt = as_a <gomp_teams *> (gsi_stmt (*gsi_p));
8a4a28a8 11617 push_gimplify_context ();
bc7bff74 11618
11619 tree block = make_node (BLOCK);
1a91d914 11620 gbind *bind = gimple_build_bind (NULL, NULL, block);
bc7bff74 11621 gsi_replace (gsi_p, bind, true);
11622 gimple_seq bind_body = NULL;
11623 gimple_seq dlist = NULL;
11624 gimple_seq olist = NULL;
11625
11626 tree num_teams = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
11627 OMP_CLAUSE_NUM_TEAMS);
11628 if (num_teams == NULL_TREE)
11629 num_teams = build_int_cst (unsigned_type_node, 0);
11630 else
11631 {
11632 num_teams = OMP_CLAUSE_NUM_TEAMS_EXPR (num_teams);
11633 num_teams = fold_convert (unsigned_type_node, num_teams);
11634 gimplify_expr (&num_teams, &bind_body, NULL, is_gimple_val, fb_rvalue);
11635 }
11636 tree thread_limit = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
11637 OMP_CLAUSE_THREAD_LIMIT);
11638 if (thread_limit == NULL_TREE)
11639 thread_limit = build_int_cst (unsigned_type_node, 0);
11640 else
11641 {
11642 thread_limit = OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit);
11643 thread_limit = fold_convert (unsigned_type_node, thread_limit);
11644 gimplify_expr (&thread_limit, &bind_body, NULL, is_gimple_val,
11645 fb_rvalue);
11646 }
11647
11648 lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt),
11649 &bind_body, &dlist, ctx, NULL);
11650 lower_omp (gimple_omp_body_ptr (teams_stmt), ctx);
11651 lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt), &olist, ctx);
11652 gimple_seq_add_stmt (&bind_body, teams_stmt);
11653
11654 location_t loc = gimple_location (teams_stmt);
11655 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TEAMS);
11656 gimple call = gimple_build_call (decl, 2, num_teams, thread_limit);
11657 gimple_set_location (call, loc);
11658 gimple_seq_add_stmt (&bind_body, call);
11659
11660 gimple_seq_add_seq (&bind_body, gimple_omp_body (teams_stmt));
11661 gimple_omp_set_body (teams_stmt, NULL);
11662 gimple_seq_add_seq (&bind_body, olist);
11663 gimple_seq_add_seq (&bind_body, dlist);
11664 gimple_seq_add_stmt (&bind_body, gimple_build_omp_return (true));
11665 gimple_bind_set_body (bind, bind_body);
11666
11667 pop_gimplify_context (bind);
11668
11669 gimple_bind_append_vars (bind, ctx->block_vars);
11670 BLOCK_VARS (block) = ctx->block_vars;
11671 if (BLOCK_VARS (block))
11672 TREE_USED (block) = 1;
11673}
11674
11675
a4890dc9 11676/* Callback for lower_omp_1. Return non-NULL if *tp needs to be
75a70cf9 11677 regimplified. If DATA is non-NULL, lower_omp_1 is outside
ca4c3545 11678 of OMP context, but with task_shared_vars set. */
46515c92 11679
11680static tree
75a70cf9 11681lower_omp_regimplify_p (tree *tp, int *walk_subtrees,
11682 void *data)
46515c92 11683{
a4890dc9 11684 tree t = *tp;
46515c92 11685
a4890dc9 11686 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
75a70cf9 11687 if (TREE_CODE (t) == VAR_DECL && data == NULL && DECL_HAS_VALUE_EXPR_P (t))
9f49e155 11688 return t;
11689
11690 if (task_shared_vars
11691 && DECL_P (t)
11692 && bitmap_bit_p (task_shared_vars, DECL_UID (t)))
a4890dc9 11693 return t;
46515c92 11694
a4890dc9 11695 /* If a global variable has been privatized, TREE_CONSTANT on
11696 ADDR_EXPR might be wrong. */
75a70cf9 11697 if (data == NULL && TREE_CODE (t) == ADDR_EXPR)
a4890dc9 11698 recompute_tree_invariant_for_addr_expr (t);
46515c92 11699
a4890dc9 11700 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
11701 return NULL_TREE;
46515c92 11702}
773c5ba7 11703
a4890dc9 11704static void
75a70cf9 11705lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
1e8e9920 11706{
75a70cf9 11707 gimple stmt = gsi_stmt (*gsi_p);
11708 struct walk_stmt_info wi;
1a91d914 11709 gcall *call_stmt;
1e8e9920 11710
75a70cf9 11711 if (gimple_has_location (stmt))
11712 input_location = gimple_location (stmt);
a4890dc9 11713
75a70cf9 11714 if (task_shared_vars)
11715 memset (&wi, '\0', sizeof (wi));
a4890dc9 11716
773c5ba7 11717 /* If we have issued syntax errors, avoid doing any heavy lifting.
ca4c3545 11718 Just replace the OMP directives with a NOP to avoid
773c5ba7 11719 confusing RTL expansion. */
852f689e 11720 if (seen_error () && is_gimple_omp (stmt))
773c5ba7 11721 {
75a70cf9 11722 gsi_replace (gsi_p, gimple_build_nop (), true);
a4890dc9 11723 return;
773c5ba7 11724 }
11725
75a70cf9 11726 switch (gimple_code (stmt))
1e8e9920 11727 {
75a70cf9 11728 case GIMPLE_COND:
1a91d914 11729 {
11730 gcond *cond_stmt = as_a <gcond *> (stmt);
11731 if ((ctx || task_shared_vars)
11732 && (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
11733 lower_omp_regimplify_p,
11734 ctx ? NULL : &wi, NULL)
11735 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
11736 lower_omp_regimplify_p,
11737 ctx ? NULL : &wi, NULL)))
11738 gimple_regimplify_operands (cond_stmt, gsi_p);
11739 }
a4890dc9 11740 break;
75a70cf9 11741 case GIMPLE_CATCH:
1a91d914 11742 lower_omp (gimple_catch_handler_ptr (as_a <gcatch *> (stmt)), ctx);
a4890dc9 11743 break;
75a70cf9 11744 case GIMPLE_EH_FILTER:
e3a19533 11745 lower_omp (gimple_eh_filter_failure_ptr (stmt), ctx);
a4890dc9 11746 break;
75a70cf9 11747 case GIMPLE_TRY:
e3a19533 11748 lower_omp (gimple_try_eval_ptr (stmt), ctx);
11749 lower_omp (gimple_try_cleanup_ptr (stmt), ctx);
a4890dc9 11750 break;
35215227 11751 case GIMPLE_TRANSACTION:
1a91d914 11752 lower_omp (gimple_transaction_body_ptr (
11753 as_a <gtransaction *> (stmt)),
11754 ctx);
35215227 11755 break;
75a70cf9 11756 case GIMPLE_BIND:
1a91d914 11757 lower_omp (gimple_bind_body_ptr (as_a <gbind *> (stmt)), ctx);
a4890dc9 11758 break;
75a70cf9 11759 case GIMPLE_OMP_PARALLEL:
11760 case GIMPLE_OMP_TASK:
11761 ctx = maybe_lookup_ctx (stmt);
bc7bff74 11762 gcc_assert (ctx);
11763 if (ctx->cancellable)
11764 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
75a70cf9 11765 lower_omp_taskreg (gsi_p, ctx);
a4890dc9 11766 break;
75a70cf9 11767 case GIMPLE_OMP_FOR:
11768 ctx = maybe_lookup_ctx (stmt);
1e8e9920 11769 gcc_assert (ctx);
bc7bff74 11770 if (ctx->cancellable)
11771 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
75a70cf9 11772 lower_omp_for (gsi_p, ctx);
1e8e9920 11773 break;
75a70cf9 11774 case GIMPLE_OMP_SECTIONS:
11775 ctx = maybe_lookup_ctx (stmt);
1e8e9920 11776 gcc_assert (ctx);
bc7bff74 11777 if (ctx->cancellable)
11778 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
75a70cf9 11779 lower_omp_sections (gsi_p, ctx);
1e8e9920 11780 break;
75a70cf9 11781 case GIMPLE_OMP_SINGLE:
11782 ctx = maybe_lookup_ctx (stmt);
1e8e9920 11783 gcc_assert (ctx);
75a70cf9 11784 lower_omp_single (gsi_p, ctx);
1e8e9920 11785 break;
75a70cf9 11786 case GIMPLE_OMP_MASTER:
11787 ctx = maybe_lookup_ctx (stmt);
1e8e9920 11788 gcc_assert (ctx);
75a70cf9 11789 lower_omp_master (gsi_p, ctx);
1e8e9920 11790 break;
bc7bff74 11791 case GIMPLE_OMP_TASKGROUP:
11792 ctx = maybe_lookup_ctx (stmt);
11793 gcc_assert (ctx);
11794 lower_omp_taskgroup (gsi_p, ctx);
11795 break;
75a70cf9 11796 case GIMPLE_OMP_ORDERED:
11797 ctx = maybe_lookup_ctx (stmt);
1e8e9920 11798 gcc_assert (ctx);
75a70cf9 11799 lower_omp_ordered (gsi_p, ctx);
1e8e9920 11800 break;
75a70cf9 11801 case GIMPLE_OMP_CRITICAL:
11802 ctx = maybe_lookup_ctx (stmt);
1e8e9920 11803 gcc_assert (ctx);
75a70cf9 11804 lower_omp_critical (gsi_p, ctx);
11805 break;
11806 case GIMPLE_OMP_ATOMIC_LOAD:
11807 if ((ctx || task_shared_vars)
1a91d914 11808 && walk_tree (gimple_omp_atomic_load_rhs_ptr (
11809 as_a <gomp_atomic_load *> (stmt)),
75a70cf9 11810 lower_omp_regimplify_p, ctx ? NULL : &wi, NULL))
11811 gimple_regimplify_operands (stmt, gsi_p);
1e8e9920 11812 break;
bc7bff74 11813 case GIMPLE_OMP_TARGET:
11814 ctx = maybe_lookup_ctx (stmt);
11815 gcc_assert (ctx);
11816 lower_omp_target (gsi_p, ctx);
11817 break;
11818 case GIMPLE_OMP_TEAMS:
11819 ctx = maybe_lookup_ctx (stmt);
11820 gcc_assert (ctx);
11821 lower_omp_teams (gsi_p, ctx);
11822 break;
11823 case GIMPLE_CALL:
11824 tree fndecl;
1a91d914 11825 call_stmt = as_a <gcall *> (stmt);
11826 fndecl = gimple_call_fndecl (call_stmt);
bc7bff74 11827 if (fndecl
11828 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
11829 switch (DECL_FUNCTION_CODE (fndecl))
11830 {
11831 case BUILT_IN_GOMP_BARRIER:
11832 if (ctx == NULL)
11833 break;
11834 /* FALLTHRU */
11835 case BUILT_IN_GOMP_CANCEL:
11836 case BUILT_IN_GOMP_CANCELLATION_POINT:
11837 omp_context *cctx;
11838 cctx = ctx;
11839 if (gimple_code (cctx->stmt) == GIMPLE_OMP_SECTION)
11840 cctx = cctx->outer;
1a91d914 11841 gcc_assert (gimple_call_lhs (call_stmt) == NULL_TREE);
bc7bff74 11842 if (!cctx->cancellable)
11843 {
11844 if (DECL_FUNCTION_CODE (fndecl)
11845 == BUILT_IN_GOMP_CANCELLATION_POINT)
11846 {
11847 stmt = gimple_build_nop ();
11848 gsi_replace (gsi_p, stmt, false);
11849 }
11850 break;
11851 }
bc7bff74 11852 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
11853 {
11854 fndecl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL);
1a91d914 11855 gimple_call_set_fndecl (call_stmt, fndecl);
11856 gimple_call_set_fntype (call_stmt, TREE_TYPE (fndecl));
bc7bff74 11857 }
15b28553 11858 tree lhs;
f9e245b2 11859 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (fndecl)));
1a91d914 11860 gimple_call_set_lhs (call_stmt, lhs);
bc7bff74 11861 tree fallthru_label;
11862 fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
11863 gimple g;
11864 g = gimple_build_label (fallthru_label);
11865 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
15b28553 11866 g = gimple_build_cond (NE_EXPR, lhs,
11867 fold_convert (TREE_TYPE (lhs),
11868 boolean_false_node),
bc7bff74 11869 cctx->cancel_label, fallthru_label);
11870 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
11871 break;
11872 default:
11873 break;
11874 }
11875 /* FALLTHRU */
a4890dc9 11876 default:
fd6481cf 11877 if ((ctx || task_shared_vars)
75a70cf9 11878 && walk_gimple_op (stmt, lower_omp_regimplify_p,
11879 ctx ? NULL : &wi))
ef8cfd4d 11880 {
11881 /* Just remove clobbers, this should happen only if we have
11882 "privatized" local addressable variables in SIMD regions,
11883 the clobber isn't needed in that case and gimplifying address
11884 of the ARRAY_REF into a pointer and creating MEM_REF based
11885 clobber would create worse code than we get with the clobber
11886 dropped. */
11887 if (gimple_clobber_p (stmt))
11888 {
11889 gsi_replace (gsi_p, gimple_build_nop (), true);
11890 break;
11891 }
11892 gimple_regimplify_operands (stmt, gsi_p);
11893 }
1e8e9920 11894 break;
1e8e9920 11895 }
1e8e9920 11896}
11897
11898static void
e3a19533 11899lower_omp (gimple_seq *body, omp_context *ctx)
1e8e9920 11900{
1d22f541 11901 location_t saved_location = input_location;
e3a19533 11902 gimple_stmt_iterator gsi;
11903 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
75a70cf9 11904 lower_omp_1 (&gsi, ctx);
ca4c3545 11905 /* During gimplification, we haven't folded statments inside offloading
11906 regions (gimplify.c:maybe_fold_stmt); do that now. */
bc7bff74 11907 if (target_nesting_level)
11908 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
11909 fold_stmt (&gsi);
1d22f541 11910 input_location = saved_location;
1e8e9920 11911}
11912\f
11913/* Main entry point. */
11914
2a1990e9 11915static unsigned int
1e8e9920 11916execute_lower_omp (void)
11917{
75a70cf9 11918 gimple_seq body;
37eaded9 11919 int i;
11920 omp_context *ctx;
75a70cf9 11921
41709826 11922 /* This pass always runs, to provide PROP_gimple_lomp.
ca4c3545 11923 But often, there is nothing to do. */
11924 if (flag_cilkplus == 0 && flag_openacc == 0 && flag_openmp == 0
11925 && flag_openmp_simd == 0)
41709826 11926 return 0;
11927
1e8e9920 11928 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
11929 delete_omp_context);
11930
75a70cf9 11931 body = gimple_body (current_function_decl);
ab129075 11932 scan_omp (&body, NULL);
fd6481cf 11933 gcc_assert (taskreg_nesting_level == 0);
37eaded9 11934 FOR_EACH_VEC_ELT (taskreg_contexts, i, ctx)
11935 finish_taskreg_scan (ctx);
11936 taskreg_contexts.release ();
1e8e9920 11937
11938 if (all_contexts->root)
fd6481cf 11939 {
11940 if (task_shared_vars)
8a4a28a8 11941 push_gimplify_context ();
e3a19533 11942 lower_omp (&body, NULL);
fd6481cf 11943 if (task_shared_vars)
11944 pop_gimplify_context (NULL);
11945 }
1e8e9920 11946
773c5ba7 11947 if (all_contexts)
11948 {
11949 splay_tree_delete (all_contexts);
11950 all_contexts = NULL;
11951 }
fd6481cf 11952 BITMAP_FREE (task_shared_vars);
2a1990e9 11953 return 0;
1e8e9920 11954}
11955
cbe8bda8 11956namespace {
11957
11958const pass_data pass_data_lower_omp =
11959{
11960 GIMPLE_PASS, /* type */
11961 "omplower", /* name */
11962 OPTGROUP_NONE, /* optinfo_flags */
cbe8bda8 11963 TV_NONE, /* tv_id */
11964 PROP_gimple_any, /* properties_required */
11965 PROP_gimple_lomp, /* properties_provided */
11966 0, /* properties_destroyed */
11967 0, /* todo_flags_start */
11968 0, /* todo_flags_finish */
1e8e9920 11969};
cbe8bda8 11970
11971class pass_lower_omp : public gimple_opt_pass
11972{
11973public:
9af5ce0c 11974 pass_lower_omp (gcc::context *ctxt)
11975 : gimple_opt_pass (pass_data_lower_omp, ctxt)
cbe8bda8 11976 {}
11977
11978 /* opt_pass methods: */
65b0537f 11979 virtual unsigned int execute (function *) { return execute_lower_omp (); }
cbe8bda8 11980
11981}; // class pass_lower_omp
11982
11983} // anon namespace
11984
11985gimple_opt_pass *
11986make_pass_lower_omp (gcc::context *ctxt)
11987{
11988 return new pass_lower_omp (ctxt);
11989}
1e8e9920 11990\f
ca4c3545 11991/* The following is a utility to diagnose structured block violations.
61e47ac8 11992 It is not part of the "omplower" pass, as that's invoked too late. It
11993 should be invoked by the respective front ends after gimplification. */
1e8e9920 11994
11995static splay_tree all_labels;
11996
11997/* Check for mismatched contexts and generate an error if needed. Return
11998 true if an error is detected. */
11999
12000static bool
75a70cf9 12001diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
12002 gimple branch_ctx, gimple label_ctx)
1e8e9920 12003{
ca4c3545 12004 gcc_checking_assert (!branch_ctx || is_gimple_omp (branch_ctx));
12005 gcc_checking_assert (!label_ctx || is_gimple_omp (label_ctx));
12006
75a70cf9 12007 if (label_ctx == branch_ctx)
1e8e9920 12008 return false;
12009
ca4c3545 12010 const char* kind = NULL;
12011
12012 if (flag_cilkplus)
12013 {
12014 if ((branch_ctx
12015 && gimple_code (branch_ctx) == GIMPLE_OMP_FOR
12016 && gimple_omp_for_kind (branch_ctx) == GF_OMP_FOR_KIND_CILKSIMD)
12017 || (label_ctx
12018 && gimple_code (label_ctx) == GIMPLE_OMP_FOR
12019 && gimple_omp_for_kind (label_ctx) == GF_OMP_FOR_KIND_CILKSIMD))
12020 kind = "Cilk Plus";
12021 }
12022 if (flag_openacc)
12023 {
12024 if ((branch_ctx && is_gimple_omp_oacc (branch_ctx))
12025 || (label_ctx && is_gimple_omp_oacc (label_ctx)))
12026 {
12027 gcc_checking_assert (kind == NULL);
12028 kind = "OpenACC";
12029 }
12030 }
12031 if (kind == NULL)
12032 {
12033 gcc_checking_assert (flag_openmp);
12034 kind = "OpenMP";
12035 }
48e1416a 12036
75a70cf9 12037 /*
12038 Previously we kept track of the label's entire context in diagnose_sb_[12]
12039 so we could traverse it and issue a correct "exit" or "enter" error
12040 message upon a structured block violation.
12041
12042 We built the context by building a list with tree_cons'ing, but there is
12043 no easy counterpart in gimple tuples. It seems like far too much work
12044 for issuing exit/enter error messages. If someone really misses the
12045 distinct error message... patches welcome.
12046 */
48e1416a 12047
75a70cf9 12048#if 0
1e8e9920 12049 /* Try to avoid confusing the user by producing and error message
f0b5f617 12050 with correct "exit" or "enter" verbiage. We prefer "exit"
1e8e9920 12051 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
12052 if (branch_ctx == NULL)
12053 exit_p = false;
12054 else
12055 {
12056 while (label_ctx)
12057 {
12058 if (TREE_VALUE (label_ctx) == branch_ctx)
12059 {
12060 exit_p = false;
12061 break;
12062 }
12063 label_ctx = TREE_CHAIN (label_ctx);
12064 }
12065 }
12066
12067 if (exit_p)
ca4c3545 12068 error ("invalid exit from %s structured block", kind);
1e8e9920 12069 else
ca4c3545 12070 error ("invalid entry to %s structured block", kind);
75a70cf9 12071#endif
1e8e9920 12072
75a70cf9 12073 /* If it's obvious we have an invalid entry, be specific about the error. */
12074 if (branch_ctx == NULL)
ca4c3545 12075 error ("invalid entry to %s structured block", kind);
75a70cf9 12076 else
f2697631 12077 {
12078 /* Otherwise, be vague and lazy, but efficient. */
ca4c3545 12079 error ("invalid branch to/from %s structured block", kind);
f2697631 12080 }
75a70cf9 12081
12082 gsi_replace (gsi_p, gimple_build_nop (), false);
1e8e9920 12083 return true;
12084}
12085
ca4c3545 12086/* Pass 1: Create a minimal tree of structured blocks, and record
75a70cf9 12087 where each label is found. */
1e8e9920 12088
12089static tree
75a70cf9 12090diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
12091 struct walk_stmt_info *wi)
1e8e9920 12092{
75a70cf9 12093 gimple context = (gimple) wi->info;
12094 gimple inner_context;
12095 gimple stmt = gsi_stmt (*gsi_p);
1e8e9920 12096
75a70cf9 12097 *handled_ops_p = true;
12098
ca4c3545 12099 switch (gimple_code (stmt))
1e8e9920 12100 {
75a70cf9 12101 WALK_SUBSTMTS;
48e1416a 12102
75a70cf9 12103 case GIMPLE_OMP_PARALLEL:
12104 case GIMPLE_OMP_TASK:
12105 case GIMPLE_OMP_SECTIONS:
12106 case GIMPLE_OMP_SINGLE:
12107 case GIMPLE_OMP_SECTION:
12108 case GIMPLE_OMP_MASTER:
12109 case GIMPLE_OMP_ORDERED:
12110 case GIMPLE_OMP_CRITICAL:
bc7bff74 12111 case GIMPLE_OMP_TARGET:
12112 case GIMPLE_OMP_TEAMS:
12113 case GIMPLE_OMP_TASKGROUP:
75a70cf9 12114 /* The minimal context here is just the current OMP construct. */
12115 inner_context = stmt;
1e8e9920 12116 wi->info = inner_context;
75a70cf9 12117 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
1e8e9920 12118 wi->info = context;
12119 break;
12120
75a70cf9 12121 case GIMPLE_OMP_FOR:
12122 inner_context = stmt;
1e8e9920 12123 wi->info = inner_context;
75a70cf9 12124 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
12125 walk them. */
12126 walk_gimple_seq (gimple_omp_for_pre_body (stmt),
12127 diagnose_sb_1, NULL, wi);
12128 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
1e8e9920 12129 wi->info = context;
12130 break;
12131
75a70cf9 12132 case GIMPLE_LABEL:
1a91d914 12133 splay_tree_insert (all_labels,
12134 (splay_tree_key) gimple_label_label (
12135 as_a <glabel *> (stmt)),
1e8e9920 12136 (splay_tree_value) context);
12137 break;
12138
12139 default:
12140 break;
12141 }
12142
12143 return NULL_TREE;
12144}
12145
12146/* Pass 2: Check each branch and see if its context differs from that of
12147 the destination label's context. */
12148
12149static tree
75a70cf9 12150diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
12151 struct walk_stmt_info *wi)
1e8e9920 12152{
75a70cf9 12153 gimple context = (gimple) wi->info;
1e8e9920 12154 splay_tree_node n;
75a70cf9 12155 gimple stmt = gsi_stmt (*gsi_p);
1e8e9920 12156
75a70cf9 12157 *handled_ops_p = true;
12158
12159 switch (gimple_code (stmt))
1e8e9920 12160 {
75a70cf9 12161 WALK_SUBSTMTS;
12162
12163 case GIMPLE_OMP_PARALLEL:
12164 case GIMPLE_OMP_TASK:
12165 case GIMPLE_OMP_SECTIONS:
12166 case GIMPLE_OMP_SINGLE:
12167 case GIMPLE_OMP_SECTION:
12168 case GIMPLE_OMP_MASTER:
12169 case GIMPLE_OMP_ORDERED:
12170 case GIMPLE_OMP_CRITICAL:
bc7bff74 12171 case GIMPLE_OMP_TARGET:
12172 case GIMPLE_OMP_TEAMS:
12173 case GIMPLE_OMP_TASKGROUP:
75a70cf9 12174 wi->info = stmt;
e3a19533 12175 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
1e8e9920 12176 wi->info = context;
12177 break;
12178
75a70cf9 12179 case GIMPLE_OMP_FOR:
12180 wi->info = stmt;
12181 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
12182 walk them. */
e3a19533 12183 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt),
12184 diagnose_sb_2, NULL, wi);
12185 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
1e8e9920 12186 wi->info = context;
12187 break;
12188
0e1818e7 12189 case GIMPLE_COND:
12190 {
1a91d914 12191 gcond *cond_stmt = as_a <gcond *> (stmt);
12192 tree lab = gimple_cond_true_label (cond_stmt);
0e1818e7 12193 if (lab)
12194 {
12195 n = splay_tree_lookup (all_labels,
12196 (splay_tree_key) lab);
12197 diagnose_sb_0 (gsi_p, context,
12198 n ? (gimple) n->value : NULL);
12199 }
1a91d914 12200 lab = gimple_cond_false_label (cond_stmt);
0e1818e7 12201 if (lab)
12202 {
12203 n = splay_tree_lookup (all_labels,
12204 (splay_tree_key) lab);
12205 diagnose_sb_0 (gsi_p, context,
12206 n ? (gimple) n->value : NULL);
12207 }
12208 }
12209 break;
12210
75a70cf9 12211 case GIMPLE_GOTO:
1e8e9920 12212 {
75a70cf9 12213 tree lab = gimple_goto_dest (stmt);
1e8e9920 12214 if (TREE_CODE (lab) != LABEL_DECL)
12215 break;
12216
12217 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
75a70cf9 12218 diagnose_sb_0 (gsi_p, context, n ? (gimple) n->value : NULL);
1e8e9920 12219 }
12220 break;
12221
75a70cf9 12222 case GIMPLE_SWITCH:
1e8e9920 12223 {
1a91d914 12224 gswitch *switch_stmt = as_a <gswitch *> (stmt);
75a70cf9 12225 unsigned int i;
1a91d914 12226 for (i = 0; i < gimple_switch_num_labels (switch_stmt); ++i)
1e8e9920 12227 {
1a91d914 12228 tree lab = CASE_LABEL (gimple_switch_label (switch_stmt, i));
1e8e9920 12229 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
75a70cf9 12230 if (n && diagnose_sb_0 (gsi_p, context, (gimple) n->value))
1e8e9920 12231 break;
12232 }
12233 }
12234 break;
12235
75a70cf9 12236 case GIMPLE_RETURN:
12237 diagnose_sb_0 (gsi_p, context, NULL);
1e8e9920 12238 break;
12239
12240 default:
12241 break;
12242 }
12243
12244 return NULL_TREE;
12245}
12246
ca4c3545 12247/* Called from tree-cfg.c::make_edges to create cfg edges for all relevant
12248 GIMPLE_* codes. */
7740abd8 12249bool
b2c0e0b7 12250make_gimple_omp_edges (basic_block bb, struct omp_region **region,
12251 int *region_idx)
7740abd8 12252{
12253 gimple last = last_stmt (bb);
12254 enum gimple_code code = gimple_code (last);
12255 struct omp_region *cur_region = *region;
12256 bool fallthru = false;
12257
12258 switch (code)
12259 {
12260 case GIMPLE_OMP_PARALLEL:
12261 case GIMPLE_OMP_TASK:
12262 case GIMPLE_OMP_FOR:
12263 case GIMPLE_OMP_SINGLE:
12264 case GIMPLE_OMP_TEAMS:
12265 case GIMPLE_OMP_MASTER:
12266 case GIMPLE_OMP_TASKGROUP:
12267 case GIMPLE_OMP_ORDERED:
12268 case GIMPLE_OMP_CRITICAL:
12269 case GIMPLE_OMP_SECTION:
12270 cur_region = new_omp_region (bb, code, cur_region);
12271 fallthru = true;
12272 break;
12273
12274 case GIMPLE_OMP_TARGET:
12275 cur_region = new_omp_region (bb, code, cur_region);
12276 fallthru = true;
ca4c3545 12277 switch (gimple_omp_target_kind (last))
12278 {
12279 case GF_OMP_TARGET_KIND_REGION:
12280 case GF_OMP_TARGET_KIND_DATA:
12281 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
12282 case GF_OMP_TARGET_KIND_OACC_KERNELS:
12283 case GF_OMP_TARGET_KIND_OACC_DATA:
12284 break;
12285 case GF_OMP_TARGET_KIND_UPDATE:
12286 case GF_OMP_TARGET_KIND_OACC_UPDATE:
12287 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
12288 cur_region = cur_region->outer;
12289 break;
12290 default:
12291 gcc_unreachable ();
12292 }
7740abd8 12293 break;
12294
12295 case GIMPLE_OMP_SECTIONS:
12296 cur_region = new_omp_region (bb, code, cur_region);
12297 fallthru = true;
12298 break;
12299
12300 case GIMPLE_OMP_SECTIONS_SWITCH:
12301 fallthru = false;
12302 break;
12303
12304 case GIMPLE_OMP_ATOMIC_LOAD:
12305 case GIMPLE_OMP_ATOMIC_STORE:
12306 fallthru = true;
12307 break;
12308
12309 case GIMPLE_OMP_RETURN:
12310 /* In the case of a GIMPLE_OMP_SECTION, the edge will go
12311 somewhere other than the next block. This will be
12312 created later. */
12313 cur_region->exit = bb;
b25f70fd 12314 if (cur_region->type == GIMPLE_OMP_TASK)
12315 /* Add an edge corresponding to not scheduling the task
12316 immediately. */
12317 make_edge (cur_region->entry, bb, EDGE_ABNORMAL);
7740abd8 12318 fallthru = cur_region->type != GIMPLE_OMP_SECTION;
12319 cur_region = cur_region->outer;
12320 break;
12321
12322 case GIMPLE_OMP_CONTINUE:
12323 cur_region->cont = bb;
12324 switch (cur_region->type)
12325 {
12326 case GIMPLE_OMP_FOR:
12327 /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
12328 succs edges as abnormal to prevent splitting
12329 them. */
12330 single_succ_edge (cur_region->entry)->flags |= EDGE_ABNORMAL;
12331 /* Make the loopback edge. */
12332 make_edge (bb, single_succ (cur_region->entry),
12333 EDGE_ABNORMAL);
12334
12335 /* Create an edge from GIMPLE_OMP_FOR to exit, which
12336 corresponds to the case that the body of the loop
12337 is not executed at all. */
12338 make_edge (cur_region->entry, bb->next_bb, EDGE_ABNORMAL);
12339 make_edge (bb, bb->next_bb, EDGE_FALLTHRU | EDGE_ABNORMAL);
12340 fallthru = false;
12341 break;
12342
12343 case GIMPLE_OMP_SECTIONS:
12344 /* Wire up the edges into and out of the nested sections. */
12345 {
12346 basic_block switch_bb = single_succ (cur_region->entry);
12347
12348 struct omp_region *i;
12349 for (i = cur_region->inner; i ; i = i->next)
12350 {
12351 gcc_assert (i->type == GIMPLE_OMP_SECTION);
12352 make_edge (switch_bb, i->entry, 0);
12353 make_edge (i->exit, bb, EDGE_FALLTHRU);
12354 }
12355
12356 /* Make the loopback edge to the block with
12357 GIMPLE_OMP_SECTIONS_SWITCH. */
12358 make_edge (bb, switch_bb, 0);
12359
12360 /* Make the edge from the switch to exit. */
12361 make_edge (switch_bb, bb->next_bb, 0);
12362 fallthru = false;
12363 }
12364 break;
12365
b25f70fd 12366 case GIMPLE_OMP_TASK:
12367 fallthru = true;
12368 break;
12369
7740abd8 12370 default:
12371 gcc_unreachable ();
12372 }
12373 break;
12374
12375 default:
12376 gcc_unreachable ();
12377 }
12378
12379 if (*region != cur_region)
b2c0e0b7 12380 {
12381 *region = cur_region;
12382 if (cur_region)
12383 *region_idx = cur_region->entry->index;
12384 else
12385 *region_idx = 0;
12386 }
7740abd8 12387
12388 return fallthru;
12389}
12390
bfec3452 12391static unsigned int
12392diagnose_omp_structured_block_errors (void)
1e8e9920 12393{
1e8e9920 12394 struct walk_stmt_info wi;
bfec3452 12395 gimple_seq body = gimple_body (current_function_decl);
1e8e9920 12396
12397 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
12398
12399 memset (&wi, 0, sizeof (wi));
75a70cf9 12400 walk_gimple_seq (body, diagnose_sb_1, NULL, &wi);
1e8e9920 12401
12402 memset (&wi, 0, sizeof (wi));
1e8e9920 12403 wi.want_locations = true;
e3a19533 12404 walk_gimple_seq_mod (&body, diagnose_sb_2, NULL, &wi);
12405
12406 gimple_set_body (current_function_decl, body);
1e8e9920 12407
12408 splay_tree_delete (all_labels);
12409 all_labels = NULL;
12410
bfec3452 12411 return 0;
1e8e9920 12412}
12413
cbe8bda8 12414namespace {
12415
12416const pass_data pass_data_diagnose_omp_blocks =
12417{
12418 GIMPLE_PASS, /* type */
12419 "*diagnose_omp_blocks", /* name */
12420 OPTGROUP_NONE, /* optinfo_flags */
cbe8bda8 12421 TV_NONE, /* tv_id */
12422 PROP_gimple_any, /* properties_required */
12423 0, /* properties_provided */
12424 0, /* properties_destroyed */
12425 0, /* todo_flags_start */
12426 0, /* todo_flags_finish */
bfec3452 12427};
12428
cbe8bda8 12429class pass_diagnose_omp_blocks : public gimple_opt_pass
12430{
12431public:
9af5ce0c 12432 pass_diagnose_omp_blocks (gcc::context *ctxt)
12433 : gimple_opt_pass (pass_data_diagnose_omp_blocks, ctxt)
cbe8bda8 12434 {}
12435
12436 /* opt_pass methods: */
ca4c3545 12437 virtual bool gate (function *)
12438 {
12439 return flag_cilkplus || flag_openacc || flag_openmp;
12440 }
65b0537f 12441 virtual unsigned int execute (function *)
12442 {
12443 return diagnose_omp_structured_block_errors ();
12444 }
cbe8bda8 12445
12446}; // class pass_diagnose_omp_blocks
12447
12448} // anon namespace
12449
12450gimple_opt_pass *
12451make_pass_diagnose_omp_blocks (gcc::context *ctxt)
12452{
12453 return new pass_diagnose_omp_blocks (ctxt);
12454}
d09768a4 12455\f
12456/* SIMD clone supporting code. */
12457
12458/* Allocate a fresh `simd_clone' and return it. NARGS is the number
12459 of arguments to reserve space for. */
12460
12461static struct cgraph_simd_clone *
12462simd_clone_struct_alloc (int nargs)
12463{
12464 struct cgraph_simd_clone *clone_info;
12465 size_t len = (sizeof (struct cgraph_simd_clone)
12466 + nargs * sizeof (struct cgraph_simd_clone_arg));
12467 clone_info = (struct cgraph_simd_clone *)
ea7d8c7a 12468 ggc_internal_cleared_alloc (len);
d09768a4 12469 return clone_info;
12470}
12471
12472/* Make a copy of the `struct cgraph_simd_clone' in FROM to TO. */
12473
12474static inline void
12475simd_clone_struct_copy (struct cgraph_simd_clone *to,
12476 struct cgraph_simd_clone *from)
12477{
12478 memcpy (to, from, (sizeof (struct cgraph_simd_clone)
46c0fd4b 12479 + ((from->nargs - from->inbranch)
12480 * sizeof (struct cgraph_simd_clone_arg))));
d09768a4 12481}
12482
12483/* Return vector of parameter types of function FNDECL. This uses
12484 TYPE_ARG_TYPES if available, otherwise falls back to types of
12485 DECL_ARGUMENTS types. */
12486
12487vec<tree>
12488simd_clone_vector_of_formal_parm_types (tree fndecl)
12489{
12490 if (TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
12491 return ipa_get_vector_of_formal_parm_types (TREE_TYPE (fndecl));
12492 vec<tree> args = ipa_get_vector_of_formal_parms (fndecl);
12493 unsigned int i;
12494 tree arg;
12495 FOR_EACH_VEC_ELT (args, i, arg)
12496 args[i] = TREE_TYPE (args[i]);
12497 return args;
12498}
12499
12500/* Given a simd function in NODE, extract the simd specific
12501 information from the OMP clauses passed in CLAUSES, and return
12502 the struct cgraph_simd_clone * if it should be cloned. *INBRANCH_SPECIFIED
12503 is set to TRUE if the `inbranch' or `notinbranch' clause specified,
12504 otherwise set to FALSE. */
12505
12506static struct cgraph_simd_clone *
12507simd_clone_clauses_extract (struct cgraph_node *node, tree clauses,
12508 bool *inbranch_specified)
12509{
12510 vec<tree> args = simd_clone_vector_of_formal_parm_types (node->decl);
12511 tree t;
12512 int n;
12513 *inbranch_specified = false;
12514
12515 n = args.length ();
12516 if (n > 0 && args.last () == void_type_node)
12517 n--;
12518
12519 /* To distinguish from an OpenMP simd clone, Cilk Plus functions to
12520 be cloned have a distinctive artificial label in addition to "omp
12521 declare simd". */
12522 bool cilk_clone
a89e6c15 12523 = (flag_cilkplus
74acc703 12524 && lookup_attribute ("cilk simd function",
d09768a4 12525 DECL_ATTRIBUTES (node->decl)));
12526
12527 /* Allocate one more than needed just in case this is an in-branch
12528 clone which will require a mask argument. */
12529 struct cgraph_simd_clone *clone_info = simd_clone_struct_alloc (n + 1);
12530 clone_info->nargs = n;
12531 clone_info->cilk_elemental = cilk_clone;
12532
12533 if (!clauses)
12534 {
12535 args.release ();
12536 return clone_info;
12537 }
12538 clauses = TREE_VALUE (clauses);
12539 if (!clauses || TREE_CODE (clauses) != OMP_CLAUSE)
12540 return clone_info;
12541
12542 for (t = clauses; t; t = OMP_CLAUSE_CHAIN (t))
12543 {
12544 switch (OMP_CLAUSE_CODE (t))
12545 {
12546 case OMP_CLAUSE_INBRANCH:
12547 clone_info->inbranch = 1;
12548 *inbranch_specified = true;
12549 break;
12550 case OMP_CLAUSE_NOTINBRANCH:
12551 clone_info->inbranch = 0;
12552 *inbranch_specified = true;
12553 break;
12554 case OMP_CLAUSE_SIMDLEN:
12555 clone_info->simdlen
12556 = TREE_INT_CST_LOW (OMP_CLAUSE_SIMDLEN_EXPR (t));
12557 break;
12558 case OMP_CLAUSE_LINEAR:
12559 {
12560 tree decl = OMP_CLAUSE_DECL (t);
12561 tree step = OMP_CLAUSE_LINEAR_STEP (t);
12562 int argno = TREE_INT_CST_LOW (decl);
12563 if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (t))
12564 {
12565 clone_info->args[argno].arg_type
12566 = SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP;
12567 clone_info->args[argno].linear_step = tree_to_shwi (step);
12568 gcc_assert (clone_info->args[argno].linear_step >= 0
12569 && clone_info->args[argno].linear_step < n);
12570 }
12571 else
12572 {
12573 if (POINTER_TYPE_P (args[argno]))
12574 step = fold_convert (ssizetype, step);
12575 if (!tree_fits_shwi_p (step))
12576 {
12577 warning_at (OMP_CLAUSE_LOCATION (t), 0,
12578 "ignoring large linear step");
12579 args.release ();
12580 return NULL;
12581 }
12582 else if (integer_zerop (step))
12583 {
12584 warning_at (OMP_CLAUSE_LOCATION (t), 0,
12585 "ignoring zero linear step");
12586 args.release ();
12587 return NULL;
12588 }
12589 else
12590 {
12591 clone_info->args[argno].arg_type
12592 = SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP;
12593 clone_info->args[argno].linear_step = tree_to_shwi (step);
12594 }
12595 }
12596 break;
12597 }
12598 case OMP_CLAUSE_UNIFORM:
12599 {
12600 tree decl = OMP_CLAUSE_DECL (t);
12601 int argno = tree_to_uhwi (decl);
12602 clone_info->args[argno].arg_type
12603 = SIMD_CLONE_ARG_TYPE_UNIFORM;
12604 break;
12605 }
12606 case OMP_CLAUSE_ALIGNED:
12607 {
12608 tree decl = OMP_CLAUSE_DECL (t);
12609 int argno = tree_to_uhwi (decl);
12610 clone_info->args[argno].alignment
12611 = TREE_INT_CST_LOW (OMP_CLAUSE_ALIGNED_ALIGNMENT (t));
12612 break;
12613 }
12614 default:
12615 break;
12616 }
12617 }
12618 args.release ();
12619 return clone_info;
12620}
12621
12622/* Given a SIMD clone in NODE, calculate the characteristic data
12623 type and return the coresponding type. The characteristic data
12624 type is computed as described in the Intel Vector ABI. */
12625
12626static tree
12627simd_clone_compute_base_data_type (struct cgraph_node *node,
12628 struct cgraph_simd_clone *clone_info)
12629{
12630 tree type = integer_type_node;
12631 tree fndecl = node->decl;
12632
12633 /* a) For non-void function, the characteristic data type is the
12634 return type. */
12635 if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) != VOID_TYPE)
12636 type = TREE_TYPE (TREE_TYPE (fndecl));
12637
12638 /* b) If the function has any non-uniform, non-linear parameters,
12639 then the characteristic data type is the type of the first
12640 such parameter. */
12641 else
12642 {
12643 vec<tree> map = simd_clone_vector_of_formal_parm_types (fndecl);
12644 for (unsigned int i = 0; i < clone_info->nargs; ++i)
12645 if (clone_info->args[i].arg_type == SIMD_CLONE_ARG_TYPE_VECTOR)
12646 {
12647 type = map[i];
12648 break;
12649 }
12650 map.release ();
12651 }
12652
12653 /* c) If the characteristic data type determined by a) or b) above
12654 is struct, union, or class type which is pass-by-value (except
12655 for the type that maps to the built-in complex data type), the
12656 characteristic data type is int. */
12657 if (RECORD_OR_UNION_TYPE_P (type)
12658 && !aggregate_value_p (type, NULL)
12659 && TREE_CODE (type) != COMPLEX_TYPE)
12660 return integer_type_node;
12661
12662 /* d) If none of the above three classes is applicable, the
12663 characteristic data type is int. */
12664
12665 return type;
12666
12667 /* e) For Intel Xeon Phi native and offload compilation, if the
12668 resulting characteristic data type is 8-bit or 16-bit integer
12669 data type, the characteristic data type is int. */
12670 /* Well, we don't handle Xeon Phi yet. */
12671}
12672
12673static tree
12674simd_clone_mangle (struct cgraph_node *node,
12675 struct cgraph_simd_clone *clone_info)
12676{
12677 char vecsize_mangle = clone_info->vecsize_mangle;
12678 char mask = clone_info->inbranch ? 'M' : 'N';
12679 unsigned int simdlen = clone_info->simdlen;
12680 unsigned int n;
12681 pretty_printer pp;
12682
12683 gcc_assert (vecsize_mangle && simdlen);
12684
12685 pp_string (&pp, "_ZGV");
12686 pp_character (&pp, vecsize_mangle);
12687 pp_character (&pp, mask);
12688 pp_decimal_int (&pp, simdlen);
12689
12690 for (n = 0; n < clone_info->nargs; ++n)
12691 {
12692 struct cgraph_simd_clone_arg arg = clone_info->args[n];
12693
12694 if (arg.arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM)
12695 pp_character (&pp, 'u');
12696 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
12697 {
12698 gcc_assert (arg.linear_step != 0);
12699 pp_character (&pp, 'l');
12700 if (arg.linear_step > 1)
12701 pp_unsigned_wide_integer (&pp, arg.linear_step);
12702 else if (arg.linear_step < 0)
12703 {
12704 pp_character (&pp, 'n');
12705 pp_unsigned_wide_integer (&pp, (-(unsigned HOST_WIDE_INT)
12706 arg.linear_step));
12707 }
12708 }
12709 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP)
12710 {
12711 pp_character (&pp, 's');
12712 pp_unsigned_wide_integer (&pp, arg.linear_step);
12713 }
12714 else
12715 pp_character (&pp, 'v');
12716 if (arg.alignment)
12717 {
12718 pp_character (&pp, 'a');
12719 pp_decimal_int (&pp, arg.alignment);
12720 }
12721 }
12722
12723 pp_underscore (&pp);
4e4baaad 12724 const char *str = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl));
12725 if (*str == '*')
12726 ++str;
12727 pp_string (&pp, str);
12728 str = pp_formatted_text (&pp);
d09768a4 12729
12730 /* If there already is a SIMD clone with the same mangled name, don't
12731 add another one. This can happen e.g. for
12732 #pragma omp declare simd
12733 #pragma omp declare simd simdlen(8)
12734 int foo (int, int);
12735 if the simdlen is assumed to be 8 for the first one, etc. */
12736 for (struct cgraph_node *clone = node->simd_clones; clone;
12737 clone = clone->simdclone->next_clone)
12738 if (strcmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (clone->decl)),
12739 str) == 0)
12740 return NULL_TREE;
12741
12742 return get_identifier (str);
12743}
12744
12745/* Create a simd clone of OLD_NODE and return it. */
12746
12747static struct cgraph_node *
12748simd_clone_create (struct cgraph_node *old_node)
12749{
12750 struct cgraph_node *new_node;
12751 if (old_node->definition)
ea0695f9 12752 {
415d1b9a 12753 if (!old_node->has_gimple_body_p ())
ea0695f9 12754 return NULL;
415d1b9a 12755 old_node->get_body ();
12756 new_node = old_node->create_version_clone_with_body (vNULL, NULL, NULL,
12757 false, NULL, NULL,
12758 "simdclone");
ea0695f9 12759 }
d09768a4 12760 else
12761 {
12762 tree old_decl = old_node->decl;
12763 tree new_decl = copy_node (old_node->decl);
12764 DECL_NAME (new_decl) = clone_function_name (old_decl, "simdclone");
12765 SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl));
12766 SET_DECL_RTL (new_decl, NULL);
12767 DECL_STATIC_CONSTRUCTOR (new_decl) = 0;
12768 DECL_STATIC_DESTRUCTOR (new_decl) = 0;
415d1b9a 12769 new_node = old_node->create_version_clone (new_decl, vNULL, NULL);
35ee1c66 12770 symtab->call_cgraph_insertion_hooks (new_node);
d09768a4 12771 }
12772 if (new_node == NULL)
12773 return new_node;
12774
12775 TREE_PUBLIC (new_node->decl) = TREE_PUBLIC (old_node->decl);
12776
12777 /* The function cgraph_function_versioning () will force the new
12778 symbol local. Undo this, and inherit external visability from
12779 the old node. */
12780 new_node->local.local = old_node->local.local;
12781 new_node->externally_visible = old_node->externally_visible;
12782
12783 return new_node;
12784}
12785
12786/* Adjust the return type of the given function to its appropriate
12787 vector counterpart. Returns a simd array to be used throughout the
12788 function as a return value. */
12789
12790static tree
12791simd_clone_adjust_return_type (struct cgraph_node *node)
12792{
12793 tree fndecl = node->decl;
12794 tree orig_rettype = TREE_TYPE (TREE_TYPE (fndecl));
12795 unsigned int veclen;
12796 tree t;
12797
12798 /* Adjust the function return type. */
12799 if (orig_rettype == void_type_node)
12800 return NULL_TREE;
12801 TREE_TYPE (fndecl) = build_distinct_type_copy (TREE_TYPE (fndecl));
fdf7662c 12802 t = TREE_TYPE (TREE_TYPE (fndecl));
12803 if (INTEGRAL_TYPE_P (t) || POINTER_TYPE_P (t))
d09768a4 12804 veclen = node->simdclone->vecsize_int;
12805 else
12806 veclen = node->simdclone->vecsize_float;
fdf7662c 12807 veclen /= GET_MODE_BITSIZE (TYPE_MODE (t));
d09768a4 12808 if (veclen > node->simdclone->simdlen)
12809 veclen = node->simdclone->simdlen;
fdf7662c 12810 if (POINTER_TYPE_P (t))
12811 t = pointer_sized_int_node;
d09768a4 12812 if (veclen == node->simdclone->simdlen)
fdf7662c 12813 t = build_vector_type (t, node->simdclone->simdlen);
d09768a4 12814 else
12815 {
fdf7662c 12816 t = build_vector_type (t, veclen);
d09768a4 12817 t = build_array_type_nelts (t, node->simdclone->simdlen / veclen);
d09768a4 12818 }
fdf7662c 12819 TREE_TYPE (TREE_TYPE (fndecl)) = t;
d09768a4 12820 if (!node->definition)
12821 return NULL_TREE;
12822
12823 t = DECL_RESULT (fndecl);
12824 /* Adjust the DECL_RESULT. */
12825 gcc_assert (TREE_TYPE (t) != void_type_node);
12826 TREE_TYPE (t) = TREE_TYPE (TREE_TYPE (fndecl));
12827 relayout_decl (t);
12828
12829 tree atype = build_array_type_nelts (orig_rettype,
12830 node->simdclone->simdlen);
12831 if (veclen != node->simdclone->simdlen)
12832 return build1 (VIEW_CONVERT_EXPR, atype, t);
12833
12834 /* Set up a SIMD array to use as the return value. */
12835 tree retval = create_tmp_var_raw (atype, "retval");
12836 gimple_add_tmp_var (retval);
12837 return retval;
12838}
12839
12840/* Each vector argument has a corresponding array to be used locally
12841 as part of the eventual loop. Create such temporary array and
12842 return it.
12843
12844 PREFIX is the prefix to be used for the temporary.
12845
12846 TYPE is the inner element type.
12847
12848 SIMDLEN is the number of elements. */
12849
12850static tree
12851create_tmp_simd_array (const char *prefix, tree type, int simdlen)
12852{
12853 tree atype = build_array_type_nelts (type, simdlen);
12854 tree avar = create_tmp_var_raw (atype, prefix);
12855 gimple_add_tmp_var (avar);
12856 return avar;
12857}
12858
12859/* Modify the function argument types to their corresponding vector
12860 counterparts if appropriate. Also, create one array for each simd
12861 argument to be used locally when using the function arguments as
12862 part of the loop.
12863
12864 NODE is the function whose arguments are to be adjusted.
12865
12866 Returns an adjustment vector that will be filled describing how the
12867 argument types will be adjusted. */
12868
12869static ipa_parm_adjustment_vec
12870simd_clone_adjust_argument_types (struct cgraph_node *node)
12871{
12872 vec<tree> args;
12873 ipa_parm_adjustment_vec adjustments;
12874
12875 if (node->definition)
12876 args = ipa_get_vector_of_formal_parms (node->decl);
12877 else
12878 args = simd_clone_vector_of_formal_parm_types (node->decl);
12879 adjustments.create (args.length ());
12880 unsigned i, j, veclen;
12881 struct ipa_parm_adjustment adj;
12882 for (i = 0; i < node->simdclone->nargs; ++i)
12883 {
12884 memset (&adj, 0, sizeof (adj));
12885 tree parm = args[i];
12886 tree parm_type = node->definition ? TREE_TYPE (parm) : parm;
12887 adj.base_index = i;
12888 adj.base = parm;
12889
12890 node->simdclone->args[i].orig_arg = node->definition ? parm : NULL_TREE;
12891 node->simdclone->args[i].orig_type = parm_type;
12892
12893 if (node->simdclone->args[i].arg_type != SIMD_CLONE_ARG_TYPE_VECTOR)
12894 {
12895 /* No adjustment necessary for scalar arguments. */
12896 adj.op = IPA_PARM_OP_COPY;
12897 }
12898 else
12899 {
12900 if (INTEGRAL_TYPE_P (parm_type) || POINTER_TYPE_P (parm_type))
12901 veclen = node->simdclone->vecsize_int;
12902 else
12903 veclen = node->simdclone->vecsize_float;
12904 veclen /= GET_MODE_BITSIZE (TYPE_MODE (parm_type));
12905 if (veclen > node->simdclone->simdlen)
12906 veclen = node->simdclone->simdlen;
12907 adj.arg_prefix = "simd";
fdf7662c 12908 if (POINTER_TYPE_P (parm_type))
12909 adj.type = build_vector_type (pointer_sized_int_node, veclen);
12910 else
12911 adj.type = build_vector_type (parm_type, veclen);
d09768a4 12912 node->simdclone->args[i].vector_type = adj.type;
12913 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
12914 {
12915 adjustments.safe_push (adj);
12916 if (j == veclen)
12917 {
12918 memset (&adj, 0, sizeof (adj));
12919 adj.op = IPA_PARM_OP_NEW;
12920 adj.arg_prefix = "simd";
12921 adj.base_index = i;
12922 adj.type = node->simdclone->args[i].vector_type;
12923 }
12924 }
12925
12926 if (node->definition)
12927 node->simdclone->args[i].simd_array
12928 = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm)),
12929 parm_type, node->simdclone->simdlen);
12930 }
12931 adjustments.safe_push (adj);
12932 }
12933
12934 if (node->simdclone->inbranch)
12935 {
12936 tree base_type
12937 = simd_clone_compute_base_data_type (node->simdclone->origin,
12938 node->simdclone);
12939
12940 memset (&adj, 0, sizeof (adj));
12941 adj.op = IPA_PARM_OP_NEW;
12942 adj.arg_prefix = "mask";
12943
12944 adj.base_index = i;
12945 if (INTEGRAL_TYPE_P (base_type) || POINTER_TYPE_P (base_type))
12946 veclen = node->simdclone->vecsize_int;
12947 else
12948 veclen = node->simdclone->vecsize_float;
12949 veclen /= GET_MODE_BITSIZE (TYPE_MODE (base_type));
12950 if (veclen > node->simdclone->simdlen)
12951 veclen = node->simdclone->simdlen;
fdf7662c 12952 if (POINTER_TYPE_P (base_type))
12953 adj.type = build_vector_type (pointer_sized_int_node, veclen);
12954 else
12955 adj.type = build_vector_type (base_type, veclen);
d09768a4 12956 adjustments.safe_push (adj);
12957
12958 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
12959 adjustments.safe_push (adj);
12960
12961 /* We have previously allocated one extra entry for the mask. Use
12962 it and fill it. */
12963 struct cgraph_simd_clone *sc = node->simdclone;
12964 sc->nargs++;
12965 if (node->definition)
12966 {
12967 sc->args[i].orig_arg
12968 = build_decl (UNKNOWN_LOCATION, PARM_DECL, NULL, base_type);
12969 sc->args[i].simd_array
12970 = create_tmp_simd_array ("mask", base_type, sc->simdlen);
12971 }
12972 sc->args[i].orig_type = base_type;
12973 sc->args[i].arg_type = SIMD_CLONE_ARG_TYPE_MASK;
12974 }
12975
12976 if (node->definition)
12977 ipa_modify_formal_parameters (node->decl, adjustments);
12978 else
12979 {
12980 tree new_arg_types = NULL_TREE, new_reversed;
12981 bool last_parm_void = false;
12982 if (args.length () > 0 && args.last () == void_type_node)
12983 last_parm_void = true;
12984
12985 gcc_assert (TYPE_ARG_TYPES (TREE_TYPE (node->decl)));
12986 j = adjustments.length ();
12987 for (i = 0; i < j; i++)
12988 {
12989 struct ipa_parm_adjustment *adj = &adjustments[i];
12990 tree ptype;
12991 if (adj->op == IPA_PARM_OP_COPY)
12992 ptype = args[adj->base_index];
12993 else
12994 ptype = adj->type;
12995 new_arg_types = tree_cons (NULL_TREE, ptype, new_arg_types);
12996 }
12997 new_reversed = nreverse (new_arg_types);
12998 if (last_parm_void)
12999 {
13000 if (new_reversed)
13001 TREE_CHAIN (new_arg_types) = void_list_node;
13002 else
13003 new_reversed = void_list_node;
13004 }
13005
13006 tree new_type = build_distinct_type_copy (TREE_TYPE (node->decl));
13007 TYPE_ARG_TYPES (new_type) = new_reversed;
13008 TREE_TYPE (node->decl) = new_type;
13009
13010 adjustments.release ();
13011 }
13012 args.release ();
13013 return adjustments;
13014}
13015
13016/* Initialize and copy the function arguments in NODE to their
13017 corresponding local simd arrays. Returns a fresh gimple_seq with
13018 the instruction sequence generated. */
13019
13020static gimple_seq
13021simd_clone_init_simd_arrays (struct cgraph_node *node,
13022 ipa_parm_adjustment_vec adjustments)
13023{
13024 gimple_seq seq = NULL;
13025 unsigned i = 0, j = 0, k;
13026
13027 for (tree arg = DECL_ARGUMENTS (node->decl);
13028 arg;
13029 arg = DECL_CHAIN (arg), i++, j++)
13030 {
13031 if (adjustments[j].op == IPA_PARM_OP_COPY)
13032 continue;
13033
13034 node->simdclone->args[i].vector_arg = arg;
13035
13036 tree array = node->simdclone->args[i].simd_array;
13037 if (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg)) == node->simdclone->simdlen)
13038 {
13039 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
13040 tree ptr = build_fold_addr_expr (array);
13041 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
13042 build_int_cst (ptype, 0));
13043 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
13044 gimplify_and_add (t, &seq);
13045 }
13046 else
13047 {
13048 unsigned int simdlen = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg));
13049 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
13050 for (k = 0; k < node->simdclone->simdlen; k += simdlen)
13051 {
13052 tree ptr = build_fold_addr_expr (array);
13053 int elemsize;
13054 if (k)
13055 {
13056 arg = DECL_CHAIN (arg);
13057 j++;
13058 }
13059 elemsize
13060 = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg))));
13061 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
13062 build_int_cst (ptype, k * elemsize));
13063 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
13064 gimplify_and_add (t, &seq);
13065 }
13066 }
13067 }
13068 return seq;
13069}
13070
13071/* Callback info for ipa_simd_modify_stmt_ops below. */
13072
13073struct modify_stmt_info {
13074 ipa_parm_adjustment_vec adjustments;
13075 gimple stmt;
13076 /* True if the parent statement was modified by
13077 ipa_simd_modify_stmt_ops. */
13078 bool modified;
13079};
13080
13081/* Callback for walk_gimple_op.
13082
13083 Adjust operands from a given statement as specified in the
13084 adjustments vector in the callback data. */
13085
13086static tree
13087ipa_simd_modify_stmt_ops (tree *tp, int *walk_subtrees, void *data)
13088{
13089 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
2d78e89f 13090 struct modify_stmt_info *info = (struct modify_stmt_info *) wi->info;
13091 tree *orig_tp = tp;
13092 if (TREE_CODE (*tp) == ADDR_EXPR)
13093 tp = &TREE_OPERAND (*tp, 0);
13094 struct ipa_parm_adjustment *cand = NULL;
13095 if (TREE_CODE (*tp) == PARM_DECL)
13096 cand = ipa_get_adjustment_candidate (&tp, NULL, info->adjustments, true);
13097 else
d09768a4 13098 {
d09768a4 13099 if (TYPE_P (*tp))
13100 *walk_subtrees = 0;
d09768a4 13101 }
d09768a4 13102
2d78e89f 13103 tree repl = NULL_TREE;
13104 if (cand)
13105 repl = unshare_expr (cand->new_decl);
13106 else
d09768a4 13107 {
2d78e89f 13108 if (tp != orig_tp)
13109 {
13110 *walk_subtrees = 0;
13111 bool modified = info->modified;
13112 info->modified = false;
13113 walk_tree (tp, ipa_simd_modify_stmt_ops, wi, wi->pset);
13114 if (!info->modified)
13115 {
13116 info->modified = modified;
13117 return NULL_TREE;
13118 }
13119 info->modified = modified;
13120 repl = *tp;
13121 }
13122 else
13123 return NULL_TREE;
d09768a4 13124 }
2d78e89f 13125
13126 if (tp != orig_tp)
d09768a4 13127 {
2d78e89f 13128 repl = build_fold_addr_expr (repl);
9c1dd4d9 13129 gimple stmt;
13130 if (is_gimple_debug (info->stmt))
13131 {
13132 tree vexpr = make_node (DEBUG_EXPR_DECL);
13133 stmt = gimple_build_debug_source_bind (vexpr, repl, NULL);
13134 DECL_ARTIFICIAL (vexpr) = 1;
13135 TREE_TYPE (vexpr) = TREE_TYPE (repl);
13136 DECL_MODE (vexpr) = TYPE_MODE (TREE_TYPE (repl));
13137 repl = vexpr;
13138 }
13139 else
13140 {
f9e245b2 13141 stmt = gimple_build_assign (make_ssa_name (TREE_TYPE (repl)), repl);
9c1dd4d9 13142 repl = gimple_assign_lhs (stmt);
13143 }
2d78e89f 13144 gimple_stmt_iterator gsi = gsi_for_stmt (info->stmt);
d09768a4 13145 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
2d78e89f 13146 *orig_tp = repl;
d09768a4 13147 }
2d78e89f 13148 else if (!useless_type_conversion_p (TREE_TYPE (*tp), TREE_TYPE (repl)))
d09768a4 13149 {
13150 tree vce = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (*tp), repl);
13151 *tp = vce;
13152 }
13153 else
13154 *tp = repl;
13155
13156 info->modified = true;
d09768a4 13157 return NULL_TREE;
13158}
13159
13160/* Traverse the function body and perform all modifications as
13161 described in ADJUSTMENTS. At function return, ADJUSTMENTS will be
13162 modified such that the replacement/reduction value will now be an
13163 offset into the corresponding simd_array.
13164
13165 This function will replace all function argument uses with their
13166 corresponding simd array elements, and ajust the return values
13167 accordingly. */
13168
13169static void
13170ipa_simd_modify_function_body (struct cgraph_node *node,
13171 ipa_parm_adjustment_vec adjustments,
13172 tree retval_array, tree iter)
13173{
13174 basic_block bb;
2d78e89f 13175 unsigned int i, j, l;
d09768a4 13176
13177 /* Re-use the adjustments array, but this time use it to replace
13178 every function argument use to an offset into the corresponding
13179 simd_array. */
13180 for (i = 0, j = 0; i < node->simdclone->nargs; ++i, ++j)
13181 {
13182 if (!node->simdclone->args[i].vector_arg)
13183 continue;
13184
13185 tree basetype = TREE_TYPE (node->simdclone->args[i].orig_arg);
13186 tree vectype = TREE_TYPE (node->simdclone->args[i].vector_arg);
13187 adjustments[j].new_decl
13188 = build4 (ARRAY_REF,
13189 basetype,
13190 node->simdclone->args[i].simd_array,
13191 iter,
13192 NULL_TREE, NULL_TREE);
13193 if (adjustments[j].op == IPA_PARM_OP_NONE
13194 && TYPE_VECTOR_SUBPARTS (vectype) < node->simdclone->simdlen)
13195 j += node->simdclone->simdlen / TYPE_VECTOR_SUBPARTS (vectype) - 1;
13196 }
13197
2d78e89f 13198 l = adjustments.length ();
13199 for (i = 1; i < num_ssa_names; i++)
13200 {
13201 tree name = ssa_name (i);
13202 if (name
13203 && SSA_NAME_VAR (name)
13204 && TREE_CODE (SSA_NAME_VAR (name)) == PARM_DECL)
13205 {
13206 for (j = 0; j < l; j++)
13207 if (SSA_NAME_VAR (name) == adjustments[j].base
13208 && adjustments[j].new_decl)
13209 {
13210 tree base_var;
13211 if (adjustments[j].new_ssa_base == NULL_TREE)
13212 {
13213 base_var
13214 = copy_var_decl (adjustments[j].base,
13215 DECL_NAME (adjustments[j].base),
13216 TREE_TYPE (adjustments[j].base));
13217 adjustments[j].new_ssa_base = base_var;
13218 }
13219 else
13220 base_var = adjustments[j].new_ssa_base;
13221 if (SSA_NAME_IS_DEFAULT_DEF (name))
13222 {
13223 bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
13224 gimple_stmt_iterator gsi = gsi_after_labels (bb);
13225 tree new_decl = unshare_expr (adjustments[j].new_decl);
13226 set_ssa_default_def (cfun, adjustments[j].base, NULL_TREE);
13227 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
13228 SSA_NAME_IS_DEFAULT_DEF (name) = 0;
13229 gimple stmt = gimple_build_assign (name, new_decl);
13230 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
13231 }
13232 else
13233 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
13234 }
13235 }
13236 }
13237
d09768a4 13238 struct modify_stmt_info info;
13239 info.adjustments = adjustments;
13240
13241 FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl))
13242 {
13243 gimple_stmt_iterator gsi;
13244
13245 gsi = gsi_start_bb (bb);
13246 while (!gsi_end_p (gsi))
13247 {
13248 gimple stmt = gsi_stmt (gsi);
13249 info.stmt = stmt;
13250 struct walk_stmt_info wi;
13251
13252 memset (&wi, 0, sizeof (wi));
13253 info.modified = false;
13254 wi.info = &info;
13255 walk_gimple_op (stmt, ipa_simd_modify_stmt_ops, &wi);
13256
1a91d914 13257 if (greturn *return_stmt = dyn_cast <greturn *> (stmt))
d09768a4 13258 {
1a91d914 13259 tree retval = gimple_return_retval (return_stmt);
d09768a4 13260 if (!retval)
13261 {
13262 gsi_remove (&gsi, true);
13263 continue;
13264 }
13265
13266 /* Replace `return foo' with `retval_array[iter] = foo'. */
13267 tree ref = build4 (ARRAY_REF, TREE_TYPE (retval),
13268 retval_array, iter, NULL, NULL);
13269 stmt = gimple_build_assign (ref, retval);
13270 gsi_replace (&gsi, stmt, true);
13271 info.modified = true;
13272 }
13273
13274 if (info.modified)
13275 {
13276 update_stmt (stmt);
13277 if (maybe_clean_eh_stmt (stmt))
13278 gimple_purge_dead_eh_edges (gimple_bb (stmt));
13279 }
13280 gsi_next (&gsi);
13281 }
13282 }
13283}
13284
13285/* Adjust the argument types in NODE to their appropriate vector
13286 counterparts. */
13287
13288static void
13289simd_clone_adjust (struct cgraph_node *node)
13290{
13291 push_cfun (DECL_STRUCT_FUNCTION (node->decl));
13292
13293 targetm.simd_clone.adjust (node);
13294
13295 tree retval = simd_clone_adjust_return_type (node);
13296 ipa_parm_adjustment_vec adjustments
13297 = simd_clone_adjust_argument_types (node);
13298
13299 push_gimplify_context ();
13300
13301 gimple_seq seq = simd_clone_init_simd_arrays (node, adjustments);
13302
13303 /* Adjust all uses of vector arguments accordingly. Adjust all
13304 return values accordingly. */
13305 tree iter = create_tmp_var (unsigned_type_node, "iter");
f9e245b2 13306 tree iter1 = make_ssa_name (iter);
13307 tree iter2 = make_ssa_name (iter);
d09768a4 13308 ipa_simd_modify_function_body (node, adjustments, retval, iter1);
13309
13310 /* Initialize the iteration variable. */
13311 basic_block entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
13312 basic_block body_bb = split_block_after_labels (entry_bb)->dest;
13313 gimple_stmt_iterator gsi = gsi_after_labels (entry_bb);
13314 /* Insert the SIMD array and iv initialization at function
13315 entry. */
13316 gsi_insert_seq_before (&gsi, seq, GSI_NEW_STMT);
13317
13318 pop_gimplify_context (NULL);
13319
13320 /* Create a new BB right before the original exit BB, to hold the
13321 iteration increment and the condition/branch. */
13322 basic_block orig_exit = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), 0)->src;
13323 basic_block incr_bb = create_empty_bb (orig_exit);
343ee723 13324 add_bb_to_loop (incr_bb, body_bb->loop_father);
d09768a4 13325 /* The succ of orig_exit was EXIT_BLOCK_PTR_FOR_FN (cfun), with an empty
13326 flag. Set it now to be a FALLTHRU_EDGE. */
13327 gcc_assert (EDGE_COUNT (orig_exit->succs) == 1);
13328 EDGE_SUCC (orig_exit, 0)->flags |= EDGE_FALLTHRU;
13329 for (unsigned i = 0;
13330 i < EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds); ++i)
13331 {
13332 edge e = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), i);
13333 redirect_edge_succ (e, incr_bb);
13334 }
13335 edge e = make_edge (incr_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
13336 e->probability = REG_BR_PROB_BASE;
13337 gsi = gsi_last_bb (incr_bb);
e9cf809e 13338 gimple g = gimple_build_assign (iter2, PLUS_EXPR, iter1,
13339 build_int_cst (unsigned_type_node, 1));
d09768a4 13340 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13341
13342 /* Mostly annotate the loop for the vectorizer (the rest is done below). */
13343 struct loop *loop = alloc_loop ();
4c73695b 13344 cfun->has_force_vectorize_loops = true;
d09768a4 13345 loop->safelen = node->simdclone->simdlen;
4c73695b 13346 loop->force_vectorize = true;
d09768a4 13347 loop->header = body_bb;
d09768a4 13348
13349 /* Branch around the body if the mask applies. */
13350 if (node->simdclone->inbranch)
13351 {
13352 gimple_stmt_iterator gsi = gsi_last_bb (loop->header);
13353 tree mask_array
13354 = node->simdclone->args[node->simdclone->nargs - 1].simd_array;
f9e245b2 13355 tree mask = make_ssa_name (TREE_TYPE (TREE_TYPE (mask_array)));
d09768a4 13356 tree aref = build4 (ARRAY_REF,
13357 TREE_TYPE (TREE_TYPE (mask_array)),
13358 mask_array, iter1,
13359 NULL, NULL);
13360 g = gimple_build_assign (mask, aref);
13361 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13362 int bitsize = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (aref)));
13363 if (!INTEGRAL_TYPE_P (TREE_TYPE (aref)))
13364 {
13365 aref = build1 (VIEW_CONVERT_EXPR,
13366 build_nonstandard_integer_type (bitsize, 0), mask);
f9e245b2 13367 mask = make_ssa_name (TREE_TYPE (aref));
d09768a4 13368 g = gimple_build_assign (mask, aref);
13369 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13370 }
13371
13372 g = gimple_build_cond (EQ_EXPR, mask, build_zero_cst (TREE_TYPE (mask)),
13373 NULL, NULL);
13374 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13375 make_edge (loop->header, incr_bb, EDGE_TRUE_VALUE);
13376 FALLTHRU_EDGE (loop->header)->flags = EDGE_FALSE_VALUE;
13377 }
13378
13379 /* Generate the condition. */
13380 g = gimple_build_cond (LT_EXPR,
13381 iter2,
13382 build_int_cst (unsigned_type_node,
13383 node->simdclone->simdlen),
13384 NULL, NULL);
13385 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13386 e = split_block (incr_bb, gsi_stmt (gsi));
13387 basic_block latch_bb = e->dest;
343ee723 13388 basic_block new_exit_bb;
4302d619 13389 new_exit_bb = split_block_after_labels (latch_bb)->dest;
d09768a4 13390 loop->latch = latch_bb;
13391
13392 redirect_edge_succ (FALLTHRU_EDGE (latch_bb), body_bb);
13393
13394 make_edge (incr_bb, new_exit_bb, EDGE_FALSE_VALUE);
13395 /* The successor of incr_bb is already pointing to latch_bb; just
13396 change the flags.
13397 make_edge (incr_bb, latch_bb, EDGE_TRUE_VALUE); */
13398 FALLTHRU_EDGE (incr_bb)->flags = EDGE_TRUE_VALUE;
13399
1a91d914 13400 gphi *phi = create_phi_node (iter1, body_bb);
d09768a4 13401 edge preheader_edge = find_edge (entry_bb, body_bb);
13402 edge latch_edge = single_succ_edge (latch_bb);
13403 add_phi_arg (phi, build_zero_cst (unsigned_type_node), preheader_edge,
13404 UNKNOWN_LOCATION);
13405 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
13406
13407 /* Generate the new return. */
13408 gsi = gsi_last_bb (new_exit_bb);
13409 if (retval
13410 && TREE_CODE (retval) == VIEW_CONVERT_EXPR
13411 && TREE_CODE (TREE_OPERAND (retval, 0)) == RESULT_DECL)
13412 retval = TREE_OPERAND (retval, 0);
13413 else if (retval)
13414 {
13415 retval = build1 (VIEW_CONVERT_EXPR,
13416 TREE_TYPE (TREE_TYPE (node->decl)),
13417 retval);
13418 retval = force_gimple_operand_gsi (&gsi, retval, true, NULL,
13419 false, GSI_CONTINUE_LINKING);
13420 }
13421 g = gimple_build_return (retval);
13422 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13423
13424 /* Handle aligned clauses by replacing default defs of the aligned
13425 uniform args with __builtin_assume_aligned (arg_N(D), alignment)
13426 lhs. Handle linear by adding PHIs. */
13427 for (unsigned i = 0; i < node->simdclone->nargs; i++)
13428 if (node->simdclone->args[i].alignment
13429 && node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
13430 && (node->simdclone->args[i].alignment
13431 & (node->simdclone->args[i].alignment - 1)) == 0
13432 && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
13433 == POINTER_TYPE)
13434 {
13435 unsigned int alignment = node->simdclone->args[i].alignment;
13436 tree orig_arg = node->simdclone->args[i].orig_arg;
13437 tree def = ssa_default_def (cfun, orig_arg);
6db33a3d 13438 if (def && !has_zero_uses (def))
d09768a4 13439 {
13440 tree fn = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
13441 gimple_seq seq = NULL;
13442 bool need_cvt = false;
1a91d914 13443 gcall *call
d09768a4 13444 = gimple_build_call (fn, 2, def, size_int (alignment));
13445 g = call;
13446 if (!useless_type_conversion_p (TREE_TYPE (orig_arg),
13447 ptr_type_node))
13448 need_cvt = true;
f9e245b2 13449 tree t = make_ssa_name (need_cvt ? ptr_type_node : orig_arg);
d09768a4 13450 gimple_call_set_lhs (g, t);
13451 gimple_seq_add_stmt_without_update (&seq, g);
13452 if (need_cvt)
13453 {
f9e245b2 13454 t = make_ssa_name (orig_arg);
e9cf809e 13455 g = gimple_build_assign (t, NOP_EXPR, gimple_call_lhs (g));
d09768a4 13456 gimple_seq_add_stmt_without_update (&seq, g);
13457 }
13458 gsi_insert_seq_on_edge_immediate
13459 (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)), seq);
13460
13461 entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
13462 int freq = compute_call_stmt_bb_frequency (current_function_decl,
13463 entry_bb);
415d1b9a 13464 node->create_edge (cgraph_node::get_create (fn),
13465 call, entry_bb->count, freq);
d09768a4 13466
13467 imm_use_iterator iter;
13468 use_operand_p use_p;
13469 gimple use_stmt;
13470 tree repl = gimple_get_lhs (g);
13471 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
13472 if (is_gimple_debug (use_stmt) || use_stmt == call)
13473 continue;
13474 else
13475 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
13476 SET_USE (use_p, repl);
13477 }
13478 }
13479 else if (node->simdclone->args[i].arg_type
13480 == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
13481 {
13482 tree orig_arg = node->simdclone->args[i].orig_arg;
13483 tree def = ssa_default_def (cfun, orig_arg);
13484 gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
13485 || POINTER_TYPE_P (TREE_TYPE (orig_arg)));
6db33a3d 13486 if (def && !has_zero_uses (def))
d09768a4 13487 {
f9e245b2 13488 iter1 = make_ssa_name (orig_arg);
13489 iter2 = make_ssa_name (orig_arg);
d09768a4 13490 phi = create_phi_node (iter1, body_bb);
13491 add_phi_arg (phi, def, preheader_edge, UNKNOWN_LOCATION);
13492 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
13493 enum tree_code code = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
13494 ? PLUS_EXPR : POINTER_PLUS_EXPR;
13495 tree addtype = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
13496 ? TREE_TYPE (orig_arg) : sizetype;
13497 tree addcst
13498 = build_int_cst (addtype, node->simdclone->args[i].linear_step);
e9cf809e 13499 g = gimple_build_assign (iter2, code, iter1, addcst);
d09768a4 13500 gsi = gsi_last_bb (incr_bb);
13501 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
13502
13503 imm_use_iterator iter;
13504 use_operand_p use_p;
13505 gimple use_stmt;
13506 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
13507 if (use_stmt == phi)
13508 continue;
13509 else
13510 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
13511 SET_USE (use_p, iter1);
13512 }
13513 }
13514
13515 calculate_dominance_info (CDI_DOMINATORS);
13516 add_loop (loop, loop->header->loop_father);
13517 update_ssa (TODO_update_ssa);
13518
13519 pop_cfun ();
13520}
13521
13522/* If the function in NODE is tagged as an elemental SIMD function,
13523 create the appropriate SIMD clones. */
13524
13525static void
13526expand_simd_clones (struct cgraph_node *node)
13527{
d09768a4 13528 tree attr = lookup_attribute ("omp declare simd",
13529 DECL_ATTRIBUTES (node->decl));
ea0695f9 13530 if (attr == NULL_TREE
13531 || node->global.inlined_to
13532 || lookup_attribute ("noclone", DECL_ATTRIBUTES (node->decl)))
d09768a4 13533 return;
ea0695f9 13534
d09768a4 13535 /* Ignore
13536 #pragma omp declare simd
13537 extern int foo ();
13538 in C, there we don't know the argument types at all. */
13539 if (!node->definition
13540 && TYPE_ARG_TYPES (TREE_TYPE (node->decl)) == NULL_TREE)
13541 return;
13542
13543 do
13544 {
13545 /* Start with parsing the "omp declare simd" attribute(s). */
13546 bool inbranch_clause_specified;
13547 struct cgraph_simd_clone *clone_info
13548 = simd_clone_clauses_extract (node, TREE_VALUE (attr),
13549 &inbranch_clause_specified);
13550 if (clone_info == NULL)
13551 continue;
13552
13553 int orig_simdlen = clone_info->simdlen;
13554 tree base_type = simd_clone_compute_base_data_type (node, clone_info);
13555 /* The target can return 0 (no simd clones should be created),
13556 1 (just one ISA of simd clones should be created) or higher
13557 count of ISA variants. In that case, clone_info is initialized
13558 for the first ISA variant. */
13559 int count
13560 = targetm.simd_clone.compute_vecsize_and_simdlen (node, clone_info,
13561 base_type, 0);
13562 if (count == 0)
13563 continue;
13564
13565 /* Loop over all COUNT ISA variants, and if !INBRANCH_CLAUSE_SPECIFIED,
13566 also create one inbranch and one !inbranch clone of it. */
13567 for (int i = 0; i < count * 2; i++)
13568 {
13569 struct cgraph_simd_clone *clone = clone_info;
13570 if (inbranch_clause_specified && (i & 1) != 0)
13571 continue;
13572
13573 if (i != 0)
13574 {
13575 clone = simd_clone_struct_alloc (clone_info->nargs
d09768a4 13576 + ((i & 1) != 0));
13577 simd_clone_struct_copy (clone, clone_info);
13578 /* Undo changes targetm.simd_clone.compute_vecsize_and_simdlen
13579 and simd_clone_adjust_argument_types did to the first
13580 clone's info. */
13581 clone->nargs -= clone_info->inbranch;
13582 clone->simdlen = orig_simdlen;
13583 /* And call the target hook again to get the right ISA. */
13584 targetm.simd_clone.compute_vecsize_and_simdlen (node, clone,
13585 base_type,
13586 i / 2);
13587 if ((i & 1) != 0)
13588 clone->inbranch = 1;
13589 }
13590
13591 /* simd_clone_mangle might fail if such a clone has been created
13592 already. */
13593 tree id = simd_clone_mangle (node, clone);
13594 if (id == NULL_TREE)
13595 continue;
13596
13597 /* Only when we are sure we want to create the clone actually
13598 clone the function (or definitions) or create another
13599 extern FUNCTION_DECL (for prototypes without definitions). */
13600 struct cgraph_node *n = simd_clone_create (node);
13601 if (n == NULL)
13602 continue;
13603
13604 n->simdclone = clone;
13605 clone->origin = node;
13606 clone->next_clone = NULL;
13607 if (node->simd_clones == NULL)
13608 {
13609 clone->prev_clone = n;
13610 node->simd_clones = n;
13611 }
13612 else
13613 {
13614 clone->prev_clone = node->simd_clones->simdclone->prev_clone;
13615 clone->prev_clone->simdclone->next_clone = n;
13616 node->simd_clones->simdclone->prev_clone = n;
13617 }
35ee1c66 13618 symtab->change_decl_assembler_name (n->decl, id);
d09768a4 13619 /* And finally adjust the return type, parameters and for
13620 definitions also function body. */
13621 if (node->definition)
13622 simd_clone_adjust (n);
13623 else
13624 {
13625 simd_clone_adjust_return_type (n);
13626 simd_clone_adjust_argument_types (n);
13627 }
13628 }
13629 }
13630 while ((attr = lookup_attribute ("omp declare simd", TREE_CHAIN (attr))));
13631}
13632
13633/* Entry point for IPA simd clone creation pass. */
13634
13635static unsigned int
13636ipa_omp_simd_clone (void)
13637{
13638 struct cgraph_node *node;
13639 FOR_EACH_FUNCTION (node)
13640 expand_simd_clones (node);
13641 return 0;
13642}
13643
13644namespace {
13645
13646const pass_data pass_data_omp_simd_clone =
13647{
13648 SIMPLE_IPA_PASS, /* type */
13649 "simdclone", /* name */
13650 OPTGROUP_NONE, /* optinfo_flags */
d09768a4 13651 TV_NONE, /* tv_id */
13652 ( PROP_ssa | PROP_cfg ), /* properties_required */
13653 0, /* properties_provided */
13654 0, /* properties_destroyed */
13655 0, /* todo_flags_start */
13656 0, /* todo_flags_finish */
13657};
13658
13659class pass_omp_simd_clone : public simple_ipa_opt_pass
13660{
13661public:
13662 pass_omp_simd_clone(gcc::context *ctxt)
13663 : simple_ipa_opt_pass(pass_data_omp_simd_clone, ctxt)
13664 {}
13665
13666 /* opt_pass methods: */
31315c24 13667 virtual bool gate (function *);
65b0537f 13668 virtual unsigned int execute (function *) { return ipa_omp_simd_clone (); }
d09768a4 13669};
13670
31315c24 13671bool
13672pass_omp_simd_clone::gate (function *)
13673{
13674 return ((flag_openmp || flag_openmp_simd
13675 || flag_cilkplus
13676 || (in_lto_p && !flag_wpa))
13677 && (targetm.simd_clone.compute_vecsize_and_simdlen != NULL));
13678}
13679
d09768a4 13680} // anon namespace
13681
13682simple_ipa_opt_pass *
13683make_pass_omp_simd_clone (gcc::context *ctxt)
13684{
13685 return new pass_omp_simd_clone (ctxt);
13686}
cbe8bda8 13687
dccabdd1 13688/* Helper function for omp_finish_file routine. Takes decls from V_DECLS and
13689 adds their addresses and sizes to constructor-vector V_CTOR. */
13690static void
13691add_decls_addresses_to_decl_constructor (vec<tree, va_gc> *v_decls,
13692 vec<constructor_elt, va_gc> *v_ctor)
13693{
13694 unsigned len = vec_safe_length (v_decls);
13695 for (unsigned i = 0; i < len; i++)
13696 {
13697 tree it = (*v_decls)[i];
13698 bool is_function = TREE_CODE (it) != VAR_DECL;
13699
13700 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE, build_fold_addr_expr (it));
13701 if (!is_function)
13702 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE,
13703 fold_convert (const_ptr_type_node,
13704 DECL_SIZE_UNIT (it)));
13705 }
13706}
13707
13708/* Create new symbols containing (address, size) pairs for global variables,
13709 marked with "omp declare target" attribute, as well as addresses for the
ca4c3545 13710 functions, which are outlined offloading regions. */
dccabdd1 13711void
13712omp_finish_file (void)
13713{
13714 unsigned num_funcs = vec_safe_length (offload_funcs);
13715 unsigned num_vars = vec_safe_length (offload_vars);
13716
13717 if (num_funcs == 0 && num_vars == 0)
13718 return;
13719
13720 if (targetm_common.have_named_sections)
13721 {
13722 vec<constructor_elt, va_gc> *v_f, *v_v;
13723 vec_alloc (v_f, num_funcs);
13724 vec_alloc (v_v, num_vars * 2);
13725
13726 add_decls_addresses_to_decl_constructor (offload_funcs, v_f);
13727 add_decls_addresses_to_decl_constructor (offload_vars, v_v);
13728
13729 tree vars_decl_type = build_array_type_nelts (pointer_sized_int_node,
13730 num_vars * 2);
13731 tree funcs_decl_type = build_array_type_nelts (pointer_sized_int_node,
13732 num_funcs);
13733 TYPE_ALIGN (vars_decl_type) = TYPE_ALIGN (pointer_sized_int_node);
13734 TYPE_ALIGN (funcs_decl_type) = TYPE_ALIGN (pointer_sized_int_node);
13735 tree ctor_v = build_constructor (vars_decl_type, v_v);
13736 tree ctor_f = build_constructor (funcs_decl_type, v_f);
13737 TREE_CONSTANT (ctor_v) = TREE_CONSTANT (ctor_f) = 1;
13738 TREE_STATIC (ctor_v) = TREE_STATIC (ctor_f) = 1;
13739 tree funcs_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
13740 get_identifier (".offload_func_table"),
13741 funcs_decl_type);
13742 tree vars_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
13743 get_identifier (".offload_var_table"),
13744 vars_decl_type);
13745 TREE_STATIC (funcs_decl) = TREE_STATIC (vars_decl) = 1;
13746 /* Do not align tables more than TYPE_ALIGN (pointer_sized_int_node),
13747 otherwise a joint table in a binary will contain padding between
13748 tables from multiple object files. */
13749 DECL_USER_ALIGN (funcs_decl) = DECL_USER_ALIGN (vars_decl) = 1;
13750 DECL_ALIGN (funcs_decl) = TYPE_ALIGN (funcs_decl_type);
13751 DECL_ALIGN (vars_decl) = TYPE_ALIGN (vars_decl_type);
13752 DECL_INITIAL (funcs_decl) = ctor_f;
13753 DECL_INITIAL (vars_decl) = ctor_v;
13754 set_decl_section_name (funcs_decl, OFFLOAD_FUNC_TABLE_SECTION_NAME);
13755 set_decl_section_name (vars_decl, OFFLOAD_VAR_TABLE_SECTION_NAME);
13756
13757 varpool_node::finalize_decl (vars_decl);
13758 varpool_node::finalize_decl (funcs_decl);
7114ebdd 13759 }
dccabdd1 13760 else
13761 {
13762 for (unsigned i = 0; i < num_funcs; i++)
13763 {
13764 tree it = (*offload_funcs)[i];
13765 targetm.record_offload_symbol (it);
13766 }
13767 for (unsigned i = 0; i < num_vars; i++)
13768 {
13769 tree it = (*offload_vars)[i];
13770 targetm.record_offload_symbol (it);
13771 }
13772 }
13773}
13774
1e8e9920 13775#include "gt-omp-low.h"