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