]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/omp-low.c
2013-09-12 Martin Jambor <mjambor@suse.cz>
[thirdparty/gcc.git] / gcc / omp-low.c
CommitLineData
1e8e9920 1/* Lowering pass for OpenMP directives. Converts OpenMP directives
2 into explicit calls to the runtime library (libgomp) and data
3 marshalling to implement data sharing and copying clauses.
4 Contributed by Diego Novillo <dnovillo@redhat.com>
5
711789cc 6 Copyright (C) 2005-2013 Free Software Foundation, Inc.
1e8e9920 7
8This file is part of GCC.
9
10GCC is free software; you can redistribute it and/or modify it under
11the terms of the GNU General Public License as published by the Free
8c4c00c1 12Software Foundation; either version 3, or (at your option) any later
1e8e9920 13version.
14
15GCC is distributed in the hope that it will be useful, but WITHOUT ANY
16WARRANTY; without even the implied warranty of MERCHANTABILITY or
17FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18for more details.
19
20You should have received a copy of the GNU General Public License
8c4c00c1 21along with GCC; see the file COPYING3. If not see
22<http://www.gnu.org/licenses/>. */
1e8e9920 23
24#include "config.h"
25#include "system.h"
26#include "coretypes.h"
27#include "tm.h"
28#include "tree.h"
29#include "rtl.h"
75a70cf9 30#include "gimple.h"
31#include "tree-iterator.h"
1e8e9920 32#include "tree-inline.h"
33#include "langhooks.h"
852f689e 34#include "diagnostic-core.h"
1e8e9920 35#include "tree-flow.h"
1e8e9920 36#include "flags.h"
37#include "function.h"
38#include "expr.h"
1e8e9920 39#include "tree-pass.h"
40#include "ggc.h"
41#include "except.h"
e3022db7 42#include "splay-tree.h"
cb7f680b 43#include "optabs.h"
44#include "cfgloop.h"
3d483a94 45#include "target.h"
1e8e9920 46
75a70cf9 47
48e1416a 48/* Lowering of OpenMP parallel and workshare constructs proceeds in two
1e8e9920 49 phases. The first phase scans the function looking for OMP statements
50 and then for variables that must be replaced to satisfy data sharing
51 clauses. The second phase expands code for the constructs, as well as
334ec2d8 52 re-gimplifying things when variables have been replaced with complex
1e8e9920 53 expressions.
54
d134bccc 55 Final code generation is done by pass_expand_omp. The flowgraph is
56 scanned for parallel regions which are then moved to a new
57 function, to be invoked by the thread library. */
1e8e9920 58
59/* Context structure. Used to store information about each parallel
60 directive in the code. */
61
62typedef struct omp_context
63{
64 /* This field must be at the beginning, as we do "inheritance": Some
65 callback functions for tree-inline.c (e.g., omp_copy_decl)
66 receive a copy_body_data pointer that is up-casted to an
67 omp_context pointer. */
68 copy_body_data cb;
69
70 /* The tree of contexts corresponding to the encountered constructs. */
71 struct omp_context *outer;
75a70cf9 72 gimple stmt;
1e8e9920 73
48e1416a 74 /* Map variables to fields in a structure that allows communication
1e8e9920 75 between sending and receiving threads. */
76 splay_tree field_map;
77 tree record_type;
78 tree sender_decl;
79 tree receiver_decl;
80
fd6481cf 81 /* These are used just by task contexts, if task firstprivate fn is
82 needed. srecord_type is used to communicate from the thread
83 that encountered the task construct to task firstprivate fn,
84 record_type is allocated by GOMP_task, initialized by task firstprivate
85 fn and passed to the task body fn. */
86 splay_tree sfield_map;
87 tree srecord_type;
88
1e8e9920 89 /* A chain of variables to add to the top-level block surrounding the
90 construct. In the case of a parallel, this is in the child function. */
91 tree block_vars;
92
93 /* What to do with variables with implicitly determined sharing
94 attributes. */
95 enum omp_clause_default_kind default_kind;
96
97 /* Nesting depth of this context. Used to beautify error messages re
98 invalid gotos. The outermost ctx is depth 1, with depth 0 being
99 reserved for the main body of the function. */
100 int depth;
101
1e8e9920 102 /* True if this parallel directive is nested within another. */
103 bool is_nested;
1e8e9920 104} omp_context;
105
106
fd6481cf 107struct omp_for_data_loop
108{
109 tree v, n1, n2, step;
110 enum tree_code cond_code;
111};
112
773c5ba7 113/* A structure describing the main elements of a parallel loop. */
1e8e9920 114
773c5ba7 115struct omp_for_data
1e8e9920 116{
fd6481cf 117 struct omp_for_data_loop loop;
75a70cf9 118 tree chunk_size;
119 gimple for_stmt;
fd6481cf 120 tree pre, iter_type;
121 int collapse;
1e8e9920 122 bool have_nowait, have_ordered;
123 enum omp_clause_schedule_kind sched_kind;
fd6481cf 124 struct omp_for_data_loop *loops;
1e8e9920 125};
126
773c5ba7 127
1e8e9920 128static splay_tree all_contexts;
fd6481cf 129static int taskreg_nesting_level;
61e47ac8 130struct omp_region *root_omp_region;
fd6481cf 131static bitmap task_shared_vars;
1e8e9920 132
ab129075 133static void scan_omp (gimple_seq *, omp_context *);
75a70cf9 134static tree scan_omp_1_op (tree *, int *, void *);
135
136#define WALK_SUBSTMTS \
137 case GIMPLE_BIND: \
138 case GIMPLE_TRY: \
139 case GIMPLE_CATCH: \
140 case GIMPLE_EH_FILTER: \
4c0315d0 141 case GIMPLE_TRANSACTION: \
75a70cf9 142 /* The sub-statements for these should be walked. */ \
143 *handled_ops_p = false; \
144 break;
145
146/* Convenience function for calling scan_omp_1_op on tree operands. */
147
148static inline tree
149scan_omp_op (tree *tp, omp_context *ctx)
150{
151 struct walk_stmt_info wi;
152
153 memset (&wi, 0, sizeof (wi));
154 wi.info = ctx;
155 wi.want_locations = true;
156
157 return walk_tree (tp, scan_omp_1_op, &wi, NULL);
158}
159
e3a19533 160static void lower_omp (gimple_seq *, omp_context *);
f49d7bb5 161static tree lookup_decl_in_outer_ctx (tree, omp_context *);
162static tree maybe_lookup_decl_in_outer_ctx (tree, omp_context *);
1e8e9920 163
164/* Find an OpenMP clause of type KIND within CLAUSES. */
165
79acaae1 166tree
590c3166 167find_omp_clause (tree clauses, enum omp_clause_code kind)
1e8e9920 168{
169 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
55d6e7cd 170 if (OMP_CLAUSE_CODE (clauses) == kind)
1e8e9920 171 return clauses;
172
173 return NULL_TREE;
174}
175
176/* Return true if CTX is for an omp parallel. */
177
178static inline bool
179is_parallel_ctx (omp_context *ctx)
180{
75a70cf9 181 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL;
1e8e9920 182}
183
773c5ba7 184
fd6481cf 185/* Return true if CTX is for an omp task. */
186
187static inline bool
188is_task_ctx (omp_context *ctx)
189{
75a70cf9 190 return gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
fd6481cf 191}
192
193
194/* Return true if CTX is for an omp parallel or omp task. */
195
196static inline bool
197is_taskreg_ctx (omp_context *ctx)
198{
75a70cf9 199 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL
200 || gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
fd6481cf 201}
202
203
773c5ba7 204/* Return true if REGION is a combined parallel+workshare region. */
1e8e9920 205
206static inline bool
773c5ba7 207is_combined_parallel (struct omp_region *region)
208{
209 return region->is_combined_parallel;
210}
211
212
213/* Extract the header elements of parallel loop FOR_STMT and store
214 them into *FD. */
215
216static void
75a70cf9 217extract_omp_for_data (gimple for_stmt, struct omp_for_data *fd,
fd6481cf 218 struct omp_for_data_loop *loops)
773c5ba7 219{
fd6481cf 220 tree t, var, *collapse_iter, *collapse_count;
221 tree count = NULL_TREE, iter_type = long_integer_type_node;
222 struct omp_for_data_loop *loop;
223 int i;
224 struct omp_for_data_loop dummy_loop;
389dd41b 225 location_t loc = gimple_location (for_stmt);
3d483a94 226 bool simd = gimple_omp_for_kind (for_stmt) == GF_OMP_FOR_KIND_SIMD;
773c5ba7 227
228 fd->for_stmt = for_stmt;
229 fd->pre = NULL;
75a70cf9 230 fd->collapse = gimple_omp_for_collapse (for_stmt);
fd6481cf 231 if (fd->collapse > 1)
232 fd->loops = loops;
233 else
234 fd->loops = &fd->loop;
773c5ba7 235
236 fd->have_nowait = fd->have_ordered = false;
237 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
238 fd->chunk_size = NULL_TREE;
fd6481cf 239 collapse_iter = NULL;
240 collapse_count = NULL;
773c5ba7 241
75a70cf9 242 for (t = gimple_omp_for_clauses (for_stmt); t ; t = OMP_CLAUSE_CHAIN (t))
55d6e7cd 243 switch (OMP_CLAUSE_CODE (t))
773c5ba7 244 {
245 case OMP_CLAUSE_NOWAIT:
246 fd->have_nowait = true;
247 break;
248 case OMP_CLAUSE_ORDERED:
249 fd->have_ordered = true;
250 break;
251 case OMP_CLAUSE_SCHEDULE:
252 fd->sched_kind = OMP_CLAUSE_SCHEDULE_KIND (t);
253 fd->chunk_size = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t);
254 break;
fd6481cf 255 case OMP_CLAUSE_COLLAPSE:
256 if (fd->collapse > 1)
257 {
258 collapse_iter = &OMP_CLAUSE_COLLAPSE_ITERVAR (t);
259 collapse_count = &OMP_CLAUSE_COLLAPSE_COUNT (t);
260 }
773c5ba7 261 default:
262 break;
263 }
264
fd6481cf 265 /* FIXME: for now map schedule(auto) to schedule(static).
266 There should be analysis to determine whether all iterations
267 are approximately the same amount of work (then schedule(static)
bde357c8 268 is best) or if it varies (then schedule(dynamic,N) is better). */
fd6481cf 269 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_AUTO)
270 {
271 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
272 gcc_assert (fd->chunk_size == NULL);
273 }
274 gcc_assert (fd->collapse == 1 || collapse_iter != NULL);
773c5ba7 275 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
276 gcc_assert (fd->chunk_size == NULL);
277 else if (fd->chunk_size == NULL)
278 {
279 /* We only need to compute a default chunk size for ordered
280 static loops and dynamic loops. */
fd6481cf 281 if (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
282 || fd->have_ordered
283 || fd->collapse > 1)
773c5ba7 284 fd->chunk_size = (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
285 ? integer_zero_node : integer_one_node;
286 }
fd6481cf 287
288 for (i = 0; i < fd->collapse; i++)
289 {
290 if (fd->collapse == 1)
291 loop = &fd->loop;
292 else if (loops != NULL)
293 loop = loops + i;
294 else
295 loop = &dummy_loop;
296
48e1416a 297
75a70cf9 298 loop->v = gimple_omp_for_index (for_stmt, i);
fd6481cf 299 gcc_assert (SSA_VAR_P (loop->v));
300 gcc_assert (TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
301 || TREE_CODE (TREE_TYPE (loop->v)) == POINTER_TYPE);
302 var = TREE_CODE (loop->v) == SSA_NAME ? SSA_NAME_VAR (loop->v) : loop->v;
75a70cf9 303 loop->n1 = gimple_omp_for_initial (for_stmt, i);
fd6481cf 304
75a70cf9 305 loop->cond_code = gimple_omp_for_cond (for_stmt, i);
306 loop->n2 = gimple_omp_for_final (for_stmt, i);
fd6481cf 307 switch (loop->cond_code)
308 {
309 case LT_EXPR:
310 case GT_EXPR:
311 break;
312 case LE_EXPR:
313 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
2cc66f2a 314 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, 1);
fd6481cf 315 else
389dd41b 316 loop->n2 = fold_build2_loc (loc,
317 PLUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
fd6481cf 318 build_int_cst (TREE_TYPE (loop->n2), 1));
319 loop->cond_code = LT_EXPR;
320 break;
321 case GE_EXPR:
322 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
2cc66f2a 323 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, -1);
fd6481cf 324 else
389dd41b 325 loop->n2 = fold_build2_loc (loc,
326 MINUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
fd6481cf 327 build_int_cst (TREE_TYPE (loop->n2), 1));
328 loop->cond_code = GT_EXPR;
329 break;
330 default:
331 gcc_unreachable ();
332 }
333
75a70cf9 334 t = gimple_omp_for_incr (for_stmt, i);
fd6481cf 335 gcc_assert (TREE_OPERAND (t, 0) == var);
336 switch (TREE_CODE (t))
337 {
338 case PLUS_EXPR:
fd6481cf 339 loop->step = TREE_OPERAND (t, 1);
340 break;
85d86b55 341 case POINTER_PLUS_EXPR:
342 loop->step = fold_convert (ssizetype, TREE_OPERAND (t, 1));
343 break;
fd6481cf 344 case MINUS_EXPR:
345 loop->step = TREE_OPERAND (t, 1);
389dd41b 346 loop->step = fold_build1_loc (loc,
347 NEGATE_EXPR, TREE_TYPE (loop->step),
fd6481cf 348 loop->step);
349 break;
350 default:
351 gcc_unreachable ();
352 }
353
3d483a94 354 if (simd)
355 {
356 if (fd->collapse == 1)
357 iter_type = TREE_TYPE (loop->v);
358 else if (i == 0
359 || TYPE_PRECISION (iter_type)
360 < TYPE_PRECISION (TREE_TYPE (loop->v)))
361 iter_type
362 = build_nonstandard_integer_type
363 (TYPE_PRECISION (TREE_TYPE (loop->v)), 1);
364 }
365 else if (iter_type != long_long_unsigned_type_node)
fd6481cf 366 {
367 if (POINTER_TYPE_P (TREE_TYPE (loop->v)))
368 iter_type = long_long_unsigned_type_node;
369 else if (TYPE_UNSIGNED (TREE_TYPE (loop->v))
370 && TYPE_PRECISION (TREE_TYPE (loop->v))
371 >= TYPE_PRECISION (iter_type))
372 {
373 tree n;
374
375 if (loop->cond_code == LT_EXPR)
389dd41b 376 n = fold_build2_loc (loc,
377 PLUS_EXPR, TREE_TYPE (loop->v),
fd6481cf 378 loop->n2, loop->step);
379 else
380 n = loop->n1;
381 if (TREE_CODE (n) != INTEGER_CST
382 || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type), n))
383 iter_type = long_long_unsigned_type_node;
384 }
385 else if (TYPE_PRECISION (TREE_TYPE (loop->v))
386 > TYPE_PRECISION (iter_type))
387 {
388 tree n1, n2;
389
390 if (loop->cond_code == LT_EXPR)
391 {
392 n1 = loop->n1;
389dd41b 393 n2 = fold_build2_loc (loc,
394 PLUS_EXPR, TREE_TYPE (loop->v),
fd6481cf 395 loop->n2, loop->step);
396 }
397 else
398 {
389dd41b 399 n1 = fold_build2_loc (loc,
400 MINUS_EXPR, TREE_TYPE (loop->v),
fd6481cf 401 loop->n2, loop->step);
402 n2 = loop->n1;
403 }
404 if (TREE_CODE (n1) != INTEGER_CST
405 || TREE_CODE (n2) != INTEGER_CST
406 || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type), n1)
407 || !tree_int_cst_lt (n2, TYPE_MAX_VALUE (iter_type)))
408 iter_type = long_long_unsigned_type_node;
409 }
410 }
411
412 if (collapse_count && *collapse_count == NULL)
413 {
8e6b4515 414 t = fold_binary (loop->cond_code, boolean_type_node,
415 fold_convert (TREE_TYPE (loop->v), loop->n1),
416 fold_convert (TREE_TYPE (loop->v), loop->n2));
417 if (t && integer_zerop (t))
418 count = build_zero_cst (long_long_unsigned_type_node);
419 else if ((i == 0 || count != NULL_TREE)
420 && TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
421 && TREE_CONSTANT (loop->n1)
422 && TREE_CONSTANT (loop->n2)
423 && TREE_CODE (loop->step) == INTEGER_CST)
fd6481cf 424 {
425 tree itype = TREE_TYPE (loop->v);
426
427 if (POINTER_TYPE_P (itype))
3cea8318 428 itype = signed_type_for (itype);
fd6481cf 429 t = build_int_cst (itype, (loop->cond_code == LT_EXPR ? -1 : 1));
389dd41b 430 t = fold_build2_loc (loc,
431 PLUS_EXPR, itype,
432 fold_convert_loc (loc, itype, loop->step), t);
433 t = fold_build2_loc (loc, PLUS_EXPR, itype, t,
434 fold_convert_loc (loc, itype, loop->n2));
435 t = fold_build2_loc (loc, MINUS_EXPR, itype, t,
436 fold_convert_loc (loc, itype, loop->n1));
fd6481cf 437 if (TYPE_UNSIGNED (itype) && loop->cond_code == GT_EXPR)
389dd41b 438 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype,
439 fold_build1_loc (loc, NEGATE_EXPR, itype, t),
440 fold_build1_loc (loc, NEGATE_EXPR, itype,
441 fold_convert_loc (loc, itype,
442 loop->step)));
fd6481cf 443 else
389dd41b 444 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, t,
445 fold_convert_loc (loc, itype, loop->step));
446 t = fold_convert_loc (loc, long_long_unsigned_type_node, t);
fd6481cf 447 if (count != NULL_TREE)
389dd41b 448 count = fold_build2_loc (loc,
449 MULT_EXPR, long_long_unsigned_type_node,
fd6481cf 450 count, t);
451 else
452 count = t;
453 if (TREE_CODE (count) != INTEGER_CST)
454 count = NULL_TREE;
455 }
8e6b4515 456 else if (count && !integer_zerop (count))
fd6481cf 457 count = NULL_TREE;
458 }
459 }
460
3d483a94 461 if (count
462 && !simd)
fd6481cf 463 {
464 if (!tree_int_cst_lt (count, TYPE_MAX_VALUE (long_integer_type_node)))
465 iter_type = long_long_unsigned_type_node;
466 else
467 iter_type = long_integer_type_node;
468 }
469 else if (collapse_iter && *collapse_iter != NULL)
470 iter_type = TREE_TYPE (*collapse_iter);
471 fd->iter_type = iter_type;
472 if (collapse_iter && *collapse_iter == NULL)
473 *collapse_iter = create_tmp_var (iter_type, ".iter");
474 if (collapse_count && *collapse_count == NULL)
475 {
476 if (count)
389dd41b 477 *collapse_count = fold_convert_loc (loc, iter_type, count);
fd6481cf 478 else
479 *collapse_count = create_tmp_var (iter_type, ".count");
480 }
481
482 if (fd->collapse > 1)
483 {
484 fd->loop.v = *collapse_iter;
485 fd->loop.n1 = build_int_cst (TREE_TYPE (fd->loop.v), 0);
486 fd->loop.n2 = *collapse_count;
487 fd->loop.step = build_int_cst (TREE_TYPE (fd->loop.v), 1);
488 fd->loop.cond_code = LT_EXPR;
489 }
773c5ba7 490}
491
492
493/* Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB
494 is the immediate dominator of PAR_ENTRY_BB, return true if there
495 are no data dependencies that would prevent expanding the parallel
496 directive at PAR_ENTRY_BB as a combined parallel+workshare region.
497
498 When expanding a combined parallel+workshare region, the call to
499 the child function may need additional arguments in the case of
75a70cf9 500 GIMPLE_OMP_FOR regions. In some cases, these arguments are
501 computed out of variables passed in from the parent to the child
502 via 'struct .omp_data_s'. For instance:
773c5ba7 503
504 #pragma omp parallel for schedule (guided, i * 4)
505 for (j ...)
506
507 Is lowered into:
508
509 # BLOCK 2 (PAR_ENTRY_BB)
510 .omp_data_o.i = i;
511 #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
48e1416a 512
773c5ba7 513 # BLOCK 3 (WS_ENTRY_BB)
514 .omp_data_i = &.omp_data_o;
515 D.1667 = .omp_data_i->i;
516 D.1598 = D.1667 * 4;
517 #pragma omp for schedule (guided, D.1598)
518
519 When we outline the parallel region, the call to the child function
520 'bar.omp_fn.0' will need the value D.1598 in its argument list, but
521 that value is computed *after* the call site. So, in principle we
522 cannot do the transformation.
523
524 To see whether the code in WS_ENTRY_BB blocks the combined
525 parallel+workshare call, we collect all the variables used in the
75a70cf9 526 GIMPLE_OMP_FOR header check whether they appear on the LHS of any
773c5ba7 527 statement in WS_ENTRY_BB. If so, then we cannot emit the combined
528 call.
529
530 FIXME. If we had the SSA form built at this point, we could merely
531 hoist the code in block 3 into block 2 and be done with it. But at
532 this point we don't have dataflow information and though we could
533 hack something up here, it is really not worth the aggravation. */
534
535static bool
f018d957 536workshare_safe_to_combine_p (basic_block ws_entry_bb)
773c5ba7 537{
538 struct omp_for_data fd;
f018d957 539 gimple ws_stmt = last_stmt (ws_entry_bb);
773c5ba7 540
75a70cf9 541 if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
773c5ba7 542 return true;
543
75a70cf9 544 gcc_assert (gimple_code (ws_stmt) == GIMPLE_OMP_FOR);
773c5ba7 545
fd6481cf 546 extract_omp_for_data (ws_stmt, &fd, NULL);
547
548 if (fd.collapse > 1 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
549 return false;
550 if (fd.iter_type != long_integer_type_node)
551 return false;
773c5ba7 552
553 /* FIXME. We give up too easily here. If any of these arguments
554 are not constants, they will likely involve variables that have
555 been mapped into fields of .omp_data_s for sharing with the child
556 function. With appropriate data flow, it would be possible to
557 see through this. */
fd6481cf 558 if (!is_gimple_min_invariant (fd.loop.n1)
559 || !is_gimple_min_invariant (fd.loop.n2)
560 || !is_gimple_min_invariant (fd.loop.step)
773c5ba7 561 || (fd.chunk_size && !is_gimple_min_invariant (fd.chunk_size)))
562 return false;
563
564 return true;
565}
566
567
568/* Collect additional arguments needed to emit a combined
569 parallel+workshare call. WS_STMT is the workshare directive being
570 expanded. */
571
f1f41a6c 572static vec<tree, va_gc> *
75a70cf9 573get_ws_args_for (gimple ws_stmt)
773c5ba7 574{
575 tree t;
389dd41b 576 location_t loc = gimple_location (ws_stmt);
f1f41a6c 577 vec<tree, va_gc> *ws_args;
773c5ba7 578
75a70cf9 579 if (gimple_code (ws_stmt) == GIMPLE_OMP_FOR)
773c5ba7 580 {
581 struct omp_for_data fd;
773c5ba7 582
fd6481cf 583 extract_omp_for_data (ws_stmt, &fd, NULL);
773c5ba7 584
f1f41a6c 585 vec_alloc (ws_args, 3 + (fd.chunk_size != 0));
773c5ba7 586
414c3a2c 587 t = fold_convert_loc (loc, long_integer_type_node, fd.loop.n1);
f1f41a6c 588 ws_args->quick_push (t);
773c5ba7 589
389dd41b 590 t = fold_convert_loc (loc, long_integer_type_node, fd.loop.n2);
f1f41a6c 591 ws_args->quick_push (t);
773c5ba7 592
414c3a2c 593 t = fold_convert_loc (loc, long_integer_type_node, fd.loop.step);
f1f41a6c 594 ws_args->quick_push (t);
414c3a2c 595
596 if (fd.chunk_size)
597 {
598 t = fold_convert_loc (loc, long_integer_type_node, fd.chunk_size);
f1f41a6c 599 ws_args->quick_push (t);
414c3a2c 600 }
773c5ba7 601
602 return ws_args;
603 }
75a70cf9 604 else if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
773c5ba7 605 {
ac6e3339 606 /* Number of sections is equal to the number of edges from the
75a70cf9 607 GIMPLE_OMP_SECTIONS_SWITCH statement, except for the one to
608 the exit of the sections region. */
609 basic_block bb = single_succ (gimple_bb (ws_stmt));
ac6e3339 610 t = build_int_cst (unsigned_type_node, EDGE_COUNT (bb->succs) - 1);
f1f41a6c 611 vec_alloc (ws_args, 1);
612 ws_args->quick_push (t);
414c3a2c 613 return ws_args;
773c5ba7 614 }
615
616 gcc_unreachable ();
617}
618
619
620/* Discover whether REGION is a combined parallel+workshare region. */
621
622static void
623determine_parallel_type (struct omp_region *region)
1e8e9920 624{
773c5ba7 625 basic_block par_entry_bb, par_exit_bb;
626 basic_block ws_entry_bb, ws_exit_bb;
627
03ed154b 628 if (region == NULL || region->inner == NULL
ac6e3339 629 || region->exit == NULL || region->inner->exit == NULL
630 || region->inner->cont == NULL)
773c5ba7 631 return;
632
633 /* We only support parallel+for and parallel+sections. */
75a70cf9 634 if (region->type != GIMPLE_OMP_PARALLEL
635 || (region->inner->type != GIMPLE_OMP_FOR
636 && region->inner->type != GIMPLE_OMP_SECTIONS))
773c5ba7 637 return;
638
639 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
640 WS_EXIT_BB -> PAR_EXIT_BB. */
61e47ac8 641 par_entry_bb = region->entry;
642 par_exit_bb = region->exit;
643 ws_entry_bb = region->inner->entry;
644 ws_exit_bb = region->inner->exit;
773c5ba7 645
646 if (single_succ (par_entry_bb) == ws_entry_bb
647 && single_succ (ws_exit_bb) == par_exit_bb
f018d957 648 && workshare_safe_to_combine_p (ws_entry_bb)
75a70cf9 649 && (gimple_omp_parallel_combined_p (last_stmt (par_entry_bb))
de7ef844 650 || (last_and_only_stmt (ws_entry_bb)
651 && last_and_only_stmt (par_exit_bb))))
773c5ba7 652 {
75a70cf9 653 gimple ws_stmt = last_stmt (ws_entry_bb);
61e47ac8 654
75a70cf9 655 if (region->inner->type == GIMPLE_OMP_FOR)
773c5ba7 656 {
657 /* If this is a combined parallel loop, we need to determine
658 whether or not to use the combined library calls. There
659 are two cases where we do not apply the transformation:
660 static loops and any kind of ordered loop. In the first
661 case, we already open code the loop so there is no need
662 to do anything else. In the latter case, the combined
663 parallel loop call would still need extra synchronization
664 to implement ordered semantics, so there would not be any
665 gain in using the combined call. */
75a70cf9 666 tree clauses = gimple_omp_for_clauses (ws_stmt);
773c5ba7 667 tree c = find_omp_clause (clauses, OMP_CLAUSE_SCHEDULE);
668 if (c == NULL
669 || OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_STATIC
670 || find_omp_clause (clauses, OMP_CLAUSE_ORDERED))
671 {
672 region->is_combined_parallel = false;
673 region->inner->is_combined_parallel = false;
674 return;
675 }
676 }
677
678 region->is_combined_parallel = true;
679 region->inner->is_combined_parallel = true;
61e47ac8 680 region->ws_args = get_ws_args_for (ws_stmt);
773c5ba7 681 }
1e8e9920 682}
683
773c5ba7 684
1e8e9920 685/* Return true if EXPR is variable sized. */
686
687static inline bool
1f1872fd 688is_variable_sized (const_tree expr)
1e8e9920 689{
690 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr)));
691}
692
693/* Return true if DECL is a reference type. */
694
695static inline bool
696is_reference (tree decl)
697{
698 return lang_hooks.decls.omp_privatize_by_reference (decl);
699}
700
701/* Lookup variables in the decl or field splay trees. The "maybe" form
702 allows for the variable form to not have been entered, otherwise we
703 assert that the variable must have been entered. */
704
705static inline tree
706lookup_decl (tree var, omp_context *ctx)
707{
e3022db7 708 tree *n;
709 n = (tree *) pointer_map_contains (ctx->cb.decl_map, var);
710 return *n;
1e8e9920 711}
712
713static inline tree
e8a588af 714maybe_lookup_decl (const_tree var, omp_context *ctx)
1e8e9920 715{
e3022db7 716 tree *n;
717 n = (tree *) pointer_map_contains (ctx->cb.decl_map, var);
718 return n ? *n : NULL_TREE;
1e8e9920 719}
720
721static inline tree
722lookup_field (tree var, omp_context *ctx)
723{
724 splay_tree_node n;
725 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
726 return (tree) n->value;
727}
728
fd6481cf 729static inline tree
730lookup_sfield (tree var, omp_context *ctx)
731{
732 splay_tree_node n;
733 n = splay_tree_lookup (ctx->sfield_map
734 ? ctx->sfield_map : ctx->field_map,
735 (splay_tree_key) var);
736 return (tree) n->value;
737}
738
1e8e9920 739static inline tree
740maybe_lookup_field (tree var, omp_context *ctx)
741{
742 splay_tree_node n;
743 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
744 return n ? (tree) n->value : NULL_TREE;
745}
746
e8a588af 747/* Return true if DECL should be copied by pointer. SHARED_CTX is
748 the parallel context if DECL is to be shared. */
1e8e9920 749
750static bool
fd6481cf 751use_pointer_for_field (tree decl, omp_context *shared_ctx)
1e8e9920 752{
753 if (AGGREGATE_TYPE_P (TREE_TYPE (decl)))
754 return true;
755
554f2707 756 /* We can only use copy-in/copy-out semantics for shared variables
1e8e9920 757 when we know the value is not accessible from an outer scope. */
e8a588af 758 if (shared_ctx)
1e8e9920 759 {
760 /* ??? Trivially accessible from anywhere. But why would we even
761 be passing an address in this case? Should we simply assert
762 this to be false, or should we have a cleanup pass that removes
763 these from the list of mappings? */
764 if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
765 return true;
766
767 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
768 without analyzing the expression whether or not its location
769 is accessible to anyone else. In the case of nested parallel
770 regions it certainly may be. */
df2c34fc 771 if (TREE_CODE (decl) != RESULT_DECL && DECL_HAS_VALUE_EXPR_P (decl))
1e8e9920 772 return true;
773
774 /* Do not use copy-in/copy-out for variables that have their
775 address taken. */
776 if (TREE_ADDRESSABLE (decl))
777 return true;
e8a588af 778
b8214689 779 /* lower_send_shared_vars only uses copy-in, but not copy-out
780 for these. */
781 if (TREE_READONLY (decl)
782 || ((TREE_CODE (decl) == RESULT_DECL
783 || TREE_CODE (decl) == PARM_DECL)
784 && DECL_BY_REFERENCE (decl)))
785 return false;
786
e8a588af 787 /* Disallow copy-in/out in nested parallel if
788 decl is shared in outer parallel, otherwise
789 each thread could store the shared variable
790 in its own copy-in location, making the
791 variable no longer really shared. */
b8214689 792 if (shared_ctx->is_nested)
e8a588af 793 {
794 omp_context *up;
795
796 for (up = shared_ctx->outer; up; up = up->outer)
0cb159ec 797 if (is_taskreg_ctx (up) && maybe_lookup_decl (decl, up))
e8a588af 798 break;
799
0cb159ec 800 if (up)
e8a588af 801 {
802 tree c;
803
75a70cf9 804 for (c = gimple_omp_taskreg_clauses (up->stmt);
e8a588af 805 c; c = OMP_CLAUSE_CHAIN (c))
806 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
807 && OMP_CLAUSE_DECL (c) == decl)
808 break;
809
810 if (c)
784ad964 811 goto maybe_mark_addressable_and_ret;
e8a588af 812 }
813 }
fd6481cf 814
b8214689 815 /* For tasks avoid using copy-in/out. As tasks can be
fd6481cf 816 deferred or executed in different thread, when GOMP_task
817 returns, the task hasn't necessarily terminated. */
b8214689 818 if (is_task_ctx (shared_ctx))
fd6481cf 819 {
784ad964 820 tree outer;
821 maybe_mark_addressable_and_ret:
822 outer = maybe_lookup_decl_in_outer_ctx (decl, shared_ctx);
fd6481cf 823 if (is_gimple_reg (outer))
824 {
825 /* Taking address of OUTER in lower_send_shared_vars
826 might need regimplification of everything that uses the
827 variable. */
828 if (!task_shared_vars)
829 task_shared_vars = BITMAP_ALLOC (NULL);
830 bitmap_set_bit (task_shared_vars, DECL_UID (outer));
831 TREE_ADDRESSABLE (outer) = 1;
832 }
833 return true;
834 }
1e8e9920 835 }
836
837 return false;
838}
839
79acaae1 840/* Create a new VAR_DECL and copy information from VAR to it. */
1e8e9920 841
79acaae1 842tree
843copy_var_decl (tree var, tree name, tree type)
1e8e9920 844{
e60a6f7b 845 tree copy = build_decl (DECL_SOURCE_LOCATION (var), VAR_DECL, name, type);
1e8e9920 846
847 TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (var);
79acaae1 848 TREE_THIS_VOLATILE (copy) = TREE_THIS_VOLATILE (var);
8ea8de24 849 DECL_GIMPLE_REG_P (copy) = DECL_GIMPLE_REG_P (var);
1e8e9920 850 DECL_ARTIFICIAL (copy) = DECL_ARTIFICIAL (var);
851 DECL_IGNORED_P (copy) = DECL_IGNORED_P (var);
79acaae1 852 DECL_CONTEXT (copy) = DECL_CONTEXT (var);
34d8484d 853 TREE_NO_WARNING (copy) = TREE_NO_WARNING (var);
1e8e9920 854 TREE_USED (copy) = 1;
1e8e9920 855 DECL_SEEN_IN_BIND_EXPR_P (copy) = 1;
856
79acaae1 857 return copy;
858}
859
860/* Construct a new automatic decl similar to VAR. */
861
862static tree
863omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx)
864{
865 tree copy = copy_var_decl (var, name, type);
866
867 DECL_CONTEXT (copy) = current_function_decl;
1767a056 868 DECL_CHAIN (copy) = ctx->block_vars;
1e8e9920 869 ctx->block_vars = copy;
870
871 return copy;
872}
873
874static tree
875omp_copy_decl_1 (tree var, omp_context *ctx)
876{
877 return omp_copy_decl_2 (var, DECL_NAME (var), TREE_TYPE (var), ctx);
878}
879
445d06b6 880/* Build COMPONENT_REF and set TREE_THIS_VOLATILE and TREE_READONLY on it
881 as appropriate. */
882static tree
883omp_build_component_ref (tree obj, tree field)
884{
885 tree ret = build3 (COMPONENT_REF, TREE_TYPE (field), obj, field, NULL);
886 if (TREE_THIS_VOLATILE (field))
887 TREE_THIS_VOLATILE (ret) |= 1;
888 if (TREE_READONLY (field))
889 TREE_READONLY (ret) |= 1;
890 return ret;
891}
892
1e8e9920 893/* Build tree nodes to access the field for VAR on the receiver side. */
894
895static tree
896build_receiver_ref (tree var, bool by_ref, omp_context *ctx)
897{
898 tree x, field = lookup_field (var, ctx);
899
900 /* If the receiver record type was remapped in the child function,
901 remap the field into the new record type. */
902 x = maybe_lookup_field (field, ctx);
903 if (x != NULL)
904 field = x;
905
182cf5a9 906 x = build_simple_mem_ref (ctx->receiver_decl);
445d06b6 907 x = omp_build_component_ref (x, field);
1e8e9920 908 if (by_ref)
182cf5a9 909 x = build_simple_mem_ref (x);
1e8e9920 910
911 return x;
912}
913
914/* Build tree nodes to access VAR in the scope outer to CTX. In the case
915 of a parallel, this is a component reference; for workshare constructs
916 this is some variable. */
917
918static tree
919build_outer_var_ref (tree var, omp_context *ctx)
920{
921 tree x;
922
f49d7bb5 923 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx)))
1e8e9920 924 x = var;
925 else if (is_variable_sized (var))
926 {
927 x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
928 x = build_outer_var_ref (x, ctx);
182cf5a9 929 x = build_simple_mem_ref (x);
1e8e9920 930 }
fd6481cf 931 else if (is_taskreg_ctx (ctx))
1e8e9920 932 {
e8a588af 933 bool by_ref = use_pointer_for_field (var, NULL);
1e8e9920 934 x = build_receiver_ref (var, by_ref, ctx);
935 }
3d483a94 936 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
937 && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD)
938 {
939 /* #pragma omp simd isn't a worksharing construct, and can reference even
940 private vars in its linear etc. clauses. */
941 x = NULL_TREE;
942 if (ctx->outer && is_taskreg_ctx (ctx))
943 x = lookup_decl (var, ctx->outer);
944 else if (ctx->outer)
945 x = maybe_lookup_decl (var, ctx->outer);
946 if (x == NULL_TREE)
947 x = var;
948 }
1e8e9920 949 else if (ctx->outer)
950 x = lookup_decl (var, ctx->outer);
9438af57 951 else if (is_reference (var))
952 /* This can happen with orphaned constructs. If var is reference, it is
953 possible it is shared and as such valid. */
954 x = var;
1e8e9920 955 else
956 gcc_unreachable ();
957
958 if (is_reference (var))
182cf5a9 959 x = build_simple_mem_ref (x);
1e8e9920 960
961 return x;
962}
963
964/* Build tree nodes to access the field for VAR on the sender side. */
965
966static tree
967build_sender_ref (tree var, omp_context *ctx)
968{
fd6481cf 969 tree field = lookup_sfield (var, ctx);
445d06b6 970 return omp_build_component_ref (ctx->sender_decl, field);
1e8e9920 971}
972
973/* Add a new field for VAR inside the structure CTX->SENDER_DECL. */
974
975static void
fd6481cf 976install_var_field (tree var, bool by_ref, int mask, omp_context *ctx)
1e8e9920 977{
fd6481cf 978 tree field, type, sfield = NULL_TREE;
1e8e9920 979
fd6481cf 980 gcc_assert ((mask & 1) == 0
981 || !splay_tree_lookup (ctx->field_map, (splay_tree_key) var));
982 gcc_assert ((mask & 2) == 0 || !ctx->sfield_map
983 || !splay_tree_lookup (ctx->sfield_map, (splay_tree_key) var));
1e8e9920 984
985 type = TREE_TYPE (var);
986 if (by_ref)
987 type = build_pointer_type (type);
fd6481cf 988 else if ((mask & 3) == 1 && is_reference (var))
989 type = TREE_TYPE (type);
1e8e9920 990
e60a6f7b 991 field = build_decl (DECL_SOURCE_LOCATION (var),
992 FIELD_DECL, DECL_NAME (var), type);
1e8e9920 993
994 /* Remember what variable this field was created for. This does have a
995 side effect of making dwarf2out ignore this member, so for helpful
996 debugging we clear it later in delete_omp_context. */
997 DECL_ABSTRACT_ORIGIN (field) = var;
fd6481cf 998 if (type == TREE_TYPE (var))
999 {
1000 DECL_ALIGN (field) = DECL_ALIGN (var);
1001 DECL_USER_ALIGN (field) = DECL_USER_ALIGN (var);
1002 TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (var);
1003 }
1004 else
1005 DECL_ALIGN (field) = TYPE_ALIGN (type);
1e8e9920 1006
fd6481cf 1007 if ((mask & 3) == 3)
1008 {
1009 insert_field_into_struct (ctx->record_type, field);
1010 if (ctx->srecord_type)
1011 {
e60a6f7b 1012 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1013 FIELD_DECL, DECL_NAME (var), type);
fd6481cf 1014 DECL_ABSTRACT_ORIGIN (sfield) = var;
1015 DECL_ALIGN (sfield) = DECL_ALIGN (field);
1016 DECL_USER_ALIGN (sfield) = DECL_USER_ALIGN (field);
1017 TREE_THIS_VOLATILE (sfield) = TREE_THIS_VOLATILE (field);
1018 insert_field_into_struct (ctx->srecord_type, sfield);
1019 }
1020 }
1021 else
1022 {
1023 if (ctx->srecord_type == NULL_TREE)
1024 {
1025 tree t;
1026
1027 ctx->srecord_type = lang_hooks.types.make_type (RECORD_TYPE);
1028 ctx->sfield_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1029 for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
1030 {
e60a6f7b 1031 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1032 FIELD_DECL, DECL_NAME (t), TREE_TYPE (t));
fd6481cf 1033 DECL_ABSTRACT_ORIGIN (sfield) = DECL_ABSTRACT_ORIGIN (t);
1034 insert_field_into_struct (ctx->srecord_type, sfield);
1035 splay_tree_insert (ctx->sfield_map,
1036 (splay_tree_key) DECL_ABSTRACT_ORIGIN (t),
1037 (splay_tree_value) sfield);
1038 }
1039 }
1040 sfield = field;
1041 insert_field_into_struct ((mask & 1) ? ctx->record_type
1042 : ctx->srecord_type, field);
1043 }
1e8e9920 1044
fd6481cf 1045 if (mask & 1)
1046 splay_tree_insert (ctx->field_map, (splay_tree_key) var,
1047 (splay_tree_value) field);
1048 if ((mask & 2) && ctx->sfield_map)
1049 splay_tree_insert (ctx->sfield_map, (splay_tree_key) var,
1050 (splay_tree_value) sfield);
1e8e9920 1051}
1052
1053static tree
1054install_var_local (tree var, omp_context *ctx)
1055{
1056 tree new_var = omp_copy_decl_1 (var, ctx);
1057 insert_decl_map (&ctx->cb, var, new_var);
1058 return new_var;
1059}
1060
1061/* Adjust the replacement for DECL in CTX for the new context. This means
1062 copying the DECL_VALUE_EXPR, and fixing up the type. */
1063
1064static void
1065fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug)
1066{
1067 tree new_decl, size;
1068
1069 new_decl = lookup_decl (decl, ctx);
1070
1071 TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb);
1072
1073 if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug)
1074 && DECL_HAS_VALUE_EXPR_P (decl))
1075 {
1076 tree ve = DECL_VALUE_EXPR (decl);
75a70cf9 1077 walk_tree (&ve, copy_tree_body_r, &ctx->cb, NULL);
1e8e9920 1078 SET_DECL_VALUE_EXPR (new_decl, ve);
1079 DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
1080 }
1081
1082 if (!TREE_CONSTANT (DECL_SIZE (new_decl)))
1083 {
1084 size = remap_decl (DECL_SIZE (decl), &ctx->cb);
1085 if (size == error_mark_node)
1086 size = TYPE_SIZE (TREE_TYPE (new_decl));
1087 DECL_SIZE (new_decl) = size;
1088
1089 size = remap_decl (DECL_SIZE_UNIT (decl), &ctx->cb);
1090 if (size == error_mark_node)
1091 size = TYPE_SIZE_UNIT (TREE_TYPE (new_decl));
1092 DECL_SIZE_UNIT (new_decl) = size;
1093 }
1094}
1095
1096/* The callback for remap_decl. Search all containing contexts for a
1097 mapping of the variable; this avoids having to duplicate the splay
1098 tree ahead of time. We know a mapping doesn't already exist in the
1099 given context. Create new mappings to implement default semantics. */
1100
1101static tree
1102omp_copy_decl (tree var, copy_body_data *cb)
1103{
1104 omp_context *ctx = (omp_context *) cb;
1105 tree new_var;
1106
1e8e9920 1107 if (TREE_CODE (var) == LABEL_DECL)
1108 {
e60a6f7b 1109 new_var = create_artificial_label (DECL_SOURCE_LOCATION (var));
773c5ba7 1110 DECL_CONTEXT (new_var) = current_function_decl;
1e8e9920 1111 insert_decl_map (&ctx->cb, var, new_var);
1112 return new_var;
1113 }
1114
fd6481cf 1115 while (!is_taskreg_ctx (ctx))
1e8e9920 1116 {
1117 ctx = ctx->outer;
1118 if (ctx == NULL)
1119 return var;
1120 new_var = maybe_lookup_decl (var, ctx);
1121 if (new_var)
1122 return new_var;
1123 }
1124
f49d7bb5 1125 if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn)
1126 return var;
1127
1e8e9920 1128 return error_mark_node;
1129}
1130
773c5ba7 1131
1132/* Return the parallel region associated with STMT. */
1133
773c5ba7 1134/* Debugging dumps for parallel regions. */
1135void dump_omp_region (FILE *, struct omp_region *, int);
1136void debug_omp_region (struct omp_region *);
1137void debug_all_omp_regions (void);
1138
1139/* Dump the parallel region tree rooted at REGION. */
1140
1141void
1142dump_omp_region (FILE *file, struct omp_region *region, int indent)
1143{
61e47ac8 1144 fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index,
75a70cf9 1145 gimple_code_name[region->type]);
773c5ba7 1146
1147 if (region->inner)
1148 dump_omp_region (file, region->inner, indent + 4);
1149
61e47ac8 1150 if (region->cont)
1151 {
75a70cf9 1152 fprintf (file, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent, "",
61e47ac8 1153 region->cont->index);
1154 }
48e1416a 1155
773c5ba7 1156 if (region->exit)
75a70cf9 1157 fprintf (file, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent, "",
61e47ac8 1158 region->exit->index);
773c5ba7 1159 else
61e47ac8 1160 fprintf (file, "%*s[no exit marker]\n", indent, "");
773c5ba7 1161
1162 if (region->next)
61e47ac8 1163 dump_omp_region (file, region->next, indent);
773c5ba7 1164}
1165
4b987fac 1166DEBUG_FUNCTION void
773c5ba7 1167debug_omp_region (struct omp_region *region)
1168{
1169 dump_omp_region (stderr, region, 0);
1170}
1171
4b987fac 1172DEBUG_FUNCTION void
773c5ba7 1173debug_all_omp_regions (void)
1174{
1175 dump_omp_region (stderr, root_omp_region, 0);
1176}
1177
1178
1179/* Create a new parallel region starting at STMT inside region PARENT. */
1180
61e47ac8 1181struct omp_region *
75a70cf9 1182new_omp_region (basic_block bb, enum gimple_code type,
1183 struct omp_region *parent)
773c5ba7 1184{
4077bf7a 1185 struct omp_region *region = XCNEW (struct omp_region);
773c5ba7 1186
1187 region->outer = parent;
61e47ac8 1188 region->entry = bb;
1189 region->type = type;
773c5ba7 1190
1191 if (parent)
1192 {
1193 /* This is a nested region. Add it to the list of inner
1194 regions in PARENT. */
1195 region->next = parent->inner;
1196 parent->inner = region;
1197 }
61e47ac8 1198 else
773c5ba7 1199 {
1200 /* This is a toplevel region. Add it to the list of toplevel
1201 regions in ROOT_OMP_REGION. */
1202 region->next = root_omp_region;
1203 root_omp_region = region;
1204 }
61e47ac8 1205
1206 return region;
1207}
1208
1209/* Release the memory associated with the region tree rooted at REGION. */
1210
1211static void
1212free_omp_region_1 (struct omp_region *region)
1213{
1214 struct omp_region *i, *n;
1215
1216 for (i = region->inner; i ; i = n)
773c5ba7 1217 {
61e47ac8 1218 n = i->next;
1219 free_omp_region_1 (i);
773c5ba7 1220 }
1221
61e47ac8 1222 free (region);
1223}
773c5ba7 1224
61e47ac8 1225/* Release the memory for the entire omp region tree. */
1226
1227void
1228free_omp_regions (void)
1229{
1230 struct omp_region *r, *n;
1231 for (r = root_omp_region; r ; r = n)
1232 {
1233 n = r->next;
1234 free_omp_region_1 (r);
1235 }
1236 root_omp_region = NULL;
773c5ba7 1237}
1238
1239
1e8e9920 1240/* Create a new context, with OUTER_CTX being the surrounding context. */
1241
1242static omp_context *
75a70cf9 1243new_omp_context (gimple stmt, omp_context *outer_ctx)
1e8e9920 1244{
1245 omp_context *ctx = XCNEW (omp_context);
1246
1247 splay_tree_insert (all_contexts, (splay_tree_key) stmt,
1248 (splay_tree_value) ctx);
1249 ctx->stmt = stmt;
1250
1251 if (outer_ctx)
1252 {
1253 ctx->outer = outer_ctx;
1254 ctx->cb = outer_ctx->cb;
1255 ctx->cb.block = NULL;
1256 ctx->depth = outer_ctx->depth + 1;
1257 }
1258 else
1259 {
1260 ctx->cb.src_fn = current_function_decl;
1261 ctx->cb.dst_fn = current_function_decl;
53f79206 1262 ctx->cb.src_node = cgraph_get_node (current_function_decl);
1263 gcc_checking_assert (ctx->cb.src_node);
1e8e9920 1264 ctx->cb.dst_node = ctx->cb.src_node;
1265 ctx->cb.src_cfun = cfun;
1266 ctx->cb.copy_decl = omp_copy_decl;
e38def9c 1267 ctx->cb.eh_lp_nr = 0;
1e8e9920 1268 ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
1269 ctx->depth = 1;
1270 }
1271
e3022db7 1272 ctx->cb.decl_map = pointer_map_create ();
1e8e9920 1273
1274 return ctx;
1275}
1276
75a70cf9 1277static gimple_seq maybe_catch_exception (gimple_seq);
f6430caa 1278
1279/* Finalize task copyfn. */
1280
1281static void
75a70cf9 1282finalize_task_copyfn (gimple task_stmt)
f6430caa 1283{
1284 struct function *child_cfun;
9078126c 1285 tree child_fn;
e3a19533 1286 gimple_seq seq = NULL, new_seq;
75a70cf9 1287 gimple bind;
f6430caa 1288
75a70cf9 1289 child_fn = gimple_omp_task_copy_fn (task_stmt);
f6430caa 1290 if (child_fn == NULL_TREE)
1291 return;
1292
1293 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
82b40354 1294 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
f6430caa 1295
f6430caa 1296 push_cfun (child_cfun);
7e3aae05 1297 bind = gimplify_body (child_fn, false);
75a70cf9 1298 gimple_seq_add_stmt (&seq, bind);
1299 new_seq = maybe_catch_exception (seq);
1300 if (new_seq != seq)
1301 {
1302 bind = gimple_build_bind (NULL, new_seq, NULL);
e3a19533 1303 seq = NULL;
75a70cf9 1304 gimple_seq_add_stmt (&seq, bind);
1305 }
1306 gimple_set_body (child_fn, seq);
f6430caa 1307 pop_cfun ();
f6430caa 1308
82b40354 1309 /* Inform the callgraph about the new function. */
f6430caa 1310 cgraph_add_new_function (child_fn, false);
1311}
1312
1e8e9920 1313/* Destroy a omp_context data structures. Called through the splay tree
1314 value delete callback. */
1315
1316static void
1317delete_omp_context (splay_tree_value value)
1318{
1319 omp_context *ctx = (omp_context *) value;
1320
e3022db7 1321 pointer_map_destroy (ctx->cb.decl_map);
1e8e9920 1322
1323 if (ctx->field_map)
1324 splay_tree_delete (ctx->field_map);
fd6481cf 1325 if (ctx->sfield_map)
1326 splay_tree_delete (ctx->sfield_map);
1e8e9920 1327
1328 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
1329 it produces corrupt debug information. */
1330 if (ctx->record_type)
1331 {
1332 tree t;
1767a056 1333 for (t = TYPE_FIELDS (ctx->record_type); t ; t = DECL_CHAIN (t))
1e8e9920 1334 DECL_ABSTRACT_ORIGIN (t) = NULL;
1335 }
fd6481cf 1336 if (ctx->srecord_type)
1337 {
1338 tree t;
1767a056 1339 for (t = TYPE_FIELDS (ctx->srecord_type); t ; t = DECL_CHAIN (t))
fd6481cf 1340 DECL_ABSTRACT_ORIGIN (t) = NULL;
1341 }
1e8e9920 1342
f6430caa 1343 if (is_task_ctx (ctx))
1344 finalize_task_copyfn (ctx->stmt);
1345
1e8e9920 1346 XDELETE (ctx);
1347}
1348
1349/* Fix up RECEIVER_DECL with a type that has been remapped to the child
1350 context. */
1351
1352static void
1353fixup_child_record_type (omp_context *ctx)
1354{
1355 tree f, type = ctx->record_type;
1356
1357 /* ??? It isn't sufficient to just call remap_type here, because
1358 variably_modified_type_p doesn't work the way we expect for
1359 record types. Testing each field for whether it needs remapping
1360 and creating a new record by hand works, however. */
1767a056 1361 for (f = TYPE_FIELDS (type); f ; f = DECL_CHAIN (f))
1e8e9920 1362 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
1363 break;
1364 if (f)
1365 {
1366 tree name, new_fields = NULL;
1367
1368 type = lang_hooks.types.make_type (RECORD_TYPE);
1369 name = DECL_NAME (TYPE_NAME (ctx->record_type));
e60a6f7b 1370 name = build_decl (DECL_SOURCE_LOCATION (ctx->receiver_decl),
1371 TYPE_DECL, name, type);
1e8e9920 1372 TYPE_NAME (type) = name;
1373
1767a056 1374 for (f = TYPE_FIELDS (ctx->record_type); f ; f = DECL_CHAIN (f))
1e8e9920 1375 {
1376 tree new_f = copy_node (f);
1377 DECL_CONTEXT (new_f) = type;
1378 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
1767a056 1379 DECL_CHAIN (new_f) = new_fields;
75a70cf9 1380 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &ctx->cb, NULL);
1381 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r,
1382 &ctx->cb, NULL);
1383 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
1384 &ctx->cb, NULL);
1e8e9920 1385 new_fields = new_f;
1386
1387 /* Arrange to be able to look up the receiver field
1388 given the sender field. */
1389 splay_tree_insert (ctx->field_map, (splay_tree_key) f,
1390 (splay_tree_value) new_f);
1391 }
1392 TYPE_FIELDS (type) = nreverse (new_fields);
1393 layout_type (type);
1394 }
1395
1396 TREE_TYPE (ctx->receiver_decl) = build_pointer_type (type);
1397}
1398
1399/* Instantiate decls as necessary in CTX to satisfy the data sharing
1400 specified by CLAUSES. */
1401
1402static void
1403scan_sharing_clauses (tree clauses, omp_context *ctx)
1404{
1405 tree c, decl;
1406 bool scan_array_reductions = false;
1407
1408 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1409 {
1410 bool by_ref;
1411
55d6e7cd 1412 switch (OMP_CLAUSE_CODE (c))
1e8e9920 1413 {
1414 case OMP_CLAUSE_PRIVATE:
1415 decl = OMP_CLAUSE_DECL (c);
fd6481cf 1416 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
1417 goto do_private;
1418 else if (!is_variable_sized (decl))
1e8e9920 1419 install_var_local (decl, ctx);
1420 break;
1421
1422 case OMP_CLAUSE_SHARED:
fd6481cf 1423 gcc_assert (is_taskreg_ctx (ctx));
1e8e9920 1424 decl = OMP_CLAUSE_DECL (c);
e7327393 1425 gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl))
1426 || !is_variable_sized (decl));
f49d7bb5 1427 /* Global variables don't need to be copied,
1428 the receiver side will use them directly. */
1429 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1430 break;
fd6481cf 1431 by_ref = use_pointer_for_field (decl, ctx);
1e8e9920 1432 if (! TREE_READONLY (decl)
1433 || TREE_ADDRESSABLE (decl)
1434 || by_ref
1435 || is_reference (decl))
1436 {
fd6481cf 1437 install_var_field (decl, by_ref, 3, ctx);
1e8e9920 1438 install_var_local (decl, ctx);
1439 break;
1440 }
1441 /* We don't need to copy const scalar vars back. */
55d6e7cd 1442 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
1e8e9920 1443 goto do_private;
1444
1445 case OMP_CLAUSE_LASTPRIVATE:
1446 /* Let the corresponding firstprivate clause create
1447 the variable. */
1448 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1449 break;
1450 /* FALLTHRU */
1451
1452 case OMP_CLAUSE_FIRSTPRIVATE:
1453 case OMP_CLAUSE_REDUCTION:
3d483a94 1454 case OMP_CLAUSE_LINEAR:
1e8e9920 1455 decl = OMP_CLAUSE_DECL (c);
1456 do_private:
1457 if (is_variable_sized (decl))
1e8e9920 1458 {
fd6481cf 1459 if (is_task_ctx (ctx))
1460 install_var_field (decl, false, 1, ctx);
1461 break;
1462 }
1463 else if (is_taskreg_ctx (ctx))
1464 {
1465 bool global
1466 = is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx));
e8a588af 1467 by_ref = use_pointer_for_field (decl, NULL);
fd6481cf 1468
1469 if (is_task_ctx (ctx)
1470 && (global || by_ref || is_reference (decl)))
1471 {
1472 install_var_field (decl, false, 1, ctx);
1473 if (!global)
1474 install_var_field (decl, by_ref, 2, ctx);
1475 }
1476 else if (!global)
1477 install_var_field (decl, by_ref, 3, ctx);
1e8e9920 1478 }
1479 install_var_local (decl, ctx);
1480 break;
1481
1482 case OMP_CLAUSE_COPYPRIVATE:
1e8e9920 1483 case OMP_CLAUSE_COPYIN:
1484 decl = OMP_CLAUSE_DECL (c);
e8a588af 1485 by_ref = use_pointer_for_field (decl, NULL);
fd6481cf 1486 install_var_field (decl, by_ref, 3, ctx);
1e8e9920 1487 break;
1488
1489 case OMP_CLAUSE_DEFAULT:
1490 ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
1491 break;
1492
2169f33b 1493 case OMP_CLAUSE_FINAL:
1e8e9920 1494 case OMP_CLAUSE_IF:
1495 case OMP_CLAUSE_NUM_THREADS:
1496 case OMP_CLAUSE_SCHEDULE:
1497 if (ctx->outer)
75a70cf9 1498 scan_omp_op (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
1e8e9920 1499 break;
1500
1501 case OMP_CLAUSE_NOWAIT:
1502 case OMP_CLAUSE_ORDERED:
fd6481cf 1503 case OMP_CLAUSE_COLLAPSE:
1504 case OMP_CLAUSE_UNTIED:
2169f33b 1505 case OMP_CLAUSE_MERGEABLE:
3d483a94 1506 case OMP_CLAUSE_SAFELEN:
1e8e9920 1507 break;
1508
1509 default:
1510 gcc_unreachable ();
1511 }
1512 }
1513
1514 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1515 {
55d6e7cd 1516 switch (OMP_CLAUSE_CODE (c))
1e8e9920 1517 {
1518 case OMP_CLAUSE_LASTPRIVATE:
1519 /* Let the corresponding firstprivate clause create
1520 the variable. */
75a70cf9 1521 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
fd6481cf 1522 scan_array_reductions = true;
1e8e9920 1523 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1524 break;
1525 /* FALLTHRU */
1526
1527 case OMP_CLAUSE_PRIVATE:
1528 case OMP_CLAUSE_FIRSTPRIVATE:
1529 case OMP_CLAUSE_REDUCTION:
3d483a94 1530 case OMP_CLAUSE_LINEAR:
1e8e9920 1531 decl = OMP_CLAUSE_DECL (c);
1532 if (is_variable_sized (decl))
1533 install_var_local (decl, ctx);
1534 fixup_remapped_decl (decl, ctx,
55d6e7cd 1535 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
1e8e9920 1536 && OMP_CLAUSE_PRIVATE_DEBUG (c));
55d6e7cd 1537 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1e8e9920 1538 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1539 scan_array_reductions = true;
1540 break;
1541
1542 case OMP_CLAUSE_SHARED:
1543 decl = OMP_CLAUSE_DECL (c);
f49d7bb5 1544 if (! is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1545 fixup_remapped_decl (decl, ctx, false);
1e8e9920 1546 break;
1547
1548 case OMP_CLAUSE_COPYPRIVATE:
1549 case OMP_CLAUSE_COPYIN:
1550 case OMP_CLAUSE_DEFAULT:
1551 case OMP_CLAUSE_IF:
1552 case OMP_CLAUSE_NUM_THREADS:
1553 case OMP_CLAUSE_SCHEDULE:
1554 case OMP_CLAUSE_NOWAIT:
1555 case OMP_CLAUSE_ORDERED:
fd6481cf 1556 case OMP_CLAUSE_COLLAPSE:
1557 case OMP_CLAUSE_UNTIED:
2169f33b 1558 case OMP_CLAUSE_FINAL:
1559 case OMP_CLAUSE_MERGEABLE:
3d483a94 1560 case OMP_CLAUSE_SAFELEN:
1e8e9920 1561 break;
1562
1563 default:
1564 gcc_unreachable ();
1565 }
1566 }
1567
1568 if (scan_array_reductions)
1569 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
55d6e7cd 1570 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1e8e9920 1571 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1572 {
ab129075 1573 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
1574 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
1e8e9920 1575 }
fd6481cf 1576 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
75a70cf9 1577 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
ab129075 1578 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
1e8e9920 1579}
1580
1581/* Create a new name for omp child function. Returns an identifier. */
1582
1583static GTY(()) unsigned int tmp_ompfn_id_num;
1584
1585static tree
fd6481cf 1586create_omp_child_function_name (bool task_copy)
1e8e9920 1587{
a70a5e2c 1588 return (clone_function_name (current_function_decl,
1589 task_copy ? "_omp_cpyfn" : "_omp_fn"));
1e8e9920 1590}
1591
1592/* Build a decl for the omp child function. It'll not contain a body
1593 yet, just the bare decl. */
1594
1595static void
fd6481cf 1596create_omp_child_function (omp_context *ctx, bool task_copy)
1e8e9920 1597{
1598 tree decl, type, name, t;
1599
fd6481cf 1600 name = create_omp_child_function_name (task_copy);
1601 if (task_copy)
1602 type = build_function_type_list (void_type_node, ptr_type_node,
1603 ptr_type_node, NULL_TREE);
1604 else
1605 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
1e8e9920 1606
e60a6f7b 1607 decl = build_decl (gimple_location (ctx->stmt),
1608 FUNCTION_DECL, name, type);
1e8e9920 1609
fd6481cf 1610 if (!task_copy)
1611 ctx->cb.dst_fn = decl;
1612 else
75a70cf9 1613 gimple_omp_task_set_copy_fn (ctx->stmt, decl);
1e8e9920 1614
1615 TREE_STATIC (decl) = 1;
1616 TREE_USED (decl) = 1;
1617 DECL_ARTIFICIAL (decl) = 1;
84bfaaeb 1618 DECL_NAMELESS (decl) = 1;
1e8e9920 1619 DECL_IGNORED_P (decl) = 0;
1620 TREE_PUBLIC (decl) = 0;
1621 DECL_UNINLINABLE (decl) = 1;
1622 DECL_EXTERNAL (decl) = 0;
1623 DECL_CONTEXT (decl) = NULL_TREE;
773c5ba7 1624 DECL_INITIAL (decl) = make_node (BLOCK);
1e8e9920 1625
e60a6f7b 1626 t = build_decl (DECL_SOURCE_LOCATION (decl),
1627 RESULT_DECL, NULL_TREE, void_type_node);
1e8e9920 1628 DECL_ARTIFICIAL (t) = 1;
1629 DECL_IGNORED_P (t) = 1;
8e5b4ed6 1630 DECL_CONTEXT (t) = decl;
1e8e9920 1631 DECL_RESULT (decl) = t;
1632
e60a6f7b 1633 t = build_decl (DECL_SOURCE_LOCATION (decl),
1634 PARM_DECL, get_identifier (".omp_data_i"), ptr_type_node);
1e8e9920 1635 DECL_ARTIFICIAL (t) = 1;
84bfaaeb 1636 DECL_NAMELESS (t) = 1;
1e8e9920 1637 DECL_ARG_TYPE (t) = ptr_type_node;
773c5ba7 1638 DECL_CONTEXT (t) = current_function_decl;
1e8e9920 1639 TREE_USED (t) = 1;
1640 DECL_ARGUMENTS (decl) = t;
fd6481cf 1641 if (!task_copy)
1642 ctx->receiver_decl = t;
1643 else
1644 {
e60a6f7b 1645 t = build_decl (DECL_SOURCE_LOCATION (decl),
1646 PARM_DECL, get_identifier (".omp_data_o"),
fd6481cf 1647 ptr_type_node);
1648 DECL_ARTIFICIAL (t) = 1;
84bfaaeb 1649 DECL_NAMELESS (t) = 1;
fd6481cf 1650 DECL_ARG_TYPE (t) = ptr_type_node;
1651 DECL_CONTEXT (t) = current_function_decl;
1652 TREE_USED (t) = 1;
86f2ad37 1653 TREE_ADDRESSABLE (t) = 1;
1767a056 1654 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
fd6481cf 1655 DECL_ARGUMENTS (decl) = t;
1656 }
1e8e9920 1657
48e1416a 1658 /* Allocate memory for the function structure. The call to
773c5ba7 1659 allocate_struct_function clobbers CFUN, so we need to restore
1e8e9920 1660 it afterward. */
87d4aa85 1661 push_struct_function (decl);
75a70cf9 1662 cfun->function_end_locus = gimple_location (ctx->stmt);
87d4aa85 1663 pop_cfun ();
1e8e9920 1664}
1665
1e8e9920 1666/* Scan an OpenMP parallel directive. */
1667
1668static void
75a70cf9 1669scan_omp_parallel (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
1e8e9920 1670{
1671 omp_context *ctx;
1672 tree name;
75a70cf9 1673 gimple stmt = gsi_stmt (*gsi);
1e8e9920 1674
1675 /* Ignore parallel directives with empty bodies, unless there
1676 are copyin clauses. */
1677 if (optimize > 0
75a70cf9 1678 && empty_body_p (gimple_omp_body (stmt))
1679 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
1680 OMP_CLAUSE_COPYIN) == NULL)
1e8e9920 1681 {
75a70cf9 1682 gsi_replace (gsi, gimple_build_nop (), false);
1e8e9920 1683 return;
1684 }
1685
75a70cf9 1686 ctx = new_omp_context (stmt, outer_ctx);
fd6481cf 1687 if (taskreg_nesting_level > 1)
773c5ba7 1688 ctx->is_nested = true;
1e8e9920 1689 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1e8e9920 1690 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
1691 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
1e8e9920 1692 name = create_tmp_var_name (".omp_data_s");
e60a6f7b 1693 name = build_decl (gimple_location (stmt),
1694 TYPE_DECL, name, ctx->record_type);
84bfaaeb 1695 DECL_ARTIFICIAL (name) = 1;
1696 DECL_NAMELESS (name) = 1;
1e8e9920 1697 TYPE_NAME (ctx->record_type) = name;
fd6481cf 1698 create_omp_child_function (ctx, false);
75a70cf9 1699 gimple_omp_parallel_set_child_fn (stmt, ctx->cb.dst_fn);
1e8e9920 1700
75a70cf9 1701 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt), ctx);
ab129075 1702 scan_omp (gimple_omp_body_ptr (stmt), ctx);
1e8e9920 1703
1704 if (TYPE_FIELDS (ctx->record_type) == NULL)
1705 ctx->record_type = ctx->receiver_decl = NULL;
1706 else
1707 {
1708 layout_type (ctx->record_type);
1709 fixup_child_record_type (ctx);
1710 }
1711}
1712
fd6481cf 1713/* Scan an OpenMP task directive. */
1714
1715static void
75a70cf9 1716scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
fd6481cf 1717{
1718 omp_context *ctx;
75a70cf9 1719 tree name, t;
1720 gimple stmt = gsi_stmt (*gsi);
389dd41b 1721 location_t loc = gimple_location (stmt);
fd6481cf 1722
1723 /* Ignore task directives with empty bodies. */
1724 if (optimize > 0
75a70cf9 1725 && empty_body_p (gimple_omp_body (stmt)))
fd6481cf 1726 {
75a70cf9 1727 gsi_replace (gsi, gimple_build_nop (), false);
fd6481cf 1728 return;
1729 }
1730
75a70cf9 1731 ctx = new_omp_context (stmt, outer_ctx);
fd6481cf 1732 if (taskreg_nesting_level > 1)
1733 ctx->is_nested = true;
1734 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1735 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
1736 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
1737 name = create_tmp_var_name (".omp_data_s");
e60a6f7b 1738 name = build_decl (gimple_location (stmt),
1739 TYPE_DECL, name, ctx->record_type);
84bfaaeb 1740 DECL_ARTIFICIAL (name) = 1;
1741 DECL_NAMELESS (name) = 1;
fd6481cf 1742 TYPE_NAME (ctx->record_type) = name;
1743 create_omp_child_function (ctx, false);
75a70cf9 1744 gimple_omp_task_set_child_fn (stmt, ctx->cb.dst_fn);
fd6481cf 1745
75a70cf9 1746 scan_sharing_clauses (gimple_omp_task_clauses (stmt), ctx);
fd6481cf 1747
1748 if (ctx->srecord_type)
1749 {
1750 name = create_tmp_var_name (".omp_data_a");
e60a6f7b 1751 name = build_decl (gimple_location (stmt),
1752 TYPE_DECL, name, ctx->srecord_type);
84bfaaeb 1753 DECL_ARTIFICIAL (name) = 1;
1754 DECL_NAMELESS (name) = 1;
fd6481cf 1755 TYPE_NAME (ctx->srecord_type) = name;
1756 create_omp_child_function (ctx, true);
1757 }
1758
ab129075 1759 scan_omp (gimple_omp_body_ptr (stmt), ctx);
fd6481cf 1760
1761 if (TYPE_FIELDS (ctx->record_type) == NULL)
1762 {
1763 ctx->record_type = ctx->receiver_decl = NULL;
75a70cf9 1764 t = build_int_cst (long_integer_type_node, 0);
1765 gimple_omp_task_set_arg_size (stmt, t);
1766 t = build_int_cst (long_integer_type_node, 1);
1767 gimple_omp_task_set_arg_align (stmt, t);
fd6481cf 1768 }
1769 else
1770 {
1771 tree *p, vla_fields = NULL_TREE, *q = &vla_fields;
1772 /* Move VLA fields to the end. */
1773 p = &TYPE_FIELDS (ctx->record_type);
1774 while (*p)
1775 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p))
1776 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p))))
1777 {
1778 *q = *p;
1779 *p = TREE_CHAIN (*p);
1780 TREE_CHAIN (*q) = NULL_TREE;
1781 q = &TREE_CHAIN (*q);
1782 }
1783 else
1767a056 1784 p = &DECL_CHAIN (*p);
fd6481cf 1785 *p = vla_fields;
1786 layout_type (ctx->record_type);
1787 fixup_child_record_type (ctx);
1788 if (ctx->srecord_type)
1789 layout_type (ctx->srecord_type);
389dd41b 1790 t = fold_convert_loc (loc, long_integer_type_node,
fd6481cf 1791 TYPE_SIZE_UNIT (ctx->record_type));
75a70cf9 1792 gimple_omp_task_set_arg_size (stmt, t);
1793 t = build_int_cst (long_integer_type_node,
fd6481cf 1794 TYPE_ALIGN_UNIT (ctx->record_type));
75a70cf9 1795 gimple_omp_task_set_arg_align (stmt, t);
fd6481cf 1796 }
1797}
1798
1e8e9920 1799
773c5ba7 1800/* Scan an OpenMP loop directive. */
1e8e9920 1801
1802static void
75a70cf9 1803scan_omp_for (gimple stmt, omp_context *outer_ctx)
1e8e9920 1804{
773c5ba7 1805 omp_context *ctx;
75a70cf9 1806 size_t i;
1e8e9920 1807
773c5ba7 1808 ctx = new_omp_context (stmt, outer_ctx);
1e8e9920 1809
75a70cf9 1810 scan_sharing_clauses (gimple_omp_for_clauses (stmt), ctx);
1e8e9920 1811
ab129075 1812 scan_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
75a70cf9 1813 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
fd6481cf 1814 {
75a70cf9 1815 scan_omp_op (gimple_omp_for_index_ptr (stmt, i), ctx);
1816 scan_omp_op (gimple_omp_for_initial_ptr (stmt, i), ctx);
1817 scan_omp_op (gimple_omp_for_final_ptr (stmt, i), ctx);
1818 scan_omp_op (gimple_omp_for_incr_ptr (stmt, i), ctx);
fd6481cf 1819 }
ab129075 1820 scan_omp (gimple_omp_body_ptr (stmt), ctx);
1e8e9920 1821}
1822
1823/* Scan an OpenMP sections directive. */
1824
1825static void
75a70cf9 1826scan_omp_sections (gimple stmt, omp_context *outer_ctx)
1e8e9920 1827{
1e8e9920 1828 omp_context *ctx;
1829
1830 ctx = new_omp_context (stmt, outer_ctx);
75a70cf9 1831 scan_sharing_clauses (gimple_omp_sections_clauses (stmt), ctx);
ab129075 1832 scan_omp (gimple_omp_body_ptr (stmt), ctx);
1e8e9920 1833}
1834
1835/* Scan an OpenMP single directive. */
1836
1837static void
75a70cf9 1838scan_omp_single (gimple stmt, omp_context *outer_ctx)
1e8e9920 1839{
1e8e9920 1840 omp_context *ctx;
1841 tree name;
1842
1843 ctx = new_omp_context (stmt, outer_ctx);
1844 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1845 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
1846 name = create_tmp_var_name (".omp_copy_s");
e60a6f7b 1847 name = build_decl (gimple_location (stmt),
1848 TYPE_DECL, name, ctx->record_type);
1e8e9920 1849 TYPE_NAME (ctx->record_type) = name;
1850
75a70cf9 1851 scan_sharing_clauses (gimple_omp_single_clauses (stmt), ctx);
ab129075 1852 scan_omp (gimple_omp_body_ptr (stmt), ctx);
1e8e9920 1853
1854 if (TYPE_FIELDS (ctx->record_type) == NULL)
1855 ctx->record_type = NULL;
1856 else
1857 layout_type (ctx->record_type);
1858}
1859
1e8e9920 1860
c1d127dd 1861/* Check OpenMP nesting restrictions. */
ab129075 1862static bool
1863check_omp_nesting_restrictions (gimple stmt, omp_context *ctx)
c1d127dd 1864{
3d483a94 1865 if (ctx != NULL)
1866 {
1867 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
1868 && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD)
1869 {
1870 error_at (gimple_location (stmt),
1871 "OpenMP constructs may not be nested inside simd region");
1872 return false;
1873 }
1874 }
75a70cf9 1875 switch (gimple_code (stmt))
c1d127dd 1876 {
75a70cf9 1877 case GIMPLE_OMP_FOR:
3d483a94 1878 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_SIMD)
1879 return true;
1880 /* FALLTHRU */
75a70cf9 1881 case GIMPLE_OMP_SECTIONS:
1882 case GIMPLE_OMP_SINGLE:
1883 case GIMPLE_CALL:
c1d127dd 1884 for (; ctx != NULL; ctx = ctx->outer)
75a70cf9 1885 switch (gimple_code (ctx->stmt))
c1d127dd 1886 {
75a70cf9 1887 case GIMPLE_OMP_FOR:
1888 case GIMPLE_OMP_SECTIONS:
1889 case GIMPLE_OMP_SINGLE:
1890 case GIMPLE_OMP_ORDERED:
1891 case GIMPLE_OMP_MASTER:
1892 case GIMPLE_OMP_TASK:
1893 if (is_gimple_call (stmt))
fd6481cf 1894 {
ab129075 1895 error_at (gimple_location (stmt),
1896 "barrier region may not be closely nested inside "
1897 "of work-sharing, critical, ordered, master or "
1898 "explicit task region");
1899 return false;
fd6481cf 1900 }
ab129075 1901 error_at (gimple_location (stmt),
1902 "work-sharing region may not be closely nested inside "
1903 "of work-sharing, critical, ordered, master or explicit "
1904 "task region");
1905 return false;
75a70cf9 1906 case GIMPLE_OMP_PARALLEL:
ab129075 1907 return true;
c1d127dd 1908 default:
1909 break;
1910 }
1911 break;
75a70cf9 1912 case GIMPLE_OMP_MASTER:
c1d127dd 1913 for (; ctx != NULL; ctx = ctx->outer)
75a70cf9 1914 switch (gimple_code (ctx->stmt))
c1d127dd 1915 {
75a70cf9 1916 case GIMPLE_OMP_FOR:
1917 case GIMPLE_OMP_SECTIONS:
1918 case GIMPLE_OMP_SINGLE:
1919 case GIMPLE_OMP_TASK:
ab129075 1920 error_at (gimple_location (stmt),
1921 "master region may not be closely nested inside "
1922 "of work-sharing or explicit task region");
1923 return false;
75a70cf9 1924 case GIMPLE_OMP_PARALLEL:
ab129075 1925 return true;
c1d127dd 1926 default:
1927 break;
1928 }
1929 break;
75a70cf9 1930 case GIMPLE_OMP_ORDERED:
c1d127dd 1931 for (; ctx != NULL; ctx = ctx->outer)
75a70cf9 1932 switch (gimple_code (ctx->stmt))
c1d127dd 1933 {
75a70cf9 1934 case GIMPLE_OMP_CRITICAL:
1935 case GIMPLE_OMP_TASK:
ab129075 1936 error_at (gimple_location (stmt),
1937 "ordered region may not be closely nested inside "
1938 "of critical or explicit task region");
1939 return false;
75a70cf9 1940 case GIMPLE_OMP_FOR:
1941 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
c1d127dd 1942 OMP_CLAUSE_ORDERED) == NULL)
ab129075 1943 {
1944 error_at (gimple_location (stmt),
1945 "ordered region must be closely nested inside "
c1d127dd 1946 "a loop region with an ordered clause");
ab129075 1947 return false;
1948 }
1949 return true;
75a70cf9 1950 case GIMPLE_OMP_PARALLEL:
ab129075 1951 return true;
c1d127dd 1952 default:
1953 break;
1954 }
1955 break;
75a70cf9 1956 case GIMPLE_OMP_CRITICAL:
c1d127dd 1957 for (; ctx != NULL; ctx = ctx->outer)
75a70cf9 1958 if (gimple_code (ctx->stmt) == GIMPLE_OMP_CRITICAL
1959 && (gimple_omp_critical_name (stmt)
1960 == gimple_omp_critical_name (ctx->stmt)))
c1d127dd 1961 {
ab129075 1962 error_at (gimple_location (stmt),
1963 "critical region may not be nested inside a critical "
1964 "region with the same name");
1965 return false;
c1d127dd 1966 }
1967 break;
1968 default:
1969 break;
1970 }
ab129075 1971 return true;
c1d127dd 1972}
1973
1974
75a70cf9 1975/* Helper function scan_omp.
1976
1977 Callback for walk_tree or operators in walk_gimple_stmt used to
1978 scan for OpenMP directives in TP. */
1e8e9920 1979
1980static tree
75a70cf9 1981scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
1e8e9920 1982{
4077bf7a 1983 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
1984 omp_context *ctx = (omp_context *) wi->info;
1e8e9920 1985 tree t = *tp;
1986
75a70cf9 1987 switch (TREE_CODE (t))
1988 {
1989 case VAR_DECL:
1990 case PARM_DECL:
1991 case LABEL_DECL:
1992 case RESULT_DECL:
1993 if (ctx)
1994 *tp = remap_decl (t, &ctx->cb);
1995 break;
1996
1997 default:
1998 if (ctx && TYPE_P (t))
1999 *tp = remap_type (t, &ctx->cb);
2000 else if (!DECL_P (t))
7cf869dd 2001 {
2002 *walk_subtrees = 1;
2003 if (ctx)
182cf5a9 2004 {
2005 tree tem = remap_type (TREE_TYPE (t), &ctx->cb);
2006 if (tem != TREE_TYPE (t))
2007 {
2008 if (TREE_CODE (t) == INTEGER_CST)
2009 *tp = build_int_cst_wide (tem,
2010 TREE_INT_CST_LOW (t),
2011 TREE_INT_CST_HIGH (t));
2012 else
2013 TREE_TYPE (t) = tem;
2014 }
2015 }
7cf869dd 2016 }
75a70cf9 2017 break;
2018 }
2019
2020 return NULL_TREE;
2021}
2022
2023
2024/* Helper function for scan_omp.
2025
2026 Callback for walk_gimple_stmt used to scan for OpenMP directives in
2027 the current statement in GSI. */
2028
2029static tree
2030scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
2031 struct walk_stmt_info *wi)
2032{
2033 gimple stmt = gsi_stmt (*gsi);
2034 omp_context *ctx = (omp_context *) wi->info;
2035
2036 if (gimple_has_location (stmt))
2037 input_location = gimple_location (stmt);
1e8e9920 2038
c1d127dd 2039 /* Check the OpenMP nesting restrictions. */
fd6481cf 2040 if (ctx != NULL)
2041 {
ab129075 2042 bool remove = false;
75a70cf9 2043 if (is_gimple_omp (stmt))
ab129075 2044 remove = !check_omp_nesting_restrictions (stmt, ctx);
75a70cf9 2045 else if (is_gimple_call (stmt))
fd6481cf 2046 {
75a70cf9 2047 tree fndecl = gimple_call_fndecl (stmt);
fd6481cf 2048 if (fndecl && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
2049 && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
ab129075 2050 remove = !check_omp_nesting_restrictions (stmt, ctx);
2051 }
2052 if (remove)
2053 {
2054 stmt = gimple_build_nop ();
2055 gsi_replace (gsi, stmt, false);
fd6481cf 2056 }
2057 }
c1d127dd 2058
75a70cf9 2059 *handled_ops_p = true;
2060
2061 switch (gimple_code (stmt))
1e8e9920 2062 {
75a70cf9 2063 case GIMPLE_OMP_PARALLEL:
fd6481cf 2064 taskreg_nesting_level++;
75a70cf9 2065 scan_omp_parallel (gsi, ctx);
fd6481cf 2066 taskreg_nesting_level--;
2067 break;
2068
75a70cf9 2069 case GIMPLE_OMP_TASK:
fd6481cf 2070 taskreg_nesting_level++;
75a70cf9 2071 scan_omp_task (gsi, ctx);
fd6481cf 2072 taskreg_nesting_level--;
1e8e9920 2073 break;
2074
75a70cf9 2075 case GIMPLE_OMP_FOR:
2076 scan_omp_for (stmt, ctx);
1e8e9920 2077 break;
2078
75a70cf9 2079 case GIMPLE_OMP_SECTIONS:
2080 scan_omp_sections (stmt, ctx);
1e8e9920 2081 break;
2082
75a70cf9 2083 case GIMPLE_OMP_SINGLE:
2084 scan_omp_single (stmt, ctx);
1e8e9920 2085 break;
2086
75a70cf9 2087 case GIMPLE_OMP_SECTION:
2088 case GIMPLE_OMP_MASTER:
2089 case GIMPLE_OMP_ORDERED:
2090 case GIMPLE_OMP_CRITICAL:
2091 ctx = new_omp_context (stmt, ctx);
ab129075 2092 scan_omp (gimple_omp_body_ptr (stmt), ctx);
1e8e9920 2093 break;
2094
75a70cf9 2095 case GIMPLE_BIND:
1e8e9920 2096 {
2097 tree var;
1e8e9920 2098
75a70cf9 2099 *handled_ops_p = false;
2100 if (ctx)
1767a056 2101 for (var = gimple_bind_vars (stmt); var ; var = DECL_CHAIN (var))
75a70cf9 2102 insert_decl_map (&ctx->cb, var, var);
1e8e9920 2103 }
2104 break;
1e8e9920 2105 default:
75a70cf9 2106 *handled_ops_p = false;
1e8e9920 2107 break;
2108 }
2109
2110 return NULL_TREE;
2111}
2112
2113
75a70cf9 2114/* Scan all the statements starting at the current statement. CTX
2115 contains context information about the OpenMP directives and
2116 clauses found during the scan. */
1e8e9920 2117
2118static void
ab129075 2119scan_omp (gimple_seq *body_p, omp_context *ctx)
1e8e9920 2120{
2121 location_t saved_location;
2122 struct walk_stmt_info wi;
2123
2124 memset (&wi, 0, sizeof (wi));
1e8e9920 2125 wi.info = ctx;
1e8e9920 2126 wi.want_locations = true;
2127
2128 saved_location = input_location;
ab129075 2129 walk_gimple_seq_mod (body_p, scan_omp_1_stmt, scan_omp_1_op, &wi);
1e8e9920 2130 input_location = saved_location;
2131}
2132\f
2133/* Re-gimplification and code generation routines. */
2134
2135/* Build a call to GOMP_barrier. */
2136
79acaae1 2137static tree
2138build_omp_barrier (void)
1e8e9920 2139{
b9a16870 2140 return build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_BARRIER), 0);
1e8e9920 2141}
2142
2143/* If a context was created for STMT when it was scanned, return it. */
2144
2145static omp_context *
75a70cf9 2146maybe_lookup_ctx (gimple stmt)
1e8e9920 2147{
2148 splay_tree_node n;
2149 n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
2150 return n ? (omp_context *) n->value : NULL;
2151}
2152
773c5ba7 2153
2154/* Find the mapping for DECL in CTX or the immediately enclosing
2155 context that has a mapping for DECL.
2156
2157 If CTX is a nested parallel directive, we may have to use the decl
2158 mappings created in CTX's parent context. Suppose that we have the
2159 following parallel nesting (variable UIDs showed for clarity):
2160
2161 iD.1562 = 0;
2162 #omp parallel shared(iD.1562) -> outer parallel
2163 iD.1562 = iD.1562 + 1;
2164
2165 #omp parallel shared (iD.1562) -> inner parallel
2166 iD.1562 = iD.1562 - 1;
2167
2168 Each parallel structure will create a distinct .omp_data_s structure
2169 for copying iD.1562 in/out of the directive:
2170
2171 outer parallel .omp_data_s.1.i -> iD.1562
2172 inner parallel .omp_data_s.2.i -> iD.1562
2173
2174 A shared variable mapping will produce a copy-out operation before
2175 the parallel directive and a copy-in operation after it. So, in
2176 this case we would have:
2177
2178 iD.1562 = 0;
2179 .omp_data_o.1.i = iD.1562;
2180 #omp parallel shared(iD.1562) -> outer parallel
2181 .omp_data_i.1 = &.omp_data_o.1
2182 .omp_data_i.1->i = .omp_data_i.1->i + 1;
2183
2184 .omp_data_o.2.i = iD.1562; -> **
2185 #omp parallel shared(iD.1562) -> inner parallel
2186 .omp_data_i.2 = &.omp_data_o.2
2187 .omp_data_i.2->i = .omp_data_i.2->i - 1;
2188
2189
2190 ** This is a problem. The symbol iD.1562 cannot be referenced
2191 inside the body of the outer parallel region. But since we are
2192 emitting this copy operation while expanding the inner parallel
2193 directive, we need to access the CTX structure of the outer
2194 parallel directive to get the correct mapping:
2195
2196 .omp_data_o.2.i = .omp_data_i.1->i
2197
2198 Since there may be other workshare or parallel directives enclosing
2199 the parallel directive, it may be necessary to walk up the context
2200 parent chain. This is not a problem in general because nested
2201 parallelism happens only rarely. */
2202
2203static tree
2204lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
2205{
2206 tree t;
2207 omp_context *up;
2208
773c5ba7 2209 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
2210 t = maybe_lookup_decl (decl, up);
2211
87b31375 2212 gcc_assert (!ctx->is_nested || t || is_global_var (decl));
773c5ba7 2213
c37594c7 2214 return t ? t : decl;
773c5ba7 2215}
2216
2217
f49d7bb5 2218/* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
2219 in outer contexts. */
2220
2221static tree
2222maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
2223{
2224 tree t = NULL;
2225 omp_context *up;
2226
87b31375 2227 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
2228 t = maybe_lookup_decl (decl, up);
f49d7bb5 2229
2230 return t ? t : decl;
2231}
2232
2233
1e8e9920 2234/* Construct the initialization value for reduction CLAUSE. */
2235
2236tree
2237omp_reduction_init (tree clause, tree type)
2238{
389dd41b 2239 location_t loc = OMP_CLAUSE_LOCATION (clause);
1e8e9920 2240 switch (OMP_CLAUSE_REDUCTION_CODE (clause))
2241 {
2242 case PLUS_EXPR:
2243 case MINUS_EXPR:
2244 case BIT_IOR_EXPR:
2245 case BIT_XOR_EXPR:
2246 case TRUTH_OR_EXPR:
2247 case TRUTH_ORIF_EXPR:
2248 case TRUTH_XOR_EXPR:
2249 case NE_EXPR:
385f3f36 2250 return build_zero_cst (type);
1e8e9920 2251
2252 case MULT_EXPR:
2253 case TRUTH_AND_EXPR:
2254 case TRUTH_ANDIF_EXPR:
2255 case EQ_EXPR:
389dd41b 2256 return fold_convert_loc (loc, type, integer_one_node);
1e8e9920 2257
2258 case BIT_AND_EXPR:
389dd41b 2259 return fold_convert_loc (loc, type, integer_minus_one_node);
1e8e9920 2260
2261 case MAX_EXPR:
2262 if (SCALAR_FLOAT_TYPE_P (type))
2263 {
2264 REAL_VALUE_TYPE max, min;
2265 if (HONOR_INFINITIES (TYPE_MODE (type)))
2266 {
2267 real_inf (&max);
2268 real_arithmetic (&min, NEGATE_EXPR, &max, NULL);
2269 }
2270 else
2271 real_maxval (&min, 1, TYPE_MODE (type));
2272 return build_real (type, min);
2273 }
2274 else
2275 {
2276 gcc_assert (INTEGRAL_TYPE_P (type));
2277 return TYPE_MIN_VALUE (type);
2278 }
2279
2280 case MIN_EXPR:
2281 if (SCALAR_FLOAT_TYPE_P (type))
2282 {
2283 REAL_VALUE_TYPE max;
2284 if (HONOR_INFINITIES (TYPE_MODE (type)))
2285 real_inf (&max);
2286 else
2287 real_maxval (&max, 0, TYPE_MODE (type));
2288 return build_real (type, max);
2289 }
2290 else
2291 {
2292 gcc_assert (INTEGRAL_TYPE_P (type));
2293 return TYPE_MAX_VALUE (type);
2294 }
2295
2296 default:
2297 gcc_unreachable ();
2298 }
2299}
2300
3d483a94 2301/* Return maximum possible vectorization factor for the target. */
2302
2303static int
2304omp_max_vf (void)
2305{
2306 if (!optimize
2307 || optimize_debug
2308 || (!flag_tree_vectorize
2309 && global_options_set.x_flag_tree_vectorize))
2310 return 1;
2311
2312 int vs = targetm.vectorize.autovectorize_vector_sizes ();
2313 if (vs)
2314 {
2315 vs = 1 << floor_log2 (vs);
2316 return vs;
2317 }
2318 enum machine_mode vqimode = targetm.vectorize.preferred_simd_mode (QImode);
2319 if (GET_MODE_CLASS (vqimode) == MODE_VECTOR_INT)
2320 return GET_MODE_NUNITS (vqimode);
2321 return 1;
2322}
2323
2324/* Helper function of lower_rec_input_clauses, used for #pragma omp simd
2325 privatization. */
2326
2327static bool
2328lower_rec_simd_input_clauses (tree new_var, omp_context *ctx, int &max_vf,
2329 tree &idx, tree &lane, tree &ivar, tree &lvar)
2330{
2331 if (max_vf == 0)
2332 {
2333 max_vf = omp_max_vf ();
2334 if (max_vf > 1)
2335 {
2336 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2337 OMP_CLAUSE_SAFELEN);
2338 if (c
2339 && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c), max_vf) == -1)
2340 max_vf = tree_low_cst (OMP_CLAUSE_SAFELEN_EXPR (c), 0);
2341 }
2342 if (max_vf > 1)
2343 {
2344 idx = create_tmp_var (unsigned_type_node, NULL);
2345 lane = create_tmp_var (unsigned_type_node, NULL);
2346 }
2347 }
2348 if (max_vf == 1)
2349 return false;
2350
2351 tree atype = build_array_type_nelts (TREE_TYPE (new_var), max_vf);
2352 tree avar = create_tmp_var_raw (atype, NULL);
2353 if (TREE_ADDRESSABLE (new_var))
2354 TREE_ADDRESSABLE (avar) = 1;
2355 DECL_ATTRIBUTES (avar)
2356 = tree_cons (get_identifier ("omp simd array"), NULL,
2357 DECL_ATTRIBUTES (avar));
2358 gimple_add_tmp_var (avar);
2359 ivar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, idx,
2360 NULL_TREE, NULL_TREE);
2361 lvar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, lane,
2362 NULL_TREE, NULL_TREE);
2363 SET_DECL_VALUE_EXPR (new_var, lvar);
2364 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
2365 return true;
2366}
2367
1e8e9920 2368/* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
2369 from the receiver (aka child) side and initializers for REFERENCE_TYPE
2370 private variables. Initialization statements go in ILIST, while calls
2371 to destructors go in DLIST. */
2372
2373static void
75a70cf9 2374lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
1e4afe3c 2375 omp_context *ctx)
1e8e9920 2376{
c2f47e15 2377 tree c, dtor, copyin_seq, x, ptr;
1e8e9920 2378 bool copyin_by_ref = false;
f49d7bb5 2379 bool lastprivate_firstprivate = false;
1e8e9920 2380 int pass;
3d483a94 2381 bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
2382 && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD);
2383 int max_vf = 0;
2384 tree lane = NULL_TREE, idx = NULL_TREE;
2385 tree ivar = NULL_TREE, lvar = NULL_TREE;
2386 gimple_seq llist[2] = { NULL, NULL };
1e8e9920 2387
1e8e9920 2388 copyin_seq = NULL;
2389
3d483a94 2390 /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
2391 with data sharing clauses referencing variable sized vars. That
2392 is unnecessarily hard to support and very unlikely to result in
2393 vectorized code anyway. */
2394 if (is_simd)
2395 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
2396 switch (OMP_CLAUSE_CODE (c))
2397 {
2398 case OMP_CLAUSE_REDUCTION:
2399 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2400 max_vf = 1;
2401 /* FALLTHRU */
2402 case OMP_CLAUSE_PRIVATE:
2403 case OMP_CLAUSE_FIRSTPRIVATE:
2404 case OMP_CLAUSE_LASTPRIVATE:
2405 case OMP_CLAUSE_LINEAR:
2406 if (is_variable_sized (OMP_CLAUSE_DECL (c)))
2407 max_vf = 1;
2408 break;
2409 default:
2410 continue;
2411 }
2412
1e8e9920 2413 /* Do all the fixed sized types in the first pass, and the variable sized
2414 types in the second pass. This makes sure that the scalar arguments to
48e1416a 2415 the variable sized types are processed before we use them in the
1e8e9920 2416 variable sized operations. */
2417 for (pass = 0; pass < 2; ++pass)
2418 {
2419 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
2420 {
55d6e7cd 2421 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
1e8e9920 2422 tree var, new_var;
2423 bool by_ref;
389dd41b 2424 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
1e8e9920 2425
2426 switch (c_kind)
2427 {
2428 case OMP_CLAUSE_PRIVATE:
2429 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
2430 continue;
2431 break;
2432 case OMP_CLAUSE_SHARED:
f49d7bb5 2433 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
2434 {
2435 gcc_assert (is_global_var (OMP_CLAUSE_DECL (c)));
2436 continue;
2437 }
1e8e9920 2438 case OMP_CLAUSE_FIRSTPRIVATE:
1e8e9920 2439 case OMP_CLAUSE_COPYIN:
2440 case OMP_CLAUSE_REDUCTION:
2441 break;
3d483a94 2442 case OMP_CLAUSE_LINEAR:
2443 break;
df2c34fc 2444 case OMP_CLAUSE_LASTPRIVATE:
f49d7bb5 2445 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
2446 {
2447 lastprivate_firstprivate = true;
2448 if (pass != 0)
2449 continue;
2450 }
df2c34fc 2451 break;
1e8e9920 2452 default:
2453 continue;
2454 }
2455
2456 new_var = var = OMP_CLAUSE_DECL (c);
2457 if (c_kind != OMP_CLAUSE_COPYIN)
2458 new_var = lookup_decl (var, ctx);
2459
2460 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
2461 {
2462 if (pass != 0)
2463 continue;
2464 }
1e8e9920 2465 else if (is_variable_sized (var))
2466 {
773c5ba7 2467 /* For variable sized types, we need to allocate the
2468 actual storage here. Call alloca and store the
2469 result in the pointer decl that we created elsewhere. */
1e8e9920 2470 if (pass == 0)
2471 continue;
2472
fd6481cf 2473 if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
2474 {
75a70cf9 2475 gimple stmt;
b9a16870 2476 tree tmp, atmp;
75a70cf9 2477
fd6481cf 2478 ptr = DECL_VALUE_EXPR (new_var);
2479 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
2480 ptr = TREE_OPERAND (ptr, 0);
2481 gcc_assert (DECL_P (ptr));
2482 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
75a70cf9 2483
2484 /* void *tmp = __builtin_alloca */
b9a16870 2485 atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
2486 stmt = gimple_build_call (atmp, 1, x);
75a70cf9 2487 tmp = create_tmp_var_raw (ptr_type_node, NULL);
2488 gimple_add_tmp_var (tmp);
2489 gimple_call_set_lhs (stmt, tmp);
2490
2491 gimple_seq_add_stmt (ilist, stmt);
2492
389dd41b 2493 x = fold_convert_loc (clause_loc, TREE_TYPE (ptr), tmp);
75a70cf9 2494 gimplify_assign (ptr, x, ilist);
fd6481cf 2495 }
1e8e9920 2496 }
1e8e9920 2497 else if (is_reference (var))
2498 {
773c5ba7 2499 /* For references that are being privatized for Fortran,
2500 allocate new backing storage for the new pointer
2501 variable. This allows us to avoid changing all the
2502 code that expects a pointer to something that expects
2503 a direct variable. Note that this doesn't apply to
2504 C++, since reference types are disallowed in data
df2c34fc 2505 sharing clauses there, except for NRV optimized
2506 return values. */
1e8e9920 2507 if (pass == 0)
2508 continue;
2509
2510 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
fd6481cf 2511 if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx))
2512 {
2513 x = build_receiver_ref (var, false, ctx);
389dd41b 2514 x = build_fold_addr_expr_loc (clause_loc, x);
fd6481cf 2515 }
2516 else if (TREE_CONSTANT (x))
1e8e9920 2517 {
2518 const char *name = NULL;
2519 if (DECL_NAME (var))
2520 name = IDENTIFIER_POINTER (DECL_NAME (new_var));
2521
df2c34fc 2522 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
2523 name);
2524 gimple_add_tmp_var (x);
86f2ad37 2525 TREE_ADDRESSABLE (x) = 1;
389dd41b 2526 x = build_fold_addr_expr_loc (clause_loc, x);
1e8e9920 2527 }
2528 else
2529 {
b9a16870 2530 tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
2531 x = build_call_expr_loc (clause_loc, atmp, 1, x);
1e8e9920 2532 }
2533
389dd41b 2534 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
75a70cf9 2535 gimplify_assign (new_var, x, ilist);
1e8e9920 2536
182cf5a9 2537 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
1e8e9920 2538 }
2539 else if (c_kind == OMP_CLAUSE_REDUCTION
2540 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2541 {
2542 if (pass == 0)
2543 continue;
2544 }
2545 else if (pass != 0)
2546 continue;
2547
55d6e7cd 2548 switch (OMP_CLAUSE_CODE (c))
1e8e9920 2549 {
2550 case OMP_CLAUSE_SHARED:
f49d7bb5 2551 /* Shared global vars are just accessed directly. */
2552 if (is_global_var (new_var))
2553 break;
1e8e9920 2554 /* Set up the DECL_VALUE_EXPR for shared variables now. This
2555 needs to be delayed until after fixup_child_record_type so
2556 that we get the correct type during the dereference. */
e8a588af 2557 by_ref = use_pointer_for_field (var, ctx);
1e8e9920 2558 x = build_receiver_ref (var, by_ref, ctx);
2559 SET_DECL_VALUE_EXPR (new_var, x);
2560 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
2561
2562 /* ??? If VAR is not passed by reference, and the variable
2563 hasn't been initialized yet, then we'll get a warning for
2564 the store into the omp_data_s structure. Ideally, we'd be
48e1416a 2565 able to notice this and not store anything at all, but
1e8e9920 2566 we're generating code too early. Suppress the warning. */
2567 if (!by_ref)
2568 TREE_NO_WARNING (var) = 1;
2569 break;
2570
2571 case OMP_CLAUSE_LASTPRIVATE:
2572 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
2573 break;
2574 /* FALLTHRU */
2575
2576 case OMP_CLAUSE_PRIVATE:
fd6481cf 2577 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE)
2578 x = build_outer_var_ref (var, ctx);
2579 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
2580 {
2581 if (is_task_ctx (ctx))
2582 x = build_receiver_ref (var, false, ctx);
2583 else
2584 x = build_outer_var_ref (var, ctx);
2585 }
2586 else
2587 x = NULL;
3d483a94 2588 do_private:
fd6481cf 2589 x = lang_hooks.decls.omp_clause_default_ctor (c, new_var, x);
3d483a94 2590 if (is_simd)
2591 {
2592 tree y = lang_hooks.decls.omp_clause_dtor (c, new_var);
2593 if ((TREE_ADDRESSABLE (new_var) || x || y
2594 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
2595 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
2596 idx, lane, ivar, lvar))
2597 {
2598 if (x)
2599 x = lang_hooks.decls.omp_clause_default_ctor
2600 (c, unshare_expr (ivar), x);
2601 if (x)
2602 gimplify_and_add (x, &llist[0]);
2603 if (y)
2604 {
2605 y = lang_hooks.decls.omp_clause_dtor (c, ivar);
2606 if (y)
2607 {
2608 gimple_seq tseq = NULL;
2609
2610 dtor = y;
2611 gimplify_stmt (&dtor, &tseq);
2612 gimple_seq_add_seq (&llist[1], tseq);
2613 }
2614 }
2615 break;
2616 }
2617 }
1e8e9920 2618 if (x)
2619 gimplify_and_add (x, ilist);
2620 /* FALLTHRU */
2621
2622 do_dtor:
2623 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
2624 if (x)
2625 {
75a70cf9 2626 gimple_seq tseq = NULL;
2627
1e8e9920 2628 dtor = x;
75a70cf9 2629 gimplify_stmt (&dtor, &tseq);
e3a19533 2630 gimple_seq_add_seq (dlist, tseq);
1e8e9920 2631 }
2632 break;
2633
3d483a94 2634 case OMP_CLAUSE_LINEAR:
2635 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c))
2636 goto do_firstprivate;
2637 if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
2638 x = NULL;
2639 else
2640 x = build_outer_var_ref (var, ctx);
2641 goto do_private;
2642
1e8e9920 2643 case OMP_CLAUSE_FIRSTPRIVATE:
fd6481cf 2644 if (is_task_ctx (ctx))
2645 {
2646 if (is_reference (var) || is_variable_sized (var))
2647 goto do_dtor;
2648 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var,
2649 ctx))
2650 || use_pointer_for_field (var, NULL))
2651 {
2652 x = build_receiver_ref (var, false, ctx);
2653 SET_DECL_VALUE_EXPR (new_var, x);
2654 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
2655 goto do_dtor;
2656 }
2657 }
3d483a94 2658 do_firstprivate:
1e8e9920 2659 x = build_outer_var_ref (var, ctx);
3d483a94 2660 if (is_simd)
2661 {
2662 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
2663 || TREE_ADDRESSABLE (new_var))
2664 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
2665 idx, lane, ivar, lvar))
2666 {
2667 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR)
2668 {
2669 tree iv = create_tmp_var (TREE_TYPE (new_var), NULL);
2670 x = lang_hooks.decls.omp_clause_copy_ctor (c, iv, x);
2671 gimplify_and_add (x, ilist);
2672 gimple_stmt_iterator gsi
2673 = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
2674 gimple g
2675 = gimple_build_assign (unshare_expr (lvar), iv);
2676 gsi_insert_before_without_update (&gsi, g,
2677 GSI_SAME_STMT);
2678 tree stept = POINTER_TYPE_P (TREE_TYPE (x))
2679 ? sizetype : TREE_TYPE (x);
2680 tree t = fold_convert (stept,
2681 OMP_CLAUSE_LINEAR_STEP (c));
2682 enum tree_code code = PLUS_EXPR;
2683 if (POINTER_TYPE_P (TREE_TYPE (new_var)))
2684 code = POINTER_PLUS_EXPR;
2685 g = gimple_build_assign_with_ops (code, iv, iv, t);
2686 gsi_insert_before_without_update (&gsi, g,
2687 GSI_SAME_STMT);
2688 break;
2689 }
2690 x = lang_hooks.decls.omp_clause_copy_ctor
2691 (c, unshare_expr (ivar), x);
2692 gimplify_and_add (x, &llist[0]);
2693 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
2694 if (x)
2695 {
2696 gimple_seq tseq = NULL;
2697
2698 dtor = x;
2699 gimplify_stmt (&dtor, &tseq);
2700 gimple_seq_add_seq (&llist[1], tseq);
2701 }
2702 break;
2703 }
2704 }
1e8e9920 2705 x = lang_hooks.decls.omp_clause_copy_ctor (c, new_var, x);
2706 gimplify_and_add (x, ilist);
2707 goto do_dtor;
1e8e9920 2708
2709 case OMP_CLAUSE_COPYIN:
e8a588af 2710 by_ref = use_pointer_for_field (var, NULL);
1e8e9920 2711 x = build_receiver_ref (var, by_ref, ctx);
2712 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
2713 append_to_statement_list (x, &copyin_seq);
2714 copyin_by_ref |= by_ref;
2715 break;
2716
2717 case OMP_CLAUSE_REDUCTION:
2718 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2719 {
fd6481cf 2720 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
2721 x = build_outer_var_ref (var, ctx);
2722
3d483a94 2723 /* FIXME: Not handled yet. */
2724 gcc_assert (!is_simd);
fd6481cf 2725 if (is_reference (var))
389dd41b 2726 x = build_fold_addr_expr_loc (clause_loc, x);
fd6481cf 2727 SET_DECL_VALUE_EXPR (placeholder, x);
2728 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
e3a19533 2729 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
75a70cf9 2730 gimple_seq_add_seq (ilist,
2731 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c));
2732 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
fd6481cf 2733 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
1e8e9920 2734 }
2735 else
2736 {
2737 x = omp_reduction_init (c, TREE_TYPE (new_var));
2738 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
3d483a94 2739 if (is_simd
2740 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
2741 idx, lane, ivar, lvar))
2742 {
2743 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
2744 tree ref = build_outer_var_ref (var, ctx);
2745
2746 gimplify_assign (unshare_expr (ivar), x, &llist[0]);
2747
2748 /* reduction(-:var) sums up the partial results, so it
2749 acts identically to reduction(+:var). */
2750 if (code == MINUS_EXPR)
2751 code = PLUS_EXPR;
2752
2753 x = build2 (code, TREE_TYPE (ref), ref, ivar);
2754 ref = build_outer_var_ref (var, ctx);
2755 gimplify_assign (ref, x, &llist[1]);
2756 }
2757 else
2758 {
2759 gimplify_assign (new_var, x, ilist);
2760 if (is_simd)
2761 gimplify_assign (build_outer_var_ref (var, ctx),
2762 new_var, dlist);
2763 }
1e8e9920 2764 }
2765 break;
2766
2767 default:
2768 gcc_unreachable ();
2769 }
2770 }
2771 }
2772
3d483a94 2773 if (lane)
2774 {
2775 tree uid = create_tmp_var (ptr_type_node, "simduid");
2776 gimple g
2777 = gimple_build_call_internal (IFN_GOMP_SIMD_LANE, 1, uid);
2778 gimple_call_set_lhs (g, lane);
2779 gimple_stmt_iterator gsi = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
2780 gsi_insert_before_without_update (&gsi, g, GSI_SAME_STMT);
2781 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SIMDUID_);
2782 OMP_CLAUSE__SIMDUID__DECL (c) = uid;
2783 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
2784 gimple_omp_for_set_clauses (ctx->stmt, c);
2785 g = gimple_build_assign_with_ops (INTEGER_CST, lane,
2786 build_int_cst (unsigned_type_node, 0),
2787 NULL_TREE);
2788 gimple_seq_add_stmt (ilist, g);
2789 for (int i = 0; i < 2; i++)
2790 if (llist[i])
2791 {
2792 tree vf = create_tmp_var (unsigned_type_node, NULL);
2793 g = gimple_build_call_internal (IFN_GOMP_SIMD_VF, 1, uid);
2794 gimple_call_set_lhs (g, vf);
2795 gimple_seq *seq = i == 0 ? ilist : dlist;
2796 gimple_seq_add_stmt (seq, g);
2797 tree t = build_int_cst (unsigned_type_node, 0);
2798 g = gimple_build_assign_with_ops (INTEGER_CST, idx, t, NULL_TREE);
2799 gimple_seq_add_stmt (seq, g);
2800 tree body = create_artificial_label (UNKNOWN_LOCATION);
2801 tree header = create_artificial_label (UNKNOWN_LOCATION);
2802 tree end = create_artificial_label (UNKNOWN_LOCATION);
2803 gimple_seq_add_stmt (seq, gimple_build_goto (header));
2804 gimple_seq_add_stmt (seq, gimple_build_label (body));
2805 gimple_seq_add_seq (seq, llist[i]);
2806 t = build_int_cst (unsigned_type_node, 1);
2807 g = gimple_build_assign_with_ops (PLUS_EXPR, idx, idx, t);
2808 gimple_seq_add_stmt (seq, g);
2809 gimple_seq_add_stmt (seq, gimple_build_label (header));
2810 g = gimple_build_cond (LT_EXPR, idx, vf, body, end);
2811 gimple_seq_add_stmt (seq, g);
2812 gimple_seq_add_stmt (seq, gimple_build_label (end));
2813 }
2814 }
2815
1e8e9920 2816 /* The copyin sequence is not to be executed by the main thread, since
2817 that would result in self-copies. Perhaps not visible to scalars,
2818 but it certainly is to C++ operator=. */
2819 if (copyin_seq)
2820 {
b9a16870 2821 x = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM),
2822 0);
1e8e9920 2823 x = build2 (NE_EXPR, boolean_type_node, x,
2824 build_int_cst (TREE_TYPE (x), 0));
2825 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
2826 gimplify_and_add (x, ilist);
2827 }
2828
2829 /* If any copyin variable is passed by reference, we must ensure the
2830 master thread doesn't modify it before it is copied over in all
f49d7bb5 2831 threads. Similarly for variables in both firstprivate and
2832 lastprivate clauses we need to ensure the lastprivate copying
2833 happens after firstprivate copying in all threads. */
2834 if (copyin_by_ref || lastprivate_firstprivate)
3d483a94 2835 {
2836 /* Don't add any barrier for #pragma omp simd or
2837 #pragma omp distribute. */
2838 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
2839 || gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_FOR)
2840 gimplify_and_add (build_omp_barrier (), ilist);
2841 }
2842
2843 /* If max_vf is non-zero, then we can use only a vectorization factor
2844 up to the max_vf we chose. So stick it into the safelen clause. */
2845 if (max_vf)
2846 {
2847 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2848 OMP_CLAUSE_SAFELEN);
2849 if (c == NULL_TREE
2850 || compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
2851 max_vf) == 1)
2852 {
2853 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_SAFELEN);
2854 OMP_CLAUSE_SAFELEN_EXPR (c) = build_int_cst (integer_type_node,
2855 max_vf);
2856 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
2857 gimple_omp_for_set_clauses (ctx->stmt, c);
2858 }
2859 }
1e8e9920 2860}
2861
773c5ba7 2862
1e8e9920 2863/* Generate code to implement the LASTPRIVATE clauses. This is used for
2864 both parallel and workshare constructs. PREDICATE may be NULL if it's
2865 always true. */
2866
2867static void
75a70cf9 2868lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
2869 omp_context *ctx)
1e8e9920 2870{
3d483a94 2871 tree x, c, label = NULL, orig_clauses = clauses;
fd6481cf 2872 bool par_clauses = false;
3d483a94 2873 tree simduid = NULL, lastlane = NULL;
1e8e9920 2874
3d483a94 2875 /* Early exit if there are no lastprivate or linear clauses. */
2876 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
2877 if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LASTPRIVATE
2878 || (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LINEAR
2879 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses)))
2880 break;
1e8e9920 2881 if (clauses == NULL)
2882 {
2883 /* If this was a workshare clause, see if it had been combined
2884 with its parallel. In that case, look for the clauses on the
2885 parallel statement itself. */
2886 if (is_parallel_ctx (ctx))
2887 return;
2888
2889 ctx = ctx->outer;
2890 if (ctx == NULL || !is_parallel_ctx (ctx))
2891 return;
2892
75a70cf9 2893 clauses = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
1e8e9920 2894 OMP_CLAUSE_LASTPRIVATE);
2895 if (clauses == NULL)
2896 return;
fd6481cf 2897 par_clauses = true;
1e8e9920 2898 }
2899
75a70cf9 2900 if (predicate)
2901 {
2902 gimple stmt;
2903 tree label_true, arm1, arm2;
2904
e60a6f7b 2905 label = create_artificial_label (UNKNOWN_LOCATION);
2906 label_true = create_artificial_label (UNKNOWN_LOCATION);
75a70cf9 2907 arm1 = TREE_OPERAND (predicate, 0);
2908 arm2 = TREE_OPERAND (predicate, 1);
2909 gimplify_expr (&arm1, stmt_list, NULL, is_gimple_val, fb_rvalue);
2910 gimplify_expr (&arm2, stmt_list, NULL, is_gimple_val, fb_rvalue);
2911 stmt = gimple_build_cond (TREE_CODE (predicate), arm1, arm2,
2912 label_true, label);
2913 gimple_seq_add_stmt (stmt_list, stmt);
2914 gimple_seq_add_stmt (stmt_list, gimple_build_label (label_true));
2915 }
1e8e9920 2916
3d483a94 2917 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
2918 && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD)
2919 {
2920 simduid = find_omp_clause (orig_clauses, OMP_CLAUSE__SIMDUID_);
2921 if (simduid)
2922 simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
2923 }
2924
fd6481cf 2925 for (c = clauses; c ;)
1e8e9920 2926 {
2927 tree var, new_var;
389dd41b 2928 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
1e8e9920 2929
3d483a94 2930 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
2931 || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
2932 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
fd6481cf 2933 {
2934 var = OMP_CLAUSE_DECL (c);
2935 new_var = lookup_decl (var, ctx);
1e8e9920 2936
3d483a94 2937 if (simduid && DECL_HAS_VALUE_EXPR_P (new_var))
2938 {
2939 tree val = DECL_VALUE_EXPR (new_var);
2940 if (TREE_CODE (val) == ARRAY_REF
2941 && VAR_P (TREE_OPERAND (val, 0))
2942 && lookup_attribute ("omp simd array",
2943 DECL_ATTRIBUTES (TREE_OPERAND (val,
2944 0))))
2945 {
2946 if (lastlane == NULL)
2947 {
2948 lastlane = create_tmp_var (unsigned_type_node, NULL);
2949 gimple g
2950 = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE,
2951 2, simduid,
2952 TREE_OPERAND (val, 1));
2953 gimple_call_set_lhs (g, lastlane);
2954 gimple_seq_add_stmt (stmt_list, g);
2955 }
2956 new_var = build4 (ARRAY_REF, TREE_TYPE (val),
2957 TREE_OPERAND (val, 0), lastlane,
2958 NULL_TREE, NULL_TREE);
2959 }
2960 }
2961
2962 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
2963 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
75a70cf9 2964 {
e3a19533 2965 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
75a70cf9 2966 gimple_seq_add_seq (stmt_list,
2967 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
3d483a94 2968 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) = NULL;
75a70cf9 2969 }
1e8e9920 2970
fd6481cf 2971 x = build_outer_var_ref (var, ctx);
2972 if (is_reference (var))
182cf5a9 2973 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
fd6481cf 2974 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
75a70cf9 2975 gimplify_and_add (x, stmt_list);
fd6481cf 2976 }
2977 c = OMP_CLAUSE_CHAIN (c);
2978 if (c == NULL && !par_clauses)
2979 {
2980 /* If this was a workshare clause, see if it had been combined
2981 with its parallel. In that case, continue looking for the
2982 clauses also on the parallel statement itself. */
2983 if (is_parallel_ctx (ctx))
2984 break;
2985
2986 ctx = ctx->outer;
2987 if (ctx == NULL || !is_parallel_ctx (ctx))
2988 break;
2989
75a70cf9 2990 c = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
fd6481cf 2991 OMP_CLAUSE_LASTPRIVATE);
2992 par_clauses = true;
2993 }
1e8e9920 2994 }
2995
75a70cf9 2996 if (label)
2997 gimple_seq_add_stmt (stmt_list, gimple_build_label (label));
1e8e9920 2998}
2999
773c5ba7 3000
1e8e9920 3001/* Generate code to implement the REDUCTION clauses. */
3002
3003static void
75a70cf9 3004lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
1e8e9920 3005{
75a70cf9 3006 gimple_seq sub_seq = NULL;
3007 gimple stmt;
3008 tree x, c;
1e8e9920 3009 int count = 0;
3010
3d483a94 3011 /* SIMD reductions are handled in lower_rec_input_clauses. */
3012 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3013 && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD)
3014 return;
3015
1e8e9920 3016 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
3017 update in that case, otherwise use a lock. */
3018 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
55d6e7cd 3019 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
1e8e9920 3020 {
3021 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3022 {
3023 /* Never use OMP_ATOMIC for array reductions. */
3024 count = -1;
3025 break;
3026 }
3027 count++;
3028 }
3029
3030 if (count == 0)
3031 return;
3032
3033 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3034 {
3035 tree var, ref, new_var;
3036 enum tree_code code;
389dd41b 3037 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
1e8e9920 3038
55d6e7cd 3039 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
1e8e9920 3040 continue;
3041
3042 var = OMP_CLAUSE_DECL (c);
3043 new_var = lookup_decl (var, ctx);
3044 if (is_reference (var))
182cf5a9 3045 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
1e8e9920 3046 ref = build_outer_var_ref (var, ctx);
3047 code = OMP_CLAUSE_REDUCTION_CODE (c);
773c5ba7 3048
3049 /* reduction(-:var) sums up the partial results, so it acts
3050 identically to reduction(+:var). */
1e8e9920 3051 if (code == MINUS_EXPR)
3052 code = PLUS_EXPR;
3053
3054 if (count == 1)
3055 {
389dd41b 3056 tree addr = build_fold_addr_expr_loc (clause_loc, ref);
1e8e9920 3057
3058 addr = save_expr (addr);
3059 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
389dd41b 3060 x = fold_build2_loc (clause_loc, code, TREE_TYPE (ref), ref, new_var);
1e8e9920 3061 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
75a70cf9 3062 gimplify_and_add (x, stmt_seqp);
1e8e9920 3063 return;
3064 }
3065
3066 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3067 {
3068 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
3069
3070 if (is_reference (var))
389dd41b 3071 ref = build_fold_addr_expr_loc (clause_loc, ref);
1e8e9920 3072 SET_DECL_VALUE_EXPR (placeholder, ref);
3073 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
e3a19533 3074 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
75a70cf9 3075 gimple_seq_add_seq (&sub_seq, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
3076 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
1e8e9920 3077 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
3078 }
3079 else
3080 {
3081 x = build2 (code, TREE_TYPE (ref), ref, new_var);
3082 ref = build_outer_var_ref (var, ctx);
75a70cf9 3083 gimplify_assign (ref, x, &sub_seq);
1e8e9920 3084 }
3085 }
3086
b9a16870 3087 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START),
3088 0);
75a70cf9 3089 gimple_seq_add_stmt (stmt_seqp, stmt);
1e8e9920 3090
75a70cf9 3091 gimple_seq_add_seq (stmt_seqp, sub_seq);
1e8e9920 3092
b9a16870 3093 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END),
3094 0);
75a70cf9 3095 gimple_seq_add_stmt (stmt_seqp, stmt);
1e8e9920 3096}
3097
773c5ba7 3098
1e8e9920 3099/* Generate code to implement the COPYPRIVATE clauses. */
3100
3101static void
75a70cf9 3102lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist,
1e8e9920 3103 omp_context *ctx)
3104{
3105 tree c;
3106
3107 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3108 {
cb561506 3109 tree var, new_var, ref, x;
1e8e9920 3110 bool by_ref;
389dd41b 3111 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
1e8e9920 3112
55d6e7cd 3113 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
1e8e9920 3114 continue;
3115
3116 var = OMP_CLAUSE_DECL (c);
e8a588af 3117 by_ref = use_pointer_for_field (var, NULL);
1e8e9920 3118
3119 ref = build_sender_ref (var, ctx);
cb561506 3120 x = new_var = lookup_decl_in_outer_ctx (var, ctx);
3121 if (by_ref)
3122 {
3123 x = build_fold_addr_expr_loc (clause_loc, new_var);
3124 x = fold_convert_loc (clause_loc, TREE_TYPE (ref), x);
3125 }
75a70cf9 3126 gimplify_assign (ref, x, slist);
1e8e9920 3127
cb561506 3128 ref = build_receiver_ref (var, false, ctx);
3129 if (by_ref)
3130 {
3131 ref = fold_convert_loc (clause_loc,
3132 build_pointer_type (TREE_TYPE (new_var)),
3133 ref);
3134 ref = build_fold_indirect_ref_loc (clause_loc, ref);
3135 }
1e8e9920 3136 if (is_reference (var))
3137 {
cb561506 3138 ref = fold_convert_loc (clause_loc, TREE_TYPE (new_var), ref);
182cf5a9 3139 ref = build_simple_mem_ref_loc (clause_loc, ref);
3140 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
1e8e9920 3141 }
cb561506 3142 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, ref);
1e8e9920 3143 gimplify_and_add (x, rlist);
3144 }
3145}
3146
773c5ba7 3147
1e8e9920 3148/* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
3149 and REDUCTION from the sender (aka parent) side. */
3150
3151static void
75a70cf9 3152lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
3153 omp_context *ctx)
1e8e9920 3154{
3155 tree c;
3156
3157 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3158 {
773c5ba7 3159 tree val, ref, x, var;
1e8e9920 3160 bool by_ref, do_in = false, do_out = false;
389dd41b 3161 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
1e8e9920 3162
55d6e7cd 3163 switch (OMP_CLAUSE_CODE (c))
1e8e9920 3164 {
fd6481cf 3165 case OMP_CLAUSE_PRIVATE:
3166 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
3167 break;
3168 continue;
1e8e9920 3169 case OMP_CLAUSE_FIRSTPRIVATE:
3170 case OMP_CLAUSE_COPYIN:
3171 case OMP_CLAUSE_LASTPRIVATE:
3172 case OMP_CLAUSE_REDUCTION:
3173 break;
3174 default:
3175 continue;
3176 }
3177
87b31375 3178 val = OMP_CLAUSE_DECL (c);
3179 var = lookup_decl_in_outer_ctx (val, ctx);
773c5ba7 3180
f49d7bb5 3181 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
3182 && is_global_var (var))
3183 continue;
1e8e9920 3184 if (is_variable_sized (val))
3185 continue;
e8a588af 3186 by_ref = use_pointer_for_field (val, NULL);
1e8e9920 3187
55d6e7cd 3188 switch (OMP_CLAUSE_CODE (c))
1e8e9920 3189 {
fd6481cf 3190 case OMP_CLAUSE_PRIVATE:
1e8e9920 3191 case OMP_CLAUSE_FIRSTPRIVATE:
3192 case OMP_CLAUSE_COPYIN:
3193 do_in = true;
3194 break;
3195
3196 case OMP_CLAUSE_LASTPRIVATE:
3197 if (by_ref || is_reference (val))
3198 {
3199 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3200 continue;
3201 do_in = true;
3202 }
3203 else
fd6481cf 3204 {
3205 do_out = true;
3206 if (lang_hooks.decls.omp_private_outer_ref (val))
3207 do_in = true;
3208 }
1e8e9920 3209 break;
3210
3211 case OMP_CLAUSE_REDUCTION:
3212 do_in = true;
3213 do_out = !(by_ref || is_reference (val));
3214 break;
3215
3216 default:
3217 gcc_unreachable ();
3218 }
3219
3220 if (do_in)
3221 {
3222 ref = build_sender_ref (val, ctx);
389dd41b 3223 x = by_ref ? build_fold_addr_expr_loc (clause_loc, var) : var;
75a70cf9 3224 gimplify_assign (ref, x, ilist);
fd6481cf 3225 if (is_task_ctx (ctx))
3226 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref, 1)) = NULL;
1e8e9920 3227 }
773c5ba7 3228
1e8e9920 3229 if (do_out)
3230 {
3231 ref = build_sender_ref (val, ctx);
75a70cf9 3232 gimplify_assign (var, ref, olist);
1e8e9920 3233 }
3234 }
3235}
3236
75a70cf9 3237/* Generate code to implement SHARED from the sender (aka parent)
3238 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
3239 list things that got automatically shared. */
1e8e9920 3240
3241static void
75a70cf9 3242lower_send_shared_vars (gimple_seq *ilist, gimple_seq *olist, omp_context *ctx)
1e8e9920 3243{
fd6481cf 3244 tree var, ovar, nvar, f, x, record_type;
1e8e9920 3245
3246 if (ctx->record_type == NULL)
3247 return;
773c5ba7 3248
fd6481cf 3249 record_type = ctx->srecord_type ? ctx->srecord_type : ctx->record_type;
1767a056 3250 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
1e8e9920 3251 {
3252 ovar = DECL_ABSTRACT_ORIGIN (f);
3253 nvar = maybe_lookup_decl (ovar, ctx);
3254 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
3255 continue;
3256
773c5ba7 3257 /* If CTX is a nested parallel directive. Find the immediately
3258 enclosing parallel or workshare construct that contains a
3259 mapping for OVAR. */
87b31375 3260 var = lookup_decl_in_outer_ctx (ovar, ctx);
773c5ba7 3261
e8a588af 3262 if (use_pointer_for_field (ovar, ctx))
1e8e9920 3263 {
3264 x = build_sender_ref (ovar, ctx);
773c5ba7 3265 var = build_fold_addr_expr (var);
75a70cf9 3266 gimplify_assign (x, var, ilist);
1e8e9920 3267 }
3268 else
3269 {
3270 x = build_sender_ref (ovar, ctx);
75a70cf9 3271 gimplify_assign (x, var, ilist);
1e8e9920 3272
d2263ebb 3273 if (!TREE_READONLY (var)
3274 /* We don't need to receive a new reference to a result
3275 or parm decl. In fact we may not store to it as we will
3276 invalidate any pending RSO and generate wrong gimple
3277 during inlining. */
3278 && !((TREE_CODE (var) == RESULT_DECL
3279 || TREE_CODE (var) == PARM_DECL)
3280 && DECL_BY_REFERENCE (var)))
fd6481cf 3281 {
3282 x = build_sender_ref (ovar, ctx);
75a70cf9 3283 gimplify_assign (var, x, olist);
fd6481cf 3284 }
1e8e9920 3285 }
3286 }
3287}
3288
75a70cf9 3289
3290/* A convenience function to build an empty GIMPLE_COND with just the
3291 condition. */
3292
3293static gimple
3294gimple_build_cond_empty (tree cond)
3295{
3296 enum tree_code pred_code;
3297 tree lhs, rhs;
3298
3299 gimple_cond_get_ops_from_tree (cond, &pred_code, &lhs, &rhs);
3300 return gimple_build_cond (pred_code, lhs, rhs, NULL_TREE, NULL_TREE);
3301}
3302
3303
48e1416a 3304/* Build the function calls to GOMP_parallel_start etc to actually
773c5ba7 3305 generate the parallel operation. REGION is the parallel region
3306 being expanded. BB is the block where to insert the code. WS_ARGS
3307 will be set if this is a call to a combined parallel+workshare
3308 construct, it contains the list of additional arguments needed by
3309 the workshare construct. */
1e8e9920 3310
3311static void
61e47ac8 3312expand_parallel_call (struct omp_region *region, basic_block bb,
f1f41a6c 3313 gimple entry_stmt, vec<tree, va_gc> *ws_args)
1e8e9920 3314{
79acaae1 3315 tree t, t1, t2, val, cond, c, clauses;
75a70cf9 3316 gimple_stmt_iterator gsi;
3317 gimple stmt;
b9a16870 3318 enum built_in_function start_ix;
3319 int start_ix2;
389dd41b 3320 location_t clause_loc;
f1f41a6c 3321 vec<tree, va_gc> *args;
773c5ba7 3322
75a70cf9 3323 clauses = gimple_omp_parallel_clauses (entry_stmt);
773c5ba7 3324
334ec2d8 3325 /* Determine what flavor of GOMP_parallel_start we will be
773c5ba7 3326 emitting. */
3327 start_ix = BUILT_IN_GOMP_PARALLEL_START;
3328 if (is_combined_parallel (region))
3329 {
61e47ac8 3330 switch (region->inner->type)
773c5ba7 3331 {
75a70cf9 3332 case GIMPLE_OMP_FOR:
fd6481cf 3333 gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
b9a16870 3334 start_ix2 = ((int)BUILT_IN_GOMP_PARALLEL_LOOP_STATIC_START
3335 + (region->inner->sched_kind
3336 == OMP_CLAUSE_SCHEDULE_RUNTIME
3337 ? 3 : region->inner->sched_kind));
3338 start_ix = (enum built_in_function)start_ix2;
61e47ac8 3339 break;
75a70cf9 3340 case GIMPLE_OMP_SECTIONS:
61e47ac8 3341 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS_START;
3342 break;
3343 default:
3344 gcc_unreachable ();
773c5ba7 3345 }
773c5ba7 3346 }
1e8e9920 3347
3348 /* By default, the value of NUM_THREADS is zero (selected at run time)
3349 and there is no conditional. */
3350 cond = NULL_TREE;
3351 val = build_int_cst (unsigned_type_node, 0);
3352
3353 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
3354 if (c)
3355 cond = OMP_CLAUSE_IF_EXPR (c);
3356
3357 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
3358 if (c)
389dd41b 3359 {
3360 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
3361 clause_loc = OMP_CLAUSE_LOCATION (c);
3362 }
3363 else
3364 clause_loc = gimple_location (entry_stmt);
1e8e9920 3365
3366 /* Ensure 'val' is of the correct type. */
389dd41b 3367 val = fold_convert_loc (clause_loc, unsigned_type_node, val);
1e8e9920 3368
3369 /* If we found the clause 'if (cond)', build either
3370 (cond != 0) or (cond ? val : 1u). */
3371 if (cond)
3372 {
75a70cf9 3373 gimple_stmt_iterator gsi;
773c5ba7 3374
3375 cond = gimple_boolify (cond);
3376
1e8e9920 3377 if (integer_zerop (val))
389dd41b 3378 val = fold_build2_loc (clause_loc,
3379 EQ_EXPR, unsigned_type_node, cond,
79acaae1 3380 build_int_cst (TREE_TYPE (cond), 0));
1e8e9920 3381 else
773c5ba7 3382 {
3383 basic_block cond_bb, then_bb, else_bb;
79acaae1 3384 edge e, e_then, e_else;
75a70cf9 3385 tree tmp_then, tmp_else, tmp_join, tmp_var;
79acaae1 3386
3387 tmp_var = create_tmp_var (TREE_TYPE (val), NULL);
3388 if (gimple_in_ssa_p (cfun))
3389 {
75a70cf9 3390 tmp_then = make_ssa_name (tmp_var, NULL);
3391 tmp_else = make_ssa_name (tmp_var, NULL);
3392 tmp_join = make_ssa_name (tmp_var, NULL);
79acaae1 3393 }
3394 else
3395 {
3396 tmp_then = tmp_var;
3397 tmp_else = tmp_var;
3398 tmp_join = tmp_var;
3399 }
773c5ba7 3400
773c5ba7 3401 e = split_block (bb, NULL);
3402 cond_bb = e->src;
3403 bb = e->dest;
3404 remove_edge (e);
3405
3406 then_bb = create_empty_bb (cond_bb);
3407 else_bb = create_empty_bb (then_bb);
79acaae1 3408 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
3409 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
773c5ba7 3410
75a70cf9 3411 stmt = gimple_build_cond_empty (cond);
3412 gsi = gsi_start_bb (cond_bb);
3413 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
773c5ba7 3414
75a70cf9 3415 gsi = gsi_start_bb (then_bb);
3416 stmt = gimple_build_assign (tmp_then, val);
3417 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
773c5ba7 3418
75a70cf9 3419 gsi = gsi_start_bb (else_bb);
3420 stmt = gimple_build_assign
3421 (tmp_else, build_int_cst (unsigned_type_node, 1));
3422 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
773c5ba7 3423
3424 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
3425 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
f6568ea4 3426 if (current_loops)
3427 {
3428 add_bb_to_loop (then_bb, cond_bb->loop_father);
3429 add_bb_to_loop (else_bb, cond_bb->loop_father);
3430 }
79acaae1 3431 e_then = make_edge (then_bb, bb, EDGE_FALLTHRU);
3432 e_else = make_edge (else_bb, bb, EDGE_FALLTHRU);
773c5ba7 3433
79acaae1 3434 if (gimple_in_ssa_p (cfun))
3435 {
75a70cf9 3436 gimple phi = create_phi_node (tmp_join, bb);
60d535d2 3437 add_phi_arg (phi, tmp_then, e_then, UNKNOWN_LOCATION);
3438 add_phi_arg (phi, tmp_else, e_else, UNKNOWN_LOCATION);
79acaae1 3439 }
3440
3441 val = tmp_join;
773c5ba7 3442 }
3443
75a70cf9 3444 gsi = gsi_start_bb (bb);
3445 val = force_gimple_operand_gsi (&gsi, val, true, NULL_TREE,
3446 false, GSI_CONTINUE_LINKING);
1e8e9920 3447 }
3448
75a70cf9 3449 gsi = gsi_last_bb (bb);
3450 t = gimple_omp_parallel_data_arg (entry_stmt);
1e8e9920 3451 if (t == NULL)
c2f47e15 3452 t1 = null_pointer_node;
1e8e9920 3453 else
c2f47e15 3454 t1 = build_fold_addr_expr (t);
75a70cf9 3455 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
773c5ba7 3456
f1f41a6c 3457 vec_alloc (args, 3 + vec_safe_length (ws_args));
3458 args->quick_push (t2);
3459 args->quick_push (t1);
3460 args->quick_push (val);
3461 if (ws_args)
3462 args->splice (*ws_args);
414c3a2c 3463
3464 t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
b9a16870 3465 builtin_decl_explicit (start_ix), args);
773c5ba7 3466
75a70cf9 3467 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
3468 false, GSI_CONTINUE_LINKING);
1e8e9920 3469
75a70cf9 3470 t = gimple_omp_parallel_data_arg (entry_stmt);
1e8e9920 3471 if (t == NULL)
3472 t = null_pointer_node;
3473 else
3474 t = build_fold_addr_expr (t);
389dd41b 3475 t = build_call_expr_loc (gimple_location (entry_stmt),
3476 gimple_omp_parallel_child_fn (entry_stmt), 1, t);
75a70cf9 3477 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
3478 false, GSI_CONTINUE_LINKING);
1e8e9920 3479
389dd41b 3480 t = build_call_expr_loc (gimple_location (entry_stmt),
b9a16870 3481 builtin_decl_explicit (BUILT_IN_GOMP_PARALLEL_END),
3482 0);
75a70cf9 3483 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
3484 false, GSI_CONTINUE_LINKING);
1e8e9920 3485}
3486
773c5ba7 3487
fd6481cf 3488/* Build the function call to GOMP_task to actually
3489 generate the task operation. BB is the block where to insert the code. */
3490
3491static void
75a70cf9 3492expand_task_call (basic_block bb, gimple entry_stmt)
fd6481cf 3493{
2169f33b 3494 tree t, t1, t2, t3, flags, cond, c, c2, clauses;
75a70cf9 3495 gimple_stmt_iterator gsi;
389dd41b 3496 location_t loc = gimple_location (entry_stmt);
fd6481cf 3497
75a70cf9 3498 clauses = gimple_omp_task_clauses (entry_stmt);
fd6481cf 3499
fd6481cf 3500 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
3501 if (c)
3502 cond = gimple_boolify (OMP_CLAUSE_IF_EXPR (c));
3503 else
3504 cond = boolean_true_node;
3505
3506 c = find_omp_clause (clauses, OMP_CLAUSE_UNTIED);
2169f33b 3507 c2 = find_omp_clause (clauses, OMP_CLAUSE_MERGEABLE);
3508 flags = build_int_cst (unsigned_type_node,
3509 (c ? 1 : 0) + (c2 ? 4 : 0));
3510
3511 c = find_omp_clause (clauses, OMP_CLAUSE_FINAL);
3512 if (c)
3513 {
3514 c = gimple_boolify (OMP_CLAUSE_FINAL_EXPR (c));
3515 c = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, c,
3516 build_int_cst (unsigned_type_node, 2),
3517 build_int_cst (unsigned_type_node, 0));
3518 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node, flags, c);
3519 }
fd6481cf 3520
75a70cf9 3521 gsi = gsi_last_bb (bb);
3522 t = gimple_omp_task_data_arg (entry_stmt);
fd6481cf 3523 if (t == NULL)
3524 t2 = null_pointer_node;
3525 else
389dd41b 3526 t2 = build_fold_addr_expr_loc (loc, t);
3527 t1 = build_fold_addr_expr_loc (loc, gimple_omp_task_child_fn (entry_stmt));
75a70cf9 3528 t = gimple_omp_task_copy_fn (entry_stmt);
fd6481cf 3529 if (t == NULL)
3530 t3 = null_pointer_node;
3531 else
389dd41b 3532 t3 = build_fold_addr_expr_loc (loc, t);
fd6481cf 3533
b9a16870 3534 t = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK),
3535 7, t1, t2, t3,
75a70cf9 3536 gimple_omp_task_arg_size (entry_stmt),
3537 gimple_omp_task_arg_align (entry_stmt), cond, flags);
fd6481cf 3538
75a70cf9 3539 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
3540 false, GSI_CONTINUE_LINKING);
fd6481cf 3541}
3542
3543
75a70cf9 3544/* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
3545 catch handler and return it. This prevents programs from violating the
3546 structured block semantics with throws. */
1e8e9920 3547
75a70cf9 3548static gimple_seq
3549maybe_catch_exception (gimple_seq body)
1e8e9920 3550{
e38def9c 3551 gimple g;
3552 tree decl;
1e8e9920 3553
3554 if (!flag_exceptions)
75a70cf9 3555 return body;
1e8e9920 3556
596981c8 3557 if (lang_hooks.eh_protect_cleanup_actions != NULL)
3558 decl = lang_hooks.eh_protect_cleanup_actions ();
1e8e9920 3559 else
b9a16870 3560 decl = builtin_decl_explicit (BUILT_IN_TRAP);
75a70cf9 3561
e38def9c 3562 g = gimple_build_eh_must_not_throw (decl);
3563 g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g),
75a70cf9 3564 GIMPLE_TRY_CATCH);
1e8e9920 3565
e38def9c 3566 return gimple_seq_alloc_with_stmt (g);
1e8e9920 3567}
3568
773c5ba7 3569/* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
1e8e9920 3570
773c5ba7 3571static tree
f1f41a6c 3572vec2chain (vec<tree, va_gc> *v)
1e8e9920 3573{
2ab2ce89 3574 tree chain = NULL_TREE, t;
3575 unsigned ix;
1e8e9920 3576
f1f41a6c 3577 FOR_EACH_VEC_SAFE_ELT_REVERSE (v, ix, t)
773c5ba7 3578 {
1767a056 3579 DECL_CHAIN (t) = chain;
2ab2ce89 3580 chain = t;
773c5ba7 3581 }
1e8e9920 3582
2ab2ce89 3583 return chain;
773c5ba7 3584}
1e8e9920 3585
1e8e9920 3586
773c5ba7 3587/* Remove barriers in REGION->EXIT's block. Note that this is only
75a70cf9 3588 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
3589 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
3590 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
773c5ba7 3591 removed. */
1e8e9920 3592
773c5ba7 3593static void
3594remove_exit_barrier (struct omp_region *region)
3595{
75a70cf9 3596 gimple_stmt_iterator gsi;
773c5ba7 3597 basic_block exit_bb;
61e47ac8 3598 edge_iterator ei;
3599 edge e;
75a70cf9 3600 gimple stmt;
4a04f4b4 3601 int any_addressable_vars = -1;
1e8e9920 3602
61e47ac8 3603 exit_bb = region->exit;
1e8e9920 3604
5056ba1a 3605 /* If the parallel region doesn't return, we don't have REGION->EXIT
3606 block at all. */
3607 if (! exit_bb)
3608 return;
3609
75a70cf9 3610 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
3611 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
61e47ac8 3612 statements that can appear in between are extremely limited -- no
3613 memory operations at all. Here, we allow nothing at all, so the
75a70cf9 3614 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
3615 gsi = gsi_last_bb (exit_bb);
3616 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
3617 gsi_prev (&gsi);
3618 if (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
773c5ba7 3619 return;
1e8e9920 3620
61e47ac8 3621 FOR_EACH_EDGE (e, ei, exit_bb->preds)
3622 {
75a70cf9 3623 gsi = gsi_last_bb (e->src);
3624 if (gsi_end_p (gsi))
61e47ac8 3625 continue;
75a70cf9 3626 stmt = gsi_stmt (gsi);
4a04f4b4 3627 if (gimple_code (stmt) == GIMPLE_OMP_RETURN
3628 && !gimple_omp_return_nowait_p (stmt))
3629 {
3630 /* OpenMP 3.0 tasks unfortunately prevent this optimization
3631 in many cases. If there could be tasks queued, the barrier
3632 might be needed to let the tasks run before some local
3633 variable of the parallel that the task uses as shared
3634 runs out of scope. The task can be spawned either
3635 from within current function (this would be easy to check)
3636 or from some function it calls and gets passed an address
3637 of such a variable. */
3638 if (any_addressable_vars < 0)
3639 {
3640 gimple parallel_stmt = last_stmt (region->entry);
3641 tree child_fun = gimple_omp_parallel_child_fn (parallel_stmt);
2ab2ce89 3642 tree local_decls, block, decl;
3643 unsigned ix;
4a04f4b4 3644
3645 any_addressable_vars = 0;
2ab2ce89 3646 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun), ix, decl)
3647 if (TREE_ADDRESSABLE (decl))
4a04f4b4 3648 {
3649 any_addressable_vars = 1;
3650 break;
3651 }
3652 for (block = gimple_block (stmt);
3653 !any_addressable_vars
3654 && block
3655 && TREE_CODE (block) == BLOCK;
3656 block = BLOCK_SUPERCONTEXT (block))
3657 {
3658 for (local_decls = BLOCK_VARS (block);
3659 local_decls;
1767a056 3660 local_decls = DECL_CHAIN (local_decls))
4a04f4b4 3661 if (TREE_ADDRESSABLE (local_decls))
3662 {
3663 any_addressable_vars = 1;
3664 break;
3665 }
3666 if (block == gimple_block (parallel_stmt))
3667 break;
3668 }
3669 }
3670 if (!any_addressable_vars)
3671 gimple_omp_return_set_nowait (stmt);
3672 }
61e47ac8 3673 }
1e8e9920 3674}
3675
61e47ac8 3676static void
3677remove_exit_barriers (struct omp_region *region)
3678{
75a70cf9 3679 if (region->type == GIMPLE_OMP_PARALLEL)
61e47ac8 3680 remove_exit_barrier (region);
3681
3682 if (region->inner)
3683 {
3684 region = region->inner;
3685 remove_exit_barriers (region);
3686 while (region->next)
3687 {
3688 region = region->next;
3689 remove_exit_barriers (region);
3690 }
3691 }
3692}
773c5ba7 3693
658b4427 3694/* Optimize omp_get_thread_num () and omp_get_num_threads ()
3695 calls. These can't be declared as const functions, but
3696 within one parallel body they are constant, so they can be
3697 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
fd6481cf 3698 which are declared const. Similarly for task body, except
3699 that in untied task omp_get_thread_num () can change at any task
3700 scheduling point. */
658b4427 3701
3702static void
75a70cf9 3703optimize_omp_library_calls (gimple entry_stmt)
658b4427 3704{
3705 basic_block bb;
75a70cf9 3706 gimple_stmt_iterator gsi;
b9a16870 3707 tree thr_num_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
3708 tree thr_num_id = DECL_ASSEMBLER_NAME (thr_num_tree);
3709 tree num_thr_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
3710 tree num_thr_id = DECL_ASSEMBLER_NAME (num_thr_tree);
75a70cf9 3711 bool untied_task = (gimple_code (entry_stmt) == GIMPLE_OMP_TASK
3712 && find_omp_clause (gimple_omp_task_clauses (entry_stmt),
fd6481cf 3713 OMP_CLAUSE_UNTIED) != NULL);
658b4427 3714
3715 FOR_EACH_BB (bb)
75a70cf9 3716 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
658b4427 3717 {
75a70cf9 3718 gimple call = gsi_stmt (gsi);
658b4427 3719 tree decl;
3720
75a70cf9 3721 if (is_gimple_call (call)
3722 && (decl = gimple_call_fndecl (call))
658b4427 3723 && DECL_EXTERNAL (decl)
3724 && TREE_PUBLIC (decl)
3725 && DECL_INITIAL (decl) == NULL)
3726 {
3727 tree built_in;
3728
3729 if (DECL_NAME (decl) == thr_num_id)
fd6481cf 3730 {
3731 /* In #pragma omp task untied omp_get_thread_num () can change
3732 during the execution of the task region. */
3733 if (untied_task)
3734 continue;
b9a16870 3735 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
fd6481cf 3736 }
658b4427 3737 else if (DECL_NAME (decl) == num_thr_id)
b9a16870 3738 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
658b4427 3739 else
3740 continue;
3741
3742 if (DECL_ASSEMBLER_NAME (decl) != DECL_ASSEMBLER_NAME (built_in)
75a70cf9 3743 || gimple_call_num_args (call) != 0)
658b4427 3744 continue;
3745
3746 if (flag_exceptions && !TREE_NOTHROW (decl))
3747 continue;
3748
3749 if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
1ea6a73c 3750 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl)),
3751 TREE_TYPE (TREE_TYPE (built_in))))
658b4427 3752 continue;
3753
0acacf9e 3754 gimple_call_set_fndecl (call, built_in);
658b4427 3755 }
3756 }
3757}
3758
8e6b4515 3759/* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
3760 regimplified. */
3761
3762static tree
3763expand_omp_regimplify_p (tree *tp, int *walk_subtrees, void *)
3764{
3765 tree t = *tp;
3766
3767 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
3768 if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t))
3769 return t;
3770
3771 if (TREE_CODE (t) == ADDR_EXPR)
3772 recompute_tree_invariant_for_addr_expr (t);
3773
3774 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
3775 return NULL_TREE;
3776}
3777
3d483a94 3778/* Prepend TO = FROM assignment before *GSI_P. */
3779
3780static void
3781expand_omp_build_assign (gimple_stmt_iterator *gsi_p, tree to, tree from)
3782{
3783 bool simple_p = DECL_P (to) && TREE_ADDRESSABLE (to);
3784 from = force_gimple_operand_gsi (gsi_p, from, simple_p, NULL_TREE,
3785 true, GSI_SAME_STMT);
3786 gimple stmt = gimple_build_assign (to, from);
3787 gsi_insert_before (gsi_p, stmt, GSI_SAME_STMT);
3788 if (walk_tree (&from, expand_omp_regimplify_p, NULL, NULL)
3789 || walk_tree (&to, expand_omp_regimplify_p, NULL, NULL))
3790 {
3791 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
3792 gimple_regimplify_operands (stmt, &gsi);
3793 }
3794}
3795
fd6481cf 3796/* Expand the OpenMP parallel or task directive starting at REGION. */
1e8e9920 3797
3798static void
fd6481cf 3799expand_omp_taskreg (struct omp_region *region)
1e8e9920 3800{
773c5ba7 3801 basic_block entry_bb, exit_bb, new_bb;
87d4aa85 3802 struct function *child_cfun;
414c3a2c 3803 tree child_fn, block, t;
75a70cf9 3804 gimple_stmt_iterator gsi;
3805 gimple entry_stmt, stmt;
773c5ba7 3806 edge e;
f1f41a6c 3807 vec<tree, va_gc> *ws_args;
773c5ba7 3808
61e47ac8 3809 entry_stmt = last_stmt (region->entry);
75a70cf9 3810 child_fn = gimple_omp_taskreg_child_fn (entry_stmt);
773c5ba7 3811 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
773c5ba7 3812
61e47ac8 3813 entry_bb = region->entry;
3814 exit_bb = region->exit;
773c5ba7 3815
773c5ba7 3816 if (is_combined_parallel (region))
61e47ac8 3817 ws_args = region->ws_args;
773c5ba7 3818 else
414c3a2c 3819 ws_args = NULL;
1e8e9920 3820
61e47ac8 3821 if (child_cfun->cfg)
1e8e9920 3822 {
773c5ba7 3823 /* Due to inlining, it may happen that we have already outlined
3824 the region, in which case all we need to do is make the
3825 sub-graph unreachable and emit the parallel call. */
3826 edge entry_succ_e, exit_succ_e;
75a70cf9 3827 gimple_stmt_iterator gsi;
773c5ba7 3828
3829 entry_succ_e = single_succ_edge (entry_bb);
773c5ba7 3830
75a70cf9 3831 gsi = gsi_last_bb (entry_bb);
3832 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_PARALLEL
3833 || gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_TASK);
3834 gsi_remove (&gsi, true);
773c5ba7 3835
3836 new_bb = entry_bb;
03ed154b 3837 if (exit_bb)
3838 {
3839 exit_succ_e = single_succ_edge (exit_bb);
3840 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
3841 }
79acaae1 3842 remove_edge_and_dominated_blocks (entry_succ_e);
1e8e9920 3843 }
773c5ba7 3844 else
3845 {
501bdd19 3846 unsigned srcidx, dstidx, num;
2ab2ce89 3847
773c5ba7 3848 /* If the parallel region needs data sent from the parent
3480139d 3849 function, then the very first statement (except possible
3850 tree profile counter updates) of the parallel body
773c5ba7 3851 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
3852 &.OMP_DATA_O is passed as an argument to the child function,
3853 we need to replace it with the argument as seen by the child
3854 function.
3855
3856 In most cases, this will end up being the identity assignment
3857 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
3858 a function call that has been inlined, the original PARM_DECL
3859 .OMP_DATA_I may have been converted into a different local
3860 variable. In which case, we need to keep the assignment. */
75a70cf9 3861 if (gimple_omp_taskreg_data_arg (entry_stmt))
773c5ba7 3862 {
3863 basic_block entry_succ_bb = single_succ (entry_bb);
75a70cf9 3864 gimple_stmt_iterator gsi;
3865 tree arg, narg;
3866 gimple parcopy_stmt = NULL;
1e8e9920 3867
75a70cf9 3868 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
3480139d 3869 {
75a70cf9 3870 gimple stmt;
3480139d 3871
75a70cf9 3872 gcc_assert (!gsi_end_p (gsi));
3873 stmt = gsi_stmt (gsi);
3874 if (gimple_code (stmt) != GIMPLE_ASSIGN)
cc6b725b 3875 continue;
3876
75a70cf9 3877 if (gimple_num_ops (stmt) == 2)
3480139d 3878 {
75a70cf9 3879 tree arg = gimple_assign_rhs1 (stmt);
3880
3881 /* We're ignore the subcode because we're
3882 effectively doing a STRIP_NOPS. */
3883
3884 if (TREE_CODE (arg) == ADDR_EXPR
3885 && TREE_OPERAND (arg, 0)
3886 == gimple_omp_taskreg_data_arg (entry_stmt))
3887 {
3888 parcopy_stmt = stmt;
3889 break;
3890 }
3480139d 3891 }
3892 }
79acaae1 3893
75a70cf9 3894 gcc_assert (parcopy_stmt != NULL);
79acaae1 3895 arg = DECL_ARGUMENTS (child_fn);
3896
3897 if (!gimple_in_ssa_p (cfun))
3898 {
75a70cf9 3899 if (gimple_assign_lhs (parcopy_stmt) == arg)
3900 gsi_remove (&gsi, true);
79acaae1 3901 else
75a70cf9 3902 {
3903 /* ?? Is setting the subcode really necessary ?? */
3904 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (arg));
3905 gimple_assign_set_rhs1 (parcopy_stmt, arg);
3906 }
79acaae1 3907 }
3908 else
3909 {
3910 /* If we are in ssa form, we must load the value from the default
3911 definition of the argument. That should not be defined now,
3912 since the argument is not used uninitialized. */
c6dfe037 3913 gcc_assert (ssa_default_def (cfun, arg) == NULL);
75a70cf9 3914 narg = make_ssa_name (arg, gimple_build_nop ());
c6dfe037 3915 set_ssa_default_def (cfun, arg, narg);
75a70cf9 3916 /* ?? Is setting the subcode really necessary ?? */
3917 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (narg));
3918 gimple_assign_set_rhs1 (parcopy_stmt, narg);
79acaae1 3919 update_stmt (parcopy_stmt);
3920 }
773c5ba7 3921 }
3922
3923 /* Declare local variables needed in CHILD_CFUN. */
3924 block = DECL_INITIAL (child_fn);
2ab2ce89 3925 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
e1a7ccb9 3926 /* The gimplifier could record temporaries in parallel/task block
3927 rather than in containing function's local_decls chain,
3928 which would mean cgraph missed finalizing them. Do it now. */
1767a056 3929 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
e1a7ccb9 3930 if (TREE_CODE (t) == VAR_DECL
3931 && TREE_STATIC (t)
3932 && !DECL_EXTERNAL (t))
3933 varpool_finalize_decl (t);
75a70cf9 3934 DECL_SAVED_TREE (child_fn) = NULL;
e3a19533 3935 /* We'll create a CFG for child_fn, so no gimple body is needed. */
3936 gimple_set_body (child_fn, NULL);
1d22f541 3937 TREE_USED (block) = 1;
773c5ba7 3938
79acaae1 3939 /* Reset DECL_CONTEXT on function arguments. */
1767a056 3940 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
773c5ba7 3941 DECL_CONTEXT (t) = child_fn;
3942
75a70cf9 3943 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
3944 so that it can be moved to the child function. */
3945 gsi = gsi_last_bb (entry_bb);
3946 stmt = gsi_stmt (gsi);
3947 gcc_assert (stmt && (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
3948 || gimple_code (stmt) == GIMPLE_OMP_TASK));
3949 gsi_remove (&gsi, true);
3950 e = split_block (entry_bb, stmt);
773c5ba7 3951 entry_bb = e->dest;
3952 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
3953
75a70cf9 3954 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
5056ba1a 3955 if (exit_bb)
3956 {
75a70cf9 3957 gsi = gsi_last_bb (exit_bb);
3958 gcc_assert (!gsi_end_p (gsi)
3959 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
3960 stmt = gimple_build_return (NULL);
3961 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
3962 gsi_remove (&gsi, true);
5056ba1a 3963 }
79acaae1 3964
3965 /* Move the parallel region into CHILD_CFUN. */
48e1416a 3966
79acaae1 3967 if (gimple_in_ssa_p (cfun))
3968 {
bcaa2770 3969 init_tree_ssa (child_cfun);
5084b2e4 3970 init_ssa_operands (child_cfun);
3971 child_cfun->gimple_df->in_ssa_p = true;
1d22f541 3972 block = NULL_TREE;
79acaae1 3973 }
1d22f541 3974 else
75a70cf9 3975 block = gimple_block (entry_stmt);
1d22f541 3976
3977 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
79acaae1 3978 if (exit_bb)
3979 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
04c2922b 3980 /* When the OMP expansion process cannot guarantee an up-to-date
3981 loop tree arrange for the child function to fixup loops. */
3982 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
3983 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
79acaae1 3984
1d22f541 3985 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
f1f41a6c 3986 num = vec_safe_length (child_cfun->local_decls);
501bdd19 3987 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
3988 {
f1f41a6c 3989 t = (*child_cfun->local_decls)[srcidx];
501bdd19 3990 if (DECL_CONTEXT (t) == cfun->decl)
3991 continue;
3992 if (srcidx != dstidx)
f1f41a6c 3993 (*child_cfun->local_decls)[dstidx] = t;
501bdd19 3994 dstidx++;
3995 }
3996 if (dstidx != num)
f1f41a6c 3997 vec_safe_truncate (child_cfun->local_decls, dstidx);
1d22f541 3998
79acaae1 3999 /* Inform the callgraph about the new function. */
82b40354 4000 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
79acaae1 4001 cgraph_add_new_function (child_fn, true);
4002
4003 /* Fix the callgraph edges for child_cfun. Those for cfun will be
4004 fixed in a following pass. */
4005 push_cfun (child_cfun);
658b4427 4006 if (optimize)
fd6481cf 4007 optimize_omp_library_calls (entry_stmt);
79acaae1 4008 rebuild_cgraph_edges ();
fbe86b1b 4009
4010 /* Some EH regions might become dead, see PR34608. If
4011 pass_cleanup_cfg isn't the first pass to happen with the
4012 new child, these dead EH edges might cause problems.
4013 Clean them up now. */
4014 if (flag_exceptions)
4015 {
4016 basic_block bb;
fbe86b1b 4017 bool changed = false;
4018
fbe86b1b 4019 FOR_EACH_BB (bb)
75a70cf9 4020 changed |= gimple_purge_dead_eh_edges (bb);
fbe86b1b 4021 if (changed)
4022 cleanup_tree_cfg ();
fbe86b1b 4023 }
dd277d48 4024 if (gimple_in_ssa_p (cfun))
4025 update_ssa (TODO_update_ssa);
79acaae1 4026 pop_cfun ();
773c5ba7 4027 }
48e1416a 4028
773c5ba7 4029 /* Emit a library call to launch the children threads. */
75a70cf9 4030 if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
fd6481cf 4031 expand_parallel_call (region, new_bb, entry_stmt, ws_args);
4032 else
4033 expand_task_call (new_bb, entry_stmt);
083152fb 4034 if (gimple_in_ssa_p (cfun))
4035 update_ssa (TODO_update_ssa_only_virtuals);
1e8e9920 4036}
4037
773c5ba7 4038
3d483a94 4039/* Helper function for expand_omp_{for_*,simd}. If this is the outermost
4040 of the combined collapse > 1 loop constructs, generate code like:
4041 if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
4042 if (cond3 is <)
4043 adj = STEP3 - 1;
4044 else
4045 adj = STEP3 + 1;
4046 count3 = (adj + N32 - N31) / STEP3;
4047 if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
4048 if (cond2 is <)
4049 adj = STEP2 - 1;
4050 else
4051 adj = STEP2 + 1;
4052 count2 = (adj + N22 - N21) / STEP2;
4053 if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
4054 if (cond1 is <)
4055 adj = STEP1 - 1;
4056 else
4057 adj = STEP1 + 1;
4058 count1 = (adj + N12 - N11) / STEP1;
4059 count = count1 * count2 * count3;
4060 Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
4061 count = 0;
4062 and set ZERO_ITER_BB to that bb. */
4063
4064/* NOTE: It *could* be better to moosh all of the BBs together,
4065 creating one larger BB with all the computation and the unexpected
4066 jump at the end. I.e.
4067
4068 bool zero3, zero2, zero1, zero;
4069
4070 zero3 = N32 c3 N31;
4071 count3 = (N32 - N31) /[cl] STEP3;
4072 zero2 = N22 c2 N21;
4073 count2 = (N22 - N21) /[cl] STEP2;
4074 zero1 = N12 c1 N11;
4075 count1 = (N12 - N11) /[cl] STEP1;
4076 zero = zero3 || zero2 || zero1;
4077 count = count1 * count2 * count3;
4078 if (__builtin_expect(zero, false)) goto zero_iter_bb;
4079
4080 After all, we expect the zero=false, and thus we expect to have to
4081 evaluate all of the comparison expressions, so short-circuiting
4082 oughtn't be a win. Since the condition isn't protecting a
4083 denominator, we're not concerned about divide-by-zero, so we can
4084 fully evaluate count even if a numerator turned out to be wrong.
4085
4086 It seems like putting this all together would create much better
4087 scheduling opportunities, and less pressure on the chip's branch
4088 predictor. */
4089
4090static void
4091expand_omp_for_init_counts (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
4092 basic_block &entry_bb, tree *counts,
4093 basic_block &zero_iter_bb, int &first_zero_iter,
4094 basic_block &l2_dom_bb)
4095{
4096 tree t, type = TREE_TYPE (fd->loop.v);
4097 gimple stmt;
4098 edge e, ne;
4099 int i;
4100
4101 /* Collapsed loops need work for expansion into SSA form. */
4102 gcc_assert (!gimple_in_ssa_p (cfun));
4103
4104 for (i = 0; i < fd->collapse; i++)
4105 {
4106 tree itype = TREE_TYPE (fd->loops[i].v);
4107
4108 if (SSA_VAR_P (fd->loop.n2)
4109 && ((t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
4110 fold_convert (itype, fd->loops[i].n1),
4111 fold_convert (itype, fd->loops[i].n2)))
4112 == NULL_TREE || !integer_onep (t)))
4113 {
4114 tree n1, n2;
4115 n1 = fold_convert (itype, unshare_expr (fd->loops[i].n1));
4116 n1 = force_gimple_operand_gsi (gsi, n1, true, NULL_TREE,
4117 true, GSI_SAME_STMT);
4118 n2 = fold_convert (itype, unshare_expr (fd->loops[i].n2));
4119 n2 = force_gimple_operand_gsi (gsi, n2, true, NULL_TREE,
4120 true, GSI_SAME_STMT);
4121 stmt = gimple_build_cond (fd->loops[i].cond_code, n1, n2,
4122 NULL_TREE, NULL_TREE);
4123 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
4124 if (walk_tree (gimple_cond_lhs_ptr (stmt),
4125 expand_omp_regimplify_p, NULL, NULL)
4126 || walk_tree (gimple_cond_rhs_ptr (stmt),
4127 expand_omp_regimplify_p, NULL, NULL))
4128 {
4129 *gsi = gsi_for_stmt (stmt);
4130 gimple_regimplify_operands (stmt, gsi);
4131 }
4132 e = split_block (entry_bb, stmt);
4133 if (zero_iter_bb == NULL)
4134 {
4135 first_zero_iter = i;
4136 zero_iter_bb = create_empty_bb (entry_bb);
4137 if (current_loops)
4138 add_bb_to_loop (zero_iter_bb, entry_bb->loop_father);
4139 *gsi = gsi_after_labels (zero_iter_bb);
4140 stmt = gimple_build_assign (fd->loop.n2,
4141 build_zero_cst (type));
4142 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
4143 set_immediate_dominator (CDI_DOMINATORS, zero_iter_bb,
4144 entry_bb);
4145 }
4146 ne = make_edge (entry_bb, zero_iter_bb, EDGE_FALSE_VALUE);
4147 ne->probability = REG_BR_PROB_BASE / 2000 - 1;
4148 e->flags = EDGE_TRUE_VALUE;
4149 e->probability = REG_BR_PROB_BASE - ne->probability;
4150 if (l2_dom_bb == NULL)
4151 l2_dom_bb = entry_bb;
4152 entry_bb = e->dest;
4153 *gsi = gsi_last_bb (entry_bb);
4154 }
4155
4156 if (POINTER_TYPE_P (itype))
4157 itype = signed_type_for (itype);
4158 t = build_int_cst (itype, (fd->loops[i].cond_code == LT_EXPR
4159 ? -1 : 1));
4160 t = fold_build2 (PLUS_EXPR, itype,
4161 fold_convert (itype, fd->loops[i].step), t);
4162 t = fold_build2 (PLUS_EXPR, itype, t,
4163 fold_convert (itype, fd->loops[i].n2));
4164 t = fold_build2 (MINUS_EXPR, itype, t,
4165 fold_convert (itype, fd->loops[i].n1));
4166 /* ?? We could probably use CEIL_DIV_EXPR instead of
4167 TRUNC_DIV_EXPR and adjusting by hand. Unless we can't
4168 generate the same code in the end because generically we
4169 don't know that the values involved must be negative for
4170 GT?? */
4171 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
4172 t = fold_build2 (TRUNC_DIV_EXPR, itype,
4173 fold_build1 (NEGATE_EXPR, itype, t),
4174 fold_build1 (NEGATE_EXPR, itype,
4175 fold_convert (itype,
4176 fd->loops[i].step)));
4177 else
4178 t = fold_build2 (TRUNC_DIV_EXPR, itype, t,
4179 fold_convert (itype, fd->loops[i].step));
4180 t = fold_convert (type, t);
4181 if (TREE_CODE (t) == INTEGER_CST)
4182 counts[i] = t;
4183 else
4184 {
4185 counts[i] = create_tmp_reg (type, ".count");
4186 expand_omp_build_assign (gsi, counts[i], t);
4187 }
4188 if (SSA_VAR_P (fd->loop.n2))
4189 {
4190 if (i == 0)
4191 t = counts[0];
4192 else
4193 t = fold_build2 (MULT_EXPR, type, fd->loop.n2, counts[i]);
4194 expand_omp_build_assign (gsi, fd->loop.n2, t);
4195 }
4196 }
4197}
4198
4199
4200/* Helper function for expand_omp_{for_*,simd}. Generate code like:
4201 T = V;
4202 V3 = N31 + (T % count3) * STEP3;
4203 T = T / count3;
4204 V2 = N21 + (T % count2) * STEP2;
4205 T = T / count2;
4206 V1 = N11 + T * STEP1;
4207 if this loop doesn't have an inner loop construct combined with it. */
4208
4209static void
4210expand_omp_for_init_vars (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
4211 tree *counts, tree startvar)
4212{
4213 int i;
4214 tree type = TREE_TYPE (fd->loop.v);
4215 tree tem = create_tmp_reg (type, ".tem");
4216 gimple stmt = gimple_build_assign (tem, startvar);
4217 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
4218
4219 for (i = fd->collapse - 1; i >= 0; i--)
4220 {
4221 tree vtype = TREE_TYPE (fd->loops[i].v), itype, t;
4222 itype = vtype;
4223 if (POINTER_TYPE_P (vtype))
4224 itype = signed_type_for (vtype);
4225 if (i != 0)
4226 t = fold_build2 (TRUNC_MOD_EXPR, type, tem, counts[i]);
4227 else
4228 t = tem;
4229 t = fold_convert (itype, t);
4230 t = fold_build2 (MULT_EXPR, itype, t,
4231 fold_convert (itype, fd->loops[i].step));
4232 if (POINTER_TYPE_P (vtype))
4233 t = fold_build_pointer_plus (fd->loops[i].n1, t);
4234 else
4235 t = fold_build2 (PLUS_EXPR, itype, fd->loops[i].n1, t);
4236 t = force_gimple_operand_gsi (gsi, t,
4237 DECL_P (fd->loops[i].v)
4238 && TREE_ADDRESSABLE (fd->loops[i].v),
4239 NULL_TREE, false,
4240 GSI_CONTINUE_LINKING);
4241 stmt = gimple_build_assign (fd->loops[i].v, t);
4242 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
4243 if (i != 0)
4244 {
4245 t = fold_build2 (TRUNC_DIV_EXPR, type, tem, counts[i]);
4246 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
4247 false, GSI_CONTINUE_LINKING);
4248 stmt = gimple_build_assign (tem, t);
4249 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
4250 }
4251 }
4252}
4253
4254
4255/* Helper function for expand_omp_for_*. Generate code like:
4256 L10:
4257 V3 += STEP3;
4258 if (V3 cond3 N32) goto BODY_BB; else goto L11;
4259 L11:
4260 V3 = N31;
4261 V2 += STEP2;
4262 if (V2 cond2 N22) goto BODY_BB; else goto L12;
4263 L12:
4264 V2 = N21;
4265 V1 += STEP1;
4266 goto BODY_BB; */
4267
4268static basic_block
4269extract_omp_for_update_vars (struct omp_for_data *fd, basic_block cont_bb,
4270 basic_block body_bb)
4271{
4272 basic_block last_bb, bb, collapse_bb = NULL;
4273 int i;
4274 gimple_stmt_iterator gsi;
4275 edge e;
4276 tree t;
4277 gimple stmt;
4278
4279 last_bb = cont_bb;
4280 for (i = fd->collapse - 1; i >= 0; i--)
4281 {
4282 tree vtype = TREE_TYPE (fd->loops[i].v);
4283
4284 bb = create_empty_bb (last_bb);
4285 if (current_loops)
4286 add_bb_to_loop (bb, last_bb->loop_father);
4287 gsi = gsi_start_bb (bb);
4288
4289 if (i < fd->collapse - 1)
4290 {
4291 e = make_edge (last_bb, bb, EDGE_FALSE_VALUE);
4292 e->probability = REG_BR_PROB_BASE / 8;
4293
4294 t = fd->loops[i + 1].n1;
4295 t = force_gimple_operand_gsi (&gsi, t,
4296 DECL_P (fd->loops[i + 1].v)
4297 && TREE_ADDRESSABLE (fd->loops[i
4298 + 1].v),
4299 NULL_TREE, false,
4300 GSI_CONTINUE_LINKING);
4301 stmt = gimple_build_assign (fd->loops[i + 1].v, t);
4302 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4303 }
4304 else
4305 collapse_bb = bb;
4306
4307 set_immediate_dominator (CDI_DOMINATORS, bb, last_bb);
4308
4309 if (POINTER_TYPE_P (vtype))
4310 t = fold_build_pointer_plus (fd->loops[i].v, fd->loops[i].step);
4311 else
4312 t = fold_build2 (PLUS_EXPR, vtype, fd->loops[i].v, fd->loops[i].step);
4313 t = force_gimple_operand_gsi (&gsi, t,
4314 DECL_P (fd->loops[i].v)
4315 && TREE_ADDRESSABLE (fd->loops[i].v),
4316 NULL_TREE, false, GSI_CONTINUE_LINKING);
4317 stmt = gimple_build_assign (fd->loops[i].v, t);
4318 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4319
4320 if (i > 0)
4321 {
4322 t = fd->loops[i].n2;
4323 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4324 false, GSI_CONTINUE_LINKING);
4325 tree v = fd->loops[i].v;
4326 if (DECL_P (v) && TREE_ADDRESSABLE (v))
4327 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
4328 false, GSI_CONTINUE_LINKING);
4329 t = fold_build2 (fd->loops[i].cond_code, boolean_type_node, v, t);
4330 stmt = gimple_build_cond_empty (t);
4331 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4332 e = make_edge (bb, body_bb, EDGE_TRUE_VALUE);
4333 e->probability = REG_BR_PROB_BASE * 7 / 8;
4334 }
4335 else
4336 make_edge (bb, body_bb, EDGE_FALLTHRU);
4337 last_bb = bb;
4338 }
4339
4340 return collapse_bb;
4341}
4342
4343
773c5ba7 4344/* A subroutine of expand_omp_for. Generate code for a parallel
1e8e9920 4345 loop with any schedule. Given parameters:
4346
4347 for (V = N1; V cond N2; V += STEP) BODY;
4348
4349 where COND is "<" or ">", we generate pseudocode
4350
4351 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
773c5ba7 4352 if (more) goto L0; else goto L3;
1e8e9920 4353 L0:
4354 V = istart0;
4355 iend = iend0;
4356 L1:
4357 BODY;
4358 V += STEP;
773c5ba7 4359 if (V cond iend) goto L1; else goto L2;
1e8e9920 4360 L2:
773c5ba7 4361 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
4362 L3:
1e8e9920 4363
773c5ba7 4364 If this is a combined omp parallel loop, instead of the call to
fd6481cf 4365 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
4366
4367 For collapsed loops, given parameters:
4368 collapse(3)
4369 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
4370 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
4371 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
4372 BODY;
4373
4374 we generate pseudocode
4375
8e6b4515 4376 if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
fd6481cf 4377 if (cond3 is <)
4378 adj = STEP3 - 1;
4379 else
4380 adj = STEP3 + 1;
4381 count3 = (adj + N32 - N31) / STEP3;
8e6b4515 4382 if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
fd6481cf 4383 if (cond2 is <)
4384 adj = STEP2 - 1;
4385 else
4386 adj = STEP2 + 1;
4387 count2 = (adj + N22 - N21) / STEP2;
8e6b4515 4388 if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
fd6481cf 4389 if (cond1 is <)
4390 adj = STEP1 - 1;
4391 else
4392 adj = STEP1 + 1;
4393 count1 = (adj + N12 - N11) / STEP1;
4394 count = count1 * count2 * count3;
8e6b4515 4395 goto Z1;
4396 Z0:
4397 count = 0;
4398 Z1:
fd6481cf 4399 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
4400 if (more) goto L0; else goto L3;
4401 L0:
4402 V = istart0;
4403 T = V;
4404 V3 = N31 + (T % count3) * STEP3;
4405 T = T / count3;
4406 V2 = N21 + (T % count2) * STEP2;
4407 T = T / count2;
4408 V1 = N11 + T * STEP1;
4409 iend = iend0;
4410 L1:
4411 BODY;
4412 V += 1;
4413 if (V < iend) goto L10; else goto L2;
4414 L10:
4415 V3 += STEP3;
4416 if (V3 cond3 N32) goto L1; else goto L11;
4417 L11:
4418 V3 = N31;
4419 V2 += STEP2;
4420 if (V2 cond2 N22) goto L1; else goto L12;
4421 L12:
4422 V2 = N21;
4423 V1 += STEP1;
4424 goto L1;
4425 L2:
4426 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
4427 L3:
4428
4429 */
1e8e9920 4430
61e47ac8 4431static void
773c5ba7 4432expand_omp_for_generic (struct omp_region *region,
4433 struct omp_for_data *fd,
1e8e9920 4434 enum built_in_function start_fn,
4435 enum built_in_function next_fn)
4436{
75a70cf9 4437 tree type, istart0, iend0, iend;
fd6481cf 4438 tree t, vmain, vback, bias = NULL_TREE;
4439 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, collapse_bb;
03ed154b 4440 basic_block l2_bb = NULL, l3_bb = NULL;
75a70cf9 4441 gimple_stmt_iterator gsi;
4442 gimple stmt;
773c5ba7 4443 bool in_combined_parallel = is_combined_parallel (region);
ac6e3339 4444 bool broken_loop = region->cont == NULL;
79acaae1 4445 edge e, ne;
fd6481cf 4446 tree *counts = NULL;
4447 int i;
ac6e3339 4448
4449 gcc_assert (!broken_loop || !in_combined_parallel);
fd6481cf 4450 gcc_assert (fd->iter_type == long_integer_type_node
4451 || !in_combined_parallel);
1e8e9920 4452
fd6481cf 4453 type = TREE_TYPE (fd->loop.v);
4454 istart0 = create_tmp_var (fd->iter_type, ".istart0");
4455 iend0 = create_tmp_var (fd->iter_type, ".iend0");
6d63fc03 4456 TREE_ADDRESSABLE (istart0) = 1;
4457 TREE_ADDRESSABLE (iend0) = 1;
1e8e9920 4458
fd6481cf 4459 /* See if we need to bias by LLONG_MIN. */
4460 if (fd->iter_type == long_long_unsigned_type_node
4461 && TREE_CODE (type) == INTEGER_TYPE
4462 && !TYPE_UNSIGNED (type))
4463 {
4464 tree n1, n2;
4465
4466 if (fd->loop.cond_code == LT_EXPR)
4467 {
4468 n1 = fd->loop.n1;
4469 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
4470 }
4471 else
4472 {
4473 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
4474 n2 = fd->loop.n1;
4475 }
4476 if (TREE_CODE (n1) != INTEGER_CST
4477 || TREE_CODE (n2) != INTEGER_CST
4478 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
4479 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
4480 }
4481
61e47ac8 4482 entry_bb = region->entry;
03ed154b 4483 cont_bb = region->cont;
fd6481cf 4484 collapse_bb = NULL;
ac6e3339 4485 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
4486 gcc_assert (broken_loop
4487 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
4488 l0_bb = split_edge (FALLTHRU_EDGE (entry_bb));
4489 l1_bb = single_succ (l0_bb);
4490 if (!broken_loop)
03ed154b 4491 {
4492 l2_bb = create_empty_bb (cont_bb);
ac6e3339 4493 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb);
4494 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
03ed154b 4495 }
ac6e3339 4496 else
4497 l2_bb = NULL;
4498 l3_bb = BRANCH_EDGE (entry_bb)->dest;
4499 exit_bb = region->exit;
773c5ba7 4500
75a70cf9 4501 gsi = gsi_last_bb (entry_bb);
fd6481cf 4502
75a70cf9 4503 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
fd6481cf 4504 if (fd->collapse > 1)
4505 {
8e6b4515 4506 int first_zero_iter = -1;
3d483a94 4507 basic_block zero_iter_bb = NULL, l2_dom_bb = NULL;
8e6b4515 4508
3d483a94 4509 counts = XALLOCAVEC (tree, fd->collapse);
4510 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
4511 zero_iter_bb, first_zero_iter,
4512 l2_dom_bb);
fd6481cf 4513
8e6b4515 4514 if (zero_iter_bb)
4515 {
4516 /* Some counts[i] vars might be uninitialized if
4517 some loop has zero iterations. But the body shouldn't
4518 be executed in that case, so just avoid uninit warnings. */
4519 for (i = first_zero_iter; i < fd->collapse; i++)
4520 if (SSA_VAR_P (counts[i]))
4521 TREE_NO_WARNING (counts[i]) = 1;
4522 gsi_prev (&gsi);
4523 e = split_block (entry_bb, gsi_stmt (gsi));
4524 entry_bb = e->dest;
4525 make_edge (zero_iter_bb, entry_bb, EDGE_FALLTHRU);
4526 gsi = gsi_last_bb (entry_bb);
4527 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
4528 get_immediate_dominator (CDI_DOMINATORS,
4529 zero_iter_bb));
4530 }
fd6481cf 4531 }
79acaae1 4532 if (in_combined_parallel)
4533 {
4534 /* In a combined parallel loop, emit a call to
4535 GOMP_loop_foo_next. */
b9a16870 4536 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
79acaae1 4537 build_fold_addr_expr (istart0),
4538 build_fold_addr_expr (iend0));
4539 }
4540 else
1e8e9920 4541 {
c2f47e15 4542 tree t0, t1, t2, t3, t4;
773c5ba7 4543 /* If this is not a combined parallel loop, emit a call to
4544 GOMP_loop_foo_start in ENTRY_BB. */
c2f47e15 4545 t4 = build_fold_addr_expr (iend0);
4546 t3 = build_fold_addr_expr (istart0);
fd6481cf 4547 t2 = fold_convert (fd->iter_type, fd->loop.step);
3d483a94 4548 t1 = fd->loop.n2;
4549 t0 = fd->loop.n1;
4550 if (POINTER_TYPE_P (TREE_TYPE (t0))
4551 && TYPE_PRECISION (TREE_TYPE (t0))
4552 != TYPE_PRECISION (fd->iter_type))
c799f233 4553 {
4554 /* Avoid casting pointers to integer of a different size. */
3cea8318 4555 tree itype = signed_type_for (type);
3d483a94 4556 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
4557 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
c799f233 4558 }
4559 else
4560 {
3d483a94 4561 t1 = fold_convert (fd->iter_type, t1);
4562 t0 = fold_convert (fd->iter_type, t0);
c799f233 4563 }
fd6481cf 4564 if (bias)
1e8e9920 4565 {
fd6481cf 4566 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
4567 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
4568 }
4569 if (fd->iter_type == long_integer_type_node)
4570 {
4571 if (fd->chunk_size)
4572 {
4573 t = fold_convert (fd->iter_type, fd->chunk_size);
b9a16870 4574 t = build_call_expr (builtin_decl_explicit (start_fn),
4575 6, t0, t1, t2, t, t3, t4);
fd6481cf 4576 }
4577 else
b9a16870 4578 t = build_call_expr (builtin_decl_explicit (start_fn),
4579 5, t0, t1, t2, t3, t4);
1e8e9920 4580 }
c2f47e15 4581 else
fd6481cf 4582 {
4583 tree t5;
4584 tree c_bool_type;
b9a16870 4585 tree bfn_decl;
fd6481cf 4586
4587 /* The GOMP_loop_ull_*start functions have additional boolean
4588 argument, true for < loops and false for > loops.
4589 In Fortran, the C bool type can be different from
4590 boolean_type_node. */
b9a16870 4591 bfn_decl = builtin_decl_explicit (start_fn);
4592 c_bool_type = TREE_TYPE (TREE_TYPE (bfn_decl));
fd6481cf 4593 t5 = build_int_cst (c_bool_type,
4594 fd->loop.cond_code == LT_EXPR ? 1 : 0);
4595 if (fd->chunk_size)
4596 {
b9a16870 4597 tree bfn_decl = builtin_decl_explicit (start_fn);
fd6481cf 4598 t = fold_convert (fd->iter_type, fd->chunk_size);
b9a16870 4599 t = build_call_expr (bfn_decl, 7, t5, t0, t1, t2, t, t3, t4);
fd6481cf 4600 }
4601 else
b9a16870 4602 t = build_call_expr (builtin_decl_explicit (start_fn),
4603 6, t5, t0, t1, t2, t3, t4);
fd6481cf 4604 }
1e8e9920 4605 }
fd6481cf 4606 if (TREE_TYPE (t) != boolean_type_node)
4607 t = fold_build2 (NE_EXPR, boolean_type_node,
4608 t, build_int_cst (TREE_TYPE (t), 0));
75a70cf9 4609 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4610 true, GSI_SAME_STMT);
4611 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
79acaae1 4612
75a70cf9 4613 /* Remove the GIMPLE_OMP_FOR statement. */
4614 gsi_remove (&gsi, true);
1e8e9920 4615
773c5ba7 4616 /* Iteration setup for sequential loop goes in L0_BB. */
3d483a94 4617 tree startvar = fd->loop.v;
4618 tree endvar = NULL_TREE;
4619
75a70cf9 4620 gsi = gsi_start_bb (l0_bb);
1efcacec 4621 t = istart0;
fd6481cf 4622 if (bias)
1efcacec 4623 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
3d483a94 4624 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
4625 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
4626 t = fold_convert (TREE_TYPE (startvar), t);
4abecb72 4627 t = force_gimple_operand_gsi (&gsi, t,
3d483a94 4628 DECL_P (startvar)
4629 && TREE_ADDRESSABLE (startvar),
4abecb72 4630 NULL_TREE, false, GSI_CONTINUE_LINKING);
3d483a94 4631 stmt = gimple_build_assign (startvar, t);
75a70cf9 4632 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
1e8e9920 4633
1efcacec 4634 t = iend0;
fd6481cf 4635 if (bias)
1efcacec 4636 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
3d483a94 4637 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
4638 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
4639 t = fold_convert (TREE_TYPE (startvar), t);
75a70cf9 4640 iend = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4641 false, GSI_CONTINUE_LINKING);
3d483a94 4642 if (endvar)
fd6481cf 4643 {
3d483a94 4644 stmt = gimple_build_assign (endvar, iend);
75a70cf9 4645 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
fd6481cf 4646 }
3d483a94 4647 if (fd->collapse > 1)
4648 expand_omp_for_init_vars (fd, &gsi, counts, startvar);
773c5ba7 4649
ac6e3339 4650 if (!broken_loop)
03ed154b 4651 {
ac6e3339 4652 /* Code to control the increment and predicate for the sequential
4653 loop goes in the CONT_BB. */
75a70cf9 4654 gsi = gsi_last_bb (cont_bb);
4655 stmt = gsi_stmt (gsi);
4656 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
4657 vmain = gimple_omp_continue_control_use (stmt);
4658 vback = gimple_omp_continue_control_def (stmt);
79acaae1 4659
3d483a94 4660 /* OMP4 placeholder: if (!gimple_omp_for_combined_p (fd->for_stmt)). */
4661 if (1)
4662 {
4663 if (POINTER_TYPE_P (type))
4664 t = fold_build_pointer_plus (vmain, fd->loop.step);
4665 else
4666 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
4667 t = force_gimple_operand_gsi (&gsi, t,
4668 DECL_P (vback)
4669 && TREE_ADDRESSABLE (vback),
4670 NULL_TREE, true, GSI_SAME_STMT);
4671 stmt = gimple_build_assign (vback, t);
4672 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
4673
4674 t = build2 (fd->loop.cond_code, boolean_type_node,
4675 DECL_P (vback) && TREE_ADDRESSABLE (vback) ? t : vback,
4676 iend);
4677 stmt = gimple_build_cond_empty (t);
4678 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
4679 }
773c5ba7 4680
75a70cf9 4681 /* Remove GIMPLE_OMP_CONTINUE. */
4682 gsi_remove (&gsi, true);
773c5ba7 4683
fd6481cf 4684 if (fd->collapse > 1)
3d483a94 4685 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, l1_bb);
fd6481cf 4686
ac6e3339 4687 /* Emit code to get the next parallel iteration in L2_BB. */
75a70cf9 4688 gsi = gsi_start_bb (l2_bb);
773c5ba7 4689
b9a16870 4690 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
ac6e3339 4691 build_fold_addr_expr (istart0),
4692 build_fold_addr_expr (iend0));
75a70cf9 4693 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4694 false, GSI_CONTINUE_LINKING);
fd6481cf 4695 if (TREE_TYPE (t) != boolean_type_node)
4696 t = fold_build2 (NE_EXPR, boolean_type_node,
4697 t, build_int_cst (TREE_TYPE (t), 0));
75a70cf9 4698 stmt = gimple_build_cond_empty (t);
4699 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
ac6e3339 4700 }
1e8e9920 4701
61e47ac8 4702 /* Add the loop cleanup function. */
75a70cf9 4703 gsi = gsi_last_bb (exit_bb);
4704 if (gimple_omp_return_nowait_p (gsi_stmt (gsi)))
b9a16870 4705 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
61e47ac8 4706 else
b9a16870 4707 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END);
75a70cf9 4708 stmt = gimple_build_call (t, 0);
4709 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
4710 gsi_remove (&gsi, true);
773c5ba7 4711
4712 /* Connect the new blocks. */
79acaae1 4713 find_edge (entry_bb, l0_bb)->flags = EDGE_TRUE_VALUE;
4714 find_edge (entry_bb, l3_bb)->flags = EDGE_FALSE_VALUE;
1e8e9920 4715
ac6e3339 4716 if (!broken_loop)
4717 {
75a70cf9 4718 gimple_seq phis;
4719
79acaae1 4720 e = find_edge (cont_bb, l3_bb);
4721 ne = make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
4722
75a70cf9 4723 phis = phi_nodes (l3_bb);
4724 for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi))
4725 {
4726 gimple phi = gsi_stmt (gsi);
4727 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, ne),
4728 PHI_ARG_DEF_FROM_EDGE (phi, e));
4729 }
79acaae1 4730 remove_edge (e);
4731
ac6e3339 4732 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
f6568ea4 4733 if (current_loops)
4734 add_bb_to_loop (l2_bb, cont_bb->loop_father);
3d483a94 4735 e = find_edge (cont_bb, l1_bb);
4736 /* OMP4 placeholder for gimple_omp_for_combined_p (fd->for_stmt). */
4737 if (0)
4738 ;
4739 else if (fd->collapse > 1)
fd6481cf 4740 {
fd6481cf 4741 remove_edge (e);
4742 e = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
4743 }
4744 else
3d483a94 4745 e->flags = EDGE_TRUE_VALUE;
4746 if (e)
fd6481cf 4747 {
3d483a94 4748 e->probability = REG_BR_PROB_BASE * 7 / 8;
4749 find_edge (cont_bb, l2_bb)->probability = REG_BR_PROB_BASE / 8;
4750 }
4751 else
4752 {
4753 e = find_edge (cont_bb, l2_bb);
4754 e->flags = EDGE_FALLTHRU;
fd6481cf 4755 }
ac6e3339 4756 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
79acaae1 4757
4758 set_immediate_dominator (CDI_DOMINATORS, l2_bb,
4759 recompute_dominator (CDI_DOMINATORS, l2_bb));
4760 set_immediate_dominator (CDI_DOMINATORS, l3_bb,
4761 recompute_dominator (CDI_DOMINATORS, l3_bb));
4762 set_immediate_dominator (CDI_DOMINATORS, l0_bb,
4763 recompute_dominator (CDI_DOMINATORS, l0_bb));
4764 set_immediate_dominator (CDI_DOMINATORS, l1_bb,
4765 recompute_dominator (CDI_DOMINATORS, l1_bb));
04c2922b 4766
4767 struct loop *outer_loop = alloc_loop ();
4768 outer_loop->header = l0_bb;
4769 outer_loop->latch = l2_bb;
4770 add_loop (outer_loop, l0_bb->loop_father);
4771
3d483a94 4772 /* OMP4 placeholder: if (!gimple_omp_for_combined_p (fd->for_stmt)). */
4773 if (1)
4774 {
4775 struct loop *loop = alloc_loop ();
4776 loop->header = l1_bb;
4777 /* The loop may have multiple latches. */
4778 add_loop (loop, outer_loop);
4779 }
ac6e3339 4780 }
1e8e9920 4781}
4782
4783
773c5ba7 4784/* A subroutine of expand_omp_for. Generate code for a parallel
4785 loop with static schedule and no specified chunk size. Given
4786 parameters:
1e8e9920 4787
4788 for (V = N1; V cond N2; V += STEP) BODY;
4789
4790 where COND is "<" or ">", we generate pseudocode
4791
8e6b4515 4792 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
1e8e9920 4793 if (cond is <)
4794 adj = STEP - 1;
4795 else
4796 adj = STEP + 1;
fd6481cf 4797 if ((__typeof (V)) -1 > 0 && cond is >)
4798 n = -(adj + N2 - N1) / -STEP;
4799 else
4800 n = (adj + N2 - N1) / STEP;
1e8e9920 4801 q = n / nthreads;
31712e83 4802 tt = n % nthreads;
4803 if (threadid < tt) goto L3; else goto L4;
4804 L3:
4805 tt = 0;
4806 q = q + 1;
4807 L4:
4808 s0 = q * threadid + tt;
4809 e0 = s0 + q;
79acaae1 4810 V = s0 * STEP + N1;
1e8e9920 4811 if (s0 >= e0) goto L2; else goto L0;
4812 L0:
1e8e9920 4813 e = e0 * STEP + N1;
4814 L1:
4815 BODY;
4816 V += STEP;
4817 if (V cond e) goto L1;
1e8e9920 4818 L2:
4819*/
4820
61e47ac8 4821static void
773c5ba7 4822expand_omp_for_static_nochunk (struct omp_region *region,
4823 struct omp_for_data *fd)
1e8e9920 4824{
31712e83 4825 tree n, q, s0, e0, e, t, tt, nthreads, threadid;
fd6481cf 4826 tree type, itype, vmain, vback;
31712e83 4827 basic_block entry_bb, second_bb, third_bb, exit_bb, seq_start_bb;
4828 basic_block body_bb, cont_bb;
61e47ac8 4829 basic_block fin_bb;
75a70cf9 4830 gimple_stmt_iterator gsi;
4831 gimple stmt;
31712e83 4832 edge ep;
1e8e9920 4833
fd6481cf 4834 itype = type = TREE_TYPE (fd->loop.v);
4835 if (POINTER_TYPE_P (type))
3cea8318 4836 itype = signed_type_for (type);
1e8e9920 4837
61e47ac8 4838 entry_bb = region->entry;
61e47ac8 4839 cont_bb = region->cont;
ac6e3339 4840 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
4841 gcc_assert (BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
4842 seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb));
4843 body_bb = single_succ (seq_start_bb);
4844 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
4845 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
4846 fin_bb = FALLTHRU_EDGE (cont_bb)->dest;
61e47ac8 4847 exit_bb = region->exit;
4848
773c5ba7 4849 /* Iteration space partitioning goes in ENTRY_BB. */
75a70cf9 4850 gsi = gsi_last_bb (entry_bb);
4851 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
61e47ac8 4852
8e6b4515 4853 t = fold_binary (fd->loop.cond_code, boolean_type_node,
4854 fold_convert (type, fd->loop.n1),
4855 fold_convert (type, fd->loop.n2));
4856 if (TYPE_UNSIGNED (type)
4857 && (t == NULL_TREE || !integer_onep (t)))
4858 {
4859 tree n1, n2;
4860 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
4861 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
4862 true, GSI_SAME_STMT);
4863 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
4864 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
4865 true, GSI_SAME_STMT);
4866 stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
4867 NULL_TREE, NULL_TREE);
4868 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
4869 if (walk_tree (gimple_cond_lhs_ptr (stmt),
4870 expand_omp_regimplify_p, NULL, NULL)
4871 || walk_tree (gimple_cond_rhs_ptr (stmt),
4872 expand_omp_regimplify_p, NULL, NULL))
4873 {
4874 gsi = gsi_for_stmt (stmt);
4875 gimple_regimplify_operands (stmt, &gsi);
4876 }
4877 ep = split_block (entry_bb, stmt);
4878 ep->flags = EDGE_TRUE_VALUE;
4879 entry_bb = ep->dest;
4880 ep->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
4881 ep = make_edge (ep->src, fin_bb, EDGE_FALSE_VALUE);
4882 ep->probability = REG_BR_PROB_BASE / 2000 - 1;
4883 if (gimple_in_ssa_p (cfun))
4884 {
4885 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
4886 for (gsi = gsi_start_phis (fin_bb);
4887 !gsi_end_p (gsi); gsi_next (&gsi))
4888 {
4889 gimple phi = gsi_stmt (gsi);
4890 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
4891 ep, UNKNOWN_LOCATION);
4892 }
4893 }
4894 gsi = gsi_last_bb (entry_bb);
4895 }
4896
b9a16870 4897 t = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS), 0);
fd6481cf 4898 t = fold_convert (itype, t);
75a70cf9 4899 nthreads = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4900 true, GSI_SAME_STMT);
48e1416a 4901
b9a16870 4902 t = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM), 0);
fd6481cf 4903 t = fold_convert (itype, t);
75a70cf9 4904 threadid = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4905 true, GSI_SAME_STMT);
1e8e9920 4906
fd6481cf 4907 fd->loop.n1
75a70cf9 4908 = force_gimple_operand_gsi (&gsi, fold_convert (type, fd->loop.n1),
4909 true, NULL_TREE, true, GSI_SAME_STMT);
fd6481cf 4910 fd->loop.n2
75a70cf9 4911 = force_gimple_operand_gsi (&gsi, fold_convert (itype, fd->loop.n2),
4912 true, NULL_TREE, true, GSI_SAME_STMT);
fd6481cf 4913 fd->loop.step
75a70cf9 4914 = force_gimple_operand_gsi (&gsi, fold_convert (itype, fd->loop.step),
4915 true, NULL_TREE, true, GSI_SAME_STMT);
fd6481cf 4916
4917 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
4918 t = fold_build2 (PLUS_EXPR, itype, fd->loop.step, t);
4919 t = fold_build2 (PLUS_EXPR, itype, t, fd->loop.n2);
4920 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, fd->loop.n1));
4921 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
4922 t = fold_build2 (TRUNC_DIV_EXPR, itype,
4923 fold_build1 (NEGATE_EXPR, itype, t),
4924 fold_build1 (NEGATE_EXPR, itype, fd->loop.step));
4925 else
4926 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, fd->loop.step);
4927 t = fold_convert (itype, t);
75a70cf9 4928 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
1e8e9920 4929
072f7ab1 4930 q = create_tmp_reg (itype, "q");
fd6481cf 4931 t = fold_build2 (TRUNC_DIV_EXPR, itype, n, nthreads);
31712e83 4932 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
4933 gsi_insert_before (&gsi, gimple_build_assign (q, t), GSI_SAME_STMT);
4934
072f7ab1 4935 tt = create_tmp_reg (itype, "tt");
31712e83 4936 t = fold_build2 (TRUNC_MOD_EXPR, itype, n, nthreads);
4937 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
4938 gsi_insert_before (&gsi, gimple_build_assign (tt, t), GSI_SAME_STMT);
1e8e9920 4939
31712e83 4940 t = build2 (LT_EXPR, boolean_type_node, threadid, tt);
4941 stmt = gimple_build_cond_empty (t);
4942 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
4943
4944 second_bb = split_block (entry_bb, stmt)->dest;
4945 gsi = gsi_last_bb (second_bb);
4946 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
4947
4948 gsi_insert_before (&gsi, gimple_build_assign (tt, build_int_cst (itype, 0)),
4949 GSI_SAME_STMT);
4950 stmt = gimple_build_assign_with_ops (PLUS_EXPR, q, q,
4951 build_int_cst (itype, 1));
4952 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
4953
4954 third_bb = split_block (second_bb, stmt)->dest;
4955 gsi = gsi_last_bb (third_bb);
4956 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
1e8e9920 4957
fd6481cf 4958 t = build2 (MULT_EXPR, itype, q, threadid);
31712e83 4959 t = build2 (PLUS_EXPR, itype, t, tt);
75a70cf9 4960 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
1e8e9920 4961
fd6481cf 4962 t = fold_build2 (PLUS_EXPR, itype, s0, q);
75a70cf9 4963 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
79acaae1 4964
1e8e9920 4965 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
75a70cf9 4966 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
773c5ba7 4967
75a70cf9 4968 /* Remove the GIMPLE_OMP_FOR statement. */
4969 gsi_remove (&gsi, true);
773c5ba7 4970
4971 /* Setup code for sequential iteration goes in SEQ_START_BB. */
75a70cf9 4972 gsi = gsi_start_bb (seq_start_bb);
1e8e9920 4973
fd6481cf 4974 t = fold_convert (itype, s0);
4975 t = fold_build2 (MULT_EXPR, itype, t, fd->loop.step);
4976 if (POINTER_TYPE_P (type))
2cc66f2a 4977 t = fold_build_pointer_plus (fd->loop.n1, t);
fd6481cf 4978 else
4979 t = fold_build2 (PLUS_EXPR, type, t, fd->loop.n1);
4abecb72 4980 t = force_gimple_operand_gsi (&gsi, t,
4981 DECL_P (fd->loop.v)
4982 && TREE_ADDRESSABLE (fd->loop.v),
4983 NULL_TREE, false, GSI_CONTINUE_LINKING);
75a70cf9 4984 stmt = gimple_build_assign (fd->loop.v, t);
4985 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
48e1416a 4986
fd6481cf 4987 t = fold_convert (itype, e0);
4988 t = fold_build2 (MULT_EXPR, itype, t, fd->loop.step);
4989 if (POINTER_TYPE_P (type))
2cc66f2a 4990 t = fold_build_pointer_plus (fd->loop.n1, t);
fd6481cf 4991 else
4992 t = fold_build2 (PLUS_EXPR, type, t, fd->loop.n1);
75a70cf9 4993 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4994 false, GSI_CONTINUE_LINKING);
1e8e9920 4995
75a70cf9 4996 /* The code controlling the sequential loop replaces the
4997 GIMPLE_OMP_CONTINUE. */
4998 gsi = gsi_last_bb (cont_bb);
4999 stmt = gsi_stmt (gsi);
5000 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
5001 vmain = gimple_omp_continue_control_use (stmt);
5002 vback = gimple_omp_continue_control_def (stmt);
79acaae1 5003
fd6481cf 5004 if (POINTER_TYPE_P (type))
2cc66f2a 5005 t = fold_build_pointer_plus (vmain, fd->loop.step);
fd6481cf 5006 else
5007 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
4abecb72 5008 t = force_gimple_operand_gsi (&gsi, t,
5009 DECL_P (vback) && TREE_ADDRESSABLE (vback),
5010 NULL_TREE, true, GSI_SAME_STMT);
75a70cf9 5011 stmt = gimple_build_assign (vback, t);
5012 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
79acaae1 5013
4abecb72 5014 t = build2 (fd->loop.cond_code, boolean_type_node,
5015 DECL_P (vback) && TREE_ADDRESSABLE (vback) ? t : vback, e);
75a70cf9 5016 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
1e8e9920 5017
75a70cf9 5018 /* Remove the GIMPLE_OMP_CONTINUE statement. */
5019 gsi_remove (&gsi, true);
773c5ba7 5020
75a70cf9 5021 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
5022 gsi = gsi_last_bb (exit_bb);
5023 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
5024 force_gimple_operand_gsi (&gsi, build_omp_barrier (), false, NULL_TREE,
5025 false, GSI_SAME_STMT);
5026 gsi_remove (&gsi, true);
773c5ba7 5027
5028 /* Connect all the blocks. */
31712e83 5029 ep = make_edge (entry_bb, third_bb, EDGE_FALSE_VALUE);
5030 ep->probability = REG_BR_PROB_BASE / 4 * 3;
5031 ep = find_edge (entry_bb, second_bb);
5032 ep->flags = EDGE_TRUE_VALUE;
5033 ep->probability = REG_BR_PROB_BASE / 4;
5034 find_edge (third_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
5035 find_edge (third_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
79acaae1 5036
ac6e3339 5037 find_edge (cont_bb, body_bb)->flags = EDGE_TRUE_VALUE;
61e47ac8 5038 find_edge (cont_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
48e1416a 5039
31712e83 5040 set_immediate_dominator (CDI_DOMINATORS, second_bb, entry_bb);
5041 set_immediate_dominator (CDI_DOMINATORS, third_bb, entry_bb);
5042 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, third_bb);
79acaae1 5043 set_immediate_dominator (CDI_DOMINATORS, body_bb,
5044 recompute_dominator (CDI_DOMINATORS, body_bb));
5045 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
5046 recompute_dominator (CDI_DOMINATORS, fin_bb));
04c2922b 5047
5048 struct loop *loop = alloc_loop ();
5049 loop->header = body_bb;
5050 loop->latch = cont_bb;
5051 add_loop (loop, body_bb->loop_father);
1e8e9920 5052}
5053
773c5ba7 5054
5055/* A subroutine of expand_omp_for. Generate code for a parallel
5056 loop with static schedule and a specified chunk size. Given
5057 parameters:
1e8e9920 5058
5059 for (V = N1; V cond N2; V += STEP) BODY;
5060
5061 where COND is "<" or ">", we generate pseudocode
5062
8e6b4515 5063 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
1e8e9920 5064 if (cond is <)
5065 adj = STEP - 1;
5066 else
5067 adj = STEP + 1;
fd6481cf 5068 if ((__typeof (V)) -1 > 0 && cond is >)
5069 n = -(adj + N2 - N1) / -STEP;
5070 else
5071 n = (adj + N2 - N1) / STEP;
1e8e9920 5072 trip = 0;
79acaae1 5073 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
5074 here so that V is defined
5075 if the loop is not entered
1e8e9920 5076 L0:
5077 s0 = (trip * nthreads + threadid) * CHUNK;
5078 e0 = min(s0 + CHUNK, n);
5079 if (s0 < n) goto L1; else goto L4;
5080 L1:
5081 V = s0 * STEP + N1;
5082 e = e0 * STEP + N1;
5083 L2:
5084 BODY;
5085 V += STEP;
5086 if (V cond e) goto L2; else goto L3;
5087 L3:
5088 trip += 1;
5089 goto L0;
5090 L4:
1e8e9920 5091*/
5092
61e47ac8 5093static void
75a70cf9 5094expand_omp_for_static_chunk (struct omp_region *region, struct omp_for_data *fd)
1e8e9920 5095{
75a70cf9 5096 tree n, s0, e0, e, t;
79acaae1 5097 tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
75a70cf9 5098 tree type, itype, v_main, v_back, v_extra;
773c5ba7 5099 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
61e47ac8 5100 basic_block trip_update_bb, cont_bb, fin_bb;
75a70cf9 5101 gimple_stmt_iterator si;
5102 gimple stmt;
5103 edge se;
1e8e9920 5104
fd6481cf 5105 itype = type = TREE_TYPE (fd->loop.v);
5106 if (POINTER_TYPE_P (type))
3cea8318 5107 itype = signed_type_for (type);
1e8e9920 5108
61e47ac8 5109 entry_bb = region->entry;
ac6e3339 5110 se = split_block (entry_bb, last_stmt (entry_bb));
5111 entry_bb = se->src;
5112 iter_part_bb = se->dest;
61e47ac8 5113 cont_bb = region->cont;
ac6e3339 5114 gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
5115 gcc_assert (BRANCH_EDGE (iter_part_bb)->dest
5116 == FALLTHRU_EDGE (cont_bb)->dest);
5117 seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
5118 body_bb = single_succ (seq_start_bb);
5119 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
5120 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
5121 fin_bb = FALLTHRU_EDGE (cont_bb)->dest;
5122 trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
61e47ac8 5123 exit_bb = region->exit;
773c5ba7 5124
773c5ba7 5125 /* Trip and adjustment setup goes in ENTRY_BB. */
75a70cf9 5126 si = gsi_last_bb (entry_bb);
5127 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_FOR);
773c5ba7 5128
8e6b4515 5129 t = fold_binary (fd->loop.cond_code, boolean_type_node,
5130 fold_convert (type, fd->loop.n1),
5131 fold_convert (type, fd->loop.n2));
5132 if (TYPE_UNSIGNED (type)
5133 && (t == NULL_TREE || !integer_onep (t)))
5134 {
5135 tree n1, n2;
5136 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
5137 n1 = force_gimple_operand_gsi (&si, n1, true, NULL_TREE,
5138 true, GSI_SAME_STMT);
5139 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
5140 n2 = force_gimple_operand_gsi (&si, n2, true, NULL_TREE,
5141 true, GSI_SAME_STMT);
5142 stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
5143 NULL_TREE, NULL_TREE);
5144 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
5145 if (walk_tree (gimple_cond_lhs_ptr (stmt),
5146 expand_omp_regimplify_p, NULL, NULL)
5147 || walk_tree (gimple_cond_rhs_ptr (stmt),
5148 expand_omp_regimplify_p, NULL, NULL))
5149 {
5150 si = gsi_for_stmt (stmt);
5151 gimple_regimplify_operands (stmt, &si);
5152 }
5153 se = split_block (entry_bb, stmt);
5154 se->flags = EDGE_TRUE_VALUE;
5155 entry_bb = se->dest;
5156 se->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
5157 se = make_edge (se->src, fin_bb, EDGE_FALSE_VALUE);
5158 se->probability = REG_BR_PROB_BASE / 2000 - 1;
5159 if (gimple_in_ssa_p (cfun))
5160 {
5161 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
5162 for (si = gsi_start_phis (fin_bb);
5163 !gsi_end_p (si); gsi_next (&si))
5164 {
5165 gimple phi = gsi_stmt (si);
5166 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
5167 se, UNKNOWN_LOCATION);
5168 }
5169 }
5170 si = gsi_last_bb (entry_bb);
5171 }
5172
b9a16870 5173 t = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS), 0);
fd6481cf 5174 t = fold_convert (itype, t);
75a70cf9 5175 nthreads = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
5176 true, GSI_SAME_STMT);
48e1416a 5177
b9a16870 5178 t = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM), 0);
fd6481cf 5179 t = fold_convert (itype, t);
75a70cf9 5180 threadid = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
5181 true, GSI_SAME_STMT);
79acaae1 5182
fd6481cf 5183 fd->loop.n1
75a70cf9 5184 = force_gimple_operand_gsi (&si, fold_convert (type, fd->loop.n1),
5185 true, NULL_TREE, true, GSI_SAME_STMT);
fd6481cf 5186 fd->loop.n2
75a70cf9 5187 = force_gimple_operand_gsi (&si, fold_convert (itype, fd->loop.n2),
5188 true, NULL_TREE, true, GSI_SAME_STMT);
fd6481cf 5189 fd->loop.step
75a70cf9 5190 = force_gimple_operand_gsi (&si, fold_convert (itype, fd->loop.step),
5191 true, NULL_TREE, true, GSI_SAME_STMT);
79acaae1 5192 fd->chunk_size
75a70cf9 5193 = force_gimple_operand_gsi (&si, fold_convert (itype, fd->chunk_size),
5194 true, NULL_TREE, true, GSI_SAME_STMT);
fd6481cf 5195
5196 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
5197 t = fold_build2 (PLUS_EXPR, itype, fd->loop.step, t);
5198 t = fold_build2 (PLUS_EXPR, itype, t, fd->loop.n2);
5199 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, fd->loop.n1));
5200 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
5201 t = fold_build2 (TRUNC_DIV_EXPR, itype,
5202 fold_build1 (NEGATE_EXPR, itype, t),
5203 fold_build1 (NEGATE_EXPR, itype, fd->loop.step));
5204 else
5205 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, fd->loop.step);
5206 t = fold_convert (itype, t);
75a70cf9 5207 n = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
5208 true, GSI_SAME_STMT);
79acaae1 5209
083152fb 5210 trip_var = create_tmp_reg (itype, ".trip");
79acaae1 5211 if (gimple_in_ssa_p (cfun))
5212 {
75a70cf9 5213 trip_init = make_ssa_name (trip_var, NULL);
5214 trip_main = make_ssa_name (trip_var, NULL);
5215 trip_back = make_ssa_name (trip_var, NULL);
79acaae1 5216 }
1e8e9920 5217 else
79acaae1 5218 {
5219 trip_init = trip_var;
5220 trip_main = trip_var;
5221 trip_back = trip_var;
5222 }
1e8e9920 5223
75a70cf9 5224 stmt = gimple_build_assign (trip_init, build_int_cst (itype, 0));
5225 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
773c5ba7 5226
fd6481cf 5227 t = fold_build2 (MULT_EXPR, itype, threadid, fd->chunk_size);
5228 t = fold_build2 (MULT_EXPR, itype, t, fd->loop.step);
5229 if (POINTER_TYPE_P (type))
2cc66f2a 5230 t = fold_build_pointer_plus (fd->loop.n1, t);
fd6481cf 5231 else
5232 t = fold_build2 (PLUS_EXPR, type, t, fd->loop.n1);
75a70cf9 5233 v_extra = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
5234 true, GSI_SAME_STMT);
79acaae1 5235
75a70cf9 5236 /* Remove the GIMPLE_OMP_FOR. */
5237 gsi_remove (&si, true);
773c5ba7 5238
5239 /* Iteration space partitioning goes in ITER_PART_BB. */
75a70cf9 5240 si = gsi_last_bb (iter_part_bb);
1e8e9920 5241
fd6481cf 5242 t = fold_build2 (MULT_EXPR, itype, trip_main, nthreads);
5243 t = fold_build2 (PLUS_EXPR, itype, t, threadid);
5244 t = fold_build2 (MULT_EXPR, itype, t, fd->chunk_size);
75a70cf9 5245 s0 = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
5246 false, GSI_CONTINUE_LINKING);
1e8e9920 5247
fd6481cf 5248 t = fold_build2 (PLUS_EXPR, itype, s0, fd->chunk_size);
5249 t = fold_build2 (MIN_EXPR, itype, t, n);
75a70cf9 5250 e0 = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
5251 false, GSI_CONTINUE_LINKING);
1e8e9920 5252
5253 t = build2 (LT_EXPR, boolean_type_node, s0, n);
75a70cf9 5254 gsi_insert_after (&si, gimple_build_cond_empty (t), GSI_CONTINUE_LINKING);
773c5ba7 5255
5256 /* Setup code for sequential iteration goes in SEQ_START_BB. */
75a70cf9 5257 si = gsi_start_bb (seq_start_bb);
1e8e9920 5258
fd6481cf 5259 t = fold_convert (itype, s0);
5260 t = fold_build2 (MULT_EXPR, itype, t, fd->loop.step);
5261 if (POINTER_TYPE_P (type))
2cc66f2a 5262 t = fold_build_pointer_plus (fd->loop.n1, t);
fd6481cf 5263 else
5264 t = fold_build2 (PLUS_EXPR, type, t, fd->loop.n1);
4abecb72 5265 t = force_gimple_operand_gsi (&si, t,
5266 DECL_P (fd->loop.v)
5267 && TREE_ADDRESSABLE (fd->loop.v),
5268 NULL_TREE, false, GSI_CONTINUE_LINKING);
75a70cf9 5269 stmt = gimple_build_assign (fd->loop.v, t);
5270 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
1e8e9920 5271
fd6481cf 5272 t = fold_convert (itype, e0);
5273 t = fold_build2 (MULT_EXPR, itype, t, fd->loop.step);
5274 if (POINTER_TYPE_P (type))
2cc66f2a 5275 t = fold_build_pointer_plus (fd->loop.n1, t);
fd6481cf 5276 else
5277 t = fold_build2 (PLUS_EXPR, type, t, fd->loop.n1);
75a70cf9 5278 e = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
5279 false, GSI_CONTINUE_LINKING);
1e8e9920 5280
61e47ac8 5281 /* The code controlling the sequential loop goes in CONT_BB,
75a70cf9 5282 replacing the GIMPLE_OMP_CONTINUE. */
5283 si = gsi_last_bb (cont_bb);
5284 stmt = gsi_stmt (si);
5285 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
5286 v_main = gimple_omp_continue_control_use (stmt);
5287 v_back = gimple_omp_continue_control_def (stmt);
79acaae1 5288
fd6481cf 5289 if (POINTER_TYPE_P (type))
2cc66f2a 5290 t = fold_build_pointer_plus (v_main, fd->loop.step);
fd6481cf 5291 else
75a70cf9 5292 t = fold_build2 (PLUS_EXPR, type, v_main, fd->loop.step);
4abecb72 5293 if (DECL_P (v_back) && TREE_ADDRESSABLE (v_back))
5294 t = force_gimple_operand_gsi (&si, t, true, NULL_TREE,
5295 true, GSI_SAME_STMT);
75a70cf9 5296 stmt = gimple_build_assign (v_back, t);
5297 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
79acaae1 5298
4abecb72 5299 t = build2 (fd->loop.cond_code, boolean_type_node,
5300 DECL_P (v_back) && TREE_ADDRESSABLE (v_back)
5301 ? t : v_back, e);
75a70cf9 5302 gsi_insert_before (&si, gimple_build_cond_empty (t), GSI_SAME_STMT);
48e1416a 5303
75a70cf9 5304 /* Remove GIMPLE_OMP_CONTINUE. */
5305 gsi_remove (&si, true);
773c5ba7 5306
5307 /* Trip update code goes into TRIP_UPDATE_BB. */
75a70cf9 5308 si = gsi_start_bb (trip_update_bb);
1e8e9920 5309
fd6481cf 5310 t = build_int_cst (itype, 1);
5311 t = build2 (PLUS_EXPR, itype, trip_main, t);
75a70cf9 5312 stmt = gimple_build_assign (trip_back, t);
5313 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
1e8e9920 5314
75a70cf9 5315 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
5316 si = gsi_last_bb (exit_bb);
5317 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
5318 force_gimple_operand_gsi (&si, build_omp_barrier (), false, NULL_TREE,
5319 false, GSI_SAME_STMT);
5320 gsi_remove (&si, true);
1e8e9920 5321
773c5ba7 5322 /* Connect the new blocks. */
ac6e3339 5323 find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
5324 find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
79acaae1 5325
ac6e3339 5326 find_edge (cont_bb, body_bb)->flags = EDGE_TRUE_VALUE;
5327 find_edge (cont_bb, trip_update_bb)->flags = EDGE_FALSE_VALUE;
79acaae1 5328
ac6e3339 5329 redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb);
79acaae1 5330
5331 if (gimple_in_ssa_p (cfun))
5332 {
75a70cf9 5333 gimple_stmt_iterator psi;
5334 gimple phi;
5335 edge re, ene;
f1f41a6c 5336 edge_var_map_vector *head;
75a70cf9 5337 edge_var_map *vm;
5338 size_t i;
5339
79acaae1 5340 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
5341 remove arguments of the phi nodes in fin_bb. We need to create
5342 appropriate phi nodes in iter_part_bb instead. */
5343 se = single_pred_edge (fin_bb);
5344 re = single_succ_edge (trip_update_bb);
75a70cf9 5345 head = redirect_edge_var_map_vector (re);
79acaae1 5346 ene = single_succ_edge (entry_bb);
5347
75a70cf9 5348 psi = gsi_start_phis (fin_bb);
f1f41a6c 5349 for (i = 0; !gsi_end_p (psi) && head->iterate (i, &vm);
75a70cf9 5350 gsi_next (&psi), ++i)
79acaae1 5351 {
75a70cf9 5352 gimple nphi;
efbcb6de 5353 source_location locus;
75a70cf9 5354
5355 phi = gsi_stmt (psi);
5356 t = gimple_phi_result (phi);
5357 gcc_assert (t == redirect_edge_var_map_result (vm));
79acaae1 5358 nphi = create_phi_node (t, iter_part_bb);
79acaae1 5359
5360 t = PHI_ARG_DEF_FROM_EDGE (phi, se);
efbcb6de 5361 locus = gimple_phi_arg_location_from_edge (phi, se);
5362
fd6481cf 5363 /* A special case -- fd->loop.v is not yet computed in
5364 iter_part_bb, we need to use v_extra instead. */
5365 if (t == fd->loop.v)
79acaae1 5366 t = v_extra;
60d535d2 5367 add_phi_arg (nphi, t, ene, locus);
efbcb6de 5368 locus = redirect_edge_var_map_location (vm);
60d535d2 5369 add_phi_arg (nphi, redirect_edge_var_map_def (vm), re, locus);
75a70cf9 5370 }
f1f41a6c 5371 gcc_assert (!gsi_end_p (psi) && i == head->length ());
75a70cf9 5372 redirect_edge_var_map_clear (re);
5373 while (1)
5374 {
5375 psi = gsi_start_phis (fin_bb);
5376 if (gsi_end_p (psi))
5377 break;
5378 remove_phi_node (&psi, false);
79acaae1 5379 }
79acaae1 5380
5381 /* Make phi node for trip. */
5382 phi = create_phi_node (trip_main, iter_part_bb);
efbcb6de 5383 add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb),
60d535d2 5384 UNKNOWN_LOCATION);
efbcb6de 5385 add_phi_arg (phi, trip_init, single_succ_edge (entry_bb),
60d535d2 5386 UNKNOWN_LOCATION);
79acaae1 5387 }
5388
5389 set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
5390 set_immediate_dominator (CDI_DOMINATORS, iter_part_bb,
5391 recompute_dominator (CDI_DOMINATORS, iter_part_bb));
5392 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
5393 recompute_dominator (CDI_DOMINATORS, fin_bb));
5394 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb,
5395 recompute_dominator (CDI_DOMINATORS, seq_start_bb));
5396 set_immediate_dominator (CDI_DOMINATORS, body_bb,
5397 recompute_dominator (CDI_DOMINATORS, body_bb));
04c2922b 5398
5399 struct loop *trip_loop = alloc_loop ();
5400 trip_loop->header = iter_part_bb;
5401 trip_loop->latch = trip_update_bb;
5402 add_loop (trip_loop, iter_part_bb->loop_father);
5403
5404 struct loop *loop = alloc_loop ();
5405 loop->header = body_bb;
5406 loop->latch = cont_bb;
5407 add_loop (loop, trip_loop);
1e8e9920 5408}
5409
3d483a94 5410/* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
5411 loop. Given parameters:
5412
5413 for (V = N1; V cond N2; V += STEP) BODY;
5414
5415 where COND is "<" or ">", we generate pseudocode
5416
5417 V = N1;
5418 goto L1;
5419 L0:
5420 BODY;
5421 V += STEP;
5422 L1:
5423 if (V cond N2) goto L0; else goto L2;
5424 L2:
5425
5426 For collapsed loops, given parameters:
5427 collapse(3)
5428 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
5429 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
5430 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
5431 BODY;
5432
5433 we generate pseudocode
5434
5435 if (cond3 is <)
5436 adj = STEP3 - 1;
5437 else
5438 adj = STEP3 + 1;
5439 count3 = (adj + N32 - N31) / STEP3;
5440 if (cond2 is <)
5441 adj = STEP2 - 1;
5442 else
5443 adj = STEP2 + 1;
5444 count2 = (adj + N22 - N21) / STEP2;
5445 if (cond1 is <)
5446 adj = STEP1 - 1;
5447 else
5448 adj = STEP1 + 1;
5449 count1 = (adj + N12 - N11) / STEP1;
5450 count = count1 * count2 * count3;
5451 V = 0;
5452 V1 = N11;
5453 V2 = N21;
5454 V3 = N31;
5455 goto L1;
5456 L0:
5457 BODY;
5458 V += 1;
5459 V3 += STEP3;
5460 V2 += (V3 cond3 N32) ? 0 : STEP2;
5461 V3 = (V3 cond3 N32) ? V3 : N31;
5462 V1 += (V2 cond2 N22) ? 0 : STEP1;
5463 V2 = (V2 cond2 N22) ? V2 : N21;
5464 L1:
5465 if (V < count) goto L0; else goto L2;
5466 L2:
5467
5468 */
5469
5470static void
5471expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
5472{
5473 tree type, t;
5474 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, l2_bb, l2_dom_bb;
5475 gimple_stmt_iterator gsi;
5476 gimple stmt;
5477 bool broken_loop = region->cont == NULL;
5478 edge e, ne;
5479 tree *counts = NULL;
5480 int i;
5481 tree safelen = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
5482 OMP_CLAUSE_SAFELEN);
5483 tree simduid = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
5484 OMP_CLAUSE__SIMDUID_);
5485 tree n2;
5486
5487 type = TREE_TYPE (fd->loop.v);
5488 entry_bb = region->entry;
5489 cont_bb = region->cont;
5490 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
5491 gcc_assert (broken_loop
5492 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
5493 l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
5494 if (!broken_loop)
5495 {
5496 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
5497 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
5498 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
5499 l2_bb = BRANCH_EDGE (entry_bb)->dest;
5500 }
5501 else
5502 {
5503 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
5504 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
5505 l2_bb = single_succ (l1_bb);
5506 }
5507 exit_bb = region->exit;
5508 l2_dom_bb = NULL;
5509
5510 gsi = gsi_last_bb (entry_bb);
5511
5512 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
5513 /* Not needed in SSA form right now. */
5514 gcc_assert (!gimple_in_ssa_p (cfun));
5515 if (fd->collapse > 1)
5516 {
5517 int first_zero_iter = -1;
5518 basic_block zero_iter_bb = l2_bb;
5519
5520 counts = XALLOCAVEC (tree, fd->collapse);
5521 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
5522 zero_iter_bb, first_zero_iter,
5523 l2_dom_bb);
5524 }
5525 if (l2_dom_bb == NULL)
5526 l2_dom_bb = l1_bb;
5527
5528 n2 = fd->loop.n2;
5529 if (0)
5530 /* Place holder for gimple_omp_for_combined_into_p() in
5531 the upcoming gomp-4_0-branch merge. */;
5532 else
5533 {
5534 expand_omp_build_assign (&gsi, fd->loop.v,
5535 fold_convert (type, fd->loop.n1));
5536 if (fd->collapse > 1)
5537 for (i = 0; i < fd->collapse; i++)
5538 {
5539 tree itype = TREE_TYPE (fd->loops[i].v);
5540 if (POINTER_TYPE_P (itype))
5541 itype = signed_type_for (itype);
5542 t = fold_convert (TREE_TYPE (fd->loops[i].v), fd->loops[i].n1);
5543 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
5544 }
5545 }
5546
5547 /* Remove the GIMPLE_OMP_FOR statement. */
5548 gsi_remove (&gsi, true);
5549
5550 if (!broken_loop)
5551 {
5552 /* Code to control the increment goes in the CONT_BB. */
5553 gsi = gsi_last_bb (cont_bb);
5554 stmt = gsi_stmt (gsi);
5555 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
5556
5557 if (POINTER_TYPE_P (type))
5558 t = fold_build_pointer_plus (fd->loop.v, fd->loop.step);
5559 else
5560 t = fold_build2 (PLUS_EXPR, type, fd->loop.v, fd->loop.step);
5561 expand_omp_build_assign (&gsi, fd->loop.v, t);
5562
5563 if (fd->collapse > 1)
5564 {
5565 i = fd->collapse - 1;
5566 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
5567 {
5568 t = fold_convert (sizetype, fd->loops[i].step);
5569 t = fold_build_pointer_plus (fd->loops[i].v, t);
5570 }
5571 else
5572 {
5573 t = fold_convert (TREE_TYPE (fd->loops[i].v),
5574 fd->loops[i].step);
5575 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
5576 fd->loops[i].v, t);
5577 }
5578 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
5579
5580 for (i = fd->collapse - 1; i > 0; i--)
5581 {
5582 tree itype = TREE_TYPE (fd->loops[i].v);
5583 tree itype2 = TREE_TYPE (fd->loops[i - 1].v);
5584 if (POINTER_TYPE_P (itype2))
5585 itype2 = signed_type_for (itype2);
5586 t = build3 (COND_EXPR, itype2,
5587 build2 (fd->loops[i].cond_code, boolean_type_node,
5588 fd->loops[i].v,
5589 fold_convert (itype, fd->loops[i].n2)),
5590 build_int_cst (itype2, 0),
5591 fold_convert (itype2, fd->loops[i - 1].step));
5592 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i - 1].v)))
5593 t = fold_build_pointer_plus (fd->loops[i - 1].v, t);
5594 else
5595 t = fold_build2 (PLUS_EXPR, itype2, fd->loops[i - 1].v, t);
5596 expand_omp_build_assign (&gsi, fd->loops[i - 1].v, t);
5597
5598 t = build3 (COND_EXPR, itype,
5599 build2 (fd->loops[i].cond_code, boolean_type_node,
5600 fd->loops[i].v,
5601 fold_convert (itype, fd->loops[i].n2)),
5602 fd->loops[i].v,
5603 fold_convert (itype, fd->loops[i].n1));
5604 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
5605 }
5606 }
5607
5608 /* Remove GIMPLE_OMP_CONTINUE. */
5609 gsi_remove (&gsi, true);
5610 }
5611
5612 /* Emit the condition in L1_BB. */
5613 gsi = gsi_start_bb (l1_bb);
5614
5615 t = fold_convert (type, n2);
5616 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5617 false, GSI_CONTINUE_LINKING);
5618 t = build2 (fd->loop.cond_code, boolean_type_node, fd->loop.v, t);
5619 stmt = gimple_build_cond_empty (t);
5620 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5621 if (walk_tree (gimple_cond_lhs_ptr (stmt), expand_omp_regimplify_p,
5622 NULL, NULL)
5623 || walk_tree (gimple_cond_rhs_ptr (stmt), expand_omp_regimplify_p,
5624 NULL, NULL))
5625 {
5626 gsi = gsi_for_stmt (stmt);
5627 gimple_regimplify_operands (stmt, &gsi);
5628 }
5629
5630 /* Remove GIMPLE_OMP_RETURN. */
5631 gsi = gsi_last_bb (exit_bb);
5632 gsi_remove (&gsi, true);
5633
5634 /* Connect the new blocks. */
5635 remove_edge (FALLTHRU_EDGE (entry_bb));
5636
5637 if (!broken_loop)
5638 {
5639 remove_edge (BRANCH_EDGE (entry_bb));
5640 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
5641
5642 e = BRANCH_EDGE (l1_bb);
5643 ne = FALLTHRU_EDGE (l1_bb);
5644 e->flags = EDGE_TRUE_VALUE;
5645 }
5646 else
5647 {
5648 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
5649
5650 ne = single_succ_edge (l1_bb);
5651 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
5652
5653 }
5654 ne->flags = EDGE_FALSE_VALUE;
5655 e->probability = REG_BR_PROB_BASE * 7 / 8;
5656 ne->probability = REG_BR_PROB_BASE / 8;
5657
5658 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
5659 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
5660 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
5661
5662 if (!broken_loop)
5663 {
5664 struct loop *loop = alloc_loop ();
5665 loop->header = l1_bb;
5666 loop->latch = e->dest;
5667 add_loop (loop, l1_bb->loop_father);
5668 if (safelen == NULL_TREE)
5669 loop->safelen = INT_MAX;
5670 else
5671 {
5672 safelen = OMP_CLAUSE_SAFELEN_EXPR (safelen);
5673 if (!host_integerp (safelen, 1)
5674 || (unsigned HOST_WIDE_INT) tree_low_cst (safelen, 1)
5675 > INT_MAX)
5676 loop->safelen = INT_MAX;
5677 else
5678 loop->safelen = tree_low_cst (safelen, 1);
5679 if (loop->safelen == 1)
5680 loop->safelen = 0;
5681 }
5682 if (simduid)
5683 {
5684 loop->simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
5685 cfun->has_simduid_loops = true;
5686 }
5687 /* If not -fno-tree-vectorize, hint that we want to vectorize
5688 the loop. */
5689 if ((flag_tree_vectorize
5690 || !global_options_set.x_flag_tree_vectorize)
5691 && loop->safelen > 1)
5692 {
5693 loop->force_vect = true;
5694 cfun->has_force_vect_loops = true;
5695 }
5696 }
5697}
5698
1e8e9920 5699
773c5ba7 5700/* Expand the OpenMP loop defined by REGION. */
1e8e9920 5701
773c5ba7 5702static void
5703expand_omp_for (struct omp_region *region)
5704{
5705 struct omp_for_data fd;
fd6481cf 5706 struct omp_for_data_loop *loops;
1e8e9920 5707
fd6481cf 5708 loops
5709 = (struct omp_for_data_loop *)
75a70cf9 5710 alloca (gimple_omp_for_collapse (last_stmt (region->entry))
fd6481cf 5711 * sizeof (struct omp_for_data_loop));
fd6481cf 5712 extract_omp_for_data (last_stmt (region->entry), &fd, loops);
f77459c5 5713 region->sched_kind = fd.sched_kind;
1e8e9920 5714
b3a3ddec 5715 gcc_assert (EDGE_COUNT (region->entry->succs) == 2);
5716 BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
5717 FALLTHRU_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
5718 if (region->cont)
5719 {
5720 gcc_assert (EDGE_COUNT (region->cont->succs) == 2);
5721 BRANCH_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
5722 FALLTHRU_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
5723 }
04c2922b 5724 else
75de4aa2 5725 /* If there isn't a continue then this is a degerate case where
04c2922b 5726 the introduction of abnormal edges during lowering will prevent
5727 original loops from being detected. Fix that up. */
5728 loops_state_set (LOOPS_NEED_FIXUP);
b3a3ddec 5729
3d483a94 5730 if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_SIMD)
5731 expand_omp_simd (region, &fd);
5732 else if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
03ed154b 5733 && !fd.have_ordered
fd6481cf 5734 && fd.collapse == 1
ac6e3339 5735 && region->cont != NULL)
1e8e9920 5736 {
5737 if (fd.chunk_size == NULL)
61e47ac8 5738 expand_omp_for_static_nochunk (region, &fd);
1e8e9920 5739 else
61e47ac8 5740 expand_omp_for_static_chunk (region, &fd);
1e8e9920 5741 }
5742 else
5743 {
fd6481cf 5744 int fn_index, start_ix, next_ix;
5745
3d483a94 5746 gcc_assert (gimple_omp_for_kind (fd.for_stmt)
5747 == GF_OMP_FOR_KIND_FOR);
0416ca72 5748 if (fd.chunk_size == NULL
5749 && fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
5750 fd.chunk_size = integer_zero_node;
fd6481cf 5751 gcc_assert (fd.sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
5752 fn_index = (fd.sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
75a70cf9 5753 ? 3 : fd.sched_kind;
fd6481cf 5754 fn_index += fd.have_ordered * 4;
b9a16870 5755 start_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_START) + fn_index;
5756 next_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT) + fn_index;
fd6481cf 5757 if (fd.iter_type == long_long_unsigned_type_node)
5758 {
b9a16870 5759 start_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
5760 - (int)BUILT_IN_GOMP_LOOP_STATIC_START);
5761 next_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
5762 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT);
fd6481cf 5763 }
b9c74b4d 5764 expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
5765 (enum built_in_function) next_ix);
1e8e9920 5766 }
28c92cbb 5767
083152fb 5768 if (gimple_in_ssa_p (cfun))
5769 update_ssa (TODO_update_ssa_only_virtuals);
1e8e9920 5770}
5771
1e8e9920 5772
5773/* Expand code for an OpenMP sections directive. In pseudo code, we generate
5774
1e8e9920 5775 v = GOMP_sections_start (n);
5776 L0:
5777 switch (v)
5778 {
5779 case 0:
5780 goto L2;
5781 case 1:
5782 section 1;
5783 goto L1;
5784 case 2:
5785 ...
5786 case n:
5787 ...
1e8e9920 5788 default:
5789 abort ();
5790 }
5791 L1:
5792 v = GOMP_sections_next ();
5793 goto L0;
5794 L2:
5795 reduction;
5796
773c5ba7 5797 If this is a combined parallel sections, replace the call to
79acaae1 5798 GOMP_sections_start with call to GOMP_sections_next. */
1e8e9920 5799
5800static void
773c5ba7 5801expand_omp_sections (struct omp_region *region)
1e8e9920 5802{
f018d957 5803 tree t, u, vin = NULL, vmain, vnext, l2;
f1f41a6c 5804 vec<tree> label_vec;
75a70cf9 5805 unsigned len;
ac6e3339 5806 basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
75a70cf9 5807 gimple_stmt_iterator si, switch_si;
5808 gimple sections_stmt, stmt, cont;
9884aaf8 5809 edge_iterator ei;
5810 edge e;
61e47ac8 5811 struct omp_region *inner;
75a70cf9 5812 unsigned i, casei;
ac6e3339 5813 bool exit_reachable = region->cont != NULL;
1e8e9920 5814
d244d9de 5815 gcc_assert (region->exit != NULL);
61e47ac8 5816 entry_bb = region->entry;
ac6e3339 5817 l0_bb = single_succ (entry_bb);
61e47ac8 5818 l1_bb = region->cont;
ac6e3339 5819 l2_bb = region->exit;
d244d9de 5820 if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
5821 l2 = gimple_block_label (l2_bb);
5822 else
03ed154b 5823 {
d244d9de 5824 /* This can happen if there are reductions. */
5825 len = EDGE_COUNT (l0_bb->succs);
5826 gcc_assert (len > 0);
5827 e = EDGE_SUCC (l0_bb, len - 1);
5828 si = gsi_last_bb (e->dest);
5829 l2 = NULL_TREE;
5830 if (gsi_end_p (si)
5831 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
5832 l2 = gimple_block_label (e->dest);
9884aaf8 5833 else
d244d9de 5834 FOR_EACH_EDGE (e, ei, l0_bb->succs)
5835 {
5836 si = gsi_last_bb (e->dest);
5837 if (gsi_end_p (si)
5838 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
9884aaf8 5839 {
d244d9de 5840 l2 = gimple_block_label (e->dest);
5841 break;
9884aaf8 5842 }
d244d9de 5843 }
03ed154b 5844 }
d244d9de 5845 if (exit_reachable)
5846 default_bb = create_empty_bb (l1_bb->prev_bb);
03ed154b 5847 else
d244d9de 5848 default_bb = create_empty_bb (l0_bb);
773c5ba7 5849
5850 /* We will build a switch() with enough cases for all the
75a70cf9 5851 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
773c5ba7 5852 and a default case to abort if something goes wrong. */
ac6e3339 5853 len = EDGE_COUNT (l0_bb->succs);
75a70cf9 5854
f1f41a6c 5855 /* Use vec::quick_push on label_vec throughout, since we know the size
75a70cf9 5856 in advance. */
f1f41a6c 5857 label_vec.create (len);
1e8e9920 5858
61e47ac8 5859 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
75a70cf9 5860 GIMPLE_OMP_SECTIONS statement. */
5861 si = gsi_last_bb (entry_bb);
5862 sections_stmt = gsi_stmt (si);
5863 gcc_assert (gimple_code (sections_stmt) == GIMPLE_OMP_SECTIONS);
5864 vin = gimple_omp_sections_control (sections_stmt);
773c5ba7 5865 if (!is_combined_parallel (region))
1e8e9920 5866 {
773c5ba7 5867 /* If we are not inside a combined parallel+sections region,
5868 call GOMP_sections_start. */
ac6e3339 5869 t = build_int_cst (unsigned_type_node,
5870 exit_reachable ? len - 1 : len);
b9a16870 5871 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START);
75a70cf9 5872 stmt = gimple_build_call (u, 1, t);
1e8e9920 5873 }
79acaae1 5874 else
5875 {
5876 /* Otherwise, call GOMP_sections_next. */
b9a16870 5877 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
75a70cf9 5878 stmt = gimple_build_call (u, 0);
79acaae1 5879 }
75a70cf9 5880 gimple_call_set_lhs (stmt, vin);
5881 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
5882 gsi_remove (&si, true);
5883
5884 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
5885 L0_BB. */
5886 switch_si = gsi_last_bb (l0_bb);
5887 gcc_assert (gimple_code (gsi_stmt (switch_si)) == GIMPLE_OMP_SECTIONS_SWITCH);
79acaae1 5888 if (exit_reachable)
5889 {
5890 cont = last_stmt (l1_bb);
75a70cf9 5891 gcc_assert (gimple_code (cont) == GIMPLE_OMP_CONTINUE);
5892 vmain = gimple_omp_continue_control_use (cont);
5893 vnext = gimple_omp_continue_control_def (cont);
79acaae1 5894 }
5895 else
5896 {
5897 vmain = vin;
5898 vnext = NULL_TREE;
5899 }
1e8e9920 5900
d244d9de 5901 t = build_case_label (build_int_cst (unsigned_type_node, 0), NULL, l2);
f1f41a6c 5902 label_vec.quick_push (t);
d244d9de 5903 i = 1;
03ed154b 5904
75a70cf9 5905 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
ac6e3339 5906 for (inner = region->inner, casei = 1;
5907 inner;
5908 inner = inner->next, i++, casei++)
1e8e9920 5909 {
773c5ba7 5910 basic_block s_entry_bb, s_exit_bb;
5911
9884aaf8 5912 /* Skip optional reduction region. */
75a70cf9 5913 if (inner->type == GIMPLE_OMP_ATOMIC_LOAD)
9884aaf8 5914 {
5915 --i;
5916 --casei;
5917 continue;
5918 }
5919
61e47ac8 5920 s_entry_bb = inner->entry;
5921 s_exit_bb = inner->exit;
1e8e9920 5922
75a70cf9 5923 t = gimple_block_label (s_entry_bb);
ac6e3339 5924 u = build_int_cst (unsigned_type_node, casei);
b6e3dd65 5925 u = build_case_label (u, NULL, t);
f1f41a6c 5926 label_vec.quick_push (u);
61e47ac8 5927
75a70cf9 5928 si = gsi_last_bb (s_entry_bb);
5929 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SECTION);
5930 gcc_assert (i < len || gimple_omp_section_last_p (gsi_stmt (si)));
5931 gsi_remove (&si, true);
61e47ac8 5932 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
03ed154b 5933
5934 if (s_exit_bb == NULL)
5935 continue;
5936
75a70cf9 5937 si = gsi_last_bb (s_exit_bb);
5938 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
5939 gsi_remove (&si, true);
03ed154b 5940
773c5ba7 5941 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
1e8e9920 5942 }
5943
773c5ba7 5944 /* Error handling code goes in DEFAULT_BB. */
75a70cf9 5945 t = gimple_block_label (default_bb);
b6e3dd65 5946 u = build_case_label (NULL, NULL, t);
61e47ac8 5947 make_edge (l0_bb, default_bb, 0);
f6568ea4 5948 if (current_loops)
04c2922b 5949 add_bb_to_loop (default_bb, current_loops->tree_root);
1e8e9920 5950
49a70175 5951 stmt = gimple_build_switch (vmain, u, label_vec);
75a70cf9 5952 gsi_insert_after (&switch_si, stmt, GSI_SAME_STMT);
5953 gsi_remove (&switch_si, true);
f1f41a6c 5954 label_vec.release ();
75a70cf9 5955
5956 si = gsi_start_bb (default_bb);
b9a16870 5957 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
75a70cf9 5958 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
773c5ba7 5959
ac6e3339 5960 if (exit_reachable)
03ed154b 5961 {
b9a16870 5962 tree bfn_decl;
5963
ac6e3339 5964 /* Code to get the next section goes in L1_BB. */
75a70cf9 5965 si = gsi_last_bb (l1_bb);
5966 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
1e8e9920 5967
b9a16870 5968 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
5969 stmt = gimple_build_call (bfn_decl, 0);
75a70cf9 5970 gimple_call_set_lhs (stmt, vnext);
5971 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
5972 gsi_remove (&si, true);
773c5ba7 5973
ac6e3339 5974 single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
03ed154b 5975 }
773c5ba7 5976
d244d9de 5977 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
5978 si = gsi_last_bb (l2_bb);
5979 if (gimple_omp_return_nowait_p (gsi_stmt (si)))
5980 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
5981 else
5982 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
5983 stmt = gimple_build_call (t, 0);
5984 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
5985 gsi_remove (&si, true);
5986
79acaae1 5987 set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
773c5ba7 5988}
1e8e9920 5989
1e8e9920 5990
61e47ac8 5991/* Expand code for an OpenMP single directive. We've already expanded
5992 much of the code, here we simply place the GOMP_barrier call. */
5993
5994static void
5995expand_omp_single (struct omp_region *region)
5996{
5997 basic_block entry_bb, exit_bb;
75a70cf9 5998 gimple_stmt_iterator si;
61e47ac8 5999 bool need_barrier = false;
6000
6001 entry_bb = region->entry;
6002 exit_bb = region->exit;
6003
75a70cf9 6004 si = gsi_last_bb (entry_bb);
61e47ac8 6005 /* The terminal barrier at the end of a GOMP_single_copy sequence cannot
6006 be removed. We need to ensure that the thread that entered the single
6007 does not exit before the data is copied out by the other threads. */
75a70cf9 6008 if (find_omp_clause (gimple_omp_single_clauses (gsi_stmt (si)),
61e47ac8 6009 OMP_CLAUSE_COPYPRIVATE))
6010 need_barrier = true;
75a70cf9 6011 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE);
6012 gsi_remove (&si, true);
61e47ac8 6013 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
6014
75a70cf9 6015 si = gsi_last_bb (exit_bb);
6016 if (!gimple_omp_return_nowait_p (gsi_stmt (si)) || need_barrier)
6017 force_gimple_operand_gsi (&si, build_omp_barrier (), false, NULL_TREE,
6018 false, GSI_SAME_STMT);
6019 gsi_remove (&si, true);
61e47ac8 6020 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
6021}
6022
6023
6024/* Generic expansion for OpenMP synchronization directives: master,
6025 ordered and critical. All we need to do here is remove the entry
6026 and exit markers for REGION. */
773c5ba7 6027
6028static void
6029expand_omp_synch (struct omp_region *region)
6030{
6031 basic_block entry_bb, exit_bb;
75a70cf9 6032 gimple_stmt_iterator si;
773c5ba7 6033
61e47ac8 6034 entry_bb = region->entry;
6035 exit_bb = region->exit;
773c5ba7 6036
75a70cf9 6037 si = gsi_last_bb (entry_bb);
6038 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE
6039 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASTER
6040 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ORDERED
6041 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CRITICAL);
6042 gsi_remove (&si, true);
773c5ba7 6043 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
6044
03ed154b 6045 if (exit_bb)
6046 {
75a70cf9 6047 si = gsi_last_bb (exit_bb);
6048 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
6049 gsi_remove (&si, true);
03ed154b 6050 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
6051 }
773c5ba7 6052}
1e8e9920 6053
2169f33b 6054/* A subroutine of expand_omp_atomic. Attempt to implement the atomic
6055 operation as a normal volatile load. */
6056
6057static bool
3ec11c49 6058expand_omp_atomic_load (basic_block load_bb, tree addr,
6059 tree loaded_val, int index)
2169f33b 6060{
3ec11c49 6061 enum built_in_function tmpbase;
6062 gimple_stmt_iterator gsi;
6063 basic_block store_bb;
6064 location_t loc;
6065 gimple stmt;
6066 tree decl, call, type, itype;
6067
6068 gsi = gsi_last_bb (load_bb);
6069 stmt = gsi_stmt (gsi);
6070 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
6071 loc = gimple_location (stmt);
6072
6073 /* ??? If the target does not implement atomic_load_optab[mode], and mode
6074 is smaller than word size, then expand_atomic_load assumes that the load
6075 is atomic. We could avoid the builtin entirely in this case. */
6076
6077 tmpbase = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
6078 decl = builtin_decl_explicit (tmpbase);
6079 if (decl == NULL_TREE)
6080 return false;
6081
6082 type = TREE_TYPE (loaded_val);
6083 itype = TREE_TYPE (TREE_TYPE (decl));
6084
6085 call = build_call_expr_loc (loc, decl, 2, addr,
6086 build_int_cst (NULL, MEMMODEL_RELAXED));
6087 if (!useless_type_conversion_p (type, itype))
6088 call = fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
6089 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
6090
6091 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
6092 gsi_remove (&gsi, true);
6093
6094 store_bb = single_succ (load_bb);
6095 gsi = gsi_last_bb (store_bb);
6096 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
6097 gsi_remove (&gsi, true);
6098
6099 if (gimple_in_ssa_p (cfun))
6100 update_ssa (TODO_update_ssa_no_phi);
6101
6102 return true;
2169f33b 6103}
6104
6105/* A subroutine of expand_omp_atomic. Attempt to implement the atomic
6106 operation as a normal volatile store. */
6107
6108static bool
3ec11c49 6109expand_omp_atomic_store (basic_block load_bb, tree addr,
6110 tree loaded_val, tree stored_val, int index)
2169f33b 6111{
3ec11c49 6112 enum built_in_function tmpbase;
6113 gimple_stmt_iterator gsi;
6114 basic_block store_bb = single_succ (load_bb);
6115 location_t loc;
6116 gimple stmt;
6117 tree decl, call, type, itype;
6118 enum machine_mode imode;
6119 bool exchange;
6120
6121 gsi = gsi_last_bb (load_bb);
6122 stmt = gsi_stmt (gsi);
6123 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
6124
6125 /* If the load value is needed, then this isn't a store but an exchange. */
6126 exchange = gimple_omp_atomic_need_value_p (stmt);
6127
6128 gsi = gsi_last_bb (store_bb);
6129 stmt = gsi_stmt (gsi);
6130 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE);
6131 loc = gimple_location (stmt);
6132
6133 /* ??? If the target does not implement atomic_store_optab[mode], and mode
6134 is smaller than word size, then expand_atomic_store assumes that the store
6135 is atomic. We could avoid the builtin entirely in this case. */
6136
6137 tmpbase = (exchange ? BUILT_IN_ATOMIC_EXCHANGE_N : BUILT_IN_ATOMIC_STORE_N);
6138 tmpbase = (enum built_in_function) ((int) tmpbase + index + 1);
6139 decl = builtin_decl_explicit (tmpbase);
6140 if (decl == NULL_TREE)
6141 return false;
6142
6143 type = TREE_TYPE (stored_val);
6144
6145 /* Dig out the type of the function's second argument. */
6146 itype = TREE_TYPE (decl);
6147 itype = TYPE_ARG_TYPES (itype);
6148 itype = TREE_CHAIN (itype);
6149 itype = TREE_VALUE (itype);
6150 imode = TYPE_MODE (itype);
6151
6152 if (exchange && !can_atomic_exchange_p (imode, true))
6153 return false;
6154
6155 if (!useless_type_conversion_p (itype, type))
6156 stored_val = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, stored_val);
6157 call = build_call_expr_loc (loc, decl, 3, addr, stored_val,
6158 build_int_cst (NULL, MEMMODEL_RELAXED));
6159 if (exchange)
6160 {
6161 if (!useless_type_conversion_p (type, itype))
6162 call = build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
6163 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
6164 }
6165
6166 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
6167 gsi_remove (&gsi, true);
6168
6169 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
6170 gsi = gsi_last_bb (load_bb);
6171 gsi_remove (&gsi, true);
6172
6173 if (gimple_in_ssa_p (cfun))
6174 update_ssa (TODO_update_ssa_no_phi);
6175
6176 return true;
2169f33b 6177}
6178
cb7f680b 6179/* A subroutine of expand_omp_atomic. Attempt to implement the atomic
1cd6e20d 6180 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
cb7f680b 6181 size of the data type, and thus usable to find the index of the builtin
6182 decl. Returns false if the expression is not of the proper form. */
6183
6184static bool
6185expand_omp_atomic_fetch_op (basic_block load_bb,
6186 tree addr, tree loaded_val,
6187 tree stored_val, int index)
6188{
b9a16870 6189 enum built_in_function oldbase, newbase, tmpbase;
cb7f680b 6190 tree decl, itype, call;
2169f33b 6191 tree lhs, rhs;
cb7f680b 6192 basic_block store_bb = single_succ (load_bb);
75a70cf9 6193 gimple_stmt_iterator gsi;
6194 gimple stmt;
389dd41b 6195 location_t loc;
1cd6e20d 6196 enum tree_code code;
2169f33b 6197 bool need_old, need_new;
1cd6e20d 6198 enum machine_mode imode;
cb7f680b 6199
6200 /* We expect to find the following sequences:
48e1416a 6201
cb7f680b 6202 load_bb:
75a70cf9 6203 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
cb7f680b 6204
6205 store_bb:
6206 val = tmp OP something; (or: something OP tmp)
48e1416a 6207 GIMPLE_OMP_STORE (val)
cb7f680b 6208
48e1416a 6209 ???FIXME: Allow a more flexible sequence.
cb7f680b 6210 Perhaps use data flow to pick the statements.
48e1416a 6211
cb7f680b 6212 */
6213
75a70cf9 6214 gsi = gsi_after_labels (store_bb);
6215 stmt = gsi_stmt (gsi);
389dd41b 6216 loc = gimple_location (stmt);
75a70cf9 6217 if (!is_gimple_assign (stmt))
cb7f680b 6218 return false;
75a70cf9 6219 gsi_next (&gsi);
6220 if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE)
cb7f680b 6221 return false;
2169f33b 6222 need_new = gimple_omp_atomic_need_value_p (gsi_stmt (gsi));
6223 need_old = gimple_omp_atomic_need_value_p (last_stmt (load_bb));
6224 gcc_checking_assert (!need_old || !need_new);
cb7f680b 6225
75a70cf9 6226 if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
cb7f680b 6227 return false;
6228
cb7f680b 6229 /* Check for one of the supported fetch-op operations. */
1cd6e20d 6230 code = gimple_assign_rhs_code (stmt);
6231 switch (code)
cb7f680b 6232 {
6233 case PLUS_EXPR:
6234 case POINTER_PLUS_EXPR:
1cd6e20d 6235 oldbase = BUILT_IN_ATOMIC_FETCH_ADD_N;
6236 newbase = BUILT_IN_ATOMIC_ADD_FETCH_N;
cb7f680b 6237 break;
6238 case MINUS_EXPR:
1cd6e20d 6239 oldbase = BUILT_IN_ATOMIC_FETCH_SUB_N;
6240 newbase = BUILT_IN_ATOMIC_SUB_FETCH_N;
cb7f680b 6241 break;
6242 case BIT_AND_EXPR:
1cd6e20d 6243 oldbase = BUILT_IN_ATOMIC_FETCH_AND_N;
6244 newbase = BUILT_IN_ATOMIC_AND_FETCH_N;
cb7f680b 6245 break;
6246 case BIT_IOR_EXPR:
1cd6e20d 6247 oldbase = BUILT_IN_ATOMIC_FETCH_OR_N;
6248 newbase = BUILT_IN_ATOMIC_OR_FETCH_N;
cb7f680b 6249 break;
6250 case BIT_XOR_EXPR:
1cd6e20d 6251 oldbase = BUILT_IN_ATOMIC_FETCH_XOR_N;
6252 newbase = BUILT_IN_ATOMIC_XOR_FETCH_N;
cb7f680b 6253 break;
6254 default:
6255 return false;
6256 }
1cd6e20d 6257
cb7f680b 6258 /* Make sure the expression is of the proper form. */
75a70cf9 6259 if (operand_equal_p (gimple_assign_rhs1 (stmt), loaded_val, 0))
6260 rhs = gimple_assign_rhs2 (stmt);
6261 else if (commutative_tree_code (gimple_assign_rhs_code (stmt))
6262 && operand_equal_p (gimple_assign_rhs2 (stmt), loaded_val, 0))
6263 rhs = gimple_assign_rhs1 (stmt);
cb7f680b 6264 else
6265 return false;
6266
b9a16870 6267 tmpbase = ((enum built_in_function)
6268 ((need_new ? newbase : oldbase) + index + 1));
6269 decl = builtin_decl_explicit (tmpbase);
0f94f46b 6270 if (decl == NULL_TREE)
6271 return false;
cb7f680b 6272 itype = TREE_TYPE (TREE_TYPE (decl));
1cd6e20d 6273 imode = TYPE_MODE (itype);
cb7f680b 6274
1cd6e20d 6275 /* We could test all of the various optabs involved, but the fact of the
6276 matter is that (with the exception of i486 vs i586 and xadd) all targets
6277 that support any atomic operaton optab also implements compare-and-swap.
6278 Let optabs.c take care of expanding any compare-and-swap loop. */
29139cdc 6279 if (!can_compare_and_swap_p (imode, true))
cb7f680b 6280 return false;
6281
75a70cf9 6282 gsi = gsi_last_bb (load_bb);
6283 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
1cd6e20d 6284
6285 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
6286 It only requires that the operation happen atomically. Thus we can
6287 use the RELAXED memory model. */
6288 call = build_call_expr_loc (loc, decl, 3, addr,
6289 fold_convert_loc (loc, itype, rhs),
6290 build_int_cst (NULL, MEMMODEL_RELAXED));
6291
2169f33b 6292 if (need_old || need_new)
6293 {
6294 lhs = need_old ? loaded_val : stored_val;
6295 call = fold_convert_loc (loc, TREE_TYPE (lhs), call);
6296 call = build2_loc (loc, MODIFY_EXPR, void_type_node, lhs, call);
6297 }
6298 else
6299 call = fold_convert_loc (loc, void_type_node, call);
75a70cf9 6300 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
6301 gsi_remove (&gsi, true);
cb7f680b 6302
75a70cf9 6303 gsi = gsi_last_bb (store_bb);
6304 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
6305 gsi_remove (&gsi, true);
6306 gsi = gsi_last_bb (store_bb);
6307 gsi_remove (&gsi, true);
cb7f680b 6308
6309 if (gimple_in_ssa_p (cfun))
6310 update_ssa (TODO_update_ssa_no_phi);
6311
6312 return true;
6313}
6314
6315/* A subroutine of expand_omp_atomic. Implement the atomic operation as:
6316
6317 oldval = *addr;
6318 repeat:
6319 newval = rhs; // with oldval replacing *addr in rhs
6320 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
6321 if (oldval != newval)
6322 goto repeat;
6323
6324 INDEX is log2 of the size of the data type, and thus usable to find the
6325 index of the builtin decl. */
6326
6327static bool
6328expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
6329 tree addr, tree loaded_val, tree stored_val,
6330 int index)
6331{
790368c5 6332 tree loadedi, storedi, initial, new_storedi, old_vali;
cb7f680b 6333 tree type, itype, cmpxchg, iaddr;
75a70cf9 6334 gimple_stmt_iterator si;
cb7f680b 6335 basic_block loop_header = single_succ (load_bb);
75a70cf9 6336 gimple phi, stmt;
cb7f680b 6337 edge e;
b9a16870 6338 enum built_in_function fncode;
cb7f680b 6339
1cd6e20d 6340 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
6341 order to use the RELAXED memory model effectively. */
b9a16870 6342 fncode = (enum built_in_function)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
6343 + index + 1);
6344 cmpxchg = builtin_decl_explicit (fncode);
0f94f46b 6345 if (cmpxchg == NULL_TREE)
6346 return false;
cb7f680b 6347 type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
6348 itype = TREE_TYPE (TREE_TYPE (cmpxchg));
6349
29139cdc 6350 if (!can_compare_and_swap_p (TYPE_MODE (itype), true))
cb7f680b 6351 return false;
6352
75a70cf9 6353 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
6354 si = gsi_last_bb (load_bb);
6355 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
6356
790368c5 6357 /* For floating-point values, we'll need to view-convert them to integers
6358 so that we can perform the atomic compare and swap. Simplify the
6359 following code by always setting up the "i"ntegral variables. */
6360 if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
6361 {
75a70cf9 6362 tree iaddr_val;
6363
072f7ab1 6364 iaddr = create_tmp_reg (build_pointer_type_for_mode (itype, ptr_mode,
6365 true), NULL);
75a70cf9 6366 iaddr_val
6367 = force_gimple_operand_gsi (&si,
6368 fold_convert (TREE_TYPE (iaddr), addr),
6369 false, NULL_TREE, true, GSI_SAME_STMT);
6370 stmt = gimple_build_assign (iaddr, iaddr_val);
6371 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
790368c5 6372 loadedi = create_tmp_var (itype, NULL);
6373 if (gimple_in_ssa_p (cfun))
b03e5397 6374 loadedi = make_ssa_name (loadedi, NULL);
790368c5 6375 }
6376 else
6377 {
6378 iaddr = addr;
6379 loadedi = loaded_val;
6380 }
75a70cf9 6381
182cf5a9 6382 initial
6383 = force_gimple_operand_gsi (&si,
6384 build2 (MEM_REF, TREE_TYPE (TREE_TYPE (iaddr)),
6385 iaddr,
6386 build_int_cst (TREE_TYPE (iaddr), 0)),
6387 true, NULL_TREE, true, GSI_SAME_STMT);
790368c5 6388
6389 /* Move the value to the LOADEDI temporary. */
cb7f680b 6390 if (gimple_in_ssa_p (cfun))
6391 {
75a70cf9 6392 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header)));
790368c5 6393 phi = create_phi_node (loadedi, loop_header);
cb7f680b 6394 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)),
6395 initial);
6396 }
6397 else
75a70cf9 6398 gsi_insert_before (&si,
6399 gimple_build_assign (loadedi, initial),
6400 GSI_SAME_STMT);
790368c5 6401 if (loadedi != loaded_val)
6402 {
75a70cf9 6403 gimple_stmt_iterator gsi2;
6404 tree x;
790368c5 6405
6406 x = build1 (VIEW_CONVERT_EXPR, type, loadedi);
75a70cf9 6407 gsi2 = gsi_start_bb (loop_header);
790368c5 6408 if (gimple_in_ssa_p (cfun))
6409 {
75a70cf9 6410 gimple stmt;
6411 x = force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
6412 true, GSI_SAME_STMT);
6413 stmt = gimple_build_assign (loaded_val, x);
6414 gsi_insert_before (&gsi2, stmt, GSI_SAME_STMT);
790368c5 6415 }
6416 else
6417 {
75a70cf9 6418 x = build2 (MODIFY_EXPR, TREE_TYPE (loaded_val), loaded_val, x);
6419 force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
6420 true, GSI_SAME_STMT);
790368c5 6421 }
6422 }
75a70cf9 6423 gsi_remove (&si, true);
cb7f680b 6424
75a70cf9 6425 si = gsi_last_bb (store_bb);
6426 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
cb7f680b 6427
790368c5 6428 if (iaddr == addr)
6429 storedi = stored_val;
cb7f680b 6430 else
790368c5 6431 storedi =
75a70cf9 6432 force_gimple_operand_gsi (&si,
790368c5 6433 build1 (VIEW_CONVERT_EXPR, itype,
6434 stored_val), true, NULL_TREE, true,
75a70cf9 6435 GSI_SAME_STMT);
cb7f680b 6436
6437 /* Build the compare&swap statement. */
6438 new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi);
75a70cf9 6439 new_storedi = force_gimple_operand_gsi (&si,
87f9ffa4 6440 fold_convert (TREE_TYPE (loadedi),
6441 new_storedi),
cb7f680b 6442 true, NULL_TREE,
75a70cf9 6443 true, GSI_SAME_STMT);
cb7f680b 6444
6445 if (gimple_in_ssa_p (cfun))
6446 old_vali = loadedi;
6447 else
6448 {
87f9ffa4 6449 old_vali = create_tmp_var (TREE_TYPE (loadedi), NULL);
75a70cf9 6450 stmt = gimple_build_assign (old_vali, loadedi);
6451 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
cb7f680b 6452
75a70cf9 6453 stmt = gimple_build_assign (loadedi, new_storedi);
6454 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
cb7f680b 6455 }
6456
6457 /* Note that we always perform the comparison as an integer, even for
48e1416a 6458 floating point. This allows the atomic operation to properly
cb7f680b 6459 succeed even with NaNs and -0.0. */
75a70cf9 6460 stmt = gimple_build_cond_empty
6461 (build2 (NE_EXPR, boolean_type_node,
6462 new_storedi, old_vali));
6463 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
cb7f680b 6464
6465 /* Update cfg. */
6466 e = single_succ_edge (store_bb);
6467 e->flags &= ~EDGE_FALLTHRU;
6468 e->flags |= EDGE_FALSE_VALUE;
6469
6470 e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE);
6471
790368c5 6472 /* Copy the new value to loadedi (we already did that before the condition
cb7f680b 6473 if we are not in SSA). */
6474 if (gimple_in_ssa_p (cfun))
6475 {
75a70cf9 6476 phi = gimple_seq_first_stmt (phi_nodes (loop_header));
790368c5 6477 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), new_storedi);
cb7f680b 6478 }
6479
75a70cf9 6480 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
6481 gsi_remove (&si, true);
cb7f680b 6482
04c2922b 6483 struct loop *loop = alloc_loop ();
6484 loop->header = loop_header;
5f037457 6485 loop->latch = store_bb;
04c2922b 6486 add_loop (loop, loop_header->loop_father);
6487
cb7f680b 6488 if (gimple_in_ssa_p (cfun))
6489 update_ssa (TODO_update_ssa_no_phi);
6490
6491 return true;
6492}
6493
6494/* A subroutine of expand_omp_atomic. Implement the atomic operation as:
6495
6496 GOMP_atomic_start ();
6497 *addr = rhs;
6498 GOMP_atomic_end ();
6499
6500 The result is not globally atomic, but works so long as all parallel
6501 references are within #pragma omp atomic directives. According to
6502 responses received from omp@openmp.org, appears to be within spec.
6503 Which makes sense, since that's how several other compilers handle
48e1416a 6504 this situation as well.
75a70cf9 6505 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
6506 expanding. STORED_VAL is the operand of the matching
6507 GIMPLE_OMP_ATOMIC_STORE.
cb7f680b 6508
48e1416a 6509 We replace
6510 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
cb7f680b 6511 loaded_val = *addr;
6512
6513 and replace
3ec11c49 6514 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
48e1416a 6515 *addr = stored_val;
cb7f680b 6516*/
6517
6518static bool
6519expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
6520 tree addr, tree loaded_val, tree stored_val)
6521{
75a70cf9 6522 gimple_stmt_iterator si;
6523 gimple stmt;
cb7f680b 6524 tree t;
6525
75a70cf9 6526 si = gsi_last_bb (load_bb);
6527 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
cb7f680b 6528
b9a16870 6529 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
414c3a2c 6530 t = build_call_expr (t, 0);
75a70cf9 6531 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
cb7f680b 6532
182cf5a9 6533 stmt = gimple_build_assign (loaded_val, build_simple_mem_ref (addr));
75a70cf9 6534 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
6535 gsi_remove (&si, true);
cb7f680b 6536
75a70cf9 6537 si = gsi_last_bb (store_bb);
6538 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
cb7f680b 6539
182cf5a9 6540 stmt = gimple_build_assign (build_simple_mem_ref (unshare_expr (addr)),
6541 stored_val);
75a70cf9 6542 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
cb7f680b 6543
b9a16870 6544 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
414c3a2c 6545 t = build_call_expr (t, 0);
75a70cf9 6546 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
6547 gsi_remove (&si, true);
cb7f680b 6548
6549 if (gimple_in_ssa_p (cfun))
6550 update_ssa (TODO_update_ssa_no_phi);
6551 return true;
6552}
6553
48e1416a 6554/* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
6555 using expand_omp_atomic_fetch_op. If it failed, we try to
cb7f680b 6556 call expand_omp_atomic_pipeline, and if it fails too, the
6557 ultimate fallback is wrapping the operation in a mutex
48e1416a 6558 (expand_omp_atomic_mutex). REGION is the atomic region built
6559 by build_omp_regions_1(). */
cb7f680b 6560
6561static void
6562expand_omp_atomic (struct omp_region *region)
6563{
6564 basic_block load_bb = region->entry, store_bb = region->exit;
75a70cf9 6565 gimple load = last_stmt (load_bb), store = last_stmt (store_bb);
6566 tree loaded_val = gimple_omp_atomic_load_lhs (load);
6567 tree addr = gimple_omp_atomic_load_rhs (load);
6568 tree stored_val = gimple_omp_atomic_store_val (store);
cb7f680b 6569 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
6570 HOST_WIDE_INT index;
6571
6572 /* Make sure the type is one of the supported sizes. */
6573 index = tree_low_cst (TYPE_SIZE_UNIT (type), 1);
6574 index = exact_log2 (index);
6575 if (index >= 0 && index <= 4)
6576 {
6577 unsigned int align = TYPE_ALIGN_UNIT (type);
6578
6579 /* __sync builtins require strict data alignment. */
dcf7024c 6580 if (exact_log2 (align) >= index)
cb7f680b 6581 {
3ec11c49 6582 /* Atomic load. */
2169f33b 6583 if (loaded_val == stored_val
6584 && (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
6585 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
6586 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
3ec11c49 6587 && expand_omp_atomic_load (load_bb, addr, loaded_val, index))
2169f33b 6588 return;
6589
3ec11c49 6590 /* Atomic store. */
2169f33b 6591 if ((GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
6592 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
6593 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
6594 && store_bb == single_succ (load_bb)
6595 && first_stmt (store_bb) == store
3ec11c49 6596 && expand_omp_atomic_store (load_bb, addr, loaded_val,
6597 stored_val, index))
2169f33b 6598 return;
6599
cb7f680b 6600 /* When possible, use specialized atomic update functions. */
6601 if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
3ec11c49 6602 && store_bb == single_succ (load_bb)
6603 && expand_omp_atomic_fetch_op (load_bb, addr,
6604 loaded_val, stored_val, index))
6605 return;
cb7f680b 6606
6607 /* If we don't have specialized __sync builtins, try and implement
6608 as a compare and swap loop. */
6609 if (expand_omp_atomic_pipeline (load_bb, store_bb, addr,
6610 loaded_val, stored_val, index))
6611 return;
6612 }
6613 }
6614
6615 /* The ultimate fallback is wrapping the operation in a mutex. */
6616 expand_omp_atomic_mutex (load_bb, store_bb, addr, loaded_val, stored_val);
6617}
6618
1e8e9920 6619
773c5ba7 6620/* Expand the parallel region tree rooted at REGION. Expansion
6621 proceeds in depth-first order. Innermost regions are expanded
6622 first. This way, parallel regions that require a new function to
75a70cf9 6623 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
773c5ba7 6624 internal dependencies in their body. */
6625
6626static void
6627expand_omp (struct omp_region *region)
6628{
6629 while (region)
6630 {
1d22f541 6631 location_t saved_location;
6632
d1d5b012 6633 /* First, determine whether this is a combined parallel+workshare
6634 region. */
75a70cf9 6635 if (region->type == GIMPLE_OMP_PARALLEL)
d1d5b012 6636 determine_parallel_type (region);
6637
773c5ba7 6638 if (region->inner)
6639 expand_omp (region->inner);
6640
1d22f541 6641 saved_location = input_location;
75a70cf9 6642 if (gimple_has_location (last_stmt (region->entry)))
6643 input_location = gimple_location (last_stmt (region->entry));
1d22f541 6644
61e47ac8 6645 switch (region->type)
773c5ba7 6646 {
75a70cf9 6647 case GIMPLE_OMP_PARALLEL:
6648 case GIMPLE_OMP_TASK:
fd6481cf 6649 expand_omp_taskreg (region);
6650 break;
6651
75a70cf9 6652 case GIMPLE_OMP_FOR:
61e47ac8 6653 expand_omp_for (region);
6654 break;
773c5ba7 6655
75a70cf9 6656 case GIMPLE_OMP_SECTIONS:
61e47ac8 6657 expand_omp_sections (region);
6658 break;
773c5ba7 6659
75a70cf9 6660 case GIMPLE_OMP_SECTION:
61e47ac8 6661 /* Individual omp sections are handled together with their
75a70cf9 6662 parent GIMPLE_OMP_SECTIONS region. */
61e47ac8 6663 break;
773c5ba7 6664
75a70cf9 6665 case GIMPLE_OMP_SINGLE:
61e47ac8 6666 expand_omp_single (region);
6667 break;
773c5ba7 6668
75a70cf9 6669 case GIMPLE_OMP_MASTER:
6670 case GIMPLE_OMP_ORDERED:
6671 case GIMPLE_OMP_CRITICAL:
61e47ac8 6672 expand_omp_synch (region);
6673 break;
773c5ba7 6674
75a70cf9 6675 case GIMPLE_OMP_ATOMIC_LOAD:
cb7f680b 6676 expand_omp_atomic (region);
6677 break;
6678
61e47ac8 6679 default:
6680 gcc_unreachable ();
6681 }
cc5982dc 6682
1d22f541 6683 input_location = saved_location;
773c5ba7 6684 region = region->next;
6685 }
6686}
6687
6688
6689/* Helper for build_omp_regions. Scan the dominator tree starting at
28c92cbb 6690 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
6691 true, the function ends once a single tree is built (otherwise, whole
6692 forest of OMP constructs may be built). */
773c5ba7 6693
6694static void
28c92cbb 6695build_omp_regions_1 (basic_block bb, struct omp_region *parent,
6696 bool single_tree)
773c5ba7 6697{
75a70cf9 6698 gimple_stmt_iterator gsi;
6699 gimple stmt;
773c5ba7 6700 basic_block son;
6701
75a70cf9 6702 gsi = gsi_last_bb (bb);
6703 if (!gsi_end_p (gsi) && is_gimple_omp (gsi_stmt (gsi)))
773c5ba7 6704 {
6705 struct omp_region *region;
75a70cf9 6706 enum gimple_code code;
773c5ba7 6707
75a70cf9 6708 stmt = gsi_stmt (gsi);
6709 code = gimple_code (stmt);
6710 if (code == GIMPLE_OMP_RETURN)
773c5ba7 6711 {
6712 /* STMT is the return point out of region PARENT. Mark it
6713 as the exit point and make PARENT the immediately
6714 enclosing region. */
6715 gcc_assert (parent);
6716 region = parent;
61e47ac8 6717 region->exit = bb;
773c5ba7 6718 parent = parent->outer;
773c5ba7 6719 }
75a70cf9 6720 else if (code == GIMPLE_OMP_ATOMIC_STORE)
cb7f680b 6721 {
75a70cf9 6722 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
6723 GIMPLE_OMP_RETURN, but matches with
6724 GIMPLE_OMP_ATOMIC_LOAD. */
cb7f680b 6725 gcc_assert (parent);
75a70cf9 6726 gcc_assert (parent->type == GIMPLE_OMP_ATOMIC_LOAD);
cb7f680b 6727 region = parent;
6728 region->exit = bb;
6729 parent = parent->outer;
6730 }
6731
75a70cf9 6732 else if (code == GIMPLE_OMP_CONTINUE)
61e47ac8 6733 {
6734 gcc_assert (parent);
6735 parent->cont = bb;
6736 }
75a70cf9 6737 else if (code == GIMPLE_OMP_SECTIONS_SWITCH)
ac6e3339 6738 {
75a70cf9 6739 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
6740 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
6741 ;
ac6e3339 6742 }
773c5ba7 6743 else
6744 {
6745 /* Otherwise, this directive becomes the parent for a new
6746 region. */
61e47ac8 6747 region = new_omp_region (bb, code, parent);
773c5ba7 6748 parent = region;
6749 }
773c5ba7 6750 }
6751
28c92cbb 6752 if (single_tree && !parent)
6753 return;
6754
773c5ba7 6755 for (son = first_dom_son (CDI_DOMINATORS, bb);
6756 son;
6757 son = next_dom_son (CDI_DOMINATORS, son))
28c92cbb 6758 build_omp_regions_1 (son, parent, single_tree);
6759}
6760
6761/* Builds the tree of OMP regions rooted at ROOT, storing it to
6762 root_omp_region. */
6763
6764static void
6765build_omp_regions_root (basic_block root)
6766{
6767 gcc_assert (root_omp_region == NULL);
6768 build_omp_regions_1 (root, NULL, true);
6769 gcc_assert (root_omp_region != NULL);
773c5ba7 6770}
6771
28c92cbb 6772/* Expands omp construct (and its subconstructs) starting in HEAD. */
6773
6774void
6775omp_expand_local (basic_block head)
6776{
6777 build_omp_regions_root (head);
6778 if (dump_file && (dump_flags & TDF_DETAILS))
6779 {
6780 fprintf (dump_file, "\nOMP region tree\n\n");
6781 dump_omp_region (dump_file, root_omp_region, 0);
6782 fprintf (dump_file, "\n");
6783 }
6784
6785 remove_exit_barriers (root_omp_region);
6786 expand_omp (root_omp_region);
6787
6788 free_omp_regions ();
6789}
773c5ba7 6790
6791/* Scan the CFG and build a tree of OMP regions. Return the root of
6792 the OMP region tree. */
6793
6794static void
6795build_omp_regions (void)
6796{
61e47ac8 6797 gcc_assert (root_omp_region == NULL);
773c5ba7 6798 calculate_dominance_info (CDI_DOMINATORS);
28c92cbb 6799 build_omp_regions_1 (ENTRY_BLOCK_PTR, NULL, false);
773c5ba7 6800}
6801
773c5ba7 6802/* Main entry point for expanding OMP-GIMPLE into runtime calls. */
6803
2a1990e9 6804static unsigned int
773c5ba7 6805execute_expand_omp (void)
6806{
6807 build_omp_regions ();
6808
61e47ac8 6809 if (!root_omp_region)
6810 return 0;
773c5ba7 6811
61e47ac8 6812 if (dump_file)
6813 {
6814 fprintf (dump_file, "\nOMP region tree\n\n");
6815 dump_omp_region (dump_file, root_omp_region, 0);
6816 fprintf (dump_file, "\n");
773c5ba7 6817 }
61e47ac8 6818
6819 remove_exit_barriers (root_omp_region);
6820
6821 expand_omp (root_omp_region);
6822
61e47ac8 6823 cleanup_tree_cfg ();
6824
6825 free_omp_regions ();
6826
2a1990e9 6827 return 0;
773c5ba7 6828}
6829
79acaae1 6830/* OMP expansion -- the default pass, run before creation of SSA form. */
6831
773c5ba7 6832static bool
6833gate_expand_omp (void)
6834{
852f689e 6835 return (flag_openmp != 0 && !seen_error ());
773c5ba7 6836}
6837
cbe8bda8 6838namespace {
6839
6840const pass_data pass_data_expand_omp =
6841{
6842 GIMPLE_PASS, /* type */
6843 "ompexp", /* name */
6844 OPTGROUP_NONE, /* optinfo_flags */
6845 true, /* has_gate */
6846 true, /* has_execute */
6847 TV_NONE, /* tv_id */
6848 PROP_gimple_any, /* properties_required */
6849 0, /* properties_provided */
6850 0, /* properties_destroyed */
6851 0, /* todo_flags_start */
6852 0, /* todo_flags_finish */
773c5ba7 6853};
cbe8bda8 6854
6855class pass_expand_omp : public gimple_opt_pass
6856{
6857public:
6858 pass_expand_omp(gcc::context *ctxt)
6859 : gimple_opt_pass(pass_data_expand_omp, ctxt)
6860 {}
6861
6862 /* opt_pass methods: */
6863 bool gate () { return gate_expand_omp (); }
6864 unsigned int execute () { return execute_expand_omp (); }
6865
6866}; // class pass_expand_omp
6867
6868} // anon namespace
6869
6870gimple_opt_pass *
6871make_pass_expand_omp (gcc::context *ctxt)
6872{
6873 return new pass_expand_omp (ctxt);
6874}
773c5ba7 6875\f
6876/* Routines to lower OpenMP directives into OMP-GIMPLE. */
6877
75a70cf9 6878/* Lower the OpenMP sections directive in the current statement in GSI_P.
6879 CTX is the enclosing OMP context for the current statement. */
773c5ba7 6880
6881static void
75a70cf9 6882lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
773c5ba7 6883{
75a70cf9 6884 tree block, control;
6885 gimple_stmt_iterator tgsi;
75a70cf9 6886 gimple stmt, new_stmt, bind, t;
e3a19533 6887 gimple_seq ilist, dlist, olist, new_body;
dac18d1a 6888 struct gimplify_ctx gctx;
773c5ba7 6889
75a70cf9 6890 stmt = gsi_stmt (*gsi_p);
773c5ba7 6891
dac18d1a 6892 push_gimplify_context (&gctx);
773c5ba7 6893
6894 dlist = NULL;
6895 ilist = NULL;
75a70cf9 6896 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
6897 &ilist, &dlist, ctx);
773c5ba7 6898
e3a19533 6899 new_body = gimple_omp_body (stmt);
6900 gimple_omp_set_body (stmt, NULL);
6901 tgsi = gsi_start (new_body);
6902 for (; !gsi_end_p (tgsi); gsi_next (&tgsi))
773c5ba7 6903 {
6904 omp_context *sctx;
75a70cf9 6905 gimple sec_start;
773c5ba7 6906
75a70cf9 6907 sec_start = gsi_stmt (tgsi);
773c5ba7 6908 sctx = maybe_lookup_ctx (sec_start);
6909 gcc_assert (sctx);
6910
e3a19533 6911 lower_omp (gimple_omp_body_ptr (sec_start), sctx);
6912 gsi_insert_seq_after (&tgsi, gimple_omp_body (sec_start),
6913 GSI_CONTINUE_LINKING);
75a70cf9 6914 gimple_omp_set_body (sec_start, NULL);
773c5ba7 6915
e3a19533 6916 if (gsi_one_before_end_p (tgsi))
773c5ba7 6917 {
75a70cf9 6918 gimple_seq l = NULL;
6919 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
773c5ba7 6920 &l, ctx);
e3a19533 6921 gsi_insert_seq_after (&tgsi, l, GSI_CONTINUE_LINKING);
75a70cf9 6922 gimple_omp_section_set_last (sec_start);
773c5ba7 6923 }
48e1416a 6924
e3a19533 6925 gsi_insert_after (&tgsi, gimple_build_omp_return (false),
6926 GSI_CONTINUE_LINKING);
773c5ba7 6927 }
1e8e9920 6928
6929 block = make_node (BLOCK);
e3a19533 6930 bind = gimple_build_bind (NULL, new_body, block);
1e8e9920 6931
75a70cf9 6932 olist = NULL;
6933 lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist, ctx);
773c5ba7 6934
1d22f541 6935 block = make_node (BLOCK);
75a70cf9 6936 new_stmt = gimple_build_bind (NULL, NULL, block);
e3a19533 6937 gsi_replace (gsi_p, new_stmt, true);
773c5ba7 6938
1d22f541 6939 pop_gimplify_context (new_stmt);
75a70cf9 6940 gimple_bind_append_vars (new_stmt, ctx->block_vars);
6941 BLOCK_VARS (block) = gimple_bind_vars (bind);
1d22f541 6942 if (BLOCK_VARS (block))
6943 TREE_USED (block) = 1;
6944
75a70cf9 6945 new_body = NULL;
6946 gimple_seq_add_seq (&new_body, ilist);
6947 gimple_seq_add_stmt (&new_body, stmt);
6948 gimple_seq_add_stmt (&new_body, gimple_build_omp_sections_switch ());
6949 gimple_seq_add_stmt (&new_body, bind);
61e47ac8 6950
ac6e3339 6951 control = create_tmp_var (unsigned_type_node, ".section");
75a70cf9 6952 t = gimple_build_omp_continue (control, control);
6953 gimple_omp_sections_set_control (stmt, control);
6954 gimple_seq_add_stmt (&new_body, t);
61e47ac8 6955
75a70cf9 6956 gimple_seq_add_seq (&new_body, olist);
6957 gimple_seq_add_seq (&new_body, dlist);
773c5ba7 6958
75a70cf9 6959 new_body = maybe_catch_exception (new_body);
aade31a0 6960
75a70cf9 6961 t = gimple_build_omp_return
6962 (!!find_omp_clause (gimple_omp_sections_clauses (stmt),
6963 OMP_CLAUSE_NOWAIT));
6964 gimple_seq_add_stmt (&new_body, t);
61e47ac8 6965
75a70cf9 6966 gimple_bind_set_body (new_stmt, new_body);
1e8e9920 6967}
6968
6969
773c5ba7 6970/* A subroutine of lower_omp_single. Expand the simple form of
75a70cf9 6971 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
1e8e9920 6972
6973 if (GOMP_single_start ())
6974 BODY;
6975 [ GOMP_barrier (); ] -> unless 'nowait' is present.
773c5ba7 6976
6977 FIXME. It may be better to delay expanding the logic of this until
6978 pass_expand_omp. The expanded logic may make the job more difficult
6979 to a synchronization analysis pass. */
1e8e9920 6980
6981static void
75a70cf9 6982lower_omp_single_simple (gimple single_stmt, gimple_seq *pre_p)
1e8e9920 6983{
e60a6f7b 6984 location_t loc = gimple_location (single_stmt);
6985 tree tlabel = create_artificial_label (loc);
6986 tree flabel = create_artificial_label (loc);
75a70cf9 6987 gimple call, cond;
6988 tree lhs, decl;
6989
b9a16870 6990 decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START);
75a70cf9 6991 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)), NULL);
6992 call = gimple_build_call (decl, 0);
6993 gimple_call_set_lhs (call, lhs);
6994 gimple_seq_add_stmt (pre_p, call);
6995
6996 cond = gimple_build_cond (EQ_EXPR, lhs,
389dd41b 6997 fold_convert_loc (loc, TREE_TYPE (lhs),
6998 boolean_true_node),
75a70cf9 6999 tlabel, flabel);
7000 gimple_seq_add_stmt (pre_p, cond);
7001 gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
7002 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
7003 gimple_seq_add_stmt (pre_p, gimple_build_label (flabel));
1e8e9920 7004}
7005
773c5ba7 7006
7007/* A subroutine of lower_omp_single. Expand the simple form of
75a70cf9 7008 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
1e8e9920 7009
7010 #pragma omp single copyprivate (a, b, c)
7011
7012 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
7013
7014 {
7015 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
7016 {
7017 BODY;
7018 copyout.a = a;
7019 copyout.b = b;
7020 copyout.c = c;
7021 GOMP_single_copy_end (&copyout);
7022 }
7023 else
7024 {
7025 a = copyout_p->a;
7026 b = copyout_p->b;
7027 c = copyout_p->c;
7028 }
7029 GOMP_barrier ();
7030 }
773c5ba7 7031
7032 FIXME. It may be better to delay expanding the logic of this until
7033 pass_expand_omp. The expanded logic may make the job more difficult
7034 to a synchronization analysis pass. */
1e8e9920 7035
7036static void
75a70cf9 7037lower_omp_single_copy (gimple single_stmt, gimple_seq *pre_p, omp_context *ctx)
1e8e9920 7038{
b9a16870 7039 tree ptr_type, t, l0, l1, l2, bfn_decl;
75a70cf9 7040 gimple_seq copyin_seq;
e60a6f7b 7041 location_t loc = gimple_location (single_stmt);
1e8e9920 7042
7043 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
7044
7045 ptr_type = build_pointer_type (ctx->record_type);
7046 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
7047
e60a6f7b 7048 l0 = create_artificial_label (loc);
7049 l1 = create_artificial_label (loc);
7050 l2 = create_artificial_label (loc);
1e8e9920 7051
b9a16870 7052 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START);
7053 t = build_call_expr_loc (loc, bfn_decl, 0);
389dd41b 7054 t = fold_convert_loc (loc, ptr_type, t);
75a70cf9 7055 gimplify_assign (ctx->receiver_decl, t, pre_p);
1e8e9920 7056
7057 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
7058 build_int_cst (ptr_type, 0));
7059 t = build3 (COND_EXPR, void_type_node, t,
7060 build_and_jump (&l0), build_and_jump (&l1));
7061 gimplify_and_add (t, pre_p);
7062
75a70cf9 7063 gimple_seq_add_stmt (pre_p, gimple_build_label (l0));
1e8e9920 7064
75a70cf9 7065 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
1e8e9920 7066
7067 copyin_seq = NULL;
75a70cf9 7068 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
1e8e9920 7069 &copyin_seq, ctx);
7070
389dd41b 7071 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
b9a16870 7072 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END);
7073 t = build_call_expr_loc (loc, bfn_decl, 1, t);
1e8e9920 7074 gimplify_and_add (t, pre_p);
7075
7076 t = build_and_jump (&l2);
7077 gimplify_and_add (t, pre_p);
7078
75a70cf9 7079 gimple_seq_add_stmt (pre_p, gimple_build_label (l1));
1e8e9920 7080
75a70cf9 7081 gimple_seq_add_seq (pre_p, copyin_seq);
1e8e9920 7082
75a70cf9 7083 gimple_seq_add_stmt (pre_p, gimple_build_label (l2));
1e8e9920 7084}
7085
773c5ba7 7086
1e8e9920 7087/* Expand code for an OpenMP single directive. */
7088
7089static void
75a70cf9 7090lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
1e8e9920 7091{
75a70cf9 7092 tree block;
7093 gimple t, bind, single_stmt = gsi_stmt (*gsi_p);
7094 gimple_seq bind_body, dlist;
dac18d1a 7095 struct gimplify_ctx gctx;
1e8e9920 7096
dac18d1a 7097 push_gimplify_context (&gctx);
1e8e9920 7098
e3a19533 7099 block = make_node (BLOCK);
7100 bind = gimple_build_bind (NULL, NULL, block);
7101 gsi_replace (gsi_p, bind, true);
75a70cf9 7102 bind_body = NULL;
e3a19533 7103 dlist = NULL;
75a70cf9 7104 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt),
7105 &bind_body, &dlist, ctx);
e3a19533 7106 lower_omp (gimple_omp_body_ptr (single_stmt), ctx);
1e8e9920 7107
75a70cf9 7108 gimple_seq_add_stmt (&bind_body, single_stmt);
1e8e9920 7109
7110 if (ctx->record_type)
75a70cf9 7111 lower_omp_single_copy (single_stmt, &bind_body, ctx);
1e8e9920 7112 else
75a70cf9 7113 lower_omp_single_simple (single_stmt, &bind_body);
7114
7115 gimple_omp_set_body (single_stmt, NULL);
1e8e9920 7116
75a70cf9 7117 gimple_seq_add_seq (&bind_body, dlist);
61e47ac8 7118
75a70cf9 7119 bind_body = maybe_catch_exception (bind_body);
61e47ac8 7120
48e1416a 7121 t = gimple_build_omp_return
75a70cf9 7122 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt),
7123 OMP_CLAUSE_NOWAIT));
7124 gimple_seq_add_stmt (&bind_body, t);
e3a19533 7125 gimple_bind_set_body (bind, bind_body);
61e47ac8 7126
1e8e9920 7127 pop_gimplify_context (bind);
773c5ba7 7128
75a70cf9 7129 gimple_bind_append_vars (bind, ctx->block_vars);
7130 BLOCK_VARS (block) = ctx->block_vars;
1d22f541 7131 if (BLOCK_VARS (block))
7132 TREE_USED (block) = 1;
1e8e9920 7133}
7134
773c5ba7 7135
1e8e9920 7136/* Expand code for an OpenMP master directive. */
7137
7138static void
75a70cf9 7139lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
1e8e9920 7140{
b9a16870 7141 tree block, lab = NULL, x, bfn_decl;
75a70cf9 7142 gimple stmt = gsi_stmt (*gsi_p), bind;
389dd41b 7143 location_t loc = gimple_location (stmt);
75a70cf9 7144 gimple_seq tseq;
dac18d1a 7145 struct gimplify_ctx gctx;
1e8e9920 7146
dac18d1a 7147 push_gimplify_context (&gctx);
1e8e9920 7148
7149 block = make_node (BLOCK);
e3a19533 7150 bind = gimple_build_bind (NULL, NULL, block);
7151 gsi_replace (gsi_p, bind, true);
7152 gimple_bind_add_stmt (bind, stmt);
61e47ac8 7153
b9a16870 7154 bfn_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
7155 x = build_call_expr_loc (loc, bfn_decl, 0);
1e8e9920 7156 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
7157 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
75a70cf9 7158 tseq = NULL;
7159 gimplify_and_add (x, &tseq);
7160 gimple_bind_add_seq (bind, tseq);
1e8e9920 7161
e3a19533 7162 lower_omp (gimple_omp_body_ptr (stmt), ctx);
75a70cf9 7163 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
7164 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
7165 gimple_omp_set_body (stmt, NULL);
1e8e9920 7166
75a70cf9 7167 gimple_bind_add_stmt (bind, gimple_build_label (lab));
61e47ac8 7168
75a70cf9 7169 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
61e47ac8 7170
1e8e9920 7171 pop_gimplify_context (bind);
773c5ba7 7172
75a70cf9 7173 gimple_bind_append_vars (bind, ctx->block_vars);
7174 BLOCK_VARS (block) = ctx->block_vars;
1e8e9920 7175}
7176
773c5ba7 7177
1e8e9920 7178/* Expand code for an OpenMP ordered directive. */
7179
7180static void
75a70cf9 7181lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
1e8e9920 7182{
75a70cf9 7183 tree block;
7184 gimple stmt = gsi_stmt (*gsi_p), bind, x;
dac18d1a 7185 struct gimplify_ctx gctx;
1e8e9920 7186
dac18d1a 7187 push_gimplify_context (&gctx);
1e8e9920 7188
7189 block = make_node (BLOCK);
e3a19533 7190 bind = gimple_build_bind (NULL, NULL, block);
7191 gsi_replace (gsi_p, bind, true);
7192 gimple_bind_add_stmt (bind, stmt);
61e47ac8 7193
b9a16870 7194 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START),
7195 0);
75a70cf9 7196 gimple_bind_add_stmt (bind, x);
1e8e9920 7197
e3a19533 7198 lower_omp (gimple_omp_body_ptr (stmt), ctx);
75a70cf9 7199 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
7200 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
7201 gimple_omp_set_body (stmt, NULL);
1e8e9920 7202
b9a16870 7203 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END), 0);
75a70cf9 7204 gimple_bind_add_stmt (bind, x);
61e47ac8 7205
75a70cf9 7206 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
61e47ac8 7207
1e8e9920 7208 pop_gimplify_context (bind);
773c5ba7 7209
75a70cf9 7210 gimple_bind_append_vars (bind, ctx->block_vars);
7211 BLOCK_VARS (block) = gimple_bind_vars (bind);
1e8e9920 7212}
7213
1e8e9920 7214
75a70cf9 7215/* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
1e8e9920 7216 substitution of a couple of function calls. But in the NAMED case,
7217 requires that languages coordinate a symbol name. It is therefore
7218 best put here in common code. */
7219
7220static GTY((param1_is (tree), param2_is (tree)))
7221 splay_tree critical_name_mutexes;
7222
7223static void
75a70cf9 7224lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
1e8e9920 7225{
75a70cf9 7226 tree block;
7227 tree name, lock, unlock;
7228 gimple stmt = gsi_stmt (*gsi_p), bind;
389dd41b 7229 location_t loc = gimple_location (stmt);
75a70cf9 7230 gimple_seq tbody;
dac18d1a 7231 struct gimplify_ctx gctx;
1e8e9920 7232
75a70cf9 7233 name = gimple_omp_critical_name (stmt);
1e8e9920 7234 if (name)
7235 {
c2f47e15 7236 tree decl;
1e8e9920 7237 splay_tree_node n;
7238
7239 if (!critical_name_mutexes)
7240 critical_name_mutexes
ba72912a 7241 = splay_tree_new_ggc (splay_tree_compare_pointers,
7242 ggc_alloc_splay_tree_tree_node_tree_node_splay_tree_s,
7243 ggc_alloc_splay_tree_tree_node_tree_node_splay_tree_node_s);
1e8e9920 7244
7245 n = splay_tree_lookup (critical_name_mutexes, (splay_tree_key) name);
7246 if (n == NULL)
7247 {
7248 char *new_str;
7249
7250 decl = create_tmp_var_raw (ptr_type_node, NULL);
7251
7252 new_str = ACONCAT ((".gomp_critical_user_",
7253 IDENTIFIER_POINTER (name), NULL));
7254 DECL_NAME (decl) = get_identifier (new_str);
7255 TREE_PUBLIC (decl) = 1;
7256 TREE_STATIC (decl) = 1;
7257 DECL_COMMON (decl) = 1;
7258 DECL_ARTIFICIAL (decl) = 1;
7259 DECL_IGNORED_P (decl) = 1;
1d416bd7 7260 varpool_finalize_decl (decl);
1e8e9920 7261
7262 splay_tree_insert (critical_name_mutexes, (splay_tree_key) name,
7263 (splay_tree_value) decl);
7264 }
7265 else
7266 decl = (tree) n->value;
7267
b9a16870 7268 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START);
389dd41b 7269 lock = build_call_expr_loc (loc, lock, 1, build_fold_addr_expr_loc (loc, decl));
1e8e9920 7270
b9a16870 7271 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END);
389dd41b 7272 unlock = build_call_expr_loc (loc, unlock, 1,
7273 build_fold_addr_expr_loc (loc, decl));
1e8e9920 7274 }
7275 else
7276 {
b9a16870 7277 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START);
389dd41b 7278 lock = build_call_expr_loc (loc, lock, 0);
1e8e9920 7279
b9a16870 7280 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END);
389dd41b 7281 unlock = build_call_expr_loc (loc, unlock, 0);
1e8e9920 7282 }
7283
dac18d1a 7284 push_gimplify_context (&gctx);
1e8e9920 7285
7286 block = make_node (BLOCK);
e3a19533 7287 bind = gimple_build_bind (NULL, NULL, block);
7288 gsi_replace (gsi_p, bind, true);
7289 gimple_bind_add_stmt (bind, stmt);
61e47ac8 7290
75a70cf9 7291 tbody = gimple_bind_body (bind);
7292 gimplify_and_add (lock, &tbody);
7293 gimple_bind_set_body (bind, tbody);
1e8e9920 7294
e3a19533 7295 lower_omp (gimple_omp_body_ptr (stmt), ctx);
75a70cf9 7296 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
7297 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
7298 gimple_omp_set_body (stmt, NULL);
1e8e9920 7299
75a70cf9 7300 tbody = gimple_bind_body (bind);
7301 gimplify_and_add (unlock, &tbody);
7302 gimple_bind_set_body (bind, tbody);
61e47ac8 7303
75a70cf9 7304 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
1e8e9920 7305
7306 pop_gimplify_context (bind);
75a70cf9 7307 gimple_bind_append_vars (bind, ctx->block_vars);
7308 BLOCK_VARS (block) = gimple_bind_vars (bind);
773c5ba7 7309}
7310
7311
7312/* A subroutine of lower_omp_for. Generate code to emit the predicate
7313 for a lastprivate clause. Given a loop control predicate of (V
7314 cond N2), we gate the clause on (!(V cond N2)). The lowered form
1e4afe3c 7315 is appended to *DLIST, iterator initialization is appended to
7316 *BODY_P. */
773c5ba7 7317
7318static void
75a70cf9 7319lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
7320 gimple_seq *dlist, struct omp_context *ctx)
773c5ba7 7321{
75a70cf9 7322 tree clauses, cond, vinit;
773c5ba7 7323 enum tree_code cond_code;
75a70cf9 7324 gimple_seq stmts;
48e1416a 7325
fd6481cf 7326 cond_code = fd->loop.cond_code;
773c5ba7 7327 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
7328
7329 /* When possible, use a strict equality expression. This can let VRP
7330 type optimizations deduce the value and remove a copy. */
fd6481cf 7331 if (host_integerp (fd->loop.step, 0))
773c5ba7 7332 {
fd6481cf 7333 HOST_WIDE_INT step = TREE_INT_CST_LOW (fd->loop.step);
773c5ba7 7334 if (step == 1 || step == -1)
7335 cond_code = EQ_EXPR;
7336 }
7337
fd6481cf 7338 cond = build2 (cond_code, boolean_type_node, fd->loop.v, fd->loop.n2);
773c5ba7 7339
75a70cf9 7340 clauses = gimple_omp_for_clauses (fd->for_stmt);
1e4afe3c 7341 stmts = NULL;
7342 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
75a70cf9 7343 if (!gimple_seq_empty_p (stmts))
1e4afe3c 7344 {
75a70cf9 7345 gimple_seq_add_seq (&stmts, *dlist);
fd6481cf 7346 *dlist = stmts;
1e4afe3c 7347
7348 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
fd6481cf 7349 vinit = fd->loop.n1;
1e4afe3c 7350 if (cond_code == EQ_EXPR
fd6481cf 7351 && host_integerp (fd->loop.n2, 0)
7352 && ! integer_zerop (fd->loop.n2))
7353 vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0);
3d483a94 7354 else
7355 vinit = unshare_expr (vinit);
1e4afe3c 7356
7357 /* Initialize the iterator variable, so that threads that don't execute
7358 any iterations don't execute the lastprivate clauses by accident. */
75a70cf9 7359 gimplify_assign (fd->loop.v, vinit, body_p);
1e4afe3c 7360 }
773c5ba7 7361}
7362
7363
7364/* Lower code for an OpenMP loop directive. */
7365
7366static void
75a70cf9 7367lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
773c5ba7 7368{
75a70cf9 7369 tree *rhs_p, block;
773c5ba7 7370 struct omp_for_data fd;
75a70cf9 7371 gimple stmt = gsi_stmt (*gsi_p), new_stmt;
f018d957 7372 gimple_seq omp_for_body, body, dlist;
75a70cf9 7373 size_t i;
dac18d1a 7374 struct gimplify_ctx gctx;
773c5ba7 7375
dac18d1a 7376 push_gimplify_context (&gctx);
773c5ba7 7377
e3a19533 7378 lower_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
773c5ba7 7379
1d22f541 7380 block = make_node (BLOCK);
75a70cf9 7381 new_stmt = gimple_build_bind (NULL, NULL, block);
e3a19533 7382 /* Replace at gsi right away, so that 'stmt' is no member
7383 of a sequence anymore as we're going to add to to a different
7384 one below. */
7385 gsi_replace (gsi_p, new_stmt, true);
1d22f541 7386
773c5ba7 7387 /* Move declaration of temporaries in the loop body before we make
7388 it go away. */
75a70cf9 7389 omp_for_body = gimple_omp_body (stmt);
7390 if (!gimple_seq_empty_p (omp_for_body)
7391 && gimple_code (gimple_seq_first_stmt (omp_for_body)) == GIMPLE_BIND)
7392 {
7393 tree vars = gimple_bind_vars (gimple_seq_first_stmt (omp_for_body));
7394 gimple_bind_append_vars (new_stmt, vars);
7395 }
773c5ba7 7396
75a70cf9 7397 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
773c5ba7 7398 dlist = NULL;
75a70cf9 7399 body = NULL;
7400 lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx);
7401 gimple_seq_add_seq (&body, gimple_omp_for_pre_body (stmt));
773c5ba7 7402
3d483a94 7403 lower_omp (gimple_omp_body_ptr (stmt), ctx);
7404
773c5ba7 7405 /* Lower the header expressions. At this point, we can assume that
7406 the header is of the form:
7407
7408 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
7409
7410 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
7411 using the .omp_data_s mapping, if needed. */
75a70cf9 7412 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
fd6481cf 7413 {
75a70cf9 7414 rhs_p = gimple_omp_for_initial_ptr (stmt, i);
fd6481cf 7415 if (!is_gimple_min_invariant (*rhs_p))
75a70cf9 7416 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
fd6481cf 7417
75a70cf9 7418 rhs_p = gimple_omp_for_final_ptr (stmt, i);
fd6481cf 7419 if (!is_gimple_min_invariant (*rhs_p))
75a70cf9 7420 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
fd6481cf 7421
75a70cf9 7422 rhs_p = &TREE_OPERAND (gimple_omp_for_incr (stmt, i), 1);
fd6481cf 7423 if (!is_gimple_min_invariant (*rhs_p))
75a70cf9 7424 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
fd6481cf 7425 }
773c5ba7 7426
7427 /* Once lowered, extract the bounds and clauses. */
fd6481cf 7428 extract_omp_for_data (stmt, &fd, NULL);
773c5ba7 7429
75a70cf9 7430 lower_omp_for_lastprivate (&fd, &body, &dlist, ctx);
773c5ba7 7431
75a70cf9 7432 gimple_seq_add_stmt (&body, stmt);
7433 gimple_seq_add_seq (&body, gimple_omp_body (stmt));
61e47ac8 7434
75a70cf9 7435 gimple_seq_add_stmt (&body, gimple_build_omp_continue (fd.loop.v,
7436 fd.loop.v));
61e47ac8 7437
773c5ba7 7438 /* After the loop, add exit clauses. */
75a70cf9 7439 lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, ctx);
7440 gimple_seq_add_seq (&body, dlist);
773c5ba7 7441
75a70cf9 7442 body = maybe_catch_exception (body);
aade31a0 7443
61e47ac8 7444 /* Region exit marker goes at the end of the loop body. */
75a70cf9 7445 gimple_seq_add_stmt (&body, gimple_build_omp_return (fd.have_nowait));
773c5ba7 7446
1d22f541 7447 pop_gimplify_context (new_stmt);
75a70cf9 7448
7449 gimple_bind_append_vars (new_stmt, ctx->block_vars);
7450 BLOCK_VARS (block) = gimple_bind_vars (new_stmt);
1d22f541 7451 if (BLOCK_VARS (block))
7452 TREE_USED (block) = 1;
773c5ba7 7453
75a70cf9 7454 gimple_bind_set_body (new_stmt, body);
7455 gimple_omp_set_body (stmt, NULL);
7456 gimple_omp_for_set_pre_body (stmt, NULL);
1e8e9920 7457}
7458
48e1416a 7459/* Callback for walk_stmts. Check if the current statement only contains
75a70cf9 7460 GIMPLE_OMP_FOR or GIMPLE_OMP_PARALLEL. */
de7ef844 7461
7462static tree
75a70cf9 7463check_combined_parallel (gimple_stmt_iterator *gsi_p,
7464 bool *handled_ops_p,
7465 struct walk_stmt_info *wi)
de7ef844 7466{
4077bf7a 7467 int *info = (int *) wi->info;
75a70cf9 7468 gimple stmt = gsi_stmt (*gsi_p);
de7ef844 7469
75a70cf9 7470 *handled_ops_p = true;
7471 switch (gimple_code (stmt))
de7ef844 7472 {
75a70cf9 7473 WALK_SUBSTMTS;
7474
7475 case GIMPLE_OMP_FOR:
7476 case GIMPLE_OMP_SECTIONS:
de7ef844 7477 *info = *info == 0 ? 1 : -1;
7478 break;
7479 default:
7480 *info = -1;
7481 break;
7482 }
7483 return NULL;
7484}
773c5ba7 7485
fd6481cf 7486struct omp_taskcopy_context
7487{
7488 /* This field must be at the beginning, as we do "inheritance": Some
7489 callback functions for tree-inline.c (e.g., omp_copy_decl)
7490 receive a copy_body_data pointer that is up-casted to an
7491 omp_context pointer. */
7492 copy_body_data cb;
7493 omp_context *ctx;
7494};
7495
7496static tree
7497task_copyfn_copy_decl (tree var, copy_body_data *cb)
7498{
7499 struct omp_taskcopy_context *tcctx = (struct omp_taskcopy_context *) cb;
7500
7501 if (splay_tree_lookup (tcctx->ctx->sfield_map, (splay_tree_key) var))
7502 return create_tmp_var (TREE_TYPE (var), NULL);
7503
7504 return var;
7505}
7506
7507static tree
7508task_copyfn_remap_type (struct omp_taskcopy_context *tcctx, tree orig_type)
7509{
7510 tree name, new_fields = NULL, type, f;
7511
7512 type = lang_hooks.types.make_type (RECORD_TYPE);
7513 name = DECL_NAME (TYPE_NAME (orig_type));
e60a6f7b 7514 name = build_decl (gimple_location (tcctx->ctx->stmt),
7515 TYPE_DECL, name, type);
fd6481cf 7516 TYPE_NAME (type) = name;
7517
7518 for (f = TYPE_FIELDS (orig_type); f ; f = TREE_CHAIN (f))
7519 {
7520 tree new_f = copy_node (f);
7521 DECL_CONTEXT (new_f) = type;
7522 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &tcctx->cb);
7523 TREE_CHAIN (new_f) = new_fields;
75a70cf9 7524 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &tcctx->cb, NULL);
7525 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r, &tcctx->cb, NULL);
7526 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
7527 &tcctx->cb, NULL);
fd6481cf 7528 new_fields = new_f;
7529 *pointer_map_insert (tcctx->cb.decl_map, f) = new_f;
7530 }
7531 TYPE_FIELDS (type) = nreverse (new_fields);
7532 layout_type (type);
7533 return type;
7534}
7535
7536/* Create task copyfn. */
7537
7538static void
75a70cf9 7539create_task_copyfn (gimple task_stmt, omp_context *ctx)
fd6481cf 7540{
7541 struct function *child_cfun;
7542 tree child_fn, t, c, src, dst, f, sf, arg, sarg, decl;
7543 tree record_type, srecord_type, bind, list;
7544 bool record_needs_remap = false, srecord_needs_remap = false;
7545 splay_tree_node n;
7546 struct omp_taskcopy_context tcctx;
dac18d1a 7547 struct gimplify_ctx gctx;
389dd41b 7548 location_t loc = gimple_location (task_stmt);
fd6481cf 7549
75a70cf9 7550 child_fn = gimple_omp_task_copy_fn (task_stmt);
fd6481cf 7551 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
7552 gcc_assert (child_cfun->cfg == NULL);
fd6481cf 7553 DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
7554
7555 /* Reset DECL_CONTEXT on function arguments. */
1767a056 7556 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
fd6481cf 7557 DECL_CONTEXT (t) = child_fn;
7558
7559 /* Populate the function. */
dac18d1a 7560 push_gimplify_context (&gctx);
9078126c 7561 push_cfun (child_cfun);
fd6481cf 7562
7563 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
7564 TREE_SIDE_EFFECTS (bind) = 1;
7565 list = NULL;
7566 DECL_SAVED_TREE (child_fn) = bind;
75a70cf9 7567 DECL_SOURCE_LOCATION (child_fn) = gimple_location (task_stmt);
fd6481cf 7568
7569 /* Remap src and dst argument types if needed. */
7570 record_type = ctx->record_type;
7571 srecord_type = ctx->srecord_type;
1767a056 7572 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
fd6481cf 7573 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
7574 {
7575 record_needs_remap = true;
7576 break;
7577 }
1767a056 7578 for (f = TYPE_FIELDS (srecord_type); f ; f = DECL_CHAIN (f))
fd6481cf 7579 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
7580 {
7581 srecord_needs_remap = true;
7582 break;
7583 }
7584
7585 if (record_needs_remap || srecord_needs_remap)
7586 {
7587 memset (&tcctx, '\0', sizeof (tcctx));
7588 tcctx.cb.src_fn = ctx->cb.src_fn;
7589 tcctx.cb.dst_fn = child_fn;
53f79206 7590 tcctx.cb.src_node = cgraph_get_node (tcctx.cb.src_fn);
7591 gcc_checking_assert (tcctx.cb.src_node);
fd6481cf 7592 tcctx.cb.dst_node = tcctx.cb.src_node;
7593 tcctx.cb.src_cfun = ctx->cb.src_cfun;
7594 tcctx.cb.copy_decl = task_copyfn_copy_decl;
e38def9c 7595 tcctx.cb.eh_lp_nr = 0;
fd6481cf 7596 tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
7597 tcctx.cb.decl_map = pointer_map_create ();
7598 tcctx.ctx = ctx;
7599
7600 if (record_needs_remap)
7601 record_type = task_copyfn_remap_type (&tcctx, record_type);
7602 if (srecord_needs_remap)
7603 srecord_type = task_copyfn_remap_type (&tcctx, srecord_type);
7604 }
7605 else
7606 tcctx.cb.decl_map = NULL;
7607
fd6481cf 7608 arg = DECL_ARGUMENTS (child_fn);
7609 TREE_TYPE (arg) = build_pointer_type (record_type);
1767a056 7610 sarg = DECL_CHAIN (arg);
fd6481cf 7611 TREE_TYPE (sarg) = build_pointer_type (srecord_type);
7612
7613 /* First pass: initialize temporaries used in record_type and srecord_type
7614 sizes and field offsets. */
7615 if (tcctx.cb.decl_map)
75a70cf9 7616 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
fd6481cf 7617 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
7618 {
7619 tree *p;
7620
7621 decl = OMP_CLAUSE_DECL (c);
7622 p = (tree *) pointer_map_contains (tcctx.cb.decl_map, decl);
7623 if (p == NULL)
7624 continue;
7625 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
7626 sf = (tree) n->value;
7627 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
182cf5a9 7628 src = build_simple_mem_ref_loc (loc, sarg);
445d06b6 7629 src = omp_build_component_ref (src, sf);
75a70cf9 7630 t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
fd6481cf 7631 append_to_statement_list (t, &list);
7632 }
7633
7634 /* Second pass: copy shared var pointers and copy construct non-VLA
7635 firstprivate vars. */
75a70cf9 7636 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
fd6481cf 7637 switch (OMP_CLAUSE_CODE (c))
7638 {
7639 case OMP_CLAUSE_SHARED:
7640 decl = OMP_CLAUSE_DECL (c);
7641 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
7642 if (n == NULL)
7643 break;
7644 f = (tree) n->value;
7645 if (tcctx.cb.decl_map)
7646 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
7647 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
7648 sf = (tree) n->value;
7649 if (tcctx.cb.decl_map)
7650 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
182cf5a9 7651 src = build_simple_mem_ref_loc (loc, sarg);
445d06b6 7652 src = omp_build_component_ref (src, sf);
182cf5a9 7653 dst = build_simple_mem_ref_loc (loc, arg);
445d06b6 7654 dst = omp_build_component_ref (dst, f);
75a70cf9 7655 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
fd6481cf 7656 append_to_statement_list (t, &list);
7657 break;
7658 case OMP_CLAUSE_FIRSTPRIVATE:
7659 decl = OMP_CLAUSE_DECL (c);
7660 if (is_variable_sized (decl))
7661 break;
7662 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
7663 if (n == NULL)
7664 break;
7665 f = (tree) n->value;
7666 if (tcctx.cb.decl_map)
7667 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
7668 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
7669 if (n != NULL)
7670 {
7671 sf = (tree) n->value;
7672 if (tcctx.cb.decl_map)
7673 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
182cf5a9 7674 src = build_simple_mem_ref_loc (loc, sarg);
445d06b6 7675 src = omp_build_component_ref (src, sf);
fd6481cf 7676 if (use_pointer_for_field (decl, NULL) || is_reference (decl))
182cf5a9 7677 src = build_simple_mem_ref_loc (loc, src);
fd6481cf 7678 }
7679 else
7680 src = decl;
182cf5a9 7681 dst = build_simple_mem_ref_loc (loc, arg);
445d06b6 7682 dst = omp_build_component_ref (dst, f);
fd6481cf 7683 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
7684 append_to_statement_list (t, &list);
7685 break;
7686 case OMP_CLAUSE_PRIVATE:
7687 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c))
7688 break;
7689 decl = OMP_CLAUSE_DECL (c);
7690 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
7691 f = (tree) n->value;
7692 if (tcctx.cb.decl_map)
7693 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
7694 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
7695 if (n != NULL)
7696 {
7697 sf = (tree) n->value;
7698 if (tcctx.cb.decl_map)
7699 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
182cf5a9 7700 src = build_simple_mem_ref_loc (loc, sarg);
445d06b6 7701 src = omp_build_component_ref (src, sf);
fd6481cf 7702 if (use_pointer_for_field (decl, NULL))
182cf5a9 7703 src = build_simple_mem_ref_loc (loc, src);
fd6481cf 7704 }
7705 else
7706 src = decl;
182cf5a9 7707 dst = build_simple_mem_ref_loc (loc, arg);
445d06b6 7708 dst = omp_build_component_ref (dst, f);
75a70cf9 7709 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
fd6481cf 7710 append_to_statement_list (t, &list);
7711 break;
7712 default:
7713 break;
7714 }
7715
7716 /* Last pass: handle VLA firstprivates. */
7717 if (tcctx.cb.decl_map)
75a70cf9 7718 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
fd6481cf 7719 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
7720 {
7721 tree ind, ptr, df;
7722
7723 decl = OMP_CLAUSE_DECL (c);
7724 if (!is_variable_sized (decl))
7725 continue;
7726 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
7727 if (n == NULL)
7728 continue;
7729 f = (tree) n->value;
7730 f = *(tree *) pointer_map_contains (tcctx.cb.decl_map, f);
7731 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
7732 ind = DECL_VALUE_EXPR (decl);
7733 gcc_assert (TREE_CODE (ind) == INDIRECT_REF);
7734 gcc_assert (DECL_P (TREE_OPERAND (ind, 0)));
7735 n = splay_tree_lookup (ctx->sfield_map,
7736 (splay_tree_key) TREE_OPERAND (ind, 0));
7737 sf = (tree) n->value;
7738 sf = *(tree *) pointer_map_contains (tcctx.cb.decl_map, sf);
182cf5a9 7739 src = build_simple_mem_ref_loc (loc, sarg);
445d06b6 7740 src = omp_build_component_ref (src, sf);
182cf5a9 7741 src = build_simple_mem_ref_loc (loc, src);
7742 dst = build_simple_mem_ref_loc (loc, arg);
445d06b6 7743 dst = omp_build_component_ref (dst, f);
fd6481cf 7744 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
7745 append_to_statement_list (t, &list);
7746 n = splay_tree_lookup (ctx->field_map,
7747 (splay_tree_key) TREE_OPERAND (ind, 0));
7748 df = (tree) n->value;
7749 df = *(tree *) pointer_map_contains (tcctx.cb.decl_map, df);
182cf5a9 7750 ptr = build_simple_mem_ref_loc (loc, arg);
445d06b6 7751 ptr = omp_build_component_ref (ptr, df);
75a70cf9 7752 t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
389dd41b 7753 build_fold_addr_expr_loc (loc, dst));
fd6481cf 7754 append_to_statement_list (t, &list);
7755 }
7756
7757 t = build1 (RETURN_EXPR, void_type_node, NULL);
7758 append_to_statement_list (t, &list);
7759
7760 if (tcctx.cb.decl_map)
7761 pointer_map_destroy (tcctx.cb.decl_map);
7762 pop_gimplify_context (NULL);
7763 BIND_EXPR_BODY (bind) = list;
7764 pop_cfun ();
fd6481cf 7765}
7766
75a70cf9 7767/* Lower the OpenMP parallel or task directive in the current statement
7768 in GSI_P. CTX holds context information for the directive. */
773c5ba7 7769
7770static void
75a70cf9 7771lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
773c5ba7 7772{
75a70cf9 7773 tree clauses;
7774 tree child_fn, t;
7775 gimple stmt = gsi_stmt (*gsi_p);
7776 gimple par_bind, bind;
7777 gimple_seq par_body, olist, ilist, par_olist, par_ilist, new_body;
dac18d1a 7778 struct gimplify_ctx gctx;
389dd41b 7779 location_t loc = gimple_location (stmt);
773c5ba7 7780
75a70cf9 7781 clauses = gimple_omp_taskreg_clauses (stmt);
7782 par_bind = gimple_seq_first_stmt (gimple_omp_body (stmt));
7783 par_body = gimple_bind_body (par_bind);
773c5ba7 7784 child_fn = ctx->cb.dst_fn;
75a70cf9 7785 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
7786 && !gimple_omp_parallel_combined_p (stmt))
de7ef844 7787 {
7788 struct walk_stmt_info wi;
7789 int ws_num = 0;
7790
7791 memset (&wi, 0, sizeof (wi));
de7ef844 7792 wi.info = &ws_num;
7793 wi.val_only = true;
75a70cf9 7794 walk_gimple_seq (par_body, check_combined_parallel, NULL, &wi);
de7ef844 7795 if (ws_num == 1)
75a70cf9 7796 gimple_omp_parallel_set_combined_p (stmt, true);
de7ef844 7797 }
fd6481cf 7798 if (ctx->srecord_type)
7799 create_task_copyfn (stmt, ctx);
773c5ba7 7800
dac18d1a 7801 push_gimplify_context (&gctx);
773c5ba7 7802
75a70cf9 7803 par_olist = NULL;
7804 par_ilist = NULL;
773c5ba7 7805 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx);
e3a19533 7806 lower_omp (&par_body, ctx);
75a70cf9 7807 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL)
fd6481cf 7808 lower_reduction_clauses (clauses, &par_olist, ctx);
773c5ba7 7809
7810 /* Declare all the variables created by mapping and the variables
7811 declared in the scope of the parallel body. */
7812 record_vars_into (ctx->block_vars, child_fn);
75a70cf9 7813 record_vars_into (gimple_bind_vars (par_bind), child_fn);
773c5ba7 7814
7815 if (ctx->record_type)
7816 {
fd6481cf 7817 ctx->sender_decl
7818 = create_tmp_var (ctx->srecord_type ? ctx->srecord_type
7819 : ctx->record_type, ".omp_data_o");
84bfaaeb 7820 DECL_NAMELESS (ctx->sender_decl) = 1;
86f2ad37 7821 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
75a70cf9 7822 gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl);
773c5ba7 7823 }
7824
75a70cf9 7825 olist = NULL;
7826 ilist = NULL;
773c5ba7 7827 lower_send_clauses (clauses, &ilist, &olist, ctx);
7828 lower_send_shared_vars (&ilist, &olist, ctx);
7829
7830 /* Once all the expansions are done, sequence all the different
75a70cf9 7831 fragments inside gimple_omp_body. */
773c5ba7 7832
75a70cf9 7833 new_body = NULL;
773c5ba7 7834
7835 if (ctx->record_type)
7836 {
389dd41b 7837 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
cc6b725b 7838 /* fixup_child_record_type might have changed receiver_decl's type. */
389dd41b 7839 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
75a70cf9 7840 gimple_seq_add_stmt (&new_body,
7841 gimple_build_assign (ctx->receiver_decl, t));
773c5ba7 7842 }
7843
75a70cf9 7844 gimple_seq_add_seq (&new_body, par_ilist);
7845 gimple_seq_add_seq (&new_body, par_body);
7846 gimple_seq_add_seq (&new_body, par_olist);
7847 new_body = maybe_catch_exception (new_body);
7848 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
7849 gimple_omp_set_body (stmt, new_body);
773c5ba7 7850
75a70cf9 7851 bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
75a70cf9 7852 gsi_replace (gsi_p, bind, true);
e3a19533 7853 gimple_bind_add_seq (bind, ilist);
7854 gimple_bind_add_stmt (bind, stmt);
7855 gimple_bind_add_seq (bind, olist);
773c5ba7 7856
75a70cf9 7857 pop_gimplify_context (NULL);
773c5ba7 7858}
7859
a4890dc9 7860/* Callback for lower_omp_1. Return non-NULL if *tp needs to be
75a70cf9 7861 regimplified. If DATA is non-NULL, lower_omp_1 is outside
7862 of OpenMP context, but with task_shared_vars set. */
46515c92 7863
7864static tree
75a70cf9 7865lower_omp_regimplify_p (tree *tp, int *walk_subtrees,
7866 void *data)
46515c92 7867{
a4890dc9 7868 tree t = *tp;
46515c92 7869
a4890dc9 7870 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
75a70cf9 7871 if (TREE_CODE (t) == VAR_DECL && data == NULL && DECL_HAS_VALUE_EXPR_P (t))
9f49e155 7872 return t;
7873
7874 if (task_shared_vars
7875 && DECL_P (t)
7876 && bitmap_bit_p (task_shared_vars, DECL_UID (t)))
a4890dc9 7877 return t;
46515c92 7878
a4890dc9 7879 /* If a global variable has been privatized, TREE_CONSTANT on
7880 ADDR_EXPR might be wrong. */
75a70cf9 7881 if (data == NULL && TREE_CODE (t) == ADDR_EXPR)
a4890dc9 7882 recompute_tree_invariant_for_addr_expr (t);
46515c92 7883
a4890dc9 7884 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
7885 return NULL_TREE;
46515c92 7886}
773c5ba7 7887
a4890dc9 7888static void
75a70cf9 7889lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
1e8e9920 7890{
75a70cf9 7891 gimple stmt = gsi_stmt (*gsi_p);
7892 struct walk_stmt_info wi;
1e8e9920 7893
75a70cf9 7894 if (gimple_has_location (stmt))
7895 input_location = gimple_location (stmt);
a4890dc9 7896
75a70cf9 7897 if (task_shared_vars)
7898 memset (&wi, '\0', sizeof (wi));
a4890dc9 7899
773c5ba7 7900 /* If we have issued syntax errors, avoid doing any heavy lifting.
7901 Just replace the OpenMP directives with a NOP to avoid
7902 confusing RTL expansion. */
852f689e 7903 if (seen_error () && is_gimple_omp (stmt))
773c5ba7 7904 {
75a70cf9 7905 gsi_replace (gsi_p, gimple_build_nop (), true);
a4890dc9 7906 return;
773c5ba7 7907 }
7908
75a70cf9 7909 switch (gimple_code (stmt))
1e8e9920 7910 {
75a70cf9 7911 case GIMPLE_COND:
fd6481cf 7912 if ((ctx || task_shared_vars)
75a70cf9 7913 && (walk_tree (gimple_cond_lhs_ptr (stmt), lower_omp_regimplify_p,
7914 ctx ? NULL : &wi, NULL)
7915 || walk_tree (gimple_cond_rhs_ptr (stmt), lower_omp_regimplify_p,
7916 ctx ? NULL : &wi, NULL)))
7917 gimple_regimplify_operands (stmt, gsi_p);
a4890dc9 7918 break;
75a70cf9 7919 case GIMPLE_CATCH:
e3a19533 7920 lower_omp (gimple_catch_handler_ptr (stmt), ctx);
a4890dc9 7921 break;
75a70cf9 7922 case GIMPLE_EH_FILTER:
e3a19533 7923 lower_omp (gimple_eh_filter_failure_ptr (stmt), ctx);
a4890dc9 7924 break;
75a70cf9 7925 case GIMPLE_TRY:
e3a19533 7926 lower_omp (gimple_try_eval_ptr (stmt), ctx);
7927 lower_omp (gimple_try_cleanup_ptr (stmt), ctx);
a4890dc9 7928 break;
35215227 7929 case GIMPLE_TRANSACTION:
7930 lower_omp (gimple_transaction_body_ptr (stmt), ctx);
7931 break;
75a70cf9 7932 case GIMPLE_BIND:
e3a19533 7933 lower_omp (gimple_bind_body_ptr (stmt), ctx);
a4890dc9 7934 break;
75a70cf9 7935 case GIMPLE_OMP_PARALLEL:
7936 case GIMPLE_OMP_TASK:
7937 ctx = maybe_lookup_ctx (stmt);
7938 lower_omp_taskreg (gsi_p, ctx);
a4890dc9 7939 break;
75a70cf9 7940 case GIMPLE_OMP_FOR:
7941 ctx = maybe_lookup_ctx (stmt);
1e8e9920 7942 gcc_assert (ctx);
75a70cf9 7943 lower_omp_for (gsi_p, ctx);
1e8e9920 7944 break;
75a70cf9 7945 case GIMPLE_OMP_SECTIONS:
7946 ctx = maybe_lookup_ctx (stmt);
1e8e9920 7947 gcc_assert (ctx);
75a70cf9 7948 lower_omp_sections (gsi_p, ctx);
1e8e9920 7949 break;
75a70cf9 7950 case GIMPLE_OMP_SINGLE:
7951 ctx = maybe_lookup_ctx (stmt);
1e8e9920 7952 gcc_assert (ctx);
75a70cf9 7953 lower_omp_single (gsi_p, ctx);
1e8e9920 7954 break;
75a70cf9 7955 case GIMPLE_OMP_MASTER:
7956 ctx = maybe_lookup_ctx (stmt);
1e8e9920 7957 gcc_assert (ctx);
75a70cf9 7958 lower_omp_master (gsi_p, ctx);
1e8e9920 7959 break;
75a70cf9 7960 case GIMPLE_OMP_ORDERED:
7961 ctx = maybe_lookup_ctx (stmt);
1e8e9920 7962 gcc_assert (ctx);
75a70cf9 7963 lower_omp_ordered (gsi_p, ctx);
1e8e9920 7964 break;
75a70cf9 7965 case GIMPLE_OMP_CRITICAL:
7966 ctx = maybe_lookup_ctx (stmt);
1e8e9920 7967 gcc_assert (ctx);
75a70cf9 7968 lower_omp_critical (gsi_p, ctx);
7969 break;
7970 case GIMPLE_OMP_ATOMIC_LOAD:
7971 if ((ctx || task_shared_vars)
7972 && walk_tree (gimple_omp_atomic_load_rhs_ptr (stmt),
7973 lower_omp_regimplify_p, ctx ? NULL : &wi, NULL))
7974 gimple_regimplify_operands (stmt, gsi_p);
1e8e9920 7975 break;
a4890dc9 7976 default:
fd6481cf 7977 if ((ctx || task_shared_vars)
75a70cf9 7978 && walk_gimple_op (stmt, lower_omp_regimplify_p,
7979 ctx ? NULL : &wi))
7980 gimple_regimplify_operands (stmt, gsi_p);
1e8e9920 7981 break;
1e8e9920 7982 }
1e8e9920 7983}
7984
7985static void
e3a19533 7986lower_omp (gimple_seq *body, omp_context *ctx)
1e8e9920 7987{
1d22f541 7988 location_t saved_location = input_location;
e3a19533 7989 gimple_stmt_iterator gsi;
7990 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
75a70cf9 7991 lower_omp_1 (&gsi, ctx);
1d22f541 7992 input_location = saved_location;
1e8e9920 7993}
7994\f
7995/* Main entry point. */
7996
2a1990e9 7997static unsigned int
1e8e9920 7998execute_lower_omp (void)
7999{
75a70cf9 8000 gimple_seq body;
8001
41709826 8002 /* This pass always runs, to provide PROP_gimple_lomp.
8003 But there is nothing to do unless -fopenmp is given. */
8004 if (flag_openmp == 0)
8005 return 0;
8006
1e8e9920 8007 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
8008 delete_omp_context);
8009
75a70cf9 8010 body = gimple_body (current_function_decl);
ab129075 8011 scan_omp (&body, NULL);
fd6481cf 8012 gcc_assert (taskreg_nesting_level == 0);
1e8e9920 8013
8014 if (all_contexts->root)
fd6481cf 8015 {
dac18d1a 8016 struct gimplify_ctx gctx;
8017
fd6481cf 8018 if (task_shared_vars)
dac18d1a 8019 push_gimplify_context (&gctx);
e3a19533 8020 lower_omp (&body, NULL);
fd6481cf 8021 if (task_shared_vars)
8022 pop_gimplify_context (NULL);
8023 }
1e8e9920 8024
773c5ba7 8025 if (all_contexts)
8026 {
8027 splay_tree_delete (all_contexts);
8028 all_contexts = NULL;
8029 }
fd6481cf 8030 BITMAP_FREE (task_shared_vars);
2a1990e9 8031 return 0;
1e8e9920 8032}
8033
cbe8bda8 8034namespace {
8035
8036const pass_data pass_data_lower_omp =
8037{
8038 GIMPLE_PASS, /* type */
8039 "omplower", /* name */
8040 OPTGROUP_NONE, /* optinfo_flags */
8041 false, /* has_gate */
8042 true, /* has_execute */
8043 TV_NONE, /* tv_id */
8044 PROP_gimple_any, /* properties_required */
8045 PROP_gimple_lomp, /* properties_provided */
8046 0, /* properties_destroyed */
8047 0, /* todo_flags_start */
8048 0, /* todo_flags_finish */
1e8e9920 8049};
cbe8bda8 8050
8051class pass_lower_omp : public gimple_opt_pass
8052{
8053public:
8054 pass_lower_omp(gcc::context *ctxt)
8055 : gimple_opt_pass(pass_data_lower_omp, ctxt)
8056 {}
8057
8058 /* opt_pass methods: */
8059 unsigned int execute () { return execute_lower_omp (); }
8060
8061}; // class pass_lower_omp
8062
8063} // anon namespace
8064
8065gimple_opt_pass *
8066make_pass_lower_omp (gcc::context *ctxt)
8067{
8068 return new pass_lower_omp (ctxt);
8069}
1e8e9920 8070\f
8071/* The following is a utility to diagnose OpenMP structured block violations.
61e47ac8 8072 It is not part of the "omplower" pass, as that's invoked too late. It
8073 should be invoked by the respective front ends after gimplification. */
1e8e9920 8074
8075static splay_tree all_labels;
8076
8077/* Check for mismatched contexts and generate an error if needed. Return
8078 true if an error is detected. */
8079
8080static bool
75a70cf9 8081diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
8082 gimple branch_ctx, gimple label_ctx)
1e8e9920 8083{
75a70cf9 8084 if (label_ctx == branch_ctx)
1e8e9920 8085 return false;
8086
48e1416a 8087
75a70cf9 8088 /*
8089 Previously we kept track of the label's entire context in diagnose_sb_[12]
8090 so we could traverse it and issue a correct "exit" or "enter" error
8091 message upon a structured block violation.
8092
8093 We built the context by building a list with tree_cons'ing, but there is
8094 no easy counterpart in gimple tuples. It seems like far too much work
8095 for issuing exit/enter error messages. If someone really misses the
8096 distinct error message... patches welcome.
8097 */
48e1416a 8098
75a70cf9 8099#if 0
1e8e9920 8100 /* Try to avoid confusing the user by producing and error message
f0b5f617 8101 with correct "exit" or "enter" verbiage. We prefer "exit"
1e8e9920 8102 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
8103 if (branch_ctx == NULL)
8104 exit_p = false;
8105 else
8106 {
8107 while (label_ctx)
8108 {
8109 if (TREE_VALUE (label_ctx) == branch_ctx)
8110 {
8111 exit_p = false;
8112 break;
8113 }
8114 label_ctx = TREE_CHAIN (label_ctx);
8115 }
8116 }
8117
8118 if (exit_p)
8119 error ("invalid exit from OpenMP structured block");
8120 else
8121 error ("invalid entry to OpenMP structured block");
75a70cf9 8122#endif
1e8e9920 8123
75a70cf9 8124 /* If it's obvious we have an invalid entry, be specific about the error. */
8125 if (branch_ctx == NULL)
8126 error ("invalid entry to OpenMP structured block");
8127 else
8128 /* Otherwise, be vague and lazy, but efficient. */
8129 error ("invalid branch to/from an OpenMP structured block");
8130
8131 gsi_replace (gsi_p, gimple_build_nop (), false);
1e8e9920 8132 return true;
8133}
8134
8135/* Pass 1: Create a minimal tree of OpenMP structured blocks, and record
75a70cf9 8136 where each label is found. */
1e8e9920 8137
8138static tree
75a70cf9 8139diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
8140 struct walk_stmt_info *wi)
1e8e9920 8141{
75a70cf9 8142 gimple context = (gimple) wi->info;
8143 gimple inner_context;
8144 gimple stmt = gsi_stmt (*gsi_p);
1e8e9920 8145
75a70cf9 8146 *handled_ops_p = true;
8147
8148 switch (gimple_code (stmt))
1e8e9920 8149 {
75a70cf9 8150 WALK_SUBSTMTS;
48e1416a 8151
75a70cf9 8152 case GIMPLE_OMP_PARALLEL:
8153 case GIMPLE_OMP_TASK:
8154 case GIMPLE_OMP_SECTIONS:
8155 case GIMPLE_OMP_SINGLE:
8156 case GIMPLE_OMP_SECTION:
8157 case GIMPLE_OMP_MASTER:
8158 case GIMPLE_OMP_ORDERED:
8159 case GIMPLE_OMP_CRITICAL:
8160 /* The minimal context here is just the current OMP construct. */
8161 inner_context = stmt;
1e8e9920 8162 wi->info = inner_context;
75a70cf9 8163 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
1e8e9920 8164 wi->info = context;
8165 break;
8166
75a70cf9 8167 case GIMPLE_OMP_FOR:
8168 inner_context = stmt;
1e8e9920 8169 wi->info = inner_context;
75a70cf9 8170 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
8171 walk them. */
8172 walk_gimple_seq (gimple_omp_for_pre_body (stmt),
8173 diagnose_sb_1, NULL, wi);
8174 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
1e8e9920 8175 wi->info = context;
8176 break;
8177
75a70cf9 8178 case GIMPLE_LABEL:
8179 splay_tree_insert (all_labels, (splay_tree_key) gimple_label_label (stmt),
1e8e9920 8180 (splay_tree_value) context);
8181 break;
8182
8183 default:
8184 break;
8185 }
8186
8187 return NULL_TREE;
8188}
8189
8190/* Pass 2: Check each branch and see if its context differs from that of
8191 the destination label's context. */
8192
8193static tree
75a70cf9 8194diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
8195 struct walk_stmt_info *wi)
1e8e9920 8196{
75a70cf9 8197 gimple context = (gimple) wi->info;
1e8e9920 8198 splay_tree_node n;
75a70cf9 8199 gimple stmt = gsi_stmt (*gsi_p);
1e8e9920 8200
75a70cf9 8201 *handled_ops_p = true;
8202
8203 switch (gimple_code (stmt))
1e8e9920 8204 {
75a70cf9 8205 WALK_SUBSTMTS;
8206
8207 case GIMPLE_OMP_PARALLEL:
8208 case GIMPLE_OMP_TASK:
8209 case GIMPLE_OMP_SECTIONS:
8210 case GIMPLE_OMP_SINGLE:
8211 case GIMPLE_OMP_SECTION:
8212 case GIMPLE_OMP_MASTER:
8213 case GIMPLE_OMP_ORDERED:
8214 case GIMPLE_OMP_CRITICAL:
8215 wi->info = stmt;
e3a19533 8216 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
1e8e9920 8217 wi->info = context;
8218 break;
8219
75a70cf9 8220 case GIMPLE_OMP_FOR:
8221 wi->info = stmt;
8222 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
8223 walk them. */
e3a19533 8224 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt),
8225 diagnose_sb_2, NULL, wi);
8226 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
1e8e9920 8227 wi->info = context;
8228 break;
8229
0e1818e7 8230 case GIMPLE_COND:
8231 {
8232 tree lab = gimple_cond_true_label (stmt);
8233 if (lab)
8234 {
8235 n = splay_tree_lookup (all_labels,
8236 (splay_tree_key) lab);
8237 diagnose_sb_0 (gsi_p, context,
8238 n ? (gimple) n->value : NULL);
8239 }
8240 lab = gimple_cond_false_label (stmt);
8241 if (lab)
8242 {
8243 n = splay_tree_lookup (all_labels,
8244 (splay_tree_key) lab);
8245 diagnose_sb_0 (gsi_p, context,
8246 n ? (gimple) n->value : NULL);
8247 }
8248 }
8249 break;
8250
75a70cf9 8251 case GIMPLE_GOTO:
1e8e9920 8252 {
75a70cf9 8253 tree lab = gimple_goto_dest (stmt);
1e8e9920 8254 if (TREE_CODE (lab) != LABEL_DECL)
8255 break;
8256
8257 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
75a70cf9 8258 diagnose_sb_0 (gsi_p, context, n ? (gimple) n->value : NULL);
1e8e9920 8259 }
8260 break;
8261
75a70cf9 8262 case GIMPLE_SWITCH:
1e8e9920 8263 {
75a70cf9 8264 unsigned int i;
8265 for (i = 0; i < gimple_switch_num_labels (stmt); ++i)
1e8e9920 8266 {
75a70cf9 8267 tree lab = CASE_LABEL (gimple_switch_label (stmt, i));
1e8e9920 8268 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
75a70cf9 8269 if (n && diagnose_sb_0 (gsi_p, context, (gimple) n->value))
1e8e9920 8270 break;
8271 }
8272 }
8273 break;
8274
75a70cf9 8275 case GIMPLE_RETURN:
8276 diagnose_sb_0 (gsi_p, context, NULL);
1e8e9920 8277 break;
8278
8279 default:
8280 break;
8281 }
8282
8283 return NULL_TREE;
8284}
8285
bfec3452 8286static unsigned int
8287diagnose_omp_structured_block_errors (void)
1e8e9920 8288{
1e8e9920 8289 struct walk_stmt_info wi;
bfec3452 8290 gimple_seq body = gimple_body (current_function_decl);
1e8e9920 8291
8292 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
8293
8294 memset (&wi, 0, sizeof (wi));
75a70cf9 8295 walk_gimple_seq (body, diagnose_sb_1, NULL, &wi);
1e8e9920 8296
8297 memset (&wi, 0, sizeof (wi));
1e8e9920 8298 wi.want_locations = true;
e3a19533 8299 walk_gimple_seq_mod (&body, diagnose_sb_2, NULL, &wi);
8300
8301 gimple_set_body (current_function_decl, body);
1e8e9920 8302
8303 splay_tree_delete (all_labels);
8304 all_labels = NULL;
8305
bfec3452 8306 return 0;
1e8e9920 8307}
8308
bfec3452 8309static bool
8310gate_diagnose_omp_blocks (void)
8311{
8312 return flag_openmp != 0;
8313}
8314
cbe8bda8 8315namespace {
8316
8317const pass_data pass_data_diagnose_omp_blocks =
8318{
8319 GIMPLE_PASS, /* type */
8320 "*diagnose_omp_blocks", /* name */
8321 OPTGROUP_NONE, /* optinfo_flags */
8322 true, /* has_gate */
8323 true, /* has_execute */
8324 TV_NONE, /* tv_id */
8325 PROP_gimple_any, /* properties_required */
8326 0, /* properties_provided */
8327 0, /* properties_destroyed */
8328 0, /* todo_flags_start */
8329 0, /* todo_flags_finish */
bfec3452 8330};
8331
cbe8bda8 8332class pass_diagnose_omp_blocks : public gimple_opt_pass
8333{
8334public:
8335 pass_diagnose_omp_blocks(gcc::context *ctxt)
8336 : gimple_opt_pass(pass_data_diagnose_omp_blocks, ctxt)
8337 {}
8338
8339 /* opt_pass methods: */
8340 bool gate () { return gate_diagnose_omp_blocks (); }
8341 unsigned int execute () {
8342 return diagnose_omp_structured_block_errors ();
8343 }
8344
8345}; // class pass_diagnose_omp_blocks
8346
8347} // anon namespace
8348
8349gimple_opt_pass *
8350make_pass_diagnose_omp_blocks (gcc::context *ctxt)
8351{
8352 return new pass_diagnose_omp_blocks (ctxt);
8353}
8354
1e8e9920 8355#include "gt-omp-low.h"