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