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