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