]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/omp-low.c
2014-11-29 Tobias Burnus <burnus@net-b.de>
[thirdparty/gcc.git] / gcc / omp-low.c
CommitLineData
1e8e9920 1/* Lowering pass for OpenMP directives. Converts OpenMP directives
2 into explicit calls to the runtime library (libgomp) and data
3 marshalling to implement data sharing and copying clauses.
4 Contributed by Diego Novillo <dnovillo@redhat.com>
5
3aea1f79 6 Copyright (C) 2005-2014 Free Software Foundation, Inc.
1e8e9920 7
8This file is part of GCC.
9
10GCC is free software; you can redistribute it and/or modify it under
11the terms of the GNU General Public License as published by the Free
8c4c00c1 12Software Foundation; either version 3, or (at your option) any later
1e8e9920 13version.
14
15GCC is distributed in the hope that it will be useful, but WITHOUT ANY
16WARRANTY; without even the implied warranty of MERCHANTABILITY or
17FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18for more details.
19
20You should have received a copy of the GNU General Public License
8c4c00c1 21along with GCC; see the file COPYING3. If not see
22<http://www.gnu.org/licenses/>. */
1e8e9920 23
24#include "config.h"
25#include "system.h"
26#include "coretypes.h"
27#include "tm.h"
28#include "tree.h"
9ed99284 29#include "stringpool.h"
30#include "stor-layout.h"
1e8e9920 31#include "rtl.h"
94ea8568 32#include "predict.h"
33#include "vec.h"
34#include "hashtab.h"
35#include "hash-set.h"
36#include "machmode.h"
37#include "hard-reg-set.h"
38#include "input.h"
39#include "function.h"
40#include "dominance.h"
41#include "cfg.h"
42#include "cfganal.h"
bc61cadb 43#include "basic-block.h"
44#include "tree-ssa-alias.h"
45#include "internal-fn.h"
46#include "gimple-fold.h"
47#include "gimple-expr.h"
48#include "is-a.h"
75a70cf9 49#include "gimple.h"
a8783bee 50#include "gimplify.h"
dcf1a1ec 51#include "gimple-iterator.h"
e795d6e1 52#include "gimplify-me.h"
dcf1a1ec 53#include "gimple-walk.h"
75a70cf9 54#include "tree-iterator.h"
1e8e9920 55#include "tree-inline.h"
56#include "langhooks.h"
852f689e 57#include "diagnostic-core.h"
073c1fd5 58#include "gimple-ssa.h"
1140c305 59#include "hash-map.h"
60#include "plugin-api.h"
61#include "ipa-ref.h"
073c1fd5 62#include "cgraph.h"
63#include "tree-cfg.h"
64#include "tree-phinodes.h"
65#include "ssa-iterators.h"
66#include "tree-ssanames.h"
67#include "tree-into-ssa.h"
9ed99284 68#include "expr.h"
073c1fd5 69#include "tree-dfa.h"
69ee5dbb 70#include "tree-ssa.h"
1e8e9920 71#include "flags.h"
1e8e9920 72#include "expr.h"
1e8e9920 73#include "tree-pass.h"
1e8e9920 74#include "except.h"
e3022db7 75#include "splay-tree.h"
34517c64 76#include "insn-codes.h"
cb7f680b 77#include "optabs.h"
78#include "cfgloop.h"
3d483a94 79#include "target.h"
dccabdd1 80#include "common/common-target.h"
7740abd8 81#include "omp-low.h"
424a4a92 82#include "gimple-low.h"
83#include "tree-cfgcleanup.h"
d09768a4 84#include "pretty-print.h"
1140c305 85#include "alloc-pool.h"
d09768a4 86#include "ipa-prop.h"
e797f49f 87#include "tree-nested.h"
d09768a4 88#include "tree-eh.h"
40750995 89#include "cilk.h"
b0c5e347 90#include "context.h"
dccabdd1 91#include "lto-section-names.h"
1e8e9920 92
75a70cf9 93
48e1416a 94/* Lowering of OpenMP parallel and workshare constructs proceeds in two
1e8e9920 95 phases. The first phase scans the function looking for OMP statements
96 and then for variables that must be replaced to satisfy data sharing
97 clauses. The second phase expands code for the constructs, as well as
334ec2d8 98 re-gimplifying things when variables have been replaced with complex
1e8e9920 99 expressions.
100
d134bccc 101 Final code generation is done by pass_expand_omp. The flowgraph is
102 scanned for parallel regions which are then moved to a new
103 function, to be invoked by the thread library. */
1e8e9920 104
7740abd8 105/* Parallel region information. Every parallel and workshare
106 directive is enclosed between two markers, the OMP_* directive
107 and a corresponding OMP_RETURN statement. */
108
109struct omp_region
110{
111 /* The enclosing region. */
112 struct omp_region *outer;
113
114 /* First child region. */
115 struct omp_region *inner;
116
117 /* Next peer region. */
118 struct omp_region *next;
119
120 /* Block containing the omp directive as its last stmt. */
121 basic_block entry;
122
123 /* Block containing the OMP_RETURN as its last stmt. */
124 basic_block exit;
125
126 /* Block containing the OMP_CONTINUE as its last stmt. */
127 basic_block cont;
128
129 /* If this is a combined parallel+workshare region, this is a list
130 of additional arguments needed by the combined parallel+workshare
131 library call. */
132 vec<tree, va_gc> *ws_args;
133
134 /* The code for the omp directive of this region. */
135 enum gimple_code type;
136
137 /* Schedule kind, only used for OMP_FOR type regions. */
138 enum omp_clause_schedule_kind sched_kind;
139
140 /* True if this is a combined parallel+workshare region. */
141 bool is_combined_parallel;
142};
143
1e8e9920 144/* Context structure. Used to store information about each parallel
145 directive in the code. */
146
147typedef struct omp_context
148{
149 /* This field must be at the beginning, as we do "inheritance": Some
150 callback functions for tree-inline.c (e.g., omp_copy_decl)
151 receive a copy_body_data pointer that is up-casted to an
152 omp_context pointer. */
153 copy_body_data cb;
154
155 /* The tree of contexts corresponding to the encountered constructs. */
156 struct omp_context *outer;
75a70cf9 157 gimple stmt;
1e8e9920 158
48e1416a 159 /* Map variables to fields in a structure that allows communication
1e8e9920 160 between sending and receiving threads. */
161 splay_tree field_map;
162 tree record_type;
163 tree sender_decl;
164 tree receiver_decl;
165
fd6481cf 166 /* These are used just by task contexts, if task firstprivate fn is
167 needed. srecord_type is used to communicate from the thread
168 that encountered the task construct to task firstprivate fn,
169 record_type is allocated by GOMP_task, initialized by task firstprivate
170 fn and passed to the task body fn. */
171 splay_tree sfield_map;
172 tree srecord_type;
173
1e8e9920 174 /* A chain of variables to add to the top-level block surrounding the
175 construct. In the case of a parallel, this is in the child function. */
176 tree block_vars;
177
bc7bff74 178 /* Label to which GOMP_cancel{,llation_point} and explicit and implicit
179 barriers should jump to during omplower pass. */
180 tree cancel_label;
181
1e8e9920 182 /* What to do with variables with implicitly determined sharing
183 attributes. */
184 enum omp_clause_default_kind default_kind;
185
186 /* Nesting depth of this context. Used to beautify error messages re
187 invalid gotos. The outermost ctx is depth 1, with depth 0 being
188 reserved for the main body of the function. */
189 int depth;
190
1e8e9920 191 /* True if this parallel directive is nested within another. */
192 bool is_nested;
bc7bff74 193
194 /* True if this construct can be cancelled. */
195 bool cancellable;
1e8e9920 196} omp_context;
197
198
fd6481cf 199struct omp_for_data_loop
200{
201 tree v, n1, n2, step;
202 enum tree_code cond_code;
203};
204
773c5ba7 205/* A structure describing the main elements of a parallel loop. */
1e8e9920 206
773c5ba7 207struct omp_for_data
1e8e9920 208{
fd6481cf 209 struct omp_for_data_loop loop;
75a70cf9 210 tree chunk_size;
1a91d914 211 gomp_for *for_stmt;
fd6481cf 212 tree pre, iter_type;
213 int collapse;
1e8e9920 214 bool have_nowait, have_ordered;
215 enum omp_clause_schedule_kind sched_kind;
fd6481cf 216 struct omp_for_data_loop *loops;
1e8e9920 217};
218
773c5ba7 219
1e8e9920 220static splay_tree all_contexts;
fd6481cf 221static int taskreg_nesting_level;
bc7bff74 222static int target_nesting_level;
7740abd8 223static struct omp_region *root_omp_region;
fd6481cf 224static bitmap task_shared_vars;
37eaded9 225static vec<omp_context *> taskreg_contexts;
1e8e9920 226
ab129075 227static void scan_omp (gimple_seq *, omp_context *);
75a70cf9 228static tree scan_omp_1_op (tree *, int *, void *);
229
230#define WALK_SUBSTMTS \
231 case GIMPLE_BIND: \
232 case GIMPLE_TRY: \
233 case GIMPLE_CATCH: \
234 case GIMPLE_EH_FILTER: \
4c0315d0 235 case GIMPLE_TRANSACTION: \
75a70cf9 236 /* The sub-statements for these should be walked. */ \
237 *handled_ops_p = false; \
238 break;
239
dccabdd1 240/* Holds offload tables with decls. */
241vec<tree, va_gc> *offload_funcs, *offload_vars;
242
75a70cf9 243/* Convenience function for calling scan_omp_1_op on tree operands. */
244
245static inline tree
246scan_omp_op (tree *tp, omp_context *ctx)
247{
248 struct walk_stmt_info wi;
249
250 memset (&wi, 0, sizeof (wi));
251 wi.info = ctx;
252 wi.want_locations = true;
253
254 return walk_tree (tp, scan_omp_1_op, &wi, NULL);
255}
256
e3a19533 257static void lower_omp (gimple_seq *, omp_context *);
f49d7bb5 258static tree lookup_decl_in_outer_ctx (tree, omp_context *);
259static tree maybe_lookup_decl_in_outer_ctx (tree, omp_context *);
1e8e9920 260
261/* Find an OpenMP clause of type KIND within CLAUSES. */
262
79acaae1 263tree
590c3166 264find_omp_clause (tree clauses, enum omp_clause_code kind)
1e8e9920 265{
266 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
55d6e7cd 267 if (OMP_CLAUSE_CODE (clauses) == kind)
1e8e9920 268 return clauses;
269
270 return NULL_TREE;
271}
272
273/* Return true if CTX is for an omp parallel. */
274
275static inline bool
276is_parallel_ctx (omp_context *ctx)
277{
75a70cf9 278 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL;
1e8e9920 279}
280
773c5ba7 281
b0c5e347 282/* Return true if CTX is for an omp target region. */
283
284static inline bool
285is_targetreg_ctx (omp_context *ctx)
286{
287 return gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET
288 && gimple_omp_target_kind (ctx->stmt) == GF_OMP_TARGET_KIND_REGION;
289}
290
291
fd6481cf 292/* Return true if CTX is for an omp task. */
293
294static inline bool
295is_task_ctx (omp_context *ctx)
296{
75a70cf9 297 return gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
fd6481cf 298}
299
300
301/* Return true if CTX is for an omp parallel or omp task. */
302
303static inline bool
304is_taskreg_ctx (omp_context *ctx)
305{
75a70cf9 306 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL
307 || gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
fd6481cf 308}
309
310
773c5ba7 311/* Return true if REGION is a combined parallel+workshare region. */
1e8e9920 312
313static inline bool
773c5ba7 314is_combined_parallel (struct omp_region *region)
315{
316 return region->is_combined_parallel;
317}
318
319
320/* Extract the header elements of parallel loop FOR_STMT and store
321 them into *FD. */
322
323static void
1a91d914 324extract_omp_for_data (gomp_for *for_stmt, struct omp_for_data *fd,
fd6481cf 325 struct omp_for_data_loop *loops)
773c5ba7 326{
fd6481cf 327 tree t, var, *collapse_iter, *collapse_count;
328 tree count = NULL_TREE, iter_type = long_integer_type_node;
329 struct omp_for_data_loop *loop;
330 int i;
331 struct omp_for_data_loop dummy_loop;
389dd41b 332 location_t loc = gimple_location (for_stmt);
10c55644 333 bool simd = gimple_omp_for_kind (for_stmt) & GF_OMP_FOR_SIMD;
bc7bff74 334 bool distribute = gimple_omp_for_kind (for_stmt)
335 == GF_OMP_FOR_KIND_DISTRIBUTE;
773c5ba7 336
337 fd->for_stmt = for_stmt;
338 fd->pre = NULL;
75a70cf9 339 fd->collapse = gimple_omp_for_collapse (for_stmt);
fd6481cf 340 if (fd->collapse > 1)
341 fd->loops = loops;
342 else
343 fd->loops = &fd->loop;
773c5ba7 344
bc7bff74 345 fd->have_nowait = distribute || simd;
346 fd->have_ordered = false;
773c5ba7 347 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
348 fd->chunk_size = NULL_TREE;
40750995 349 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
350 fd->sched_kind = OMP_CLAUSE_SCHEDULE_CILKFOR;
fd6481cf 351 collapse_iter = NULL;
352 collapse_count = NULL;
773c5ba7 353
75a70cf9 354 for (t = gimple_omp_for_clauses (for_stmt); t ; t = OMP_CLAUSE_CHAIN (t))
55d6e7cd 355 switch (OMP_CLAUSE_CODE (t))
773c5ba7 356 {
357 case OMP_CLAUSE_NOWAIT:
358 fd->have_nowait = true;
359 break;
360 case OMP_CLAUSE_ORDERED:
361 fd->have_ordered = true;
362 break;
363 case OMP_CLAUSE_SCHEDULE:
bc7bff74 364 gcc_assert (!distribute);
773c5ba7 365 fd->sched_kind = OMP_CLAUSE_SCHEDULE_KIND (t);
366 fd->chunk_size = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t);
367 break;
bc7bff74 368 case OMP_CLAUSE_DIST_SCHEDULE:
369 gcc_assert (distribute);
370 fd->chunk_size = OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (t);
371 break;
fd6481cf 372 case OMP_CLAUSE_COLLAPSE:
373 if (fd->collapse > 1)
374 {
375 collapse_iter = &OMP_CLAUSE_COLLAPSE_ITERVAR (t);
376 collapse_count = &OMP_CLAUSE_COLLAPSE_COUNT (t);
377 }
757abb46 378 break;
773c5ba7 379 default:
380 break;
381 }
382
fd6481cf 383 /* FIXME: for now map schedule(auto) to schedule(static).
384 There should be analysis to determine whether all iterations
385 are approximately the same amount of work (then schedule(static)
bde357c8 386 is best) or if it varies (then schedule(dynamic,N) is better). */
fd6481cf 387 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_AUTO)
388 {
389 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
390 gcc_assert (fd->chunk_size == NULL);
391 }
392 gcc_assert (fd->collapse == 1 || collapse_iter != NULL);
773c5ba7 393 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
394 gcc_assert (fd->chunk_size == NULL);
395 else if (fd->chunk_size == NULL)
396 {
397 /* We only need to compute a default chunk size for ordered
398 static loops and dynamic loops. */
fd6481cf 399 if (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
bc7bff74 400 || fd->have_ordered)
773c5ba7 401 fd->chunk_size = (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
402 ? integer_zero_node : integer_one_node;
403 }
fd6481cf 404
405 for (i = 0; i < fd->collapse; i++)
406 {
407 if (fd->collapse == 1)
408 loop = &fd->loop;
409 else if (loops != NULL)
410 loop = loops + i;
411 else
412 loop = &dummy_loop;
413
75a70cf9 414 loop->v = gimple_omp_for_index (for_stmt, i);
fd6481cf 415 gcc_assert (SSA_VAR_P (loop->v));
416 gcc_assert (TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
417 || TREE_CODE (TREE_TYPE (loop->v)) == POINTER_TYPE);
418 var = TREE_CODE (loop->v) == SSA_NAME ? SSA_NAME_VAR (loop->v) : loop->v;
75a70cf9 419 loop->n1 = gimple_omp_for_initial (for_stmt, i);
fd6481cf 420
75a70cf9 421 loop->cond_code = gimple_omp_for_cond (for_stmt, i);
422 loop->n2 = gimple_omp_for_final (for_stmt, i);
fd6481cf 423 switch (loop->cond_code)
424 {
425 case LT_EXPR:
426 case GT_EXPR:
427 break;
f2697631 428 case NE_EXPR:
429 gcc_assert (gimple_omp_for_kind (for_stmt)
40750995 430 == GF_OMP_FOR_KIND_CILKSIMD
431 || (gimple_omp_for_kind (for_stmt)
432 == GF_OMP_FOR_KIND_CILKFOR));
f2697631 433 break;
fd6481cf 434 case LE_EXPR:
435 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
2cc66f2a 436 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, 1);
fd6481cf 437 else
389dd41b 438 loop->n2 = fold_build2_loc (loc,
439 PLUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
fd6481cf 440 build_int_cst (TREE_TYPE (loop->n2), 1));
441 loop->cond_code = LT_EXPR;
442 break;
443 case GE_EXPR:
444 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
2cc66f2a 445 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, -1);
fd6481cf 446 else
389dd41b 447 loop->n2 = fold_build2_loc (loc,
448 MINUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
fd6481cf 449 build_int_cst (TREE_TYPE (loop->n2), 1));
450 loop->cond_code = GT_EXPR;
451 break;
452 default:
453 gcc_unreachable ();
454 }
455
75a70cf9 456 t = gimple_omp_for_incr (for_stmt, i);
fd6481cf 457 gcc_assert (TREE_OPERAND (t, 0) == var);
458 switch (TREE_CODE (t))
459 {
460 case PLUS_EXPR:
fd6481cf 461 loop->step = TREE_OPERAND (t, 1);
462 break;
85d86b55 463 case POINTER_PLUS_EXPR:
464 loop->step = fold_convert (ssizetype, TREE_OPERAND (t, 1));
465 break;
fd6481cf 466 case MINUS_EXPR:
467 loop->step = TREE_OPERAND (t, 1);
389dd41b 468 loop->step = fold_build1_loc (loc,
469 NEGATE_EXPR, TREE_TYPE (loop->step),
fd6481cf 470 loop->step);
471 break;
472 default:
473 gcc_unreachable ();
474 }
475
bc7bff74 476 if (simd
477 || (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
478 && !fd->have_ordered))
3d483a94 479 {
480 if (fd->collapse == 1)
481 iter_type = TREE_TYPE (loop->v);
482 else if (i == 0
483 || TYPE_PRECISION (iter_type)
484 < TYPE_PRECISION (TREE_TYPE (loop->v)))
485 iter_type
486 = build_nonstandard_integer_type
bc7bff74 487 (TYPE_PRECISION (TREE_TYPE (loop->v)), 1);
3d483a94 488 }
489 else if (iter_type != long_long_unsigned_type_node)
fd6481cf 490 {
491 if (POINTER_TYPE_P (TREE_TYPE (loop->v)))
492 iter_type = long_long_unsigned_type_node;
493 else if (TYPE_UNSIGNED (TREE_TYPE (loop->v))
494 && TYPE_PRECISION (TREE_TYPE (loop->v))
495 >= TYPE_PRECISION (iter_type))
496 {
497 tree n;
498
499 if (loop->cond_code == LT_EXPR)
389dd41b 500 n = fold_build2_loc (loc,
501 PLUS_EXPR, TREE_TYPE (loop->v),
fd6481cf 502 loop->n2, loop->step);
503 else
504 n = loop->n1;
505 if (TREE_CODE (n) != INTEGER_CST
506 || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type), n))
507 iter_type = long_long_unsigned_type_node;
508 }
509 else if (TYPE_PRECISION (TREE_TYPE (loop->v))
510 > TYPE_PRECISION (iter_type))
511 {
512 tree n1, n2;
513
514 if (loop->cond_code == LT_EXPR)
515 {
516 n1 = loop->n1;
389dd41b 517 n2 = fold_build2_loc (loc,
518 PLUS_EXPR, TREE_TYPE (loop->v),
fd6481cf 519 loop->n2, loop->step);
520 }
521 else
522 {
389dd41b 523 n1 = fold_build2_loc (loc,
524 MINUS_EXPR, TREE_TYPE (loop->v),
fd6481cf 525 loop->n2, loop->step);
526 n2 = loop->n1;
527 }
528 if (TREE_CODE (n1) != INTEGER_CST
529 || TREE_CODE (n2) != INTEGER_CST
530 || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type), n1)
531 || !tree_int_cst_lt (n2, TYPE_MAX_VALUE (iter_type)))
532 iter_type = long_long_unsigned_type_node;
533 }
534 }
535
536 if (collapse_count && *collapse_count == NULL)
537 {
8e6b4515 538 t = fold_binary (loop->cond_code, boolean_type_node,
539 fold_convert (TREE_TYPE (loop->v), loop->n1),
540 fold_convert (TREE_TYPE (loop->v), loop->n2));
541 if (t && integer_zerop (t))
542 count = build_zero_cst (long_long_unsigned_type_node);
543 else if ((i == 0 || count != NULL_TREE)
544 && TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
545 && TREE_CONSTANT (loop->n1)
546 && TREE_CONSTANT (loop->n2)
547 && TREE_CODE (loop->step) == INTEGER_CST)
fd6481cf 548 {
549 tree itype = TREE_TYPE (loop->v);
550
551 if (POINTER_TYPE_P (itype))
3cea8318 552 itype = signed_type_for (itype);
fd6481cf 553 t = build_int_cst (itype, (loop->cond_code == LT_EXPR ? -1 : 1));
389dd41b 554 t = fold_build2_loc (loc,
555 PLUS_EXPR, itype,
556 fold_convert_loc (loc, itype, loop->step), t);
557 t = fold_build2_loc (loc, PLUS_EXPR, itype, t,
558 fold_convert_loc (loc, itype, loop->n2));
559 t = fold_build2_loc (loc, MINUS_EXPR, itype, t,
560 fold_convert_loc (loc, itype, loop->n1));
fd6481cf 561 if (TYPE_UNSIGNED (itype) && loop->cond_code == GT_EXPR)
389dd41b 562 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype,
563 fold_build1_loc (loc, NEGATE_EXPR, itype, t),
564 fold_build1_loc (loc, NEGATE_EXPR, itype,
565 fold_convert_loc (loc, itype,
566 loop->step)));
fd6481cf 567 else
389dd41b 568 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, t,
569 fold_convert_loc (loc, itype, loop->step));
570 t = fold_convert_loc (loc, long_long_unsigned_type_node, t);
fd6481cf 571 if (count != NULL_TREE)
389dd41b 572 count = fold_build2_loc (loc,
573 MULT_EXPR, long_long_unsigned_type_node,
fd6481cf 574 count, t);
575 else
576 count = t;
577 if (TREE_CODE (count) != INTEGER_CST)
578 count = NULL_TREE;
579 }
8e6b4515 580 else if (count && !integer_zerop (count))
fd6481cf 581 count = NULL_TREE;
582 }
583 }
584
3d483a94 585 if (count
bc7bff74 586 && !simd
587 && (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
588 || fd->have_ordered))
fd6481cf 589 {
590 if (!tree_int_cst_lt (count, TYPE_MAX_VALUE (long_integer_type_node)))
591 iter_type = long_long_unsigned_type_node;
592 else
593 iter_type = long_integer_type_node;
594 }
595 else if (collapse_iter && *collapse_iter != NULL)
596 iter_type = TREE_TYPE (*collapse_iter);
597 fd->iter_type = iter_type;
598 if (collapse_iter && *collapse_iter == NULL)
599 *collapse_iter = create_tmp_var (iter_type, ".iter");
600 if (collapse_count && *collapse_count == NULL)
601 {
602 if (count)
389dd41b 603 *collapse_count = fold_convert_loc (loc, iter_type, count);
fd6481cf 604 else
605 *collapse_count = create_tmp_var (iter_type, ".count");
606 }
607
608 if (fd->collapse > 1)
609 {
610 fd->loop.v = *collapse_iter;
611 fd->loop.n1 = build_int_cst (TREE_TYPE (fd->loop.v), 0);
612 fd->loop.n2 = *collapse_count;
613 fd->loop.step = build_int_cst (TREE_TYPE (fd->loop.v), 1);
614 fd->loop.cond_code = LT_EXPR;
615 }
773c5ba7 616}
617
618
619/* Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB
620 is the immediate dominator of PAR_ENTRY_BB, return true if there
621 are no data dependencies that would prevent expanding the parallel
622 directive at PAR_ENTRY_BB as a combined parallel+workshare region.
623
624 When expanding a combined parallel+workshare region, the call to
625 the child function may need additional arguments in the case of
75a70cf9 626 GIMPLE_OMP_FOR regions. In some cases, these arguments are
627 computed out of variables passed in from the parent to the child
628 via 'struct .omp_data_s'. For instance:
773c5ba7 629
630 #pragma omp parallel for schedule (guided, i * 4)
631 for (j ...)
632
633 Is lowered into:
634
635 # BLOCK 2 (PAR_ENTRY_BB)
636 .omp_data_o.i = i;
637 #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
48e1416a 638
773c5ba7 639 # BLOCK 3 (WS_ENTRY_BB)
640 .omp_data_i = &.omp_data_o;
641 D.1667 = .omp_data_i->i;
642 D.1598 = D.1667 * 4;
643 #pragma omp for schedule (guided, D.1598)
644
645 When we outline the parallel region, the call to the child function
646 'bar.omp_fn.0' will need the value D.1598 in its argument list, but
647 that value is computed *after* the call site. So, in principle we
648 cannot do the transformation.
649
650 To see whether the code in WS_ENTRY_BB blocks the combined
651 parallel+workshare call, we collect all the variables used in the
75a70cf9 652 GIMPLE_OMP_FOR header check whether they appear on the LHS of any
773c5ba7 653 statement in WS_ENTRY_BB. If so, then we cannot emit the combined
654 call.
655
656 FIXME. If we had the SSA form built at this point, we could merely
657 hoist the code in block 3 into block 2 and be done with it. But at
658 this point we don't have dataflow information and though we could
659 hack something up here, it is really not worth the aggravation. */
660
661static bool
f018d957 662workshare_safe_to_combine_p (basic_block ws_entry_bb)
773c5ba7 663{
664 struct omp_for_data fd;
f018d957 665 gimple ws_stmt = last_stmt (ws_entry_bb);
773c5ba7 666
75a70cf9 667 if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
773c5ba7 668 return true;
669
75a70cf9 670 gcc_assert (gimple_code (ws_stmt) == GIMPLE_OMP_FOR);
773c5ba7 671
1a91d914 672 extract_omp_for_data (as_a <gomp_for *> (ws_stmt), &fd, NULL);
fd6481cf 673
674 if (fd.collapse > 1 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
675 return false;
676 if (fd.iter_type != long_integer_type_node)
677 return false;
773c5ba7 678
679 /* FIXME. We give up too easily here. If any of these arguments
680 are not constants, they will likely involve variables that have
681 been mapped into fields of .omp_data_s for sharing with the child
682 function. With appropriate data flow, it would be possible to
683 see through this. */
fd6481cf 684 if (!is_gimple_min_invariant (fd.loop.n1)
685 || !is_gimple_min_invariant (fd.loop.n2)
686 || !is_gimple_min_invariant (fd.loop.step)
773c5ba7 687 || (fd.chunk_size && !is_gimple_min_invariant (fd.chunk_size)))
688 return false;
689
690 return true;
691}
692
693
694/* Collect additional arguments needed to emit a combined
695 parallel+workshare call. WS_STMT is the workshare directive being
696 expanded. */
697
f1f41a6c 698static vec<tree, va_gc> *
bc7bff74 699get_ws_args_for (gimple par_stmt, gimple ws_stmt)
773c5ba7 700{
701 tree t;
389dd41b 702 location_t loc = gimple_location (ws_stmt);
f1f41a6c 703 vec<tree, va_gc> *ws_args;
773c5ba7 704
1a91d914 705 if (gomp_for *for_stmt = dyn_cast <gomp_for *> (ws_stmt))
773c5ba7 706 {
707 struct omp_for_data fd;
bc7bff74 708 tree n1, n2;
773c5ba7 709
1a91d914 710 extract_omp_for_data (for_stmt, &fd, NULL);
bc7bff74 711 n1 = fd.loop.n1;
712 n2 = fd.loop.n2;
713
1a91d914 714 if (gimple_omp_for_combined_into_p (for_stmt))
bc7bff74 715 {
716 tree innerc
717 = find_omp_clause (gimple_omp_parallel_clauses (par_stmt),
718 OMP_CLAUSE__LOOPTEMP_);
719 gcc_assert (innerc);
720 n1 = OMP_CLAUSE_DECL (innerc);
721 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
722 OMP_CLAUSE__LOOPTEMP_);
723 gcc_assert (innerc);
724 n2 = OMP_CLAUSE_DECL (innerc);
725 }
773c5ba7 726
f1f41a6c 727 vec_alloc (ws_args, 3 + (fd.chunk_size != 0));
773c5ba7 728
bc7bff74 729 t = fold_convert_loc (loc, long_integer_type_node, n1);
f1f41a6c 730 ws_args->quick_push (t);
773c5ba7 731
bc7bff74 732 t = fold_convert_loc (loc, long_integer_type_node, n2);
f1f41a6c 733 ws_args->quick_push (t);
773c5ba7 734
414c3a2c 735 t = fold_convert_loc (loc, long_integer_type_node, fd.loop.step);
f1f41a6c 736 ws_args->quick_push (t);
414c3a2c 737
738 if (fd.chunk_size)
739 {
740 t = fold_convert_loc (loc, long_integer_type_node, fd.chunk_size);
f1f41a6c 741 ws_args->quick_push (t);
414c3a2c 742 }
773c5ba7 743
744 return ws_args;
745 }
75a70cf9 746 else if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
773c5ba7 747 {
ac6e3339 748 /* Number of sections is equal to the number of edges from the
75a70cf9 749 GIMPLE_OMP_SECTIONS_SWITCH statement, except for the one to
750 the exit of the sections region. */
751 basic_block bb = single_succ (gimple_bb (ws_stmt));
ac6e3339 752 t = build_int_cst (unsigned_type_node, EDGE_COUNT (bb->succs) - 1);
f1f41a6c 753 vec_alloc (ws_args, 1);
754 ws_args->quick_push (t);
414c3a2c 755 return ws_args;
773c5ba7 756 }
757
758 gcc_unreachable ();
759}
760
761
762/* Discover whether REGION is a combined parallel+workshare region. */
763
764static void
765determine_parallel_type (struct omp_region *region)
1e8e9920 766{
773c5ba7 767 basic_block par_entry_bb, par_exit_bb;
768 basic_block ws_entry_bb, ws_exit_bb;
769
03ed154b 770 if (region == NULL || region->inner == NULL
ac6e3339 771 || region->exit == NULL || region->inner->exit == NULL
772 || region->inner->cont == NULL)
773c5ba7 773 return;
774
775 /* We only support parallel+for and parallel+sections. */
75a70cf9 776 if (region->type != GIMPLE_OMP_PARALLEL
777 || (region->inner->type != GIMPLE_OMP_FOR
778 && region->inner->type != GIMPLE_OMP_SECTIONS))
773c5ba7 779 return;
780
781 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
782 WS_EXIT_BB -> PAR_EXIT_BB. */
61e47ac8 783 par_entry_bb = region->entry;
784 par_exit_bb = region->exit;
785 ws_entry_bb = region->inner->entry;
786 ws_exit_bb = region->inner->exit;
773c5ba7 787
788 if (single_succ (par_entry_bb) == ws_entry_bb
789 && single_succ (ws_exit_bb) == par_exit_bb
f018d957 790 && workshare_safe_to_combine_p (ws_entry_bb)
75a70cf9 791 && (gimple_omp_parallel_combined_p (last_stmt (par_entry_bb))
de7ef844 792 || (last_and_only_stmt (ws_entry_bb)
793 && last_and_only_stmt (par_exit_bb))))
773c5ba7 794 {
bc7bff74 795 gimple par_stmt = last_stmt (par_entry_bb);
75a70cf9 796 gimple ws_stmt = last_stmt (ws_entry_bb);
61e47ac8 797
75a70cf9 798 if (region->inner->type == GIMPLE_OMP_FOR)
773c5ba7 799 {
800 /* If this is a combined parallel loop, we need to determine
801 whether or not to use the combined library calls. There
802 are two cases where we do not apply the transformation:
803 static loops and any kind of ordered loop. In the first
804 case, we already open code the loop so there is no need
805 to do anything else. In the latter case, the combined
806 parallel loop call would still need extra synchronization
807 to implement ordered semantics, so there would not be any
808 gain in using the combined call. */
75a70cf9 809 tree clauses = gimple_omp_for_clauses (ws_stmt);
773c5ba7 810 tree c = find_omp_clause (clauses, OMP_CLAUSE_SCHEDULE);
811 if (c == NULL
812 || OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_STATIC
813 || find_omp_clause (clauses, OMP_CLAUSE_ORDERED))
814 {
815 region->is_combined_parallel = false;
816 region->inner->is_combined_parallel = false;
817 return;
818 }
819 }
820
821 region->is_combined_parallel = true;
822 region->inner->is_combined_parallel = true;
bc7bff74 823 region->ws_args = get_ws_args_for (par_stmt, ws_stmt);
773c5ba7 824 }
1e8e9920 825}
826
773c5ba7 827
1e8e9920 828/* Return true if EXPR is variable sized. */
829
830static inline bool
1f1872fd 831is_variable_sized (const_tree expr)
1e8e9920 832{
833 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr)));
834}
835
836/* Return true if DECL is a reference type. */
837
838static inline bool
839is_reference (tree decl)
840{
841 return lang_hooks.decls.omp_privatize_by_reference (decl);
842}
843
844/* Lookup variables in the decl or field splay trees. The "maybe" form
845 allows for the variable form to not have been entered, otherwise we
846 assert that the variable must have been entered. */
847
848static inline tree
849lookup_decl (tree var, omp_context *ctx)
850{
06ecf488 851 tree *n = ctx->cb.decl_map->get (var);
e3022db7 852 return *n;
1e8e9920 853}
854
855static inline tree
e8a588af 856maybe_lookup_decl (const_tree var, omp_context *ctx)
1e8e9920 857{
06ecf488 858 tree *n = ctx->cb.decl_map->get (const_cast<tree> (var));
e3022db7 859 return n ? *n : NULL_TREE;
1e8e9920 860}
861
862static inline tree
863lookup_field (tree var, omp_context *ctx)
864{
865 splay_tree_node n;
866 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
867 return (tree) n->value;
868}
869
fd6481cf 870static inline tree
871lookup_sfield (tree var, omp_context *ctx)
872{
873 splay_tree_node n;
874 n = splay_tree_lookup (ctx->sfield_map
875 ? ctx->sfield_map : ctx->field_map,
876 (splay_tree_key) var);
877 return (tree) n->value;
878}
879
1e8e9920 880static inline tree
881maybe_lookup_field (tree var, omp_context *ctx)
882{
883 splay_tree_node n;
884 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
885 return n ? (tree) n->value : NULL_TREE;
886}
887
e8a588af 888/* Return true if DECL should be copied by pointer. SHARED_CTX is
889 the parallel context if DECL is to be shared. */
1e8e9920 890
891static bool
fd6481cf 892use_pointer_for_field (tree decl, omp_context *shared_ctx)
1e8e9920 893{
894 if (AGGREGATE_TYPE_P (TREE_TYPE (decl)))
895 return true;
896
554f2707 897 /* We can only use copy-in/copy-out semantics for shared variables
1e8e9920 898 when we know the value is not accessible from an outer scope. */
e8a588af 899 if (shared_ctx)
1e8e9920 900 {
901 /* ??? Trivially accessible from anywhere. But why would we even
902 be passing an address in this case? Should we simply assert
903 this to be false, or should we have a cleanup pass that removes
904 these from the list of mappings? */
905 if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
906 return true;
907
908 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
909 without analyzing the expression whether or not its location
910 is accessible to anyone else. In the case of nested parallel
911 regions it certainly may be. */
df2c34fc 912 if (TREE_CODE (decl) != RESULT_DECL && DECL_HAS_VALUE_EXPR_P (decl))
1e8e9920 913 return true;
914
915 /* Do not use copy-in/copy-out for variables that have their
916 address taken. */
917 if (TREE_ADDRESSABLE (decl))
918 return true;
e8a588af 919
b8214689 920 /* lower_send_shared_vars only uses copy-in, but not copy-out
921 for these. */
922 if (TREE_READONLY (decl)
923 || ((TREE_CODE (decl) == RESULT_DECL
924 || TREE_CODE (decl) == PARM_DECL)
925 && DECL_BY_REFERENCE (decl)))
926 return false;
927
e8a588af 928 /* Disallow copy-in/out in nested parallel if
929 decl is shared in outer parallel, otherwise
930 each thread could store the shared variable
931 in its own copy-in location, making the
932 variable no longer really shared. */
b8214689 933 if (shared_ctx->is_nested)
e8a588af 934 {
935 omp_context *up;
936
937 for (up = shared_ctx->outer; up; up = up->outer)
0cb159ec 938 if (is_taskreg_ctx (up) && maybe_lookup_decl (decl, up))
e8a588af 939 break;
940
0cb159ec 941 if (up)
e8a588af 942 {
943 tree c;
944
75a70cf9 945 for (c = gimple_omp_taskreg_clauses (up->stmt);
e8a588af 946 c; c = OMP_CLAUSE_CHAIN (c))
947 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
948 && OMP_CLAUSE_DECL (c) == decl)
949 break;
950
951 if (c)
784ad964 952 goto maybe_mark_addressable_and_ret;
e8a588af 953 }
954 }
fd6481cf 955
b8214689 956 /* For tasks avoid using copy-in/out. As tasks can be
fd6481cf 957 deferred or executed in different thread, when GOMP_task
958 returns, the task hasn't necessarily terminated. */
b8214689 959 if (is_task_ctx (shared_ctx))
fd6481cf 960 {
784ad964 961 tree outer;
962 maybe_mark_addressable_and_ret:
963 outer = maybe_lookup_decl_in_outer_ctx (decl, shared_ctx);
fd6481cf 964 if (is_gimple_reg (outer))
965 {
966 /* Taking address of OUTER in lower_send_shared_vars
967 might need regimplification of everything that uses the
968 variable. */
969 if (!task_shared_vars)
970 task_shared_vars = BITMAP_ALLOC (NULL);
971 bitmap_set_bit (task_shared_vars, DECL_UID (outer));
972 TREE_ADDRESSABLE (outer) = 1;
973 }
974 return true;
975 }
1e8e9920 976 }
977
978 return false;
979}
980
79acaae1 981/* Construct a new automatic decl similar to VAR. */
982
983static tree
984omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx)
985{
986 tree copy = copy_var_decl (var, name, type);
987
988 DECL_CONTEXT (copy) = current_function_decl;
1767a056 989 DECL_CHAIN (copy) = ctx->block_vars;
1e8e9920 990 ctx->block_vars = copy;
991
992 return copy;
993}
994
995static tree
996omp_copy_decl_1 (tree var, omp_context *ctx)
997{
998 return omp_copy_decl_2 (var, DECL_NAME (var), TREE_TYPE (var), ctx);
999}
1000
445d06b6 1001/* Build COMPONENT_REF and set TREE_THIS_VOLATILE and TREE_READONLY on it
1002 as appropriate. */
1003static tree
1004omp_build_component_ref (tree obj, tree field)
1005{
1006 tree ret = build3 (COMPONENT_REF, TREE_TYPE (field), obj, field, NULL);
1007 if (TREE_THIS_VOLATILE (field))
1008 TREE_THIS_VOLATILE (ret) |= 1;
1009 if (TREE_READONLY (field))
1010 TREE_READONLY (ret) |= 1;
1011 return ret;
1012}
1013
1e8e9920 1014/* Build tree nodes to access the field for VAR on the receiver side. */
1015
1016static tree
1017build_receiver_ref (tree var, bool by_ref, omp_context *ctx)
1018{
1019 tree x, field = lookup_field (var, ctx);
1020
1021 /* If the receiver record type was remapped in the child function,
1022 remap the field into the new record type. */
1023 x = maybe_lookup_field (field, ctx);
1024 if (x != NULL)
1025 field = x;
1026
182cf5a9 1027 x = build_simple_mem_ref (ctx->receiver_decl);
445d06b6 1028 x = omp_build_component_ref (x, field);
1e8e9920 1029 if (by_ref)
182cf5a9 1030 x = build_simple_mem_ref (x);
1e8e9920 1031
1032 return x;
1033}
1034
1035/* Build tree nodes to access VAR in the scope outer to CTX. In the case
1036 of a parallel, this is a component reference; for workshare constructs
1037 this is some variable. */
1038
1039static tree
1040build_outer_var_ref (tree var, omp_context *ctx)
1041{
1042 tree x;
1043
f49d7bb5 1044 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx)))
1e8e9920 1045 x = var;
1046 else if (is_variable_sized (var))
1047 {
1048 x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
1049 x = build_outer_var_ref (x, ctx);
182cf5a9 1050 x = build_simple_mem_ref (x);
1e8e9920 1051 }
fd6481cf 1052 else if (is_taskreg_ctx (ctx))
1e8e9920 1053 {
e8a588af 1054 bool by_ref = use_pointer_for_field (var, NULL);
1e8e9920 1055 x = build_receiver_ref (var, by_ref, ctx);
1056 }
3d483a94 1057 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
10c55644 1058 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3d483a94 1059 {
1060 /* #pragma omp simd isn't a worksharing construct, and can reference even
1061 private vars in its linear etc. clauses. */
1062 x = NULL_TREE;
1063 if (ctx->outer && is_taskreg_ctx (ctx))
1064 x = lookup_decl (var, ctx->outer);
1065 else if (ctx->outer)
84cb1020 1066 x = maybe_lookup_decl_in_outer_ctx (var, ctx);
3d483a94 1067 if (x == NULL_TREE)
1068 x = var;
1069 }
1e8e9920 1070 else if (ctx->outer)
1071 x = lookup_decl (var, ctx->outer);
9438af57 1072 else if (is_reference (var))
1073 /* This can happen with orphaned constructs. If var is reference, it is
1074 possible it is shared and as such valid. */
1075 x = var;
1e8e9920 1076 else
1077 gcc_unreachable ();
1078
1079 if (is_reference (var))
182cf5a9 1080 x = build_simple_mem_ref (x);
1e8e9920 1081
1082 return x;
1083}
1084
1085/* Build tree nodes to access the field for VAR on the sender side. */
1086
1087static tree
1088build_sender_ref (tree var, omp_context *ctx)
1089{
fd6481cf 1090 tree field = lookup_sfield (var, ctx);
445d06b6 1091 return omp_build_component_ref (ctx->sender_decl, field);
1e8e9920 1092}
1093
1094/* Add a new field for VAR inside the structure CTX->SENDER_DECL. */
1095
1096static void
fd6481cf 1097install_var_field (tree var, bool by_ref, int mask, omp_context *ctx)
1e8e9920 1098{
fd6481cf 1099 tree field, type, sfield = NULL_TREE;
1e8e9920 1100
fd6481cf 1101 gcc_assert ((mask & 1) == 0
1102 || !splay_tree_lookup (ctx->field_map, (splay_tree_key) var));
1103 gcc_assert ((mask & 2) == 0 || !ctx->sfield_map
1104 || !splay_tree_lookup (ctx->sfield_map, (splay_tree_key) var));
1e8e9920 1105
1106 type = TREE_TYPE (var);
bc7bff74 1107 if (mask & 4)
1108 {
1109 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
1110 type = build_pointer_type (build_pointer_type (type));
1111 }
1112 else if (by_ref)
1e8e9920 1113 type = build_pointer_type (type);
fd6481cf 1114 else if ((mask & 3) == 1 && is_reference (var))
1115 type = TREE_TYPE (type);
1e8e9920 1116
e60a6f7b 1117 field = build_decl (DECL_SOURCE_LOCATION (var),
1118 FIELD_DECL, DECL_NAME (var), type);
1e8e9920 1119
1120 /* Remember what variable this field was created for. This does have a
1121 side effect of making dwarf2out ignore this member, so for helpful
1122 debugging we clear it later in delete_omp_context. */
1123 DECL_ABSTRACT_ORIGIN (field) = var;
fd6481cf 1124 if (type == TREE_TYPE (var))
1125 {
1126 DECL_ALIGN (field) = DECL_ALIGN (var);
1127 DECL_USER_ALIGN (field) = DECL_USER_ALIGN (var);
1128 TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (var);
1129 }
1130 else
1131 DECL_ALIGN (field) = TYPE_ALIGN (type);
1e8e9920 1132
fd6481cf 1133 if ((mask & 3) == 3)
1134 {
1135 insert_field_into_struct (ctx->record_type, field);
1136 if (ctx->srecord_type)
1137 {
e60a6f7b 1138 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1139 FIELD_DECL, DECL_NAME (var), type);
fd6481cf 1140 DECL_ABSTRACT_ORIGIN (sfield) = var;
1141 DECL_ALIGN (sfield) = DECL_ALIGN (field);
1142 DECL_USER_ALIGN (sfield) = DECL_USER_ALIGN (field);
1143 TREE_THIS_VOLATILE (sfield) = TREE_THIS_VOLATILE (field);
1144 insert_field_into_struct (ctx->srecord_type, sfield);
1145 }
1146 }
1147 else
1148 {
1149 if (ctx->srecord_type == NULL_TREE)
1150 {
1151 tree t;
1152
1153 ctx->srecord_type = lang_hooks.types.make_type (RECORD_TYPE);
1154 ctx->sfield_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1155 for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
1156 {
e60a6f7b 1157 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1158 FIELD_DECL, DECL_NAME (t), TREE_TYPE (t));
fd6481cf 1159 DECL_ABSTRACT_ORIGIN (sfield) = DECL_ABSTRACT_ORIGIN (t);
1160 insert_field_into_struct (ctx->srecord_type, sfield);
1161 splay_tree_insert (ctx->sfield_map,
1162 (splay_tree_key) DECL_ABSTRACT_ORIGIN (t),
1163 (splay_tree_value) sfield);
1164 }
1165 }
1166 sfield = field;
1167 insert_field_into_struct ((mask & 1) ? ctx->record_type
1168 : ctx->srecord_type, field);
1169 }
1e8e9920 1170
fd6481cf 1171 if (mask & 1)
1172 splay_tree_insert (ctx->field_map, (splay_tree_key) var,
1173 (splay_tree_value) field);
1174 if ((mask & 2) && ctx->sfield_map)
1175 splay_tree_insert (ctx->sfield_map, (splay_tree_key) var,
1176 (splay_tree_value) sfield);
1e8e9920 1177}
1178
1179static tree
1180install_var_local (tree var, omp_context *ctx)
1181{
1182 tree new_var = omp_copy_decl_1 (var, ctx);
1183 insert_decl_map (&ctx->cb, var, new_var);
1184 return new_var;
1185}
1186
1187/* Adjust the replacement for DECL in CTX for the new context. This means
1188 copying the DECL_VALUE_EXPR, and fixing up the type. */
1189
1190static void
1191fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug)
1192{
1193 tree new_decl, size;
1194
1195 new_decl = lookup_decl (decl, ctx);
1196
1197 TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb);
1198
1199 if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug)
1200 && DECL_HAS_VALUE_EXPR_P (decl))
1201 {
1202 tree ve = DECL_VALUE_EXPR (decl);
75a70cf9 1203 walk_tree (&ve, copy_tree_body_r, &ctx->cb, NULL);
1e8e9920 1204 SET_DECL_VALUE_EXPR (new_decl, ve);
1205 DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
1206 }
1207
1208 if (!TREE_CONSTANT (DECL_SIZE (new_decl)))
1209 {
1210 size = remap_decl (DECL_SIZE (decl), &ctx->cb);
1211 if (size == error_mark_node)
1212 size = TYPE_SIZE (TREE_TYPE (new_decl));
1213 DECL_SIZE (new_decl) = size;
1214
1215 size = remap_decl (DECL_SIZE_UNIT (decl), &ctx->cb);
1216 if (size == error_mark_node)
1217 size = TYPE_SIZE_UNIT (TREE_TYPE (new_decl));
1218 DECL_SIZE_UNIT (new_decl) = size;
1219 }
1220}
1221
1222/* The callback for remap_decl. Search all containing contexts for a
1223 mapping of the variable; this avoids having to duplicate the splay
1224 tree ahead of time. We know a mapping doesn't already exist in the
1225 given context. Create new mappings to implement default semantics. */
1226
1227static tree
1228omp_copy_decl (tree var, copy_body_data *cb)
1229{
1230 omp_context *ctx = (omp_context *) cb;
1231 tree new_var;
1232
1e8e9920 1233 if (TREE_CODE (var) == LABEL_DECL)
1234 {
e60a6f7b 1235 new_var = create_artificial_label (DECL_SOURCE_LOCATION (var));
773c5ba7 1236 DECL_CONTEXT (new_var) = current_function_decl;
1e8e9920 1237 insert_decl_map (&ctx->cb, var, new_var);
1238 return new_var;
1239 }
1240
fd6481cf 1241 while (!is_taskreg_ctx (ctx))
1e8e9920 1242 {
1243 ctx = ctx->outer;
1244 if (ctx == NULL)
1245 return var;
1246 new_var = maybe_lookup_decl (var, ctx);
1247 if (new_var)
1248 return new_var;
1249 }
1250
f49d7bb5 1251 if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn)
1252 return var;
1253
1e8e9920 1254 return error_mark_node;
1255}
1256
773c5ba7 1257
773c5ba7 1258/* Debugging dumps for parallel regions. */
1259void dump_omp_region (FILE *, struct omp_region *, int);
1260void debug_omp_region (struct omp_region *);
1261void debug_all_omp_regions (void);
1262
1263/* Dump the parallel region tree rooted at REGION. */
1264
1265void
1266dump_omp_region (FILE *file, struct omp_region *region, int indent)
1267{
61e47ac8 1268 fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index,
75a70cf9 1269 gimple_code_name[region->type]);
773c5ba7 1270
1271 if (region->inner)
1272 dump_omp_region (file, region->inner, indent + 4);
1273
61e47ac8 1274 if (region->cont)
1275 {
75a70cf9 1276 fprintf (file, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent, "",
61e47ac8 1277 region->cont->index);
1278 }
48e1416a 1279
773c5ba7 1280 if (region->exit)
75a70cf9 1281 fprintf (file, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent, "",
61e47ac8 1282 region->exit->index);
773c5ba7 1283 else
61e47ac8 1284 fprintf (file, "%*s[no exit marker]\n", indent, "");
773c5ba7 1285
1286 if (region->next)
61e47ac8 1287 dump_omp_region (file, region->next, indent);
773c5ba7 1288}
1289
4b987fac 1290DEBUG_FUNCTION void
773c5ba7 1291debug_omp_region (struct omp_region *region)
1292{
1293 dump_omp_region (stderr, region, 0);
1294}
1295
4b987fac 1296DEBUG_FUNCTION void
773c5ba7 1297debug_all_omp_regions (void)
1298{
1299 dump_omp_region (stderr, root_omp_region, 0);
1300}
1301
1302
1303/* Create a new parallel region starting at STMT inside region PARENT. */
1304
7740abd8 1305static struct omp_region *
75a70cf9 1306new_omp_region (basic_block bb, enum gimple_code type,
1307 struct omp_region *parent)
773c5ba7 1308{
4077bf7a 1309 struct omp_region *region = XCNEW (struct omp_region);
773c5ba7 1310
1311 region->outer = parent;
61e47ac8 1312 region->entry = bb;
1313 region->type = type;
773c5ba7 1314
1315 if (parent)
1316 {
1317 /* This is a nested region. Add it to the list of inner
1318 regions in PARENT. */
1319 region->next = parent->inner;
1320 parent->inner = region;
1321 }
61e47ac8 1322 else
773c5ba7 1323 {
1324 /* This is a toplevel region. Add it to the list of toplevel
1325 regions in ROOT_OMP_REGION. */
1326 region->next = root_omp_region;
1327 root_omp_region = region;
1328 }
61e47ac8 1329
1330 return region;
1331}
1332
1333/* Release the memory associated with the region tree rooted at REGION. */
1334
1335static void
1336free_omp_region_1 (struct omp_region *region)
1337{
1338 struct omp_region *i, *n;
1339
1340 for (i = region->inner; i ; i = n)
773c5ba7 1341 {
61e47ac8 1342 n = i->next;
1343 free_omp_region_1 (i);
773c5ba7 1344 }
1345
61e47ac8 1346 free (region);
1347}
773c5ba7 1348
61e47ac8 1349/* Release the memory for the entire omp region tree. */
1350
1351void
1352free_omp_regions (void)
1353{
1354 struct omp_region *r, *n;
1355 for (r = root_omp_region; r ; r = n)
1356 {
1357 n = r->next;
1358 free_omp_region_1 (r);
1359 }
1360 root_omp_region = NULL;
773c5ba7 1361}
1362
1363
1e8e9920 1364/* Create a new context, with OUTER_CTX being the surrounding context. */
1365
1366static omp_context *
75a70cf9 1367new_omp_context (gimple stmt, omp_context *outer_ctx)
1e8e9920 1368{
1369 omp_context *ctx = XCNEW (omp_context);
1370
1371 splay_tree_insert (all_contexts, (splay_tree_key) stmt,
1372 (splay_tree_value) ctx);
1373 ctx->stmt = stmt;
1374
1375 if (outer_ctx)
1376 {
1377 ctx->outer = outer_ctx;
1378 ctx->cb = outer_ctx->cb;
1379 ctx->cb.block = NULL;
1380 ctx->depth = outer_ctx->depth + 1;
1381 }
1382 else
1383 {
1384 ctx->cb.src_fn = current_function_decl;
1385 ctx->cb.dst_fn = current_function_decl;
415d1b9a 1386 ctx->cb.src_node = cgraph_node::get (current_function_decl);
53f79206 1387 gcc_checking_assert (ctx->cb.src_node);
1e8e9920 1388 ctx->cb.dst_node = ctx->cb.src_node;
1389 ctx->cb.src_cfun = cfun;
1390 ctx->cb.copy_decl = omp_copy_decl;
e38def9c 1391 ctx->cb.eh_lp_nr = 0;
1e8e9920 1392 ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
1393 ctx->depth = 1;
1394 }
1395
06ecf488 1396 ctx->cb.decl_map = new hash_map<tree, tree>;
1e8e9920 1397
1398 return ctx;
1399}
1400
75a70cf9 1401static gimple_seq maybe_catch_exception (gimple_seq);
f6430caa 1402
1403/* Finalize task copyfn. */
1404
1405static void
1a91d914 1406finalize_task_copyfn (gomp_task *task_stmt)
f6430caa 1407{
1408 struct function *child_cfun;
9078126c 1409 tree child_fn;
e3a19533 1410 gimple_seq seq = NULL, new_seq;
1a91d914 1411 gbind *bind;
f6430caa 1412
75a70cf9 1413 child_fn = gimple_omp_task_copy_fn (task_stmt);
f6430caa 1414 if (child_fn == NULL_TREE)
1415 return;
1416
1417 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
82b40354 1418 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
f6430caa 1419
f6430caa 1420 push_cfun (child_cfun);
7e3aae05 1421 bind = gimplify_body (child_fn, false);
75a70cf9 1422 gimple_seq_add_stmt (&seq, bind);
1423 new_seq = maybe_catch_exception (seq);
1424 if (new_seq != seq)
1425 {
1426 bind = gimple_build_bind (NULL, new_seq, NULL);
e3a19533 1427 seq = NULL;
75a70cf9 1428 gimple_seq_add_stmt (&seq, bind);
1429 }
1430 gimple_set_body (child_fn, seq);
f6430caa 1431 pop_cfun ();
f6430caa 1432
82b40354 1433 /* Inform the callgraph about the new function. */
415d1b9a 1434 cgraph_node::add_new_function (child_fn, false);
f6430caa 1435}
1436
1e8e9920 1437/* Destroy a omp_context data structures. Called through the splay tree
1438 value delete callback. */
1439
1440static void
1441delete_omp_context (splay_tree_value value)
1442{
1443 omp_context *ctx = (omp_context *) value;
1444
06ecf488 1445 delete ctx->cb.decl_map;
1e8e9920 1446
1447 if (ctx->field_map)
1448 splay_tree_delete (ctx->field_map);
fd6481cf 1449 if (ctx->sfield_map)
1450 splay_tree_delete (ctx->sfield_map);
1e8e9920 1451
1452 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
1453 it produces corrupt debug information. */
1454 if (ctx->record_type)
1455 {
1456 tree t;
1767a056 1457 for (t = TYPE_FIELDS (ctx->record_type); t ; t = DECL_CHAIN (t))
1e8e9920 1458 DECL_ABSTRACT_ORIGIN (t) = NULL;
1459 }
fd6481cf 1460 if (ctx->srecord_type)
1461 {
1462 tree t;
1767a056 1463 for (t = TYPE_FIELDS (ctx->srecord_type); t ; t = DECL_CHAIN (t))
fd6481cf 1464 DECL_ABSTRACT_ORIGIN (t) = NULL;
1465 }
1e8e9920 1466
f6430caa 1467 if (is_task_ctx (ctx))
1a91d914 1468 finalize_task_copyfn (as_a <gomp_task *> (ctx->stmt));
f6430caa 1469
1e8e9920 1470 XDELETE (ctx);
1471}
1472
1473/* Fix up RECEIVER_DECL with a type that has been remapped to the child
1474 context. */
1475
1476static void
1477fixup_child_record_type (omp_context *ctx)
1478{
1479 tree f, type = ctx->record_type;
1480
1481 /* ??? It isn't sufficient to just call remap_type here, because
1482 variably_modified_type_p doesn't work the way we expect for
1483 record types. Testing each field for whether it needs remapping
1484 and creating a new record by hand works, however. */
1767a056 1485 for (f = TYPE_FIELDS (type); f ; f = DECL_CHAIN (f))
1e8e9920 1486 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
1487 break;
1488 if (f)
1489 {
1490 tree name, new_fields = NULL;
1491
1492 type = lang_hooks.types.make_type (RECORD_TYPE);
1493 name = DECL_NAME (TYPE_NAME (ctx->record_type));
e60a6f7b 1494 name = build_decl (DECL_SOURCE_LOCATION (ctx->receiver_decl),
1495 TYPE_DECL, name, type);
1e8e9920 1496 TYPE_NAME (type) = name;
1497
1767a056 1498 for (f = TYPE_FIELDS (ctx->record_type); f ; f = DECL_CHAIN (f))
1e8e9920 1499 {
1500 tree new_f = copy_node (f);
1501 DECL_CONTEXT (new_f) = type;
1502 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
1767a056 1503 DECL_CHAIN (new_f) = new_fields;
75a70cf9 1504 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &ctx->cb, NULL);
1505 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r,
1506 &ctx->cb, NULL);
1507 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
1508 &ctx->cb, NULL);
1e8e9920 1509 new_fields = new_f;
1510
1511 /* Arrange to be able to look up the receiver field
1512 given the sender field. */
1513 splay_tree_insert (ctx->field_map, (splay_tree_key) f,
1514 (splay_tree_value) new_f);
1515 }
1516 TYPE_FIELDS (type) = nreverse (new_fields);
1517 layout_type (type);
1518 }
1519
5455b100 1520 TREE_TYPE (ctx->receiver_decl)
1521 = build_qualified_type (build_reference_type (type), TYPE_QUAL_RESTRICT);
1e8e9920 1522}
1523
1524/* Instantiate decls as necessary in CTX to satisfy the data sharing
1525 specified by CLAUSES. */
1526
1527static void
1528scan_sharing_clauses (tree clauses, omp_context *ctx)
1529{
1530 tree c, decl;
1531 bool scan_array_reductions = false;
1532
1533 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1534 {
1535 bool by_ref;
1536
55d6e7cd 1537 switch (OMP_CLAUSE_CODE (c))
1e8e9920 1538 {
1539 case OMP_CLAUSE_PRIVATE:
1540 decl = OMP_CLAUSE_DECL (c);
fd6481cf 1541 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
1542 goto do_private;
1543 else if (!is_variable_sized (decl))
1e8e9920 1544 install_var_local (decl, ctx);
1545 break;
1546
1547 case OMP_CLAUSE_SHARED:
5fddcf34 1548 decl = OMP_CLAUSE_DECL (c);
bc7bff74 1549 /* Ignore shared directives in teams construct. */
1550 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
5fddcf34 1551 {
1552 /* Global variables don't need to be copied,
1553 the receiver side will use them directly. */
1554 tree odecl = maybe_lookup_decl_in_outer_ctx (decl, ctx);
1555 if (is_global_var (odecl))
1556 break;
1557 insert_decl_map (&ctx->cb, decl, odecl);
1558 break;
1559 }
fd6481cf 1560 gcc_assert (is_taskreg_ctx (ctx));
e7327393 1561 gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl))
1562 || !is_variable_sized (decl));
f49d7bb5 1563 /* Global variables don't need to be copied,
1564 the receiver side will use them directly. */
1565 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1566 break;
fd6481cf 1567 by_ref = use_pointer_for_field (decl, ctx);
1e8e9920 1568 if (! TREE_READONLY (decl)
1569 || TREE_ADDRESSABLE (decl)
1570 || by_ref
1571 || is_reference (decl))
1572 {
fd6481cf 1573 install_var_field (decl, by_ref, 3, ctx);
1e8e9920 1574 install_var_local (decl, ctx);
1575 break;
1576 }
1577 /* We don't need to copy const scalar vars back. */
55d6e7cd 1578 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
1e8e9920 1579 goto do_private;
1580
1581 case OMP_CLAUSE_LASTPRIVATE:
1582 /* Let the corresponding firstprivate clause create
1583 the variable. */
1584 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1585 break;
1586 /* FALLTHRU */
1587
1588 case OMP_CLAUSE_FIRSTPRIVATE:
1589 case OMP_CLAUSE_REDUCTION:
3d483a94 1590 case OMP_CLAUSE_LINEAR:
1e8e9920 1591 decl = OMP_CLAUSE_DECL (c);
1592 do_private:
1593 if (is_variable_sized (decl))
1e8e9920 1594 {
fd6481cf 1595 if (is_task_ctx (ctx))
1596 install_var_field (decl, false, 1, ctx);
1597 break;
1598 }
1599 else if (is_taskreg_ctx (ctx))
1600 {
1601 bool global
1602 = is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx));
e8a588af 1603 by_ref = use_pointer_for_field (decl, NULL);
fd6481cf 1604
1605 if (is_task_ctx (ctx)
1606 && (global || by_ref || is_reference (decl)))
1607 {
1608 install_var_field (decl, false, 1, ctx);
1609 if (!global)
1610 install_var_field (decl, by_ref, 2, ctx);
1611 }
1612 else if (!global)
1613 install_var_field (decl, by_ref, 3, ctx);
1e8e9920 1614 }
1615 install_var_local (decl, ctx);
1616 break;
1617
bc7bff74 1618 case OMP_CLAUSE__LOOPTEMP_:
1619 gcc_assert (is_parallel_ctx (ctx));
1620 decl = OMP_CLAUSE_DECL (c);
1621 install_var_field (decl, false, 3, ctx);
1622 install_var_local (decl, ctx);
1623 break;
1624
1e8e9920 1625 case OMP_CLAUSE_COPYPRIVATE:
1e8e9920 1626 case OMP_CLAUSE_COPYIN:
1627 decl = OMP_CLAUSE_DECL (c);
e8a588af 1628 by_ref = use_pointer_for_field (decl, NULL);
fd6481cf 1629 install_var_field (decl, by_ref, 3, ctx);
1e8e9920 1630 break;
1631
1632 case OMP_CLAUSE_DEFAULT:
1633 ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
1634 break;
1635
2169f33b 1636 case OMP_CLAUSE_FINAL:
1e8e9920 1637 case OMP_CLAUSE_IF:
1638 case OMP_CLAUSE_NUM_THREADS:
bc7bff74 1639 case OMP_CLAUSE_NUM_TEAMS:
1640 case OMP_CLAUSE_THREAD_LIMIT:
1641 case OMP_CLAUSE_DEVICE:
1e8e9920 1642 case OMP_CLAUSE_SCHEDULE:
bc7bff74 1643 case OMP_CLAUSE_DIST_SCHEDULE:
1644 case OMP_CLAUSE_DEPEND:
40750995 1645 case OMP_CLAUSE__CILK_FOR_COUNT_:
1e8e9920 1646 if (ctx->outer)
75a70cf9 1647 scan_omp_op (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
1e8e9920 1648 break;
1649
bc7bff74 1650 case OMP_CLAUSE_TO:
1651 case OMP_CLAUSE_FROM:
1652 case OMP_CLAUSE_MAP:
1653 if (ctx->outer)
1654 scan_omp_op (&OMP_CLAUSE_SIZE (c), ctx->outer);
1655 decl = OMP_CLAUSE_DECL (c);
1656 /* Global variables with "omp declare target" attribute
1657 don't need to be copied, the receiver side will use them
1658 directly. */
1659 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1660 && DECL_P (decl)
1661 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
b0c5e347 1662 && varpool_node::get_create (decl)->offloadable)
bc7bff74 1663 break;
1664 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1665 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER)
1666 {
1667 /* Ignore OMP_CLAUSE_MAP_POINTER kind for arrays in
1668 #pragma omp target data, there is nothing to map for
1669 those. */
1670 if (gimple_omp_target_kind (ctx->stmt) == GF_OMP_TARGET_KIND_DATA
1671 && !POINTER_TYPE_P (TREE_TYPE (decl)))
1672 break;
1673 }
1674 if (DECL_P (decl))
1675 {
1676 if (DECL_SIZE (decl)
1677 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1678 {
1679 tree decl2 = DECL_VALUE_EXPR (decl);
1680 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1681 decl2 = TREE_OPERAND (decl2, 0);
1682 gcc_assert (DECL_P (decl2));
1683 install_var_field (decl2, true, 3, ctx);
1684 install_var_local (decl2, ctx);
1685 install_var_local (decl, ctx);
1686 }
1687 else
1688 {
1689 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1690 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
1691 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
1692 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1693 install_var_field (decl, true, 7, ctx);
1694 else
1695 install_var_field (decl, true, 3, ctx);
1696 if (gimple_omp_target_kind (ctx->stmt)
1697 == GF_OMP_TARGET_KIND_REGION)
1698 install_var_local (decl, ctx);
1699 }
1700 }
1701 else
1702 {
1703 tree base = get_base_address (decl);
1704 tree nc = OMP_CLAUSE_CHAIN (c);
1705 if (DECL_P (base)
1706 && nc != NULL_TREE
1707 && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
1708 && OMP_CLAUSE_DECL (nc) == base
1709 && OMP_CLAUSE_MAP_KIND (nc) == OMP_CLAUSE_MAP_POINTER
1710 && integer_zerop (OMP_CLAUSE_SIZE (nc)))
1711 {
1712 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c) = 1;
1713 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (nc) = 1;
1714 }
1715 else
1716 {
691447ab 1717 if (ctx->outer)
1718 {
1719 scan_omp_op (&OMP_CLAUSE_DECL (c), ctx->outer);
1720 decl = OMP_CLAUSE_DECL (c);
1721 }
bc7bff74 1722 gcc_assert (!splay_tree_lookup (ctx->field_map,
1723 (splay_tree_key) decl));
1724 tree field
1725 = build_decl (OMP_CLAUSE_LOCATION (c),
1726 FIELD_DECL, NULL_TREE, ptr_type_node);
1727 DECL_ALIGN (field) = TYPE_ALIGN (ptr_type_node);
1728 insert_field_into_struct (ctx->record_type, field);
1729 splay_tree_insert (ctx->field_map, (splay_tree_key) decl,
1730 (splay_tree_value) field);
1731 }
1732 }
1733 break;
1734
1e8e9920 1735 case OMP_CLAUSE_NOWAIT:
1736 case OMP_CLAUSE_ORDERED:
fd6481cf 1737 case OMP_CLAUSE_COLLAPSE:
1738 case OMP_CLAUSE_UNTIED:
2169f33b 1739 case OMP_CLAUSE_MERGEABLE:
bc7bff74 1740 case OMP_CLAUSE_PROC_BIND:
3d483a94 1741 case OMP_CLAUSE_SAFELEN:
1e8e9920 1742 break;
1743
bc7bff74 1744 case OMP_CLAUSE_ALIGNED:
1745 decl = OMP_CLAUSE_DECL (c);
1746 if (is_global_var (decl)
1747 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1748 install_var_local (decl, ctx);
1749 break;
1750
1e8e9920 1751 default:
1752 gcc_unreachable ();
1753 }
1754 }
1755
1756 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1757 {
55d6e7cd 1758 switch (OMP_CLAUSE_CODE (c))
1e8e9920 1759 {
1760 case OMP_CLAUSE_LASTPRIVATE:
1761 /* Let the corresponding firstprivate clause create
1762 the variable. */
75a70cf9 1763 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
fd6481cf 1764 scan_array_reductions = true;
1e8e9920 1765 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1766 break;
1767 /* FALLTHRU */
1768
1769 case OMP_CLAUSE_PRIVATE:
1770 case OMP_CLAUSE_FIRSTPRIVATE:
1771 case OMP_CLAUSE_REDUCTION:
3d483a94 1772 case OMP_CLAUSE_LINEAR:
1e8e9920 1773 decl = OMP_CLAUSE_DECL (c);
1774 if (is_variable_sized (decl))
1775 install_var_local (decl, ctx);
1776 fixup_remapped_decl (decl, ctx,
55d6e7cd 1777 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
1e8e9920 1778 && OMP_CLAUSE_PRIVATE_DEBUG (c));
55d6e7cd 1779 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1e8e9920 1780 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1781 scan_array_reductions = true;
2b536a17 1782 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
1783 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
1784 scan_array_reductions = true;
1e8e9920 1785 break;
1786
1787 case OMP_CLAUSE_SHARED:
bc7bff74 1788 /* Ignore shared directives in teams construct. */
1789 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1790 break;
1e8e9920 1791 decl = OMP_CLAUSE_DECL (c);
f49d7bb5 1792 if (! is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1793 fixup_remapped_decl (decl, ctx, false);
1e8e9920 1794 break;
1795
bc7bff74 1796 case OMP_CLAUSE_MAP:
1797 if (gimple_omp_target_kind (ctx->stmt) == GF_OMP_TARGET_KIND_DATA)
1798 break;
1799 decl = OMP_CLAUSE_DECL (c);
1800 if (DECL_P (decl)
1801 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
b0c5e347 1802 && varpool_node::get_create (decl)->offloadable)
bc7bff74 1803 break;
1804 if (DECL_P (decl))
1805 {
1806 if (OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
1807 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
1808 && !COMPLETE_TYPE_P (TREE_TYPE (decl)))
1809 {
1810 tree new_decl = lookup_decl (decl, ctx);
1811 TREE_TYPE (new_decl)
1812 = remap_type (TREE_TYPE (decl), &ctx->cb);
1813 }
1814 else if (DECL_SIZE (decl)
1815 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1816 {
1817 tree decl2 = DECL_VALUE_EXPR (decl);
1818 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1819 decl2 = TREE_OPERAND (decl2, 0);
1820 gcc_assert (DECL_P (decl2));
1821 fixup_remapped_decl (decl2, ctx, false);
1822 fixup_remapped_decl (decl, ctx, true);
1823 }
1824 else
1825 fixup_remapped_decl (decl, ctx, false);
1826 }
1827 break;
1828
1e8e9920 1829 case OMP_CLAUSE_COPYPRIVATE:
1830 case OMP_CLAUSE_COPYIN:
1831 case OMP_CLAUSE_DEFAULT:
1832 case OMP_CLAUSE_IF:
1833 case OMP_CLAUSE_NUM_THREADS:
bc7bff74 1834 case OMP_CLAUSE_NUM_TEAMS:
1835 case OMP_CLAUSE_THREAD_LIMIT:
1836 case OMP_CLAUSE_DEVICE:
1e8e9920 1837 case OMP_CLAUSE_SCHEDULE:
bc7bff74 1838 case OMP_CLAUSE_DIST_SCHEDULE:
1e8e9920 1839 case OMP_CLAUSE_NOWAIT:
1840 case OMP_CLAUSE_ORDERED:
fd6481cf 1841 case OMP_CLAUSE_COLLAPSE:
1842 case OMP_CLAUSE_UNTIED:
2169f33b 1843 case OMP_CLAUSE_FINAL:
1844 case OMP_CLAUSE_MERGEABLE:
bc7bff74 1845 case OMP_CLAUSE_PROC_BIND:
3d483a94 1846 case OMP_CLAUSE_SAFELEN:
bc7bff74 1847 case OMP_CLAUSE_ALIGNED:
1848 case OMP_CLAUSE_DEPEND:
1849 case OMP_CLAUSE__LOOPTEMP_:
1850 case OMP_CLAUSE_TO:
1851 case OMP_CLAUSE_FROM:
40750995 1852 case OMP_CLAUSE__CILK_FOR_COUNT_:
1e8e9920 1853 break;
1854
1855 default:
1856 gcc_unreachable ();
1857 }
1858 }
1859
1860 if (scan_array_reductions)
1861 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
55d6e7cd 1862 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1e8e9920 1863 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1864 {
ab129075 1865 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
1866 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
1e8e9920 1867 }
fd6481cf 1868 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
75a70cf9 1869 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
ab129075 1870 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
2b536a17 1871 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
1872 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
1873 scan_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
1e8e9920 1874}
1875
40750995 1876/* Create a new name for omp child function. Returns an identifier. If
1877 IS_CILK_FOR is true then the suffix for the child function is
1878 "_cilk_for_fn." */
1e8e9920 1879
1e8e9920 1880static tree
40750995 1881create_omp_child_function_name (bool task_copy, bool is_cilk_for)
1e8e9920 1882{
40750995 1883 if (is_cilk_for)
1884 return clone_function_name (current_function_decl, "_cilk_for_fn");
1885 return clone_function_name (current_function_decl,
1886 task_copy ? "_omp_cpyfn" : "_omp_fn");
1887}
1888
1889/* Returns the type of the induction variable for the child function for
1890 _Cilk_for and the types for _high and _low variables based on TYPE. */
1891
1892static tree
1893cilk_for_check_loop_diff_type (tree type)
1894{
1895 if (TYPE_PRECISION (type) <= TYPE_PRECISION (uint32_type_node))
1896 {
1897 if (TYPE_UNSIGNED (type))
1898 return uint32_type_node;
1899 else
1900 return integer_type_node;
1901 }
1902 else
1903 {
1904 if (TYPE_UNSIGNED (type))
1905 return uint64_type_node;
1906 else
1907 return long_long_integer_type_node;
1908 }
1e8e9920 1909}
1910
1911/* Build a decl for the omp child function. It'll not contain a body
1912 yet, just the bare decl. */
1913
1914static void
fd6481cf 1915create_omp_child_function (omp_context *ctx, bool task_copy)
1e8e9920 1916{
1917 tree decl, type, name, t;
1918
40750995 1919 tree cilk_for_count
1920 = (flag_cilkplus && gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
1921 ? find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
1922 OMP_CLAUSE__CILK_FOR_COUNT_) : NULL_TREE;
1923 tree cilk_var_type = NULL_TREE;
1924
1925 name = create_omp_child_function_name (task_copy,
1926 cilk_for_count != NULL_TREE);
fd6481cf 1927 if (task_copy)
1928 type = build_function_type_list (void_type_node, ptr_type_node,
1929 ptr_type_node, NULL_TREE);
40750995 1930 else if (cilk_for_count)
1931 {
1932 type = TREE_TYPE (OMP_CLAUSE_OPERAND (cilk_for_count, 0));
1933 cilk_var_type = cilk_for_check_loop_diff_type (type);
1934 type = build_function_type_list (void_type_node, ptr_type_node,
1935 cilk_var_type, cilk_var_type, NULL_TREE);
1936 }
fd6481cf 1937 else
1938 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
1e8e9920 1939
40750995 1940 decl = build_decl (gimple_location (ctx->stmt), FUNCTION_DECL, name, type);
1e8e9920 1941
fd6481cf 1942 if (!task_copy)
1943 ctx->cb.dst_fn = decl;
1944 else
75a70cf9 1945 gimple_omp_task_set_copy_fn (ctx->stmt, decl);
1e8e9920 1946
1947 TREE_STATIC (decl) = 1;
1948 TREE_USED (decl) = 1;
1949 DECL_ARTIFICIAL (decl) = 1;
1950 DECL_IGNORED_P (decl) = 0;
1951 TREE_PUBLIC (decl) = 0;
1952 DECL_UNINLINABLE (decl) = 1;
1953 DECL_EXTERNAL (decl) = 0;
1954 DECL_CONTEXT (decl) = NULL_TREE;
773c5ba7 1955 DECL_INITIAL (decl) = make_node (BLOCK);
b0c5e347 1956 if (cgraph_node::get (current_function_decl)->offloadable)
1957 cgraph_node::get_create (decl)->offloadable = 1;
bc7bff74 1958 else
1959 {
1960 omp_context *octx;
1961 for (octx = ctx; octx; octx = octx->outer)
b0c5e347 1962 if (is_targetreg_ctx (octx))
bc7bff74 1963 {
b0c5e347 1964 cgraph_node::get_create (decl)->offloadable = 1;
7114ebdd 1965#ifdef ENABLE_OFFLOADING
b0c5e347 1966 g->have_offload = true;
7114ebdd 1967#endif
bc7bff74 1968 break;
1969 }
1970 }
1e8e9920 1971
e60a6f7b 1972 t = build_decl (DECL_SOURCE_LOCATION (decl),
1973 RESULT_DECL, NULL_TREE, void_type_node);
1e8e9920 1974 DECL_ARTIFICIAL (t) = 1;
1975 DECL_IGNORED_P (t) = 1;
8e5b4ed6 1976 DECL_CONTEXT (t) = decl;
1e8e9920 1977 DECL_RESULT (decl) = t;
1978
40750995 1979 /* _Cilk_for's child function requires two extra parameters called
1980 __low and __high that are set the by Cilk runtime when it calls this
1981 function. */
1982 if (cilk_for_count)
1983 {
1984 t = build_decl (DECL_SOURCE_LOCATION (decl),
1985 PARM_DECL, get_identifier ("__high"), cilk_var_type);
1986 DECL_ARTIFICIAL (t) = 1;
1987 DECL_NAMELESS (t) = 1;
1988 DECL_ARG_TYPE (t) = ptr_type_node;
1989 DECL_CONTEXT (t) = current_function_decl;
1990 TREE_USED (t) = 1;
1991 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
1992 DECL_ARGUMENTS (decl) = t;
1993
1994 t = build_decl (DECL_SOURCE_LOCATION (decl),
1995 PARM_DECL, get_identifier ("__low"), cilk_var_type);
1996 DECL_ARTIFICIAL (t) = 1;
1997 DECL_NAMELESS (t) = 1;
1998 DECL_ARG_TYPE (t) = ptr_type_node;
1999 DECL_CONTEXT (t) = current_function_decl;
2000 TREE_USED (t) = 1;
2001 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2002 DECL_ARGUMENTS (decl) = t;
2003 }
2004
2005 tree data_name = get_identifier (".omp_data_i");
2006 t = build_decl (DECL_SOURCE_LOCATION (decl), PARM_DECL, data_name,
2007 ptr_type_node);
1e8e9920 2008 DECL_ARTIFICIAL (t) = 1;
84bfaaeb 2009 DECL_NAMELESS (t) = 1;
1e8e9920 2010 DECL_ARG_TYPE (t) = ptr_type_node;
773c5ba7 2011 DECL_CONTEXT (t) = current_function_decl;
1e8e9920 2012 TREE_USED (t) = 1;
40750995 2013 if (cilk_for_count)
2014 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
1e8e9920 2015 DECL_ARGUMENTS (decl) = t;
fd6481cf 2016 if (!task_copy)
2017 ctx->receiver_decl = t;
2018 else
2019 {
e60a6f7b 2020 t = build_decl (DECL_SOURCE_LOCATION (decl),
2021 PARM_DECL, get_identifier (".omp_data_o"),
fd6481cf 2022 ptr_type_node);
2023 DECL_ARTIFICIAL (t) = 1;
84bfaaeb 2024 DECL_NAMELESS (t) = 1;
fd6481cf 2025 DECL_ARG_TYPE (t) = ptr_type_node;
2026 DECL_CONTEXT (t) = current_function_decl;
2027 TREE_USED (t) = 1;
86f2ad37 2028 TREE_ADDRESSABLE (t) = 1;
1767a056 2029 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
fd6481cf 2030 DECL_ARGUMENTS (decl) = t;
2031 }
1e8e9920 2032
48e1416a 2033 /* Allocate memory for the function structure. The call to
773c5ba7 2034 allocate_struct_function clobbers CFUN, so we need to restore
1e8e9920 2035 it afterward. */
87d4aa85 2036 push_struct_function (decl);
75a70cf9 2037 cfun->function_end_locus = gimple_location (ctx->stmt);
87d4aa85 2038 pop_cfun ();
1e8e9920 2039}
2040
bc7bff74 2041/* Callback for walk_gimple_seq. Check if combined parallel
2042 contains gimple_omp_for_combined_into_p OMP_FOR. */
2043
2044static tree
2045find_combined_for (gimple_stmt_iterator *gsi_p,
2046 bool *handled_ops_p,
2047 struct walk_stmt_info *wi)
2048{
2049 gimple stmt = gsi_stmt (*gsi_p);
2050
2051 *handled_ops_p = true;
2052 switch (gimple_code (stmt))
2053 {
2054 WALK_SUBSTMTS;
2055
2056 case GIMPLE_OMP_FOR:
2057 if (gimple_omp_for_combined_into_p (stmt)
2058 && gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR)
2059 {
2060 wi->info = stmt;
2061 return integer_zero_node;
2062 }
2063 break;
2064 default:
2065 break;
2066 }
2067 return NULL;
2068}
2069
1e8e9920 2070/* Scan an OpenMP parallel directive. */
2071
2072static void
75a70cf9 2073scan_omp_parallel (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
1e8e9920 2074{
2075 omp_context *ctx;
2076 tree name;
1a91d914 2077 gomp_parallel *stmt = as_a <gomp_parallel *> (gsi_stmt (*gsi));
1e8e9920 2078
2079 /* Ignore parallel directives with empty bodies, unless there
2080 are copyin clauses. */
2081 if (optimize > 0
75a70cf9 2082 && empty_body_p (gimple_omp_body (stmt))
2083 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
2084 OMP_CLAUSE_COPYIN) == NULL)
1e8e9920 2085 {
75a70cf9 2086 gsi_replace (gsi, gimple_build_nop (), false);
1e8e9920 2087 return;
2088 }
2089
bc7bff74 2090 if (gimple_omp_parallel_combined_p (stmt))
2091 {
bc7bff74 2092 struct walk_stmt_info wi;
2093
2094 memset (&wi, 0, sizeof (wi));
2095 wi.val_only = true;
2096 walk_gimple_seq (gimple_omp_body (stmt),
2097 find_combined_for, NULL, &wi);
1a91d914 2098 if (wi.info)
bc7bff74 2099 {
1a91d914 2100 gomp_for *for_stmt = as_a <gomp_for *> ((gimple) wi.info);
bc7bff74 2101 struct omp_for_data fd;
2102 extract_omp_for_data (for_stmt, &fd, NULL);
2103 /* We need two temporaries with fd.loop.v type (istart/iend)
2104 and then (fd.collapse - 1) temporaries with the same
2105 type for count2 ... countN-1 vars if not constant. */
2106 size_t count = 2, i;
2107 tree type = fd.iter_type;
2108 if (fd.collapse > 1
2109 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
2110 count += fd.collapse - 1;
2111 for (i = 0; i < count; i++)
2112 {
2113 tree temp = create_tmp_var (type, NULL);
2114 tree c = build_omp_clause (UNKNOWN_LOCATION,
2115 OMP_CLAUSE__LOOPTEMP_);
691447ab 2116 insert_decl_map (&outer_ctx->cb, temp, temp);
bc7bff74 2117 OMP_CLAUSE_DECL (c) = temp;
2118 OMP_CLAUSE_CHAIN (c) = gimple_omp_parallel_clauses (stmt);
2119 gimple_omp_parallel_set_clauses (stmt, c);
2120 }
2121 }
2122 }
2123
75a70cf9 2124 ctx = new_omp_context (stmt, outer_ctx);
37eaded9 2125 taskreg_contexts.safe_push (ctx);
fd6481cf 2126 if (taskreg_nesting_level > 1)
773c5ba7 2127 ctx->is_nested = true;
1e8e9920 2128 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1e8e9920 2129 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2130 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
1e8e9920 2131 name = create_tmp_var_name (".omp_data_s");
e60a6f7b 2132 name = build_decl (gimple_location (stmt),
2133 TYPE_DECL, name, ctx->record_type);
84bfaaeb 2134 DECL_ARTIFICIAL (name) = 1;
2135 DECL_NAMELESS (name) = 1;
1e8e9920 2136 TYPE_NAME (ctx->record_type) = name;
fd6481cf 2137 create_omp_child_function (ctx, false);
75a70cf9 2138 gimple_omp_parallel_set_child_fn (stmt, ctx->cb.dst_fn);
1e8e9920 2139
75a70cf9 2140 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt), ctx);
ab129075 2141 scan_omp (gimple_omp_body_ptr (stmt), ctx);
1e8e9920 2142
2143 if (TYPE_FIELDS (ctx->record_type) == NULL)
2144 ctx->record_type = ctx->receiver_decl = NULL;
1e8e9920 2145}
2146
fd6481cf 2147/* Scan an OpenMP task directive. */
2148
2149static void
75a70cf9 2150scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
fd6481cf 2151{
2152 omp_context *ctx;
75a70cf9 2153 tree name, t;
1a91d914 2154 gomp_task *stmt = as_a <gomp_task *> (gsi_stmt (*gsi));
fd6481cf 2155
2156 /* Ignore task directives with empty bodies. */
2157 if (optimize > 0
75a70cf9 2158 && empty_body_p (gimple_omp_body (stmt)))
fd6481cf 2159 {
75a70cf9 2160 gsi_replace (gsi, gimple_build_nop (), false);
fd6481cf 2161 return;
2162 }
2163
75a70cf9 2164 ctx = new_omp_context (stmt, outer_ctx);
37eaded9 2165 taskreg_contexts.safe_push (ctx);
fd6481cf 2166 if (taskreg_nesting_level > 1)
2167 ctx->is_nested = true;
2168 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2169 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2170 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2171 name = create_tmp_var_name (".omp_data_s");
e60a6f7b 2172 name = build_decl (gimple_location (stmt),
2173 TYPE_DECL, name, ctx->record_type);
84bfaaeb 2174 DECL_ARTIFICIAL (name) = 1;
2175 DECL_NAMELESS (name) = 1;
fd6481cf 2176 TYPE_NAME (ctx->record_type) = name;
2177 create_omp_child_function (ctx, false);
75a70cf9 2178 gimple_omp_task_set_child_fn (stmt, ctx->cb.dst_fn);
fd6481cf 2179
75a70cf9 2180 scan_sharing_clauses (gimple_omp_task_clauses (stmt), ctx);
fd6481cf 2181
2182 if (ctx->srecord_type)
2183 {
2184 name = create_tmp_var_name (".omp_data_a");
e60a6f7b 2185 name = build_decl (gimple_location (stmt),
2186 TYPE_DECL, name, ctx->srecord_type);
84bfaaeb 2187 DECL_ARTIFICIAL (name) = 1;
2188 DECL_NAMELESS (name) = 1;
fd6481cf 2189 TYPE_NAME (ctx->srecord_type) = name;
2190 create_omp_child_function (ctx, true);
2191 }
2192
ab129075 2193 scan_omp (gimple_omp_body_ptr (stmt), ctx);
fd6481cf 2194
2195 if (TYPE_FIELDS (ctx->record_type) == NULL)
2196 {
2197 ctx->record_type = ctx->receiver_decl = NULL;
75a70cf9 2198 t = build_int_cst (long_integer_type_node, 0);
2199 gimple_omp_task_set_arg_size (stmt, t);
2200 t = build_int_cst (long_integer_type_node, 1);
2201 gimple_omp_task_set_arg_align (stmt, t);
fd6481cf 2202 }
37eaded9 2203}
2204
2205
2206/* If any decls have been made addressable during scan_omp,
2207 adjust their fields if needed, and layout record types
2208 of parallel/task constructs. */
2209
2210static void
2211finish_taskreg_scan (omp_context *ctx)
2212{
2213 if (ctx->record_type == NULL_TREE)
2214 return;
2215
2216 /* If any task_shared_vars were needed, verify all
2217 OMP_CLAUSE_SHARED clauses on GIMPLE_OMP_{PARALLEL,TASK}
2218 statements if use_pointer_for_field hasn't changed
2219 because of that. If it did, update field types now. */
2220 if (task_shared_vars)
2221 {
2222 tree c;
2223
2224 for (c = gimple_omp_taskreg_clauses (ctx->stmt);
2225 c; c = OMP_CLAUSE_CHAIN (c))
2226 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED)
2227 {
2228 tree decl = OMP_CLAUSE_DECL (c);
2229
2230 /* Global variables don't need to be copied,
2231 the receiver side will use them directly. */
2232 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
2233 continue;
2234 if (!bitmap_bit_p (task_shared_vars, DECL_UID (decl))
2235 || !use_pointer_for_field (decl, ctx))
2236 continue;
2237 tree field = lookup_field (decl, ctx);
2238 if (TREE_CODE (TREE_TYPE (field)) == POINTER_TYPE
2239 && TREE_TYPE (TREE_TYPE (field)) == TREE_TYPE (decl))
2240 continue;
2241 TREE_TYPE (field) = build_pointer_type (TREE_TYPE (decl));
2242 TREE_THIS_VOLATILE (field) = 0;
2243 DECL_USER_ALIGN (field) = 0;
2244 DECL_ALIGN (field) = TYPE_ALIGN (TREE_TYPE (field));
2245 if (TYPE_ALIGN (ctx->record_type) < DECL_ALIGN (field))
2246 TYPE_ALIGN (ctx->record_type) = DECL_ALIGN (field);
2247 if (ctx->srecord_type)
2248 {
2249 tree sfield = lookup_sfield (decl, ctx);
2250 TREE_TYPE (sfield) = TREE_TYPE (field);
2251 TREE_THIS_VOLATILE (sfield) = 0;
2252 DECL_USER_ALIGN (sfield) = 0;
2253 DECL_ALIGN (sfield) = DECL_ALIGN (field);
2254 if (TYPE_ALIGN (ctx->srecord_type) < DECL_ALIGN (sfield))
2255 TYPE_ALIGN (ctx->srecord_type) = DECL_ALIGN (sfield);
2256 }
2257 }
2258 }
2259
2260 if (gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2261 {
2262 layout_type (ctx->record_type);
2263 fixup_child_record_type (ctx);
2264 }
fd6481cf 2265 else
2266 {
37eaded9 2267 location_t loc = gimple_location (ctx->stmt);
fd6481cf 2268 tree *p, vla_fields = NULL_TREE, *q = &vla_fields;
2269 /* Move VLA fields to the end. */
2270 p = &TYPE_FIELDS (ctx->record_type);
2271 while (*p)
2272 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p))
2273 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p))))
2274 {
2275 *q = *p;
2276 *p = TREE_CHAIN (*p);
2277 TREE_CHAIN (*q) = NULL_TREE;
2278 q = &TREE_CHAIN (*q);
2279 }
2280 else
1767a056 2281 p = &DECL_CHAIN (*p);
fd6481cf 2282 *p = vla_fields;
2283 layout_type (ctx->record_type);
2284 fixup_child_record_type (ctx);
2285 if (ctx->srecord_type)
2286 layout_type (ctx->srecord_type);
37eaded9 2287 tree t = fold_convert_loc (loc, long_integer_type_node,
2288 TYPE_SIZE_UNIT (ctx->record_type));
2289 gimple_omp_task_set_arg_size (ctx->stmt, t);
75a70cf9 2290 t = build_int_cst (long_integer_type_node,
fd6481cf 2291 TYPE_ALIGN_UNIT (ctx->record_type));
37eaded9 2292 gimple_omp_task_set_arg_align (ctx->stmt, t);
fd6481cf 2293 }
2294}
2295
1e8e9920 2296
773c5ba7 2297/* Scan an OpenMP loop directive. */
1e8e9920 2298
2299static void
1a91d914 2300scan_omp_for (gomp_for *stmt, omp_context *outer_ctx)
1e8e9920 2301{
773c5ba7 2302 omp_context *ctx;
75a70cf9 2303 size_t i;
1e8e9920 2304
773c5ba7 2305 ctx = new_omp_context (stmt, outer_ctx);
1e8e9920 2306
75a70cf9 2307 scan_sharing_clauses (gimple_omp_for_clauses (stmt), ctx);
1e8e9920 2308
ab129075 2309 scan_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
75a70cf9 2310 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
fd6481cf 2311 {
75a70cf9 2312 scan_omp_op (gimple_omp_for_index_ptr (stmt, i), ctx);
2313 scan_omp_op (gimple_omp_for_initial_ptr (stmt, i), ctx);
2314 scan_omp_op (gimple_omp_for_final_ptr (stmt, i), ctx);
2315 scan_omp_op (gimple_omp_for_incr_ptr (stmt, i), ctx);
fd6481cf 2316 }
ab129075 2317 scan_omp (gimple_omp_body_ptr (stmt), ctx);
1e8e9920 2318}
2319
2320/* Scan an OpenMP sections directive. */
2321
2322static void
1a91d914 2323scan_omp_sections (gomp_sections *stmt, omp_context *outer_ctx)
1e8e9920 2324{
1e8e9920 2325 omp_context *ctx;
2326
2327 ctx = new_omp_context (stmt, outer_ctx);
75a70cf9 2328 scan_sharing_clauses (gimple_omp_sections_clauses (stmt), ctx);
ab129075 2329 scan_omp (gimple_omp_body_ptr (stmt), ctx);
1e8e9920 2330}
2331
2332/* Scan an OpenMP single directive. */
2333
2334static void
1a91d914 2335scan_omp_single (gomp_single *stmt, omp_context *outer_ctx)
1e8e9920 2336{
1e8e9920 2337 omp_context *ctx;
2338 tree name;
2339
2340 ctx = new_omp_context (stmt, outer_ctx);
2341 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2342 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2343 name = create_tmp_var_name (".omp_copy_s");
e60a6f7b 2344 name = build_decl (gimple_location (stmt),
2345 TYPE_DECL, name, ctx->record_type);
1e8e9920 2346 TYPE_NAME (ctx->record_type) = name;
2347
75a70cf9 2348 scan_sharing_clauses (gimple_omp_single_clauses (stmt), ctx);
ab129075 2349 scan_omp (gimple_omp_body_ptr (stmt), ctx);
1e8e9920 2350
2351 if (TYPE_FIELDS (ctx->record_type) == NULL)
2352 ctx->record_type = NULL;
2353 else
2354 layout_type (ctx->record_type);
2355}
2356
bc7bff74 2357/* Scan an OpenMP target{, data, update} directive. */
2358
2359static void
1a91d914 2360scan_omp_target (gomp_target *stmt, omp_context *outer_ctx)
bc7bff74 2361{
2362 omp_context *ctx;
2363 tree name;
2364 int kind = gimple_omp_target_kind (stmt);
2365
2366 ctx = new_omp_context (stmt, outer_ctx);
2367 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2368 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2369 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2370 name = create_tmp_var_name (".omp_data_t");
2371 name = build_decl (gimple_location (stmt),
2372 TYPE_DECL, name, ctx->record_type);
2373 DECL_ARTIFICIAL (name) = 1;
2374 DECL_NAMELESS (name) = 1;
2375 TYPE_NAME (ctx->record_type) = name;
2376 if (kind == GF_OMP_TARGET_KIND_REGION)
2377 {
2378 create_omp_child_function (ctx, false);
2379 gimple_omp_target_set_child_fn (stmt, ctx->cb.dst_fn);
2380 }
2381
2382 scan_sharing_clauses (gimple_omp_target_clauses (stmt), ctx);
2383 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2384
2385 if (TYPE_FIELDS (ctx->record_type) == NULL)
2386 ctx->record_type = ctx->receiver_decl = NULL;
2387 else
2388 {
2389 TYPE_FIELDS (ctx->record_type)
2390 = nreverse (TYPE_FIELDS (ctx->record_type));
2391#ifdef ENABLE_CHECKING
2392 tree field;
2393 unsigned int align = DECL_ALIGN (TYPE_FIELDS (ctx->record_type));
2394 for (field = TYPE_FIELDS (ctx->record_type);
2395 field;
2396 field = DECL_CHAIN (field))
2397 gcc_assert (DECL_ALIGN (field) == align);
2398#endif
2399 layout_type (ctx->record_type);
2400 if (kind == GF_OMP_TARGET_KIND_REGION)
2401 fixup_child_record_type (ctx);
2402 }
2403}
2404
2405/* Scan an OpenMP teams directive. */
2406
2407static void
1a91d914 2408scan_omp_teams (gomp_teams *stmt, omp_context *outer_ctx)
bc7bff74 2409{
2410 omp_context *ctx = new_omp_context (stmt, outer_ctx);
2411 scan_sharing_clauses (gimple_omp_teams_clauses (stmt), ctx);
2412 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2413}
1e8e9920 2414
c1d127dd 2415/* Check OpenMP nesting restrictions. */
ab129075 2416static bool
2417check_omp_nesting_restrictions (gimple stmt, omp_context *ctx)
c1d127dd 2418{
3d483a94 2419 if (ctx != NULL)
2420 {
2421 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
10c55644 2422 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3d483a94 2423 {
2424 error_at (gimple_location (stmt),
2425 "OpenMP constructs may not be nested inside simd region");
2426 return false;
2427 }
bc7bff74 2428 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
2429 {
2430 if ((gimple_code (stmt) != GIMPLE_OMP_FOR
2431 || (gimple_omp_for_kind (stmt)
2432 != GF_OMP_FOR_KIND_DISTRIBUTE))
2433 && gimple_code (stmt) != GIMPLE_OMP_PARALLEL)
2434 {
2435 error_at (gimple_location (stmt),
2436 "only distribute or parallel constructs are allowed to "
2437 "be closely nested inside teams construct");
2438 return false;
2439 }
2440 }
3d483a94 2441 }
75a70cf9 2442 switch (gimple_code (stmt))
c1d127dd 2443 {
75a70cf9 2444 case GIMPLE_OMP_FOR:
10c55644 2445 if (gimple_omp_for_kind (stmt) & GF_OMP_FOR_SIMD)
3d483a94 2446 return true;
bc7bff74 2447 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
2448 {
2449 if (ctx != NULL && gimple_code (ctx->stmt) != GIMPLE_OMP_TEAMS)
2450 {
2451 error_at (gimple_location (stmt),
2452 "distribute construct must be closely nested inside "
2453 "teams construct");
2454 return false;
2455 }
2456 return true;
2457 }
2458 /* FALLTHRU */
2459 case GIMPLE_CALL:
2460 if (is_gimple_call (stmt)
2461 && (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2462 == BUILT_IN_GOMP_CANCEL
2463 || DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2464 == BUILT_IN_GOMP_CANCELLATION_POINT))
2465 {
2466 const char *bad = NULL;
2467 const char *kind = NULL;
2468 if (ctx == NULL)
2469 {
2470 error_at (gimple_location (stmt), "orphaned %qs construct",
2471 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2472 == BUILT_IN_GOMP_CANCEL
2473 ? "#pragma omp cancel"
2474 : "#pragma omp cancellation point");
2475 return false;
2476 }
6b409616 2477 switch (tree_fits_shwi_p (gimple_call_arg (stmt, 0))
2478 ? tree_to_shwi (gimple_call_arg (stmt, 0))
bc7bff74 2479 : 0)
2480 {
2481 case 1:
2482 if (gimple_code (ctx->stmt) != GIMPLE_OMP_PARALLEL)
2483 bad = "#pragma omp parallel";
2484 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2485 == BUILT_IN_GOMP_CANCEL
2486 && !integer_zerop (gimple_call_arg (stmt, 1)))
2487 ctx->cancellable = true;
2488 kind = "parallel";
2489 break;
2490 case 2:
2491 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
2492 || gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR)
2493 bad = "#pragma omp for";
2494 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2495 == BUILT_IN_GOMP_CANCEL
2496 && !integer_zerop (gimple_call_arg (stmt, 1)))
2497 {
2498 ctx->cancellable = true;
2499 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2500 OMP_CLAUSE_NOWAIT))
2501 warning_at (gimple_location (stmt), 0,
2502 "%<#pragma omp cancel for%> inside "
2503 "%<nowait%> for construct");
2504 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2505 OMP_CLAUSE_ORDERED))
2506 warning_at (gimple_location (stmt), 0,
2507 "%<#pragma omp cancel for%> inside "
2508 "%<ordered%> for construct");
2509 }
2510 kind = "for";
2511 break;
2512 case 4:
2513 if (gimple_code (ctx->stmt) != GIMPLE_OMP_SECTIONS
2514 && gimple_code (ctx->stmt) != GIMPLE_OMP_SECTION)
2515 bad = "#pragma omp sections";
2516 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2517 == BUILT_IN_GOMP_CANCEL
2518 && !integer_zerop (gimple_call_arg (stmt, 1)))
2519 {
2520 if (gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS)
2521 {
2522 ctx->cancellable = true;
2523 if (find_omp_clause (gimple_omp_sections_clauses
2524 (ctx->stmt),
2525 OMP_CLAUSE_NOWAIT))
2526 warning_at (gimple_location (stmt), 0,
2527 "%<#pragma omp cancel sections%> inside "
2528 "%<nowait%> sections construct");
2529 }
2530 else
2531 {
2532 gcc_assert (ctx->outer
2533 && gimple_code (ctx->outer->stmt)
2534 == GIMPLE_OMP_SECTIONS);
2535 ctx->outer->cancellable = true;
2536 if (find_omp_clause (gimple_omp_sections_clauses
2537 (ctx->outer->stmt),
2538 OMP_CLAUSE_NOWAIT))
2539 warning_at (gimple_location (stmt), 0,
2540 "%<#pragma omp cancel sections%> inside "
2541 "%<nowait%> sections construct");
2542 }
2543 }
2544 kind = "sections";
2545 break;
2546 case 8:
2547 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TASK)
2548 bad = "#pragma omp task";
2549 else
2550 ctx->cancellable = true;
2551 kind = "taskgroup";
2552 break;
2553 default:
2554 error_at (gimple_location (stmt), "invalid arguments");
2555 return false;
2556 }
2557 if (bad)
2558 {
2559 error_at (gimple_location (stmt),
2560 "%<%s %s%> construct not closely nested inside of %qs",
2561 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2562 == BUILT_IN_GOMP_CANCEL
2563 ? "#pragma omp cancel"
2564 : "#pragma omp cancellation point", kind, bad);
2565 return false;
2566 }
2567 }
3d483a94 2568 /* FALLTHRU */
75a70cf9 2569 case GIMPLE_OMP_SECTIONS:
2570 case GIMPLE_OMP_SINGLE:
c1d127dd 2571 for (; ctx != NULL; ctx = ctx->outer)
75a70cf9 2572 switch (gimple_code (ctx->stmt))
c1d127dd 2573 {
75a70cf9 2574 case GIMPLE_OMP_FOR:
2575 case GIMPLE_OMP_SECTIONS:
2576 case GIMPLE_OMP_SINGLE:
2577 case GIMPLE_OMP_ORDERED:
2578 case GIMPLE_OMP_MASTER:
2579 case GIMPLE_OMP_TASK:
bc7bff74 2580 case GIMPLE_OMP_CRITICAL:
75a70cf9 2581 if (is_gimple_call (stmt))
fd6481cf 2582 {
bc7bff74 2583 if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2584 != BUILT_IN_GOMP_BARRIER)
2585 return true;
ab129075 2586 error_at (gimple_location (stmt),
2587 "barrier region may not be closely nested inside "
2588 "of work-sharing, critical, ordered, master or "
2589 "explicit task region");
2590 return false;
fd6481cf 2591 }
ab129075 2592 error_at (gimple_location (stmt),
2593 "work-sharing region may not be closely nested inside "
2594 "of work-sharing, critical, ordered, master or explicit "
2595 "task region");
2596 return false;
75a70cf9 2597 case GIMPLE_OMP_PARALLEL:
ab129075 2598 return true;
c1d127dd 2599 default:
2600 break;
2601 }
2602 break;
75a70cf9 2603 case GIMPLE_OMP_MASTER:
c1d127dd 2604 for (; ctx != NULL; ctx = ctx->outer)
75a70cf9 2605 switch (gimple_code (ctx->stmt))
c1d127dd 2606 {
75a70cf9 2607 case GIMPLE_OMP_FOR:
2608 case GIMPLE_OMP_SECTIONS:
2609 case GIMPLE_OMP_SINGLE:
2610 case GIMPLE_OMP_TASK:
ab129075 2611 error_at (gimple_location (stmt),
2612 "master region may not be closely nested inside "
2613 "of work-sharing or explicit task region");
2614 return false;
75a70cf9 2615 case GIMPLE_OMP_PARALLEL:
ab129075 2616 return true;
c1d127dd 2617 default:
2618 break;
2619 }
2620 break;
75a70cf9 2621 case GIMPLE_OMP_ORDERED:
c1d127dd 2622 for (; ctx != NULL; ctx = ctx->outer)
75a70cf9 2623 switch (gimple_code (ctx->stmt))
c1d127dd 2624 {
75a70cf9 2625 case GIMPLE_OMP_CRITICAL:
2626 case GIMPLE_OMP_TASK:
ab129075 2627 error_at (gimple_location (stmt),
2628 "ordered region may not be closely nested inside "
2629 "of critical or explicit task region");
2630 return false;
75a70cf9 2631 case GIMPLE_OMP_FOR:
2632 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
c1d127dd 2633 OMP_CLAUSE_ORDERED) == NULL)
ab129075 2634 {
2635 error_at (gimple_location (stmt),
2636 "ordered region must be closely nested inside "
c1d127dd 2637 "a loop region with an ordered clause");
ab129075 2638 return false;
2639 }
2640 return true;
75a70cf9 2641 case GIMPLE_OMP_PARALLEL:
bc7bff74 2642 error_at (gimple_location (stmt),
2643 "ordered region must be closely nested inside "
2644 "a loop region with an ordered clause");
2645 return false;
c1d127dd 2646 default:
2647 break;
2648 }
2649 break;
75a70cf9 2650 case GIMPLE_OMP_CRITICAL:
1a91d914 2651 {
2652 tree this_stmt_name
2653 = gimple_omp_critical_name (as_a <gomp_critical *> (stmt));
2654 for (; ctx != NULL; ctx = ctx->outer)
2655 if (gomp_critical *other_crit
2656 = dyn_cast <gomp_critical *> (ctx->stmt))
2657 if (this_stmt_name == gimple_omp_critical_name (other_crit))
2658 {
2659 error_at (gimple_location (stmt),
2660 "critical region may not be nested inside a critical "
2661 "region with the same name");
2662 return false;
2663 }
2664 }
c1d127dd 2665 break;
bc7bff74 2666 case GIMPLE_OMP_TEAMS:
2667 if (ctx == NULL
2668 || gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET
2669 || gimple_omp_target_kind (ctx->stmt) != GF_OMP_TARGET_KIND_REGION)
2670 {
2671 error_at (gimple_location (stmt),
2672 "teams construct not closely nested inside of target "
2673 "region");
2674 return false;
2675 }
2676 break;
691447ab 2677 case GIMPLE_OMP_TARGET:
2678 for (; ctx != NULL; ctx = ctx->outer)
b0c5e347 2679 if (is_targetreg_ctx (ctx))
691447ab 2680 {
2681 const char *name;
2682 switch (gimple_omp_target_kind (stmt))
2683 {
2684 case GF_OMP_TARGET_KIND_REGION: name = "target"; break;
2685 case GF_OMP_TARGET_KIND_DATA: name = "target data"; break;
2686 case GF_OMP_TARGET_KIND_UPDATE: name = "target update"; break;
2687 default: gcc_unreachable ();
2688 }
2689 warning_at (gimple_location (stmt), 0,
2690 "%s construct inside of target region", name);
2691 }
2692 break;
c1d127dd 2693 default:
2694 break;
2695 }
ab129075 2696 return true;
c1d127dd 2697}
2698
2699
75a70cf9 2700/* Helper function scan_omp.
2701
2702 Callback for walk_tree or operators in walk_gimple_stmt used to
2703 scan for OpenMP directives in TP. */
1e8e9920 2704
2705static tree
75a70cf9 2706scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
1e8e9920 2707{
4077bf7a 2708 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
2709 omp_context *ctx = (omp_context *) wi->info;
1e8e9920 2710 tree t = *tp;
2711
75a70cf9 2712 switch (TREE_CODE (t))
2713 {
2714 case VAR_DECL:
2715 case PARM_DECL:
2716 case LABEL_DECL:
2717 case RESULT_DECL:
2718 if (ctx)
2719 *tp = remap_decl (t, &ctx->cb);
2720 break;
2721
2722 default:
2723 if (ctx && TYPE_P (t))
2724 *tp = remap_type (t, &ctx->cb);
2725 else if (!DECL_P (t))
7cf869dd 2726 {
2727 *walk_subtrees = 1;
2728 if (ctx)
182cf5a9 2729 {
2730 tree tem = remap_type (TREE_TYPE (t), &ctx->cb);
2731 if (tem != TREE_TYPE (t))
2732 {
2733 if (TREE_CODE (t) == INTEGER_CST)
e913b5cd 2734 *tp = wide_int_to_tree (tem, t);
182cf5a9 2735 else
2736 TREE_TYPE (t) = tem;
2737 }
2738 }
7cf869dd 2739 }
75a70cf9 2740 break;
2741 }
2742
2743 return NULL_TREE;
2744}
2745
f2697631 2746/* Return true if FNDECL is a setjmp or a longjmp. */
2747
2748static bool
2749setjmp_or_longjmp_p (const_tree fndecl)
2750{
2751 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
2752 && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_SETJMP
2753 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LONGJMP))
2754 return true;
2755
2756 tree declname = DECL_NAME (fndecl);
2757 if (!declname)
2758 return false;
2759 const char *name = IDENTIFIER_POINTER (declname);
2760 return !strcmp (name, "setjmp") || !strcmp (name, "longjmp");
2761}
2762
75a70cf9 2763
2764/* Helper function for scan_omp.
2765
2766 Callback for walk_gimple_stmt used to scan for OpenMP directives in
2767 the current statement in GSI. */
2768
2769static tree
2770scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
2771 struct walk_stmt_info *wi)
2772{
2773 gimple stmt = gsi_stmt (*gsi);
2774 omp_context *ctx = (omp_context *) wi->info;
2775
2776 if (gimple_has_location (stmt))
2777 input_location = gimple_location (stmt);
1e8e9920 2778
c1d127dd 2779 /* Check the OpenMP nesting restrictions. */
bc7bff74 2780 bool remove = false;
2781 if (is_gimple_omp (stmt))
2782 remove = !check_omp_nesting_restrictions (stmt, ctx);
2783 else if (is_gimple_call (stmt))
2784 {
2785 tree fndecl = gimple_call_fndecl (stmt);
f2697631 2786 if (fndecl)
2787 {
2788 if (setjmp_or_longjmp_p (fndecl)
2789 && ctx
2790 && gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
10c55644 2791 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
f2697631 2792 {
2793 remove = true;
2794 error_at (gimple_location (stmt),
2795 "setjmp/longjmp inside simd construct");
2796 }
2797 else if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
2798 switch (DECL_FUNCTION_CODE (fndecl))
2799 {
2800 case BUILT_IN_GOMP_BARRIER:
2801 case BUILT_IN_GOMP_CANCEL:
2802 case BUILT_IN_GOMP_CANCELLATION_POINT:
2803 case BUILT_IN_GOMP_TASKYIELD:
2804 case BUILT_IN_GOMP_TASKWAIT:
2805 case BUILT_IN_GOMP_TASKGROUP_START:
2806 case BUILT_IN_GOMP_TASKGROUP_END:
2807 remove = !check_omp_nesting_restrictions (stmt, ctx);
2808 break;
2809 default:
2810 break;
2811 }
2812 }
bc7bff74 2813 }
2814 if (remove)
2815 {
2816 stmt = gimple_build_nop ();
2817 gsi_replace (gsi, stmt, false);
fd6481cf 2818 }
c1d127dd 2819
75a70cf9 2820 *handled_ops_p = true;
2821
2822 switch (gimple_code (stmt))
1e8e9920 2823 {
75a70cf9 2824 case GIMPLE_OMP_PARALLEL:
fd6481cf 2825 taskreg_nesting_level++;
75a70cf9 2826 scan_omp_parallel (gsi, ctx);
fd6481cf 2827 taskreg_nesting_level--;
2828 break;
2829
75a70cf9 2830 case GIMPLE_OMP_TASK:
fd6481cf 2831 taskreg_nesting_level++;
75a70cf9 2832 scan_omp_task (gsi, ctx);
fd6481cf 2833 taskreg_nesting_level--;
1e8e9920 2834 break;
2835
75a70cf9 2836 case GIMPLE_OMP_FOR:
1a91d914 2837 scan_omp_for (as_a <gomp_for *> (stmt), ctx);
1e8e9920 2838 break;
2839
75a70cf9 2840 case GIMPLE_OMP_SECTIONS:
1a91d914 2841 scan_omp_sections (as_a <gomp_sections *> (stmt), ctx);
1e8e9920 2842 break;
2843
75a70cf9 2844 case GIMPLE_OMP_SINGLE:
1a91d914 2845 scan_omp_single (as_a <gomp_single *> (stmt), ctx);
1e8e9920 2846 break;
2847
75a70cf9 2848 case GIMPLE_OMP_SECTION:
2849 case GIMPLE_OMP_MASTER:
bc7bff74 2850 case GIMPLE_OMP_TASKGROUP:
75a70cf9 2851 case GIMPLE_OMP_ORDERED:
2852 case GIMPLE_OMP_CRITICAL:
2853 ctx = new_omp_context (stmt, ctx);
ab129075 2854 scan_omp (gimple_omp_body_ptr (stmt), ctx);
1e8e9920 2855 break;
2856
bc7bff74 2857 case GIMPLE_OMP_TARGET:
1a91d914 2858 scan_omp_target (as_a <gomp_target *> (stmt), ctx);
bc7bff74 2859 break;
2860
2861 case GIMPLE_OMP_TEAMS:
1a91d914 2862 scan_omp_teams (as_a <gomp_teams *> (stmt), ctx);
bc7bff74 2863 break;
2864
75a70cf9 2865 case GIMPLE_BIND:
1e8e9920 2866 {
2867 tree var;
1e8e9920 2868
75a70cf9 2869 *handled_ops_p = false;
2870 if (ctx)
1a91d914 2871 for (var = gimple_bind_vars (as_a <gbind *> (stmt));
2872 var ;
2873 var = DECL_CHAIN (var))
75a70cf9 2874 insert_decl_map (&ctx->cb, var, var);
1e8e9920 2875 }
2876 break;
1e8e9920 2877 default:
75a70cf9 2878 *handled_ops_p = false;
1e8e9920 2879 break;
2880 }
2881
2882 return NULL_TREE;
2883}
2884
2885
75a70cf9 2886/* Scan all the statements starting at the current statement. CTX
2887 contains context information about the OpenMP directives and
2888 clauses found during the scan. */
1e8e9920 2889
2890static void
ab129075 2891scan_omp (gimple_seq *body_p, omp_context *ctx)
1e8e9920 2892{
2893 location_t saved_location;
2894 struct walk_stmt_info wi;
2895
2896 memset (&wi, 0, sizeof (wi));
1e8e9920 2897 wi.info = ctx;
1e8e9920 2898 wi.want_locations = true;
2899
2900 saved_location = input_location;
ab129075 2901 walk_gimple_seq_mod (body_p, scan_omp_1_stmt, scan_omp_1_op, &wi);
1e8e9920 2902 input_location = saved_location;
2903}
2904\f
2905/* Re-gimplification and code generation routines. */
2906
2907/* Build a call to GOMP_barrier. */
2908
bc7bff74 2909static gimple
2910build_omp_barrier (tree lhs)
2911{
2912 tree fndecl = builtin_decl_explicit (lhs ? BUILT_IN_GOMP_BARRIER_CANCEL
2913 : BUILT_IN_GOMP_BARRIER);
1a91d914 2914 gcall *g = gimple_build_call (fndecl, 0);
bc7bff74 2915 if (lhs)
2916 gimple_call_set_lhs (g, lhs);
2917 return g;
1e8e9920 2918}
2919
2920/* If a context was created for STMT when it was scanned, return it. */
2921
2922static omp_context *
75a70cf9 2923maybe_lookup_ctx (gimple stmt)
1e8e9920 2924{
2925 splay_tree_node n;
2926 n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
2927 return n ? (omp_context *) n->value : NULL;
2928}
2929
773c5ba7 2930
2931/* Find the mapping for DECL in CTX or the immediately enclosing
2932 context that has a mapping for DECL.
2933
2934 If CTX is a nested parallel directive, we may have to use the decl
2935 mappings created in CTX's parent context. Suppose that we have the
2936 following parallel nesting (variable UIDs showed for clarity):
2937
2938 iD.1562 = 0;
2939 #omp parallel shared(iD.1562) -> outer parallel
2940 iD.1562 = iD.1562 + 1;
2941
2942 #omp parallel shared (iD.1562) -> inner parallel
2943 iD.1562 = iD.1562 - 1;
2944
2945 Each parallel structure will create a distinct .omp_data_s structure
2946 for copying iD.1562 in/out of the directive:
2947
2948 outer parallel .omp_data_s.1.i -> iD.1562
2949 inner parallel .omp_data_s.2.i -> iD.1562
2950
2951 A shared variable mapping will produce a copy-out operation before
2952 the parallel directive and a copy-in operation after it. So, in
2953 this case we would have:
2954
2955 iD.1562 = 0;
2956 .omp_data_o.1.i = iD.1562;
2957 #omp parallel shared(iD.1562) -> outer parallel
2958 .omp_data_i.1 = &.omp_data_o.1
2959 .omp_data_i.1->i = .omp_data_i.1->i + 1;
2960
2961 .omp_data_o.2.i = iD.1562; -> **
2962 #omp parallel shared(iD.1562) -> inner parallel
2963 .omp_data_i.2 = &.omp_data_o.2
2964 .omp_data_i.2->i = .omp_data_i.2->i - 1;
2965
2966
2967 ** This is a problem. The symbol iD.1562 cannot be referenced
2968 inside the body of the outer parallel region. But since we are
2969 emitting this copy operation while expanding the inner parallel
2970 directive, we need to access the CTX structure of the outer
2971 parallel directive to get the correct mapping:
2972
2973 .omp_data_o.2.i = .omp_data_i.1->i
2974
2975 Since there may be other workshare or parallel directives enclosing
2976 the parallel directive, it may be necessary to walk up the context
2977 parent chain. This is not a problem in general because nested
2978 parallelism happens only rarely. */
2979
2980static tree
2981lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
2982{
2983 tree t;
2984 omp_context *up;
2985
773c5ba7 2986 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
2987 t = maybe_lookup_decl (decl, up);
2988
87b31375 2989 gcc_assert (!ctx->is_nested || t || is_global_var (decl));
773c5ba7 2990
c37594c7 2991 return t ? t : decl;
773c5ba7 2992}
2993
2994
f49d7bb5 2995/* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
2996 in outer contexts. */
2997
2998static tree
2999maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
3000{
3001 tree t = NULL;
3002 omp_context *up;
3003
87b31375 3004 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
3005 t = maybe_lookup_decl (decl, up);
f49d7bb5 3006
3007 return t ? t : decl;
3008}
3009
3010
1e8e9920 3011/* Construct the initialization value for reduction CLAUSE. */
3012
3013tree
3014omp_reduction_init (tree clause, tree type)
3015{
389dd41b 3016 location_t loc = OMP_CLAUSE_LOCATION (clause);
1e8e9920 3017 switch (OMP_CLAUSE_REDUCTION_CODE (clause))
3018 {
3019 case PLUS_EXPR:
3020 case MINUS_EXPR:
3021 case BIT_IOR_EXPR:
3022 case BIT_XOR_EXPR:
3023 case TRUTH_OR_EXPR:
3024 case TRUTH_ORIF_EXPR:
3025 case TRUTH_XOR_EXPR:
3026 case NE_EXPR:
385f3f36 3027 return build_zero_cst (type);
1e8e9920 3028
3029 case MULT_EXPR:
3030 case TRUTH_AND_EXPR:
3031 case TRUTH_ANDIF_EXPR:
3032 case EQ_EXPR:
389dd41b 3033 return fold_convert_loc (loc, type, integer_one_node);
1e8e9920 3034
3035 case BIT_AND_EXPR:
389dd41b 3036 return fold_convert_loc (loc, type, integer_minus_one_node);
1e8e9920 3037
3038 case MAX_EXPR:
3039 if (SCALAR_FLOAT_TYPE_P (type))
3040 {
3041 REAL_VALUE_TYPE max, min;
3042 if (HONOR_INFINITIES (TYPE_MODE (type)))
3043 {
3044 real_inf (&max);
3045 real_arithmetic (&min, NEGATE_EXPR, &max, NULL);
3046 }
3047 else
3048 real_maxval (&min, 1, TYPE_MODE (type));
3049 return build_real (type, min);
3050 }
3051 else
3052 {
3053 gcc_assert (INTEGRAL_TYPE_P (type));
3054 return TYPE_MIN_VALUE (type);
3055 }
3056
3057 case MIN_EXPR:
3058 if (SCALAR_FLOAT_TYPE_P (type))
3059 {
3060 REAL_VALUE_TYPE max;
3061 if (HONOR_INFINITIES (TYPE_MODE (type)))
3062 real_inf (&max);
3063 else
3064 real_maxval (&max, 0, TYPE_MODE (type));
3065 return build_real (type, max);
3066 }
3067 else
3068 {
3069 gcc_assert (INTEGRAL_TYPE_P (type));
3070 return TYPE_MAX_VALUE (type);
3071 }
3072
3073 default:
3074 gcc_unreachable ();
3075 }
3076}
3077
bc7bff74 3078/* Return alignment to be assumed for var in CLAUSE, which should be
3079 OMP_CLAUSE_ALIGNED. */
3080
3081static tree
3082omp_clause_aligned_alignment (tree clause)
3083{
3084 if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause))
3085 return OMP_CLAUSE_ALIGNED_ALIGNMENT (clause);
3086
3087 /* Otherwise return implementation defined alignment. */
3088 unsigned int al = 1;
3754d046 3089 machine_mode mode, vmode;
bc7bff74 3090 int vs = targetm.vectorize.autovectorize_vector_sizes ();
3091 if (vs)
3092 vs = 1 << floor_log2 (vs);
3093 static enum mode_class classes[]
3094 = { MODE_INT, MODE_VECTOR_INT, MODE_FLOAT, MODE_VECTOR_FLOAT };
3095 for (int i = 0; i < 4; i += 2)
3096 for (mode = GET_CLASS_NARROWEST_MODE (classes[i]);
3097 mode != VOIDmode;
3098 mode = GET_MODE_WIDER_MODE (mode))
3099 {
3100 vmode = targetm.vectorize.preferred_simd_mode (mode);
3101 if (GET_MODE_CLASS (vmode) != classes[i + 1])
3102 continue;
3103 while (vs
3104 && GET_MODE_SIZE (vmode) < vs
3105 && GET_MODE_2XWIDER_MODE (vmode) != VOIDmode)
3106 vmode = GET_MODE_2XWIDER_MODE (vmode);
3107
3108 tree type = lang_hooks.types.type_for_mode (mode, 1);
3109 if (type == NULL_TREE || TYPE_MODE (type) != mode)
3110 continue;
3111 type = build_vector_type (type, GET_MODE_SIZE (vmode)
3112 / GET_MODE_SIZE (mode));
3113 if (TYPE_MODE (type) != vmode)
3114 continue;
3115 if (TYPE_ALIGN_UNIT (type) > al)
3116 al = TYPE_ALIGN_UNIT (type);
3117 }
3118 return build_int_cst (integer_type_node, al);
3119}
3120
3d483a94 3121/* Return maximum possible vectorization factor for the target. */
3122
3123static int
3124omp_max_vf (void)
3125{
3126 if (!optimize
3127 || optimize_debug
ad45e43e 3128 || !flag_tree_loop_optimize
043115ec 3129 || (!flag_tree_loop_vectorize
3130 && (global_options_set.x_flag_tree_loop_vectorize
3131 || global_options_set.x_flag_tree_vectorize)))
3d483a94 3132 return 1;
3133
3134 int vs = targetm.vectorize.autovectorize_vector_sizes ();
3135 if (vs)
3136 {
3137 vs = 1 << floor_log2 (vs);
3138 return vs;
3139 }
3754d046 3140 machine_mode vqimode = targetm.vectorize.preferred_simd_mode (QImode);
3d483a94 3141 if (GET_MODE_CLASS (vqimode) == MODE_VECTOR_INT)
3142 return GET_MODE_NUNITS (vqimode);
3143 return 1;
3144}
3145
3146/* Helper function of lower_rec_input_clauses, used for #pragma omp simd
3147 privatization. */
3148
3149static bool
3150lower_rec_simd_input_clauses (tree new_var, omp_context *ctx, int &max_vf,
3151 tree &idx, tree &lane, tree &ivar, tree &lvar)
3152{
3153 if (max_vf == 0)
3154 {
3155 max_vf = omp_max_vf ();
3156 if (max_vf > 1)
3157 {
3158 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3159 OMP_CLAUSE_SAFELEN);
c3f3b68d 3160 if (c && TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) != INTEGER_CST)
3161 max_vf = 1;
3162 else if (c && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
3163 max_vf) == -1)
d85a2013 3164 max_vf = tree_to_shwi (OMP_CLAUSE_SAFELEN_EXPR (c));
3d483a94 3165 }
3166 if (max_vf > 1)
3167 {
3168 idx = create_tmp_var (unsigned_type_node, NULL);
3169 lane = create_tmp_var (unsigned_type_node, NULL);
3170 }
3171 }
3172 if (max_vf == 1)
3173 return false;
3174
3175 tree atype = build_array_type_nelts (TREE_TYPE (new_var), max_vf);
3176 tree avar = create_tmp_var_raw (atype, NULL);
3177 if (TREE_ADDRESSABLE (new_var))
3178 TREE_ADDRESSABLE (avar) = 1;
3179 DECL_ATTRIBUTES (avar)
3180 = tree_cons (get_identifier ("omp simd array"), NULL,
3181 DECL_ATTRIBUTES (avar));
3182 gimple_add_tmp_var (avar);
3183 ivar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, idx,
3184 NULL_TREE, NULL_TREE);
3185 lvar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, lane,
3186 NULL_TREE, NULL_TREE);
bc7bff74 3187 if (DECL_P (new_var))
3188 {
3189 SET_DECL_VALUE_EXPR (new_var, lvar);
3190 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3191 }
3d483a94 3192 return true;
3193}
3194
2712b6de 3195/* Helper function of lower_rec_input_clauses. For a reference
3196 in simd reduction, add an underlying variable it will reference. */
3197
3198static void
3199handle_simd_reference (location_t loc, tree new_vard, gimple_seq *ilist)
3200{
3201 tree z = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard)));
3202 if (TREE_CONSTANT (z))
3203 {
3204 const char *name = NULL;
3205 if (DECL_NAME (new_vard))
3206 name = IDENTIFIER_POINTER (DECL_NAME (new_vard));
3207
3208 z = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_vard)), name);
3209 gimple_add_tmp_var (z);
3210 TREE_ADDRESSABLE (z) = 1;
3211 z = build_fold_addr_expr_loc (loc, z);
3212 gimplify_assign (new_vard, z, ilist);
3213 }
3214}
3215
1e8e9920 3216/* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
3217 from the receiver (aka child) side and initializers for REFERENCE_TYPE
3218 private variables. Initialization statements go in ILIST, while calls
3219 to destructors go in DLIST. */
3220
3221static void
75a70cf9 3222lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
bc7bff74 3223 omp_context *ctx, struct omp_for_data *fd)
1e8e9920 3224{
c2f47e15 3225 tree c, dtor, copyin_seq, x, ptr;
1e8e9920 3226 bool copyin_by_ref = false;
f49d7bb5 3227 bool lastprivate_firstprivate = false;
bc7bff74 3228 bool reduction_omp_orig_ref = false;
1e8e9920 3229 int pass;
3d483a94 3230 bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
10c55644 3231 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD);
3d483a94 3232 int max_vf = 0;
3233 tree lane = NULL_TREE, idx = NULL_TREE;
3234 tree ivar = NULL_TREE, lvar = NULL_TREE;
3235 gimple_seq llist[2] = { NULL, NULL };
1e8e9920 3236
1e8e9920 3237 copyin_seq = NULL;
3238
3d483a94 3239 /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
3240 with data sharing clauses referencing variable sized vars. That
3241 is unnecessarily hard to support and very unlikely to result in
3242 vectorized code anyway. */
3243 if (is_simd)
3244 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3245 switch (OMP_CLAUSE_CODE (c))
3246 {
9580cb79 3247 case OMP_CLAUSE_LINEAR:
3248 if (OMP_CLAUSE_LINEAR_ARRAY (c))
3249 max_vf = 1;
3250 /* FALLTHRU */
3d483a94 3251 case OMP_CLAUSE_REDUCTION:
3d483a94 3252 case OMP_CLAUSE_PRIVATE:
3253 case OMP_CLAUSE_FIRSTPRIVATE:
3254 case OMP_CLAUSE_LASTPRIVATE:
3d483a94 3255 if (is_variable_sized (OMP_CLAUSE_DECL (c)))
3256 max_vf = 1;
3257 break;
3258 default:
3259 continue;
3260 }
3261
1e8e9920 3262 /* Do all the fixed sized types in the first pass, and the variable sized
3263 types in the second pass. This makes sure that the scalar arguments to
48e1416a 3264 the variable sized types are processed before we use them in the
1e8e9920 3265 variable sized operations. */
3266 for (pass = 0; pass < 2; ++pass)
3267 {
3268 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3269 {
55d6e7cd 3270 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
1e8e9920 3271 tree var, new_var;
3272 bool by_ref;
389dd41b 3273 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
1e8e9920 3274
3275 switch (c_kind)
3276 {
3277 case OMP_CLAUSE_PRIVATE:
3278 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
3279 continue;
3280 break;
3281 case OMP_CLAUSE_SHARED:
bc7bff74 3282 /* Ignore shared directives in teams construct. */
3283 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3284 continue;
f49d7bb5 3285 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
3286 {
3287 gcc_assert (is_global_var (OMP_CLAUSE_DECL (c)));
3288 continue;
3289 }
1e8e9920 3290 case OMP_CLAUSE_FIRSTPRIVATE:
1e8e9920 3291 case OMP_CLAUSE_COPYIN:
bc7bff74 3292 case OMP_CLAUSE_LINEAR:
3293 break;
1e8e9920 3294 case OMP_CLAUSE_REDUCTION:
bc7bff74 3295 if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
3296 reduction_omp_orig_ref = true;
1e8e9920 3297 break;
bc7bff74 3298 case OMP_CLAUSE__LOOPTEMP_:
3299 /* Handle _looptemp_ clauses only on parallel. */
3300 if (fd)
3301 continue;
3d483a94 3302 break;
df2c34fc 3303 case OMP_CLAUSE_LASTPRIVATE:
f49d7bb5 3304 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3305 {
3306 lastprivate_firstprivate = true;
3307 if (pass != 0)
3308 continue;
3309 }
cf5f881f 3310 /* Even without corresponding firstprivate, if
3311 decl is Fortran allocatable, it needs outer var
3312 reference. */
3313 else if (pass == 0
3314 && lang_hooks.decls.omp_private_outer_ref
3315 (OMP_CLAUSE_DECL (c)))
3316 lastprivate_firstprivate = true;
df2c34fc 3317 break;
bc7bff74 3318 case OMP_CLAUSE_ALIGNED:
3319 if (pass == 0)
3320 continue;
3321 var = OMP_CLAUSE_DECL (c);
3322 if (TREE_CODE (TREE_TYPE (var)) == POINTER_TYPE
3323 && !is_global_var (var))
3324 {
3325 new_var = maybe_lookup_decl (var, ctx);
3326 if (new_var == NULL_TREE)
3327 new_var = maybe_lookup_decl_in_outer_ctx (var, ctx);
3328 x = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3329 x = build_call_expr_loc (clause_loc, x, 2, new_var,
3330 omp_clause_aligned_alignment (c));
3331 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3332 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
3333 gimplify_and_add (x, ilist);
3334 }
3335 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
3336 && is_global_var (var))
3337 {
3338 tree ptype = build_pointer_type (TREE_TYPE (var)), t, t2;
3339 new_var = lookup_decl (var, ctx);
3340 t = maybe_lookup_decl_in_outer_ctx (var, ctx);
3341 t = build_fold_addr_expr_loc (clause_loc, t);
3342 t2 = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3343 t = build_call_expr_loc (clause_loc, t2, 2, t,
3344 omp_clause_aligned_alignment (c));
3345 t = fold_convert_loc (clause_loc, ptype, t);
3346 x = create_tmp_var (ptype, NULL);
3347 t = build2 (MODIFY_EXPR, ptype, x, t);
3348 gimplify_and_add (t, ilist);
3349 t = build_simple_mem_ref_loc (clause_loc, x);
3350 SET_DECL_VALUE_EXPR (new_var, t);
3351 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3352 }
3353 continue;
1e8e9920 3354 default:
3355 continue;
3356 }
3357
3358 new_var = var = OMP_CLAUSE_DECL (c);
3359 if (c_kind != OMP_CLAUSE_COPYIN)
3360 new_var = lookup_decl (var, ctx);
3361
3362 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
3363 {
3364 if (pass != 0)
3365 continue;
3366 }
1e8e9920 3367 else if (is_variable_sized (var))
3368 {
773c5ba7 3369 /* For variable sized types, we need to allocate the
3370 actual storage here. Call alloca and store the
3371 result in the pointer decl that we created elsewhere. */
1e8e9920 3372 if (pass == 0)
3373 continue;
3374
fd6481cf 3375 if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
3376 {
1a91d914 3377 gcall *stmt;
b9a16870 3378 tree tmp, atmp;
75a70cf9 3379
fd6481cf 3380 ptr = DECL_VALUE_EXPR (new_var);
3381 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
3382 ptr = TREE_OPERAND (ptr, 0);
3383 gcc_assert (DECL_P (ptr));
3384 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
75a70cf9 3385
3386 /* void *tmp = __builtin_alloca */
b9a16870 3387 atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3388 stmt = gimple_build_call (atmp, 1, x);
75a70cf9 3389 tmp = create_tmp_var_raw (ptr_type_node, NULL);
3390 gimple_add_tmp_var (tmp);
3391 gimple_call_set_lhs (stmt, tmp);
3392
3393 gimple_seq_add_stmt (ilist, stmt);
3394
389dd41b 3395 x = fold_convert_loc (clause_loc, TREE_TYPE (ptr), tmp);
75a70cf9 3396 gimplify_assign (ptr, x, ilist);
fd6481cf 3397 }
1e8e9920 3398 }
1e8e9920 3399 else if (is_reference (var))
3400 {
773c5ba7 3401 /* For references that are being privatized for Fortran,
3402 allocate new backing storage for the new pointer
3403 variable. This allows us to avoid changing all the
3404 code that expects a pointer to something that expects
bc7bff74 3405 a direct variable. */
1e8e9920 3406 if (pass == 0)
3407 continue;
3408
3409 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
fd6481cf 3410 if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx))
3411 {
3412 x = build_receiver_ref (var, false, ctx);
389dd41b 3413 x = build_fold_addr_expr_loc (clause_loc, x);
fd6481cf 3414 }
3415 else if (TREE_CONSTANT (x))
1e8e9920 3416 {
2712b6de 3417 /* For reduction in SIMD loop, defer adding the
3418 initialization of the reference, because if we decide
3419 to use SIMD array for it, the initilization could cause
3420 expansion ICE. */
3421 if (c_kind == OMP_CLAUSE_REDUCTION && is_simd)
09d1c205 3422 x = NULL_TREE;
3423 else
3424 {
3425 const char *name = NULL;
3426 if (DECL_NAME (var))
3427 name = IDENTIFIER_POINTER (DECL_NAME (new_var));
3428
3429 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
3430 name);
3431 gimple_add_tmp_var (x);
3432 TREE_ADDRESSABLE (x) = 1;
3433 x = build_fold_addr_expr_loc (clause_loc, x);
3434 }
1e8e9920 3435 }
3436 else
3437 {
b9a16870 3438 tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3439 x = build_call_expr_loc (clause_loc, atmp, 1, x);
1e8e9920 3440 }
3441
09d1c205 3442 if (x)
3443 {
3444 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3445 gimplify_assign (new_var, x, ilist);
3446 }
1e8e9920 3447
182cf5a9 3448 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
1e8e9920 3449 }
3450 else if (c_kind == OMP_CLAUSE_REDUCTION
3451 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3452 {
3453 if (pass == 0)
3454 continue;
3455 }
3456 else if (pass != 0)
3457 continue;
3458
55d6e7cd 3459 switch (OMP_CLAUSE_CODE (c))
1e8e9920 3460 {
3461 case OMP_CLAUSE_SHARED:
bc7bff74 3462 /* Ignore shared directives in teams construct. */
3463 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3464 continue;
f49d7bb5 3465 /* Shared global vars are just accessed directly. */
3466 if (is_global_var (new_var))
3467 break;
1e8e9920 3468 /* Set up the DECL_VALUE_EXPR for shared variables now. This
3469 needs to be delayed until after fixup_child_record_type so
3470 that we get the correct type during the dereference. */
e8a588af 3471 by_ref = use_pointer_for_field (var, ctx);
1e8e9920 3472 x = build_receiver_ref (var, by_ref, ctx);
3473 SET_DECL_VALUE_EXPR (new_var, x);
3474 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3475
3476 /* ??? If VAR is not passed by reference, and the variable
3477 hasn't been initialized yet, then we'll get a warning for
3478 the store into the omp_data_s structure. Ideally, we'd be
48e1416a 3479 able to notice this and not store anything at all, but
1e8e9920 3480 we're generating code too early. Suppress the warning. */
3481 if (!by_ref)
3482 TREE_NO_WARNING (var) = 1;
3483 break;
3484
3485 case OMP_CLAUSE_LASTPRIVATE:
3486 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3487 break;
3488 /* FALLTHRU */
3489
3490 case OMP_CLAUSE_PRIVATE:
fd6481cf 3491 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE)
3492 x = build_outer_var_ref (var, ctx);
3493 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
3494 {
3495 if (is_task_ctx (ctx))
3496 x = build_receiver_ref (var, false, ctx);
3497 else
3498 x = build_outer_var_ref (var, ctx);
3499 }
3500 else
3501 x = NULL;
3d483a94 3502 do_private:
bc7bff74 3503 tree nx;
3504 nx = lang_hooks.decls.omp_clause_default_ctor (c, new_var, x);
3d483a94 3505 if (is_simd)
3506 {
3507 tree y = lang_hooks.decls.omp_clause_dtor (c, new_var);
bc7bff74 3508 if ((TREE_ADDRESSABLE (new_var) || nx || y
3d483a94 3509 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
3510 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3511 idx, lane, ivar, lvar))
3512 {
bc7bff74 3513 if (nx)
3d483a94 3514 x = lang_hooks.decls.omp_clause_default_ctor
3515 (c, unshare_expr (ivar), x);
bc7bff74 3516 if (nx && x)
3d483a94 3517 gimplify_and_add (x, &llist[0]);
3518 if (y)
3519 {
3520 y = lang_hooks.decls.omp_clause_dtor (c, ivar);
3521 if (y)
3522 {
3523 gimple_seq tseq = NULL;
3524
3525 dtor = y;
3526 gimplify_stmt (&dtor, &tseq);
3527 gimple_seq_add_seq (&llist[1], tseq);
3528 }
3529 }
3530 break;
3531 }
3532 }
bc7bff74 3533 if (nx)
3534 gimplify_and_add (nx, ilist);
1e8e9920 3535 /* FALLTHRU */
3536
3537 do_dtor:
3538 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
3539 if (x)
3540 {
75a70cf9 3541 gimple_seq tseq = NULL;
3542
1e8e9920 3543 dtor = x;
75a70cf9 3544 gimplify_stmt (&dtor, &tseq);
e3a19533 3545 gimple_seq_add_seq (dlist, tseq);
1e8e9920 3546 }
3547 break;
3548
3d483a94 3549 case OMP_CLAUSE_LINEAR:
3550 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c))
3551 goto do_firstprivate;
3552 if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
3553 x = NULL;
3554 else
3555 x = build_outer_var_ref (var, ctx);
3556 goto do_private;
3557
1e8e9920 3558 case OMP_CLAUSE_FIRSTPRIVATE:
fd6481cf 3559 if (is_task_ctx (ctx))
3560 {
3561 if (is_reference (var) || is_variable_sized (var))
3562 goto do_dtor;
3563 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var,
3564 ctx))
3565 || use_pointer_for_field (var, NULL))
3566 {
3567 x = build_receiver_ref (var, false, ctx);
3568 SET_DECL_VALUE_EXPR (new_var, x);
3569 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3570 goto do_dtor;
3571 }
3572 }
3d483a94 3573 do_firstprivate:
1e8e9920 3574 x = build_outer_var_ref (var, ctx);
3d483a94 3575 if (is_simd)
3576 {
bc7bff74 3577 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3578 && gimple_omp_for_combined_into_p (ctx->stmt))
3579 {
9580cb79 3580 tree t = OMP_CLAUSE_LINEAR_STEP (c);
3581 tree stept = TREE_TYPE (t);
3582 tree ct = find_omp_clause (clauses,
3583 OMP_CLAUSE__LOOPTEMP_);
3584 gcc_assert (ct);
3585 tree l = OMP_CLAUSE_DECL (ct);
e471cc6f 3586 tree n1 = fd->loop.n1;
3587 tree step = fd->loop.step;
3588 tree itype = TREE_TYPE (l);
3589 if (POINTER_TYPE_P (itype))
3590 itype = signed_type_for (itype);
3591 l = fold_build2 (MINUS_EXPR, itype, l, n1);
3592 if (TYPE_UNSIGNED (itype)
3593 && fd->loop.cond_code == GT_EXPR)
3594 l = fold_build2 (TRUNC_DIV_EXPR, itype,
3595 fold_build1 (NEGATE_EXPR, itype, l),
3596 fold_build1 (NEGATE_EXPR,
3597 itype, step));
3598 else
3599 l = fold_build2 (TRUNC_DIV_EXPR, itype, l, step);
bc7bff74 3600 t = fold_build2 (MULT_EXPR, stept,
3601 fold_convert (stept, l), t);
9580cb79 3602
3603 if (OMP_CLAUSE_LINEAR_ARRAY (c))
3604 {
3605 x = lang_hooks.decls.omp_clause_linear_ctor
3606 (c, new_var, x, t);
3607 gimplify_and_add (x, ilist);
3608 goto do_dtor;
3609 }
3610
bc7bff74 3611 if (POINTER_TYPE_P (TREE_TYPE (x)))
3612 x = fold_build2 (POINTER_PLUS_EXPR,
3613 TREE_TYPE (x), x, t);
3614 else
3615 x = fold_build2 (PLUS_EXPR, TREE_TYPE (x), x, t);
3616 }
3617
3d483a94 3618 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
3619 || TREE_ADDRESSABLE (new_var))
3620 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3621 idx, lane, ivar, lvar))
3622 {
3623 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR)
3624 {
3625 tree iv = create_tmp_var (TREE_TYPE (new_var), NULL);
3626 x = lang_hooks.decls.omp_clause_copy_ctor (c, iv, x);
3627 gimplify_and_add (x, ilist);
3628 gimple_stmt_iterator gsi
3629 = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
1a91d914 3630 gassign *g
3d483a94 3631 = gimple_build_assign (unshare_expr (lvar), iv);
3632 gsi_insert_before_without_update (&gsi, g,
3633 GSI_SAME_STMT);
9580cb79 3634 tree t = OMP_CLAUSE_LINEAR_STEP (c);
3d483a94 3635 enum tree_code code = PLUS_EXPR;
3636 if (POINTER_TYPE_P (TREE_TYPE (new_var)))
3637 code = POINTER_PLUS_EXPR;
3638 g = gimple_build_assign_with_ops (code, iv, iv, t);
3639 gsi_insert_before_without_update (&gsi, g,
3640 GSI_SAME_STMT);
3641 break;
3642 }
3643 x = lang_hooks.decls.omp_clause_copy_ctor
3644 (c, unshare_expr (ivar), x);
3645 gimplify_and_add (x, &llist[0]);
3646 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
3647 if (x)
3648 {
3649 gimple_seq tseq = NULL;
3650
3651 dtor = x;
3652 gimplify_stmt (&dtor, &tseq);
3653 gimple_seq_add_seq (&llist[1], tseq);
3654 }
3655 break;
3656 }
3657 }
1e8e9920 3658 x = lang_hooks.decls.omp_clause_copy_ctor (c, new_var, x);
3659 gimplify_and_add (x, ilist);
3660 goto do_dtor;
1e8e9920 3661
bc7bff74 3662 case OMP_CLAUSE__LOOPTEMP_:
3663 gcc_assert (is_parallel_ctx (ctx));
3664 x = build_outer_var_ref (var, ctx);
3665 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
3666 gimplify_and_add (x, ilist);
3667 break;
3668
1e8e9920 3669 case OMP_CLAUSE_COPYIN:
e8a588af 3670 by_ref = use_pointer_for_field (var, NULL);
1e8e9920 3671 x = build_receiver_ref (var, by_ref, ctx);
3672 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
3673 append_to_statement_list (x, &copyin_seq);
3674 copyin_by_ref |= by_ref;
3675 break;
3676
3677 case OMP_CLAUSE_REDUCTION:
3678 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3679 {
fd6481cf 3680 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
bc7bff74 3681 gimple tseq;
fd6481cf 3682 x = build_outer_var_ref (var, ctx);
3683
bc7bff74 3684 if (is_reference (var)
3685 && !useless_type_conversion_p (TREE_TYPE (placeholder),
3686 TREE_TYPE (x)))
389dd41b 3687 x = build_fold_addr_expr_loc (clause_loc, x);
fd6481cf 3688 SET_DECL_VALUE_EXPR (placeholder, x);
3689 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
bc7bff74 3690 tree new_vard = new_var;
3691 if (is_reference (var))
3692 {
3693 gcc_assert (TREE_CODE (new_var) == MEM_REF);
3694 new_vard = TREE_OPERAND (new_var, 0);
3695 gcc_assert (DECL_P (new_vard));
3696 }
3d483a94 3697 if (is_simd
3698 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3699 idx, lane, ivar, lvar))
3700 {
bc7bff74 3701 if (new_vard == new_var)
3702 {
3703 gcc_assert (DECL_VALUE_EXPR (new_var) == lvar);
3704 SET_DECL_VALUE_EXPR (new_var, ivar);
3705 }
3706 else
3707 {
3708 SET_DECL_VALUE_EXPR (new_vard,
3709 build_fold_addr_expr (ivar));
3710 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
3711 }
3712 x = lang_hooks.decls.omp_clause_default_ctor
3713 (c, unshare_expr (ivar),
3714 build_outer_var_ref (var, ctx));
3715 if (x)
3716 gimplify_and_add (x, &llist[0]);
3717 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
3718 {
3719 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
3720 lower_omp (&tseq, ctx);
3721 gimple_seq_add_seq (&llist[0], tseq);
3722 }
3723 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
3724 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
3725 lower_omp (&tseq, ctx);
3726 gimple_seq_add_seq (&llist[1], tseq);
3727 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
3728 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
3729 if (new_vard == new_var)
3730 SET_DECL_VALUE_EXPR (new_var, lvar);
3731 else
3732 SET_DECL_VALUE_EXPR (new_vard,
3733 build_fold_addr_expr (lvar));
3734 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
3735 if (x)
3736 {
3737 tseq = NULL;
3738 dtor = x;
3739 gimplify_stmt (&dtor, &tseq);
3740 gimple_seq_add_seq (&llist[1], tseq);
3741 }
3742 break;
3743 }
09d1c205 3744 /* If this is a reference to constant size reduction var
3745 with placeholder, we haven't emitted the initializer
3746 for it because it is undesirable if SIMD arrays are used.
3747 But if they aren't used, we need to emit the deferred
3748 initialization now. */
3749 else if (is_reference (var) && is_simd)
2712b6de 3750 handle_simd_reference (clause_loc, new_vard, ilist);
bc7bff74 3751 x = lang_hooks.decls.omp_clause_default_ctor
cf5f881f 3752 (c, unshare_expr (new_var),
3753 build_outer_var_ref (var, ctx));
bc7bff74 3754 if (x)
3755 gimplify_and_add (x, ilist);
3756 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
3757 {
3758 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
3759 lower_omp (&tseq, ctx);
3760 gimple_seq_add_seq (ilist, tseq);
3761 }
75a70cf9 3762 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
bc7bff74 3763 if (is_simd)
3764 {
3765 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
3766 lower_omp (&tseq, ctx);
3767 gimple_seq_add_seq (dlist, tseq);
3768 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
3769 }
fd6481cf 3770 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
bc7bff74 3771 goto do_dtor;
1e8e9920 3772 }
3773 else
3774 {
3775 x = omp_reduction_init (c, TREE_TYPE (new_var));
3776 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
c22ad515 3777 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
3778
3779 /* reduction(-:var) sums up the partial results, so it
3780 acts identically to reduction(+:var). */
3781 if (code == MINUS_EXPR)
3782 code = PLUS_EXPR;
3783
2712b6de 3784 tree new_vard = new_var;
3785 if (is_simd && is_reference (var))
3786 {
3787 gcc_assert (TREE_CODE (new_var) == MEM_REF);
3788 new_vard = TREE_OPERAND (new_var, 0);
3789 gcc_assert (DECL_P (new_vard));
3790 }
3d483a94 3791 if (is_simd
3792 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3793 idx, lane, ivar, lvar))
3794 {
3d483a94 3795 tree ref = build_outer_var_ref (var, ctx);
3796
3797 gimplify_assign (unshare_expr (ivar), x, &llist[0]);
3798
3d483a94 3799 x = build2 (code, TREE_TYPE (ref), ref, ivar);
3800 ref = build_outer_var_ref (var, ctx);
3801 gimplify_assign (ref, x, &llist[1]);
2712b6de 3802
3803 if (new_vard != new_var)
3804 {
3805 SET_DECL_VALUE_EXPR (new_vard,
3806 build_fold_addr_expr (lvar));
3807 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
3808 }
3d483a94 3809 }
3810 else
3811 {
2712b6de 3812 if (is_reference (var) && is_simd)
3813 handle_simd_reference (clause_loc, new_vard, ilist);
3d483a94 3814 gimplify_assign (new_var, x, ilist);
3815 if (is_simd)
c22ad515 3816 {
3817 tree ref = build_outer_var_ref (var, ctx);
3818
3819 x = build2 (code, TREE_TYPE (ref), ref, new_var);
3820 ref = build_outer_var_ref (var, ctx);
3821 gimplify_assign (ref, x, dlist);
3822 }
3d483a94 3823 }
1e8e9920 3824 }
3825 break;
3826
3827 default:
3828 gcc_unreachable ();
3829 }
3830 }
3831 }
3832
3d483a94 3833 if (lane)
3834 {
3835 tree uid = create_tmp_var (ptr_type_node, "simduid");
8e1a382d 3836 /* Don't want uninit warnings on simduid, it is always uninitialized,
3837 but we use it not for the value, but for the DECL_UID only. */
3838 TREE_NO_WARNING (uid) = 1;
3d483a94 3839 gimple g
3840 = gimple_build_call_internal (IFN_GOMP_SIMD_LANE, 1, uid);
3841 gimple_call_set_lhs (g, lane);
3842 gimple_stmt_iterator gsi = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
3843 gsi_insert_before_without_update (&gsi, g, GSI_SAME_STMT);
3844 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SIMDUID_);
3845 OMP_CLAUSE__SIMDUID__DECL (c) = uid;
3846 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
3847 gimple_omp_for_set_clauses (ctx->stmt, c);
3848 g = gimple_build_assign_with_ops (INTEGER_CST, lane,
806413d2 3849 build_int_cst (unsigned_type_node, 0));
3d483a94 3850 gimple_seq_add_stmt (ilist, g);
3851 for (int i = 0; i < 2; i++)
3852 if (llist[i])
3853 {
3854 tree vf = create_tmp_var (unsigned_type_node, NULL);
3855 g = gimple_build_call_internal (IFN_GOMP_SIMD_VF, 1, uid);
3856 gimple_call_set_lhs (g, vf);
3857 gimple_seq *seq = i == 0 ? ilist : dlist;
3858 gimple_seq_add_stmt (seq, g);
3859 tree t = build_int_cst (unsigned_type_node, 0);
806413d2 3860 g = gimple_build_assign_with_ops (INTEGER_CST, idx, t);
3d483a94 3861 gimple_seq_add_stmt (seq, g);
3862 tree body = create_artificial_label (UNKNOWN_LOCATION);
3863 tree header = create_artificial_label (UNKNOWN_LOCATION);
3864 tree end = create_artificial_label (UNKNOWN_LOCATION);
3865 gimple_seq_add_stmt (seq, gimple_build_goto (header));
3866 gimple_seq_add_stmt (seq, gimple_build_label (body));
3867 gimple_seq_add_seq (seq, llist[i]);
3868 t = build_int_cst (unsigned_type_node, 1);
3869 g = gimple_build_assign_with_ops (PLUS_EXPR, idx, idx, t);
3870 gimple_seq_add_stmt (seq, g);
3871 gimple_seq_add_stmt (seq, gimple_build_label (header));
3872 g = gimple_build_cond (LT_EXPR, idx, vf, body, end);
3873 gimple_seq_add_stmt (seq, g);
3874 gimple_seq_add_stmt (seq, gimple_build_label (end));
3875 }
3876 }
3877
1e8e9920 3878 /* The copyin sequence is not to be executed by the main thread, since
3879 that would result in self-copies. Perhaps not visible to scalars,
3880 but it certainly is to C++ operator=. */
3881 if (copyin_seq)
3882 {
b9a16870 3883 x = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM),
3884 0);
1e8e9920 3885 x = build2 (NE_EXPR, boolean_type_node, x,
3886 build_int_cst (TREE_TYPE (x), 0));
3887 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
3888 gimplify_and_add (x, ilist);
3889 }
3890
3891 /* If any copyin variable is passed by reference, we must ensure the
3892 master thread doesn't modify it before it is copied over in all
f49d7bb5 3893 threads. Similarly for variables in both firstprivate and
3894 lastprivate clauses we need to ensure the lastprivate copying
bc7bff74 3895 happens after firstprivate copying in all threads. And similarly
3896 for UDRs if initializer expression refers to omp_orig. */
3897 if (copyin_by_ref || lastprivate_firstprivate || reduction_omp_orig_ref)
3d483a94 3898 {
3899 /* Don't add any barrier for #pragma omp simd or
3900 #pragma omp distribute. */
3901 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
7c01fa6c 3902 || gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_FOR)
bc7bff74 3903 gimple_seq_add_stmt (ilist, build_omp_barrier (NULL_TREE));
3d483a94 3904 }
3905
3906 /* If max_vf is non-zero, then we can use only a vectorization factor
3907 up to the max_vf we chose. So stick it into the safelen clause. */
3908 if (max_vf)
3909 {
3910 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3911 OMP_CLAUSE_SAFELEN);
3912 if (c == NULL_TREE
c3f3b68d 3913 || (TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) == INTEGER_CST
3914 && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
3915 max_vf) == 1))
3d483a94 3916 {
3917 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_SAFELEN);
3918 OMP_CLAUSE_SAFELEN_EXPR (c) = build_int_cst (integer_type_node,
3919 max_vf);
3920 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
3921 gimple_omp_for_set_clauses (ctx->stmt, c);
3922 }
3923 }
1e8e9920 3924}
3925
773c5ba7 3926
1e8e9920 3927/* Generate code to implement the LASTPRIVATE clauses. This is used for
3928 both parallel and workshare constructs. PREDICATE may be NULL if it's
3929 always true. */
3930
3931static void
75a70cf9 3932lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
bc7bff74 3933 omp_context *ctx)
1e8e9920 3934{
3d483a94 3935 tree x, c, label = NULL, orig_clauses = clauses;
fd6481cf 3936 bool par_clauses = false;
3d483a94 3937 tree simduid = NULL, lastlane = NULL;
1e8e9920 3938
3d483a94 3939 /* Early exit if there are no lastprivate or linear clauses. */
3940 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
3941 if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LASTPRIVATE
3942 || (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LINEAR
3943 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses)))
3944 break;
1e8e9920 3945 if (clauses == NULL)
3946 {
3947 /* If this was a workshare clause, see if it had been combined
3948 with its parallel. In that case, look for the clauses on the
3949 parallel statement itself. */
3950 if (is_parallel_ctx (ctx))
3951 return;
3952
3953 ctx = ctx->outer;
3954 if (ctx == NULL || !is_parallel_ctx (ctx))
3955 return;
3956
75a70cf9 3957 clauses = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
1e8e9920 3958 OMP_CLAUSE_LASTPRIVATE);
3959 if (clauses == NULL)
3960 return;
fd6481cf 3961 par_clauses = true;
1e8e9920 3962 }
3963
75a70cf9 3964 if (predicate)
3965 {
1a91d914 3966 gcond *stmt;
75a70cf9 3967 tree label_true, arm1, arm2;
3968
e60a6f7b 3969 label = create_artificial_label (UNKNOWN_LOCATION);
3970 label_true = create_artificial_label (UNKNOWN_LOCATION);
75a70cf9 3971 arm1 = TREE_OPERAND (predicate, 0);
3972 arm2 = TREE_OPERAND (predicate, 1);
3973 gimplify_expr (&arm1, stmt_list, NULL, is_gimple_val, fb_rvalue);
3974 gimplify_expr (&arm2, stmt_list, NULL, is_gimple_val, fb_rvalue);
3975 stmt = gimple_build_cond (TREE_CODE (predicate), arm1, arm2,
3976 label_true, label);
3977 gimple_seq_add_stmt (stmt_list, stmt);
3978 gimple_seq_add_stmt (stmt_list, gimple_build_label (label_true));
3979 }
1e8e9920 3980
3d483a94 3981 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
10c55644 3982 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3d483a94 3983 {
3984 simduid = find_omp_clause (orig_clauses, OMP_CLAUSE__SIMDUID_);
3985 if (simduid)
3986 simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
3987 }
3988
fd6481cf 3989 for (c = clauses; c ;)
1e8e9920 3990 {
3991 tree var, new_var;
389dd41b 3992 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
1e8e9920 3993
3d483a94 3994 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
3995 || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3996 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
fd6481cf 3997 {
3998 var = OMP_CLAUSE_DECL (c);
3999 new_var = lookup_decl (var, ctx);
1e8e9920 4000
3d483a94 4001 if (simduid && DECL_HAS_VALUE_EXPR_P (new_var))
4002 {
4003 tree val = DECL_VALUE_EXPR (new_var);
4004 if (TREE_CODE (val) == ARRAY_REF
4005 && VAR_P (TREE_OPERAND (val, 0))
4006 && lookup_attribute ("omp simd array",
4007 DECL_ATTRIBUTES (TREE_OPERAND (val,
4008 0))))
4009 {
4010 if (lastlane == NULL)
4011 {
4012 lastlane = create_tmp_var (unsigned_type_node, NULL);
1a91d914 4013 gcall *g
3d483a94 4014 = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE,
4015 2, simduid,
4016 TREE_OPERAND (val, 1));
4017 gimple_call_set_lhs (g, lastlane);
4018 gimple_seq_add_stmt (stmt_list, g);
4019 }
4020 new_var = build4 (ARRAY_REF, TREE_TYPE (val),
4021 TREE_OPERAND (val, 0), lastlane,
4022 NULL_TREE, NULL_TREE);
4023 }
4024 }
4025
4026 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
4027 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
75a70cf9 4028 {
e3a19533 4029 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
75a70cf9 4030 gimple_seq_add_seq (stmt_list,
4031 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
3d483a94 4032 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) = NULL;
75a70cf9 4033 }
2b536a17 4034 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
4035 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
4036 {
4037 lower_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
4038 gimple_seq_add_seq (stmt_list,
4039 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c));
4040 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c) = NULL;
4041 }
1e8e9920 4042
fd6481cf 4043 x = build_outer_var_ref (var, ctx);
4044 if (is_reference (var))
182cf5a9 4045 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
fd6481cf 4046 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
75a70cf9 4047 gimplify_and_add (x, stmt_list);
fd6481cf 4048 }
4049 c = OMP_CLAUSE_CHAIN (c);
4050 if (c == NULL && !par_clauses)
4051 {
4052 /* If this was a workshare clause, see if it had been combined
4053 with its parallel. In that case, continue looking for the
4054 clauses also on the parallel statement itself. */
4055 if (is_parallel_ctx (ctx))
4056 break;
4057
4058 ctx = ctx->outer;
4059 if (ctx == NULL || !is_parallel_ctx (ctx))
4060 break;
4061
75a70cf9 4062 c = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
fd6481cf 4063 OMP_CLAUSE_LASTPRIVATE);
4064 par_clauses = true;
4065 }
1e8e9920 4066 }
4067
75a70cf9 4068 if (label)
4069 gimple_seq_add_stmt (stmt_list, gimple_build_label (label));
1e8e9920 4070}
4071
773c5ba7 4072
1e8e9920 4073/* Generate code to implement the REDUCTION clauses. */
4074
4075static void
75a70cf9 4076lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
1e8e9920 4077{
75a70cf9 4078 gimple_seq sub_seq = NULL;
4079 gimple stmt;
4080 tree x, c;
1e8e9920 4081 int count = 0;
4082
3d483a94 4083 /* SIMD reductions are handled in lower_rec_input_clauses. */
4084 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
10c55644 4085 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3d483a94 4086 return;
4087
1e8e9920 4088 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
4089 update in that case, otherwise use a lock. */
4090 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
55d6e7cd 4091 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
1e8e9920 4092 {
4093 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4094 {
bc7bff74 4095 /* Never use OMP_ATOMIC for array reductions or UDRs. */
1e8e9920 4096 count = -1;
4097 break;
4098 }
4099 count++;
4100 }
4101
4102 if (count == 0)
4103 return;
4104
4105 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4106 {
4107 tree var, ref, new_var;
4108 enum tree_code code;
389dd41b 4109 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
1e8e9920 4110
55d6e7cd 4111 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
1e8e9920 4112 continue;
4113
4114 var = OMP_CLAUSE_DECL (c);
4115 new_var = lookup_decl (var, ctx);
4116 if (is_reference (var))
182cf5a9 4117 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
1e8e9920 4118 ref = build_outer_var_ref (var, ctx);
4119 code = OMP_CLAUSE_REDUCTION_CODE (c);
773c5ba7 4120
4121 /* reduction(-:var) sums up the partial results, so it acts
4122 identically to reduction(+:var). */
1e8e9920 4123 if (code == MINUS_EXPR)
4124 code = PLUS_EXPR;
4125
4126 if (count == 1)
4127 {
389dd41b 4128 tree addr = build_fold_addr_expr_loc (clause_loc, ref);
1e8e9920 4129
4130 addr = save_expr (addr);
4131 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
389dd41b 4132 x = fold_build2_loc (clause_loc, code, TREE_TYPE (ref), ref, new_var);
1e8e9920 4133 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
75a70cf9 4134 gimplify_and_add (x, stmt_seqp);
1e8e9920 4135 return;
4136 }
4137
4138 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4139 {
4140 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
4141
bc7bff74 4142 if (is_reference (var)
4143 && !useless_type_conversion_p (TREE_TYPE (placeholder),
4144 TREE_TYPE (ref)))
389dd41b 4145 ref = build_fold_addr_expr_loc (clause_loc, ref);
1e8e9920 4146 SET_DECL_VALUE_EXPR (placeholder, ref);
4147 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
e3a19533 4148 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
75a70cf9 4149 gimple_seq_add_seq (&sub_seq, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
4150 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
1e8e9920 4151 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
4152 }
4153 else
4154 {
4155 x = build2 (code, TREE_TYPE (ref), ref, new_var);
4156 ref = build_outer_var_ref (var, ctx);
75a70cf9 4157 gimplify_assign (ref, x, &sub_seq);
1e8e9920 4158 }
4159 }
4160
b9a16870 4161 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START),
4162 0);
75a70cf9 4163 gimple_seq_add_stmt (stmt_seqp, stmt);
1e8e9920 4164
75a70cf9 4165 gimple_seq_add_seq (stmt_seqp, sub_seq);
1e8e9920 4166
b9a16870 4167 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END),
4168 0);
75a70cf9 4169 gimple_seq_add_stmt (stmt_seqp, stmt);
1e8e9920 4170}
4171
773c5ba7 4172
1e8e9920 4173/* Generate code to implement the COPYPRIVATE clauses. */
4174
4175static void
75a70cf9 4176lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist,
1e8e9920 4177 omp_context *ctx)
4178{
4179 tree c;
4180
4181 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4182 {
cb561506 4183 tree var, new_var, ref, x;
1e8e9920 4184 bool by_ref;
389dd41b 4185 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
1e8e9920 4186
55d6e7cd 4187 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
1e8e9920 4188 continue;
4189
4190 var = OMP_CLAUSE_DECL (c);
e8a588af 4191 by_ref = use_pointer_for_field (var, NULL);
1e8e9920 4192
4193 ref = build_sender_ref (var, ctx);
cb561506 4194 x = new_var = lookup_decl_in_outer_ctx (var, ctx);
4195 if (by_ref)
4196 {
4197 x = build_fold_addr_expr_loc (clause_loc, new_var);
4198 x = fold_convert_loc (clause_loc, TREE_TYPE (ref), x);
4199 }
75a70cf9 4200 gimplify_assign (ref, x, slist);
1e8e9920 4201
cb561506 4202 ref = build_receiver_ref (var, false, ctx);
4203 if (by_ref)
4204 {
4205 ref = fold_convert_loc (clause_loc,
4206 build_pointer_type (TREE_TYPE (new_var)),
4207 ref);
4208 ref = build_fold_indirect_ref_loc (clause_loc, ref);
4209 }
1e8e9920 4210 if (is_reference (var))
4211 {
cb561506 4212 ref = fold_convert_loc (clause_loc, TREE_TYPE (new_var), ref);
182cf5a9 4213 ref = build_simple_mem_ref_loc (clause_loc, ref);
4214 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
1e8e9920 4215 }
cb561506 4216 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, ref);
1e8e9920 4217 gimplify_and_add (x, rlist);
4218 }
4219}
4220
773c5ba7 4221
1e8e9920 4222/* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
4223 and REDUCTION from the sender (aka parent) side. */
4224
4225static void
75a70cf9 4226lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
4227 omp_context *ctx)
1e8e9920 4228{
4229 tree c;
4230
4231 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4232 {
773c5ba7 4233 tree val, ref, x, var;
1e8e9920 4234 bool by_ref, do_in = false, do_out = false;
389dd41b 4235 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
1e8e9920 4236
55d6e7cd 4237 switch (OMP_CLAUSE_CODE (c))
1e8e9920 4238 {
fd6481cf 4239 case OMP_CLAUSE_PRIVATE:
4240 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
4241 break;
4242 continue;
1e8e9920 4243 case OMP_CLAUSE_FIRSTPRIVATE:
4244 case OMP_CLAUSE_COPYIN:
4245 case OMP_CLAUSE_LASTPRIVATE:
4246 case OMP_CLAUSE_REDUCTION:
bc7bff74 4247 case OMP_CLAUSE__LOOPTEMP_:
1e8e9920 4248 break;
4249 default:
4250 continue;
4251 }
4252
87b31375 4253 val = OMP_CLAUSE_DECL (c);
4254 var = lookup_decl_in_outer_ctx (val, ctx);
773c5ba7 4255
f49d7bb5 4256 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
4257 && is_global_var (var))
4258 continue;
1e8e9920 4259 if (is_variable_sized (val))
4260 continue;
e8a588af 4261 by_ref = use_pointer_for_field (val, NULL);
1e8e9920 4262
55d6e7cd 4263 switch (OMP_CLAUSE_CODE (c))
1e8e9920 4264 {
fd6481cf 4265 case OMP_CLAUSE_PRIVATE:
1e8e9920 4266 case OMP_CLAUSE_FIRSTPRIVATE:
4267 case OMP_CLAUSE_COPYIN:
bc7bff74 4268 case OMP_CLAUSE__LOOPTEMP_:
1e8e9920 4269 do_in = true;
4270 break;
4271
4272 case OMP_CLAUSE_LASTPRIVATE:
4273 if (by_ref || is_reference (val))
4274 {
4275 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4276 continue;
4277 do_in = true;
4278 }
4279 else
fd6481cf 4280 {
4281 do_out = true;
4282 if (lang_hooks.decls.omp_private_outer_ref (val))
4283 do_in = true;
4284 }
1e8e9920 4285 break;
4286
4287 case OMP_CLAUSE_REDUCTION:
4288 do_in = true;
4289 do_out = !(by_ref || is_reference (val));
4290 break;
4291
4292 default:
4293 gcc_unreachable ();
4294 }
4295
4296 if (do_in)
4297 {
4298 ref = build_sender_ref (val, ctx);
389dd41b 4299 x = by_ref ? build_fold_addr_expr_loc (clause_loc, var) : var;
75a70cf9 4300 gimplify_assign (ref, x, ilist);
fd6481cf 4301 if (is_task_ctx (ctx))
4302 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref, 1)) = NULL;
1e8e9920 4303 }
773c5ba7 4304
1e8e9920 4305 if (do_out)
4306 {
4307 ref = build_sender_ref (val, ctx);
75a70cf9 4308 gimplify_assign (var, ref, olist);
1e8e9920 4309 }
4310 }
4311}
4312
75a70cf9 4313/* Generate code to implement SHARED from the sender (aka parent)
4314 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
4315 list things that got automatically shared. */
1e8e9920 4316
4317static void
75a70cf9 4318lower_send_shared_vars (gimple_seq *ilist, gimple_seq *olist, omp_context *ctx)
1e8e9920 4319{
fd6481cf 4320 tree var, ovar, nvar, f, x, record_type;
1e8e9920 4321
4322 if (ctx->record_type == NULL)
4323 return;
773c5ba7 4324
fd6481cf 4325 record_type = ctx->srecord_type ? ctx->srecord_type : ctx->record_type;
1767a056 4326 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
1e8e9920 4327 {
4328 ovar = DECL_ABSTRACT_ORIGIN (f);
4329 nvar = maybe_lookup_decl (ovar, ctx);
4330 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
4331 continue;
4332
773c5ba7 4333 /* If CTX is a nested parallel directive. Find the immediately
4334 enclosing parallel or workshare construct that contains a
4335 mapping for OVAR. */
87b31375 4336 var = lookup_decl_in_outer_ctx (ovar, ctx);
773c5ba7 4337
e8a588af 4338 if (use_pointer_for_field (ovar, ctx))
1e8e9920 4339 {
4340 x = build_sender_ref (ovar, ctx);
773c5ba7 4341 var = build_fold_addr_expr (var);
75a70cf9 4342 gimplify_assign (x, var, ilist);
1e8e9920 4343 }
4344 else
4345 {
4346 x = build_sender_ref (ovar, ctx);
75a70cf9 4347 gimplify_assign (x, var, ilist);
1e8e9920 4348
d2263ebb 4349 if (!TREE_READONLY (var)
4350 /* We don't need to receive a new reference to a result
4351 or parm decl. In fact we may not store to it as we will
4352 invalidate any pending RSO and generate wrong gimple
4353 during inlining. */
4354 && !((TREE_CODE (var) == RESULT_DECL
4355 || TREE_CODE (var) == PARM_DECL)
4356 && DECL_BY_REFERENCE (var)))
fd6481cf 4357 {
4358 x = build_sender_ref (ovar, ctx);
75a70cf9 4359 gimplify_assign (var, x, olist);
fd6481cf 4360 }
1e8e9920 4361 }
4362 }
4363}
4364
75a70cf9 4365
4366/* A convenience function to build an empty GIMPLE_COND with just the
4367 condition. */
4368
1a91d914 4369static gcond *
75a70cf9 4370gimple_build_cond_empty (tree cond)
4371{
4372 enum tree_code pred_code;
4373 tree lhs, rhs;
4374
4375 gimple_cond_get_ops_from_tree (cond, &pred_code, &lhs, &rhs);
4376 return gimple_build_cond (pred_code, lhs, rhs, NULL_TREE, NULL_TREE);
4377}
4378
4379
48e1416a 4380/* Build the function calls to GOMP_parallel_start etc to actually
773c5ba7 4381 generate the parallel operation. REGION is the parallel region
4382 being expanded. BB is the block where to insert the code. WS_ARGS
4383 will be set if this is a call to a combined parallel+workshare
4384 construct, it contains the list of additional arguments needed by
4385 the workshare construct. */
1e8e9920 4386
4387static void
61e47ac8 4388expand_parallel_call (struct omp_region *region, basic_block bb,
1a91d914 4389 gomp_parallel *entry_stmt,
4390 vec<tree, va_gc> *ws_args)
1e8e9920 4391{
bc7bff74 4392 tree t, t1, t2, val, cond, c, clauses, flags;
75a70cf9 4393 gimple_stmt_iterator gsi;
4394 gimple stmt;
b9a16870 4395 enum built_in_function start_ix;
4396 int start_ix2;
389dd41b 4397 location_t clause_loc;
f1f41a6c 4398 vec<tree, va_gc> *args;
773c5ba7 4399
75a70cf9 4400 clauses = gimple_omp_parallel_clauses (entry_stmt);
773c5ba7 4401
bc7bff74 4402 /* Determine what flavor of GOMP_parallel we will be
773c5ba7 4403 emitting. */
bc7bff74 4404 start_ix = BUILT_IN_GOMP_PARALLEL;
773c5ba7 4405 if (is_combined_parallel (region))
4406 {
61e47ac8 4407 switch (region->inner->type)
773c5ba7 4408 {
75a70cf9 4409 case GIMPLE_OMP_FOR:
fd6481cf 4410 gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
bc7bff74 4411 start_ix2 = ((int)BUILT_IN_GOMP_PARALLEL_LOOP_STATIC
b9a16870 4412 + (region->inner->sched_kind
4413 == OMP_CLAUSE_SCHEDULE_RUNTIME
4414 ? 3 : region->inner->sched_kind));
4415 start_ix = (enum built_in_function)start_ix2;
61e47ac8 4416 break;
75a70cf9 4417 case GIMPLE_OMP_SECTIONS:
bc7bff74 4418 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS;
61e47ac8 4419 break;
4420 default:
4421 gcc_unreachable ();
773c5ba7 4422 }
773c5ba7 4423 }
1e8e9920 4424
4425 /* By default, the value of NUM_THREADS is zero (selected at run time)
4426 and there is no conditional. */
4427 cond = NULL_TREE;
4428 val = build_int_cst (unsigned_type_node, 0);
bc7bff74 4429 flags = build_int_cst (unsigned_type_node, 0);
1e8e9920 4430
4431 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
4432 if (c)
4433 cond = OMP_CLAUSE_IF_EXPR (c);
4434
4435 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
4436 if (c)
389dd41b 4437 {
4438 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
4439 clause_loc = OMP_CLAUSE_LOCATION (c);
4440 }
4441 else
4442 clause_loc = gimple_location (entry_stmt);
1e8e9920 4443
bc7bff74 4444 c = find_omp_clause (clauses, OMP_CLAUSE_PROC_BIND);
4445 if (c)
4446 flags = build_int_cst (unsigned_type_node, OMP_CLAUSE_PROC_BIND_KIND (c));
4447
1e8e9920 4448 /* Ensure 'val' is of the correct type. */
389dd41b 4449 val = fold_convert_loc (clause_loc, unsigned_type_node, val);
1e8e9920 4450
4451 /* If we found the clause 'if (cond)', build either
4452 (cond != 0) or (cond ? val : 1u). */
4453 if (cond)
4454 {
773c5ba7 4455 cond = gimple_boolify (cond);
4456
1e8e9920 4457 if (integer_zerop (val))
389dd41b 4458 val = fold_build2_loc (clause_loc,
4459 EQ_EXPR, unsigned_type_node, cond,
79acaae1 4460 build_int_cst (TREE_TYPE (cond), 0));
1e8e9920 4461 else
773c5ba7 4462 {
4463 basic_block cond_bb, then_bb, else_bb;
79acaae1 4464 edge e, e_then, e_else;
75a70cf9 4465 tree tmp_then, tmp_else, tmp_join, tmp_var;
79acaae1 4466
4467 tmp_var = create_tmp_var (TREE_TYPE (val), NULL);
4468 if (gimple_in_ssa_p (cfun))
4469 {
75a70cf9 4470 tmp_then = make_ssa_name (tmp_var, NULL);
4471 tmp_else = make_ssa_name (tmp_var, NULL);
4472 tmp_join = make_ssa_name (tmp_var, NULL);
79acaae1 4473 }
4474 else
4475 {
4476 tmp_then = tmp_var;
4477 tmp_else = tmp_var;
4478 tmp_join = tmp_var;
4479 }
773c5ba7 4480
773c5ba7 4481 e = split_block (bb, NULL);
4482 cond_bb = e->src;
4483 bb = e->dest;
4484 remove_edge (e);
4485
4486 then_bb = create_empty_bb (cond_bb);
4487 else_bb = create_empty_bb (then_bb);
79acaae1 4488 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
4489 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
773c5ba7 4490
75a70cf9 4491 stmt = gimple_build_cond_empty (cond);
4492 gsi = gsi_start_bb (cond_bb);
4493 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
773c5ba7 4494
75a70cf9 4495 gsi = gsi_start_bb (then_bb);
4496 stmt = gimple_build_assign (tmp_then, val);
4497 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
773c5ba7 4498
75a70cf9 4499 gsi = gsi_start_bb (else_bb);
4500 stmt = gimple_build_assign
4501 (tmp_else, build_int_cst (unsigned_type_node, 1));
4502 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
773c5ba7 4503
4504 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
4505 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
b3083327 4506 add_bb_to_loop (then_bb, cond_bb->loop_father);
4507 add_bb_to_loop (else_bb, cond_bb->loop_father);
79acaae1 4508 e_then = make_edge (then_bb, bb, EDGE_FALLTHRU);
4509 e_else = make_edge (else_bb, bb, EDGE_FALLTHRU);
773c5ba7 4510
79acaae1 4511 if (gimple_in_ssa_p (cfun))
4512 {
1a91d914 4513 gphi *phi = create_phi_node (tmp_join, bb);
60d535d2 4514 add_phi_arg (phi, tmp_then, e_then, UNKNOWN_LOCATION);
4515 add_phi_arg (phi, tmp_else, e_else, UNKNOWN_LOCATION);
79acaae1 4516 }
4517
4518 val = tmp_join;
773c5ba7 4519 }
4520
75a70cf9 4521 gsi = gsi_start_bb (bb);
4522 val = force_gimple_operand_gsi (&gsi, val, true, NULL_TREE,
4523 false, GSI_CONTINUE_LINKING);
1e8e9920 4524 }
4525
75a70cf9 4526 gsi = gsi_last_bb (bb);
4527 t = gimple_omp_parallel_data_arg (entry_stmt);
1e8e9920 4528 if (t == NULL)
c2f47e15 4529 t1 = null_pointer_node;
1e8e9920 4530 else
c2f47e15 4531 t1 = build_fold_addr_expr (t);
75a70cf9 4532 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
773c5ba7 4533
bc7bff74 4534 vec_alloc (args, 4 + vec_safe_length (ws_args));
f1f41a6c 4535 args->quick_push (t2);
4536 args->quick_push (t1);
4537 args->quick_push (val);
4538 if (ws_args)
4539 args->splice (*ws_args);
bc7bff74 4540 args->quick_push (flags);
414c3a2c 4541
4542 t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
b9a16870 4543 builtin_decl_explicit (start_ix), args);
773c5ba7 4544
75a70cf9 4545 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4546 false, GSI_CONTINUE_LINKING);
1e8e9920 4547}
4548
40750995 4549/* Insert a function call whose name is FUNC_NAME with the information from
4550 ENTRY_STMT into the basic_block BB. */
4551
4552static void
1a91d914 4553expand_cilk_for_call (basic_block bb, gomp_parallel *entry_stmt,
40750995 4554 vec <tree, va_gc> *ws_args)
4555{
4556 tree t, t1, t2;
4557 gimple_stmt_iterator gsi;
4558 vec <tree, va_gc> *args;
4559
4560 gcc_assert (vec_safe_length (ws_args) == 2);
4561 tree func_name = (*ws_args)[0];
4562 tree grain = (*ws_args)[1];
4563
4564 tree clauses = gimple_omp_parallel_clauses (entry_stmt);
4565 tree count = find_omp_clause (clauses, OMP_CLAUSE__CILK_FOR_COUNT_);
4566 gcc_assert (count != NULL_TREE);
4567 count = OMP_CLAUSE_OPERAND (count, 0);
4568
4569 gsi = gsi_last_bb (bb);
4570 t = gimple_omp_parallel_data_arg (entry_stmt);
4571 if (t == NULL)
4572 t1 = null_pointer_node;
4573 else
4574 t1 = build_fold_addr_expr (t);
4575 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
4576
4577 vec_alloc (args, 4);
4578 args->quick_push (t2);
4579 args->quick_push (t1);
4580 args->quick_push (count);
4581 args->quick_push (grain);
4582 t = build_call_expr_loc_vec (UNKNOWN_LOCATION, func_name, args);
4583
4584 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, false,
4585 GSI_CONTINUE_LINKING);
4586}
773c5ba7 4587
fd6481cf 4588/* Build the function call to GOMP_task to actually
4589 generate the task operation. BB is the block where to insert the code. */
4590
4591static void
1a91d914 4592expand_task_call (basic_block bb, gomp_task *entry_stmt)
fd6481cf 4593{
bc7bff74 4594 tree t, t1, t2, t3, flags, cond, c, c2, clauses, depend;
75a70cf9 4595 gimple_stmt_iterator gsi;
389dd41b 4596 location_t loc = gimple_location (entry_stmt);
fd6481cf 4597
75a70cf9 4598 clauses = gimple_omp_task_clauses (entry_stmt);
fd6481cf 4599
fd6481cf 4600 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
4601 if (c)
4602 cond = gimple_boolify (OMP_CLAUSE_IF_EXPR (c));
4603 else
4604 cond = boolean_true_node;
4605
4606 c = find_omp_clause (clauses, OMP_CLAUSE_UNTIED);
2169f33b 4607 c2 = find_omp_clause (clauses, OMP_CLAUSE_MERGEABLE);
bc7bff74 4608 depend = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
2169f33b 4609 flags = build_int_cst (unsigned_type_node,
bc7bff74 4610 (c ? 1 : 0) + (c2 ? 4 : 0) + (depend ? 8 : 0));
2169f33b 4611
4612 c = find_omp_clause (clauses, OMP_CLAUSE_FINAL);
4613 if (c)
4614 {
4615 c = gimple_boolify (OMP_CLAUSE_FINAL_EXPR (c));
4616 c = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, c,
4617 build_int_cst (unsigned_type_node, 2),
4618 build_int_cst (unsigned_type_node, 0));
4619 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node, flags, c);
4620 }
bc7bff74 4621 if (depend)
4622 depend = OMP_CLAUSE_DECL (depend);
4623 else
4624 depend = build_int_cst (ptr_type_node, 0);
fd6481cf 4625
75a70cf9 4626 gsi = gsi_last_bb (bb);
4627 t = gimple_omp_task_data_arg (entry_stmt);
fd6481cf 4628 if (t == NULL)
4629 t2 = null_pointer_node;
4630 else
389dd41b 4631 t2 = build_fold_addr_expr_loc (loc, t);
4632 t1 = build_fold_addr_expr_loc (loc, gimple_omp_task_child_fn (entry_stmt));
75a70cf9 4633 t = gimple_omp_task_copy_fn (entry_stmt);
fd6481cf 4634 if (t == NULL)
4635 t3 = null_pointer_node;
4636 else
389dd41b 4637 t3 = build_fold_addr_expr_loc (loc, t);
fd6481cf 4638
b9a16870 4639 t = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK),
bc7bff74 4640 8, t1, t2, t3,
75a70cf9 4641 gimple_omp_task_arg_size (entry_stmt),
bc7bff74 4642 gimple_omp_task_arg_align (entry_stmt), cond, flags,
4643 depend);
fd6481cf 4644
75a70cf9 4645 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4646 false, GSI_CONTINUE_LINKING);
fd6481cf 4647}
4648
4649
75a70cf9 4650/* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
4651 catch handler and return it. This prevents programs from violating the
4652 structured block semantics with throws. */
1e8e9920 4653
75a70cf9 4654static gimple_seq
4655maybe_catch_exception (gimple_seq body)
1e8e9920 4656{
e38def9c 4657 gimple g;
4658 tree decl;
1e8e9920 4659
4660 if (!flag_exceptions)
75a70cf9 4661 return body;
1e8e9920 4662
596981c8 4663 if (lang_hooks.eh_protect_cleanup_actions != NULL)
4664 decl = lang_hooks.eh_protect_cleanup_actions ();
1e8e9920 4665 else
b9a16870 4666 decl = builtin_decl_explicit (BUILT_IN_TRAP);
75a70cf9 4667
e38def9c 4668 g = gimple_build_eh_must_not_throw (decl);
4669 g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g),
75a70cf9 4670 GIMPLE_TRY_CATCH);
1e8e9920 4671
e38def9c 4672 return gimple_seq_alloc_with_stmt (g);
1e8e9920 4673}
4674
773c5ba7 4675/* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
1e8e9920 4676
773c5ba7 4677static tree
f1f41a6c 4678vec2chain (vec<tree, va_gc> *v)
1e8e9920 4679{
2ab2ce89 4680 tree chain = NULL_TREE, t;
4681 unsigned ix;
1e8e9920 4682
f1f41a6c 4683 FOR_EACH_VEC_SAFE_ELT_REVERSE (v, ix, t)
773c5ba7 4684 {
1767a056 4685 DECL_CHAIN (t) = chain;
2ab2ce89 4686 chain = t;
773c5ba7 4687 }
1e8e9920 4688
2ab2ce89 4689 return chain;
773c5ba7 4690}
1e8e9920 4691
1e8e9920 4692
773c5ba7 4693/* Remove barriers in REGION->EXIT's block. Note that this is only
75a70cf9 4694 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
4695 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
4696 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
773c5ba7 4697 removed. */
1e8e9920 4698
773c5ba7 4699static void
4700remove_exit_barrier (struct omp_region *region)
4701{
75a70cf9 4702 gimple_stmt_iterator gsi;
773c5ba7 4703 basic_block exit_bb;
61e47ac8 4704 edge_iterator ei;
4705 edge e;
75a70cf9 4706 gimple stmt;
4a04f4b4 4707 int any_addressable_vars = -1;
1e8e9920 4708
61e47ac8 4709 exit_bb = region->exit;
1e8e9920 4710
5056ba1a 4711 /* If the parallel region doesn't return, we don't have REGION->EXIT
4712 block at all. */
4713 if (! exit_bb)
4714 return;
4715
75a70cf9 4716 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
4717 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
61e47ac8 4718 statements that can appear in between are extremely limited -- no
4719 memory operations at all. Here, we allow nothing at all, so the
75a70cf9 4720 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
4721 gsi = gsi_last_bb (exit_bb);
4722 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
4723 gsi_prev (&gsi);
4724 if (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
773c5ba7 4725 return;
1e8e9920 4726
61e47ac8 4727 FOR_EACH_EDGE (e, ei, exit_bb->preds)
4728 {
75a70cf9 4729 gsi = gsi_last_bb (e->src);
4730 if (gsi_end_p (gsi))
61e47ac8 4731 continue;
75a70cf9 4732 stmt = gsi_stmt (gsi);
4a04f4b4 4733 if (gimple_code (stmt) == GIMPLE_OMP_RETURN
4734 && !gimple_omp_return_nowait_p (stmt))
4735 {
4736 /* OpenMP 3.0 tasks unfortunately prevent this optimization
4737 in many cases. If there could be tasks queued, the barrier
4738 might be needed to let the tasks run before some local
4739 variable of the parallel that the task uses as shared
4740 runs out of scope. The task can be spawned either
4741 from within current function (this would be easy to check)
4742 or from some function it calls and gets passed an address
4743 of such a variable. */
4744 if (any_addressable_vars < 0)
4745 {
1a91d914 4746 gomp_parallel *parallel_stmt
4747 = as_a <gomp_parallel *> (last_stmt (region->entry));
4a04f4b4 4748 tree child_fun = gimple_omp_parallel_child_fn (parallel_stmt);
2ab2ce89 4749 tree local_decls, block, decl;
4750 unsigned ix;
4a04f4b4 4751
4752 any_addressable_vars = 0;
2ab2ce89 4753 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun), ix, decl)
4754 if (TREE_ADDRESSABLE (decl))
4a04f4b4 4755 {
4756 any_addressable_vars = 1;
4757 break;
4758 }
4759 for (block = gimple_block (stmt);
4760 !any_addressable_vars
4761 && block
4762 && TREE_CODE (block) == BLOCK;
4763 block = BLOCK_SUPERCONTEXT (block))
4764 {
4765 for (local_decls = BLOCK_VARS (block);
4766 local_decls;
1767a056 4767 local_decls = DECL_CHAIN (local_decls))
4a04f4b4 4768 if (TREE_ADDRESSABLE (local_decls))
4769 {
4770 any_addressable_vars = 1;
4771 break;
4772 }
4773 if (block == gimple_block (parallel_stmt))
4774 break;
4775 }
4776 }
4777 if (!any_addressable_vars)
4778 gimple_omp_return_set_nowait (stmt);
4779 }
61e47ac8 4780 }
1e8e9920 4781}
4782
61e47ac8 4783static void
4784remove_exit_barriers (struct omp_region *region)
4785{
75a70cf9 4786 if (region->type == GIMPLE_OMP_PARALLEL)
61e47ac8 4787 remove_exit_barrier (region);
4788
4789 if (region->inner)
4790 {
4791 region = region->inner;
4792 remove_exit_barriers (region);
4793 while (region->next)
4794 {
4795 region = region->next;
4796 remove_exit_barriers (region);
4797 }
4798 }
4799}
773c5ba7 4800
658b4427 4801/* Optimize omp_get_thread_num () and omp_get_num_threads ()
4802 calls. These can't be declared as const functions, but
4803 within one parallel body they are constant, so they can be
4804 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
fd6481cf 4805 which are declared const. Similarly for task body, except
4806 that in untied task omp_get_thread_num () can change at any task
4807 scheduling point. */
658b4427 4808
4809static void
75a70cf9 4810optimize_omp_library_calls (gimple entry_stmt)
658b4427 4811{
4812 basic_block bb;
75a70cf9 4813 gimple_stmt_iterator gsi;
b9a16870 4814 tree thr_num_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
4815 tree thr_num_id = DECL_ASSEMBLER_NAME (thr_num_tree);
4816 tree num_thr_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
4817 tree num_thr_id = DECL_ASSEMBLER_NAME (num_thr_tree);
75a70cf9 4818 bool untied_task = (gimple_code (entry_stmt) == GIMPLE_OMP_TASK
4819 && find_omp_clause (gimple_omp_task_clauses (entry_stmt),
fd6481cf 4820 OMP_CLAUSE_UNTIED) != NULL);
658b4427 4821
fc00614f 4822 FOR_EACH_BB_FN (bb, cfun)
75a70cf9 4823 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
658b4427 4824 {
75a70cf9 4825 gimple call = gsi_stmt (gsi);
658b4427 4826 tree decl;
4827
75a70cf9 4828 if (is_gimple_call (call)
4829 && (decl = gimple_call_fndecl (call))
658b4427 4830 && DECL_EXTERNAL (decl)
4831 && TREE_PUBLIC (decl)
4832 && DECL_INITIAL (decl) == NULL)
4833 {
4834 tree built_in;
4835
4836 if (DECL_NAME (decl) == thr_num_id)
fd6481cf 4837 {
4838 /* In #pragma omp task untied omp_get_thread_num () can change
4839 during the execution of the task region. */
4840 if (untied_task)
4841 continue;
b9a16870 4842 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
fd6481cf 4843 }
658b4427 4844 else if (DECL_NAME (decl) == num_thr_id)
b9a16870 4845 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
658b4427 4846 else
4847 continue;
4848
4849 if (DECL_ASSEMBLER_NAME (decl) != DECL_ASSEMBLER_NAME (built_in)
75a70cf9 4850 || gimple_call_num_args (call) != 0)
658b4427 4851 continue;
4852
4853 if (flag_exceptions && !TREE_NOTHROW (decl))
4854 continue;
4855
4856 if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
1ea6a73c 4857 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl)),
4858 TREE_TYPE (TREE_TYPE (built_in))))
658b4427 4859 continue;
4860
0acacf9e 4861 gimple_call_set_fndecl (call, built_in);
658b4427 4862 }
4863 }
4864}
4865
8e6b4515 4866/* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
4867 regimplified. */
4868
4869static tree
4870expand_omp_regimplify_p (tree *tp, int *walk_subtrees, void *)
4871{
4872 tree t = *tp;
4873
4874 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
4875 if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t))
4876 return t;
4877
4878 if (TREE_CODE (t) == ADDR_EXPR)
4879 recompute_tree_invariant_for_addr_expr (t);
4880
4881 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
4882 return NULL_TREE;
4883}
4884
3d483a94 4885/* Prepend TO = FROM assignment before *GSI_P. */
4886
4887static void
4888expand_omp_build_assign (gimple_stmt_iterator *gsi_p, tree to, tree from)
4889{
4890 bool simple_p = DECL_P (to) && TREE_ADDRESSABLE (to);
4891 from = force_gimple_operand_gsi (gsi_p, from, simple_p, NULL_TREE,
4892 true, GSI_SAME_STMT);
4893 gimple stmt = gimple_build_assign (to, from);
4894 gsi_insert_before (gsi_p, stmt, GSI_SAME_STMT);
4895 if (walk_tree (&from, expand_omp_regimplify_p, NULL, NULL)
4896 || walk_tree (&to, expand_omp_regimplify_p, NULL, NULL))
4897 {
4898 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
4899 gimple_regimplify_operands (stmt, &gsi);
4900 }
4901}
4902
fd6481cf 4903/* Expand the OpenMP parallel or task directive starting at REGION. */
1e8e9920 4904
4905static void
fd6481cf 4906expand_omp_taskreg (struct omp_region *region)
1e8e9920 4907{
773c5ba7 4908 basic_block entry_bb, exit_bb, new_bb;
87d4aa85 4909 struct function *child_cfun;
414c3a2c 4910 tree child_fn, block, t;
75a70cf9 4911 gimple_stmt_iterator gsi;
4912 gimple entry_stmt, stmt;
773c5ba7 4913 edge e;
f1f41a6c 4914 vec<tree, va_gc> *ws_args;
773c5ba7 4915
61e47ac8 4916 entry_stmt = last_stmt (region->entry);
75a70cf9 4917 child_fn = gimple_omp_taskreg_child_fn (entry_stmt);
773c5ba7 4918 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
773c5ba7 4919
61e47ac8 4920 entry_bb = region->entry;
4921 exit_bb = region->exit;
773c5ba7 4922
40750995 4923 bool is_cilk_for
4924 = (flag_cilkplus
4925 && gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL
4926 && find_omp_clause (gimple_omp_parallel_clauses (entry_stmt),
4927 OMP_CLAUSE__CILK_FOR_COUNT_) != NULL_TREE);
4928
4929 if (is_cilk_for)
4930 /* If it is a _Cilk_for statement, it is modelled *like* a parallel for,
4931 and the inner statement contains the name of the built-in function
4932 and grain. */
4933 ws_args = region->inner->ws_args;
4934 else if (is_combined_parallel (region))
61e47ac8 4935 ws_args = region->ws_args;
773c5ba7 4936 else
414c3a2c 4937 ws_args = NULL;
1e8e9920 4938
61e47ac8 4939 if (child_cfun->cfg)
1e8e9920 4940 {
773c5ba7 4941 /* Due to inlining, it may happen that we have already outlined
4942 the region, in which case all we need to do is make the
4943 sub-graph unreachable and emit the parallel call. */
4944 edge entry_succ_e, exit_succ_e;
773c5ba7 4945
4946 entry_succ_e = single_succ_edge (entry_bb);
773c5ba7 4947
75a70cf9 4948 gsi = gsi_last_bb (entry_bb);
4949 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_PARALLEL
4950 || gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_TASK);
4951 gsi_remove (&gsi, true);
773c5ba7 4952
4953 new_bb = entry_bb;
03ed154b 4954 if (exit_bb)
4955 {
4956 exit_succ_e = single_succ_edge (exit_bb);
4957 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
4958 }
79acaae1 4959 remove_edge_and_dominated_blocks (entry_succ_e);
1e8e9920 4960 }
773c5ba7 4961 else
4962 {
501bdd19 4963 unsigned srcidx, dstidx, num;
2ab2ce89 4964
773c5ba7 4965 /* If the parallel region needs data sent from the parent
3480139d 4966 function, then the very first statement (except possible
4967 tree profile counter updates) of the parallel body
773c5ba7 4968 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
4969 &.OMP_DATA_O is passed as an argument to the child function,
4970 we need to replace it with the argument as seen by the child
4971 function.
4972
4973 In most cases, this will end up being the identity assignment
4974 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
4975 a function call that has been inlined, the original PARM_DECL
4976 .OMP_DATA_I may have been converted into a different local
4977 variable. In which case, we need to keep the assignment. */
75a70cf9 4978 if (gimple_omp_taskreg_data_arg (entry_stmt))
773c5ba7 4979 {
4980 basic_block entry_succ_bb = single_succ (entry_bb);
75a70cf9 4981 tree arg, narg;
4982 gimple parcopy_stmt = NULL;
1e8e9920 4983
75a70cf9 4984 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
3480139d 4985 {
75a70cf9 4986 gimple stmt;
3480139d 4987
75a70cf9 4988 gcc_assert (!gsi_end_p (gsi));
4989 stmt = gsi_stmt (gsi);
4990 if (gimple_code (stmt) != GIMPLE_ASSIGN)
cc6b725b 4991 continue;
4992
75a70cf9 4993 if (gimple_num_ops (stmt) == 2)
3480139d 4994 {
75a70cf9 4995 tree arg = gimple_assign_rhs1 (stmt);
4996
4997 /* We're ignore the subcode because we're
4998 effectively doing a STRIP_NOPS. */
4999
5000 if (TREE_CODE (arg) == ADDR_EXPR
5001 && TREE_OPERAND (arg, 0)
5002 == gimple_omp_taskreg_data_arg (entry_stmt))
5003 {
5004 parcopy_stmt = stmt;
5005 break;
5006 }
3480139d 5007 }
5008 }
79acaae1 5009
75a70cf9 5010 gcc_assert (parcopy_stmt != NULL);
79acaae1 5011 arg = DECL_ARGUMENTS (child_fn);
5012
5013 if (!gimple_in_ssa_p (cfun))
5014 {
75a70cf9 5015 if (gimple_assign_lhs (parcopy_stmt) == arg)
5016 gsi_remove (&gsi, true);
79acaae1 5017 else
75a70cf9 5018 {
5019 /* ?? Is setting the subcode really necessary ?? */
5020 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (arg));
5021 gimple_assign_set_rhs1 (parcopy_stmt, arg);
5022 }
79acaae1 5023 }
5024 else
5025 {
5026 /* If we are in ssa form, we must load the value from the default
5027 definition of the argument. That should not be defined now,
5028 since the argument is not used uninitialized. */
c6dfe037 5029 gcc_assert (ssa_default_def (cfun, arg) == NULL);
75a70cf9 5030 narg = make_ssa_name (arg, gimple_build_nop ());
c6dfe037 5031 set_ssa_default_def (cfun, arg, narg);
75a70cf9 5032 /* ?? Is setting the subcode really necessary ?? */
5033 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (narg));
5034 gimple_assign_set_rhs1 (parcopy_stmt, narg);
79acaae1 5035 update_stmt (parcopy_stmt);
5036 }
773c5ba7 5037 }
5038
5039 /* Declare local variables needed in CHILD_CFUN. */
5040 block = DECL_INITIAL (child_fn);
2ab2ce89 5041 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
e1a7ccb9 5042 /* The gimplifier could record temporaries in parallel/task block
5043 rather than in containing function's local_decls chain,
5044 which would mean cgraph missed finalizing them. Do it now. */
1767a056 5045 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
e1a7ccb9 5046 if (TREE_CODE (t) == VAR_DECL
5047 && TREE_STATIC (t)
5048 && !DECL_EXTERNAL (t))
97221fd7 5049 varpool_node::finalize_decl (t);
75a70cf9 5050 DECL_SAVED_TREE (child_fn) = NULL;
e3a19533 5051 /* We'll create a CFG for child_fn, so no gimple body is needed. */
5052 gimple_set_body (child_fn, NULL);
1d22f541 5053 TREE_USED (block) = 1;
773c5ba7 5054
79acaae1 5055 /* Reset DECL_CONTEXT on function arguments. */
1767a056 5056 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
773c5ba7 5057 DECL_CONTEXT (t) = child_fn;
5058
75a70cf9 5059 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
5060 so that it can be moved to the child function. */
5061 gsi = gsi_last_bb (entry_bb);
5062 stmt = gsi_stmt (gsi);
5063 gcc_assert (stmt && (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
5064 || gimple_code (stmt) == GIMPLE_OMP_TASK));
5065 gsi_remove (&gsi, true);
5066 e = split_block (entry_bb, stmt);
773c5ba7 5067 entry_bb = e->dest;
5068 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
5069
75a70cf9 5070 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
5056ba1a 5071 if (exit_bb)
5072 {
75a70cf9 5073 gsi = gsi_last_bb (exit_bb);
5074 gcc_assert (!gsi_end_p (gsi)
5075 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
5076 stmt = gimple_build_return (NULL);
5077 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
5078 gsi_remove (&gsi, true);
5056ba1a 5079 }
79acaae1 5080
5081 /* Move the parallel region into CHILD_CFUN. */
48e1416a 5082
79acaae1 5083 if (gimple_in_ssa_p (cfun))
5084 {
bcaa2770 5085 init_tree_ssa (child_cfun);
5084b2e4 5086 init_ssa_operands (child_cfun);
5087 child_cfun->gimple_df->in_ssa_p = true;
1d22f541 5088 block = NULL_TREE;
79acaae1 5089 }
1d22f541 5090 else
75a70cf9 5091 block = gimple_block (entry_stmt);
1d22f541 5092
5093 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
79acaae1 5094 if (exit_bb)
5095 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
04c2922b 5096 /* When the OMP expansion process cannot guarantee an up-to-date
5097 loop tree arrange for the child function to fixup loops. */
5098 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
5099 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
79acaae1 5100
1d22f541 5101 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
f1f41a6c 5102 num = vec_safe_length (child_cfun->local_decls);
501bdd19 5103 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
5104 {
f1f41a6c 5105 t = (*child_cfun->local_decls)[srcidx];
501bdd19 5106 if (DECL_CONTEXT (t) == cfun->decl)
5107 continue;
5108 if (srcidx != dstidx)
f1f41a6c 5109 (*child_cfun->local_decls)[dstidx] = t;
501bdd19 5110 dstidx++;
5111 }
5112 if (dstidx != num)
f1f41a6c 5113 vec_safe_truncate (child_cfun->local_decls, dstidx);
1d22f541 5114
79acaae1 5115 /* Inform the callgraph about the new function. */
82b40354 5116 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
415d1b9a 5117 cgraph_node::add_new_function (child_fn, true);
79acaae1 5118
5119 /* Fix the callgraph edges for child_cfun. Those for cfun will be
5120 fixed in a following pass. */
5121 push_cfun (child_cfun);
658b4427 5122 if (optimize)
fd6481cf 5123 optimize_omp_library_calls (entry_stmt);
35ee1c66 5124 cgraph_edge::rebuild_edges ();
fbe86b1b 5125
5126 /* Some EH regions might become dead, see PR34608. If
5127 pass_cleanup_cfg isn't the first pass to happen with the
5128 new child, these dead EH edges might cause problems.
5129 Clean them up now. */
5130 if (flag_exceptions)
5131 {
5132 basic_block bb;
fbe86b1b 5133 bool changed = false;
5134
fc00614f 5135 FOR_EACH_BB_FN (bb, cfun)
75a70cf9 5136 changed |= gimple_purge_dead_eh_edges (bb);
fbe86b1b 5137 if (changed)
5138 cleanup_tree_cfg ();
fbe86b1b 5139 }
dd277d48 5140 if (gimple_in_ssa_p (cfun))
5141 update_ssa (TODO_update_ssa);
79acaae1 5142 pop_cfun ();
773c5ba7 5143 }
48e1416a 5144
773c5ba7 5145 /* Emit a library call to launch the children threads. */
40750995 5146 if (is_cilk_for)
1a91d914 5147 expand_cilk_for_call (new_bb,
5148 as_a <gomp_parallel *> (entry_stmt), ws_args);
40750995 5149 else if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
1a91d914 5150 expand_parallel_call (region, new_bb,
5151 as_a <gomp_parallel *> (entry_stmt), ws_args);
fd6481cf 5152 else
1a91d914 5153 expand_task_call (new_bb, as_a <gomp_task *> (entry_stmt));
083152fb 5154 if (gimple_in_ssa_p (cfun))
5155 update_ssa (TODO_update_ssa_only_virtuals);
1e8e9920 5156}
5157
773c5ba7 5158
3d483a94 5159/* Helper function for expand_omp_{for_*,simd}. If this is the outermost
5160 of the combined collapse > 1 loop constructs, generate code like:
5161 if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
5162 if (cond3 is <)
5163 adj = STEP3 - 1;
5164 else
5165 adj = STEP3 + 1;
5166 count3 = (adj + N32 - N31) / STEP3;
5167 if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
5168 if (cond2 is <)
5169 adj = STEP2 - 1;
5170 else
5171 adj = STEP2 + 1;
5172 count2 = (adj + N22 - N21) / STEP2;
5173 if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
5174 if (cond1 is <)
5175 adj = STEP1 - 1;
5176 else
5177 adj = STEP1 + 1;
5178 count1 = (adj + N12 - N11) / STEP1;
5179 count = count1 * count2 * count3;
5180 Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
5181 count = 0;
bc7bff74 5182 and set ZERO_ITER_BB to that bb. If this isn't the outermost
5183 of the combined loop constructs, just initialize COUNTS array
5184 from the _looptemp_ clauses. */
3d483a94 5185
5186/* NOTE: It *could* be better to moosh all of the BBs together,
5187 creating one larger BB with all the computation and the unexpected
5188 jump at the end. I.e.
5189
5190 bool zero3, zero2, zero1, zero;
5191
5192 zero3 = N32 c3 N31;
5193 count3 = (N32 - N31) /[cl] STEP3;
5194 zero2 = N22 c2 N21;
5195 count2 = (N22 - N21) /[cl] STEP2;
5196 zero1 = N12 c1 N11;
5197 count1 = (N12 - N11) /[cl] STEP1;
5198 zero = zero3 || zero2 || zero1;
5199 count = count1 * count2 * count3;
5200 if (__builtin_expect(zero, false)) goto zero_iter_bb;
5201
5202 After all, we expect the zero=false, and thus we expect to have to
5203 evaluate all of the comparison expressions, so short-circuiting
5204 oughtn't be a win. Since the condition isn't protecting a
5205 denominator, we're not concerned about divide-by-zero, so we can
5206 fully evaluate count even if a numerator turned out to be wrong.
5207
5208 It seems like putting this all together would create much better
5209 scheduling opportunities, and less pressure on the chip's branch
5210 predictor. */
5211
5212static void
5213expand_omp_for_init_counts (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
5214 basic_block &entry_bb, tree *counts,
5215 basic_block &zero_iter_bb, int &first_zero_iter,
5216 basic_block &l2_dom_bb)
5217{
5218 tree t, type = TREE_TYPE (fd->loop.v);
3d483a94 5219 edge e, ne;
5220 int i;
5221
5222 /* Collapsed loops need work for expansion into SSA form. */
5223 gcc_assert (!gimple_in_ssa_p (cfun));
5224
bc7bff74 5225 if (gimple_omp_for_combined_into_p (fd->for_stmt)
5226 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
5227 {
5228 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5229 isn't supposed to be handled, as the inner loop doesn't
5230 use it. */
5231 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
5232 OMP_CLAUSE__LOOPTEMP_);
5233 gcc_assert (innerc);
5234 for (i = 0; i < fd->collapse; i++)
5235 {
5236 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5237 OMP_CLAUSE__LOOPTEMP_);
5238 gcc_assert (innerc);
5239 if (i)
5240 counts[i] = OMP_CLAUSE_DECL (innerc);
5241 else
5242 counts[0] = NULL_TREE;
5243 }
5244 return;
5245 }
5246
3d483a94 5247 for (i = 0; i < fd->collapse; i++)
5248 {
5249 tree itype = TREE_TYPE (fd->loops[i].v);
5250
5251 if (SSA_VAR_P (fd->loop.n2)
5252 && ((t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
5253 fold_convert (itype, fd->loops[i].n1),
5254 fold_convert (itype, fd->loops[i].n2)))
5255 == NULL_TREE || !integer_onep (t)))
5256 {
1a91d914 5257 gcond *cond_stmt;
3d483a94 5258 tree n1, n2;
5259 n1 = fold_convert (itype, unshare_expr (fd->loops[i].n1));
5260 n1 = force_gimple_operand_gsi (gsi, n1, true, NULL_TREE,
5261 true, GSI_SAME_STMT);
5262 n2 = fold_convert (itype, unshare_expr (fd->loops[i].n2));
5263 n2 = force_gimple_operand_gsi (gsi, n2, true, NULL_TREE,
5264 true, GSI_SAME_STMT);
1a91d914 5265 cond_stmt = gimple_build_cond (fd->loops[i].cond_code, n1, n2,
5266 NULL_TREE, NULL_TREE);
5267 gsi_insert_before (gsi, cond_stmt, GSI_SAME_STMT);
5268 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
3d483a94 5269 expand_omp_regimplify_p, NULL, NULL)
1a91d914 5270 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
3d483a94 5271 expand_omp_regimplify_p, NULL, NULL))
5272 {
1a91d914 5273 *gsi = gsi_for_stmt (cond_stmt);
5274 gimple_regimplify_operands (cond_stmt, gsi);
3d483a94 5275 }
1a91d914 5276 e = split_block (entry_bb, cond_stmt);
3d483a94 5277 if (zero_iter_bb == NULL)
5278 {
1a91d914 5279 gassign *assign_stmt;
3d483a94 5280 first_zero_iter = i;
5281 zero_iter_bb = create_empty_bb (entry_bb);
b3083327 5282 add_bb_to_loop (zero_iter_bb, entry_bb->loop_father);
3d483a94 5283 *gsi = gsi_after_labels (zero_iter_bb);
1a91d914 5284 assign_stmt = gimple_build_assign (fd->loop.n2,
5285 build_zero_cst (type));
5286 gsi_insert_before (gsi, assign_stmt, GSI_SAME_STMT);
3d483a94 5287 set_immediate_dominator (CDI_DOMINATORS, zero_iter_bb,
5288 entry_bb);
5289 }
5290 ne = make_edge (entry_bb, zero_iter_bb, EDGE_FALSE_VALUE);
5291 ne->probability = REG_BR_PROB_BASE / 2000 - 1;
5292 e->flags = EDGE_TRUE_VALUE;
5293 e->probability = REG_BR_PROB_BASE - ne->probability;
5294 if (l2_dom_bb == NULL)
5295 l2_dom_bb = entry_bb;
5296 entry_bb = e->dest;
5297 *gsi = gsi_last_bb (entry_bb);
5298 }
5299
5300 if (POINTER_TYPE_P (itype))
5301 itype = signed_type_for (itype);
5302 t = build_int_cst (itype, (fd->loops[i].cond_code == LT_EXPR
5303 ? -1 : 1));
5304 t = fold_build2 (PLUS_EXPR, itype,
5305 fold_convert (itype, fd->loops[i].step), t);
5306 t = fold_build2 (PLUS_EXPR, itype, t,
5307 fold_convert (itype, fd->loops[i].n2));
5308 t = fold_build2 (MINUS_EXPR, itype, t,
5309 fold_convert (itype, fd->loops[i].n1));
5310 /* ?? We could probably use CEIL_DIV_EXPR instead of
5311 TRUNC_DIV_EXPR and adjusting by hand. Unless we can't
5312 generate the same code in the end because generically we
5313 don't know that the values involved must be negative for
5314 GT?? */
5315 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
5316 t = fold_build2 (TRUNC_DIV_EXPR, itype,
5317 fold_build1 (NEGATE_EXPR, itype, t),
5318 fold_build1 (NEGATE_EXPR, itype,
5319 fold_convert (itype,
5320 fd->loops[i].step)));
5321 else
5322 t = fold_build2 (TRUNC_DIV_EXPR, itype, t,
5323 fold_convert (itype, fd->loops[i].step));
5324 t = fold_convert (type, t);
5325 if (TREE_CODE (t) == INTEGER_CST)
5326 counts[i] = t;
5327 else
5328 {
5329 counts[i] = create_tmp_reg (type, ".count");
5330 expand_omp_build_assign (gsi, counts[i], t);
5331 }
5332 if (SSA_VAR_P (fd->loop.n2))
5333 {
5334 if (i == 0)
5335 t = counts[0];
5336 else
5337 t = fold_build2 (MULT_EXPR, type, fd->loop.n2, counts[i]);
5338 expand_omp_build_assign (gsi, fd->loop.n2, t);
5339 }
5340 }
5341}
5342
5343
5344/* Helper function for expand_omp_{for_*,simd}. Generate code like:
5345 T = V;
5346 V3 = N31 + (T % count3) * STEP3;
5347 T = T / count3;
5348 V2 = N21 + (T % count2) * STEP2;
5349 T = T / count2;
5350 V1 = N11 + T * STEP1;
bc7bff74 5351 if this loop doesn't have an inner loop construct combined with it.
5352 If it does have an inner loop construct combined with it and the
5353 iteration count isn't known constant, store values from counts array
5354 into its _looptemp_ temporaries instead. */
3d483a94 5355
5356static void
5357expand_omp_for_init_vars (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
bc7bff74 5358 tree *counts, gimple inner_stmt, tree startvar)
3d483a94 5359{
5360 int i;
bc7bff74 5361 if (gimple_omp_for_combined_p (fd->for_stmt))
5362 {
5363 /* If fd->loop.n2 is constant, then no propagation of the counts
5364 is needed, they are constant. */
5365 if (TREE_CODE (fd->loop.n2) == INTEGER_CST)
5366 return;
5367
5368 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
5369 ? gimple_omp_parallel_clauses (inner_stmt)
5370 : gimple_omp_for_clauses (inner_stmt);
5371 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5372 isn't supposed to be handled, as the inner loop doesn't
5373 use it. */
5374 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
5375 gcc_assert (innerc);
5376 for (i = 0; i < fd->collapse; i++)
5377 {
5378 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5379 OMP_CLAUSE__LOOPTEMP_);
5380 gcc_assert (innerc);
5381 if (i)
5382 {
5383 tree tem = OMP_CLAUSE_DECL (innerc);
5384 tree t = fold_convert (TREE_TYPE (tem), counts[i]);
5385 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5386 false, GSI_CONTINUE_LINKING);
1a91d914 5387 gassign *stmt = gimple_build_assign (tem, t);
bc7bff74 5388 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5389 }
5390 }
5391 return;
5392 }
5393
3d483a94 5394 tree type = TREE_TYPE (fd->loop.v);
5395 tree tem = create_tmp_reg (type, ".tem");
1a91d914 5396 gassign *stmt = gimple_build_assign (tem, startvar);
3d483a94 5397 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5398
5399 for (i = fd->collapse - 1; i >= 0; i--)
5400 {
5401 tree vtype = TREE_TYPE (fd->loops[i].v), itype, t;
5402 itype = vtype;
5403 if (POINTER_TYPE_P (vtype))
5404 itype = signed_type_for (vtype);
5405 if (i != 0)
5406 t = fold_build2 (TRUNC_MOD_EXPR, type, tem, counts[i]);
5407 else
5408 t = tem;
5409 t = fold_convert (itype, t);
5410 t = fold_build2 (MULT_EXPR, itype, t,
5411 fold_convert (itype, fd->loops[i].step));
5412 if (POINTER_TYPE_P (vtype))
5413 t = fold_build_pointer_plus (fd->loops[i].n1, t);
5414 else
5415 t = fold_build2 (PLUS_EXPR, itype, fd->loops[i].n1, t);
5416 t = force_gimple_operand_gsi (gsi, t,
5417 DECL_P (fd->loops[i].v)
5418 && TREE_ADDRESSABLE (fd->loops[i].v),
5419 NULL_TREE, false,
5420 GSI_CONTINUE_LINKING);
5421 stmt = gimple_build_assign (fd->loops[i].v, t);
5422 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5423 if (i != 0)
5424 {
5425 t = fold_build2 (TRUNC_DIV_EXPR, type, tem, counts[i]);
5426 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5427 false, GSI_CONTINUE_LINKING);
5428 stmt = gimple_build_assign (tem, t);
5429 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5430 }
5431 }
5432}
5433
5434
5435/* Helper function for expand_omp_for_*. Generate code like:
5436 L10:
5437 V3 += STEP3;
5438 if (V3 cond3 N32) goto BODY_BB; else goto L11;
5439 L11:
5440 V3 = N31;
5441 V2 += STEP2;
5442 if (V2 cond2 N22) goto BODY_BB; else goto L12;
5443 L12:
5444 V2 = N21;
5445 V1 += STEP1;
5446 goto BODY_BB; */
5447
5448static basic_block
5449extract_omp_for_update_vars (struct omp_for_data *fd, basic_block cont_bb,
5450 basic_block body_bb)
5451{
5452 basic_block last_bb, bb, collapse_bb = NULL;
5453 int i;
5454 gimple_stmt_iterator gsi;
5455 edge e;
5456 tree t;
5457 gimple stmt;
5458
5459 last_bb = cont_bb;
5460 for (i = fd->collapse - 1; i >= 0; i--)
5461 {
5462 tree vtype = TREE_TYPE (fd->loops[i].v);
5463
5464 bb = create_empty_bb (last_bb);
b3083327 5465 add_bb_to_loop (bb, last_bb->loop_father);
3d483a94 5466 gsi = gsi_start_bb (bb);
5467
5468 if (i < fd->collapse - 1)
5469 {
5470 e = make_edge (last_bb, bb, EDGE_FALSE_VALUE);
5471 e->probability = REG_BR_PROB_BASE / 8;
5472
5473 t = fd->loops[i + 1].n1;
5474 t = force_gimple_operand_gsi (&gsi, t,
5475 DECL_P (fd->loops[i + 1].v)
5476 && TREE_ADDRESSABLE (fd->loops[i
5477 + 1].v),
5478 NULL_TREE, false,
5479 GSI_CONTINUE_LINKING);
5480 stmt = gimple_build_assign (fd->loops[i + 1].v, t);
5481 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5482 }
5483 else
5484 collapse_bb = bb;
5485
5486 set_immediate_dominator (CDI_DOMINATORS, bb, last_bb);
5487
5488 if (POINTER_TYPE_P (vtype))
5489 t = fold_build_pointer_plus (fd->loops[i].v, fd->loops[i].step);
5490 else
5491 t = fold_build2 (PLUS_EXPR, vtype, fd->loops[i].v, fd->loops[i].step);
5492 t = force_gimple_operand_gsi (&gsi, t,
5493 DECL_P (fd->loops[i].v)
5494 && TREE_ADDRESSABLE (fd->loops[i].v),
5495 NULL_TREE, false, GSI_CONTINUE_LINKING);
5496 stmt = gimple_build_assign (fd->loops[i].v, t);
5497 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5498
5499 if (i > 0)
5500 {
5501 t = fd->loops[i].n2;
5502 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5503 false, GSI_CONTINUE_LINKING);
5504 tree v = fd->loops[i].v;
5505 if (DECL_P (v) && TREE_ADDRESSABLE (v))
5506 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
5507 false, GSI_CONTINUE_LINKING);
5508 t = fold_build2 (fd->loops[i].cond_code, boolean_type_node, v, t);
5509 stmt = gimple_build_cond_empty (t);
5510 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5511 e = make_edge (bb, body_bb, EDGE_TRUE_VALUE);
5512 e->probability = REG_BR_PROB_BASE * 7 / 8;
5513 }
5514 else
5515 make_edge (bb, body_bb, EDGE_FALLTHRU);
5516 last_bb = bb;
5517 }
5518
5519 return collapse_bb;
5520}
5521
5522
773c5ba7 5523/* A subroutine of expand_omp_for. Generate code for a parallel
1e8e9920 5524 loop with any schedule. Given parameters:
5525
5526 for (V = N1; V cond N2; V += STEP) BODY;
5527
5528 where COND is "<" or ">", we generate pseudocode
5529
5530 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
773c5ba7 5531 if (more) goto L0; else goto L3;
1e8e9920 5532 L0:
5533 V = istart0;
5534 iend = iend0;
5535 L1:
5536 BODY;
5537 V += STEP;
773c5ba7 5538 if (V cond iend) goto L1; else goto L2;
1e8e9920 5539 L2:
773c5ba7 5540 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
5541 L3:
1e8e9920 5542
773c5ba7 5543 If this is a combined omp parallel loop, instead of the call to
fd6481cf 5544 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
bc7bff74 5545 If this is gimple_omp_for_combined_p loop, then instead of assigning
5546 V and iend in L0 we assign the first two _looptemp_ clause decls of the
5547 inner GIMPLE_OMP_FOR and V += STEP; and
5548 if (V cond iend) goto L1; else goto L2; are removed.
fd6481cf 5549
5550 For collapsed loops, given parameters:
5551 collapse(3)
5552 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
5553 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
5554 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
5555 BODY;
5556
5557 we generate pseudocode
5558
8e6b4515 5559 if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
fd6481cf 5560 if (cond3 is <)
5561 adj = STEP3 - 1;
5562 else
5563 adj = STEP3 + 1;
5564 count3 = (adj + N32 - N31) / STEP3;
8e6b4515 5565 if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
fd6481cf 5566 if (cond2 is <)
5567 adj = STEP2 - 1;
5568 else
5569 adj = STEP2 + 1;
5570 count2 = (adj + N22 - N21) / STEP2;
8e6b4515 5571 if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
fd6481cf 5572 if (cond1 is <)
5573 adj = STEP1 - 1;
5574 else
5575 adj = STEP1 + 1;
5576 count1 = (adj + N12 - N11) / STEP1;
5577 count = count1 * count2 * count3;
8e6b4515 5578 goto Z1;
5579 Z0:
5580 count = 0;
5581 Z1:
fd6481cf 5582 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
5583 if (more) goto L0; else goto L3;
5584 L0:
5585 V = istart0;
5586 T = V;
5587 V3 = N31 + (T % count3) * STEP3;
5588 T = T / count3;
5589 V2 = N21 + (T % count2) * STEP2;
5590 T = T / count2;
5591 V1 = N11 + T * STEP1;
5592 iend = iend0;
5593 L1:
5594 BODY;
5595 V += 1;
5596 if (V < iend) goto L10; else goto L2;
5597 L10:
5598 V3 += STEP3;
5599 if (V3 cond3 N32) goto L1; else goto L11;
5600 L11:
5601 V3 = N31;
5602 V2 += STEP2;
5603 if (V2 cond2 N22) goto L1; else goto L12;
5604 L12:
5605 V2 = N21;
5606 V1 += STEP1;
5607 goto L1;
5608 L2:
5609 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
5610 L3:
5611
5612 */
1e8e9920 5613
61e47ac8 5614static void
773c5ba7 5615expand_omp_for_generic (struct omp_region *region,
5616 struct omp_for_data *fd,
1e8e9920 5617 enum built_in_function start_fn,
bc7bff74 5618 enum built_in_function next_fn,
5619 gimple inner_stmt)
1e8e9920 5620{
75a70cf9 5621 tree type, istart0, iend0, iend;
fd6481cf 5622 tree t, vmain, vback, bias = NULL_TREE;
5623 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, collapse_bb;
03ed154b 5624 basic_block l2_bb = NULL, l3_bb = NULL;
75a70cf9 5625 gimple_stmt_iterator gsi;
1a91d914 5626 gassign *assign_stmt;
773c5ba7 5627 bool in_combined_parallel = is_combined_parallel (region);
ac6e3339 5628 bool broken_loop = region->cont == NULL;
79acaae1 5629 edge e, ne;
fd6481cf 5630 tree *counts = NULL;
5631 int i;
ac6e3339 5632
5633 gcc_assert (!broken_loop || !in_combined_parallel);
fd6481cf 5634 gcc_assert (fd->iter_type == long_integer_type_node
5635 || !in_combined_parallel);
1e8e9920 5636
fd6481cf 5637 type = TREE_TYPE (fd->loop.v);
5638 istart0 = create_tmp_var (fd->iter_type, ".istart0");
5639 iend0 = create_tmp_var (fd->iter_type, ".iend0");
6d63fc03 5640 TREE_ADDRESSABLE (istart0) = 1;
5641 TREE_ADDRESSABLE (iend0) = 1;
1e8e9920 5642
fd6481cf 5643 /* See if we need to bias by LLONG_MIN. */
5644 if (fd->iter_type == long_long_unsigned_type_node
5645 && TREE_CODE (type) == INTEGER_TYPE
5646 && !TYPE_UNSIGNED (type))
5647 {
5648 tree n1, n2;
5649
5650 if (fd->loop.cond_code == LT_EXPR)
5651 {
5652 n1 = fd->loop.n1;
5653 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
5654 }
5655 else
5656 {
5657 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
5658 n2 = fd->loop.n1;
5659 }
5660 if (TREE_CODE (n1) != INTEGER_CST
5661 || TREE_CODE (n2) != INTEGER_CST
5662 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
5663 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
5664 }
5665
61e47ac8 5666 entry_bb = region->entry;
03ed154b 5667 cont_bb = region->cont;
fd6481cf 5668 collapse_bb = NULL;
ac6e3339 5669 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
5670 gcc_assert (broken_loop
5671 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
5672 l0_bb = split_edge (FALLTHRU_EDGE (entry_bb));
5673 l1_bb = single_succ (l0_bb);
5674 if (!broken_loop)
03ed154b 5675 {
5676 l2_bb = create_empty_bb (cont_bb);
ac6e3339 5677 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb);
5678 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
03ed154b 5679 }
ac6e3339 5680 else
5681 l2_bb = NULL;
5682 l3_bb = BRANCH_EDGE (entry_bb)->dest;
5683 exit_bb = region->exit;
773c5ba7 5684
75a70cf9 5685 gsi = gsi_last_bb (entry_bb);
fd6481cf 5686
75a70cf9 5687 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
fd6481cf 5688 if (fd->collapse > 1)
5689 {
8e6b4515 5690 int first_zero_iter = -1;
3d483a94 5691 basic_block zero_iter_bb = NULL, l2_dom_bb = NULL;
8e6b4515 5692
3d483a94 5693 counts = XALLOCAVEC (tree, fd->collapse);
5694 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
5695 zero_iter_bb, first_zero_iter,
5696 l2_dom_bb);
fd6481cf 5697
8e6b4515 5698 if (zero_iter_bb)
5699 {
5700 /* Some counts[i] vars might be uninitialized if
5701 some loop has zero iterations. But the body shouldn't
5702 be executed in that case, so just avoid uninit warnings. */
5703 for (i = first_zero_iter; i < fd->collapse; i++)
5704 if (SSA_VAR_P (counts[i]))
5705 TREE_NO_WARNING (counts[i]) = 1;
5706 gsi_prev (&gsi);
5707 e = split_block (entry_bb, gsi_stmt (gsi));
5708 entry_bb = e->dest;
5709 make_edge (zero_iter_bb, entry_bb, EDGE_FALLTHRU);
5710 gsi = gsi_last_bb (entry_bb);
5711 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
5712 get_immediate_dominator (CDI_DOMINATORS,
5713 zero_iter_bb));
5714 }
fd6481cf 5715 }
79acaae1 5716 if (in_combined_parallel)
5717 {
5718 /* In a combined parallel loop, emit a call to
5719 GOMP_loop_foo_next. */
b9a16870 5720 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
79acaae1 5721 build_fold_addr_expr (istart0),
5722 build_fold_addr_expr (iend0));
5723 }
5724 else
1e8e9920 5725 {
c2f47e15 5726 tree t0, t1, t2, t3, t4;
773c5ba7 5727 /* If this is not a combined parallel loop, emit a call to
5728 GOMP_loop_foo_start in ENTRY_BB. */
c2f47e15 5729 t4 = build_fold_addr_expr (iend0);
5730 t3 = build_fold_addr_expr (istart0);
fd6481cf 5731 t2 = fold_convert (fd->iter_type, fd->loop.step);
3d483a94 5732 t1 = fd->loop.n2;
5733 t0 = fd->loop.n1;
bc7bff74 5734 if (gimple_omp_for_combined_into_p (fd->for_stmt))
5735 {
5736 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
5737 OMP_CLAUSE__LOOPTEMP_);
5738 gcc_assert (innerc);
5739 t0 = OMP_CLAUSE_DECL (innerc);
5740 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5741 OMP_CLAUSE__LOOPTEMP_);
5742 gcc_assert (innerc);
5743 t1 = OMP_CLAUSE_DECL (innerc);
5744 }
3d483a94 5745 if (POINTER_TYPE_P (TREE_TYPE (t0))
5746 && TYPE_PRECISION (TREE_TYPE (t0))
5747 != TYPE_PRECISION (fd->iter_type))
c799f233 5748 {
5749 /* Avoid casting pointers to integer of a different size. */
3cea8318 5750 tree itype = signed_type_for (type);
3d483a94 5751 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
5752 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
c799f233 5753 }
5754 else
5755 {
3d483a94 5756 t1 = fold_convert (fd->iter_type, t1);
5757 t0 = fold_convert (fd->iter_type, t0);
c799f233 5758 }
fd6481cf 5759 if (bias)
1e8e9920 5760 {
fd6481cf 5761 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
5762 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
5763 }
5764 if (fd->iter_type == long_integer_type_node)
5765 {
5766 if (fd->chunk_size)
5767 {
5768 t = fold_convert (fd->iter_type, fd->chunk_size);
b9a16870 5769 t = build_call_expr (builtin_decl_explicit (start_fn),
5770 6, t0, t1, t2, t, t3, t4);
fd6481cf 5771 }
5772 else
b9a16870 5773 t = build_call_expr (builtin_decl_explicit (start_fn),
5774 5, t0, t1, t2, t3, t4);
1e8e9920 5775 }
c2f47e15 5776 else
fd6481cf 5777 {
5778 tree t5;
5779 tree c_bool_type;
b9a16870 5780 tree bfn_decl;
fd6481cf 5781
5782 /* The GOMP_loop_ull_*start functions have additional boolean
5783 argument, true for < loops and false for > loops.
5784 In Fortran, the C bool type can be different from
5785 boolean_type_node. */
b9a16870 5786 bfn_decl = builtin_decl_explicit (start_fn);
5787 c_bool_type = TREE_TYPE (TREE_TYPE (bfn_decl));
fd6481cf 5788 t5 = build_int_cst (c_bool_type,
5789 fd->loop.cond_code == LT_EXPR ? 1 : 0);
5790 if (fd->chunk_size)
5791 {
b9a16870 5792 tree bfn_decl = builtin_decl_explicit (start_fn);
fd6481cf 5793 t = fold_convert (fd->iter_type, fd->chunk_size);
b9a16870 5794 t = build_call_expr (bfn_decl, 7, t5, t0, t1, t2, t, t3, t4);
fd6481cf 5795 }
5796 else
b9a16870 5797 t = build_call_expr (builtin_decl_explicit (start_fn),
5798 6, t5, t0, t1, t2, t3, t4);
fd6481cf 5799 }
1e8e9920 5800 }
fd6481cf 5801 if (TREE_TYPE (t) != boolean_type_node)
5802 t = fold_build2 (NE_EXPR, boolean_type_node,
5803 t, build_int_cst (TREE_TYPE (t), 0));
75a70cf9 5804 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5805 true, GSI_SAME_STMT);
5806 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
79acaae1 5807
75a70cf9 5808 /* Remove the GIMPLE_OMP_FOR statement. */
5809 gsi_remove (&gsi, true);
1e8e9920 5810
773c5ba7 5811 /* Iteration setup for sequential loop goes in L0_BB. */
3d483a94 5812 tree startvar = fd->loop.v;
5813 tree endvar = NULL_TREE;
5814
bc7bff74 5815 if (gimple_omp_for_combined_p (fd->for_stmt))
5816 {
5817 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_FOR
5818 && gimple_omp_for_kind (inner_stmt)
5819 == GF_OMP_FOR_KIND_SIMD);
5820 tree innerc = find_omp_clause (gimple_omp_for_clauses (inner_stmt),
5821 OMP_CLAUSE__LOOPTEMP_);
5822 gcc_assert (innerc);
5823 startvar = OMP_CLAUSE_DECL (innerc);
5824 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5825 OMP_CLAUSE__LOOPTEMP_);
5826 gcc_assert (innerc);
5827 endvar = OMP_CLAUSE_DECL (innerc);
5828 }
5829
75a70cf9 5830 gsi = gsi_start_bb (l0_bb);
1efcacec 5831 t = istart0;
fd6481cf 5832 if (bias)
1efcacec 5833 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
3d483a94 5834 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
5835 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
5836 t = fold_convert (TREE_TYPE (startvar), t);
4abecb72 5837 t = force_gimple_operand_gsi (&gsi, t,
3d483a94 5838 DECL_P (startvar)
5839 && TREE_ADDRESSABLE (startvar),
4abecb72 5840 NULL_TREE, false, GSI_CONTINUE_LINKING);
1a91d914 5841 assign_stmt = gimple_build_assign (startvar, t);
5842 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
1e8e9920 5843
1efcacec 5844 t = iend0;
fd6481cf 5845 if (bias)
1efcacec 5846 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
3d483a94 5847 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
5848 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
5849 t = fold_convert (TREE_TYPE (startvar), t);
75a70cf9 5850 iend = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5851 false, GSI_CONTINUE_LINKING);
3d483a94 5852 if (endvar)
fd6481cf 5853 {
1a91d914 5854 assign_stmt = gimple_build_assign (endvar, iend);
5855 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
d44f2f7c 5856 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (iend)))
1a91d914 5857 assign_stmt = gimple_build_assign (fd->loop.v, iend);
d44f2f7c 5858 else
1a91d914 5859 assign_stmt = gimple_build_assign_with_ops (NOP_EXPR, fd->loop.v, iend);
5860 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
fd6481cf 5861 }
3d483a94 5862 if (fd->collapse > 1)
bc7bff74 5863 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
773c5ba7 5864
ac6e3339 5865 if (!broken_loop)
03ed154b 5866 {
ac6e3339 5867 /* Code to control the increment and predicate for the sequential
5868 loop goes in the CONT_BB. */
75a70cf9 5869 gsi = gsi_last_bb (cont_bb);
1a91d914 5870 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
5871 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
5872 vmain = gimple_omp_continue_control_use (cont_stmt);
5873 vback = gimple_omp_continue_control_def (cont_stmt);
79acaae1 5874
bc7bff74 5875 if (!gimple_omp_for_combined_p (fd->for_stmt))
3d483a94 5876 {
5877 if (POINTER_TYPE_P (type))
5878 t = fold_build_pointer_plus (vmain, fd->loop.step);
5879 else
5880 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
5881 t = force_gimple_operand_gsi (&gsi, t,
5882 DECL_P (vback)
5883 && TREE_ADDRESSABLE (vback),
5884 NULL_TREE, true, GSI_SAME_STMT);
1a91d914 5885 assign_stmt = gimple_build_assign (vback, t);
5886 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
3d483a94 5887
5888 t = build2 (fd->loop.cond_code, boolean_type_node,
5889 DECL_P (vback) && TREE_ADDRESSABLE (vback) ? t : vback,
5890 iend);
1a91d914 5891 gcond *cond_stmt = gimple_build_cond_empty (t);
5892 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
3d483a94 5893 }
773c5ba7 5894
75a70cf9 5895 /* Remove GIMPLE_OMP_CONTINUE. */
5896 gsi_remove (&gsi, true);
773c5ba7 5897
bc7bff74 5898 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
3d483a94 5899 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, l1_bb);
fd6481cf 5900
ac6e3339 5901 /* Emit code to get the next parallel iteration in L2_BB. */
75a70cf9 5902 gsi = gsi_start_bb (l2_bb);
773c5ba7 5903
b9a16870 5904 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
ac6e3339 5905 build_fold_addr_expr (istart0),
5906 build_fold_addr_expr (iend0));
75a70cf9 5907 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5908 false, GSI_CONTINUE_LINKING);
fd6481cf 5909 if (TREE_TYPE (t) != boolean_type_node)
5910 t = fold_build2 (NE_EXPR, boolean_type_node,
5911 t, build_int_cst (TREE_TYPE (t), 0));
1a91d914 5912 gcond *cond_stmt = gimple_build_cond_empty (t);
5913 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
ac6e3339 5914 }
1e8e9920 5915
61e47ac8 5916 /* Add the loop cleanup function. */
75a70cf9 5917 gsi = gsi_last_bb (exit_bb);
5918 if (gimple_omp_return_nowait_p (gsi_stmt (gsi)))
b9a16870 5919 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
bc7bff74 5920 else if (gimple_omp_return_lhs (gsi_stmt (gsi)))
5921 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL);
61e47ac8 5922 else
b9a16870 5923 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END);
1a91d914 5924 gcall *call_stmt = gimple_build_call (t, 0);
bc7bff74 5925 if (gimple_omp_return_lhs (gsi_stmt (gsi)))
1a91d914 5926 gimple_call_set_lhs (call_stmt, gimple_omp_return_lhs (gsi_stmt (gsi)));
5927 gsi_insert_after (&gsi, call_stmt, GSI_SAME_STMT);
75a70cf9 5928 gsi_remove (&gsi, true);
773c5ba7 5929
5930 /* Connect the new blocks. */
79acaae1 5931 find_edge (entry_bb, l0_bb)->flags = EDGE_TRUE_VALUE;
5932 find_edge (entry_bb, l3_bb)->flags = EDGE_FALSE_VALUE;
1e8e9920 5933
ac6e3339 5934 if (!broken_loop)
5935 {
75a70cf9 5936 gimple_seq phis;
5937
79acaae1 5938 e = find_edge (cont_bb, l3_bb);
5939 ne = make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
5940
75a70cf9 5941 phis = phi_nodes (l3_bb);
5942 for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi))
5943 {
5944 gimple phi = gsi_stmt (gsi);
5945 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, ne),
5946 PHI_ARG_DEF_FROM_EDGE (phi, e));
5947 }
79acaae1 5948 remove_edge (e);
5949
ac6e3339 5950 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
b3083327 5951 add_bb_to_loop (l2_bb, cont_bb->loop_father);
3d483a94 5952 e = find_edge (cont_bb, l1_bb);
bc7bff74 5953 if (gimple_omp_for_combined_p (fd->for_stmt))
5954 {
5955 remove_edge (e);
5956 e = NULL;
5957 }
3d483a94 5958 else if (fd->collapse > 1)
fd6481cf 5959 {
fd6481cf 5960 remove_edge (e);
5961 e = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
5962 }
5963 else
3d483a94 5964 e->flags = EDGE_TRUE_VALUE;
5965 if (e)
fd6481cf 5966 {
3d483a94 5967 e->probability = REG_BR_PROB_BASE * 7 / 8;
5968 find_edge (cont_bb, l2_bb)->probability = REG_BR_PROB_BASE / 8;
5969 }
5970 else
5971 {
5972 e = find_edge (cont_bb, l2_bb);
5973 e->flags = EDGE_FALLTHRU;
fd6481cf 5974 }
ac6e3339 5975 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
79acaae1 5976
5977 set_immediate_dominator (CDI_DOMINATORS, l2_bb,
5978 recompute_dominator (CDI_DOMINATORS, l2_bb));
5979 set_immediate_dominator (CDI_DOMINATORS, l3_bb,
5980 recompute_dominator (CDI_DOMINATORS, l3_bb));
5981 set_immediate_dominator (CDI_DOMINATORS, l0_bb,
5982 recompute_dominator (CDI_DOMINATORS, l0_bb));
5983 set_immediate_dominator (CDI_DOMINATORS, l1_bb,
5984 recompute_dominator (CDI_DOMINATORS, l1_bb));
04c2922b 5985
5986 struct loop *outer_loop = alloc_loop ();
5987 outer_loop->header = l0_bb;
5988 outer_loop->latch = l2_bb;
5989 add_loop (outer_loop, l0_bb->loop_father);
5990
bc7bff74 5991 if (!gimple_omp_for_combined_p (fd->for_stmt))
3d483a94 5992 {
5993 struct loop *loop = alloc_loop ();
5994 loop->header = l1_bb;
5995 /* The loop may have multiple latches. */
5996 add_loop (loop, outer_loop);
5997 }
ac6e3339 5998 }
1e8e9920 5999}
6000
6001
773c5ba7 6002/* A subroutine of expand_omp_for. Generate code for a parallel
6003 loop with static schedule and no specified chunk size. Given
6004 parameters:
1e8e9920 6005
6006 for (V = N1; V cond N2; V += STEP) BODY;
6007
6008 where COND is "<" or ">", we generate pseudocode
6009
8e6b4515 6010 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
1e8e9920 6011 if (cond is <)
6012 adj = STEP - 1;
6013 else
6014 adj = STEP + 1;
fd6481cf 6015 if ((__typeof (V)) -1 > 0 && cond is >)
6016 n = -(adj + N2 - N1) / -STEP;
6017 else
6018 n = (adj + N2 - N1) / STEP;
1e8e9920 6019 q = n / nthreads;
31712e83 6020 tt = n % nthreads;
6021 if (threadid < tt) goto L3; else goto L4;
6022 L3:
6023 tt = 0;
6024 q = q + 1;
6025 L4:
6026 s0 = q * threadid + tt;
6027 e0 = s0 + q;
79acaae1 6028 V = s0 * STEP + N1;
1e8e9920 6029 if (s0 >= e0) goto L2; else goto L0;
6030 L0:
1e8e9920 6031 e = e0 * STEP + N1;
6032 L1:
6033 BODY;
6034 V += STEP;
6035 if (V cond e) goto L1;
1e8e9920 6036 L2:
6037*/
6038
61e47ac8 6039static void
773c5ba7 6040expand_omp_for_static_nochunk (struct omp_region *region,
bc7bff74 6041 struct omp_for_data *fd,
6042 gimple inner_stmt)
1e8e9920 6043{
31712e83 6044 tree n, q, s0, e0, e, t, tt, nthreads, threadid;
fd6481cf 6045 tree type, itype, vmain, vback;
31712e83 6046 basic_block entry_bb, second_bb, third_bb, exit_bb, seq_start_bb;
bc7bff74 6047 basic_block body_bb, cont_bb, collapse_bb = NULL;
61e47ac8 6048 basic_block fin_bb;
75a70cf9 6049 gimple_stmt_iterator gsi;
31712e83 6050 edge ep;
bc7bff74 6051 enum built_in_function get_num_threads = BUILT_IN_OMP_GET_NUM_THREADS;
6052 enum built_in_function get_thread_num = BUILT_IN_OMP_GET_THREAD_NUM;
6053 bool broken_loop = region->cont == NULL;
6054 tree *counts = NULL;
6055 tree n1, n2, step;
1e8e9920 6056
fd6481cf 6057 itype = type = TREE_TYPE (fd->loop.v);
6058 if (POINTER_TYPE_P (type))
3cea8318 6059 itype = signed_type_for (type);
1e8e9920 6060
61e47ac8 6061 entry_bb = region->entry;
61e47ac8 6062 cont_bb = region->cont;
ac6e3339 6063 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
bc7bff74 6064 fin_bb = BRANCH_EDGE (entry_bb)->dest;
6065 gcc_assert (broken_loop
6066 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
ac6e3339 6067 seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb));
6068 body_bb = single_succ (seq_start_bb);
bc7bff74 6069 if (!broken_loop)
6070 {
6071 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
6072 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6073 }
61e47ac8 6074 exit_bb = region->exit;
6075
773c5ba7 6076 /* Iteration space partitioning goes in ENTRY_BB. */
75a70cf9 6077 gsi = gsi_last_bb (entry_bb);
6078 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
61e47ac8 6079
bc7bff74 6080 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
6081 {
6082 get_num_threads = BUILT_IN_OMP_GET_NUM_TEAMS;
6083 get_thread_num = BUILT_IN_OMP_GET_TEAM_NUM;
6084 }
6085
6086 if (fd->collapse > 1)
6087 {
6088 int first_zero_iter = -1;
6089 basic_block l2_dom_bb = NULL;
6090
6091 counts = XALLOCAVEC (tree, fd->collapse);
6092 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6093 fin_bb, first_zero_iter,
6094 l2_dom_bb);
6095 t = NULL_TREE;
6096 }
6097 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
6098 t = integer_one_node;
6099 else
6100 t = fold_binary (fd->loop.cond_code, boolean_type_node,
6101 fold_convert (type, fd->loop.n1),
6102 fold_convert (type, fd->loop.n2));
6103 if (fd->collapse == 1
6104 && TYPE_UNSIGNED (type)
8e6b4515 6105 && (t == NULL_TREE || !integer_onep (t)))
6106 {
8e6b4515 6107 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
6108 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
6109 true, GSI_SAME_STMT);
6110 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
6111 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
6112 true, GSI_SAME_STMT);
1a91d914 6113 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
6114 NULL_TREE, NULL_TREE);
6115 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
6116 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
8e6b4515 6117 expand_omp_regimplify_p, NULL, NULL)
1a91d914 6118 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
8e6b4515 6119 expand_omp_regimplify_p, NULL, NULL))
6120 {
1a91d914 6121 gsi = gsi_for_stmt (cond_stmt);
6122 gimple_regimplify_operands (cond_stmt, &gsi);
8e6b4515 6123 }
1a91d914 6124 ep = split_block (entry_bb, cond_stmt);
8e6b4515 6125 ep->flags = EDGE_TRUE_VALUE;
6126 entry_bb = ep->dest;
6127 ep->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
6128 ep = make_edge (ep->src, fin_bb, EDGE_FALSE_VALUE);
6129 ep->probability = REG_BR_PROB_BASE / 2000 - 1;
6130 if (gimple_in_ssa_p (cfun))
6131 {
6132 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
1a91d914 6133 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
6134 !gsi_end_p (gpi); gsi_next (&gpi))
8e6b4515 6135 {
1a91d914 6136 gphi *phi = gpi.phi ();
8e6b4515 6137 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
6138 ep, UNKNOWN_LOCATION);
6139 }
6140 }
6141 gsi = gsi_last_bb (entry_bb);
6142 }
6143
bc7bff74 6144 t = build_call_expr (builtin_decl_explicit (get_num_threads), 0);
fd6481cf 6145 t = fold_convert (itype, t);
75a70cf9 6146 nthreads = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6147 true, GSI_SAME_STMT);
48e1416a 6148
bc7bff74 6149 t = build_call_expr (builtin_decl_explicit (get_thread_num), 0);
fd6481cf 6150 t = fold_convert (itype, t);
75a70cf9 6151 threadid = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6152 true, GSI_SAME_STMT);
1e8e9920 6153
bc7bff74 6154 n1 = fd->loop.n1;
6155 n2 = fd->loop.n2;
6156 step = fd->loop.step;
6157 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6158 {
6159 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6160 OMP_CLAUSE__LOOPTEMP_);
6161 gcc_assert (innerc);
6162 n1 = OMP_CLAUSE_DECL (innerc);
6163 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6164 OMP_CLAUSE__LOOPTEMP_);
6165 gcc_assert (innerc);
6166 n2 = OMP_CLAUSE_DECL (innerc);
6167 }
6168 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
6169 true, NULL_TREE, true, GSI_SAME_STMT);
6170 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
6171 true, NULL_TREE, true, GSI_SAME_STMT);
6172 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
6173 true, NULL_TREE, true, GSI_SAME_STMT);
fd6481cf 6174
6175 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
bc7bff74 6176 t = fold_build2 (PLUS_EXPR, itype, step, t);
6177 t = fold_build2 (PLUS_EXPR, itype, t, n2);
6178 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
fd6481cf 6179 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
6180 t = fold_build2 (TRUNC_DIV_EXPR, itype,
6181 fold_build1 (NEGATE_EXPR, itype, t),
bc7bff74 6182 fold_build1 (NEGATE_EXPR, itype, step));
fd6481cf 6183 else
bc7bff74 6184 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
fd6481cf 6185 t = fold_convert (itype, t);
75a70cf9 6186 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
1e8e9920 6187
072f7ab1 6188 q = create_tmp_reg (itype, "q");
fd6481cf 6189 t = fold_build2 (TRUNC_DIV_EXPR, itype, n, nthreads);
31712e83 6190 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
6191 gsi_insert_before (&gsi, gimple_build_assign (q, t), GSI_SAME_STMT);
6192
072f7ab1 6193 tt = create_tmp_reg (itype, "tt");
31712e83 6194 t = fold_build2 (TRUNC_MOD_EXPR, itype, n, nthreads);
6195 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
6196 gsi_insert_before (&gsi, gimple_build_assign (tt, t), GSI_SAME_STMT);
1e8e9920 6197
31712e83 6198 t = build2 (LT_EXPR, boolean_type_node, threadid, tt);
1a91d914 6199 gcond *cond_stmt = gimple_build_cond_empty (t);
6200 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
31712e83 6201
1a91d914 6202 second_bb = split_block (entry_bb, cond_stmt)->dest;
31712e83 6203 gsi = gsi_last_bb (second_bb);
6204 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6205
6206 gsi_insert_before (&gsi, gimple_build_assign (tt, build_int_cst (itype, 0)),
6207 GSI_SAME_STMT);
1a91d914 6208 gassign *assign_stmt
6209 = gimple_build_assign_with_ops (PLUS_EXPR, q, q,
6210 build_int_cst (itype, 1));
6211 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
31712e83 6212
1a91d914 6213 third_bb = split_block (second_bb, assign_stmt)->dest;
31712e83 6214 gsi = gsi_last_bb (third_bb);
6215 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
1e8e9920 6216
fd6481cf 6217 t = build2 (MULT_EXPR, itype, q, threadid);
31712e83 6218 t = build2 (PLUS_EXPR, itype, t, tt);
75a70cf9 6219 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
1e8e9920 6220
fd6481cf 6221 t = fold_build2 (PLUS_EXPR, itype, s0, q);
75a70cf9 6222 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
79acaae1 6223
1e8e9920 6224 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
75a70cf9 6225 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
773c5ba7 6226
75a70cf9 6227 /* Remove the GIMPLE_OMP_FOR statement. */
6228 gsi_remove (&gsi, true);
773c5ba7 6229
6230 /* Setup code for sequential iteration goes in SEQ_START_BB. */
75a70cf9 6231 gsi = gsi_start_bb (seq_start_bb);
1e8e9920 6232
bc7bff74 6233 tree startvar = fd->loop.v;
6234 tree endvar = NULL_TREE;
6235
6236 if (gimple_omp_for_combined_p (fd->for_stmt))
6237 {
6238 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
6239 ? gimple_omp_parallel_clauses (inner_stmt)
6240 : gimple_omp_for_clauses (inner_stmt);
6241 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
6242 gcc_assert (innerc);
6243 startvar = OMP_CLAUSE_DECL (innerc);
6244 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6245 OMP_CLAUSE__LOOPTEMP_);
6246 gcc_assert (innerc);
6247 endvar = OMP_CLAUSE_DECL (innerc);
6248 }
fd6481cf 6249 t = fold_convert (itype, s0);
bc7bff74 6250 t = fold_build2 (MULT_EXPR, itype, t, step);
fd6481cf 6251 if (POINTER_TYPE_P (type))
bc7bff74 6252 t = fold_build_pointer_plus (n1, t);
fd6481cf 6253 else
bc7bff74 6254 t = fold_build2 (PLUS_EXPR, type, t, n1);
6255 t = fold_convert (TREE_TYPE (startvar), t);
4abecb72 6256 t = force_gimple_operand_gsi (&gsi, t,
bc7bff74 6257 DECL_P (startvar)
6258 && TREE_ADDRESSABLE (startvar),
4abecb72 6259 NULL_TREE, false, GSI_CONTINUE_LINKING);
1a91d914 6260 assign_stmt = gimple_build_assign (startvar, t);
6261 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
48e1416a 6262
fd6481cf 6263 t = fold_convert (itype, e0);
bc7bff74 6264 t = fold_build2 (MULT_EXPR, itype, t, step);
fd6481cf 6265 if (POINTER_TYPE_P (type))
bc7bff74 6266 t = fold_build_pointer_plus (n1, t);
fd6481cf 6267 else
bc7bff74 6268 t = fold_build2 (PLUS_EXPR, type, t, n1);
6269 t = fold_convert (TREE_TYPE (startvar), t);
75a70cf9 6270 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6271 false, GSI_CONTINUE_LINKING);
bc7bff74 6272 if (endvar)
6273 {
1a91d914 6274 assign_stmt = gimple_build_assign (endvar, e);
6275 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
d44f2f7c 6276 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
1a91d914 6277 assign_stmt = gimple_build_assign (fd->loop.v, e);
d44f2f7c 6278 else
1a91d914 6279 assign_stmt = gimple_build_assign_with_ops (NOP_EXPR, fd->loop.v, e);
6280 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
bc7bff74 6281 }
6282 if (fd->collapse > 1)
6283 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
1e8e9920 6284
bc7bff74 6285 if (!broken_loop)
6286 {
6287 /* The code controlling the sequential loop replaces the
6288 GIMPLE_OMP_CONTINUE. */
6289 gsi = gsi_last_bb (cont_bb);
1a91d914 6290 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
6291 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
6292 vmain = gimple_omp_continue_control_use (cont_stmt);
6293 vback = gimple_omp_continue_control_def (cont_stmt);
79acaae1 6294
bc7bff74 6295 if (!gimple_omp_for_combined_p (fd->for_stmt))
6296 {
6297 if (POINTER_TYPE_P (type))
6298 t = fold_build_pointer_plus (vmain, step);
6299 else
6300 t = fold_build2 (PLUS_EXPR, type, vmain, step);
6301 t = force_gimple_operand_gsi (&gsi, t,
6302 DECL_P (vback)
6303 && TREE_ADDRESSABLE (vback),
6304 NULL_TREE, true, GSI_SAME_STMT);
1a91d914 6305 assign_stmt = gimple_build_assign (vback, t);
6306 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
79acaae1 6307
bc7bff74 6308 t = build2 (fd->loop.cond_code, boolean_type_node,
6309 DECL_P (vback) && TREE_ADDRESSABLE (vback)
6310 ? t : vback, e);
6311 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6312 }
1e8e9920 6313
bc7bff74 6314 /* Remove the GIMPLE_OMP_CONTINUE statement. */
6315 gsi_remove (&gsi, true);
6316
6317 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
6318 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
6319 }
773c5ba7 6320
75a70cf9 6321 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
6322 gsi = gsi_last_bb (exit_bb);
6323 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
bc7bff74 6324 {
6325 t = gimple_omp_return_lhs (gsi_stmt (gsi));
6326 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
6327 }
75a70cf9 6328 gsi_remove (&gsi, true);
773c5ba7 6329
6330 /* Connect all the blocks. */
31712e83 6331 ep = make_edge (entry_bb, third_bb, EDGE_FALSE_VALUE);
6332 ep->probability = REG_BR_PROB_BASE / 4 * 3;
6333 ep = find_edge (entry_bb, second_bb);
6334 ep->flags = EDGE_TRUE_VALUE;
6335 ep->probability = REG_BR_PROB_BASE / 4;
6336 find_edge (third_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
6337 find_edge (third_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
79acaae1 6338
bc7bff74 6339 if (!broken_loop)
6340 {
6341 ep = find_edge (cont_bb, body_bb);
6342 if (gimple_omp_for_combined_p (fd->for_stmt))
6343 {
6344 remove_edge (ep);
6345 ep = NULL;
6346 }
6347 else if (fd->collapse > 1)
6348 {
6349 remove_edge (ep);
6350 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6351 }
6352 else
6353 ep->flags = EDGE_TRUE_VALUE;
6354 find_edge (cont_bb, fin_bb)->flags
6355 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
6356 }
48e1416a 6357
31712e83 6358 set_immediate_dominator (CDI_DOMINATORS, second_bb, entry_bb);
6359 set_immediate_dominator (CDI_DOMINATORS, third_bb, entry_bb);
6360 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, third_bb);
bc7bff74 6361
79acaae1 6362 set_immediate_dominator (CDI_DOMINATORS, body_bb,
6363 recompute_dominator (CDI_DOMINATORS, body_bb));
6364 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
6365 recompute_dominator (CDI_DOMINATORS, fin_bb));
04c2922b 6366
bc7bff74 6367 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
6368 {
6369 struct loop *loop = alloc_loop ();
6370 loop->header = body_bb;
6371 if (collapse_bb == NULL)
6372 loop->latch = cont_bb;
6373 add_loop (loop, body_bb->loop_father);
6374 }
1e8e9920 6375}
6376
773c5ba7 6377
6378/* A subroutine of expand_omp_for. Generate code for a parallel
6379 loop with static schedule and a specified chunk size. Given
6380 parameters:
1e8e9920 6381
6382 for (V = N1; V cond N2; V += STEP) BODY;
6383
6384 where COND is "<" or ">", we generate pseudocode
6385
8e6b4515 6386 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
1e8e9920 6387 if (cond is <)
6388 adj = STEP - 1;
6389 else
6390 adj = STEP + 1;
fd6481cf 6391 if ((__typeof (V)) -1 > 0 && cond is >)
6392 n = -(adj + N2 - N1) / -STEP;
6393 else
6394 n = (adj + N2 - N1) / STEP;
1e8e9920 6395 trip = 0;
79acaae1 6396 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
6397 here so that V is defined
6398 if the loop is not entered
1e8e9920 6399 L0:
6400 s0 = (trip * nthreads + threadid) * CHUNK;
6401 e0 = min(s0 + CHUNK, n);
6402 if (s0 < n) goto L1; else goto L4;
6403 L1:
6404 V = s0 * STEP + N1;
6405 e = e0 * STEP + N1;
6406 L2:
6407 BODY;
6408 V += STEP;
6409 if (V cond e) goto L2; else goto L3;
6410 L3:
6411 trip += 1;
6412 goto L0;
6413 L4:
1e8e9920 6414*/
6415
61e47ac8 6416static void
bc7bff74 6417expand_omp_for_static_chunk (struct omp_region *region,
6418 struct omp_for_data *fd, gimple inner_stmt)
1e8e9920 6419{
75a70cf9 6420 tree n, s0, e0, e, t;
79acaae1 6421 tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
93481288 6422 tree type, itype, vmain, vback, vextra;
773c5ba7 6423 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
bc7bff74 6424 basic_block trip_update_bb = NULL, cont_bb, collapse_bb = NULL, fin_bb;
93481288 6425 gimple_stmt_iterator gsi;
75a70cf9 6426 edge se;
bc7bff74 6427 enum built_in_function get_num_threads = BUILT_IN_OMP_GET_NUM_THREADS;
6428 enum built_in_function get_thread_num = BUILT_IN_OMP_GET_THREAD_NUM;
6429 bool broken_loop = region->cont == NULL;
6430 tree *counts = NULL;
6431 tree n1, n2, step;
1e8e9920 6432
fd6481cf 6433 itype = type = TREE_TYPE (fd->loop.v);
6434 if (POINTER_TYPE_P (type))
3cea8318 6435 itype = signed_type_for (type);
1e8e9920 6436
61e47ac8 6437 entry_bb = region->entry;
ac6e3339 6438 se = split_block (entry_bb, last_stmt (entry_bb));
6439 entry_bb = se->src;
6440 iter_part_bb = se->dest;
61e47ac8 6441 cont_bb = region->cont;
ac6e3339 6442 gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
bc7bff74 6443 fin_bb = BRANCH_EDGE (iter_part_bb)->dest;
6444 gcc_assert (broken_loop
6445 || fin_bb == FALLTHRU_EDGE (cont_bb)->dest);
ac6e3339 6446 seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
6447 body_bb = single_succ (seq_start_bb);
bc7bff74 6448 if (!broken_loop)
6449 {
6450 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
6451 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6452 trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
6453 }
61e47ac8 6454 exit_bb = region->exit;
773c5ba7 6455
773c5ba7 6456 /* Trip and adjustment setup goes in ENTRY_BB. */
93481288 6457 gsi = gsi_last_bb (entry_bb);
6458 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
773c5ba7 6459
bc7bff74 6460 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
6461 {
6462 get_num_threads = BUILT_IN_OMP_GET_NUM_TEAMS;
6463 get_thread_num = BUILT_IN_OMP_GET_TEAM_NUM;
6464 }
6465
6466 if (fd->collapse > 1)
6467 {
6468 int first_zero_iter = -1;
6469 basic_block l2_dom_bb = NULL;
6470
6471 counts = XALLOCAVEC (tree, fd->collapse);
93481288 6472 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
bc7bff74 6473 fin_bb, first_zero_iter,
6474 l2_dom_bb);
6475 t = NULL_TREE;
6476 }
6477 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
6478 t = integer_one_node;
6479 else
6480 t = fold_binary (fd->loop.cond_code, boolean_type_node,
6481 fold_convert (type, fd->loop.n1),
6482 fold_convert (type, fd->loop.n2));
6483 if (fd->collapse == 1
6484 && TYPE_UNSIGNED (type)
8e6b4515 6485 && (t == NULL_TREE || !integer_onep (t)))
6486 {
8e6b4515 6487 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
93481288 6488 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
8e6b4515 6489 true, GSI_SAME_STMT);
6490 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
93481288 6491 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
8e6b4515 6492 true, GSI_SAME_STMT);
1a91d914 6493 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
6494 NULL_TREE, NULL_TREE);
6495 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
6496 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
8e6b4515 6497 expand_omp_regimplify_p, NULL, NULL)
1a91d914 6498 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
8e6b4515 6499 expand_omp_regimplify_p, NULL, NULL))
6500 {
1a91d914 6501 gsi = gsi_for_stmt (cond_stmt);
6502 gimple_regimplify_operands (cond_stmt, &gsi);
8e6b4515 6503 }
1a91d914 6504 se = split_block (entry_bb, cond_stmt);
8e6b4515 6505 se->flags = EDGE_TRUE_VALUE;
6506 entry_bb = se->dest;
6507 se->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
6508 se = make_edge (se->src, fin_bb, EDGE_FALSE_VALUE);
6509 se->probability = REG_BR_PROB_BASE / 2000 - 1;
6510 if (gimple_in_ssa_p (cfun))
6511 {
6512 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
1a91d914 6513 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
6514 !gsi_end_p (gpi); gsi_next (&gpi))
8e6b4515 6515 {
1a91d914 6516 gphi *phi = gpi.phi ();
8e6b4515 6517 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
6518 se, UNKNOWN_LOCATION);
6519 }
6520 }
93481288 6521 gsi = gsi_last_bb (entry_bb);
8e6b4515 6522 }
6523
bc7bff74 6524 t = build_call_expr (builtin_decl_explicit (get_num_threads), 0);
fd6481cf 6525 t = fold_convert (itype, t);
93481288 6526 nthreads = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
75a70cf9 6527 true, GSI_SAME_STMT);
48e1416a 6528
bc7bff74 6529 t = build_call_expr (builtin_decl_explicit (get_thread_num), 0);
fd6481cf 6530 t = fold_convert (itype, t);
93481288 6531 threadid = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
75a70cf9 6532 true, GSI_SAME_STMT);
79acaae1 6533
bc7bff74 6534 n1 = fd->loop.n1;
6535 n2 = fd->loop.n2;
6536 step = fd->loop.step;
6537 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6538 {
6539 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6540 OMP_CLAUSE__LOOPTEMP_);
6541 gcc_assert (innerc);
6542 n1 = OMP_CLAUSE_DECL (innerc);
6543 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6544 OMP_CLAUSE__LOOPTEMP_);
6545 gcc_assert (innerc);
6546 n2 = OMP_CLAUSE_DECL (innerc);
6547 }
93481288 6548 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
bc7bff74 6549 true, NULL_TREE, true, GSI_SAME_STMT);
93481288 6550 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
bc7bff74 6551 true, NULL_TREE, true, GSI_SAME_STMT);
93481288 6552 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
bc7bff74 6553 true, NULL_TREE, true, GSI_SAME_STMT);
79acaae1 6554 fd->chunk_size
93481288 6555 = force_gimple_operand_gsi (&gsi, fold_convert (itype, fd->chunk_size),
75a70cf9 6556 true, NULL_TREE, true, GSI_SAME_STMT);
fd6481cf 6557
6558 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
bc7bff74 6559 t = fold_build2 (PLUS_EXPR, itype, step, t);
6560 t = fold_build2 (PLUS_EXPR, itype, t, n2);
6561 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
fd6481cf 6562 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
6563 t = fold_build2 (TRUNC_DIV_EXPR, itype,
6564 fold_build1 (NEGATE_EXPR, itype, t),
bc7bff74 6565 fold_build1 (NEGATE_EXPR, itype, step));
fd6481cf 6566 else
bc7bff74 6567 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
fd6481cf 6568 t = fold_convert (itype, t);
93481288 6569 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
75a70cf9 6570 true, GSI_SAME_STMT);
79acaae1 6571
083152fb 6572 trip_var = create_tmp_reg (itype, ".trip");
79acaae1 6573 if (gimple_in_ssa_p (cfun))
6574 {
75a70cf9 6575 trip_init = make_ssa_name (trip_var, NULL);
6576 trip_main = make_ssa_name (trip_var, NULL);
6577 trip_back = make_ssa_name (trip_var, NULL);
79acaae1 6578 }
1e8e9920 6579 else
79acaae1 6580 {
6581 trip_init = trip_var;
6582 trip_main = trip_var;
6583 trip_back = trip_var;
6584 }
1e8e9920 6585
1a91d914 6586 gassign *assign_stmt
6587 = gimple_build_assign (trip_init, build_int_cst (itype, 0));
6588 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
773c5ba7 6589
fd6481cf 6590 t = fold_build2 (MULT_EXPR, itype, threadid, fd->chunk_size);
bc7bff74 6591 t = fold_build2 (MULT_EXPR, itype, t, step);
fd6481cf 6592 if (POINTER_TYPE_P (type))
bc7bff74 6593 t = fold_build_pointer_plus (n1, t);
fd6481cf 6594 else
bc7bff74 6595 t = fold_build2 (PLUS_EXPR, type, t, n1);
93481288 6596 vextra = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6597 true, GSI_SAME_STMT);
79acaae1 6598
75a70cf9 6599 /* Remove the GIMPLE_OMP_FOR. */
93481288 6600 gsi_remove (&gsi, true);
773c5ba7 6601
6602 /* Iteration space partitioning goes in ITER_PART_BB. */
93481288 6603 gsi = gsi_last_bb (iter_part_bb);
1e8e9920 6604
fd6481cf 6605 t = fold_build2 (MULT_EXPR, itype, trip_main, nthreads);
6606 t = fold_build2 (PLUS_EXPR, itype, t, threadid);
6607 t = fold_build2 (MULT_EXPR, itype, t, fd->chunk_size);
93481288 6608 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
75a70cf9 6609 false, GSI_CONTINUE_LINKING);
1e8e9920 6610
fd6481cf 6611 t = fold_build2 (PLUS_EXPR, itype, s0, fd->chunk_size);
6612 t = fold_build2 (MIN_EXPR, itype, t, n);
93481288 6613 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
75a70cf9 6614 false, GSI_CONTINUE_LINKING);
1e8e9920 6615
6616 t = build2 (LT_EXPR, boolean_type_node, s0, n);
93481288 6617 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_CONTINUE_LINKING);
773c5ba7 6618
6619 /* Setup code for sequential iteration goes in SEQ_START_BB. */
93481288 6620 gsi = gsi_start_bb (seq_start_bb);
1e8e9920 6621
bc7bff74 6622 tree startvar = fd->loop.v;
6623 tree endvar = NULL_TREE;
6624
6625 if (gimple_omp_for_combined_p (fd->for_stmt))
6626 {
6627 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
6628 ? gimple_omp_parallel_clauses (inner_stmt)
6629 : gimple_omp_for_clauses (inner_stmt);
6630 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
6631 gcc_assert (innerc);
6632 startvar = OMP_CLAUSE_DECL (innerc);
6633 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6634 OMP_CLAUSE__LOOPTEMP_);
6635 gcc_assert (innerc);
6636 endvar = OMP_CLAUSE_DECL (innerc);
6637 }
6638
fd6481cf 6639 t = fold_convert (itype, s0);
bc7bff74 6640 t = fold_build2 (MULT_EXPR, itype, t, step);
fd6481cf 6641 if (POINTER_TYPE_P (type))
bc7bff74 6642 t = fold_build_pointer_plus (n1, t);
fd6481cf 6643 else
bc7bff74 6644 t = fold_build2 (PLUS_EXPR, type, t, n1);
6645 t = fold_convert (TREE_TYPE (startvar), t);
93481288 6646 t = force_gimple_operand_gsi (&gsi, t,
bc7bff74 6647 DECL_P (startvar)
6648 && TREE_ADDRESSABLE (startvar),
4abecb72 6649 NULL_TREE, false, GSI_CONTINUE_LINKING);
1a91d914 6650 assign_stmt = gimple_build_assign (startvar, t);
6651 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
1e8e9920 6652
fd6481cf 6653 t = fold_convert (itype, e0);
bc7bff74 6654 t = fold_build2 (MULT_EXPR, itype, t, step);
fd6481cf 6655 if (POINTER_TYPE_P (type))
bc7bff74 6656 t = fold_build_pointer_plus (n1, t);
fd6481cf 6657 else
bc7bff74 6658 t = fold_build2 (PLUS_EXPR, type, t, n1);
6659 t = fold_convert (TREE_TYPE (startvar), t);
93481288 6660 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
75a70cf9 6661 false, GSI_CONTINUE_LINKING);
bc7bff74 6662 if (endvar)
6663 {
1a91d914 6664 assign_stmt = gimple_build_assign (endvar, e);
6665 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
d44f2f7c 6666 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
1a91d914 6667 assign_stmt = gimple_build_assign (fd->loop.v, e);
d44f2f7c 6668 else
1a91d914 6669 assign_stmt = gimple_build_assign_with_ops (NOP_EXPR, fd->loop.v, e);
6670 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
bc7bff74 6671 }
6672 if (fd->collapse > 1)
93481288 6673 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
bc7bff74 6674
6675 if (!broken_loop)
6676 {
6677 /* The code controlling the sequential loop goes in CONT_BB,
6678 replacing the GIMPLE_OMP_CONTINUE. */
93481288 6679 gsi = gsi_last_bb (cont_bb);
1a91d914 6680 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
6681 vmain = gimple_omp_continue_control_use (cont_stmt);
6682 vback = gimple_omp_continue_control_def (cont_stmt);
1e8e9920 6683
bc7bff74 6684 if (!gimple_omp_for_combined_p (fd->for_stmt))
6685 {
6686 if (POINTER_TYPE_P (type))
93481288 6687 t = fold_build_pointer_plus (vmain, step);
bc7bff74 6688 else
93481288 6689 t = fold_build2 (PLUS_EXPR, type, vmain, step);
6690 if (DECL_P (vback) && TREE_ADDRESSABLE (vback))
6691 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
bc7bff74 6692 true, GSI_SAME_STMT);
1a91d914 6693 assign_stmt = gimple_build_assign (vback, t);
6694 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
79acaae1 6695
bc7bff74 6696 t = build2 (fd->loop.cond_code, boolean_type_node,
93481288 6697 DECL_P (vback) && TREE_ADDRESSABLE (vback)
6698 ? t : vback, e);
6699 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
bc7bff74 6700 }
79acaae1 6701
bc7bff74 6702 /* Remove GIMPLE_OMP_CONTINUE. */
93481288 6703 gsi_remove (&gsi, true);
48e1416a 6704
bc7bff74 6705 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
6706 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
773c5ba7 6707
bc7bff74 6708 /* Trip update code goes into TRIP_UPDATE_BB. */
93481288 6709 gsi = gsi_start_bb (trip_update_bb);
1e8e9920 6710
bc7bff74 6711 t = build_int_cst (itype, 1);
6712 t = build2 (PLUS_EXPR, itype, trip_main, t);
1a91d914 6713 assign_stmt = gimple_build_assign (trip_back, t);
6714 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
bc7bff74 6715 }
1e8e9920 6716
75a70cf9 6717 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
93481288 6718 gsi = gsi_last_bb (exit_bb);
6719 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
bc7bff74 6720 {
93481288 6721 t = gimple_omp_return_lhs (gsi_stmt (gsi));
6722 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
bc7bff74 6723 }
93481288 6724 gsi_remove (&gsi, true);
1e8e9920 6725
773c5ba7 6726 /* Connect the new blocks. */
ac6e3339 6727 find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
6728 find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
79acaae1 6729
bc7bff74 6730 if (!broken_loop)
6731 {
6732 se = find_edge (cont_bb, body_bb);
6733 if (gimple_omp_for_combined_p (fd->for_stmt))
6734 {
6735 remove_edge (se);
6736 se = NULL;
6737 }
6738 else if (fd->collapse > 1)
6739 {
6740 remove_edge (se);
6741 se = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6742 }
6743 else
6744 se->flags = EDGE_TRUE_VALUE;
6745 find_edge (cont_bb, trip_update_bb)->flags
6746 = se ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
79acaae1 6747
bc7bff74 6748 redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb);
6749 }
79acaae1 6750
6751 if (gimple_in_ssa_p (cfun))
6752 {
1a91d914 6753 gphi_iterator psi;
6754 gphi *phi;
75a70cf9 6755 edge re, ene;
75a70cf9 6756 edge_var_map *vm;
6757 size_t i;
6758
bc7bff74 6759 gcc_assert (fd->collapse == 1 && !broken_loop);
6760
79acaae1 6761 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
6762 remove arguments of the phi nodes in fin_bb. We need to create
6763 appropriate phi nodes in iter_part_bb instead. */
6764 se = single_pred_edge (fin_bb);
6765 re = single_succ_edge (trip_update_bb);
06ecf488 6766 vec<edge_var_map> *head = redirect_edge_var_map_vector (re);
79acaae1 6767 ene = single_succ_edge (entry_bb);
6768
75a70cf9 6769 psi = gsi_start_phis (fin_bb);
f1f41a6c 6770 for (i = 0; !gsi_end_p (psi) && head->iterate (i, &vm);
75a70cf9 6771 gsi_next (&psi), ++i)
79acaae1 6772 {
1a91d914 6773 gphi *nphi;
efbcb6de 6774 source_location locus;
75a70cf9 6775
1a91d914 6776 phi = psi.phi ();
75a70cf9 6777 t = gimple_phi_result (phi);
6778 gcc_assert (t == redirect_edge_var_map_result (vm));
79acaae1 6779 nphi = create_phi_node (t, iter_part_bb);
79acaae1 6780
6781 t = PHI_ARG_DEF_FROM_EDGE (phi, se);
efbcb6de 6782 locus = gimple_phi_arg_location_from_edge (phi, se);
6783
fd6481cf 6784 /* A special case -- fd->loop.v is not yet computed in
93481288 6785 iter_part_bb, we need to use vextra instead. */
fd6481cf 6786 if (t == fd->loop.v)
93481288 6787 t = vextra;
60d535d2 6788 add_phi_arg (nphi, t, ene, locus);
efbcb6de 6789 locus = redirect_edge_var_map_location (vm);
60d535d2 6790 add_phi_arg (nphi, redirect_edge_var_map_def (vm), re, locus);
75a70cf9 6791 }
f1f41a6c 6792 gcc_assert (!gsi_end_p (psi) && i == head->length ());
75a70cf9 6793 redirect_edge_var_map_clear (re);
6794 while (1)
6795 {
6796 psi = gsi_start_phis (fin_bb);
6797 if (gsi_end_p (psi))
6798 break;
6799 remove_phi_node (&psi, false);
79acaae1 6800 }
79acaae1 6801
6802 /* Make phi node for trip. */
6803 phi = create_phi_node (trip_main, iter_part_bb);
efbcb6de 6804 add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb),
60d535d2 6805 UNKNOWN_LOCATION);
efbcb6de 6806 add_phi_arg (phi, trip_init, single_succ_edge (entry_bb),
60d535d2 6807 UNKNOWN_LOCATION);
79acaae1 6808 }
6809
bc7bff74 6810 if (!broken_loop)
6811 set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
79acaae1 6812 set_immediate_dominator (CDI_DOMINATORS, iter_part_bb,
6813 recompute_dominator (CDI_DOMINATORS, iter_part_bb));
6814 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
6815 recompute_dominator (CDI_DOMINATORS, fin_bb));
6816 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb,
6817 recompute_dominator (CDI_DOMINATORS, seq_start_bb));
6818 set_immediate_dominator (CDI_DOMINATORS, body_bb,
6819 recompute_dominator (CDI_DOMINATORS, body_bb));
04c2922b 6820
bc7bff74 6821 if (!broken_loop)
6822 {
6823 struct loop *trip_loop = alloc_loop ();
6824 trip_loop->header = iter_part_bb;
6825 trip_loop->latch = trip_update_bb;
6826 add_loop (trip_loop, iter_part_bb->loop_father);
04c2922b 6827
bc7bff74 6828 if (!gimple_omp_for_combined_p (fd->for_stmt))
6829 {
6830 struct loop *loop = alloc_loop ();
6831 loop->header = body_bb;
33ee4d72 6832 if (collapse_bb == NULL)
6833 loop->latch = cont_bb;
bc7bff74 6834 add_loop (loop, trip_loop);
6835 }
6836 }
1e8e9920 6837}
6838
40750995 6839/* A subroutine of expand_omp_for. Generate code for _Cilk_for loop.
6840 Given parameters:
6841 for (V = N1; V cond N2; V += STEP) BODY;
6842
6843 where COND is "<" or ">" or "!=", we generate pseudocode
6844
6845 for (ind_var = low; ind_var < high; ind_var++)
6846 {
6847 V = n1 + (ind_var * STEP)
6848
6849 <BODY>
6850 }
6851
6852 In the above pseudocode, low and high are function parameters of the
6853 child function. In the function below, we are inserting a temp.
6854 variable that will be making a call to two OMP functions that will not be
6855 found in the body of _Cilk_for (since OMP_FOR cannot be mixed
6856 with _Cilk_for). These functions are replaced with low and high
6857 by the function that handles taskreg. */
6858
6859
6860static void
6861expand_cilk_for (struct omp_region *region, struct omp_for_data *fd)
6862{
6863 bool broken_loop = region->cont == NULL;
6864 basic_block entry_bb = region->entry;
6865 basic_block cont_bb = region->cont;
6866
6867 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
6868 gcc_assert (broken_loop
6869 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
6870 basic_block l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
6871 basic_block l1_bb, l2_bb;
6872
6873 if (!broken_loop)
6874 {
6875 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
6876 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6877 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
6878 l2_bb = BRANCH_EDGE (entry_bb)->dest;
6879 }
6880 else
6881 {
6882 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
6883 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
6884 l2_bb = single_succ (l1_bb);
6885 }
6886 basic_block exit_bb = region->exit;
6887 basic_block l2_dom_bb = NULL;
6888
6889 gimple_stmt_iterator gsi = gsi_last_bb (entry_bb);
6890
6891 /* Below statements until the "tree high_val = ..." are pseudo statements
6892 used to pass information to be used by expand_omp_taskreg.
6893 low_val and high_val will be replaced by the __low and __high
6894 parameter from the child function.
6895
6896 The call_exprs part is a place-holder, it is mainly used
6897 to distinctly identify to the top-level part that this is
6898 where we should put low and high (reasoning given in header
6899 comment). */
6900
6901 tree child_fndecl
1a91d914 6902 = gimple_omp_parallel_child_fn (
6903 as_a <gomp_parallel *> (last_stmt (region->outer->entry)));
40750995 6904 tree t, low_val = NULL_TREE, high_val = NULL_TREE;
6905 for (t = DECL_ARGUMENTS (child_fndecl); t; t = TREE_CHAIN (t))
6906 {
6907 if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__high"))
6908 high_val = t;
6909 else if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__low"))
6910 low_val = t;
6911 }
6912 gcc_assert (low_val && high_val);
6913
6914 tree type = TREE_TYPE (low_val);
6915 tree ind_var = create_tmp_reg (type, "__cilk_ind_var");
6916 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6917
6918 /* Not needed in SSA form right now. */
6919 gcc_assert (!gimple_in_ssa_p (cfun));
6920 if (l2_dom_bb == NULL)
6921 l2_dom_bb = l1_bb;
6922
6923 tree n1 = low_val;
6924 tree n2 = high_val;
6925
6926 gimple stmt = gimple_build_assign (ind_var, n1);
6927
6928 /* Replace the GIMPLE_OMP_FOR statement. */
6929 gsi_replace (&gsi, stmt, true);
6930
6931 if (!broken_loop)
6932 {
6933 /* Code to control the increment goes in the CONT_BB. */
6934 gsi = gsi_last_bb (cont_bb);
6935 stmt = gsi_stmt (gsi);
6936 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
6937 stmt = gimple_build_assign_with_ops (PLUS_EXPR, ind_var, ind_var,
6938 build_one_cst (type));
6939
6940 /* Replace GIMPLE_OMP_CONTINUE. */
6941 gsi_replace (&gsi, stmt, true);
6942 }
6943
6944 /* Emit the condition in L1_BB. */
6945 gsi = gsi_after_labels (l1_bb);
6946 t = fold_build2 (MULT_EXPR, TREE_TYPE (fd->loop.step),
6947 fold_convert (TREE_TYPE (fd->loop.step), ind_var),
6948 fd->loop.step);
6949 if (POINTER_TYPE_P (TREE_TYPE (fd->loop.n1)))
6950 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (fd->loop.n1),
6951 fd->loop.n1, fold_convert (sizetype, t));
6952 else
6953 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loop.n1),
6954 fd->loop.n1, fold_convert (TREE_TYPE (fd->loop.n1), t));
6955 t = fold_convert (TREE_TYPE (fd->loop.v), t);
6956 expand_omp_build_assign (&gsi, fd->loop.v, t);
6957
6958 /* The condition is always '<' since the runtime will fill in the low
6959 and high values. */
6960 stmt = gimple_build_cond (LT_EXPR, ind_var, n2, NULL_TREE, NULL_TREE);
6961 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
6962
6963 /* Remove GIMPLE_OMP_RETURN. */
6964 gsi = gsi_last_bb (exit_bb);
6965 gsi_remove (&gsi, true);
6966
6967 /* Connect the new blocks. */
6968 remove_edge (FALLTHRU_EDGE (entry_bb));
6969
6970 edge e, ne;
6971 if (!broken_loop)
6972 {
6973 remove_edge (BRANCH_EDGE (entry_bb));
6974 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
6975
6976 e = BRANCH_EDGE (l1_bb);
6977 ne = FALLTHRU_EDGE (l1_bb);
6978 e->flags = EDGE_TRUE_VALUE;
6979 }
6980 else
6981 {
6982 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
6983
6984 ne = single_succ_edge (l1_bb);
6985 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
6986
6987 }
6988 ne->flags = EDGE_FALSE_VALUE;
6989 e->probability = REG_BR_PROB_BASE * 7 / 8;
6990 ne->probability = REG_BR_PROB_BASE / 8;
6991
6992 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
6993 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
6994 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
6995
6996 if (!broken_loop)
6997 {
6998 struct loop *loop = alloc_loop ();
6999 loop->header = l1_bb;
7000 loop->latch = cont_bb;
7001 add_loop (loop, l1_bb->loop_father);
7002 loop->safelen = INT_MAX;
7003 }
7004
7005 /* Pick the correct library function based on the precision of the
7006 induction variable type. */
7007 tree lib_fun = NULL_TREE;
7008 if (TYPE_PRECISION (type) == 32)
7009 lib_fun = cilk_for_32_fndecl;
7010 else if (TYPE_PRECISION (type) == 64)
7011 lib_fun = cilk_for_64_fndecl;
7012 else
7013 gcc_unreachable ();
7014
7015 gcc_assert (fd->sched_kind == OMP_CLAUSE_SCHEDULE_CILKFOR);
7016
7017 /* WS_ARGS contains the library function flavor to call:
7018 __libcilkrts_cilk_for_64 or __libcilkrts_cilk_for_32), and the
7019 user-defined grain value. If the user does not define one, then zero
7020 is passed in by the parser. */
7021 vec_alloc (region->ws_args, 2);
7022 region->ws_args->quick_push (lib_fun);
7023 region->ws_args->quick_push (fd->chunk_size);
7024}
bc7bff74 7025
3d483a94 7026/* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
7027 loop. Given parameters:
7028
7029 for (V = N1; V cond N2; V += STEP) BODY;
7030
7031 where COND is "<" or ">", we generate pseudocode
7032
7033 V = N1;
7034 goto L1;
7035 L0:
7036 BODY;
7037 V += STEP;
7038 L1:
7039 if (V cond N2) goto L0; else goto L2;
7040 L2:
7041
7042 For collapsed loops, given parameters:
7043 collapse(3)
7044 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
7045 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
7046 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
7047 BODY;
7048
7049 we generate pseudocode
7050
7051 if (cond3 is <)
7052 adj = STEP3 - 1;
7053 else
7054 adj = STEP3 + 1;
7055 count3 = (adj + N32 - N31) / STEP3;
7056 if (cond2 is <)
7057 adj = STEP2 - 1;
7058 else
7059 adj = STEP2 + 1;
7060 count2 = (adj + N22 - N21) / STEP2;
7061 if (cond1 is <)
7062 adj = STEP1 - 1;
7063 else
7064 adj = STEP1 + 1;
7065 count1 = (adj + N12 - N11) / STEP1;
7066 count = count1 * count2 * count3;
7067 V = 0;
7068 V1 = N11;
7069 V2 = N21;
7070 V3 = N31;
7071 goto L1;
7072 L0:
7073 BODY;
7074 V += 1;
7075 V3 += STEP3;
7076 V2 += (V3 cond3 N32) ? 0 : STEP2;
7077 V3 = (V3 cond3 N32) ? V3 : N31;
7078 V1 += (V2 cond2 N22) ? 0 : STEP1;
7079 V2 = (V2 cond2 N22) ? V2 : N21;
7080 L1:
7081 if (V < count) goto L0; else goto L2;
7082 L2:
7083
7084 */
7085
7086static void
7087expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
7088{
7089 tree type, t;
7090 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, l2_bb, l2_dom_bb;
7091 gimple_stmt_iterator gsi;
7092 gimple stmt;
1a91d914 7093 gcond *cond_stmt;
3d483a94 7094 bool broken_loop = region->cont == NULL;
7095 edge e, ne;
7096 tree *counts = NULL;
7097 int i;
7098 tree safelen = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7099 OMP_CLAUSE_SAFELEN);
7100 tree simduid = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7101 OMP_CLAUSE__SIMDUID_);
bc7bff74 7102 tree n1, n2;
3d483a94 7103
7104 type = TREE_TYPE (fd->loop.v);
7105 entry_bb = region->entry;
7106 cont_bb = region->cont;
7107 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
7108 gcc_assert (broken_loop
7109 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
7110 l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
7111 if (!broken_loop)
7112 {
7113 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
7114 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
7115 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
7116 l2_bb = BRANCH_EDGE (entry_bb)->dest;
7117 }
7118 else
7119 {
7120 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
7121 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
7122 l2_bb = single_succ (l1_bb);
7123 }
7124 exit_bb = region->exit;
7125 l2_dom_bb = NULL;
7126
7127 gsi = gsi_last_bb (entry_bb);
7128
7129 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
7130 /* Not needed in SSA form right now. */
7131 gcc_assert (!gimple_in_ssa_p (cfun));
7132 if (fd->collapse > 1)
7133 {
7134 int first_zero_iter = -1;
7135 basic_block zero_iter_bb = l2_bb;
7136
7137 counts = XALLOCAVEC (tree, fd->collapse);
7138 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
7139 zero_iter_bb, first_zero_iter,
7140 l2_dom_bb);
7141 }
7142 if (l2_dom_bb == NULL)
7143 l2_dom_bb = l1_bb;
7144
bc7bff74 7145 n1 = fd->loop.n1;
3d483a94 7146 n2 = fd->loop.n2;
bc7bff74 7147 if (gimple_omp_for_combined_into_p (fd->for_stmt))
7148 {
7149 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7150 OMP_CLAUSE__LOOPTEMP_);
7151 gcc_assert (innerc);
7152 n1 = OMP_CLAUSE_DECL (innerc);
7153 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7154 OMP_CLAUSE__LOOPTEMP_);
7155 gcc_assert (innerc);
7156 n2 = OMP_CLAUSE_DECL (innerc);
7157 expand_omp_build_assign (&gsi, fd->loop.v,
7158 fold_convert (type, n1));
7159 if (fd->collapse > 1)
7160 {
7161 gsi_prev (&gsi);
7162 expand_omp_for_init_vars (fd, &gsi, counts, NULL, n1);
7163 gsi_next (&gsi);
7164 }
7165 }
3d483a94 7166 else
7167 {
7168 expand_omp_build_assign (&gsi, fd->loop.v,
7169 fold_convert (type, fd->loop.n1));
7170 if (fd->collapse > 1)
7171 for (i = 0; i < fd->collapse; i++)
7172 {
7173 tree itype = TREE_TYPE (fd->loops[i].v);
7174 if (POINTER_TYPE_P (itype))
7175 itype = signed_type_for (itype);
7176 t = fold_convert (TREE_TYPE (fd->loops[i].v), fd->loops[i].n1);
7177 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7178 }
7179 }
7180
7181 /* Remove the GIMPLE_OMP_FOR statement. */
7182 gsi_remove (&gsi, true);
7183
7184 if (!broken_loop)
7185 {
7186 /* Code to control the increment goes in the CONT_BB. */
7187 gsi = gsi_last_bb (cont_bb);
7188 stmt = gsi_stmt (gsi);
7189 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
7190
7191 if (POINTER_TYPE_P (type))
7192 t = fold_build_pointer_plus (fd->loop.v, fd->loop.step);
7193 else
7194 t = fold_build2 (PLUS_EXPR, type, fd->loop.v, fd->loop.step);
7195 expand_omp_build_assign (&gsi, fd->loop.v, t);
7196
7197 if (fd->collapse > 1)
7198 {
7199 i = fd->collapse - 1;
7200 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
7201 {
7202 t = fold_convert (sizetype, fd->loops[i].step);
7203 t = fold_build_pointer_plus (fd->loops[i].v, t);
7204 }
7205 else
7206 {
7207 t = fold_convert (TREE_TYPE (fd->loops[i].v),
7208 fd->loops[i].step);
7209 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
7210 fd->loops[i].v, t);
7211 }
7212 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7213
7214 for (i = fd->collapse - 1; i > 0; i--)
7215 {
7216 tree itype = TREE_TYPE (fd->loops[i].v);
7217 tree itype2 = TREE_TYPE (fd->loops[i - 1].v);
7218 if (POINTER_TYPE_P (itype2))
7219 itype2 = signed_type_for (itype2);
7220 t = build3 (COND_EXPR, itype2,
7221 build2 (fd->loops[i].cond_code, boolean_type_node,
7222 fd->loops[i].v,
7223 fold_convert (itype, fd->loops[i].n2)),
7224 build_int_cst (itype2, 0),
7225 fold_convert (itype2, fd->loops[i - 1].step));
7226 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i - 1].v)))
7227 t = fold_build_pointer_plus (fd->loops[i - 1].v, t);
7228 else
7229 t = fold_build2 (PLUS_EXPR, itype2, fd->loops[i - 1].v, t);
7230 expand_omp_build_assign (&gsi, fd->loops[i - 1].v, t);
7231
7232 t = build3 (COND_EXPR, itype,
7233 build2 (fd->loops[i].cond_code, boolean_type_node,
7234 fd->loops[i].v,
7235 fold_convert (itype, fd->loops[i].n2)),
7236 fd->loops[i].v,
7237 fold_convert (itype, fd->loops[i].n1));
7238 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7239 }
7240 }
7241
7242 /* Remove GIMPLE_OMP_CONTINUE. */
7243 gsi_remove (&gsi, true);
7244 }
7245
7246 /* Emit the condition in L1_BB. */
7247 gsi = gsi_start_bb (l1_bb);
7248
7249 t = fold_convert (type, n2);
7250 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7251 false, GSI_CONTINUE_LINKING);
7252 t = build2 (fd->loop.cond_code, boolean_type_node, fd->loop.v, t);
1a91d914 7253 cond_stmt = gimple_build_cond_empty (t);
7254 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
7255 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt), expand_omp_regimplify_p,
3d483a94 7256 NULL, NULL)
1a91d914 7257 || walk_tree (gimple_cond_rhs_ptr (cond_stmt), expand_omp_regimplify_p,
3d483a94 7258 NULL, NULL))
7259 {
1a91d914 7260 gsi = gsi_for_stmt (cond_stmt);
7261 gimple_regimplify_operands (cond_stmt, &gsi);
3d483a94 7262 }
7263
7264 /* Remove GIMPLE_OMP_RETURN. */
7265 gsi = gsi_last_bb (exit_bb);
7266 gsi_remove (&gsi, true);
7267
7268 /* Connect the new blocks. */
7269 remove_edge (FALLTHRU_EDGE (entry_bb));
7270
7271 if (!broken_loop)
7272 {
7273 remove_edge (BRANCH_EDGE (entry_bb));
7274 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
7275
7276 e = BRANCH_EDGE (l1_bb);
7277 ne = FALLTHRU_EDGE (l1_bb);
7278 e->flags = EDGE_TRUE_VALUE;
7279 }
7280 else
7281 {
7282 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7283
7284 ne = single_succ_edge (l1_bb);
7285 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
7286
7287 }
7288 ne->flags = EDGE_FALSE_VALUE;
7289 e->probability = REG_BR_PROB_BASE * 7 / 8;
7290 ne->probability = REG_BR_PROB_BASE / 8;
7291
7292 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
7293 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
7294 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
7295
7296 if (!broken_loop)
7297 {
7298 struct loop *loop = alloc_loop ();
7299 loop->header = l1_bb;
33ee4d72 7300 loop->latch = cont_bb;
3d483a94 7301 add_loop (loop, l1_bb->loop_father);
7302 if (safelen == NULL_TREE)
7303 loop->safelen = INT_MAX;
7304 else
7305 {
7306 safelen = OMP_CLAUSE_SAFELEN_EXPR (safelen);
c3f3b68d 7307 if (TREE_CODE (safelen) != INTEGER_CST)
7308 loop->safelen = 0;
7309 else if (!tree_fits_uhwi_p (safelen)
7310 || tree_to_uhwi (safelen) > INT_MAX)
3d483a94 7311 loop->safelen = INT_MAX;
7312 else
d85a2013 7313 loop->safelen = tree_to_uhwi (safelen);
3d483a94 7314 if (loop->safelen == 1)
7315 loop->safelen = 0;
7316 }
7317 if (simduid)
7318 {
7319 loop->simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
7320 cfun->has_simduid_loops = true;
7321 }
043115ec 7322 /* If not -fno-tree-loop-vectorize, hint that we want to vectorize
3d483a94 7323 the loop. */
043115ec 7324 if ((flag_tree_loop_vectorize
7325 || (!global_options_set.x_flag_tree_loop_vectorize
7326 && !global_options_set.x_flag_tree_vectorize))
ad45e43e 7327 && flag_tree_loop_optimize
3d483a94 7328 && loop->safelen > 1)
7329 {
4c73695b 7330 loop->force_vectorize = true;
7331 cfun->has_force_vectorize_loops = true;
3d483a94 7332 }
7333 }
7334}
7335
1e8e9920 7336
773c5ba7 7337/* Expand the OpenMP loop defined by REGION. */
1e8e9920 7338
773c5ba7 7339static void
bc7bff74 7340expand_omp_for (struct omp_region *region, gimple inner_stmt)
773c5ba7 7341{
7342 struct omp_for_data fd;
fd6481cf 7343 struct omp_for_data_loop *loops;
1e8e9920 7344
fd6481cf 7345 loops
7346 = (struct omp_for_data_loop *)
75a70cf9 7347 alloca (gimple_omp_for_collapse (last_stmt (region->entry))
fd6481cf 7348 * sizeof (struct omp_for_data_loop));
1a91d914 7349 extract_omp_for_data (as_a <gomp_for *> (last_stmt (region->entry)),
7350 &fd, loops);
f77459c5 7351 region->sched_kind = fd.sched_kind;
1e8e9920 7352
b3a3ddec 7353 gcc_assert (EDGE_COUNT (region->entry->succs) == 2);
7354 BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
7355 FALLTHRU_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
7356 if (region->cont)
7357 {
7358 gcc_assert (EDGE_COUNT (region->cont->succs) == 2);
7359 BRANCH_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
7360 FALLTHRU_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
7361 }
04c2922b 7362 else
75de4aa2 7363 /* If there isn't a continue then this is a degerate case where
04c2922b 7364 the introduction of abnormal edges during lowering will prevent
7365 original loops from being detected. Fix that up. */
7366 loops_state_set (LOOPS_NEED_FIXUP);
b3a3ddec 7367
10c55644 7368 if (gimple_omp_for_kind (fd.for_stmt) & GF_OMP_FOR_SIMD)
3d483a94 7369 expand_omp_simd (region, &fd);
40750995 7370 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
7371 expand_cilk_for (region, &fd);
3d483a94 7372 else if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
bc7bff74 7373 && !fd.have_ordered)
1e8e9920 7374 {
7375 if (fd.chunk_size == NULL)
bc7bff74 7376 expand_omp_for_static_nochunk (region, &fd, inner_stmt);
1e8e9920 7377 else
bc7bff74 7378 expand_omp_for_static_chunk (region, &fd, inner_stmt);
1e8e9920 7379 }
7380 else
7381 {
fd6481cf 7382 int fn_index, start_ix, next_ix;
7383
3d483a94 7384 gcc_assert (gimple_omp_for_kind (fd.for_stmt)
7385 == GF_OMP_FOR_KIND_FOR);
0416ca72 7386 if (fd.chunk_size == NULL
7387 && fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
7388 fd.chunk_size = integer_zero_node;
fd6481cf 7389 gcc_assert (fd.sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
7390 fn_index = (fd.sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
75a70cf9 7391 ? 3 : fd.sched_kind;
fd6481cf 7392 fn_index += fd.have_ordered * 4;
b9a16870 7393 start_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_START) + fn_index;
7394 next_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT) + fn_index;
fd6481cf 7395 if (fd.iter_type == long_long_unsigned_type_node)
7396 {
b9a16870 7397 start_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
7398 - (int)BUILT_IN_GOMP_LOOP_STATIC_START);
7399 next_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
7400 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT);
fd6481cf 7401 }
b9c74b4d 7402 expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
bc7bff74 7403 (enum built_in_function) next_ix, inner_stmt);
1e8e9920 7404 }
28c92cbb 7405
083152fb 7406 if (gimple_in_ssa_p (cfun))
7407 update_ssa (TODO_update_ssa_only_virtuals);
1e8e9920 7408}
7409
1e8e9920 7410
7411/* Expand code for an OpenMP sections directive. In pseudo code, we generate
7412
1e8e9920 7413 v = GOMP_sections_start (n);
7414 L0:
7415 switch (v)
7416 {
7417 case 0:
7418 goto L2;
7419 case 1:
7420 section 1;
7421 goto L1;
7422 case 2:
7423 ...
7424 case n:
7425 ...
1e8e9920 7426 default:
7427 abort ();
7428 }
7429 L1:
7430 v = GOMP_sections_next ();
7431 goto L0;
7432 L2:
7433 reduction;
7434
773c5ba7 7435 If this is a combined parallel sections, replace the call to
79acaae1 7436 GOMP_sections_start with call to GOMP_sections_next. */
1e8e9920 7437
7438static void
773c5ba7 7439expand_omp_sections (struct omp_region *region)
1e8e9920 7440{
f018d957 7441 tree t, u, vin = NULL, vmain, vnext, l2;
75a70cf9 7442 unsigned len;
ac6e3339 7443 basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
75a70cf9 7444 gimple_stmt_iterator si, switch_si;
1a91d914 7445 gomp_sections *sections_stmt;
7446 gimple stmt;
7447 gomp_continue *cont;
9884aaf8 7448 edge_iterator ei;
7449 edge e;
61e47ac8 7450 struct omp_region *inner;
75a70cf9 7451 unsigned i, casei;
ac6e3339 7452 bool exit_reachable = region->cont != NULL;
1e8e9920 7453
d244d9de 7454 gcc_assert (region->exit != NULL);
61e47ac8 7455 entry_bb = region->entry;
ac6e3339 7456 l0_bb = single_succ (entry_bb);
61e47ac8 7457 l1_bb = region->cont;
ac6e3339 7458 l2_bb = region->exit;
d244d9de 7459 if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
7460 l2 = gimple_block_label (l2_bb);
7461 else
03ed154b 7462 {
d244d9de 7463 /* This can happen if there are reductions. */
7464 len = EDGE_COUNT (l0_bb->succs);
7465 gcc_assert (len > 0);
7466 e = EDGE_SUCC (l0_bb, len - 1);
7467 si = gsi_last_bb (e->dest);
7468 l2 = NULL_TREE;
7469 if (gsi_end_p (si)
7470 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
7471 l2 = gimple_block_label (e->dest);
9884aaf8 7472 else
d244d9de 7473 FOR_EACH_EDGE (e, ei, l0_bb->succs)
7474 {
7475 si = gsi_last_bb (e->dest);
7476 if (gsi_end_p (si)
7477 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
9884aaf8 7478 {
d244d9de 7479 l2 = gimple_block_label (e->dest);
7480 break;
9884aaf8 7481 }
d244d9de 7482 }
03ed154b 7483 }
d244d9de 7484 if (exit_reachable)
7485 default_bb = create_empty_bb (l1_bb->prev_bb);
03ed154b 7486 else
d244d9de 7487 default_bb = create_empty_bb (l0_bb);
773c5ba7 7488
7489 /* We will build a switch() with enough cases for all the
75a70cf9 7490 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
773c5ba7 7491 and a default case to abort if something goes wrong. */
ac6e3339 7492 len = EDGE_COUNT (l0_bb->succs);
75a70cf9 7493
f1f41a6c 7494 /* Use vec::quick_push on label_vec throughout, since we know the size
75a70cf9 7495 in advance. */
c2078b80 7496 auto_vec<tree> label_vec (len);
1e8e9920 7497
61e47ac8 7498 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
75a70cf9 7499 GIMPLE_OMP_SECTIONS statement. */
7500 si = gsi_last_bb (entry_bb);
1a91d914 7501 sections_stmt = as_a <gomp_sections *> (gsi_stmt (si));
75a70cf9 7502 gcc_assert (gimple_code (sections_stmt) == GIMPLE_OMP_SECTIONS);
7503 vin = gimple_omp_sections_control (sections_stmt);
773c5ba7 7504 if (!is_combined_parallel (region))
1e8e9920 7505 {
773c5ba7 7506 /* If we are not inside a combined parallel+sections region,
7507 call GOMP_sections_start. */
39cb6d68 7508 t = build_int_cst (unsigned_type_node, len - 1);
b9a16870 7509 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START);
75a70cf9 7510 stmt = gimple_build_call (u, 1, t);
1e8e9920 7511 }
79acaae1 7512 else
7513 {
7514 /* Otherwise, call GOMP_sections_next. */
b9a16870 7515 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
75a70cf9 7516 stmt = gimple_build_call (u, 0);
79acaae1 7517 }
75a70cf9 7518 gimple_call_set_lhs (stmt, vin);
7519 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
7520 gsi_remove (&si, true);
7521
7522 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
7523 L0_BB. */
7524 switch_si = gsi_last_bb (l0_bb);
7525 gcc_assert (gimple_code (gsi_stmt (switch_si)) == GIMPLE_OMP_SECTIONS_SWITCH);
79acaae1 7526 if (exit_reachable)
7527 {
1a91d914 7528 cont = as_a <gomp_continue *> (last_stmt (l1_bb));
75a70cf9 7529 gcc_assert (gimple_code (cont) == GIMPLE_OMP_CONTINUE);
7530 vmain = gimple_omp_continue_control_use (cont);
7531 vnext = gimple_omp_continue_control_def (cont);
79acaae1 7532 }
7533 else
7534 {
7535 vmain = vin;
7536 vnext = NULL_TREE;
7537 }
1e8e9920 7538
d244d9de 7539 t = build_case_label (build_int_cst (unsigned_type_node, 0), NULL, l2);
f1f41a6c 7540 label_vec.quick_push (t);
d244d9de 7541 i = 1;
03ed154b 7542
75a70cf9 7543 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
ac6e3339 7544 for (inner = region->inner, casei = 1;
7545 inner;
7546 inner = inner->next, i++, casei++)
1e8e9920 7547 {
773c5ba7 7548 basic_block s_entry_bb, s_exit_bb;
7549
9884aaf8 7550 /* Skip optional reduction region. */
75a70cf9 7551 if (inner->type == GIMPLE_OMP_ATOMIC_LOAD)
9884aaf8 7552 {
7553 --i;
7554 --casei;
7555 continue;
7556 }
7557
61e47ac8 7558 s_entry_bb = inner->entry;
7559 s_exit_bb = inner->exit;
1e8e9920 7560
75a70cf9 7561 t = gimple_block_label (s_entry_bb);
ac6e3339 7562 u = build_int_cst (unsigned_type_node, casei);
b6e3dd65 7563 u = build_case_label (u, NULL, t);
f1f41a6c 7564 label_vec.quick_push (u);
61e47ac8 7565
75a70cf9 7566 si = gsi_last_bb (s_entry_bb);
7567 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SECTION);
7568 gcc_assert (i < len || gimple_omp_section_last_p (gsi_stmt (si)));
7569 gsi_remove (&si, true);
61e47ac8 7570 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
03ed154b 7571
7572 if (s_exit_bb == NULL)
7573 continue;
7574
75a70cf9 7575 si = gsi_last_bb (s_exit_bb);
7576 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
7577 gsi_remove (&si, true);
03ed154b 7578
773c5ba7 7579 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
1e8e9920 7580 }
7581
773c5ba7 7582 /* Error handling code goes in DEFAULT_BB. */
75a70cf9 7583 t = gimple_block_label (default_bb);
b6e3dd65 7584 u = build_case_label (NULL, NULL, t);
61e47ac8 7585 make_edge (l0_bb, default_bb, 0);
b3083327 7586 add_bb_to_loop (default_bb, current_loops->tree_root);
1e8e9920 7587
49a70175 7588 stmt = gimple_build_switch (vmain, u, label_vec);
75a70cf9 7589 gsi_insert_after (&switch_si, stmt, GSI_SAME_STMT);
7590 gsi_remove (&switch_si, true);
75a70cf9 7591
7592 si = gsi_start_bb (default_bb);
b9a16870 7593 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
75a70cf9 7594 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
773c5ba7 7595
ac6e3339 7596 if (exit_reachable)
03ed154b 7597 {
b9a16870 7598 tree bfn_decl;
7599
ac6e3339 7600 /* Code to get the next section goes in L1_BB. */
75a70cf9 7601 si = gsi_last_bb (l1_bb);
7602 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
1e8e9920 7603
b9a16870 7604 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
7605 stmt = gimple_build_call (bfn_decl, 0);
75a70cf9 7606 gimple_call_set_lhs (stmt, vnext);
7607 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
7608 gsi_remove (&si, true);
773c5ba7 7609
ac6e3339 7610 single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
03ed154b 7611 }
773c5ba7 7612
d244d9de 7613 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
7614 si = gsi_last_bb (l2_bb);
7615 if (gimple_omp_return_nowait_p (gsi_stmt (si)))
7616 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
bc7bff74 7617 else if (gimple_omp_return_lhs (gsi_stmt (si)))
7618 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL);
d244d9de 7619 else
7620 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
7621 stmt = gimple_build_call (t, 0);
bc7bff74 7622 if (gimple_omp_return_lhs (gsi_stmt (si)))
7623 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (si)));
d244d9de 7624 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
7625 gsi_remove (&si, true);
7626
79acaae1 7627 set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
773c5ba7 7628}
1e8e9920 7629
1e8e9920 7630
61e47ac8 7631/* Expand code for an OpenMP single directive. We've already expanded
7632 much of the code, here we simply place the GOMP_barrier call. */
7633
7634static void
7635expand_omp_single (struct omp_region *region)
7636{
7637 basic_block entry_bb, exit_bb;
75a70cf9 7638 gimple_stmt_iterator si;
61e47ac8 7639
7640 entry_bb = region->entry;
7641 exit_bb = region->exit;
7642
75a70cf9 7643 si = gsi_last_bb (entry_bb);
75a70cf9 7644 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE);
7645 gsi_remove (&si, true);
61e47ac8 7646 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7647
75a70cf9 7648 si = gsi_last_bb (exit_bb);
bc7bff74 7649 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
7650 {
7651 tree t = gimple_omp_return_lhs (gsi_stmt (si));
7652 gsi_insert_after (&si, build_omp_barrier (t), GSI_SAME_STMT);
7653 }
75a70cf9 7654 gsi_remove (&si, true);
61e47ac8 7655 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
7656}
7657
7658
7659/* Generic expansion for OpenMP synchronization directives: master,
7660 ordered and critical. All we need to do here is remove the entry
7661 and exit markers for REGION. */
773c5ba7 7662
7663static void
7664expand_omp_synch (struct omp_region *region)
7665{
7666 basic_block entry_bb, exit_bb;
75a70cf9 7667 gimple_stmt_iterator si;
773c5ba7 7668
61e47ac8 7669 entry_bb = region->entry;
7670 exit_bb = region->exit;
773c5ba7 7671
75a70cf9 7672 si = gsi_last_bb (entry_bb);
7673 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE
7674 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASTER
bc7bff74 7675 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TASKGROUP
75a70cf9 7676 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ORDERED
bc7bff74 7677 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CRITICAL
7678 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TEAMS);
75a70cf9 7679 gsi_remove (&si, true);
773c5ba7 7680 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7681
03ed154b 7682 if (exit_bb)
7683 {
75a70cf9 7684 si = gsi_last_bb (exit_bb);
7685 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
7686 gsi_remove (&si, true);
03ed154b 7687 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
7688 }
773c5ba7 7689}
1e8e9920 7690
2169f33b 7691/* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7692 operation as a normal volatile load. */
7693
7694static bool
3ec11c49 7695expand_omp_atomic_load (basic_block load_bb, tree addr,
7696 tree loaded_val, int index)
2169f33b 7697{
3ec11c49 7698 enum built_in_function tmpbase;
7699 gimple_stmt_iterator gsi;
7700 basic_block store_bb;
7701 location_t loc;
7702 gimple stmt;
7703 tree decl, call, type, itype;
7704
7705 gsi = gsi_last_bb (load_bb);
7706 stmt = gsi_stmt (gsi);
7707 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
7708 loc = gimple_location (stmt);
7709
7710 /* ??? If the target does not implement atomic_load_optab[mode], and mode
7711 is smaller than word size, then expand_atomic_load assumes that the load
7712 is atomic. We could avoid the builtin entirely in this case. */
7713
7714 tmpbase = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
7715 decl = builtin_decl_explicit (tmpbase);
7716 if (decl == NULL_TREE)
7717 return false;
7718
7719 type = TREE_TYPE (loaded_val);
7720 itype = TREE_TYPE (TREE_TYPE (decl));
7721
7722 call = build_call_expr_loc (loc, decl, 2, addr,
bc7bff74 7723 build_int_cst (NULL,
7724 gimple_omp_atomic_seq_cst_p (stmt)
7725 ? MEMMODEL_SEQ_CST
7726 : MEMMODEL_RELAXED));
3ec11c49 7727 if (!useless_type_conversion_p (type, itype))
7728 call = fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
7729 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
7730
7731 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
7732 gsi_remove (&gsi, true);
7733
7734 store_bb = single_succ (load_bb);
7735 gsi = gsi_last_bb (store_bb);
7736 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
7737 gsi_remove (&gsi, true);
7738
7739 if (gimple_in_ssa_p (cfun))
7740 update_ssa (TODO_update_ssa_no_phi);
7741
7742 return true;
2169f33b 7743}
7744
7745/* A subroutine of expand_omp_atomic. Attempt to implement the atomic
7746 operation as a normal volatile store. */
7747
7748static bool
3ec11c49 7749expand_omp_atomic_store (basic_block load_bb, tree addr,
7750 tree loaded_val, tree stored_val, int index)
2169f33b 7751{
3ec11c49 7752 enum built_in_function tmpbase;
7753 gimple_stmt_iterator gsi;
7754 basic_block store_bb = single_succ (load_bb);
7755 location_t loc;
7756 gimple stmt;
7757 tree decl, call, type, itype;
3754d046 7758 machine_mode imode;
3ec11c49 7759 bool exchange;
7760
7761 gsi = gsi_last_bb (load_bb);
7762 stmt = gsi_stmt (gsi);
7763 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
7764
7765 /* If the load value is needed, then this isn't a store but an exchange. */
7766 exchange = gimple_omp_atomic_need_value_p (stmt);
7767
7768 gsi = gsi_last_bb (store_bb);
7769 stmt = gsi_stmt (gsi);
7770 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE);
7771 loc = gimple_location (stmt);
7772
7773 /* ??? If the target does not implement atomic_store_optab[mode], and mode
7774 is smaller than word size, then expand_atomic_store assumes that the store
7775 is atomic. We could avoid the builtin entirely in this case. */
7776
7777 tmpbase = (exchange ? BUILT_IN_ATOMIC_EXCHANGE_N : BUILT_IN_ATOMIC_STORE_N);
7778 tmpbase = (enum built_in_function) ((int) tmpbase + index + 1);
7779 decl = builtin_decl_explicit (tmpbase);
7780 if (decl == NULL_TREE)
7781 return false;
7782
7783 type = TREE_TYPE (stored_val);
7784
7785 /* Dig out the type of the function's second argument. */
7786 itype = TREE_TYPE (decl);
7787 itype = TYPE_ARG_TYPES (itype);
7788 itype = TREE_CHAIN (itype);
7789 itype = TREE_VALUE (itype);
7790 imode = TYPE_MODE (itype);
7791
7792 if (exchange && !can_atomic_exchange_p (imode, true))
7793 return false;
7794
7795 if (!useless_type_conversion_p (itype, type))
7796 stored_val = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, stored_val);
7797 call = build_call_expr_loc (loc, decl, 3, addr, stored_val,
bc7bff74 7798 build_int_cst (NULL,
7799 gimple_omp_atomic_seq_cst_p (stmt)
7800 ? MEMMODEL_SEQ_CST
7801 : MEMMODEL_RELAXED));
3ec11c49 7802 if (exchange)
7803 {
7804 if (!useless_type_conversion_p (type, itype))
7805 call = build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
7806 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
7807 }
7808
7809 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
7810 gsi_remove (&gsi, true);
7811
7812 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
7813 gsi = gsi_last_bb (load_bb);
7814 gsi_remove (&gsi, true);
7815
7816 if (gimple_in_ssa_p (cfun))
7817 update_ssa (TODO_update_ssa_no_phi);
7818
7819 return true;
2169f33b 7820}
7821
cb7f680b 7822/* A subroutine of expand_omp_atomic. Attempt to implement the atomic
1cd6e20d 7823 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
cb7f680b 7824 size of the data type, and thus usable to find the index of the builtin
7825 decl. Returns false if the expression is not of the proper form. */
7826
7827static bool
7828expand_omp_atomic_fetch_op (basic_block load_bb,
7829 tree addr, tree loaded_val,
7830 tree stored_val, int index)
7831{
b9a16870 7832 enum built_in_function oldbase, newbase, tmpbase;
cb7f680b 7833 tree decl, itype, call;
2169f33b 7834 tree lhs, rhs;
cb7f680b 7835 basic_block store_bb = single_succ (load_bb);
75a70cf9 7836 gimple_stmt_iterator gsi;
7837 gimple stmt;
389dd41b 7838 location_t loc;
1cd6e20d 7839 enum tree_code code;
2169f33b 7840 bool need_old, need_new;
3754d046 7841 machine_mode imode;
bc7bff74 7842 bool seq_cst;
cb7f680b 7843
7844 /* We expect to find the following sequences:
48e1416a 7845
cb7f680b 7846 load_bb:
75a70cf9 7847 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
cb7f680b 7848
7849 store_bb:
7850 val = tmp OP something; (or: something OP tmp)
48e1416a 7851 GIMPLE_OMP_STORE (val)
cb7f680b 7852
48e1416a 7853 ???FIXME: Allow a more flexible sequence.
cb7f680b 7854 Perhaps use data flow to pick the statements.
48e1416a 7855
cb7f680b 7856 */
7857
75a70cf9 7858 gsi = gsi_after_labels (store_bb);
7859 stmt = gsi_stmt (gsi);
389dd41b 7860 loc = gimple_location (stmt);
75a70cf9 7861 if (!is_gimple_assign (stmt))
cb7f680b 7862 return false;
75a70cf9 7863 gsi_next (&gsi);
7864 if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE)
cb7f680b 7865 return false;
2169f33b 7866 need_new = gimple_omp_atomic_need_value_p (gsi_stmt (gsi));
7867 need_old = gimple_omp_atomic_need_value_p (last_stmt (load_bb));
bc7bff74 7868 seq_cst = gimple_omp_atomic_seq_cst_p (last_stmt (load_bb));
2169f33b 7869 gcc_checking_assert (!need_old || !need_new);
cb7f680b 7870
75a70cf9 7871 if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
cb7f680b 7872 return false;
7873
cb7f680b 7874 /* Check for one of the supported fetch-op operations. */
1cd6e20d 7875 code = gimple_assign_rhs_code (stmt);
7876 switch (code)
cb7f680b 7877 {
7878 case PLUS_EXPR:
7879 case POINTER_PLUS_EXPR:
1cd6e20d 7880 oldbase = BUILT_IN_ATOMIC_FETCH_ADD_N;
7881 newbase = BUILT_IN_ATOMIC_ADD_FETCH_N;
cb7f680b 7882 break;
7883 case MINUS_EXPR:
1cd6e20d 7884 oldbase = BUILT_IN_ATOMIC_FETCH_SUB_N;
7885 newbase = BUILT_IN_ATOMIC_SUB_FETCH_N;
cb7f680b 7886 break;
7887 case BIT_AND_EXPR:
1cd6e20d 7888 oldbase = BUILT_IN_ATOMIC_FETCH_AND_N;
7889 newbase = BUILT_IN_ATOMIC_AND_FETCH_N;
cb7f680b 7890 break;
7891 case BIT_IOR_EXPR:
1cd6e20d 7892 oldbase = BUILT_IN_ATOMIC_FETCH_OR_N;
7893 newbase = BUILT_IN_ATOMIC_OR_FETCH_N;
cb7f680b 7894 break;
7895 case BIT_XOR_EXPR:
1cd6e20d 7896 oldbase = BUILT_IN_ATOMIC_FETCH_XOR_N;
7897 newbase = BUILT_IN_ATOMIC_XOR_FETCH_N;
cb7f680b 7898 break;
7899 default:
7900 return false;
7901 }
1cd6e20d 7902
cb7f680b 7903 /* Make sure the expression is of the proper form. */
75a70cf9 7904 if (operand_equal_p (gimple_assign_rhs1 (stmt), loaded_val, 0))
7905 rhs = gimple_assign_rhs2 (stmt);
7906 else if (commutative_tree_code (gimple_assign_rhs_code (stmt))
7907 && operand_equal_p (gimple_assign_rhs2 (stmt), loaded_val, 0))
7908 rhs = gimple_assign_rhs1 (stmt);
cb7f680b 7909 else
7910 return false;
7911
b9a16870 7912 tmpbase = ((enum built_in_function)
7913 ((need_new ? newbase : oldbase) + index + 1));
7914 decl = builtin_decl_explicit (tmpbase);
0f94f46b 7915 if (decl == NULL_TREE)
7916 return false;
cb7f680b 7917 itype = TREE_TYPE (TREE_TYPE (decl));
1cd6e20d 7918 imode = TYPE_MODE (itype);
cb7f680b 7919
1cd6e20d 7920 /* We could test all of the various optabs involved, but the fact of the
7921 matter is that (with the exception of i486 vs i586 and xadd) all targets
7922 that support any atomic operaton optab also implements compare-and-swap.
7923 Let optabs.c take care of expanding any compare-and-swap loop. */
29139cdc 7924 if (!can_compare_and_swap_p (imode, true))
cb7f680b 7925 return false;
7926
75a70cf9 7927 gsi = gsi_last_bb (load_bb);
7928 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
1cd6e20d 7929
7930 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
7931 It only requires that the operation happen atomically. Thus we can
7932 use the RELAXED memory model. */
7933 call = build_call_expr_loc (loc, decl, 3, addr,
7934 fold_convert_loc (loc, itype, rhs),
bc7bff74 7935 build_int_cst (NULL,
7936 seq_cst ? MEMMODEL_SEQ_CST
7937 : MEMMODEL_RELAXED));
1cd6e20d 7938
2169f33b 7939 if (need_old || need_new)
7940 {
7941 lhs = need_old ? loaded_val : stored_val;
7942 call = fold_convert_loc (loc, TREE_TYPE (lhs), call);
7943 call = build2_loc (loc, MODIFY_EXPR, void_type_node, lhs, call);
7944 }
7945 else
7946 call = fold_convert_loc (loc, void_type_node, call);
75a70cf9 7947 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
7948 gsi_remove (&gsi, true);
cb7f680b 7949
75a70cf9 7950 gsi = gsi_last_bb (store_bb);
7951 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
7952 gsi_remove (&gsi, true);
7953 gsi = gsi_last_bb (store_bb);
7954 gsi_remove (&gsi, true);
cb7f680b 7955
7956 if (gimple_in_ssa_p (cfun))
7957 update_ssa (TODO_update_ssa_no_phi);
7958
7959 return true;
7960}
7961
7962/* A subroutine of expand_omp_atomic. Implement the atomic operation as:
7963
7964 oldval = *addr;
7965 repeat:
7966 newval = rhs; // with oldval replacing *addr in rhs
7967 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
7968 if (oldval != newval)
7969 goto repeat;
7970
7971 INDEX is log2 of the size of the data type, and thus usable to find the
7972 index of the builtin decl. */
7973
7974static bool
7975expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
7976 tree addr, tree loaded_val, tree stored_val,
7977 int index)
7978{
790368c5 7979 tree loadedi, storedi, initial, new_storedi, old_vali;
cb7f680b 7980 tree type, itype, cmpxchg, iaddr;
75a70cf9 7981 gimple_stmt_iterator si;
cb7f680b 7982 basic_block loop_header = single_succ (load_bb);
75a70cf9 7983 gimple phi, stmt;
cb7f680b 7984 edge e;
b9a16870 7985 enum built_in_function fncode;
cb7f680b 7986
1cd6e20d 7987 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
7988 order to use the RELAXED memory model effectively. */
b9a16870 7989 fncode = (enum built_in_function)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
7990 + index + 1);
7991 cmpxchg = builtin_decl_explicit (fncode);
0f94f46b 7992 if (cmpxchg == NULL_TREE)
7993 return false;
cb7f680b 7994 type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
7995 itype = TREE_TYPE (TREE_TYPE (cmpxchg));
7996
29139cdc 7997 if (!can_compare_and_swap_p (TYPE_MODE (itype), true))
cb7f680b 7998 return false;
7999
75a70cf9 8000 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
8001 si = gsi_last_bb (load_bb);
8002 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
8003
790368c5 8004 /* For floating-point values, we'll need to view-convert them to integers
8005 so that we can perform the atomic compare and swap. Simplify the
8006 following code by always setting up the "i"ntegral variables. */
8007 if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
8008 {
75a70cf9 8009 tree iaddr_val;
8010
072f7ab1 8011 iaddr = create_tmp_reg (build_pointer_type_for_mode (itype, ptr_mode,
8012 true), NULL);
75a70cf9 8013 iaddr_val
8014 = force_gimple_operand_gsi (&si,
8015 fold_convert (TREE_TYPE (iaddr), addr),
8016 false, NULL_TREE, true, GSI_SAME_STMT);
8017 stmt = gimple_build_assign (iaddr, iaddr_val);
8018 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
790368c5 8019 loadedi = create_tmp_var (itype, NULL);
8020 if (gimple_in_ssa_p (cfun))
b03e5397 8021 loadedi = make_ssa_name (loadedi, NULL);
790368c5 8022 }
8023 else
8024 {
8025 iaddr = addr;
8026 loadedi = loaded_val;
8027 }
75a70cf9 8028
2ed72821 8029 fncode = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
8030 tree loaddecl = builtin_decl_explicit (fncode);
8031 if (loaddecl)
8032 initial
8033 = fold_convert (TREE_TYPE (TREE_TYPE (iaddr)),
8034 build_call_expr (loaddecl, 2, iaddr,
8035 build_int_cst (NULL_TREE,
8036 MEMMODEL_RELAXED)));
8037 else
8038 initial = build2 (MEM_REF, TREE_TYPE (TREE_TYPE (iaddr)), iaddr,
8039 build_int_cst (TREE_TYPE (iaddr), 0));
8040
182cf5a9 8041 initial
2ed72821 8042 = force_gimple_operand_gsi (&si, initial, true, NULL_TREE, true,
8043 GSI_SAME_STMT);
790368c5 8044
8045 /* Move the value to the LOADEDI temporary. */
cb7f680b 8046 if (gimple_in_ssa_p (cfun))
8047 {
75a70cf9 8048 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header)));
790368c5 8049 phi = create_phi_node (loadedi, loop_header);
cb7f680b 8050 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)),
8051 initial);
8052 }
8053 else
75a70cf9 8054 gsi_insert_before (&si,
8055 gimple_build_assign (loadedi, initial),
8056 GSI_SAME_STMT);
790368c5 8057 if (loadedi != loaded_val)
8058 {
75a70cf9 8059 gimple_stmt_iterator gsi2;
8060 tree x;
790368c5 8061
8062 x = build1 (VIEW_CONVERT_EXPR, type, loadedi);
75a70cf9 8063 gsi2 = gsi_start_bb (loop_header);
790368c5 8064 if (gimple_in_ssa_p (cfun))
8065 {
1a91d914 8066 gassign *stmt;
75a70cf9 8067 x = force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
8068 true, GSI_SAME_STMT);
8069 stmt = gimple_build_assign (loaded_val, x);
8070 gsi_insert_before (&gsi2, stmt, GSI_SAME_STMT);
790368c5 8071 }
8072 else
8073 {
75a70cf9 8074 x = build2 (MODIFY_EXPR, TREE_TYPE (loaded_val), loaded_val, x);
8075 force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
8076 true, GSI_SAME_STMT);
790368c5 8077 }
8078 }
75a70cf9 8079 gsi_remove (&si, true);
cb7f680b 8080
75a70cf9 8081 si = gsi_last_bb (store_bb);
8082 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
cb7f680b 8083
790368c5 8084 if (iaddr == addr)
8085 storedi = stored_val;
cb7f680b 8086 else
790368c5 8087 storedi =
75a70cf9 8088 force_gimple_operand_gsi (&si,
790368c5 8089 build1 (VIEW_CONVERT_EXPR, itype,
8090 stored_val), true, NULL_TREE, true,
75a70cf9 8091 GSI_SAME_STMT);
cb7f680b 8092
8093 /* Build the compare&swap statement. */
8094 new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi);
75a70cf9 8095 new_storedi = force_gimple_operand_gsi (&si,
87f9ffa4 8096 fold_convert (TREE_TYPE (loadedi),
8097 new_storedi),
cb7f680b 8098 true, NULL_TREE,
75a70cf9 8099 true, GSI_SAME_STMT);
cb7f680b 8100
8101 if (gimple_in_ssa_p (cfun))
8102 old_vali = loadedi;
8103 else
8104 {
87f9ffa4 8105 old_vali = create_tmp_var (TREE_TYPE (loadedi), NULL);
75a70cf9 8106 stmt = gimple_build_assign (old_vali, loadedi);
8107 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
cb7f680b 8108
75a70cf9 8109 stmt = gimple_build_assign (loadedi, new_storedi);
8110 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
cb7f680b 8111 }
8112
8113 /* Note that we always perform the comparison as an integer, even for
48e1416a 8114 floating point. This allows the atomic operation to properly
cb7f680b 8115 succeed even with NaNs and -0.0. */
75a70cf9 8116 stmt = gimple_build_cond_empty
8117 (build2 (NE_EXPR, boolean_type_node,
8118 new_storedi, old_vali));
8119 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
cb7f680b 8120
8121 /* Update cfg. */
8122 e = single_succ_edge (store_bb);
8123 e->flags &= ~EDGE_FALLTHRU;
8124 e->flags |= EDGE_FALSE_VALUE;
8125
8126 e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE);
8127
790368c5 8128 /* Copy the new value to loadedi (we already did that before the condition
cb7f680b 8129 if we are not in SSA). */
8130 if (gimple_in_ssa_p (cfun))
8131 {
75a70cf9 8132 phi = gimple_seq_first_stmt (phi_nodes (loop_header));
790368c5 8133 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), new_storedi);
cb7f680b 8134 }
8135
75a70cf9 8136 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
8137 gsi_remove (&si, true);
cb7f680b 8138
04c2922b 8139 struct loop *loop = alloc_loop ();
8140 loop->header = loop_header;
5f037457 8141 loop->latch = store_bb;
04c2922b 8142 add_loop (loop, loop_header->loop_father);
8143
cb7f680b 8144 if (gimple_in_ssa_p (cfun))
8145 update_ssa (TODO_update_ssa_no_phi);
8146
8147 return true;
8148}
8149
8150/* A subroutine of expand_omp_atomic. Implement the atomic operation as:
8151
8152 GOMP_atomic_start ();
8153 *addr = rhs;
8154 GOMP_atomic_end ();
8155
8156 The result is not globally atomic, but works so long as all parallel
8157 references are within #pragma omp atomic directives. According to
8158 responses received from omp@openmp.org, appears to be within spec.
8159 Which makes sense, since that's how several other compilers handle
48e1416a 8160 this situation as well.
75a70cf9 8161 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
8162 expanding. STORED_VAL is the operand of the matching
8163 GIMPLE_OMP_ATOMIC_STORE.
cb7f680b 8164
48e1416a 8165 We replace
8166 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
cb7f680b 8167 loaded_val = *addr;
8168
8169 and replace
3ec11c49 8170 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
48e1416a 8171 *addr = stored_val;
cb7f680b 8172*/
8173
8174static bool
8175expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
8176 tree addr, tree loaded_val, tree stored_val)
8177{
75a70cf9 8178 gimple_stmt_iterator si;
1a91d914 8179 gassign *stmt;
cb7f680b 8180 tree t;
8181
75a70cf9 8182 si = gsi_last_bb (load_bb);
8183 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
cb7f680b 8184
b9a16870 8185 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
414c3a2c 8186 t = build_call_expr (t, 0);
75a70cf9 8187 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
cb7f680b 8188
182cf5a9 8189 stmt = gimple_build_assign (loaded_val, build_simple_mem_ref (addr));
75a70cf9 8190 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8191 gsi_remove (&si, true);
cb7f680b 8192
75a70cf9 8193 si = gsi_last_bb (store_bb);
8194 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
cb7f680b 8195
182cf5a9 8196 stmt = gimple_build_assign (build_simple_mem_ref (unshare_expr (addr)),
8197 stored_val);
75a70cf9 8198 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
cb7f680b 8199
b9a16870 8200 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
414c3a2c 8201 t = build_call_expr (t, 0);
75a70cf9 8202 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
8203 gsi_remove (&si, true);
cb7f680b 8204
8205 if (gimple_in_ssa_p (cfun))
8206 update_ssa (TODO_update_ssa_no_phi);
8207 return true;
8208}
8209
48e1416a 8210/* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
8211 using expand_omp_atomic_fetch_op. If it failed, we try to
cb7f680b 8212 call expand_omp_atomic_pipeline, and if it fails too, the
8213 ultimate fallback is wrapping the operation in a mutex
48e1416a 8214 (expand_omp_atomic_mutex). REGION is the atomic region built
8215 by build_omp_regions_1(). */
cb7f680b 8216
8217static void
8218expand_omp_atomic (struct omp_region *region)
8219{
8220 basic_block load_bb = region->entry, store_bb = region->exit;
1a91d914 8221 gomp_atomic_load *load = as_a <gomp_atomic_load *> (last_stmt (load_bb));
8222 gomp_atomic_store *store = as_a <gomp_atomic_store *> (last_stmt (store_bb));
75a70cf9 8223 tree loaded_val = gimple_omp_atomic_load_lhs (load);
8224 tree addr = gimple_omp_atomic_load_rhs (load);
8225 tree stored_val = gimple_omp_atomic_store_val (store);
cb7f680b 8226 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
8227 HOST_WIDE_INT index;
8228
8229 /* Make sure the type is one of the supported sizes. */
e913b5cd 8230 index = tree_to_uhwi (TYPE_SIZE_UNIT (type));
cb7f680b 8231 index = exact_log2 (index);
8232 if (index >= 0 && index <= 4)
8233 {
8234 unsigned int align = TYPE_ALIGN_UNIT (type);
8235
8236 /* __sync builtins require strict data alignment. */
dcf7024c 8237 if (exact_log2 (align) >= index)
cb7f680b 8238 {
3ec11c49 8239 /* Atomic load. */
2169f33b 8240 if (loaded_val == stored_val
8241 && (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
8242 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
8243 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
3ec11c49 8244 && expand_omp_atomic_load (load_bb, addr, loaded_val, index))
2169f33b 8245 return;
8246
3ec11c49 8247 /* Atomic store. */
2169f33b 8248 if ((GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
8249 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
8250 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
8251 && store_bb == single_succ (load_bb)
8252 && first_stmt (store_bb) == store
3ec11c49 8253 && expand_omp_atomic_store (load_bb, addr, loaded_val,
8254 stored_val, index))
2169f33b 8255 return;
8256
cb7f680b 8257 /* When possible, use specialized atomic update functions. */
8258 if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
3ec11c49 8259 && store_bb == single_succ (load_bb)
8260 && expand_omp_atomic_fetch_op (load_bb, addr,
8261 loaded_val, stored_val, index))
8262 return;
cb7f680b 8263
8264 /* If we don't have specialized __sync builtins, try and implement
8265 as a compare and swap loop. */
8266 if (expand_omp_atomic_pipeline (load_bb, store_bb, addr,
8267 loaded_val, stored_val, index))
8268 return;
8269 }
8270 }
8271
8272 /* The ultimate fallback is wrapping the operation in a mutex. */
8273 expand_omp_atomic_mutex (load_bb, store_bb, addr, loaded_val, stored_val);
8274}
8275
1e8e9920 8276
bc7bff74 8277/* Expand the OpenMP target{, data, update} directive starting at REGION. */
773c5ba7 8278
8279static void
bc7bff74 8280expand_omp_target (struct omp_region *region)
773c5ba7 8281{
bc7bff74 8282 basic_block entry_bb, exit_bb, new_bb;
8283 struct function *child_cfun = NULL;
8284 tree child_fn = NULL_TREE, block, t;
8285 gimple_stmt_iterator gsi;
1a91d914 8286 gomp_target *entry_stmt;
8287 gimple stmt;
bc7bff74 8288 edge e;
8289
1a91d914 8290 entry_stmt = as_a <gomp_target *> (last_stmt (region->entry));
bc7bff74 8291 new_bb = region->entry;
8292 int kind = gimple_omp_target_kind (entry_stmt);
8293 if (kind == GF_OMP_TARGET_KIND_REGION)
8294 {
8295 child_fn = gimple_omp_target_child_fn (entry_stmt);
8296 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
8297 }
8298
8299 entry_bb = region->entry;
8300 exit_bb = region->exit;
8301
8302 if (kind == GF_OMP_TARGET_KIND_REGION)
8303 {
8304 unsigned srcidx, dstidx, num;
8305
8306 /* If the target region needs data sent from the parent
8307 function, then the very first statement (except possible
8308 tree profile counter updates) of the parallel body
8309 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
8310 &.OMP_DATA_O is passed as an argument to the child function,
8311 we need to replace it with the argument as seen by the child
8312 function.
8313
8314 In most cases, this will end up being the identity assignment
8315 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
8316 a function call that has been inlined, the original PARM_DECL
8317 .OMP_DATA_I may have been converted into a different local
8318 variable. In which case, we need to keep the assignment. */
8319 if (gimple_omp_target_data_arg (entry_stmt))
8320 {
8321 basic_block entry_succ_bb = single_succ (entry_bb);
8322 gimple_stmt_iterator gsi;
8323 tree arg;
8324 gimple tgtcopy_stmt = NULL;
8325 tree sender
8326 = TREE_VEC_ELT (gimple_omp_target_data_arg (entry_stmt), 0);
8327
8328 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
8329 {
8330 gcc_assert (!gsi_end_p (gsi));
8331 stmt = gsi_stmt (gsi);
8332 if (gimple_code (stmt) != GIMPLE_ASSIGN)
8333 continue;
8334
8335 if (gimple_num_ops (stmt) == 2)
8336 {
8337 tree arg = gimple_assign_rhs1 (stmt);
8338
8339 /* We're ignoring the subcode because we're
8340 effectively doing a STRIP_NOPS. */
8341
8342 if (TREE_CODE (arg) == ADDR_EXPR
8343 && TREE_OPERAND (arg, 0) == sender)
8344 {
8345 tgtcopy_stmt = stmt;
8346 break;
8347 }
8348 }
8349 }
8350
8351 gcc_assert (tgtcopy_stmt != NULL);
8352 arg = DECL_ARGUMENTS (child_fn);
8353
8354 gcc_assert (gimple_assign_lhs (tgtcopy_stmt) == arg);
8355 gsi_remove (&gsi, true);
8356 }
8357
8358 /* Declare local variables needed in CHILD_CFUN. */
8359 block = DECL_INITIAL (child_fn);
8360 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
8361 /* The gimplifier could record temporaries in target block
8362 rather than in containing function's local_decls chain,
8363 which would mean cgraph missed finalizing them. Do it now. */
8364 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
8365 if (TREE_CODE (t) == VAR_DECL
8366 && TREE_STATIC (t)
8367 && !DECL_EXTERNAL (t))
97221fd7 8368 varpool_node::finalize_decl (t);
bc7bff74 8369 DECL_SAVED_TREE (child_fn) = NULL;
8370 /* We'll create a CFG for child_fn, so no gimple body is needed. */
8371 gimple_set_body (child_fn, NULL);
8372 TREE_USED (block) = 1;
8373
8374 /* Reset DECL_CONTEXT on function arguments. */
8375 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
8376 DECL_CONTEXT (t) = child_fn;
8377
8378 /* Split ENTRY_BB at GIMPLE_OMP_TARGET,
8379 so that it can be moved to the child function. */
8380 gsi = gsi_last_bb (entry_bb);
8381 stmt = gsi_stmt (gsi);
8382 gcc_assert (stmt && gimple_code (stmt) == GIMPLE_OMP_TARGET
8383 && gimple_omp_target_kind (stmt)
8384 == GF_OMP_TARGET_KIND_REGION);
8385 gsi_remove (&gsi, true);
8386 e = split_block (entry_bb, stmt);
8387 entry_bb = e->dest;
8388 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
8389
8390 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
8391 if (exit_bb)
8392 {
8393 gsi = gsi_last_bb (exit_bb);
8394 gcc_assert (!gsi_end_p (gsi)
8395 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
8396 stmt = gimple_build_return (NULL);
8397 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
8398 gsi_remove (&gsi, true);
8399 }
8400
8401 /* Move the target region into CHILD_CFUN. */
8402
8403 block = gimple_block (entry_stmt);
8404
8405 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
8406 if (exit_bb)
8407 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
8408 /* When the OMP expansion process cannot guarantee an up-to-date
8409 loop tree arrange for the child function to fixup loops. */
8410 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
8411 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
8412
8413 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
8414 num = vec_safe_length (child_cfun->local_decls);
8415 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
8416 {
8417 t = (*child_cfun->local_decls)[srcidx];
8418 if (DECL_CONTEXT (t) == cfun->decl)
8419 continue;
8420 if (srcidx != dstidx)
8421 (*child_cfun->local_decls)[dstidx] = t;
8422 dstidx++;
8423 }
8424 if (dstidx != num)
8425 vec_safe_truncate (child_cfun->local_decls, dstidx);
8426
8427 /* Inform the callgraph about the new function. */
8428 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
415d1b9a 8429 cgraph_node::add_new_function (child_fn, true);
bc7bff74 8430
7114ebdd 8431#ifdef ENABLE_OFFLOADING
dccabdd1 8432 /* Add the new function to the offload table. */
8433 vec_safe_push (offload_funcs, child_fn);
7114ebdd 8434#endif
dccabdd1 8435
bc7bff74 8436 /* Fix the callgraph edges for child_cfun. Those for cfun will be
8437 fixed in a following pass. */
8438 push_cfun (child_cfun);
35ee1c66 8439 cgraph_edge::rebuild_edges ();
bc7bff74 8440
7114ebdd 8441#ifdef ENABLE_OFFLOADING
b0c5e347 8442 /* Prevent IPA from removing child_fn as unreachable, since there are no
8443 refs from the parent function to child_fn in offload LTO mode. */
7114ebdd 8444 struct cgraph_node *node = cgraph_node::get (child_fn);
b0c5e347 8445 node->mark_force_output ();
7114ebdd 8446#endif
b0c5e347 8447
bc7bff74 8448 /* Some EH regions might become dead, see PR34608. If
8449 pass_cleanup_cfg isn't the first pass to happen with the
8450 new child, these dead EH edges might cause problems.
8451 Clean them up now. */
8452 if (flag_exceptions)
8453 {
8454 basic_block bb;
8455 bool changed = false;
8456
fc00614f 8457 FOR_EACH_BB_FN (bb, cfun)
bc7bff74 8458 changed |= gimple_purge_dead_eh_edges (bb);
8459 if (changed)
8460 cleanup_tree_cfg ();
8461 }
8462 pop_cfun ();
8463 }
8464
8465 /* Emit a library call to launch the target region, or do data
8466 transfers. */
8467 tree t1, t2, t3, t4, device, cond, c, clauses;
8468 enum built_in_function start_ix;
8469 location_t clause_loc;
8470
8471 clauses = gimple_omp_target_clauses (entry_stmt);
8472
8473 if (kind == GF_OMP_TARGET_KIND_REGION)
8474 start_ix = BUILT_IN_GOMP_TARGET;
8475 else if (kind == GF_OMP_TARGET_KIND_DATA)
8476 start_ix = BUILT_IN_GOMP_TARGET_DATA;
8477 else
8478 start_ix = BUILT_IN_GOMP_TARGET_UPDATE;
8479
8480 /* By default, the value of DEVICE is -1 (let runtime library choose)
8481 and there is no conditional. */
8482 cond = NULL_TREE;
8483 device = build_int_cst (integer_type_node, -1);
8484
8485 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
8486 if (c)
8487 cond = OMP_CLAUSE_IF_EXPR (c);
8488
8489 c = find_omp_clause (clauses, OMP_CLAUSE_DEVICE);
8490 if (c)
8491 {
8492 device = OMP_CLAUSE_DEVICE_ID (c);
8493 clause_loc = OMP_CLAUSE_LOCATION (c);
8494 }
8495 else
8496 clause_loc = gimple_location (entry_stmt);
8497
8498 /* Ensure 'device' is of the correct type. */
8499 device = fold_convert_loc (clause_loc, integer_type_node, device);
8500
8501 /* If we found the clause 'if (cond)', build
8502 (cond ? device : -2). */
8503 if (cond)
8504 {
8505 cond = gimple_boolify (cond);
8506
8507 basic_block cond_bb, then_bb, else_bb;
8508 edge e;
8509 tree tmp_var;
8510
8511 tmp_var = create_tmp_var (TREE_TYPE (device), NULL);
8512 if (kind != GF_OMP_TARGET_KIND_REGION)
8513 {
8514 gsi = gsi_last_bb (new_bb);
8515 gsi_prev (&gsi);
8516 e = split_block (new_bb, gsi_stmt (gsi));
8517 }
8518 else
8519 e = split_block (new_bb, NULL);
8520 cond_bb = e->src;
8521 new_bb = e->dest;
8522 remove_edge (e);
8523
8524 then_bb = create_empty_bb (cond_bb);
8525 else_bb = create_empty_bb (then_bb);
8526 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
8527 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
8528
8529 stmt = gimple_build_cond_empty (cond);
8530 gsi = gsi_last_bb (cond_bb);
8531 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
8532
8533 gsi = gsi_start_bb (then_bb);
8534 stmt = gimple_build_assign (tmp_var, device);
8535 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
8536
8537 gsi = gsi_start_bb (else_bb);
8538 stmt = gimple_build_assign (tmp_var,
8539 build_int_cst (integer_type_node, -2));
8540 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
8541
8542 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
8543 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
b3083327 8544 add_bb_to_loop (then_bb, cond_bb->loop_father);
8545 add_bb_to_loop (else_bb, cond_bb->loop_father);
bc7bff74 8546 make_edge (then_bb, new_bb, EDGE_FALLTHRU);
8547 make_edge (else_bb, new_bb, EDGE_FALLTHRU);
8548
8549 device = tmp_var;
8550 }
8551
8552 gsi = gsi_last_bb (new_bb);
8553 t = gimple_omp_target_data_arg (entry_stmt);
8554 if (t == NULL)
8555 {
8556 t1 = size_zero_node;
8557 t2 = build_zero_cst (ptr_type_node);
8558 t3 = t2;
8559 t4 = t2;
8560 }
8561 else
8562 {
8563 t1 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t, 1))));
8564 t1 = size_binop (PLUS_EXPR, t1, size_int (1));
8565 t2 = build_fold_addr_expr (TREE_VEC_ELT (t, 0));
8566 t3 = build_fold_addr_expr (TREE_VEC_ELT (t, 1));
8567 t4 = build_fold_addr_expr (TREE_VEC_ELT (t, 2));
8568 }
8569
8570 gimple g;
8571 /* FIXME: This will be address of
8572 extern char __OPENMP_TARGET__[] __attribute__((visibility ("hidden")))
8573 symbol, as soon as the linker plugin is able to create it for us. */
8574 tree openmp_target = build_zero_cst (ptr_type_node);
8575 if (kind == GF_OMP_TARGET_KIND_REGION)
8576 {
8577 tree fnaddr = build_fold_addr_expr (child_fn);
8578 g = gimple_build_call (builtin_decl_explicit (start_ix), 7,
8579 device, fnaddr, openmp_target, t1, t2, t3, t4);
8580 }
8581 else
8582 g = gimple_build_call (builtin_decl_explicit (start_ix), 6,
8583 device, openmp_target, t1, t2, t3, t4);
8584 gimple_set_location (g, gimple_location (entry_stmt));
8585 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
8586 if (kind != GF_OMP_TARGET_KIND_REGION)
8587 {
8588 g = gsi_stmt (gsi);
8589 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_TARGET);
8590 gsi_remove (&gsi, true);
8591 }
8592 if (kind == GF_OMP_TARGET_KIND_DATA && region->exit)
8593 {
8594 gsi = gsi_last_bb (region->exit);
8595 g = gsi_stmt (gsi);
8596 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_RETURN);
8597 gsi_remove (&gsi, true);
8598 }
8599}
8600
8601
8602/* Expand the parallel region tree rooted at REGION. Expansion
8603 proceeds in depth-first order. Innermost regions are expanded
8604 first. This way, parallel regions that require a new function to
75a70cf9 8605 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
773c5ba7 8606 internal dependencies in their body. */
8607
8608static void
8609expand_omp (struct omp_region *region)
8610{
8611 while (region)
8612 {
1d22f541 8613 location_t saved_location;
bc7bff74 8614 gimple inner_stmt = NULL;
1d22f541 8615
d1d5b012 8616 /* First, determine whether this is a combined parallel+workshare
8617 region. */
75a70cf9 8618 if (region->type == GIMPLE_OMP_PARALLEL)
d1d5b012 8619 determine_parallel_type (region);
8620
bc7bff74 8621 if (region->type == GIMPLE_OMP_FOR
8622 && gimple_omp_for_combined_p (last_stmt (region->entry)))
8623 inner_stmt = last_stmt (region->inner->entry);
8624
773c5ba7 8625 if (region->inner)
8626 expand_omp (region->inner);
8627
1d22f541 8628 saved_location = input_location;
75a70cf9 8629 if (gimple_has_location (last_stmt (region->entry)))
8630 input_location = gimple_location (last_stmt (region->entry));
1d22f541 8631
61e47ac8 8632 switch (region->type)
773c5ba7 8633 {
75a70cf9 8634 case GIMPLE_OMP_PARALLEL:
8635 case GIMPLE_OMP_TASK:
fd6481cf 8636 expand_omp_taskreg (region);
8637 break;
8638
75a70cf9 8639 case GIMPLE_OMP_FOR:
bc7bff74 8640 expand_omp_for (region, inner_stmt);
61e47ac8 8641 break;
773c5ba7 8642
75a70cf9 8643 case GIMPLE_OMP_SECTIONS:
61e47ac8 8644 expand_omp_sections (region);
8645 break;
773c5ba7 8646
75a70cf9 8647 case GIMPLE_OMP_SECTION:
61e47ac8 8648 /* Individual omp sections are handled together with their
75a70cf9 8649 parent GIMPLE_OMP_SECTIONS region. */
61e47ac8 8650 break;
773c5ba7 8651
75a70cf9 8652 case GIMPLE_OMP_SINGLE:
61e47ac8 8653 expand_omp_single (region);
8654 break;
773c5ba7 8655
75a70cf9 8656 case GIMPLE_OMP_MASTER:
bc7bff74 8657 case GIMPLE_OMP_TASKGROUP:
75a70cf9 8658 case GIMPLE_OMP_ORDERED:
8659 case GIMPLE_OMP_CRITICAL:
bc7bff74 8660 case GIMPLE_OMP_TEAMS:
61e47ac8 8661 expand_omp_synch (region);
8662 break;
773c5ba7 8663
75a70cf9 8664 case GIMPLE_OMP_ATOMIC_LOAD:
cb7f680b 8665 expand_omp_atomic (region);
8666 break;
8667
bc7bff74 8668 case GIMPLE_OMP_TARGET:
8669 expand_omp_target (region);
8670 break;
8671
61e47ac8 8672 default:
8673 gcc_unreachable ();
8674 }
cc5982dc 8675
1d22f541 8676 input_location = saved_location;
773c5ba7 8677 region = region->next;
8678 }
8679}
8680
8681
8682/* Helper for build_omp_regions. Scan the dominator tree starting at
28c92cbb 8683 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
8684 true, the function ends once a single tree is built (otherwise, whole
8685 forest of OMP constructs may be built). */
773c5ba7 8686
8687static void
28c92cbb 8688build_omp_regions_1 (basic_block bb, struct omp_region *parent,
8689 bool single_tree)
773c5ba7 8690{
75a70cf9 8691 gimple_stmt_iterator gsi;
8692 gimple stmt;
773c5ba7 8693 basic_block son;
8694
75a70cf9 8695 gsi = gsi_last_bb (bb);
8696 if (!gsi_end_p (gsi) && is_gimple_omp (gsi_stmt (gsi)))
773c5ba7 8697 {
8698 struct omp_region *region;
75a70cf9 8699 enum gimple_code code;
773c5ba7 8700
75a70cf9 8701 stmt = gsi_stmt (gsi);
8702 code = gimple_code (stmt);
8703 if (code == GIMPLE_OMP_RETURN)
773c5ba7 8704 {
8705 /* STMT is the return point out of region PARENT. Mark it
8706 as the exit point and make PARENT the immediately
8707 enclosing region. */
8708 gcc_assert (parent);
8709 region = parent;
61e47ac8 8710 region->exit = bb;
773c5ba7 8711 parent = parent->outer;
773c5ba7 8712 }
75a70cf9 8713 else if (code == GIMPLE_OMP_ATOMIC_STORE)
cb7f680b 8714 {
75a70cf9 8715 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
8716 GIMPLE_OMP_RETURN, but matches with
8717 GIMPLE_OMP_ATOMIC_LOAD. */
cb7f680b 8718 gcc_assert (parent);
75a70cf9 8719 gcc_assert (parent->type == GIMPLE_OMP_ATOMIC_LOAD);
cb7f680b 8720 region = parent;
8721 region->exit = bb;
8722 parent = parent->outer;
8723 }
8724
75a70cf9 8725 else if (code == GIMPLE_OMP_CONTINUE)
61e47ac8 8726 {
8727 gcc_assert (parent);
8728 parent->cont = bb;
8729 }
75a70cf9 8730 else if (code == GIMPLE_OMP_SECTIONS_SWITCH)
ac6e3339 8731 {
75a70cf9 8732 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
8733 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
8734 ;
ac6e3339 8735 }
bc7bff74 8736 else if (code == GIMPLE_OMP_TARGET
8737 && gimple_omp_target_kind (stmt) == GF_OMP_TARGET_KIND_UPDATE)
8738 new_omp_region (bb, code, parent);
773c5ba7 8739 else
8740 {
8741 /* Otherwise, this directive becomes the parent for a new
8742 region. */
61e47ac8 8743 region = new_omp_region (bb, code, parent);
773c5ba7 8744 parent = region;
8745 }
773c5ba7 8746 }
8747
28c92cbb 8748 if (single_tree && !parent)
8749 return;
8750
773c5ba7 8751 for (son = first_dom_son (CDI_DOMINATORS, bb);
8752 son;
8753 son = next_dom_son (CDI_DOMINATORS, son))
28c92cbb 8754 build_omp_regions_1 (son, parent, single_tree);
8755}
8756
8757/* Builds the tree of OMP regions rooted at ROOT, storing it to
8758 root_omp_region. */
8759
8760static void
8761build_omp_regions_root (basic_block root)
8762{
8763 gcc_assert (root_omp_region == NULL);
8764 build_omp_regions_1 (root, NULL, true);
8765 gcc_assert (root_omp_region != NULL);
773c5ba7 8766}
8767
28c92cbb 8768/* Expands omp construct (and its subconstructs) starting in HEAD. */
8769
8770void
8771omp_expand_local (basic_block head)
8772{
8773 build_omp_regions_root (head);
8774 if (dump_file && (dump_flags & TDF_DETAILS))
8775 {
8776 fprintf (dump_file, "\nOMP region tree\n\n");
8777 dump_omp_region (dump_file, root_omp_region, 0);
8778 fprintf (dump_file, "\n");
8779 }
8780
8781 remove_exit_barriers (root_omp_region);
8782 expand_omp (root_omp_region);
8783
8784 free_omp_regions ();
8785}
773c5ba7 8786
8787/* Scan the CFG and build a tree of OMP regions. Return the root of
8788 the OMP region tree. */
8789
8790static void
8791build_omp_regions (void)
8792{
61e47ac8 8793 gcc_assert (root_omp_region == NULL);
773c5ba7 8794 calculate_dominance_info (CDI_DOMINATORS);
34154e27 8795 build_omp_regions_1 (ENTRY_BLOCK_PTR_FOR_FN (cfun), NULL, false);
773c5ba7 8796}
8797
773c5ba7 8798/* Main entry point for expanding OMP-GIMPLE into runtime calls. */
8799
2a1990e9 8800static unsigned int
773c5ba7 8801execute_expand_omp (void)
8802{
8803 build_omp_regions ();
8804
61e47ac8 8805 if (!root_omp_region)
8806 return 0;
773c5ba7 8807
61e47ac8 8808 if (dump_file)
8809 {
8810 fprintf (dump_file, "\nOMP region tree\n\n");
8811 dump_omp_region (dump_file, root_omp_region, 0);
8812 fprintf (dump_file, "\n");
773c5ba7 8813 }
61e47ac8 8814
8815 remove_exit_barriers (root_omp_region);
8816
8817 expand_omp (root_omp_region);
8818
61e47ac8 8819 cleanup_tree_cfg ();
8820
8821 free_omp_regions ();
8822
2a1990e9 8823 return 0;
773c5ba7 8824}
8825
79acaae1 8826/* OMP expansion -- the default pass, run before creation of SSA form. */
8827
cbe8bda8 8828namespace {
8829
8830const pass_data pass_data_expand_omp =
8831{
8832 GIMPLE_PASS, /* type */
8833 "ompexp", /* name */
8834 OPTGROUP_NONE, /* optinfo_flags */
cbe8bda8 8835 TV_NONE, /* tv_id */
8836 PROP_gimple_any, /* properties_required */
8917c50b 8837 PROP_gimple_eomp, /* properties_provided */
cbe8bda8 8838 0, /* properties_destroyed */
8839 0, /* todo_flags_start */
8840 0, /* todo_flags_finish */
773c5ba7 8841};
cbe8bda8 8842
8843class pass_expand_omp : public gimple_opt_pass
8844{
8845public:
9af5ce0c 8846 pass_expand_omp (gcc::context *ctxt)
8847 : gimple_opt_pass (pass_data_expand_omp, ctxt)
cbe8bda8 8848 {}
8849
8850 /* opt_pass methods: */
8917c50b 8851 virtual unsigned int execute (function *)
31315c24 8852 {
8917c50b 8853 bool gate = ((flag_openmp != 0 || flag_openmp_simd != 0
8854 || flag_cilkplus != 0) && !seen_error ());
31315c24 8855
8917c50b 8856 /* This pass always runs, to provide PROP_gimple_eomp.
8857 But there is nothing to do unless -fopenmp is given. */
8858 if (!gate)
8859 return 0;
8860
8861 return execute_expand_omp ();
8862 }
cbe8bda8 8863
8864}; // class pass_expand_omp
8865
8866} // anon namespace
8867
8868gimple_opt_pass *
8869make_pass_expand_omp (gcc::context *ctxt)
8870{
8871 return new pass_expand_omp (ctxt);
8872}
8917c50b 8873
8874namespace {
8875
8876const pass_data pass_data_expand_omp_ssa =
8877{
8878 GIMPLE_PASS, /* type */
8879 "ompexpssa", /* name */
8880 OPTGROUP_NONE, /* optinfo_flags */
8881 TV_NONE, /* tv_id */
8882 PROP_cfg | PROP_ssa, /* properties_required */
8883 PROP_gimple_eomp, /* properties_provided */
8884 0, /* properties_destroyed */
8885 0, /* todo_flags_start */
8886 TODO_cleanup_cfg | TODO_rebuild_alias, /* todo_flags_finish */
8887};
8888
8889class pass_expand_omp_ssa : public gimple_opt_pass
8890{
8891public:
8892 pass_expand_omp_ssa (gcc::context *ctxt)
8893 : gimple_opt_pass (pass_data_expand_omp_ssa, ctxt)
8894 {}
8895
8896 /* opt_pass methods: */
8897 virtual bool gate (function *fun)
8898 {
8899 return !(fun->curr_properties & PROP_gimple_eomp);
8900 }
8901 virtual unsigned int execute (function *) { return execute_expand_omp (); }
8902
8903}; // class pass_expand_omp_ssa
8904
8905} // anon namespace
8906
8907gimple_opt_pass *
8908make_pass_expand_omp_ssa (gcc::context *ctxt)
8909{
8910 return new pass_expand_omp_ssa (ctxt);
8911}
773c5ba7 8912\f
8913/* Routines to lower OpenMP directives into OMP-GIMPLE. */
8914
bc7bff74 8915/* If ctx is a worksharing context inside of a cancellable parallel
8916 region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
8917 and conditional branch to parallel's cancel_label to handle
8918 cancellation in the implicit barrier. */
8919
8920static void
8921maybe_add_implicit_barrier_cancel (omp_context *ctx, gimple_seq *body)
8922{
8923 gimple omp_return = gimple_seq_last_stmt (*body);
8924 gcc_assert (gimple_code (omp_return) == GIMPLE_OMP_RETURN);
8925 if (gimple_omp_return_nowait_p (omp_return))
8926 return;
8927 if (ctx->outer
8928 && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_PARALLEL
8929 && ctx->outer->cancellable)
8930 {
15b28553 8931 tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL);
8932 tree c_bool_type = TREE_TYPE (TREE_TYPE (fndecl));
8933 tree lhs = create_tmp_var (c_bool_type, NULL);
bc7bff74 8934 gimple_omp_return_set_lhs (omp_return, lhs);
8935 tree fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
15b28553 8936 gimple g = gimple_build_cond (NE_EXPR, lhs,
8937 fold_convert (c_bool_type,
8938 boolean_false_node),
bc7bff74 8939 ctx->outer->cancel_label, fallthru_label);
8940 gimple_seq_add_stmt (body, g);
8941 gimple_seq_add_stmt (body, gimple_build_label (fallthru_label));
8942 }
8943}
8944
75a70cf9 8945/* Lower the OpenMP sections directive in the current statement in GSI_P.
8946 CTX is the enclosing OMP context for the current statement. */
773c5ba7 8947
8948static void
75a70cf9 8949lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
773c5ba7 8950{
75a70cf9 8951 tree block, control;
8952 gimple_stmt_iterator tgsi;
1a91d914 8953 gomp_sections *stmt;
8954 gimple t;
8955 gbind *new_stmt, *bind;
e3a19533 8956 gimple_seq ilist, dlist, olist, new_body;
773c5ba7 8957
1a91d914 8958 stmt = as_a <gomp_sections *> (gsi_stmt (*gsi_p));
773c5ba7 8959
8a4a28a8 8960 push_gimplify_context ();
773c5ba7 8961
8962 dlist = NULL;
8963 ilist = NULL;
75a70cf9 8964 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
bc7bff74 8965 &ilist, &dlist, ctx, NULL);
773c5ba7 8966
e3a19533 8967 new_body = gimple_omp_body (stmt);
8968 gimple_omp_set_body (stmt, NULL);
8969 tgsi = gsi_start (new_body);
8970 for (; !gsi_end_p (tgsi); gsi_next (&tgsi))
773c5ba7 8971 {
8972 omp_context *sctx;
75a70cf9 8973 gimple sec_start;
773c5ba7 8974
75a70cf9 8975 sec_start = gsi_stmt (tgsi);
773c5ba7 8976 sctx = maybe_lookup_ctx (sec_start);
8977 gcc_assert (sctx);
8978
e3a19533 8979 lower_omp (gimple_omp_body_ptr (sec_start), sctx);
8980 gsi_insert_seq_after (&tgsi, gimple_omp_body (sec_start),
8981 GSI_CONTINUE_LINKING);
75a70cf9 8982 gimple_omp_set_body (sec_start, NULL);
773c5ba7 8983
e3a19533 8984 if (gsi_one_before_end_p (tgsi))
773c5ba7 8985 {
75a70cf9 8986 gimple_seq l = NULL;
8987 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
773c5ba7 8988 &l, ctx);
e3a19533 8989 gsi_insert_seq_after (&tgsi, l, GSI_CONTINUE_LINKING);
75a70cf9 8990 gimple_omp_section_set_last (sec_start);
773c5ba7 8991 }
48e1416a 8992
e3a19533 8993 gsi_insert_after (&tgsi, gimple_build_omp_return (false),
8994 GSI_CONTINUE_LINKING);
773c5ba7 8995 }
1e8e9920 8996
8997 block = make_node (BLOCK);
e3a19533 8998 bind = gimple_build_bind (NULL, new_body, block);
1e8e9920 8999
75a70cf9 9000 olist = NULL;
9001 lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist, ctx);
773c5ba7 9002
1d22f541 9003 block = make_node (BLOCK);
75a70cf9 9004 new_stmt = gimple_build_bind (NULL, NULL, block);
e3a19533 9005 gsi_replace (gsi_p, new_stmt, true);
773c5ba7 9006
1d22f541 9007 pop_gimplify_context (new_stmt);
75a70cf9 9008 gimple_bind_append_vars (new_stmt, ctx->block_vars);
9009 BLOCK_VARS (block) = gimple_bind_vars (bind);
1d22f541 9010 if (BLOCK_VARS (block))
9011 TREE_USED (block) = 1;
9012
75a70cf9 9013 new_body = NULL;
9014 gimple_seq_add_seq (&new_body, ilist);
9015 gimple_seq_add_stmt (&new_body, stmt);
9016 gimple_seq_add_stmt (&new_body, gimple_build_omp_sections_switch ());
9017 gimple_seq_add_stmt (&new_body, bind);
61e47ac8 9018
ac6e3339 9019 control = create_tmp_var (unsigned_type_node, ".section");
75a70cf9 9020 t = gimple_build_omp_continue (control, control);
9021 gimple_omp_sections_set_control (stmt, control);
9022 gimple_seq_add_stmt (&new_body, t);
61e47ac8 9023
75a70cf9 9024 gimple_seq_add_seq (&new_body, olist);
bc7bff74 9025 if (ctx->cancellable)
9026 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
75a70cf9 9027 gimple_seq_add_seq (&new_body, dlist);
773c5ba7 9028
75a70cf9 9029 new_body = maybe_catch_exception (new_body);
aade31a0 9030
75a70cf9 9031 t = gimple_build_omp_return
9032 (!!find_omp_clause (gimple_omp_sections_clauses (stmt),
9033 OMP_CLAUSE_NOWAIT));
9034 gimple_seq_add_stmt (&new_body, t);
bc7bff74 9035 maybe_add_implicit_barrier_cancel (ctx, &new_body);
61e47ac8 9036
75a70cf9 9037 gimple_bind_set_body (new_stmt, new_body);
1e8e9920 9038}
9039
9040
773c5ba7 9041/* A subroutine of lower_omp_single. Expand the simple form of
75a70cf9 9042 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
1e8e9920 9043
9044 if (GOMP_single_start ())
9045 BODY;
9046 [ GOMP_barrier (); ] -> unless 'nowait' is present.
773c5ba7 9047
9048 FIXME. It may be better to delay expanding the logic of this until
9049 pass_expand_omp. The expanded logic may make the job more difficult
9050 to a synchronization analysis pass. */
1e8e9920 9051
9052static void
1a91d914 9053lower_omp_single_simple (gomp_single *single_stmt, gimple_seq *pre_p)
1e8e9920 9054{
e60a6f7b 9055 location_t loc = gimple_location (single_stmt);
9056 tree tlabel = create_artificial_label (loc);
9057 tree flabel = create_artificial_label (loc);
75a70cf9 9058 gimple call, cond;
9059 tree lhs, decl;
9060
b9a16870 9061 decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START);
75a70cf9 9062 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)), NULL);
9063 call = gimple_build_call (decl, 0);
9064 gimple_call_set_lhs (call, lhs);
9065 gimple_seq_add_stmt (pre_p, call);
9066
9067 cond = gimple_build_cond (EQ_EXPR, lhs,
389dd41b 9068 fold_convert_loc (loc, TREE_TYPE (lhs),
9069 boolean_true_node),
75a70cf9 9070 tlabel, flabel);
9071 gimple_seq_add_stmt (pre_p, cond);
9072 gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
9073 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
9074 gimple_seq_add_stmt (pre_p, gimple_build_label (flabel));
1e8e9920 9075}
9076
773c5ba7 9077
9078/* A subroutine of lower_omp_single. Expand the simple form of
75a70cf9 9079 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
1e8e9920 9080
9081 #pragma omp single copyprivate (a, b, c)
9082
9083 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
9084
9085 {
9086 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
9087 {
9088 BODY;
9089 copyout.a = a;
9090 copyout.b = b;
9091 copyout.c = c;
9092 GOMP_single_copy_end (&copyout);
9093 }
9094 else
9095 {
9096 a = copyout_p->a;
9097 b = copyout_p->b;
9098 c = copyout_p->c;
9099 }
9100 GOMP_barrier ();
9101 }
773c5ba7 9102
9103 FIXME. It may be better to delay expanding the logic of this until
9104 pass_expand_omp. The expanded logic may make the job more difficult
9105 to a synchronization analysis pass. */
1e8e9920 9106
9107static void
1a91d914 9108lower_omp_single_copy (gomp_single *single_stmt, gimple_seq *pre_p,
9109 omp_context *ctx)
1e8e9920 9110{
b9a16870 9111 tree ptr_type, t, l0, l1, l2, bfn_decl;
75a70cf9 9112 gimple_seq copyin_seq;
e60a6f7b 9113 location_t loc = gimple_location (single_stmt);
1e8e9920 9114
9115 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
9116
9117 ptr_type = build_pointer_type (ctx->record_type);
9118 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
9119
e60a6f7b 9120 l0 = create_artificial_label (loc);
9121 l1 = create_artificial_label (loc);
9122 l2 = create_artificial_label (loc);
1e8e9920 9123
b9a16870 9124 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START);
9125 t = build_call_expr_loc (loc, bfn_decl, 0);
389dd41b 9126 t = fold_convert_loc (loc, ptr_type, t);
75a70cf9 9127 gimplify_assign (ctx->receiver_decl, t, pre_p);
1e8e9920 9128
9129 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
9130 build_int_cst (ptr_type, 0));
9131 t = build3 (COND_EXPR, void_type_node, t,
9132 build_and_jump (&l0), build_and_jump (&l1));
9133 gimplify_and_add (t, pre_p);
9134
75a70cf9 9135 gimple_seq_add_stmt (pre_p, gimple_build_label (l0));
1e8e9920 9136
75a70cf9 9137 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
1e8e9920 9138
9139 copyin_seq = NULL;
75a70cf9 9140 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
1e8e9920 9141 &copyin_seq, ctx);
9142
389dd41b 9143 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
b9a16870 9144 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END);
9145 t = build_call_expr_loc (loc, bfn_decl, 1, t);
1e8e9920 9146 gimplify_and_add (t, pre_p);
9147
9148 t = build_and_jump (&l2);
9149 gimplify_and_add (t, pre_p);
9150
75a70cf9 9151 gimple_seq_add_stmt (pre_p, gimple_build_label (l1));
1e8e9920 9152
75a70cf9 9153 gimple_seq_add_seq (pre_p, copyin_seq);
1e8e9920 9154
75a70cf9 9155 gimple_seq_add_stmt (pre_p, gimple_build_label (l2));
1e8e9920 9156}
9157
773c5ba7 9158
1e8e9920 9159/* Expand code for an OpenMP single directive. */
9160
9161static void
75a70cf9 9162lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
1e8e9920 9163{
75a70cf9 9164 tree block;
1a91d914 9165 gimple t;
9166 gomp_single *single_stmt = as_a <gomp_single *> (gsi_stmt (*gsi_p));
9167 gbind *bind;
bc7bff74 9168 gimple_seq bind_body, bind_body_tail = NULL, dlist;
1e8e9920 9169
8a4a28a8 9170 push_gimplify_context ();
1e8e9920 9171
e3a19533 9172 block = make_node (BLOCK);
9173 bind = gimple_build_bind (NULL, NULL, block);
9174 gsi_replace (gsi_p, bind, true);
75a70cf9 9175 bind_body = NULL;
e3a19533 9176 dlist = NULL;
75a70cf9 9177 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt),
bc7bff74 9178 &bind_body, &dlist, ctx, NULL);
e3a19533 9179 lower_omp (gimple_omp_body_ptr (single_stmt), ctx);
1e8e9920 9180
75a70cf9 9181 gimple_seq_add_stmt (&bind_body, single_stmt);
1e8e9920 9182
9183 if (ctx->record_type)
75a70cf9 9184 lower_omp_single_copy (single_stmt, &bind_body, ctx);
1e8e9920 9185 else
75a70cf9 9186 lower_omp_single_simple (single_stmt, &bind_body);
9187
9188 gimple_omp_set_body (single_stmt, NULL);
1e8e9920 9189
75a70cf9 9190 gimple_seq_add_seq (&bind_body, dlist);
61e47ac8 9191
75a70cf9 9192 bind_body = maybe_catch_exception (bind_body);
61e47ac8 9193
48e1416a 9194 t = gimple_build_omp_return
75a70cf9 9195 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt),
9196 OMP_CLAUSE_NOWAIT));
bc7bff74 9197 gimple_seq_add_stmt (&bind_body_tail, t);
9198 maybe_add_implicit_barrier_cancel (ctx, &bind_body_tail);
9199 if (ctx->record_type)
9200 {
9201 gimple_stmt_iterator gsi = gsi_start (bind_body_tail);
9202 tree clobber = build_constructor (ctx->record_type, NULL);
9203 TREE_THIS_VOLATILE (clobber) = 1;
9204 gsi_insert_after (&gsi, gimple_build_assign (ctx->sender_decl,
9205 clobber), GSI_SAME_STMT);
9206 }
9207 gimple_seq_add_seq (&bind_body, bind_body_tail);
e3a19533 9208 gimple_bind_set_body (bind, bind_body);
61e47ac8 9209
1e8e9920 9210 pop_gimplify_context (bind);
773c5ba7 9211
75a70cf9 9212 gimple_bind_append_vars (bind, ctx->block_vars);
9213 BLOCK_VARS (block) = ctx->block_vars;
1d22f541 9214 if (BLOCK_VARS (block))
9215 TREE_USED (block) = 1;
1e8e9920 9216}
9217
773c5ba7 9218
1e8e9920 9219/* Expand code for an OpenMP master directive. */
9220
9221static void
75a70cf9 9222lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
1e8e9920 9223{
b9a16870 9224 tree block, lab = NULL, x, bfn_decl;
1a91d914 9225 gimple stmt = gsi_stmt (*gsi_p);
9226 gbind *bind;
389dd41b 9227 location_t loc = gimple_location (stmt);
75a70cf9 9228 gimple_seq tseq;
1e8e9920 9229
8a4a28a8 9230 push_gimplify_context ();
1e8e9920 9231
9232 block = make_node (BLOCK);
e3a19533 9233 bind = gimple_build_bind (NULL, NULL, block);
9234 gsi_replace (gsi_p, bind, true);
9235 gimple_bind_add_stmt (bind, stmt);
61e47ac8 9236
b9a16870 9237 bfn_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
9238 x = build_call_expr_loc (loc, bfn_decl, 0);
1e8e9920 9239 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
9240 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
75a70cf9 9241 tseq = NULL;
9242 gimplify_and_add (x, &tseq);
9243 gimple_bind_add_seq (bind, tseq);
1e8e9920 9244
e3a19533 9245 lower_omp (gimple_omp_body_ptr (stmt), ctx);
75a70cf9 9246 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
9247 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
9248 gimple_omp_set_body (stmt, NULL);
1e8e9920 9249
75a70cf9 9250 gimple_bind_add_stmt (bind, gimple_build_label (lab));
61e47ac8 9251
75a70cf9 9252 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
61e47ac8 9253
1e8e9920 9254 pop_gimplify_context (bind);
773c5ba7 9255
75a70cf9 9256 gimple_bind_append_vars (bind, ctx->block_vars);
9257 BLOCK_VARS (block) = ctx->block_vars;
1e8e9920 9258}
9259
773c5ba7 9260
bc7bff74 9261/* Expand code for an OpenMP taskgroup directive. */
9262
9263static void
9264lower_omp_taskgroup (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9265{
1a91d914 9266 gimple stmt = gsi_stmt (*gsi_p);
9267 gcall *x;
9268 gbind *bind;
bc7bff74 9269 tree block = make_node (BLOCK);
9270
9271 bind = gimple_build_bind (NULL, NULL, block);
9272 gsi_replace (gsi_p, bind, true);
9273 gimple_bind_add_stmt (bind, stmt);
9274
9275 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START),
9276 0);
9277 gimple_bind_add_stmt (bind, x);
9278
9279 lower_omp (gimple_omp_body_ptr (stmt), ctx);
9280 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
9281 gimple_omp_set_body (stmt, NULL);
9282
9283 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
9284
9285 gimple_bind_append_vars (bind, ctx->block_vars);
9286 BLOCK_VARS (block) = ctx->block_vars;
9287}
9288
9289
1e8e9920 9290/* Expand code for an OpenMP ordered directive. */
9291
9292static void
75a70cf9 9293lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
1e8e9920 9294{
75a70cf9 9295 tree block;
1a91d914 9296 gimple stmt = gsi_stmt (*gsi_p);
9297 gcall *x;
9298 gbind *bind;
1e8e9920 9299
8a4a28a8 9300 push_gimplify_context ();
1e8e9920 9301
9302 block = make_node (BLOCK);
e3a19533 9303 bind = gimple_build_bind (NULL, NULL, block);
9304 gsi_replace (gsi_p, bind, true);
9305 gimple_bind_add_stmt (bind, stmt);
61e47ac8 9306
b9a16870 9307 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START),
9308 0);
75a70cf9 9309 gimple_bind_add_stmt (bind, x);
1e8e9920 9310
e3a19533 9311 lower_omp (gimple_omp_body_ptr (stmt), ctx);
75a70cf9 9312 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
9313 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
9314 gimple_omp_set_body (stmt, NULL);
1e8e9920 9315
b9a16870 9316 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END), 0);
75a70cf9 9317 gimple_bind_add_stmt (bind, x);
61e47ac8 9318
75a70cf9 9319 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
61e47ac8 9320
1e8e9920 9321 pop_gimplify_context (bind);
773c5ba7 9322
75a70cf9 9323 gimple_bind_append_vars (bind, ctx->block_vars);
9324 BLOCK_VARS (block) = gimple_bind_vars (bind);
1e8e9920 9325}
9326
1e8e9920 9327
75a70cf9 9328/* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
1e8e9920 9329 substitution of a couple of function calls. But in the NAMED case,
9330 requires that languages coordinate a symbol name. It is therefore
9331 best put here in common code. */
9332
d4786b13 9333static GTY(()) hash_map<tree, tree> *critical_name_mutexes;
1e8e9920 9334
9335static void
75a70cf9 9336lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
1e8e9920 9337{
75a70cf9 9338 tree block;
9339 tree name, lock, unlock;
1a91d914 9340 gomp_critical *stmt = as_a <gomp_critical *> (gsi_stmt (*gsi_p));
9341 gbind *bind;
389dd41b 9342 location_t loc = gimple_location (stmt);
75a70cf9 9343 gimple_seq tbody;
1e8e9920 9344
75a70cf9 9345 name = gimple_omp_critical_name (stmt);
1e8e9920 9346 if (name)
9347 {
c2f47e15 9348 tree decl;
1e8e9920 9349
9350 if (!critical_name_mutexes)
d4786b13 9351 critical_name_mutexes = hash_map<tree, tree>::create_ggc (10);
1e8e9920 9352
d4786b13 9353 tree *n = critical_name_mutexes->get (name);
1e8e9920 9354 if (n == NULL)
9355 {
9356 char *new_str;
9357
9358 decl = create_tmp_var_raw (ptr_type_node, NULL);
9359
9360 new_str = ACONCAT ((".gomp_critical_user_",
9361 IDENTIFIER_POINTER (name), NULL));
9362 DECL_NAME (decl) = get_identifier (new_str);
9363 TREE_PUBLIC (decl) = 1;
9364 TREE_STATIC (decl) = 1;
9365 DECL_COMMON (decl) = 1;
9366 DECL_ARTIFICIAL (decl) = 1;
9367 DECL_IGNORED_P (decl) = 1;
b0c5e347 9368
97221fd7 9369 varpool_node::finalize_decl (decl);
1e8e9920 9370
d4786b13 9371 critical_name_mutexes->put (name, decl);
1e8e9920 9372 }
9373 else
d4786b13 9374 decl = *n;
1e8e9920 9375
351fb0ce 9376 /* If '#pragma omp critical' is inside target region or
9377 inside function marked as offloadable, the symbol must be
9378 marked as offloadable too. */
9379 omp_context *octx;
9380 if (cgraph_node::get (current_function_decl)->offloadable)
9381 varpool_node::get_create (decl)->offloadable = 1;
9382 else
9383 for (octx = ctx->outer; octx; octx = octx->outer)
9384 if (is_targetreg_ctx (octx))
9385 {
9386 varpool_node::get_create (decl)->offloadable = 1;
9387 break;
9388 }
9389
b9a16870 9390 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START);
389dd41b 9391 lock = build_call_expr_loc (loc, lock, 1, build_fold_addr_expr_loc (loc, decl));
1e8e9920 9392
b9a16870 9393 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END);
389dd41b 9394 unlock = build_call_expr_loc (loc, unlock, 1,
9395 build_fold_addr_expr_loc (loc, decl));
1e8e9920 9396 }
9397 else
9398 {
b9a16870 9399 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START);
389dd41b 9400 lock = build_call_expr_loc (loc, lock, 0);
1e8e9920 9401
b9a16870 9402 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END);
389dd41b 9403 unlock = build_call_expr_loc (loc, unlock, 0);
1e8e9920 9404 }
9405
8a4a28a8 9406 push_gimplify_context ();
1e8e9920 9407
9408 block = make_node (BLOCK);
e3a19533 9409 bind = gimple_build_bind (NULL, NULL, block);
9410 gsi_replace (gsi_p, bind, true);
9411 gimple_bind_add_stmt (bind, stmt);
61e47ac8 9412
75a70cf9 9413 tbody = gimple_bind_body (bind);
9414 gimplify_and_add (lock, &tbody);
9415 gimple_bind_set_body (bind, tbody);
1e8e9920 9416
e3a19533 9417 lower_omp (gimple_omp_body_ptr (stmt), ctx);
75a70cf9 9418 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
9419 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
9420 gimple_omp_set_body (stmt, NULL);
1e8e9920 9421
75a70cf9 9422 tbody = gimple_bind_body (bind);
9423 gimplify_and_add (unlock, &tbody);
9424 gimple_bind_set_body (bind, tbody);
61e47ac8 9425
75a70cf9 9426 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
1e8e9920 9427
9428 pop_gimplify_context (bind);
75a70cf9 9429 gimple_bind_append_vars (bind, ctx->block_vars);
9430 BLOCK_VARS (block) = gimple_bind_vars (bind);
773c5ba7 9431}
9432
9433
9434/* A subroutine of lower_omp_for. Generate code to emit the predicate
9435 for a lastprivate clause. Given a loop control predicate of (V
9436 cond N2), we gate the clause on (!(V cond N2)). The lowered form
1e4afe3c 9437 is appended to *DLIST, iterator initialization is appended to
9438 *BODY_P. */
773c5ba7 9439
9440static void
75a70cf9 9441lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
9442 gimple_seq *dlist, struct omp_context *ctx)
773c5ba7 9443{
75a70cf9 9444 tree clauses, cond, vinit;
773c5ba7 9445 enum tree_code cond_code;
75a70cf9 9446 gimple_seq stmts;
48e1416a 9447
fd6481cf 9448 cond_code = fd->loop.cond_code;
773c5ba7 9449 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
9450
9451 /* When possible, use a strict equality expression. This can let VRP
9452 type optimizations deduce the value and remove a copy. */
e913b5cd 9453 if (tree_fits_shwi_p (fd->loop.step))
773c5ba7 9454 {
e913b5cd 9455 HOST_WIDE_INT step = tree_to_shwi (fd->loop.step);
773c5ba7 9456 if (step == 1 || step == -1)
9457 cond_code = EQ_EXPR;
9458 }
9459
fd6481cf 9460 cond = build2 (cond_code, boolean_type_node, fd->loop.v, fd->loop.n2);
773c5ba7 9461
75a70cf9 9462 clauses = gimple_omp_for_clauses (fd->for_stmt);
1e4afe3c 9463 stmts = NULL;
9464 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
75a70cf9 9465 if (!gimple_seq_empty_p (stmts))
1e4afe3c 9466 {
75a70cf9 9467 gimple_seq_add_seq (&stmts, *dlist);
fd6481cf 9468 *dlist = stmts;
1e4afe3c 9469
9470 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
fd6481cf 9471 vinit = fd->loop.n1;
1e4afe3c 9472 if (cond_code == EQ_EXPR
e913b5cd 9473 && tree_fits_shwi_p (fd->loop.n2)
fd6481cf 9474 && ! integer_zerop (fd->loop.n2))
9475 vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0);
3d483a94 9476 else
9477 vinit = unshare_expr (vinit);
1e4afe3c 9478
9479 /* Initialize the iterator variable, so that threads that don't execute
9480 any iterations don't execute the lastprivate clauses by accident. */
75a70cf9 9481 gimplify_assign (fd->loop.v, vinit, body_p);
1e4afe3c 9482 }
773c5ba7 9483}
9484
9485
9486/* Lower code for an OpenMP loop directive. */
9487
9488static void
75a70cf9 9489lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
773c5ba7 9490{
75a70cf9 9491 tree *rhs_p, block;
bc7bff74 9492 struct omp_for_data fd, *fdp = NULL;
1a91d914 9493 gomp_for *stmt = as_a <gomp_for *> (gsi_stmt (*gsi_p));
9494 gbind *new_stmt;
f018d957 9495 gimple_seq omp_for_body, body, dlist;
75a70cf9 9496 size_t i;
773c5ba7 9497
8a4a28a8 9498 push_gimplify_context ();
773c5ba7 9499
e3a19533 9500 lower_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
773c5ba7 9501
1d22f541 9502 block = make_node (BLOCK);
75a70cf9 9503 new_stmt = gimple_build_bind (NULL, NULL, block);
e3a19533 9504 /* Replace at gsi right away, so that 'stmt' is no member
9505 of a sequence anymore as we're going to add to to a different
9506 one below. */
9507 gsi_replace (gsi_p, new_stmt, true);
1d22f541 9508
773c5ba7 9509 /* Move declaration of temporaries in the loop body before we make
9510 it go away. */
75a70cf9 9511 omp_for_body = gimple_omp_body (stmt);
9512 if (!gimple_seq_empty_p (omp_for_body)
9513 && gimple_code (gimple_seq_first_stmt (omp_for_body)) == GIMPLE_BIND)
9514 {
1a91d914 9515 gbind *inner_bind
9516 = as_a <gbind *> (gimple_seq_first_stmt (omp_for_body));
6d5a8d89 9517 tree vars = gimple_bind_vars (inner_bind);
75a70cf9 9518 gimple_bind_append_vars (new_stmt, vars);
6d5a8d89 9519 /* bind_vars/BLOCK_VARS are being moved to new_stmt/block, don't
9520 keep them on the inner_bind and it's block. */
9521 gimple_bind_set_vars (inner_bind, NULL_TREE);
9522 if (gimple_bind_block (inner_bind))
9523 BLOCK_VARS (gimple_bind_block (inner_bind)) = NULL_TREE;
75a70cf9 9524 }
773c5ba7 9525
bc7bff74 9526 if (gimple_omp_for_combined_into_p (stmt))
9527 {
9528 extract_omp_for_data (stmt, &fd, NULL);
9529 fdp = &fd;
9530
9531 /* We need two temporaries with fd.loop.v type (istart/iend)
9532 and then (fd.collapse - 1) temporaries with the same
9533 type for count2 ... countN-1 vars if not constant. */
9534 size_t count = 2;
9535 tree type = fd.iter_type;
9536 if (fd.collapse > 1
9537 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
9538 count += fd.collapse - 1;
9539 bool parallel_for = gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR;
9540 tree outerc = NULL, *pc = gimple_omp_for_clauses_ptr (stmt);
9541 tree clauses = *pc;
9542 if (parallel_for)
9543 outerc
9544 = find_omp_clause (gimple_omp_parallel_clauses (ctx->outer->stmt),
9545 OMP_CLAUSE__LOOPTEMP_);
9546 for (i = 0; i < count; i++)
9547 {
9548 tree temp;
9549 if (parallel_for)
9550 {
9551 gcc_assert (outerc);
9552 temp = lookup_decl (OMP_CLAUSE_DECL (outerc), ctx->outer);
9553 outerc = find_omp_clause (OMP_CLAUSE_CHAIN (outerc),
9554 OMP_CLAUSE__LOOPTEMP_);
9555 }
9556 else
691447ab 9557 {
9558 temp = create_tmp_var (type, NULL);
9559 insert_decl_map (&ctx->outer->cb, temp, temp);
9560 }
bc7bff74 9561 *pc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
9562 OMP_CLAUSE_DECL (*pc) = temp;
9563 pc = &OMP_CLAUSE_CHAIN (*pc);
9564 }
9565 *pc = clauses;
9566 }
9567
75a70cf9 9568 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
773c5ba7 9569 dlist = NULL;
75a70cf9 9570 body = NULL;
bc7bff74 9571 lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx,
9572 fdp);
75a70cf9 9573 gimple_seq_add_seq (&body, gimple_omp_for_pre_body (stmt));
773c5ba7 9574
3d483a94 9575 lower_omp (gimple_omp_body_ptr (stmt), ctx);
9576
773c5ba7 9577 /* Lower the header expressions. At this point, we can assume that
9578 the header is of the form:
9579
9580 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
9581
9582 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
9583 using the .omp_data_s mapping, if needed. */
75a70cf9 9584 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
fd6481cf 9585 {
75a70cf9 9586 rhs_p = gimple_omp_for_initial_ptr (stmt, i);
fd6481cf 9587 if (!is_gimple_min_invariant (*rhs_p))
75a70cf9 9588 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
fd6481cf 9589
75a70cf9 9590 rhs_p = gimple_omp_for_final_ptr (stmt, i);
fd6481cf 9591 if (!is_gimple_min_invariant (*rhs_p))
75a70cf9 9592 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
fd6481cf 9593
75a70cf9 9594 rhs_p = &TREE_OPERAND (gimple_omp_for_incr (stmt, i), 1);
fd6481cf 9595 if (!is_gimple_min_invariant (*rhs_p))
75a70cf9 9596 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
fd6481cf 9597 }
773c5ba7 9598
9599 /* Once lowered, extract the bounds and clauses. */
fd6481cf 9600 extract_omp_for_data (stmt, &fd, NULL);
773c5ba7 9601
75a70cf9 9602 lower_omp_for_lastprivate (&fd, &body, &dlist, ctx);
773c5ba7 9603
75a70cf9 9604 gimple_seq_add_stmt (&body, stmt);
9605 gimple_seq_add_seq (&body, gimple_omp_body (stmt));
61e47ac8 9606
75a70cf9 9607 gimple_seq_add_stmt (&body, gimple_build_omp_continue (fd.loop.v,
9608 fd.loop.v));
61e47ac8 9609
773c5ba7 9610 /* After the loop, add exit clauses. */
75a70cf9 9611 lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, ctx);
bc7bff74 9612
9613 if (ctx->cancellable)
9614 gimple_seq_add_stmt (&body, gimple_build_label (ctx->cancel_label));
9615
75a70cf9 9616 gimple_seq_add_seq (&body, dlist);
773c5ba7 9617
75a70cf9 9618 body = maybe_catch_exception (body);
aade31a0 9619
61e47ac8 9620 /* Region exit marker goes at the end of the loop body. */
75a70cf9 9621 gimple_seq_add_stmt (&body, gimple_build_omp_return (fd.have_nowait));
bc7bff74 9622 maybe_add_implicit_barrier_cancel (ctx, &body);
1d22f541 9623 pop_gimplify_context (new_stmt);
75a70cf9 9624
9625 gimple_bind_append_vars (new_stmt, ctx->block_vars);
9626 BLOCK_VARS (block) = gimple_bind_vars (new_stmt);
1d22f541 9627 if (BLOCK_VARS (block))
9628 TREE_USED (block) = 1;
773c5ba7 9629
75a70cf9 9630 gimple_bind_set_body (new_stmt, body);
9631 gimple_omp_set_body (stmt, NULL);
9632 gimple_omp_for_set_pre_body (stmt, NULL);
1e8e9920 9633}
9634
48e1416a 9635/* Callback for walk_stmts. Check if the current statement only contains
a7dfc4fe 9636 GIMPLE_OMP_FOR or GIMPLE_OMP_SECTIONS. */
de7ef844 9637
9638static tree
75a70cf9 9639check_combined_parallel (gimple_stmt_iterator *gsi_p,
9640 bool *handled_ops_p,
9641 struct walk_stmt_info *wi)
de7ef844 9642{
4077bf7a 9643 int *info = (int *) wi->info;
75a70cf9 9644 gimple stmt = gsi_stmt (*gsi_p);
de7ef844 9645
75a70cf9 9646 *handled_ops_p = true;
9647 switch (gimple_code (stmt))
de7ef844 9648 {
75a70cf9 9649 WALK_SUBSTMTS;
9650
9651 case GIMPLE_OMP_FOR:
9652 case GIMPLE_OMP_SECTIONS:
de7ef844 9653 *info = *info == 0 ? 1 : -1;
9654 break;
9655 default:
9656 *info = -1;
9657 break;
9658 }
9659 return NULL;
9660}
773c5ba7 9661
fd6481cf 9662struct omp_taskcopy_context
9663{
9664 /* This field must be at the beginning, as we do "inheritance": Some
9665 callback functions for tree-inline.c (e.g., omp_copy_decl)
9666 receive a copy_body_data pointer that is up-casted to an
9667 omp_context pointer. */
9668 copy_body_data cb;
9669 omp_context *ctx;
9670};
9671
9672static tree
9673task_copyfn_copy_decl (tree var, copy_body_data *cb)
9674{
9675 struct omp_taskcopy_context *tcctx = (struct omp_taskcopy_context *) cb;
9676
9677 if (splay_tree_lookup (tcctx->ctx->sfield_map, (splay_tree_key) var))
9678 return create_tmp_var (TREE_TYPE (var), NULL);
9679
9680 return var;
9681}
9682
9683static tree
9684task_copyfn_remap_type (struct omp_taskcopy_context *tcctx, tree orig_type)
9685{
9686 tree name, new_fields = NULL, type, f;
9687
9688 type = lang_hooks.types.make_type (RECORD_TYPE);
9689 name = DECL_NAME (TYPE_NAME (orig_type));
e60a6f7b 9690 name = build_decl (gimple_location (tcctx->ctx->stmt),
9691 TYPE_DECL, name, type);
fd6481cf 9692 TYPE_NAME (type) = name;
9693
9694 for (f = TYPE_FIELDS (orig_type); f ; f = TREE_CHAIN (f))
9695 {
9696 tree new_f = copy_node (f);
9697 DECL_CONTEXT (new_f) = type;
9698 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &tcctx->cb);
9699 TREE_CHAIN (new_f) = new_fields;
75a70cf9 9700 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &tcctx->cb, NULL);
9701 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r, &tcctx->cb, NULL);
9702 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
9703 &tcctx->cb, NULL);
fd6481cf 9704 new_fields = new_f;
06ecf488 9705 tcctx->cb.decl_map->put (f, new_f);
fd6481cf 9706 }
9707 TYPE_FIELDS (type) = nreverse (new_fields);
9708 layout_type (type);
9709 return type;
9710}
9711
9712/* Create task copyfn. */
9713
9714static void
1a91d914 9715create_task_copyfn (gomp_task *task_stmt, omp_context *ctx)
fd6481cf 9716{
9717 struct function *child_cfun;
9718 tree child_fn, t, c, src, dst, f, sf, arg, sarg, decl;
9719 tree record_type, srecord_type, bind, list;
9720 bool record_needs_remap = false, srecord_needs_remap = false;
9721 splay_tree_node n;
9722 struct omp_taskcopy_context tcctx;
389dd41b 9723 location_t loc = gimple_location (task_stmt);
fd6481cf 9724
75a70cf9 9725 child_fn = gimple_omp_task_copy_fn (task_stmt);
fd6481cf 9726 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
9727 gcc_assert (child_cfun->cfg == NULL);
fd6481cf 9728 DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
9729
9730 /* Reset DECL_CONTEXT on function arguments. */
1767a056 9731 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
fd6481cf 9732 DECL_CONTEXT (t) = child_fn;
9733
9734 /* Populate the function. */
8a4a28a8 9735 push_gimplify_context ();
9078126c 9736 push_cfun (child_cfun);
fd6481cf 9737
9738 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
9739 TREE_SIDE_EFFECTS (bind) = 1;
9740 list = NULL;
9741 DECL_SAVED_TREE (child_fn) = bind;
75a70cf9 9742 DECL_SOURCE_LOCATION (child_fn) = gimple_location (task_stmt);
fd6481cf 9743
9744 /* Remap src and dst argument types if needed. */
9745 record_type = ctx->record_type;
9746 srecord_type = ctx->srecord_type;
1767a056 9747 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
fd6481cf 9748 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
9749 {
9750 record_needs_remap = true;
9751 break;
9752 }
1767a056 9753 for (f = TYPE_FIELDS (srecord_type); f ; f = DECL_CHAIN (f))
fd6481cf 9754 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
9755 {
9756 srecord_needs_remap = true;
9757 break;
9758 }
9759
9760 if (record_needs_remap || srecord_needs_remap)
9761 {
9762 memset (&tcctx, '\0', sizeof (tcctx));
9763 tcctx.cb.src_fn = ctx->cb.src_fn;
9764 tcctx.cb.dst_fn = child_fn;
415d1b9a 9765 tcctx.cb.src_node = cgraph_node::get (tcctx.cb.src_fn);
53f79206 9766 gcc_checking_assert (tcctx.cb.src_node);
fd6481cf 9767 tcctx.cb.dst_node = tcctx.cb.src_node;
9768 tcctx.cb.src_cfun = ctx->cb.src_cfun;
9769 tcctx.cb.copy_decl = task_copyfn_copy_decl;
e38def9c 9770 tcctx.cb.eh_lp_nr = 0;
fd6481cf 9771 tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
06ecf488 9772 tcctx.cb.decl_map = new hash_map<tree, tree>;
fd6481cf 9773 tcctx.ctx = ctx;
9774
9775 if (record_needs_remap)
9776 record_type = task_copyfn_remap_type (&tcctx, record_type);
9777 if (srecord_needs_remap)
9778 srecord_type = task_copyfn_remap_type (&tcctx, srecord_type);
9779 }
9780 else
9781 tcctx.cb.decl_map = NULL;
9782
fd6481cf 9783 arg = DECL_ARGUMENTS (child_fn);
9784 TREE_TYPE (arg) = build_pointer_type (record_type);
1767a056 9785 sarg = DECL_CHAIN (arg);
fd6481cf 9786 TREE_TYPE (sarg) = build_pointer_type (srecord_type);
9787
9788 /* First pass: initialize temporaries used in record_type and srecord_type
9789 sizes and field offsets. */
9790 if (tcctx.cb.decl_map)
75a70cf9 9791 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
fd6481cf 9792 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
9793 {
9794 tree *p;
9795
9796 decl = OMP_CLAUSE_DECL (c);
06ecf488 9797 p = tcctx.cb.decl_map->get (decl);
fd6481cf 9798 if (p == NULL)
9799 continue;
9800 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9801 sf = (tree) n->value;
06ecf488 9802 sf = *tcctx.cb.decl_map->get (sf);
182cf5a9 9803 src = build_simple_mem_ref_loc (loc, sarg);
445d06b6 9804 src = omp_build_component_ref (src, sf);
75a70cf9 9805 t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
fd6481cf 9806 append_to_statement_list (t, &list);
9807 }
9808
9809 /* Second pass: copy shared var pointers and copy construct non-VLA
9810 firstprivate vars. */
75a70cf9 9811 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
fd6481cf 9812 switch (OMP_CLAUSE_CODE (c))
9813 {
9814 case OMP_CLAUSE_SHARED:
9815 decl = OMP_CLAUSE_DECL (c);
9816 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9817 if (n == NULL)
9818 break;
9819 f = (tree) n->value;
9820 if (tcctx.cb.decl_map)
06ecf488 9821 f = *tcctx.cb.decl_map->get (f);
fd6481cf 9822 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9823 sf = (tree) n->value;
9824 if (tcctx.cb.decl_map)
06ecf488 9825 sf = *tcctx.cb.decl_map->get (sf);
182cf5a9 9826 src = build_simple_mem_ref_loc (loc, sarg);
445d06b6 9827 src = omp_build_component_ref (src, sf);
182cf5a9 9828 dst = build_simple_mem_ref_loc (loc, arg);
445d06b6 9829 dst = omp_build_component_ref (dst, f);
75a70cf9 9830 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
fd6481cf 9831 append_to_statement_list (t, &list);
9832 break;
9833 case OMP_CLAUSE_FIRSTPRIVATE:
9834 decl = OMP_CLAUSE_DECL (c);
9835 if (is_variable_sized (decl))
9836 break;
9837 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9838 if (n == NULL)
9839 break;
9840 f = (tree) n->value;
9841 if (tcctx.cb.decl_map)
06ecf488 9842 f = *tcctx.cb.decl_map->get (f);
fd6481cf 9843 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9844 if (n != NULL)
9845 {
9846 sf = (tree) n->value;
9847 if (tcctx.cb.decl_map)
06ecf488 9848 sf = *tcctx.cb.decl_map->get (sf);
182cf5a9 9849 src = build_simple_mem_ref_loc (loc, sarg);
445d06b6 9850 src = omp_build_component_ref (src, sf);
fd6481cf 9851 if (use_pointer_for_field (decl, NULL) || is_reference (decl))
182cf5a9 9852 src = build_simple_mem_ref_loc (loc, src);
fd6481cf 9853 }
9854 else
9855 src = decl;
182cf5a9 9856 dst = build_simple_mem_ref_loc (loc, arg);
445d06b6 9857 dst = omp_build_component_ref (dst, f);
fd6481cf 9858 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
9859 append_to_statement_list (t, &list);
9860 break;
9861 case OMP_CLAUSE_PRIVATE:
9862 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c))
9863 break;
9864 decl = OMP_CLAUSE_DECL (c);
9865 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9866 f = (tree) n->value;
9867 if (tcctx.cb.decl_map)
06ecf488 9868 f = *tcctx.cb.decl_map->get (f);
fd6481cf 9869 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
9870 if (n != NULL)
9871 {
9872 sf = (tree) n->value;
9873 if (tcctx.cb.decl_map)
06ecf488 9874 sf = *tcctx.cb.decl_map->get (sf);
182cf5a9 9875 src = build_simple_mem_ref_loc (loc, sarg);
445d06b6 9876 src = omp_build_component_ref (src, sf);
fd6481cf 9877 if (use_pointer_for_field (decl, NULL))
182cf5a9 9878 src = build_simple_mem_ref_loc (loc, src);
fd6481cf 9879 }
9880 else
9881 src = decl;
182cf5a9 9882 dst = build_simple_mem_ref_loc (loc, arg);
445d06b6 9883 dst = omp_build_component_ref (dst, f);
75a70cf9 9884 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
fd6481cf 9885 append_to_statement_list (t, &list);
9886 break;
9887 default:
9888 break;
9889 }
9890
9891 /* Last pass: handle VLA firstprivates. */
9892 if (tcctx.cb.decl_map)
75a70cf9 9893 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
fd6481cf 9894 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
9895 {
9896 tree ind, ptr, df;
9897
9898 decl = OMP_CLAUSE_DECL (c);
9899 if (!is_variable_sized (decl))
9900 continue;
9901 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
9902 if (n == NULL)
9903 continue;
9904 f = (tree) n->value;
06ecf488 9905 f = *tcctx.cb.decl_map->get (f);
fd6481cf 9906 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
9907 ind = DECL_VALUE_EXPR (decl);
9908 gcc_assert (TREE_CODE (ind) == INDIRECT_REF);
9909 gcc_assert (DECL_P (TREE_OPERAND (ind, 0)));
9910 n = splay_tree_lookup (ctx->sfield_map,
9911 (splay_tree_key) TREE_OPERAND (ind, 0));
9912 sf = (tree) n->value;
06ecf488 9913 sf = *tcctx.cb.decl_map->get (sf);
182cf5a9 9914 src = build_simple_mem_ref_loc (loc, sarg);
445d06b6 9915 src = omp_build_component_ref (src, sf);
182cf5a9 9916 src = build_simple_mem_ref_loc (loc, src);
9917 dst = build_simple_mem_ref_loc (loc, arg);
445d06b6 9918 dst = omp_build_component_ref (dst, f);
fd6481cf 9919 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
9920 append_to_statement_list (t, &list);
9921 n = splay_tree_lookup (ctx->field_map,
9922 (splay_tree_key) TREE_OPERAND (ind, 0));
9923 df = (tree) n->value;
06ecf488 9924 df = *tcctx.cb.decl_map->get (df);
182cf5a9 9925 ptr = build_simple_mem_ref_loc (loc, arg);
445d06b6 9926 ptr = omp_build_component_ref (ptr, df);
75a70cf9 9927 t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
389dd41b 9928 build_fold_addr_expr_loc (loc, dst));
fd6481cf 9929 append_to_statement_list (t, &list);
9930 }
9931
9932 t = build1 (RETURN_EXPR, void_type_node, NULL);
9933 append_to_statement_list (t, &list);
9934
9935 if (tcctx.cb.decl_map)
06ecf488 9936 delete tcctx.cb.decl_map;
fd6481cf 9937 pop_gimplify_context (NULL);
9938 BIND_EXPR_BODY (bind) = list;
9939 pop_cfun ();
fd6481cf 9940}
9941
bc7bff74 9942static void
9943lower_depend_clauses (gimple stmt, gimple_seq *iseq, gimple_seq *oseq)
9944{
9945 tree c, clauses;
9946 gimple g;
9947 size_t n_in = 0, n_out = 0, idx = 2, i;
9948
9949 clauses = find_omp_clause (gimple_omp_task_clauses (stmt),
9950 OMP_CLAUSE_DEPEND);
9951 gcc_assert (clauses);
9952 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9953 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
9954 switch (OMP_CLAUSE_DEPEND_KIND (c))
9955 {
9956 case OMP_CLAUSE_DEPEND_IN:
9957 n_in++;
9958 break;
9959 case OMP_CLAUSE_DEPEND_OUT:
9960 case OMP_CLAUSE_DEPEND_INOUT:
9961 n_out++;
9962 break;
9963 default:
9964 gcc_unreachable ();
9965 }
9966 tree type = build_array_type_nelts (ptr_type_node, n_in + n_out + 2);
9967 tree array = create_tmp_var (type, NULL);
9968 tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
9969 NULL_TREE);
9970 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_in + n_out));
9971 gimple_seq_add_stmt (iseq, g);
9972 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
9973 NULL_TREE);
9974 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_out));
9975 gimple_seq_add_stmt (iseq, g);
9976 for (i = 0; i < 2; i++)
9977 {
9978 if ((i ? n_in : n_out) == 0)
9979 continue;
9980 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9981 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
9982 && ((OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_IN) ^ i))
9983 {
9984 tree t = OMP_CLAUSE_DECL (c);
9985 t = fold_convert (ptr_type_node, t);
9986 gimplify_expr (&t, iseq, NULL, is_gimple_val, fb_rvalue);
9987 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (idx++),
9988 NULL_TREE, NULL_TREE);
9989 g = gimple_build_assign (r, t);
9990 gimple_seq_add_stmt (iseq, g);
9991 }
9992 }
9993 tree *p = gimple_omp_task_clauses_ptr (stmt);
9994 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
9995 OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
9996 OMP_CLAUSE_CHAIN (c) = *p;
9997 *p = c;
9998 tree clobber = build_constructor (type, NULL);
9999 TREE_THIS_VOLATILE (clobber) = 1;
10000 g = gimple_build_assign (array, clobber);
10001 gimple_seq_add_stmt (oseq, g);
10002}
10003
75a70cf9 10004/* Lower the OpenMP parallel or task directive in the current statement
10005 in GSI_P. CTX holds context information for the directive. */
773c5ba7 10006
10007static void
75a70cf9 10008lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
773c5ba7 10009{
75a70cf9 10010 tree clauses;
10011 tree child_fn, t;
10012 gimple stmt = gsi_stmt (*gsi_p);
1a91d914 10013 gbind *par_bind, *bind, *dep_bind = NULL;
bc7bff74 10014 gimple_seq par_body, olist, ilist, par_olist, par_rlist, par_ilist, new_body;
389dd41b 10015 location_t loc = gimple_location (stmt);
773c5ba7 10016
75a70cf9 10017 clauses = gimple_omp_taskreg_clauses (stmt);
1a91d914 10018 par_bind
10019 = as_a <gbind *> (gimple_seq_first_stmt (gimple_omp_body (stmt)));
75a70cf9 10020 par_body = gimple_bind_body (par_bind);
773c5ba7 10021 child_fn = ctx->cb.dst_fn;
75a70cf9 10022 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
10023 && !gimple_omp_parallel_combined_p (stmt))
de7ef844 10024 {
10025 struct walk_stmt_info wi;
10026 int ws_num = 0;
10027
10028 memset (&wi, 0, sizeof (wi));
de7ef844 10029 wi.info = &ws_num;
10030 wi.val_only = true;
75a70cf9 10031 walk_gimple_seq (par_body, check_combined_parallel, NULL, &wi);
de7ef844 10032 if (ws_num == 1)
75a70cf9 10033 gimple_omp_parallel_set_combined_p (stmt, true);
de7ef844 10034 }
bc7bff74 10035 gimple_seq dep_ilist = NULL;
10036 gimple_seq dep_olist = NULL;
10037 if (gimple_code (stmt) == GIMPLE_OMP_TASK
10038 && find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
10039 {
8a4a28a8 10040 push_gimplify_context ();
bc7bff74 10041 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
10042 lower_depend_clauses (stmt, &dep_ilist, &dep_olist);
10043 }
10044
fd6481cf 10045 if (ctx->srecord_type)
1a91d914 10046 create_task_copyfn (as_a <gomp_task *> (stmt), ctx);
773c5ba7 10047
8a4a28a8 10048 push_gimplify_context ();
773c5ba7 10049
75a70cf9 10050 par_olist = NULL;
10051 par_ilist = NULL;
bc7bff74 10052 par_rlist = NULL;
10053 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx, NULL);
e3a19533 10054 lower_omp (&par_body, ctx);
75a70cf9 10055 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL)
bc7bff74 10056 lower_reduction_clauses (clauses, &par_rlist, ctx);
773c5ba7 10057
10058 /* Declare all the variables created by mapping and the variables
10059 declared in the scope of the parallel body. */
10060 record_vars_into (ctx->block_vars, child_fn);
75a70cf9 10061 record_vars_into (gimple_bind_vars (par_bind), child_fn);
773c5ba7 10062
10063 if (ctx->record_type)
10064 {
fd6481cf 10065 ctx->sender_decl
10066 = create_tmp_var (ctx->srecord_type ? ctx->srecord_type
10067 : ctx->record_type, ".omp_data_o");
84bfaaeb 10068 DECL_NAMELESS (ctx->sender_decl) = 1;
86f2ad37 10069 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
75a70cf9 10070 gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl);
773c5ba7 10071 }
10072
75a70cf9 10073 olist = NULL;
10074 ilist = NULL;
773c5ba7 10075 lower_send_clauses (clauses, &ilist, &olist, ctx);
10076 lower_send_shared_vars (&ilist, &olist, ctx);
10077
bc7bff74 10078 if (ctx->record_type)
10079 {
10080 tree clobber = build_constructor (TREE_TYPE (ctx->sender_decl), NULL);
10081 TREE_THIS_VOLATILE (clobber) = 1;
10082 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
10083 clobber));
10084 }
10085
773c5ba7 10086 /* Once all the expansions are done, sequence all the different
75a70cf9 10087 fragments inside gimple_omp_body. */
773c5ba7 10088
75a70cf9 10089 new_body = NULL;
773c5ba7 10090
10091 if (ctx->record_type)
10092 {
389dd41b 10093 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
cc6b725b 10094 /* fixup_child_record_type might have changed receiver_decl's type. */
389dd41b 10095 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
75a70cf9 10096 gimple_seq_add_stmt (&new_body,
10097 gimple_build_assign (ctx->receiver_decl, t));
773c5ba7 10098 }
10099
75a70cf9 10100 gimple_seq_add_seq (&new_body, par_ilist);
10101 gimple_seq_add_seq (&new_body, par_body);
bc7bff74 10102 gimple_seq_add_seq (&new_body, par_rlist);
10103 if (ctx->cancellable)
10104 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
75a70cf9 10105 gimple_seq_add_seq (&new_body, par_olist);
10106 new_body = maybe_catch_exception (new_body);
10107 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
10108 gimple_omp_set_body (stmt, new_body);
773c5ba7 10109
75a70cf9 10110 bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
bc7bff74 10111 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
10112 gimple_bind_add_seq (bind, ilist);
10113 gimple_bind_add_stmt (bind, stmt);
10114 gimple_bind_add_seq (bind, olist);
10115
10116 pop_gimplify_context (NULL);
10117
10118 if (dep_bind)
10119 {
10120 gimple_bind_add_seq (dep_bind, dep_ilist);
10121 gimple_bind_add_stmt (dep_bind, bind);
10122 gimple_bind_add_seq (dep_bind, dep_olist);
10123 pop_gimplify_context (dep_bind);
10124 }
10125}
10126
10127/* Lower the OpenMP target directive in the current statement
10128 in GSI_P. CTX holds context information for the directive. */
10129
10130static void
10131lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10132{
10133 tree clauses;
10134 tree child_fn, t, c;
1a91d914 10135 gomp_target *stmt = as_a <gomp_target *> (gsi_stmt (*gsi_p));
10136 gbind *tgt_bind = NULL, *bind;
bc7bff74 10137 gimple_seq tgt_body = NULL, olist, ilist, new_body;
bc7bff74 10138 location_t loc = gimple_location (stmt);
10139 int kind = gimple_omp_target_kind (stmt);
10140 unsigned int map_cnt = 0;
10141
10142 clauses = gimple_omp_target_clauses (stmt);
10143 if (kind == GF_OMP_TARGET_KIND_REGION)
10144 {
1a91d914 10145 tgt_bind = gimple_seq_first_stmt_as_a_bind (gimple_omp_body (stmt));
bc7bff74 10146 tgt_body = gimple_bind_body (tgt_bind);
10147 }
10148 else if (kind == GF_OMP_TARGET_KIND_DATA)
10149 tgt_body = gimple_omp_body (stmt);
10150 child_fn = ctx->cb.dst_fn;
10151
8a4a28a8 10152 push_gimplify_context ();
bc7bff74 10153
10154 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
10155 switch (OMP_CLAUSE_CODE (c))
10156 {
10157 tree var, x;
10158
10159 default:
10160 break;
10161 case OMP_CLAUSE_MAP:
10162 case OMP_CLAUSE_TO:
10163 case OMP_CLAUSE_FROM:
10164 var = OMP_CLAUSE_DECL (c);
10165 if (!DECL_P (var))
10166 {
10167 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
10168 || !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
10169 map_cnt++;
10170 continue;
10171 }
10172
10173 if (DECL_SIZE (var)
10174 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
10175 {
10176 tree var2 = DECL_VALUE_EXPR (var);
10177 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
10178 var2 = TREE_OPERAND (var2, 0);
10179 gcc_assert (DECL_P (var2));
10180 var = var2;
10181 }
10182
10183 if (!maybe_lookup_field (var, ctx))
10184 continue;
10185
10186 if (kind == GF_OMP_TARGET_KIND_REGION)
10187 {
10188 x = build_receiver_ref (var, true, ctx);
10189 tree new_var = lookup_decl (var, ctx);
10190 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
10191 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
10192 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
10193 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
10194 x = build_simple_mem_ref (x);
10195 SET_DECL_VALUE_EXPR (new_var, x);
10196 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
10197 }
10198 map_cnt++;
10199 }
10200
10201 if (kind == GF_OMP_TARGET_KIND_REGION)
10202 {
10203 target_nesting_level++;
10204 lower_omp (&tgt_body, ctx);
10205 target_nesting_level--;
10206 }
10207 else if (kind == GF_OMP_TARGET_KIND_DATA)
10208 lower_omp (&tgt_body, ctx);
10209
10210 if (kind == GF_OMP_TARGET_KIND_REGION)
10211 {
10212 /* Declare all the variables created by mapping and the variables
10213 declared in the scope of the target body. */
10214 record_vars_into (ctx->block_vars, child_fn);
10215 record_vars_into (gimple_bind_vars (tgt_bind), child_fn);
10216 }
10217
10218 olist = NULL;
10219 ilist = NULL;
10220 if (ctx->record_type)
10221 {
10222 ctx->sender_decl
10223 = create_tmp_var (ctx->record_type, ".omp_data_arr");
10224 DECL_NAMELESS (ctx->sender_decl) = 1;
10225 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
10226 t = make_tree_vec (3);
10227 TREE_VEC_ELT (t, 0) = ctx->sender_decl;
10228 TREE_VEC_ELT (t, 1)
10229 = create_tmp_var (build_array_type_nelts (size_type_node, map_cnt),
10230 ".omp_data_sizes");
10231 DECL_NAMELESS (TREE_VEC_ELT (t, 1)) = 1;
10232 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 1)) = 1;
10233 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 1;
10234 TREE_VEC_ELT (t, 2)
10235 = create_tmp_var (build_array_type_nelts (unsigned_char_type_node,
10236 map_cnt),
10237 ".omp_data_kinds");
10238 DECL_NAMELESS (TREE_VEC_ELT (t, 2)) = 1;
10239 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 2)) = 1;
10240 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 1;
10241 gimple_omp_target_set_data_arg (stmt, t);
10242
10243 vec<constructor_elt, va_gc> *vsize;
10244 vec<constructor_elt, va_gc> *vkind;
10245 vec_alloc (vsize, map_cnt);
10246 vec_alloc (vkind, map_cnt);
10247 unsigned int map_idx = 0;
10248
10249 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
10250 switch (OMP_CLAUSE_CODE (c))
10251 {
10252 tree ovar, nc;
10253
10254 default:
10255 break;
10256 case OMP_CLAUSE_MAP:
10257 case OMP_CLAUSE_TO:
10258 case OMP_CLAUSE_FROM:
10259 nc = c;
10260 ovar = OMP_CLAUSE_DECL (c);
10261 if (!DECL_P (ovar))
10262 {
10263 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
10264 && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
10265 {
10266 gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c))
10267 == get_base_address (ovar));
10268 nc = OMP_CLAUSE_CHAIN (c);
10269 ovar = OMP_CLAUSE_DECL (nc);
10270 }
10271 else
10272 {
10273 tree x = build_sender_ref (ovar, ctx);
10274 tree v
10275 = build_fold_addr_expr_with_type (ovar, ptr_type_node);
10276 gimplify_assign (x, v, &ilist);
10277 nc = NULL_TREE;
10278 }
10279 }
10280 else
10281 {
10282 if (DECL_SIZE (ovar)
10283 && TREE_CODE (DECL_SIZE (ovar)) != INTEGER_CST)
10284 {
10285 tree ovar2 = DECL_VALUE_EXPR (ovar);
10286 gcc_assert (TREE_CODE (ovar2) == INDIRECT_REF);
10287 ovar2 = TREE_OPERAND (ovar2, 0);
10288 gcc_assert (DECL_P (ovar2));
10289 ovar = ovar2;
10290 }
10291 if (!maybe_lookup_field (ovar, ctx))
10292 continue;
10293 }
10294
4f3b8d78 10295 unsigned int talign = TYPE_ALIGN_UNIT (TREE_TYPE (ovar));
10296 if (DECL_P (ovar) && DECL_ALIGN_UNIT (ovar) > talign)
10297 talign = DECL_ALIGN_UNIT (ovar);
bc7bff74 10298 if (nc)
10299 {
10300 tree var = lookup_decl_in_outer_ctx (ovar, ctx);
10301 tree x = build_sender_ref (ovar, ctx);
10302 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
10303 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
10304 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
10305 && TREE_CODE (TREE_TYPE (ovar)) == ARRAY_TYPE)
10306 {
10307 gcc_assert (kind == GF_OMP_TARGET_KIND_REGION);
10308 tree avar
10309 = create_tmp_var (TREE_TYPE (TREE_TYPE (x)), NULL);
10310 mark_addressable (avar);
10311 gimplify_assign (avar, build_fold_addr_expr (var), &ilist);
4f3b8d78 10312 talign = DECL_ALIGN_UNIT (avar);
bc7bff74 10313 avar = build_fold_addr_expr (avar);
10314 gimplify_assign (x, avar, &ilist);
10315 }
10316 else if (is_gimple_reg (var))
10317 {
10318 gcc_assert (kind == GF_OMP_TARGET_KIND_REGION);
10319 tree avar = create_tmp_var (TREE_TYPE (var), NULL);
10320 mark_addressable (avar);
10321 if (OMP_CLAUSE_MAP_KIND (c) != OMP_CLAUSE_MAP_ALLOC
10322 && OMP_CLAUSE_MAP_KIND (c) != OMP_CLAUSE_MAP_FROM)
10323 gimplify_assign (avar, var, &ilist);
10324 avar = build_fold_addr_expr (avar);
10325 gimplify_assign (x, avar, &ilist);
10326 if ((OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_FROM
10327 || OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_TOFROM)
10328 && !TYPE_READONLY (TREE_TYPE (var)))
10329 {
10330 x = build_sender_ref (ovar, ctx);
10331 x = build_simple_mem_ref (x);
10332 gimplify_assign (var, x, &olist);
10333 }
10334 }
10335 else
10336 {
10337 var = build_fold_addr_expr (var);
10338 gimplify_assign (x, var, &ilist);
10339 }
10340 }
10341 tree s = OMP_CLAUSE_SIZE (c);
10342 if (s == NULL_TREE)
10343 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
10344 s = fold_convert (size_type_node, s);
10345 tree purpose = size_int (map_idx++);
10346 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
10347 if (TREE_CODE (s) != INTEGER_CST)
10348 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
10349
10350 unsigned char tkind = 0;
10351 switch (OMP_CLAUSE_CODE (c))
10352 {
10353 case OMP_CLAUSE_MAP:
10354 tkind = OMP_CLAUSE_MAP_KIND (c);
10355 break;
10356 case OMP_CLAUSE_TO:
10357 tkind = OMP_CLAUSE_MAP_TO;
10358 break;
10359 case OMP_CLAUSE_FROM:
10360 tkind = OMP_CLAUSE_MAP_FROM;
10361 break;
10362 default:
10363 gcc_unreachable ();
10364 }
bc7bff74 10365 talign = ceil_log2 (talign);
10366 tkind |= talign << 3;
10367 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
10368 build_int_cst (unsigned_char_type_node,
10369 tkind));
10370 if (nc && nc != c)
10371 c = nc;
10372 }
10373
10374 gcc_assert (map_idx == map_cnt);
10375
10376 DECL_INITIAL (TREE_VEC_ELT (t, 1))
10377 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)), vsize);
10378 DECL_INITIAL (TREE_VEC_ELT (t, 2))
10379 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 2)), vkind);
10380 if (!TREE_STATIC (TREE_VEC_ELT (t, 1)))
10381 {
10382 gimple_seq initlist = NULL;
10383 force_gimple_operand (build1 (DECL_EXPR, void_type_node,
10384 TREE_VEC_ELT (t, 1)),
10385 &initlist, true, NULL_TREE);
10386 gimple_seq_add_seq (&ilist, initlist);
d8e1e68d 10387
10388 tree clobber = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)),
10389 NULL);
10390 TREE_THIS_VOLATILE (clobber) = 1;
10391 gimple_seq_add_stmt (&olist,
10392 gimple_build_assign (TREE_VEC_ELT (t, 1),
10393 clobber));
bc7bff74 10394 }
10395
10396 tree clobber = build_constructor (ctx->record_type, NULL);
10397 TREE_THIS_VOLATILE (clobber) = 1;
10398 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
10399 clobber));
10400 }
10401
10402 /* Once all the expansions are done, sequence all the different
10403 fragments inside gimple_omp_body. */
10404
10405 new_body = NULL;
10406
10407 if (ctx->record_type && kind == GF_OMP_TARGET_KIND_REGION)
10408 {
10409 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
10410 /* fixup_child_record_type might have changed receiver_decl's type. */
10411 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
10412 gimple_seq_add_stmt (&new_body,
10413 gimple_build_assign (ctx->receiver_decl, t));
10414 }
10415
10416 if (kind == GF_OMP_TARGET_KIND_REGION)
10417 {
10418 gimple_seq_add_seq (&new_body, tgt_body);
10419 new_body = maybe_catch_exception (new_body);
10420 }
10421 else if (kind == GF_OMP_TARGET_KIND_DATA)
10422 new_body = tgt_body;
10423 if (kind != GF_OMP_TARGET_KIND_UPDATE)
10424 {
10425 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
10426 gimple_omp_set_body (stmt, new_body);
10427 }
10428
10429 bind = gimple_build_bind (NULL, NULL,
10430 tgt_bind ? gimple_bind_block (tgt_bind)
10431 : NULL_TREE);
75a70cf9 10432 gsi_replace (gsi_p, bind, true);
e3a19533 10433 gimple_bind_add_seq (bind, ilist);
10434 gimple_bind_add_stmt (bind, stmt);
10435 gimple_bind_add_seq (bind, olist);
773c5ba7 10436
75a70cf9 10437 pop_gimplify_context (NULL);
773c5ba7 10438}
10439
bc7bff74 10440/* Expand code for an OpenMP teams directive. */
10441
10442static void
10443lower_omp_teams (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10444{
1a91d914 10445 gomp_teams *teams_stmt = as_a <gomp_teams *> (gsi_stmt (*gsi_p));
8a4a28a8 10446 push_gimplify_context ();
bc7bff74 10447
10448 tree block = make_node (BLOCK);
1a91d914 10449 gbind *bind = gimple_build_bind (NULL, NULL, block);
bc7bff74 10450 gsi_replace (gsi_p, bind, true);
10451 gimple_seq bind_body = NULL;
10452 gimple_seq dlist = NULL;
10453 gimple_seq olist = NULL;
10454
10455 tree num_teams = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
10456 OMP_CLAUSE_NUM_TEAMS);
10457 if (num_teams == NULL_TREE)
10458 num_teams = build_int_cst (unsigned_type_node, 0);
10459 else
10460 {
10461 num_teams = OMP_CLAUSE_NUM_TEAMS_EXPR (num_teams);
10462 num_teams = fold_convert (unsigned_type_node, num_teams);
10463 gimplify_expr (&num_teams, &bind_body, NULL, is_gimple_val, fb_rvalue);
10464 }
10465 tree thread_limit = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
10466 OMP_CLAUSE_THREAD_LIMIT);
10467 if (thread_limit == NULL_TREE)
10468 thread_limit = build_int_cst (unsigned_type_node, 0);
10469 else
10470 {
10471 thread_limit = OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit);
10472 thread_limit = fold_convert (unsigned_type_node, thread_limit);
10473 gimplify_expr (&thread_limit, &bind_body, NULL, is_gimple_val,
10474 fb_rvalue);
10475 }
10476
10477 lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt),
10478 &bind_body, &dlist, ctx, NULL);
10479 lower_omp (gimple_omp_body_ptr (teams_stmt), ctx);
10480 lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt), &olist, ctx);
10481 gimple_seq_add_stmt (&bind_body, teams_stmt);
10482
10483 location_t loc = gimple_location (teams_stmt);
10484 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TEAMS);
10485 gimple call = gimple_build_call (decl, 2, num_teams, thread_limit);
10486 gimple_set_location (call, loc);
10487 gimple_seq_add_stmt (&bind_body, call);
10488
10489 gimple_seq_add_seq (&bind_body, gimple_omp_body (teams_stmt));
10490 gimple_omp_set_body (teams_stmt, NULL);
10491 gimple_seq_add_seq (&bind_body, olist);
10492 gimple_seq_add_seq (&bind_body, dlist);
10493 gimple_seq_add_stmt (&bind_body, gimple_build_omp_return (true));
10494 gimple_bind_set_body (bind, bind_body);
10495
10496 pop_gimplify_context (bind);
10497
10498 gimple_bind_append_vars (bind, ctx->block_vars);
10499 BLOCK_VARS (block) = ctx->block_vars;
10500 if (BLOCK_VARS (block))
10501 TREE_USED (block) = 1;
10502}
10503
10504
a4890dc9 10505/* Callback for lower_omp_1. Return non-NULL if *tp needs to be
75a70cf9 10506 regimplified. If DATA is non-NULL, lower_omp_1 is outside
10507 of OpenMP context, but with task_shared_vars set. */
46515c92 10508
10509static tree
75a70cf9 10510lower_omp_regimplify_p (tree *tp, int *walk_subtrees,
10511 void *data)
46515c92 10512{
a4890dc9 10513 tree t = *tp;
46515c92 10514
a4890dc9 10515 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
75a70cf9 10516 if (TREE_CODE (t) == VAR_DECL && data == NULL && DECL_HAS_VALUE_EXPR_P (t))
9f49e155 10517 return t;
10518
10519 if (task_shared_vars
10520 && DECL_P (t)
10521 && bitmap_bit_p (task_shared_vars, DECL_UID (t)))
a4890dc9 10522 return t;
46515c92 10523
a4890dc9 10524 /* If a global variable has been privatized, TREE_CONSTANT on
10525 ADDR_EXPR might be wrong. */
75a70cf9 10526 if (data == NULL && TREE_CODE (t) == ADDR_EXPR)
a4890dc9 10527 recompute_tree_invariant_for_addr_expr (t);
46515c92 10528
a4890dc9 10529 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
10530 return NULL_TREE;
46515c92 10531}
773c5ba7 10532
a4890dc9 10533static void
75a70cf9 10534lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
1e8e9920 10535{
75a70cf9 10536 gimple stmt = gsi_stmt (*gsi_p);
10537 struct walk_stmt_info wi;
1a91d914 10538 gcall *call_stmt;
1e8e9920 10539
75a70cf9 10540 if (gimple_has_location (stmt))
10541 input_location = gimple_location (stmt);
a4890dc9 10542
75a70cf9 10543 if (task_shared_vars)
10544 memset (&wi, '\0', sizeof (wi));
a4890dc9 10545
773c5ba7 10546 /* If we have issued syntax errors, avoid doing any heavy lifting.
10547 Just replace the OpenMP directives with a NOP to avoid
10548 confusing RTL expansion. */
852f689e 10549 if (seen_error () && is_gimple_omp (stmt))
773c5ba7 10550 {
75a70cf9 10551 gsi_replace (gsi_p, gimple_build_nop (), true);
a4890dc9 10552 return;
773c5ba7 10553 }
10554
75a70cf9 10555 switch (gimple_code (stmt))
1e8e9920 10556 {
75a70cf9 10557 case GIMPLE_COND:
1a91d914 10558 {
10559 gcond *cond_stmt = as_a <gcond *> (stmt);
10560 if ((ctx || task_shared_vars)
10561 && (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
10562 lower_omp_regimplify_p,
10563 ctx ? NULL : &wi, NULL)
10564 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
10565 lower_omp_regimplify_p,
10566 ctx ? NULL : &wi, NULL)))
10567 gimple_regimplify_operands (cond_stmt, gsi_p);
10568 }
a4890dc9 10569 break;
75a70cf9 10570 case GIMPLE_CATCH:
1a91d914 10571 lower_omp (gimple_catch_handler_ptr (as_a <gcatch *> (stmt)), ctx);
a4890dc9 10572 break;
75a70cf9 10573 case GIMPLE_EH_FILTER:
e3a19533 10574 lower_omp (gimple_eh_filter_failure_ptr (stmt), ctx);
a4890dc9 10575 break;
75a70cf9 10576 case GIMPLE_TRY:
e3a19533 10577 lower_omp (gimple_try_eval_ptr (stmt), ctx);
10578 lower_omp (gimple_try_cleanup_ptr (stmt), ctx);
a4890dc9 10579 break;
35215227 10580 case GIMPLE_TRANSACTION:
1a91d914 10581 lower_omp (gimple_transaction_body_ptr (
10582 as_a <gtransaction *> (stmt)),
10583 ctx);
35215227 10584 break;
75a70cf9 10585 case GIMPLE_BIND:
1a91d914 10586 lower_omp (gimple_bind_body_ptr (as_a <gbind *> (stmt)), ctx);
a4890dc9 10587 break;
75a70cf9 10588 case GIMPLE_OMP_PARALLEL:
10589 case GIMPLE_OMP_TASK:
10590 ctx = maybe_lookup_ctx (stmt);
bc7bff74 10591 gcc_assert (ctx);
10592 if (ctx->cancellable)
10593 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
75a70cf9 10594 lower_omp_taskreg (gsi_p, ctx);
a4890dc9 10595 break;
75a70cf9 10596 case GIMPLE_OMP_FOR:
10597 ctx = maybe_lookup_ctx (stmt);
1e8e9920 10598 gcc_assert (ctx);
bc7bff74 10599 if (ctx->cancellable)
10600 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
75a70cf9 10601 lower_omp_for (gsi_p, ctx);
1e8e9920 10602 break;
75a70cf9 10603 case GIMPLE_OMP_SECTIONS:
10604 ctx = maybe_lookup_ctx (stmt);
1e8e9920 10605 gcc_assert (ctx);
bc7bff74 10606 if (ctx->cancellable)
10607 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
75a70cf9 10608 lower_omp_sections (gsi_p, ctx);
1e8e9920 10609 break;
75a70cf9 10610 case GIMPLE_OMP_SINGLE:
10611 ctx = maybe_lookup_ctx (stmt);
1e8e9920 10612 gcc_assert (ctx);
75a70cf9 10613 lower_omp_single (gsi_p, ctx);
1e8e9920 10614 break;
75a70cf9 10615 case GIMPLE_OMP_MASTER:
10616 ctx = maybe_lookup_ctx (stmt);
1e8e9920 10617 gcc_assert (ctx);
75a70cf9 10618 lower_omp_master (gsi_p, ctx);
1e8e9920 10619 break;
bc7bff74 10620 case GIMPLE_OMP_TASKGROUP:
10621 ctx = maybe_lookup_ctx (stmt);
10622 gcc_assert (ctx);
10623 lower_omp_taskgroup (gsi_p, ctx);
10624 break;
75a70cf9 10625 case GIMPLE_OMP_ORDERED:
10626 ctx = maybe_lookup_ctx (stmt);
1e8e9920 10627 gcc_assert (ctx);
75a70cf9 10628 lower_omp_ordered (gsi_p, ctx);
1e8e9920 10629 break;
75a70cf9 10630 case GIMPLE_OMP_CRITICAL:
10631 ctx = maybe_lookup_ctx (stmt);
1e8e9920 10632 gcc_assert (ctx);
75a70cf9 10633 lower_omp_critical (gsi_p, ctx);
10634 break;
10635 case GIMPLE_OMP_ATOMIC_LOAD:
10636 if ((ctx || task_shared_vars)
1a91d914 10637 && walk_tree (gimple_omp_atomic_load_rhs_ptr (
10638 as_a <gomp_atomic_load *> (stmt)),
75a70cf9 10639 lower_omp_regimplify_p, ctx ? NULL : &wi, NULL))
10640 gimple_regimplify_operands (stmt, gsi_p);
1e8e9920 10641 break;
bc7bff74 10642 case GIMPLE_OMP_TARGET:
10643 ctx = maybe_lookup_ctx (stmt);
10644 gcc_assert (ctx);
10645 lower_omp_target (gsi_p, ctx);
10646 break;
10647 case GIMPLE_OMP_TEAMS:
10648 ctx = maybe_lookup_ctx (stmt);
10649 gcc_assert (ctx);
10650 lower_omp_teams (gsi_p, ctx);
10651 break;
10652 case GIMPLE_CALL:
10653 tree fndecl;
1a91d914 10654 call_stmt = as_a <gcall *> (stmt);
10655 fndecl = gimple_call_fndecl (call_stmt);
bc7bff74 10656 if (fndecl
10657 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
10658 switch (DECL_FUNCTION_CODE (fndecl))
10659 {
10660 case BUILT_IN_GOMP_BARRIER:
10661 if (ctx == NULL)
10662 break;
10663 /* FALLTHRU */
10664 case BUILT_IN_GOMP_CANCEL:
10665 case BUILT_IN_GOMP_CANCELLATION_POINT:
10666 omp_context *cctx;
10667 cctx = ctx;
10668 if (gimple_code (cctx->stmt) == GIMPLE_OMP_SECTION)
10669 cctx = cctx->outer;
1a91d914 10670 gcc_assert (gimple_call_lhs (call_stmt) == NULL_TREE);
bc7bff74 10671 if (!cctx->cancellable)
10672 {
10673 if (DECL_FUNCTION_CODE (fndecl)
10674 == BUILT_IN_GOMP_CANCELLATION_POINT)
10675 {
10676 stmt = gimple_build_nop ();
10677 gsi_replace (gsi_p, stmt, false);
10678 }
10679 break;
10680 }
bc7bff74 10681 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
10682 {
10683 fndecl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL);
1a91d914 10684 gimple_call_set_fndecl (call_stmt, fndecl);
10685 gimple_call_set_fntype (call_stmt, TREE_TYPE (fndecl));
bc7bff74 10686 }
15b28553 10687 tree lhs;
10688 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (fndecl)), NULL);
1a91d914 10689 gimple_call_set_lhs (call_stmt, lhs);
bc7bff74 10690 tree fallthru_label;
10691 fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
10692 gimple g;
10693 g = gimple_build_label (fallthru_label);
10694 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
15b28553 10695 g = gimple_build_cond (NE_EXPR, lhs,
10696 fold_convert (TREE_TYPE (lhs),
10697 boolean_false_node),
bc7bff74 10698 cctx->cancel_label, fallthru_label);
10699 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
10700 break;
10701 default:
10702 break;
10703 }
10704 /* FALLTHRU */
a4890dc9 10705 default:
fd6481cf 10706 if ((ctx || task_shared_vars)
75a70cf9 10707 && walk_gimple_op (stmt, lower_omp_regimplify_p,
10708 ctx ? NULL : &wi))
ef8cfd4d 10709 {
10710 /* Just remove clobbers, this should happen only if we have
10711 "privatized" local addressable variables in SIMD regions,
10712 the clobber isn't needed in that case and gimplifying address
10713 of the ARRAY_REF into a pointer and creating MEM_REF based
10714 clobber would create worse code than we get with the clobber
10715 dropped. */
10716 if (gimple_clobber_p (stmt))
10717 {
10718 gsi_replace (gsi_p, gimple_build_nop (), true);
10719 break;
10720 }
10721 gimple_regimplify_operands (stmt, gsi_p);
10722 }
1e8e9920 10723 break;
1e8e9920 10724 }
1e8e9920 10725}
10726
10727static void
e3a19533 10728lower_omp (gimple_seq *body, omp_context *ctx)
1e8e9920 10729{
1d22f541 10730 location_t saved_location = input_location;
e3a19533 10731 gimple_stmt_iterator gsi;
10732 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
75a70cf9 10733 lower_omp_1 (&gsi, ctx);
c09f306d 10734 /* During gimplification, we have not always invoked fold_stmt
10735 (gimplify.c:maybe_fold_stmt); call it now. */
bc7bff74 10736 if (target_nesting_level)
10737 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
10738 fold_stmt (&gsi);
1d22f541 10739 input_location = saved_location;
1e8e9920 10740}
10741\f
10742/* Main entry point. */
10743
2a1990e9 10744static unsigned int
1e8e9920 10745execute_lower_omp (void)
10746{
75a70cf9 10747 gimple_seq body;
37eaded9 10748 int i;
10749 omp_context *ctx;
75a70cf9 10750
41709826 10751 /* This pass always runs, to provide PROP_gimple_lomp.
10752 But there is nothing to do unless -fopenmp is given. */
a89e6c15 10753 if (flag_openmp == 0 && flag_openmp_simd == 0 && flag_cilkplus == 0)
41709826 10754 return 0;
10755
1e8e9920 10756 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
10757 delete_omp_context);
10758
75a70cf9 10759 body = gimple_body (current_function_decl);
ab129075 10760 scan_omp (&body, NULL);
fd6481cf 10761 gcc_assert (taskreg_nesting_level == 0);
37eaded9 10762 FOR_EACH_VEC_ELT (taskreg_contexts, i, ctx)
10763 finish_taskreg_scan (ctx);
10764 taskreg_contexts.release ();
1e8e9920 10765
10766 if (all_contexts->root)
fd6481cf 10767 {
10768 if (task_shared_vars)
8a4a28a8 10769 push_gimplify_context ();
e3a19533 10770 lower_omp (&body, NULL);
fd6481cf 10771 if (task_shared_vars)
10772 pop_gimplify_context (NULL);
10773 }
1e8e9920 10774
773c5ba7 10775 if (all_contexts)
10776 {
10777 splay_tree_delete (all_contexts);
10778 all_contexts = NULL;
10779 }
fd6481cf 10780 BITMAP_FREE (task_shared_vars);
2a1990e9 10781 return 0;
1e8e9920 10782}
10783
cbe8bda8 10784namespace {
10785
10786const pass_data pass_data_lower_omp =
10787{
10788 GIMPLE_PASS, /* type */
10789 "omplower", /* name */
10790 OPTGROUP_NONE, /* optinfo_flags */
cbe8bda8 10791 TV_NONE, /* tv_id */
10792 PROP_gimple_any, /* properties_required */
10793 PROP_gimple_lomp, /* properties_provided */
10794 0, /* properties_destroyed */
10795 0, /* todo_flags_start */
10796 0, /* todo_flags_finish */
1e8e9920 10797};
cbe8bda8 10798
10799class pass_lower_omp : public gimple_opt_pass
10800{
10801public:
9af5ce0c 10802 pass_lower_omp (gcc::context *ctxt)
10803 : gimple_opt_pass (pass_data_lower_omp, ctxt)
cbe8bda8 10804 {}
10805
10806 /* opt_pass methods: */
65b0537f 10807 virtual unsigned int execute (function *) { return execute_lower_omp (); }
cbe8bda8 10808
10809}; // class pass_lower_omp
10810
10811} // anon namespace
10812
10813gimple_opt_pass *
10814make_pass_lower_omp (gcc::context *ctxt)
10815{
10816 return new pass_lower_omp (ctxt);
10817}
1e8e9920 10818\f
10819/* The following is a utility to diagnose OpenMP structured block violations.
61e47ac8 10820 It is not part of the "omplower" pass, as that's invoked too late. It
10821 should be invoked by the respective front ends after gimplification. */
1e8e9920 10822
10823static splay_tree all_labels;
10824
10825/* Check for mismatched contexts and generate an error if needed. Return
10826 true if an error is detected. */
10827
10828static bool
75a70cf9 10829diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
10830 gimple branch_ctx, gimple label_ctx)
1e8e9920 10831{
75a70cf9 10832 if (label_ctx == branch_ctx)
1e8e9920 10833 return false;
10834
48e1416a 10835
75a70cf9 10836 /*
10837 Previously we kept track of the label's entire context in diagnose_sb_[12]
10838 so we could traverse it and issue a correct "exit" or "enter" error
10839 message upon a structured block violation.
10840
10841 We built the context by building a list with tree_cons'ing, but there is
10842 no easy counterpart in gimple tuples. It seems like far too much work
10843 for issuing exit/enter error messages. If someone really misses the
10844 distinct error message... patches welcome.
10845 */
48e1416a 10846
75a70cf9 10847#if 0
1e8e9920 10848 /* Try to avoid confusing the user by producing and error message
f0b5f617 10849 with correct "exit" or "enter" verbiage. We prefer "exit"
1e8e9920 10850 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
10851 if (branch_ctx == NULL)
10852 exit_p = false;
10853 else
10854 {
10855 while (label_ctx)
10856 {
10857 if (TREE_VALUE (label_ctx) == branch_ctx)
10858 {
10859 exit_p = false;
10860 break;
10861 }
10862 label_ctx = TREE_CHAIN (label_ctx);
10863 }
10864 }
10865
10866 if (exit_p)
10867 error ("invalid exit from OpenMP structured block");
10868 else
10869 error ("invalid entry to OpenMP structured block");
75a70cf9 10870#endif
1e8e9920 10871
f2697631 10872 bool cilkplus_block = false;
a89e6c15 10873 if (flag_cilkplus)
f2697631 10874 {
10875 if ((branch_ctx
10876 && gimple_code (branch_ctx) == GIMPLE_OMP_FOR
10877 && gimple_omp_for_kind (branch_ctx) == GF_OMP_FOR_KIND_CILKSIMD)
a4eb3f73 10878 || (label_ctx
10879 && gimple_code (label_ctx) == GIMPLE_OMP_FOR
f2697631 10880 && gimple_omp_for_kind (label_ctx) == GF_OMP_FOR_KIND_CILKSIMD))
10881 cilkplus_block = true;
10882 }
10883
75a70cf9 10884 /* If it's obvious we have an invalid entry, be specific about the error. */
10885 if (branch_ctx == NULL)
f2697631 10886 {
10887 if (cilkplus_block)
10888 error ("invalid entry to Cilk Plus structured block");
10889 else
10890 error ("invalid entry to OpenMP structured block");
10891 }
75a70cf9 10892 else
f2697631 10893 {
10894 /* Otherwise, be vague and lazy, but efficient. */
10895 if (cilkplus_block)
10896 error ("invalid branch to/from a Cilk Plus structured block");
10897 else
10898 error ("invalid branch to/from an OpenMP structured block");
10899 }
75a70cf9 10900
10901 gsi_replace (gsi_p, gimple_build_nop (), false);
1e8e9920 10902 return true;
10903}
10904
10905/* Pass 1: Create a minimal tree of OpenMP structured blocks, and record
75a70cf9 10906 where each label is found. */
1e8e9920 10907
10908static tree
75a70cf9 10909diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
10910 struct walk_stmt_info *wi)
1e8e9920 10911{
75a70cf9 10912 gimple context = (gimple) wi->info;
10913 gimple inner_context;
10914 gimple stmt = gsi_stmt (*gsi_p);
1e8e9920 10915
75a70cf9 10916 *handled_ops_p = true;
10917
10918 switch (gimple_code (stmt))
1e8e9920 10919 {
75a70cf9 10920 WALK_SUBSTMTS;
48e1416a 10921
75a70cf9 10922 case GIMPLE_OMP_PARALLEL:
10923 case GIMPLE_OMP_TASK:
10924 case GIMPLE_OMP_SECTIONS:
10925 case GIMPLE_OMP_SINGLE:
10926 case GIMPLE_OMP_SECTION:
10927 case GIMPLE_OMP_MASTER:
10928 case GIMPLE_OMP_ORDERED:
10929 case GIMPLE_OMP_CRITICAL:
bc7bff74 10930 case GIMPLE_OMP_TARGET:
10931 case GIMPLE_OMP_TEAMS:
10932 case GIMPLE_OMP_TASKGROUP:
75a70cf9 10933 /* The minimal context here is just the current OMP construct. */
10934 inner_context = stmt;
1e8e9920 10935 wi->info = inner_context;
75a70cf9 10936 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
1e8e9920 10937 wi->info = context;
10938 break;
10939
75a70cf9 10940 case GIMPLE_OMP_FOR:
10941 inner_context = stmt;
1e8e9920 10942 wi->info = inner_context;
75a70cf9 10943 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
10944 walk them. */
10945 walk_gimple_seq (gimple_omp_for_pre_body (stmt),
10946 diagnose_sb_1, NULL, wi);
10947 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
1e8e9920 10948 wi->info = context;
10949 break;
10950
75a70cf9 10951 case GIMPLE_LABEL:
1a91d914 10952 splay_tree_insert (all_labels,
10953 (splay_tree_key) gimple_label_label (
10954 as_a <glabel *> (stmt)),
1e8e9920 10955 (splay_tree_value) context);
10956 break;
10957
10958 default:
10959 break;
10960 }
10961
10962 return NULL_TREE;
10963}
10964
10965/* Pass 2: Check each branch and see if its context differs from that of
10966 the destination label's context. */
10967
10968static tree
75a70cf9 10969diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
10970 struct walk_stmt_info *wi)
1e8e9920 10971{
75a70cf9 10972 gimple context = (gimple) wi->info;
1e8e9920 10973 splay_tree_node n;
75a70cf9 10974 gimple stmt = gsi_stmt (*gsi_p);
1e8e9920 10975
75a70cf9 10976 *handled_ops_p = true;
10977
10978 switch (gimple_code (stmt))
1e8e9920 10979 {
75a70cf9 10980 WALK_SUBSTMTS;
10981
10982 case GIMPLE_OMP_PARALLEL:
10983 case GIMPLE_OMP_TASK:
10984 case GIMPLE_OMP_SECTIONS:
10985 case GIMPLE_OMP_SINGLE:
10986 case GIMPLE_OMP_SECTION:
10987 case GIMPLE_OMP_MASTER:
10988 case GIMPLE_OMP_ORDERED:
10989 case GIMPLE_OMP_CRITICAL:
bc7bff74 10990 case GIMPLE_OMP_TARGET:
10991 case GIMPLE_OMP_TEAMS:
10992 case GIMPLE_OMP_TASKGROUP:
75a70cf9 10993 wi->info = stmt;
e3a19533 10994 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
1e8e9920 10995 wi->info = context;
10996 break;
10997
75a70cf9 10998 case GIMPLE_OMP_FOR:
10999 wi->info = stmt;
11000 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
11001 walk them. */
e3a19533 11002 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt),
11003 diagnose_sb_2, NULL, wi);
11004 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
1e8e9920 11005 wi->info = context;
11006 break;
11007
0e1818e7 11008 case GIMPLE_COND:
11009 {
1a91d914 11010 gcond *cond_stmt = as_a <gcond *> (stmt);
11011 tree lab = gimple_cond_true_label (cond_stmt);
0e1818e7 11012 if (lab)
11013 {
11014 n = splay_tree_lookup (all_labels,
11015 (splay_tree_key) lab);
11016 diagnose_sb_0 (gsi_p, context,
11017 n ? (gimple) n->value : NULL);
11018 }
1a91d914 11019 lab = gimple_cond_false_label (cond_stmt);
0e1818e7 11020 if (lab)
11021 {
11022 n = splay_tree_lookup (all_labels,
11023 (splay_tree_key) lab);
11024 diagnose_sb_0 (gsi_p, context,
11025 n ? (gimple) n->value : NULL);
11026 }
11027 }
11028 break;
11029
75a70cf9 11030 case GIMPLE_GOTO:
1e8e9920 11031 {
75a70cf9 11032 tree lab = gimple_goto_dest (stmt);
1e8e9920 11033 if (TREE_CODE (lab) != LABEL_DECL)
11034 break;
11035
11036 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
75a70cf9 11037 diagnose_sb_0 (gsi_p, context, n ? (gimple) n->value : NULL);
1e8e9920 11038 }
11039 break;
11040
75a70cf9 11041 case GIMPLE_SWITCH:
1e8e9920 11042 {
1a91d914 11043 gswitch *switch_stmt = as_a <gswitch *> (stmt);
75a70cf9 11044 unsigned int i;
1a91d914 11045 for (i = 0; i < gimple_switch_num_labels (switch_stmt); ++i)
1e8e9920 11046 {
1a91d914 11047 tree lab = CASE_LABEL (gimple_switch_label (switch_stmt, i));
1e8e9920 11048 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
75a70cf9 11049 if (n && diagnose_sb_0 (gsi_p, context, (gimple) n->value))
1e8e9920 11050 break;
11051 }
11052 }
11053 break;
11054
75a70cf9 11055 case GIMPLE_RETURN:
11056 diagnose_sb_0 (gsi_p, context, NULL);
1e8e9920 11057 break;
11058
11059 default:
11060 break;
11061 }
11062
11063 return NULL_TREE;
11064}
11065
7740abd8 11066/* Called from tree-cfg.c::make_edges to create cfg edges for all GIMPLE_OMP
11067 codes. */
11068bool
b2c0e0b7 11069make_gimple_omp_edges (basic_block bb, struct omp_region **region,
11070 int *region_idx)
7740abd8 11071{
11072 gimple last = last_stmt (bb);
11073 enum gimple_code code = gimple_code (last);
11074 struct omp_region *cur_region = *region;
11075 bool fallthru = false;
11076
11077 switch (code)
11078 {
11079 case GIMPLE_OMP_PARALLEL:
11080 case GIMPLE_OMP_TASK:
11081 case GIMPLE_OMP_FOR:
11082 case GIMPLE_OMP_SINGLE:
11083 case GIMPLE_OMP_TEAMS:
11084 case GIMPLE_OMP_MASTER:
11085 case GIMPLE_OMP_TASKGROUP:
11086 case GIMPLE_OMP_ORDERED:
11087 case GIMPLE_OMP_CRITICAL:
11088 case GIMPLE_OMP_SECTION:
11089 cur_region = new_omp_region (bb, code, cur_region);
11090 fallthru = true;
11091 break;
11092
11093 case GIMPLE_OMP_TARGET:
11094 cur_region = new_omp_region (bb, code, cur_region);
11095 fallthru = true;
11096 if (gimple_omp_target_kind (last) == GF_OMP_TARGET_KIND_UPDATE)
11097 cur_region = cur_region->outer;
11098 break;
11099
11100 case GIMPLE_OMP_SECTIONS:
11101 cur_region = new_omp_region (bb, code, cur_region);
11102 fallthru = true;
11103 break;
11104
11105 case GIMPLE_OMP_SECTIONS_SWITCH:
11106 fallthru = false;
11107 break;
11108
11109 case GIMPLE_OMP_ATOMIC_LOAD:
11110 case GIMPLE_OMP_ATOMIC_STORE:
11111 fallthru = true;
11112 break;
11113
11114 case GIMPLE_OMP_RETURN:
11115 /* In the case of a GIMPLE_OMP_SECTION, the edge will go
11116 somewhere other than the next block. This will be
11117 created later. */
11118 cur_region->exit = bb;
11119 fallthru = cur_region->type != GIMPLE_OMP_SECTION;
11120 cur_region = cur_region->outer;
11121 break;
11122
11123 case GIMPLE_OMP_CONTINUE:
11124 cur_region->cont = bb;
11125 switch (cur_region->type)
11126 {
11127 case GIMPLE_OMP_FOR:
11128 /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
11129 succs edges as abnormal to prevent splitting
11130 them. */
11131 single_succ_edge (cur_region->entry)->flags |= EDGE_ABNORMAL;
11132 /* Make the loopback edge. */
11133 make_edge (bb, single_succ (cur_region->entry),
11134 EDGE_ABNORMAL);
11135
11136 /* Create an edge from GIMPLE_OMP_FOR to exit, which
11137 corresponds to the case that the body of the loop
11138 is not executed at all. */
11139 make_edge (cur_region->entry, bb->next_bb, EDGE_ABNORMAL);
11140 make_edge (bb, bb->next_bb, EDGE_FALLTHRU | EDGE_ABNORMAL);
11141 fallthru = false;
11142 break;
11143
11144 case GIMPLE_OMP_SECTIONS:
11145 /* Wire up the edges into and out of the nested sections. */
11146 {
11147 basic_block switch_bb = single_succ (cur_region->entry);
11148
11149 struct omp_region *i;
11150 for (i = cur_region->inner; i ; i = i->next)
11151 {
11152 gcc_assert (i->type == GIMPLE_OMP_SECTION);
11153 make_edge (switch_bb, i->entry, 0);
11154 make_edge (i->exit, bb, EDGE_FALLTHRU);
11155 }
11156
11157 /* Make the loopback edge to the block with
11158 GIMPLE_OMP_SECTIONS_SWITCH. */
11159 make_edge (bb, switch_bb, 0);
11160
11161 /* Make the edge from the switch to exit. */
11162 make_edge (switch_bb, bb->next_bb, 0);
11163 fallthru = false;
11164 }
11165 break;
11166
11167 default:
11168 gcc_unreachable ();
11169 }
11170 break;
11171
11172 default:
11173 gcc_unreachable ();
11174 }
11175
11176 if (*region != cur_region)
b2c0e0b7 11177 {
11178 *region = cur_region;
11179 if (cur_region)
11180 *region_idx = cur_region->entry->index;
11181 else
11182 *region_idx = 0;
11183 }
7740abd8 11184
11185 return fallthru;
11186}
11187
bfec3452 11188static unsigned int
11189diagnose_omp_structured_block_errors (void)
1e8e9920 11190{
1e8e9920 11191 struct walk_stmt_info wi;
bfec3452 11192 gimple_seq body = gimple_body (current_function_decl);
1e8e9920 11193
11194 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
11195
11196 memset (&wi, 0, sizeof (wi));
75a70cf9 11197 walk_gimple_seq (body, diagnose_sb_1, NULL, &wi);
1e8e9920 11198
11199 memset (&wi, 0, sizeof (wi));
1e8e9920 11200 wi.want_locations = true;
e3a19533 11201 walk_gimple_seq_mod (&body, diagnose_sb_2, NULL, &wi);
11202
11203 gimple_set_body (current_function_decl, body);
1e8e9920 11204
11205 splay_tree_delete (all_labels);
11206 all_labels = NULL;
11207
bfec3452 11208 return 0;
1e8e9920 11209}
11210
cbe8bda8 11211namespace {
11212
11213const pass_data pass_data_diagnose_omp_blocks =
11214{
11215 GIMPLE_PASS, /* type */
11216 "*diagnose_omp_blocks", /* name */
11217 OPTGROUP_NONE, /* optinfo_flags */
cbe8bda8 11218 TV_NONE, /* tv_id */
11219 PROP_gimple_any, /* properties_required */
11220 0, /* properties_provided */
11221 0, /* properties_destroyed */
11222 0, /* todo_flags_start */
11223 0, /* todo_flags_finish */
bfec3452 11224};
11225
cbe8bda8 11226class pass_diagnose_omp_blocks : public gimple_opt_pass
11227{
11228public:
9af5ce0c 11229 pass_diagnose_omp_blocks (gcc::context *ctxt)
11230 : gimple_opt_pass (pass_data_diagnose_omp_blocks, ctxt)
cbe8bda8 11231 {}
11232
11233 /* opt_pass methods: */
31315c24 11234 virtual bool gate (function *) { return flag_openmp || flag_cilkplus; }
65b0537f 11235 virtual unsigned int execute (function *)
11236 {
11237 return diagnose_omp_structured_block_errors ();
11238 }
cbe8bda8 11239
11240}; // class pass_diagnose_omp_blocks
11241
11242} // anon namespace
11243
11244gimple_opt_pass *
11245make_pass_diagnose_omp_blocks (gcc::context *ctxt)
11246{
11247 return new pass_diagnose_omp_blocks (ctxt);
11248}
d09768a4 11249\f
11250/* SIMD clone supporting code. */
11251
11252/* Allocate a fresh `simd_clone' and return it. NARGS is the number
11253 of arguments to reserve space for. */
11254
11255static struct cgraph_simd_clone *
11256simd_clone_struct_alloc (int nargs)
11257{
11258 struct cgraph_simd_clone *clone_info;
11259 size_t len = (sizeof (struct cgraph_simd_clone)
11260 + nargs * sizeof (struct cgraph_simd_clone_arg));
11261 clone_info = (struct cgraph_simd_clone *)
ea7d8c7a 11262 ggc_internal_cleared_alloc (len);
d09768a4 11263 return clone_info;
11264}
11265
11266/* Make a copy of the `struct cgraph_simd_clone' in FROM to TO. */
11267
11268static inline void
11269simd_clone_struct_copy (struct cgraph_simd_clone *to,
11270 struct cgraph_simd_clone *from)
11271{
11272 memcpy (to, from, (sizeof (struct cgraph_simd_clone)
46c0fd4b 11273 + ((from->nargs - from->inbranch)
11274 * sizeof (struct cgraph_simd_clone_arg))));
d09768a4 11275}
11276
11277/* Return vector of parameter types of function FNDECL. This uses
11278 TYPE_ARG_TYPES if available, otherwise falls back to types of
11279 DECL_ARGUMENTS types. */
11280
11281vec<tree>
11282simd_clone_vector_of_formal_parm_types (tree fndecl)
11283{
11284 if (TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
11285 return ipa_get_vector_of_formal_parm_types (TREE_TYPE (fndecl));
11286 vec<tree> args = ipa_get_vector_of_formal_parms (fndecl);
11287 unsigned int i;
11288 tree arg;
11289 FOR_EACH_VEC_ELT (args, i, arg)
11290 args[i] = TREE_TYPE (args[i]);
11291 return args;
11292}
11293
11294/* Given a simd function in NODE, extract the simd specific
11295 information from the OMP clauses passed in CLAUSES, and return
11296 the struct cgraph_simd_clone * if it should be cloned. *INBRANCH_SPECIFIED
11297 is set to TRUE if the `inbranch' or `notinbranch' clause specified,
11298 otherwise set to FALSE. */
11299
11300static struct cgraph_simd_clone *
11301simd_clone_clauses_extract (struct cgraph_node *node, tree clauses,
11302 bool *inbranch_specified)
11303{
11304 vec<tree> args = simd_clone_vector_of_formal_parm_types (node->decl);
11305 tree t;
11306 int n;
11307 *inbranch_specified = false;
11308
11309 n = args.length ();
11310 if (n > 0 && args.last () == void_type_node)
11311 n--;
11312
11313 /* To distinguish from an OpenMP simd clone, Cilk Plus functions to
11314 be cloned have a distinctive artificial label in addition to "omp
11315 declare simd". */
11316 bool cilk_clone
a89e6c15 11317 = (flag_cilkplus
74acc703 11318 && lookup_attribute ("cilk simd function",
d09768a4 11319 DECL_ATTRIBUTES (node->decl)));
11320
11321 /* Allocate one more than needed just in case this is an in-branch
11322 clone which will require a mask argument. */
11323 struct cgraph_simd_clone *clone_info = simd_clone_struct_alloc (n + 1);
11324 clone_info->nargs = n;
11325 clone_info->cilk_elemental = cilk_clone;
11326
11327 if (!clauses)
11328 {
11329 args.release ();
11330 return clone_info;
11331 }
11332 clauses = TREE_VALUE (clauses);
11333 if (!clauses || TREE_CODE (clauses) != OMP_CLAUSE)
11334 return clone_info;
11335
11336 for (t = clauses; t; t = OMP_CLAUSE_CHAIN (t))
11337 {
11338 switch (OMP_CLAUSE_CODE (t))
11339 {
11340 case OMP_CLAUSE_INBRANCH:
11341 clone_info->inbranch = 1;
11342 *inbranch_specified = true;
11343 break;
11344 case OMP_CLAUSE_NOTINBRANCH:
11345 clone_info->inbranch = 0;
11346 *inbranch_specified = true;
11347 break;
11348 case OMP_CLAUSE_SIMDLEN:
11349 clone_info->simdlen
11350 = TREE_INT_CST_LOW (OMP_CLAUSE_SIMDLEN_EXPR (t));
11351 break;
11352 case OMP_CLAUSE_LINEAR:
11353 {
11354 tree decl = OMP_CLAUSE_DECL (t);
11355 tree step = OMP_CLAUSE_LINEAR_STEP (t);
11356 int argno = TREE_INT_CST_LOW (decl);
11357 if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (t))
11358 {
11359 clone_info->args[argno].arg_type
11360 = SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP;
11361 clone_info->args[argno].linear_step = tree_to_shwi (step);
11362 gcc_assert (clone_info->args[argno].linear_step >= 0
11363 && clone_info->args[argno].linear_step < n);
11364 }
11365 else
11366 {
11367 if (POINTER_TYPE_P (args[argno]))
11368 step = fold_convert (ssizetype, step);
11369 if (!tree_fits_shwi_p (step))
11370 {
11371 warning_at (OMP_CLAUSE_LOCATION (t), 0,
11372 "ignoring large linear step");
11373 args.release ();
11374 return NULL;
11375 }
11376 else if (integer_zerop (step))
11377 {
11378 warning_at (OMP_CLAUSE_LOCATION (t), 0,
11379 "ignoring zero linear step");
11380 args.release ();
11381 return NULL;
11382 }
11383 else
11384 {
11385 clone_info->args[argno].arg_type
11386 = SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP;
11387 clone_info->args[argno].linear_step = tree_to_shwi (step);
11388 }
11389 }
11390 break;
11391 }
11392 case OMP_CLAUSE_UNIFORM:
11393 {
11394 tree decl = OMP_CLAUSE_DECL (t);
11395 int argno = tree_to_uhwi (decl);
11396 clone_info->args[argno].arg_type
11397 = SIMD_CLONE_ARG_TYPE_UNIFORM;
11398 break;
11399 }
11400 case OMP_CLAUSE_ALIGNED:
11401 {
11402 tree decl = OMP_CLAUSE_DECL (t);
11403 int argno = tree_to_uhwi (decl);
11404 clone_info->args[argno].alignment
11405 = TREE_INT_CST_LOW (OMP_CLAUSE_ALIGNED_ALIGNMENT (t));
11406 break;
11407 }
11408 default:
11409 break;
11410 }
11411 }
11412 args.release ();
11413 return clone_info;
11414}
11415
11416/* Given a SIMD clone in NODE, calculate the characteristic data
11417 type and return the coresponding type. The characteristic data
11418 type is computed as described in the Intel Vector ABI. */
11419
11420static tree
11421simd_clone_compute_base_data_type (struct cgraph_node *node,
11422 struct cgraph_simd_clone *clone_info)
11423{
11424 tree type = integer_type_node;
11425 tree fndecl = node->decl;
11426
11427 /* a) For non-void function, the characteristic data type is the
11428 return type. */
11429 if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) != VOID_TYPE)
11430 type = TREE_TYPE (TREE_TYPE (fndecl));
11431
11432 /* b) If the function has any non-uniform, non-linear parameters,
11433 then the characteristic data type is the type of the first
11434 such parameter. */
11435 else
11436 {
11437 vec<tree> map = simd_clone_vector_of_formal_parm_types (fndecl);
11438 for (unsigned int i = 0; i < clone_info->nargs; ++i)
11439 if (clone_info->args[i].arg_type == SIMD_CLONE_ARG_TYPE_VECTOR)
11440 {
11441 type = map[i];
11442 break;
11443 }
11444 map.release ();
11445 }
11446
11447 /* c) If the characteristic data type determined by a) or b) above
11448 is struct, union, or class type which is pass-by-value (except
11449 for the type that maps to the built-in complex data type), the
11450 characteristic data type is int. */
11451 if (RECORD_OR_UNION_TYPE_P (type)
11452 && !aggregate_value_p (type, NULL)
11453 && TREE_CODE (type) != COMPLEX_TYPE)
11454 return integer_type_node;
11455
11456 /* d) If none of the above three classes is applicable, the
11457 characteristic data type is int. */
11458
11459 return type;
11460
11461 /* e) For Intel Xeon Phi native and offload compilation, if the
11462 resulting characteristic data type is 8-bit or 16-bit integer
11463 data type, the characteristic data type is int. */
11464 /* Well, we don't handle Xeon Phi yet. */
11465}
11466
11467static tree
11468simd_clone_mangle (struct cgraph_node *node,
11469 struct cgraph_simd_clone *clone_info)
11470{
11471 char vecsize_mangle = clone_info->vecsize_mangle;
11472 char mask = clone_info->inbranch ? 'M' : 'N';
11473 unsigned int simdlen = clone_info->simdlen;
11474 unsigned int n;
11475 pretty_printer pp;
11476
11477 gcc_assert (vecsize_mangle && simdlen);
11478
11479 pp_string (&pp, "_ZGV");
11480 pp_character (&pp, vecsize_mangle);
11481 pp_character (&pp, mask);
11482 pp_decimal_int (&pp, simdlen);
11483
11484 for (n = 0; n < clone_info->nargs; ++n)
11485 {
11486 struct cgraph_simd_clone_arg arg = clone_info->args[n];
11487
11488 if (arg.arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM)
11489 pp_character (&pp, 'u');
11490 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
11491 {
11492 gcc_assert (arg.linear_step != 0);
11493 pp_character (&pp, 'l');
11494 if (arg.linear_step > 1)
11495 pp_unsigned_wide_integer (&pp, arg.linear_step);
11496 else if (arg.linear_step < 0)
11497 {
11498 pp_character (&pp, 'n');
11499 pp_unsigned_wide_integer (&pp, (-(unsigned HOST_WIDE_INT)
11500 arg.linear_step));
11501 }
11502 }
11503 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP)
11504 {
11505 pp_character (&pp, 's');
11506 pp_unsigned_wide_integer (&pp, arg.linear_step);
11507 }
11508 else
11509 pp_character (&pp, 'v');
11510 if (arg.alignment)
11511 {
11512 pp_character (&pp, 'a');
11513 pp_decimal_int (&pp, arg.alignment);
11514 }
11515 }
11516
11517 pp_underscore (&pp);
11518 pp_string (&pp,
11519 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl)));
11520 const char *str = pp_formatted_text (&pp);
11521
11522 /* If there already is a SIMD clone with the same mangled name, don't
11523 add another one. This can happen e.g. for
11524 #pragma omp declare simd
11525 #pragma omp declare simd simdlen(8)
11526 int foo (int, int);
11527 if the simdlen is assumed to be 8 for the first one, etc. */
11528 for (struct cgraph_node *clone = node->simd_clones; clone;
11529 clone = clone->simdclone->next_clone)
11530 if (strcmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (clone->decl)),
11531 str) == 0)
11532 return NULL_TREE;
11533
11534 return get_identifier (str);
11535}
11536
11537/* Create a simd clone of OLD_NODE and return it. */
11538
11539static struct cgraph_node *
11540simd_clone_create (struct cgraph_node *old_node)
11541{
11542 struct cgraph_node *new_node;
11543 if (old_node->definition)
ea0695f9 11544 {
415d1b9a 11545 if (!old_node->has_gimple_body_p ())
ea0695f9 11546 return NULL;
415d1b9a 11547 old_node->get_body ();
11548 new_node = old_node->create_version_clone_with_body (vNULL, NULL, NULL,
11549 false, NULL, NULL,
11550 "simdclone");
ea0695f9 11551 }
d09768a4 11552 else
11553 {
11554 tree old_decl = old_node->decl;
11555 tree new_decl = copy_node (old_node->decl);
11556 DECL_NAME (new_decl) = clone_function_name (old_decl, "simdclone");
11557 SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl));
11558 SET_DECL_RTL (new_decl, NULL);
11559 DECL_STATIC_CONSTRUCTOR (new_decl) = 0;
11560 DECL_STATIC_DESTRUCTOR (new_decl) = 0;
415d1b9a 11561 new_node = old_node->create_version_clone (new_decl, vNULL, NULL);
35ee1c66 11562 symtab->call_cgraph_insertion_hooks (new_node);
d09768a4 11563 }
11564 if (new_node == NULL)
11565 return new_node;
11566
11567 TREE_PUBLIC (new_node->decl) = TREE_PUBLIC (old_node->decl);
11568
11569 /* The function cgraph_function_versioning () will force the new
11570 symbol local. Undo this, and inherit external visability from
11571 the old node. */
11572 new_node->local.local = old_node->local.local;
11573 new_node->externally_visible = old_node->externally_visible;
11574
11575 return new_node;
11576}
11577
11578/* Adjust the return type of the given function to its appropriate
11579 vector counterpart. Returns a simd array to be used throughout the
11580 function as a return value. */
11581
11582static tree
11583simd_clone_adjust_return_type (struct cgraph_node *node)
11584{
11585 tree fndecl = node->decl;
11586 tree orig_rettype = TREE_TYPE (TREE_TYPE (fndecl));
11587 unsigned int veclen;
11588 tree t;
11589
11590 /* Adjust the function return type. */
11591 if (orig_rettype == void_type_node)
11592 return NULL_TREE;
11593 TREE_TYPE (fndecl) = build_distinct_type_copy (TREE_TYPE (fndecl));
11594 if (INTEGRAL_TYPE_P (TREE_TYPE (TREE_TYPE (fndecl)))
11595 || POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (fndecl))))
11596 veclen = node->simdclone->vecsize_int;
11597 else
11598 veclen = node->simdclone->vecsize_float;
11599 veclen /= GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (fndecl))));
11600 if (veclen > node->simdclone->simdlen)
11601 veclen = node->simdclone->simdlen;
11602 if (veclen == node->simdclone->simdlen)
11603 TREE_TYPE (TREE_TYPE (fndecl))
11604 = build_vector_type (TREE_TYPE (TREE_TYPE (fndecl)),
11605 node->simdclone->simdlen);
11606 else
11607 {
11608 t = build_vector_type (TREE_TYPE (TREE_TYPE (fndecl)), veclen);
11609 t = build_array_type_nelts (t, node->simdclone->simdlen / veclen);
11610 TREE_TYPE (TREE_TYPE (fndecl)) = t;
11611 }
11612 if (!node->definition)
11613 return NULL_TREE;
11614
11615 t = DECL_RESULT (fndecl);
11616 /* Adjust the DECL_RESULT. */
11617 gcc_assert (TREE_TYPE (t) != void_type_node);
11618 TREE_TYPE (t) = TREE_TYPE (TREE_TYPE (fndecl));
11619 relayout_decl (t);
11620
11621 tree atype = build_array_type_nelts (orig_rettype,
11622 node->simdclone->simdlen);
11623 if (veclen != node->simdclone->simdlen)
11624 return build1 (VIEW_CONVERT_EXPR, atype, t);
11625
11626 /* Set up a SIMD array to use as the return value. */
11627 tree retval = create_tmp_var_raw (atype, "retval");
11628 gimple_add_tmp_var (retval);
11629 return retval;
11630}
11631
11632/* Each vector argument has a corresponding array to be used locally
11633 as part of the eventual loop. Create such temporary array and
11634 return it.
11635
11636 PREFIX is the prefix to be used for the temporary.
11637
11638 TYPE is the inner element type.
11639
11640 SIMDLEN is the number of elements. */
11641
11642static tree
11643create_tmp_simd_array (const char *prefix, tree type, int simdlen)
11644{
11645 tree atype = build_array_type_nelts (type, simdlen);
11646 tree avar = create_tmp_var_raw (atype, prefix);
11647 gimple_add_tmp_var (avar);
11648 return avar;
11649}
11650
11651/* Modify the function argument types to their corresponding vector
11652 counterparts if appropriate. Also, create one array for each simd
11653 argument to be used locally when using the function arguments as
11654 part of the loop.
11655
11656 NODE is the function whose arguments are to be adjusted.
11657
11658 Returns an adjustment vector that will be filled describing how the
11659 argument types will be adjusted. */
11660
11661static ipa_parm_adjustment_vec
11662simd_clone_adjust_argument_types (struct cgraph_node *node)
11663{
11664 vec<tree> args;
11665 ipa_parm_adjustment_vec adjustments;
11666
11667 if (node->definition)
11668 args = ipa_get_vector_of_formal_parms (node->decl);
11669 else
11670 args = simd_clone_vector_of_formal_parm_types (node->decl);
11671 adjustments.create (args.length ());
11672 unsigned i, j, veclen;
11673 struct ipa_parm_adjustment adj;
11674 for (i = 0; i < node->simdclone->nargs; ++i)
11675 {
11676 memset (&adj, 0, sizeof (adj));
11677 tree parm = args[i];
11678 tree parm_type = node->definition ? TREE_TYPE (parm) : parm;
11679 adj.base_index = i;
11680 adj.base = parm;
11681
11682 node->simdclone->args[i].orig_arg = node->definition ? parm : NULL_TREE;
11683 node->simdclone->args[i].orig_type = parm_type;
11684
11685 if (node->simdclone->args[i].arg_type != SIMD_CLONE_ARG_TYPE_VECTOR)
11686 {
11687 /* No adjustment necessary for scalar arguments. */
11688 adj.op = IPA_PARM_OP_COPY;
11689 }
11690 else
11691 {
11692 if (INTEGRAL_TYPE_P (parm_type) || POINTER_TYPE_P (parm_type))
11693 veclen = node->simdclone->vecsize_int;
11694 else
11695 veclen = node->simdclone->vecsize_float;
11696 veclen /= GET_MODE_BITSIZE (TYPE_MODE (parm_type));
11697 if (veclen > node->simdclone->simdlen)
11698 veclen = node->simdclone->simdlen;
11699 adj.arg_prefix = "simd";
11700 adj.type = build_vector_type (parm_type, veclen);
11701 node->simdclone->args[i].vector_type = adj.type;
11702 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
11703 {
11704 adjustments.safe_push (adj);
11705 if (j == veclen)
11706 {
11707 memset (&adj, 0, sizeof (adj));
11708 adj.op = IPA_PARM_OP_NEW;
11709 adj.arg_prefix = "simd";
11710 adj.base_index = i;
11711 adj.type = node->simdclone->args[i].vector_type;
11712 }
11713 }
11714
11715 if (node->definition)
11716 node->simdclone->args[i].simd_array
11717 = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm)),
11718 parm_type, node->simdclone->simdlen);
11719 }
11720 adjustments.safe_push (adj);
11721 }
11722
11723 if (node->simdclone->inbranch)
11724 {
11725 tree base_type
11726 = simd_clone_compute_base_data_type (node->simdclone->origin,
11727 node->simdclone);
11728
11729 memset (&adj, 0, sizeof (adj));
11730 adj.op = IPA_PARM_OP_NEW;
11731 adj.arg_prefix = "mask";
11732
11733 adj.base_index = i;
11734 if (INTEGRAL_TYPE_P (base_type) || POINTER_TYPE_P (base_type))
11735 veclen = node->simdclone->vecsize_int;
11736 else
11737 veclen = node->simdclone->vecsize_float;
11738 veclen /= GET_MODE_BITSIZE (TYPE_MODE (base_type));
11739 if (veclen > node->simdclone->simdlen)
11740 veclen = node->simdclone->simdlen;
11741 adj.type = build_vector_type (base_type, veclen);
11742 adjustments.safe_push (adj);
11743
11744 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
11745 adjustments.safe_push (adj);
11746
11747 /* We have previously allocated one extra entry for the mask. Use
11748 it and fill it. */
11749 struct cgraph_simd_clone *sc = node->simdclone;
11750 sc->nargs++;
11751 if (node->definition)
11752 {
11753 sc->args[i].orig_arg
11754 = build_decl (UNKNOWN_LOCATION, PARM_DECL, NULL, base_type);
11755 sc->args[i].simd_array
11756 = create_tmp_simd_array ("mask", base_type, sc->simdlen);
11757 }
11758 sc->args[i].orig_type = base_type;
11759 sc->args[i].arg_type = SIMD_CLONE_ARG_TYPE_MASK;
11760 }
11761
11762 if (node->definition)
11763 ipa_modify_formal_parameters (node->decl, adjustments);
11764 else
11765 {
11766 tree new_arg_types = NULL_TREE, new_reversed;
11767 bool last_parm_void = false;
11768 if (args.length () > 0 && args.last () == void_type_node)
11769 last_parm_void = true;
11770
11771 gcc_assert (TYPE_ARG_TYPES (TREE_TYPE (node->decl)));
11772 j = adjustments.length ();
11773 for (i = 0; i < j; i++)
11774 {
11775 struct ipa_parm_adjustment *adj = &adjustments[i];
11776 tree ptype;
11777 if (adj->op == IPA_PARM_OP_COPY)
11778 ptype = args[adj->base_index];
11779 else
11780 ptype = adj->type;
11781 new_arg_types = tree_cons (NULL_TREE, ptype, new_arg_types);
11782 }
11783 new_reversed = nreverse (new_arg_types);
11784 if (last_parm_void)
11785 {
11786 if (new_reversed)
11787 TREE_CHAIN (new_arg_types) = void_list_node;
11788 else
11789 new_reversed = void_list_node;
11790 }
11791
11792 tree new_type = build_distinct_type_copy (TREE_TYPE (node->decl));
11793 TYPE_ARG_TYPES (new_type) = new_reversed;
11794 TREE_TYPE (node->decl) = new_type;
11795
11796 adjustments.release ();
11797 }
11798 args.release ();
11799 return adjustments;
11800}
11801
11802/* Initialize and copy the function arguments in NODE to their
11803 corresponding local simd arrays. Returns a fresh gimple_seq with
11804 the instruction sequence generated. */
11805
11806static gimple_seq
11807simd_clone_init_simd_arrays (struct cgraph_node *node,
11808 ipa_parm_adjustment_vec adjustments)
11809{
11810 gimple_seq seq = NULL;
11811 unsigned i = 0, j = 0, k;
11812
11813 for (tree arg = DECL_ARGUMENTS (node->decl);
11814 arg;
11815 arg = DECL_CHAIN (arg), i++, j++)
11816 {
11817 if (adjustments[j].op == IPA_PARM_OP_COPY)
11818 continue;
11819
11820 node->simdclone->args[i].vector_arg = arg;
11821
11822 tree array = node->simdclone->args[i].simd_array;
11823 if (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg)) == node->simdclone->simdlen)
11824 {
11825 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
11826 tree ptr = build_fold_addr_expr (array);
11827 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
11828 build_int_cst (ptype, 0));
11829 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
11830 gimplify_and_add (t, &seq);
11831 }
11832 else
11833 {
11834 unsigned int simdlen = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg));
11835 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
11836 for (k = 0; k < node->simdclone->simdlen; k += simdlen)
11837 {
11838 tree ptr = build_fold_addr_expr (array);
11839 int elemsize;
11840 if (k)
11841 {
11842 arg = DECL_CHAIN (arg);
11843 j++;
11844 }
11845 elemsize
11846 = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg))));
11847 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
11848 build_int_cst (ptype, k * elemsize));
11849 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
11850 gimplify_and_add (t, &seq);
11851 }
11852 }
11853 }
11854 return seq;
11855}
11856
11857/* Callback info for ipa_simd_modify_stmt_ops below. */
11858
11859struct modify_stmt_info {
11860 ipa_parm_adjustment_vec adjustments;
11861 gimple stmt;
11862 /* True if the parent statement was modified by
11863 ipa_simd_modify_stmt_ops. */
11864 bool modified;
11865};
11866
11867/* Callback for walk_gimple_op.
11868
11869 Adjust operands from a given statement as specified in the
11870 adjustments vector in the callback data. */
11871
11872static tree
11873ipa_simd_modify_stmt_ops (tree *tp, int *walk_subtrees, void *data)
11874{
11875 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
2d78e89f 11876 struct modify_stmt_info *info = (struct modify_stmt_info *) wi->info;
11877 tree *orig_tp = tp;
11878 if (TREE_CODE (*tp) == ADDR_EXPR)
11879 tp = &TREE_OPERAND (*tp, 0);
11880 struct ipa_parm_adjustment *cand = NULL;
11881 if (TREE_CODE (*tp) == PARM_DECL)
11882 cand = ipa_get_adjustment_candidate (&tp, NULL, info->adjustments, true);
11883 else
d09768a4 11884 {
d09768a4 11885 if (TYPE_P (*tp))
11886 *walk_subtrees = 0;
d09768a4 11887 }
d09768a4 11888
2d78e89f 11889 tree repl = NULL_TREE;
11890 if (cand)
11891 repl = unshare_expr (cand->new_decl);
11892 else
d09768a4 11893 {
2d78e89f 11894 if (tp != orig_tp)
11895 {
11896 *walk_subtrees = 0;
11897 bool modified = info->modified;
11898 info->modified = false;
11899 walk_tree (tp, ipa_simd_modify_stmt_ops, wi, wi->pset);
11900 if (!info->modified)
11901 {
11902 info->modified = modified;
11903 return NULL_TREE;
11904 }
11905 info->modified = modified;
11906 repl = *tp;
11907 }
11908 else
11909 return NULL_TREE;
d09768a4 11910 }
2d78e89f 11911
11912 if (tp != orig_tp)
d09768a4 11913 {
2d78e89f 11914 repl = build_fold_addr_expr (repl);
9c1dd4d9 11915 gimple stmt;
11916 if (is_gimple_debug (info->stmt))
11917 {
11918 tree vexpr = make_node (DEBUG_EXPR_DECL);
11919 stmt = gimple_build_debug_source_bind (vexpr, repl, NULL);
11920 DECL_ARTIFICIAL (vexpr) = 1;
11921 TREE_TYPE (vexpr) = TREE_TYPE (repl);
11922 DECL_MODE (vexpr) = TYPE_MODE (TREE_TYPE (repl));
11923 repl = vexpr;
11924 }
11925 else
11926 {
11927 stmt = gimple_build_assign (make_ssa_name (TREE_TYPE (repl),
11928 NULL), repl);
11929 repl = gimple_assign_lhs (stmt);
11930 }
2d78e89f 11931 gimple_stmt_iterator gsi = gsi_for_stmt (info->stmt);
d09768a4 11932 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
2d78e89f 11933 *orig_tp = repl;
d09768a4 11934 }
2d78e89f 11935 else if (!useless_type_conversion_p (TREE_TYPE (*tp), TREE_TYPE (repl)))
d09768a4 11936 {
11937 tree vce = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (*tp), repl);
11938 *tp = vce;
11939 }
11940 else
11941 *tp = repl;
11942
11943 info->modified = true;
d09768a4 11944 return NULL_TREE;
11945}
11946
11947/* Traverse the function body and perform all modifications as
11948 described in ADJUSTMENTS. At function return, ADJUSTMENTS will be
11949 modified such that the replacement/reduction value will now be an
11950 offset into the corresponding simd_array.
11951
11952 This function will replace all function argument uses with their
11953 corresponding simd array elements, and ajust the return values
11954 accordingly. */
11955
11956static void
11957ipa_simd_modify_function_body (struct cgraph_node *node,
11958 ipa_parm_adjustment_vec adjustments,
11959 tree retval_array, tree iter)
11960{
11961 basic_block bb;
2d78e89f 11962 unsigned int i, j, l;
d09768a4 11963
11964 /* Re-use the adjustments array, but this time use it to replace
11965 every function argument use to an offset into the corresponding
11966 simd_array. */
11967 for (i = 0, j = 0; i < node->simdclone->nargs; ++i, ++j)
11968 {
11969 if (!node->simdclone->args[i].vector_arg)
11970 continue;
11971
11972 tree basetype = TREE_TYPE (node->simdclone->args[i].orig_arg);
11973 tree vectype = TREE_TYPE (node->simdclone->args[i].vector_arg);
11974 adjustments[j].new_decl
11975 = build4 (ARRAY_REF,
11976 basetype,
11977 node->simdclone->args[i].simd_array,
11978 iter,
11979 NULL_TREE, NULL_TREE);
11980 if (adjustments[j].op == IPA_PARM_OP_NONE
11981 && TYPE_VECTOR_SUBPARTS (vectype) < node->simdclone->simdlen)
11982 j += node->simdclone->simdlen / TYPE_VECTOR_SUBPARTS (vectype) - 1;
11983 }
11984
2d78e89f 11985 l = adjustments.length ();
11986 for (i = 1; i < num_ssa_names; i++)
11987 {
11988 tree name = ssa_name (i);
11989 if (name
11990 && SSA_NAME_VAR (name)
11991 && TREE_CODE (SSA_NAME_VAR (name)) == PARM_DECL)
11992 {
11993 for (j = 0; j < l; j++)
11994 if (SSA_NAME_VAR (name) == adjustments[j].base
11995 && adjustments[j].new_decl)
11996 {
11997 tree base_var;
11998 if (adjustments[j].new_ssa_base == NULL_TREE)
11999 {
12000 base_var
12001 = copy_var_decl (adjustments[j].base,
12002 DECL_NAME (adjustments[j].base),
12003 TREE_TYPE (adjustments[j].base));
12004 adjustments[j].new_ssa_base = base_var;
12005 }
12006 else
12007 base_var = adjustments[j].new_ssa_base;
12008 if (SSA_NAME_IS_DEFAULT_DEF (name))
12009 {
12010 bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
12011 gimple_stmt_iterator gsi = gsi_after_labels (bb);
12012 tree new_decl = unshare_expr (adjustments[j].new_decl);
12013 set_ssa_default_def (cfun, adjustments[j].base, NULL_TREE);
12014 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
12015 SSA_NAME_IS_DEFAULT_DEF (name) = 0;
12016 gimple stmt = gimple_build_assign (name, new_decl);
12017 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
12018 }
12019 else
12020 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
12021 }
12022 }
12023 }
12024
d09768a4 12025 struct modify_stmt_info info;
12026 info.adjustments = adjustments;
12027
12028 FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl))
12029 {
12030 gimple_stmt_iterator gsi;
12031
12032 gsi = gsi_start_bb (bb);
12033 while (!gsi_end_p (gsi))
12034 {
12035 gimple stmt = gsi_stmt (gsi);
12036 info.stmt = stmt;
12037 struct walk_stmt_info wi;
12038
12039 memset (&wi, 0, sizeof (wi));
12040 info.modified = false;
12041 wi.info = &info;
12042 walk_gimple_op (stmt, ipa_simd_modify_stmt_ops, &wi);
12043
1a91d914 12044 if (greturn *return_stmt = dyn_cast <greturn *> (stmt))
d09768a4 12045 {
1a91d914 12046 tree retval = gimple_return_retval (return_stmt);
d09768a4 12047 if (!retval)
12048 {
12049 gsi_remove (&gsi, true);
12050 continue;
12051 }
12052
12053 /* Replace `return foo' with `retval_array[iter] = foo'. */
12054 tree ref = build4 (ARRAY_REF, TREE_TYPE (retval),
12055 retval_array, iter, NULL, NULL);
12056 stmt = gimple_build_assign (ref, retval);
12057 gsi_replace (&gsi, stmt, true);
12058 info.modified = true;
12059 }
12060
12061 if (info.modified)
12062 {
12063 update_stmt (stmt);
12064 if (maybe_clean_eh_stmt (stmt))
12065 gimple_purge_dead_eh_edges (gimple_bb (stmt));
12066 }
12067 gsi_next (&gsi);
12068 }
12069 }
12070}
12071
12072/* Adjust the argument types in NODE to their appropriate vector
12073 counterparts. */
12074
12075static void
12076simd_clone_adjust (struct cgraph_node *node)
12077{
12078 push_cfun (DECL_STRUCT_FUNCTION (node->decl));
12079
12080 targetm.simd_clone.adjust (node);
12081
12082 tree retval = simd_clone_adjust_return_type (node);
12083 ipa_parm_adjustment_vec adjustments
12084 = simd_clone_adjust_argument_types (node);
12085
12086 push_gimplify_context ();
12087
12088 gimple_seq seq = simd_clone_init_simd_arrays (node, adjustments);
12089
12090 /* Adjust all uses of vector arguments accordingly. Adjust all
12091 return values accordingly. */
12092 tree iter = create_tmp_var (unsigned_type_node, "iter");
12093 tree iter1 = make_ssa_name (iter, NULL);
12094 tree iter2 = make_ssa_name (iter, NULL);
12095 ipa_simd_modify_function_body (node, adjustments, retval, iter1);
12096
12097 /* Initialize the iteration variable. */
12098 basic_block entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
12099 basic_block body_bb = split_block_after_labels (entry_bb)->dest;
12100 gimple_stmt_iterator gsi = gsi_after_labels (entry_bb);
12101 /* Insert the SIMD array and iv initialization at function
12102 entry. */
12103 gsi_insert_seq_before (&gsi, seq, GSI_NEW_STMT);
12104
12105 pop_gimplify_context (NULL);
12106
12107 /* Create a new BB right before the original exit BB, to hold the
12108 iteration increment and the condition/branch. */
12109 basic_block orig_exit = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), 0)->src;
12110 basic_block incr_bb = create_empty_bb (orig_exit);
343ee723 12111 add_bb_to_loop (incr_bb, body_bb->loop_father);
d09768a4 12112 /* The succ of orig_exit was EXIT_BLOCK_PTR_FOR_FN (cfun), with an empty
12113 flag. Set it now to be a FALLTHRU_EDGE. */
12114 gcc_assert (EDGE_COUNT (orig_exit->succs) == 1);
12115 EDGE_SUCC (orig_exit, 0)->flags |= EDGE_FALLTHRU;
12116 for (unsigned i = 0;
12117 i < EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds); ++i)
12118 {
12119 edge e = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), i);
12120 redirect_edge_succ (e, incr_bb);
12121 }
12122 edge e = make_edge (incr_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
12123 e->probability = REG_BR_PROB_BASE;
12124 gsi = gsi_last_bb (incr_bb);
12125 gimple g = gimple_build_assign_with_ops (PLUS_EXPR, iter2, iter1,
12126 build_int_cst (unsigned_type_node,
12127 1));
12128 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
12129
12130 /* Mostly annotate the loop for the vectorizer (the rest is done below). */
12131 struct loop *loop = alloc_loop ();
4c73695b 12132 cfun->has_force_vectorize_loops = true;
d09768a4 12133 loop->safelen = node->simdclone->simdlen;
4c73695b 12134 loop->force_vectorize = true;
d09768a4 12135 loop->header = body_bb;
d09768a4 12136
12137 /* Branch around the body if the mask applies. */
12138 if (node->simdclone->inbranch)
12139 {
12140 gimple_stmt_iterator gsi = gsi_last_bb (loop->header);
12141 tree mask_array
12142 = node->simdclone->args[node->simdclone->nargs - 1].simd_array;
12143 tree mask = make_ssa_name (TREE_TYPE (TREE_TYPE (mask_array)), NULL);
12144 tree aref = build4 (ARRAY_REF,
12145 TREE_TYPE (TREE_TYPE (mask_array)),
12146 mask_array, iter1,
12147 NULL, NULL);
12148 g = gimple_build_assign (mask, aref);
12149 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
12150 int bitsize = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (aref)));
12151 if (!INTEGRAL_TYPE_P (TREE_TYPE (aref)))
12152 {
12153 aref = build1 (VIEW_CONVERT_EXPR,
12154 build_nonstandard_integer_type (bitsize, 0), mask);
12155 mask = make_ssa_name (TREE_TYPE (aref), NULL);
12156 g = gimple_build_assign (mask, aref);
12157 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
12158 }
12159
12160 g = gimple_build_cond (EQ_EXPR, mask, build_zero_cst (TREE_TYPE (mask)),
12161 NULL, NULL);
12162 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
12163 make_edge (loop->header, incr_bb, EDGE_TRUE_VALUE);
12164 FALLTHRU_EDGE (loop->header)->flags = EDGE_FALSE_VALUE;
12165 }
12166
12167 /* Generate the condition. */
12168 g = gimple_build_cond (LT_EXPR,
12169 iter2,
12170 build_int_cst (unsigned_type_node,
12171 node->simdclone->simdlen),
12172 NULL, NULL);
12173 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
12174 e = split_block (incr_bb, gsi_stmt (gsi));
12175 basic_block latch_bb = e->dest;
343ee723 12176 basic_block new_exit_bb;
d09768a4 12177 new_exit_bb = split_block (latch_bb, NULL)->dest;
12178 loop->latch = latch_bb;
12179
12180 redirect_edge_succ (FALLTHRU_EDGE (latch_bb), body_bb);
12181
12182 make_edge (incr_bb, new_exit_bb, EDGE_FALSE_VALUE);
12183 /* The successor of incr_bb is already pointing to latch_bb; just
12184 change the flags.
12185 make_edge (incr_bb, latch_bb, EDGE_TRUE_VALUE); */
12186 FALLTHRU_EDGE (incr_bb)->flags = EDGE_TRUE_VALUE;
12187
1a91d914 12188 gphi *phi = create_phi_node (iter1, body_bb);
d09768a4 12189 edge preheader_edge = find_edge (entry_bb, body_bb);
12190 edge latch_edge = single_succ_edge (latch_bb);
12191 add_phi_arg (phi, build_zero_cst (unsigned_type_node), preheader_edge,
12192 UNKNOWN_LOCATION);
12193 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
12194
12195 /* Generate the new return. */
12196 gsi = gsi_last_bb (new_exit_bb);
12197 if (retval
12198 && TREE_CODE (retval) == VIEW_CONVERT_EXPR
12199 && TREE_CODE (TREE_OPERAND (retval, 0)) == RESULT_DECL)
12200 retval = TREE_OPERAND (retval, 0);
12201 else if (retval)
12202 {
12203 retval = build1 (VIEW_CONVERT_EXPR,
12204 TREE_TYPE (TREE_TYPE (node->decl)),
12205 retval);
12206 retval = force_gimple_operand_gsi (&gsi, retval, true, NULL,
12207 false, GSI_CONTINUE_LINKING);
12208 }
12209 g = gimple_build_return (retval);
12210 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
12211
12212 /* Handle aligned clauses by replacing default defs of the aligned
12213 uniform args with __builtin_assume_aligned (arg_N(D), alignment)
12214 lhs. Handle linear by adding PHIs. */
12215 for (unsigned i = 0; i < node->simdclone->nargs; i++)
12216 if (node->simdclone->args[i].alignment
12217 && node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
12218 && (node->simdclone->args[i].alignment
12219 & (node->simdclone->args[i].alignment - 1)) == 0
12220 && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
12221 == POINTER_TYPE)
12222 {
12223 unsigned int alignment = node->simdclone->args[i].alignment;
12224 tree orig_arg = node->simdclone->args[i].orig_arg;
12225 tree def = ssa_default_def (cfun, orig_arg);
6db33a3d 12226 if (def && !has_zero_uses (def))
d09768a4 12227 {
12228 tree fn = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
12229 gimple_seq seq = NULL;
12230 bool need_cvt = false;
1a91d914 12231 gcall *call
d09768a4 12232 = gimple_build_call (fn, 2, def, size_int (alignment));
12233 g = call;
12234 if (!useless_type_conversion_p (TREE_TYPE (orig_arg),
12235 ptr_type_node))
12236 need_cvt = true;
12237 tree t = make_ssa_name (need_cvt ? ptr_type_node : orig_arg, NULL);
12238 gimple_call_set_lhs (g, t);
12239 gimple_seq_add_stmt_without_update (&seq, g);
12240 if (need_cvt)
12241 {
12242 t = make_ssa_name (orig_arg, NULL);
12243 g = gimple_build_assign_with_ops (NOP_EXPR, t,
806413d2 12244 gimple_call_lhs (g));
d09768a4 12245 gimple_seq_add_stmt_without_update (&seq, g);
12246 }
12247 gsi_insert_seq_on_edge_immediate
12248 (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)), seq);
12249
12250 entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
12251 int freq = compute_call_stmt_bb_frequency (current_function_decl,
12252 entry_bb);
415d1b9a 12253 node->create_edge (cgraph_node::get_create (fn),
12254 call, entry_bb->count, freq);
d09768a4 12255
12256 imm_use_iterator iter;
12257 use_operand_p use_p;
12258 gimple use_stmt;
12259 tree repl = gimple_get_lhs (g);
12260 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
12261 if (is_gimple_debug (use_stmt) || use_stmt == call)
12262 continue;
12263 else
12264 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
12265 SET_USE (use_p, repl);
12266 }
12267 }
12268 else if (node->simdclone->args[i].arg_type
12269 == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
12270 {
12271 tree orig_arg = node->simdclone->args[i].orig_arg;
12272 tree def = ssa_default_def (cfun, orig_arg);
12273 gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
12274 || POINTER_TYPE_P (TREE_TYPE (orig_arg)));
6db33a3d 12275 if (def && !has_zero_uses (def))
d09768a4 12276 {
12277 iter1 = make_ssa_name (orig_arg, NULL);
12278 iter2 = make_ssa_name (orig_arg, NULL);
12279 phi = create_phi_node (iter1, body_bb);
12280 add_phi_arg (phi, def, preheader_edge, UNKNOWN_LOCATION);
12281 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
12282 enum tree_code code = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
12283 ? PLUS_EXPR : POINTER_PLUS_EXPR;
12284 tree addtype = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
12285 ? TREE_TYPE (orig_arg) : sizetype;
12286 tree addcst
12287 = build_int_cst (addtype, node->simdclone->args[i].linear_step);
12288 g = gimple_build_assign_with_ops (code, iter2, iter1, addcst);
12289 gsi = gsi_last_bb (incr_bb);
12290 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
12291
12292 imm_use_iterator iter;
12293 use_operand_p use_p;
12294 gimple use_stmt;
12295 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
12296 if (use_stmt == phi)
12297 continue;
12298 else
12299 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
12300 SET_USE (use_p, iter1);
12301 }
12302 }
12303
12304 calculate_dominance_info (CDI_DOMINATORS);
12305 add_loop (loop, loop->header->loop_father);
12306 update_ssa (TODO_update_ssa);
12307
12308 pop_cfun ();
12309}
12310
12311/* If the function in NODE is tagged as an elemental SIMD function,
12312 create the appropriate SIMD clones. */
12313
12314static void
12315expand_simd_clones (struct cgraph_node *node)
12316{
d09768a4 12317 tree attr = lookup_attribute ("omp declare simd",
12318 DECL_ATTRIBUTES (node->decl));
ea0695f9 12319 if (attr == NULL_TREE
12320 || node->global.inlined_to
12321 || lookup_attribute ("noclone", DECL_ATTRIBUTES (node->decl)))
d09768a4 12322 return;
ea0695f9 12323
d09768a4 12324 /* Ignore
12325 #pragma omp declare simd
12326 extern int foo ();
12327 in C, there we don't know the argument types at all. */
12328 if (!node->definition
12329 && TYPE_ARG_TYPES (TREE_TYPE (node->decl)) == NULL_TREE)
12330 return;
12331
12332 do
12333 {
12334 /* Start with parsing the "omp declare simd" attribute(s). */
12335 bool inbranch_clause_specified;
12336 struct cgraph_simd_clone *clone_info
12337 = simd_clone_clauses_extract (node, TREE_VALUE (attr),
12338 &inbranch_clause_specified);
12339 if (clone_info == NULL)
12340 continue;
12341
12342 int orig_simdlen = clone_info->simdlen;
12343 tree base_type = simd_clone_compute_base_data_type (node, clone_info);
12344 /* The target can return 0 (no simd clones should be created),
12345 1 (just one ISA of simd clones should be created) or higher
12346 count of ISA variants. In that case, clone_info is initialized
12347 for the first ISA variant. */
12348 int count
12349 = targetm.simd_clone.compute_vecsize_and_simdlen (node, clone_info,
12350 base_type, 0);
12351 if (count == 0)
12352 continue;
12353
12354 /* Loop over all COUNT ISA variants, and if !INBRANCH_CLAUSE_SPECIFIED,
12355 also create one inbranch and one !inbranch clone of it. */
12356 for (int i = 0; i < count * 2; i++)
12357 {
12358 struct cgraph_simd_clone *clone = clone_info;
12359 if (inbranch_clause_specified && (i & 1) != 0)
12360 continue;
12361
12362 if (i != 0)
12363 {
12364 clone = simd_clone_struct_alloc (clone_info->nargs
d09768a4 12365 + ((i & 1) != 0));
12366 simd_clone_struct_copy (clone, clone_info);
12367 /* Undo changes targetm.simd_clone.compute_vecsize_and_simdlen
12368 and simd_clone_adjust_argument_types did to the first
12369 clone's info. */
12370 clone->nargs -= clone_info->inbranch;
12371 clone->simdlen = orig_simdlen;
12372 /* And call the target hook again to get the right ISA. */
12373 targetm.simd_clone.compute_vecsize_and_simdlen (node, clone,
12374 base_type,
12375 i / 2);
12376 if ((i & 1) != 0)
12377 clone->inbranch = 1;
12378 }
12379
12380 /* simd_clone_mangle might fail if such a clone has been created
12381 already. */
12382 tree id = simd_clone_mangle (node, clone);
12383 if (id == NULL_TREE)
12384 continue;
12385
12386 /* Only when we are sure we want to create the clone actually
12387 clone the function (or definitions) or create another
12388 extern FUNCTION_DECL (for prototypes without definitions). */
12389 struct cgraph_node *n = simd_clone_create (node);
12390 if (n == NULL)
12391 continue;
12392
12393 n->simdclone = clone;
12394 clone->origin = node;
12395 clone->next_clone = NULL;
12396 if (node->simd_clones == NULL)
12397 {
12398 clone->prev_clone = n;
12399 node->simd_clones = n;
12400 }
12401 else
12402 {
12403 clone->prev_clone = node->simd_clones->simdclone->prev_clone;
12404 clone->prev_clone->simdclone->next_clone = n;
12405 node->simd_clones->simdclone->prev_clone = n;
12406 }
35ee1c66 12407 symtab->change_decl_assembler_name (n->decl, id);
d09768a4 12408 /* And finally adjust the return type, parameters and for
12409 definitions also function body. */
12410 if (node->definition)
12411 simd_clone_adjust (n);
12412 else
12413 {
12414 simd_clone_adjust_return_type (n);
12415 simd_clone_adjust_argument_types (n);
12416 }
12417 }
12418 }
12419 while ((attr = lookup_attribute ("omp declare simd", TREE_CHAIN (attr))));
12420}
12421
12422/* Entry point for IPA simd clone creation pass. */
12423
12424static unsigned int
12425ipa_omp_simd_clone (void)
12426{
12427 struct cgraph_node *node;
12428 FOR_EACH_FUNCTION (node)
12429 expand_simd_clones (node);
12430 return 0;
12431}
12432
12433namespace {
12434
12435const pass_data pass_data_omp_simd_clone =
12436{
12437 SIMPLE_IPA_PASS, /* type */
12438 "simdclone", /* name */
12439 OPTGROUP_NONE, /* optinfo_flags */
d09768a4 12440 TV_NONE, /* tv_id */
12441 ( PROP_ssa | PROP_cfg ), /* properties_required */
12442 0, /* properties_provided */
12443 0, /* properties_destroyed */
12444 0, /* todo_flags_start */
12445 0, /* todo_flags_finish */
12446};
12447
12448class pass_omp_simd_clone : public simple_ipa_opt_pass
12449{
12450public:
12451 pass_omp_simd_clone(gcc::context *ctxt)
12452 : simple_ipa_opt_pass(pass_data_omp_simd_clone, ctxt)
12453 {}
12454
12455 /* opt_pass methods: */
31315c24 12456 virtual bool gate (function *);
65b0537f 12457 virtual unsigned int execute (function *) { return ipa_omp_simd_clone (); }
d09768a4 12458};
12459
31315c24 12460bool
12461pass_omp_simd_clone::gate (function *)
12462{
12463 return ((flag_openmp || flag_openmp_simd
12464 || flag_cilkplus
12465 || (in_lto_p && !flag_wpa))
12466 && (targetm.simd_clone.compute_vecsize_and_simdlen != NULL));
12467}
12468
d09768a4 12469} // anon namespace
12470
12471simple_ipa_opt_pass *
12472make_pass_omp_simd_clone (gcc::context *ctxt)
12473{
12474 return new pass_omp_simd_clone (ctxt);
12475}
cbe8bda8 12476
dccabdd1 12477/* Helper function for omp_finish_file routine. Takes decls from V_DECLS and
12478 adds their addresses and sizes to constructor-vector V_CTOR. */
12479static void
12480add_decls_addresses_to_decl_constructor (vec<tree, va_gc> *v_decls,
12481 vec<constructor_elt, va_gc> *v_ctor)
12482{
12483 unsigned len = vec_safe_length (v_decls);
12484 for (unsigned i = 0; i < len; i++)
12485 {
12486 tree it = (*v_decls)[i];
12487 bool is_function = TREE_CODE (it) != VAR_DECL;
12488
12489 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE, build_fold_addr_expr (it));
12490 if (!is_function)
12491 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE,
12492 fold_convert (const_ptr_type_node,
12493 DECL_SIZE_UNIT (it)));
12494 }
12495}
12496
12497/* Create new symbols containing (address, size) pairs for global variables,
12498 marked with "omp declare target" attribute, as well as addresses for the
12499 functions, which are outlined target regions. */
12500void
12501omp_finish_file (void)
12502{
12503 unsigned num_funcs = vec_safe_length (offload_funcs);
12504 unsigned num_vars = vec_safe_length (offload_vars);
12505
12506 if (num_funcs == 0 && num_vars == 0)
12507 return;
12508
12509 if (targetm_common.have_named_sections)
12510 {
12511 vec<constructor_elt, va_gc> *v_f, *v_v;
12512 vec_alloc (v_f, num_funcs);
12513 vec_alloc (v_v, num_vars * 2);
12514
12515 add_decls_addresses_to_decl_constructor (offload_funcs, v_f);
12516 add_decls_addresses_to_decl_constructor (offload_vars, v_v);
12517
12518 tree vars_decl_type = build_array_type_nelts (pointer_sized_int_node,
12519 num_vars * 2);
12520 tree funcs_decl_type = build_array_type_nelts (pointer_sized_int_node,
12521 num_funcs);
12522 TYPE_ALIGN (vars_decl_type) = TYPE_ALIGN (pointer_sized_int_node);
12523 TYPE_ALIGN (funcs_decl_type) = TYPE_ALIGN (pointer_sized_int_node);
12524 tree ctor_v = build_constructor (vars_decl_type, v_v);
12525 tree ctor_f = build_constructor (funcs_decl_type, v_f);
12526 TREE_CONSTANT (ctor_v) = TREE_CONSTANT (ctor_f) = 1;
12527 TREE_STATIC (ctor_v) = TREE_STATIC (ctor_f) = 1;
12528 tree funcs_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
12529 get_identifier (".offload_func_table"),
12530 funcs_decl_type);
12531 tree vars_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
12532 get_identifier (".offload_var_table"),
12533 vars_decl_type);
12534 TREE_STATIC (funcs_decl) = TREE_STATIC (vars_decl) = 1;
12535 /* Do not align tables more than TYPE_ALIGN (pointer_sized_int_node),
12536 otherwise a joint table in a binary will contain padding between
12537 tables from multiple object files. */
12538 DECL_USER_ALIGN (funcs_decl) = DECL_USER_ALIGN (vars_decl) = 1;
12539 DECL_ALIGN (funcs_decl) = TYPE_ALIGN (funcs_decl_type);
12540 DECL_ALIGN (vars_decl) = TYPE_ALIGN (vars_decl_type);
12541 DECL_INITIAL (funcs_decl) = ctor_f;
12542 DECL_INITIAL (vars_decl) = ctor_v;
12543 set_decl_section_name (funcs_decl, OFFLOAD_FUNC_TABLE_SECTION_NAME);
12544 set_decl_section_name (vars_decl, OFFLOAD_VAR_TABLE_SECTION_NAME);
12545
12546 varpool_node::finalize_decl (vars_decl);
12547 varpool_node::finalize_decl (funcs_decl);
7114ebdd 12548 }
dccabdd1 12549 else
12550 {
12551 for (unsigned i = 0; i < num_funcs; i++)
12552 {
12553 tree it = (*offload_funcs)[i];
12554 targetm.record_offload_symbol (it);
12555 }
12556 for (unsigned i = 0; i < num_vars; i++)
12557 {
12558 tree it = (*offload_vars)[i];
12559 targetm.record_offload_symbol (it);
12560 }
12561 }
12562}
12563
1e8e9920 12564#include "gt-omp-low.h"