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