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