]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/omp-low.c
re PR middle-end/27416 (ICE on invalid firstprivate/lastprivate)
[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
5b4fc8fb 6 Copyright (C) 2005, 2006 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
12Software Foundation; either version 2, or (at your option) any later
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
21along with GCC; see the file COPYING. If not, write to the Free
22Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
2302110-1301, USA. */
24
25#include "config.h"
26#include "system.h"
27#include "coretypes.h"
28#include "tm.h"
29#include "tree.h"
30#include "rtl.h"
31#include "tree-gimple.h"
32#include "tree-inline.h"
33#include "langhooks.h"
34#include "diagnostic.h"
35#include "tree-flow.h"
36#include "timevar.h"
37#include "flags.h"
38#include "function.h"
39#include "expr.h"
40#include "toplev.h"
41#include "tree-pass.h"
42#include "ggc.h"
43#include "except.h"
44
45
46/* Lowering of OpenMP parallel and workshare constructs proceeds in two
47 phases. The first phase scans the function looking for OMP statements
48 and then for variables that must be replaced to satisfy data sharing
49 clauses. The second phase expands code for the constructs, as well as
c0220ea4 50 re-gimplifying things when variables have been replaced with complex
953ff289
DN
51 expressions.
52
7ebaeab5
DN
53 Final code generation is done by pass_expand_omp. The flowgraph is
54 scanned for parallel regions which are then moved to a new
55 function, to be invoked by the thread library. */
953ff289
DN
56
57/* Context structure. Used to store information about each parallel
58 directive in the code. */
59
60typedef struct omp_context
61{
62 /* This field must be at the beginning, as we do "inheritance": Some
63 callback functions for tree-inline.c (e.g., omp_copy_decl)
64 receive a copy_body_data pointer that is up-casted to an
65 omp_context pointer. */
66 copy_body_data cb;
67
68 /* The tree of contexts corresponding to the encountered constructs. */
69 struct omp_context *outer;
70 tree stmt;
71
72 /* Map variables to fields in a structure that allows communication
73 between sending and receiving threads. */
74 splay_tree field_map;
75 tree record_type;
76 tree sender_decl;
77 tree receiver_decl;
78
79 /* A chain of variables to add to the top-level block surrounding the
80 construct. In the case of a parallel, this is in the child function. */
81 tree block_vars;
82
83 /* What to do with variables with implicitly determined sharing
84 attributes. */
85 enum omp_clause_default_kind default_kind;
86
87 /* Nesting depth of this context. Used to beautify error messages re
88 invalid gotos. The outermost ctx is depth 1, with depth 0 being
89 reserved for the main body of the function. */
90 int depth;
91
953ff289
DN
92 /* True if this parallel directive is nested within another. */
93 bool is_nested;
953ff289
DN
94} omp_context;
95
96
50674e96 97/* A structure describing the main elements of a parallel loop. */
953ff289 98
50674e96 99struct omp_for_data
953ff289
DN
100{
101 tree v, n1, n2, step, chunk_size, for_stmt;
102 enum tree_code cond_code;
103 tree pre;
953ff289
DN
104 bool have_nowait, have_ordered;
105 enum omp_clause_schedule_kind sched_kind;
106};
107
50674e96 108
953ff289
DN
109static splay_tree all_contexts;
110static int parallel_nesting_level;
777f7f9a 111struct omp_region *root_omp_region;
953ff289
DN
112
113static void scan_omp (tree *, omp_context *);
50674e96 114static void lower_omp (tree *, omp_context *);
8ca5b2a2
JJ
115static tree lookup_decl_in_outer_ctx (tree, omp_context *);
116static tree maybe_lookup_decl_in_outer_ctx (tree, omp_context *);
953ff289
DN
117
118/* Find an OpenMP clause of type KIND within CLAUSES. */
119
50674e96 120static tree
953ff289
DN
121find_omp_clause (tree clauses, enum tree_code kind)
122{
123 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
aaf46ef9 124 if (OMP_CLAUSE_CODE (clauses) == kind)
953ff289
DN
125 return clauses;
126
127 return NULL_TREE;
128}
129
130/* Return true if CTX is for an omp parallel. */
131
132static inline bool
133is_parallel_ctx (omp_context *ctx)
134{
50674e96 135 return TREE_CODE (ctx->stmt) == OMP_PARALLEL;
953ff289
DN
136}
137
50674e96
DN
138
139/* Return true if REGION is a combined parallel+workshare region. */
953ff289
DN
140
141static inline bool
50674e96
DN
142is_combined_parallel (struct omp_region *region)
143{
144 return region->is_combined_parallel;
145}
146
147
148/* Extract the header elements of parallel loop FOR_STMT and store
149 them into *FD. */
150
151static void
152extract_omp_for_data (tree for_stmt, struct omp_for_data *fd)
153{
154 tree t;
155
156 fd->for_stmt = for_stmt;
157 fd->pre = NULL;
158
159 t = OMP_FOR_INIT (for_stmt);
160 gcc_assert (TREE_CODE (t) == MODIFY_EXPR);
161 fd->v = TREE_OPERAND (t, 0);
162 gcc_assert (DECL_P (fd->v));
163 gcc_assert (TREE_CODE (TREE_TYPE (fd->v)) == INTEGER_TYPE);
164 fd->n1 = TREE_OPERAND (t, 1);
165
166 t = OMP_FOR_COND (for_stmt);
167 fd->cond_code = TREE_CODE (t);
168 gcc_assert (TREE_OPERAND (t, 0) == fd->v);
169 fd->n2 = TREE_OPERAND (t, 1);
170 switch (fd->cond_code)
171 {
172 case LT_EXPR:
173 case GT_EXPR:
174 break;
175 case LE_EXPR:
176 fd->n2 = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->n2), fd->n2,
177 build_int_cst (TREE_TYPE (fd->n2), 1));
178 fd->cond_code = LT_EXPR;
179 break;
180 case GE_EXPR:
181 fd->n2 = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->n2), fd->n2,
182 build_int_cst (TREE_TYPE (fd->n2), 1));
183 fd->cond_code = GT_EXPR;
184 break;
185 default:
186 gcc_unreachable ();
187 }
188
189 t = OMP_FOR_INCR (fd->for_stmt);
190 gcc_assert (TREE_CODE (t) == MODIFY_EXPR);
191 gcc_assert (TREE_OPERAND (t, 0) == fd->v);
192 t = TREE_OPERAND (t, 1);
193 gcc_assert (TREE_OPERAND (t, 0) == fd->v);
194 switch (TREE_CODE (t))
195 {
196 case PLUS_EXPR:
197 fd->step = TREE_OPERAND (t, 1);
198 break;
199 case MINUS_EXPR:
200 fd->step = TREE_OPERAND (t, 1);
201 fd->step = fold_build1 (NEGATE_EXPR, TREE_TYPE (fd->step), fd->step);
202 break;
203 default:
204 gcc_unreachable ();
205 }
206
207 fd->have_nowait = fd->have_ordered = false;
208 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
209 fd->chunk_size = NULL_TREE;
210
211 for (t = OMP_FOR_CLAUSES (for_stmt); t ; t = OMP_CLAUSE_CHAIN (t))
aaf46ef9 212 switch (OMP_CLAUSE_CODE (t))
50674e96
DN
213 {
214 case OMP_CLAUSE_NOWAIT:
215 fd->have_nowait = true;
216 break;
217 case OMP_CLAUSE_ORDERED:
218 fd->have_ordered = true;
219 break;
220 case OMP_CLAUSE_SCHEDULE:
221 fd->sched_kind = OMP_CLAUSE_SCHEDULE_KIND (t);
222 fd->chunk_size = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t);
223 break;
224 default:
225 break;
226 }
227
228 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
229 gcc_assert (fd->chunk_size == NULL);
230 else if (fd->chunk_size == NULL)
231 {
232 /* We only need to compute a default chunk size for ordered
233 static loops and dynamic loops. */
234 if (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC || fd->have_ordered)
235 fd->chunk_size = (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
236 ? integer_zero_node : integer_one_node;
237 }
238}
239
240
241/* Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB
242 is the immediate dominator of PAR_ENTRY_BB, return true if there
243 are no data dependencies that would prevent expanding the parallel
244 directive at PAR_ENTRY_BB as a combined parallel+workshare region.
245
246 When expanding a combined parallel+workshare region, the call to
247 the child function may need additional arguments in the case of
248 OMP_FOR regions. In some cases, these arguments are computed out
249 of variables passed in from the parent to the child via 'struct
250 .omp_data_s'. For instance:
251
252 #pragma omp parallel for schedule (guided, i * 4)
253 for (j ...)
254
255 Is lowered into:
256
257 # BLOCK 2 (PAR_ENTRY_BB)
258 .omp_data_o.i = i;
259 #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
260
261 # BLOCK 3 (WS_ENTRY_BB)
262 .omp_data_i = &.omp_data_o;
263 D.1667 = .omp_data_i->i;
264 D.1598 = D.1667 * 4;
265 #pragma omp for schedule (guided, D.1598)
266
267 When we outline the parallel region, the call to the child function
268 'bar.omp_fn.0' will need the value D.1598 in its argument list, but
269 that value is computed *after* the call site. So, in principle we
270 cannot do the transformation.
271
272 To see whether the code in WS_ENTRY_BB blocks the combined
273 parallel+workshare call, we collect all the variables used in the
274 OMP_FOR header check whether they appear on the LHS of any
275 statement in WS_ENTRY_BB. If so, then we cannot emit the combined
276 call.
277
278 FIXME. If we had the SSA form built at this point, we could merely
279 hoist the code in block 3 into block 2 and be done with it. But at
280 this point we don't have dataflow information and though we could
281 hack something up here, it is really not worth the aggravation. */
282
283static bool
284workshare_safe_to_combine_p (basic_block par_entry_bb, basic_block ws_entry_bb)
285{
286 struct omp_for_data fd;
287 tree par_stmt, ws_stmt;
288
289 par_stmt = last_stmt (par_entry_bb);
290 ws_stmt = last_stmt (ws_entry_bb);
291
292 if (TREE_CODE (ws_stmt) == OMP_SECTIONS)
293 return true;
294
295 gcc_assert (TREE_CODE (ws_stmt) == OMP_FOR);
296
297 extract_omp_for_data (ws_stmt, &fd);
298
299 /* FIXME. We give up too easily here. If any of these arguments
300 are not constants, they will likely involve variables that have
301 been mapped into fields of .omp_data_s for sharing with the child
302 function. With appropriate data flow, it would be possible to
303 see through this. */
304 if (!is_gimple_min_invariant (fd.n1)
305 || !is_gimple_min_invariant (fd.n2)
306 || !is_gimple_min_invariant (fd.step)
307 || (fd.chunk_size && !is_gimple_min_invariant (fd.chunk_size)))
308 return false;
309
310 return true;
311}
312
313
314/* Collect additional arguments needed to emit a combined
315 parallel+workshare call. WS_STMT is the workshare directive being
316 expanded. */
317
318static tree
319get_ws_args_for (tree ws_stmt)
320{
321 tree t;
322
323 if (TREE_CODE (ws_stmt) == OMP_FOR)
324 {
325 struct omp_for_data fd;
326 tree ws_args;
327
328 extract_omp_for_data (ws_stmt, &fd);
329
330 ws_args = NULL_TREE;
331 if (fd.chunk_size)
332 {
333 t = fold_convert (long_integer_type_node, fd.chunk_size);
334 ws_args = tree_cons (NULL, t, ws_args);
335 }
336
337 t = fold_convert (long_integer_type_node, fd.step);
338 ws_args = tree_cons (NULL, t, ws_args);
339
340 t = fold_convert (long_integer_type_node, fd.n2);
341 ws_args = tree_cons (NULL, t, ws_args);
342
343 t = fold_convert (long_integer_type_node, fd.n1);
344 ws_args = tree_cons (NULL, t, ws_args);
345
346 return ws_args;
347 }
348 else if (TREE_CODE (ws_stmt) == OMP_SECTIONS)
349 {
350 basic_block bb = bb_for_stmt (ws_stmt);
351 t = build_int_cst (unsigned_type_node, EDGE_COUNT (bb->succs));
352 t = tree_cons (NULL, t, NULL);
353 return t;
354 }
355
356 gcc_unreachable ();
357}
358
359
360/* Discover whether REGION is a combined parallel+workshare region. */
361
362static void
363determine_parallel_type (struct omp_region *region)
953ff289 364{
50674e96
DN
365 basic_block par_entry_bb, par_exit_bb;
366 basic_block ws_entry_bb, ws_exit_bb;
367
368 if (region == NULL || region->inner == NULL)
369 return;
370
371 /* We only support parallel+for and parallel+sections. */
777f7f9a
RH
372 if (region->type != OMP_PARALLEL
373 || (region->inner->type != OMP_FOR
374 && region->inner->type != OMP_SECTIONS))
50674e96
DN
375 return;
376
377 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
378 WS_EXIT_BB -> PAR_EXIT_BB. */
777f7f9a
RH
379 par_entry_bb = region->entry;
380 par_exit_bb = region->exit;
381 ws_entry_bb = region->inner->entry;
382 ws_exit_bb = region->inner->exit;
50674e96
DN
383
384 if (single_succ (par_entry_bb) == ws_entry_bb
385 && single_succ (ws_exit_bb) == par_exit_bb
386 && workshare_safe_to_combine_p (par_entry_bb, ws_entry_bb))
387 {
777f7f9a
RH
388 tree ws_stmt = last_stmt (region->inner->entry);
389
390 if (region->inner->type == OMP_FOR)
50674e96
DN
391 {
392 /* If this is a combined parallel loop, we need to determine
393 whether or not to use the combined library calls. There
394 are two cases where we do not apply the transformation:
395 static loops and any kind of ordered loop. In the first
396 case, we already open code the loop so there is no need
397 to do anything else. In the latter case, the combined
398 parallel loop call would still need extra synchronization
399 to implement ordered semantics, so there would not be any
400 gain in using the combined call. */
777f7f9a 401 tree clauses = OMP_FOR_CLAUSES (ws_stmt);
50674e96
DN
402 tree c = find_omp_clause (clauses, OMP_CLAUSE_SCHEDULE);
403 if (c == NULL
404 || OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_STATIC
405 || find_omp_clause (clauses, OMP_CLAUSE_ORDERED))
406 {
407 region->is_combined_parallel = false;
408 region->inner->is_combined_parallel = false;
409 return;
410 }
411 }
412
413 region->is_combined_parallel = true;
414 region->inner->is_combined_parallel = true;
777f7f9a 415 region->ws_args = get_ws_args_for (ws_stmt);
50674e96 416 }
953ff289
DN
417}
418
50674e96 419
953ff289
DN
420/* Return true if EXPR is variable sized. */
421
422static inline bool
423is_variable_sized (tree expr)
424{
425 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr)));
426}
427
428/* Return true if DECL is a reference type. */
429
430static inline bool
431is_reference (tree decl)
432{
433 return lang_hooks.decls.omp_privatize_by_reference (decl);
434}
435
436/* Lookup variables in the decl or field splay trees. The "maybe" form
437 allows for the variable form to not have been entered, otherwise we
438 assert that the variable must have been entered. */
439
440static inline tree
441lookup_decl (tree var, omp_context *ctx)
442{
443 splay_tree_node n;
444 n = splay_tree_lookup (ctx->cb.decl_map, (splay_tree_key) var);
445 return (tree) n->value;
446}
447
448static inline tree
449maybe_lookup_decl (tree var, omp_context *ctx)
450{
451 splay_tree_node n;
452 n = splay_tree_lookup (ctx->cb.decl_map, (splay_tree_key) var);
453 return n ? (tree) n->value : NULL_TREE;
454}
455
456static inline tree
457lookup_field (tree var, omp_context *ctx)
458{
459 splay_tree_node n;
460 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
461 return (tree) n->value;
462}
463
464static inline tree
465maybe_lookup_field (tree var, omp_context *ctx)
466{
467 splay_tree_node n;
468 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
469 return n ? (tree) n->value : NULL_TREE;
470}
471
472/* Return true if DECL should be copied by pointer. SHARED_P is true
473 if DECL is to be shared. */
474
475static bool
476use_pointer_for_field (tree decl, bool shared_p)
477{
478 if (AGGREGATE_TYPE_P (TREE_TYPE (decl)))
479 return true;
480
481 /* We can only use copy-in/copy-out semantics for shared varibles
482 when we know the value is not accessible from an outer scope. */
483 if (shared_p)
484 {
485 /* ??? Trivially accessible from anywhere. But why would we even
486 be passing an address in this case? Should we simply assert
487 this to be false, or should we have a cleanup pass that removes
488 these from the list of mappings? */
489 if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
490 return true;
491
492 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
493 without analyzing the expression whether or not its location
494 is accessible to anyone else. In the case of nested parallel
495 regions it certainly may be. */
077b0dfb 496 if (TREE_CODE (decl) != RESULT_DECL && DECL_HAS_VALUE_EXPR_P (decl))
953ff289
DN
497 return true;
498
499 /* Do not use copy-in/copy-out for variables that have their
500 address taken. */
501 if (TREE_ADDRESSABLE (decl))
502 return true;
503 }
504
505 return false;
506}
507
508/* Construct a new automatic decl similar to VAR. */
509
510static tree
511omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx)
512{
513 tree copy = build_decl (VAR_DECL, name, type);
514
515 TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (var);
516 DECL_COMPLEX_GIMPLE_REG_P (copy) = DECL_COMPLEX_GIMPLE_REG_P (var);
517 DECL_ARTIFICIAL (copy) = DECL_ARTIFICIAL (var);
518 DECL_IGNORED_P (copy) = DECL_IGNORED_P (var);
519 TREE_USED (copy) = 1;
50674e96 520 DECL_CONTEXT (copy) = current_function_decl;
953ff289
DN
521 DECL_SEEN_IN_BIND_EXPR_P (copy) = 1;
522
523 TREE_CHAIN (copy) = ctx->block_vars;
524 ctx->block_vars = copy;
525
526 return copy;
527}
528
529static tree
530omp_copy_decl_1 (tree var, omp_context *ctx)
531{
532 return omp_copy_decl_2 (var, DECL_NAME (var), TREE_TYPE (var), ctx);
533}
534
535/* Build tree nodes to access the field for VAR on the receiver side. */
536
537static tree
538build_receiver_ref (tree var, bool by_ref, omp_context *ctx)
539{
540 tree x, field = lookup_field (var, ctx);
541
542 /* If the receiver record type was remapped in the child function,
543 remap the field into the new record type. */
544 x = maybe_lookup_field (field, ctx);
545 if (x != NULL)
546 field = x;
547
548 x = build_fold_indirect_ref (ctx->receiver_decl);
549 x = build3 (COMPONENT_REF, TREE_TYPE (field), x, field, NULL);
550 if (by_ref)
551 x = build_fold_indirect_ref (x);
552
553 return x;
554}
555
556/* Build tree nodes to access VAR in the scope outer to CTX. In the case
557 of a parallel, this is a component reference; for workshare constructs
558 this is some variable. */
559
560static tree
561build_outer_var_ref (tree var, omp_context *ctx)
562{
563 tree x;
564
8ca5b2a2 565 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx)))
953ff289
DN
566 x = var;
567 else if (is_variable_sized (var))
568 {
569 x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
570 x = build_outer_var_ref (x, ctx);
571 x = build_fold_indirect_ref (x);
572 }
573 else if (is_parallel_ctx (ctx))
574 {
575 bool by_ref = use_pointer_for_field (var, false);
576 x = build_receiver_ref (var, by_ref, ctx);
577 }
578 else if (ctx->outer)
579 x = lookup_decl (var, ctx->outer);
eeb1d9e0
JJ
580 else if (is_reference (var))
581 /* This can happen with orphaned constructs. If var is reference, it is
582 possible it is shared and as such valid. */
583 x = var;
953ff289
DN
584 else
585 gcc_unreachable ();
586
587 if (is_reference (var))
588 x = build_fold_indirect_ref (x);
589
590 return x;
591}
592
593/* Build tree nodes to access the field for VAR on the sender side. */
594
595static tree
596build_sender_ref (tree var, omp_context *ctx)
597{
598 tree field = lookup_field (var, ctx);
599 return build3 (COMPONENT_REF, TREE_TYPE (field),
600 ctx->sender_decl, field, NULL);
601}
602
603/* Add a new field for VAR inside the structure CTX->SENDER_DECL. */
604
605static void
606install_var_field (tree var, bool by_ref, omp_context *ctx)
607{
608 tree field, type;
609
610 gcc_assert (!splay_tree_lookup (ctx->field_map, (splay_tree_key) var));
611
612 type = TREE_TYPE (var);
613 if (by_ref)
614 type = build_pointer_type (type);
615
616 field = build_decl (FIELD_DECL, DECL_NAME (var), type);
617
618 /* Remember what variable this field was created for. This does have a
619 side effect of making dwarf2out ignore this member, so for helpful
620 debugging we clear it later in delete_omp_context. */
621 DECL_ABSTRACT_ORIGIN (field) = var;
622
623 insert_field_into_struct (ctx->record_type, field);
624
625 splay_tree_insert (ctx->field_map, (splay_tree_key) var,
626 (splay_tree_value) field);
627}
628
629static tree
630install_var_local (tree var, omp_context *ctx)
631{
632 tree new_var = omp_copy_decl_1 (var, ctx);
633 insert_decl_map (&ctx->cb, var, new_var);
634 return new_var;
635}
636
637/* Adjust the replacement for DECL in CTX for the new context. This means
638 copying the DECL_VALUE_EXPR, and fixing up the type. */
639
640static void
641fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug)
642{
643 tree new_decl, size;
644
645 new_decl = lookup_decl (decl, ctx);
646
647 TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb);
648
649 if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug)
650 && DECL_HAS_VALUE_EXPR_P (decl))
651 {
652 tree ve = DECL_VALUE_EXPR (decl);
653 walk_tree (&ve, copy_body_r, &ctx->cb, NULL);
654 SET_DECL_VALUE_EXPR (new_decl, ve);
655 DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
656 }
657
658 if (!TREE_CONSTANT (DECL_SIZE (new_decl)))
659 {
660 size = remap_decl (DECL_SIZE (decl), &ctx->cb);
661 if (size == error_mark_node)
662 size = TYPE_SIZE (TREE_TYPE (new_decl));
663 DECL_SIZE (new_decl) = size;
664
665 size = remap_decl (DECL_SIZE_UNIT (decl), &ctx->cb);
666 if (size == error_mark_node)
667 size = TYPE_SIZE_UNIT (TREE_TYPE (new_decl));
668 DECL_SIZE_UNIT (new_decl) = size;
669 }
670}
671
672/* The callback for remap_decl. Search all containing contexts for a
673 mapping of the variable; this avoids having to duplicate the splay
674 tree ahead of time. We know a mapping doesn't already exist in the
675 given context. Create new mappings to implement default semantics. */
676
677static tree
678omp_copy_decl (tree var, copy_body_data *cb)
679{
680 omp_context *ctx = (omp_context *) cb;
681 tree new_var;
682
953ff289
DN
683 if (TREE_CODE (var) == LABEL_DECL)
684 {
685 new_var = create_artificial_label ();
50674e96 686 DECL_CONTEXT (new_var) = current_function_decl;
953ff289
DN
687 insert_decl_map (&ctx->cb, var, new_var);
688 return new_var;
689 }
690
691 while (!is_parallel_ctx (ctx))
692 {
693 ctx = ctx->outer;
694 if (ctx == NULL)
695 return var;
696 new_var = maybe_lookup_decl (var, ctx);
697 if (new_var)
698 return new_var;
699 }
700
8ca5b2a2
JJ
701 if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn)
702 return var;
703
953ff289
DN
704 return error_mark_node;
705}
706
50674e96
DN
707
708/* Return the parallel region associated with STMT. */
709
50674e96
DN
710/* Debugging dumps for parallel regions. */
711void dump_omp_region (FILE *, struct omp_region *, int);
712void debug_omp_region (struct omp_region *);
713void debug_all_omp_regions (void);
714
715/* Dump the parallel region tree rooted at REGION. */
716
717void
718dump_omp_region (FILE *file, struct omp_region *region, int indent)
719{
777f7f9a
RH
720 fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index,
721 tree_code_name[region->type]);
50674e96
DN
722
723 if (region->inner)
724 dump_omp_region (file, region->inner, indent + 4);
725
777f7f9a
RH
726 if (region->cont)
727 {
444e96af 728 fprintf (file, "%*sbb %d: OMP_CONTINUE\n", indent, "",
777f7f9a
RH
729 region->cont->index);
730 }
731
50674e96 732 if (region->exit)
077b0dfb 733 fprintf (file, "%*sbb %d: OMP_RETURN\n", indent, "",
777f7f9a 734 region->exit->index);
50674e96 735 else
777f7f9a 736 fprintf (file, "%*s[no exit marker]\n", indent, "");
50674e96
DN
737
738 if (region->next)
777f7f9a 739 dump_omp_region (file, region->next, indent);
50674e96
DN
740}
741
742void
743debug_omp_region (struct omp_region *region)
744{
745 dump_omp_region (stderr, region, 0);
746}
747
748void
749debug_all_omp_regions (void)
750{
751 dump_omp_region (stderr, root_omp_region, 0);
752}
753
754
755/* Create a new parallel region starting at STMT inside region PARENT. */
756
777f7f9a
RH
757struct omp_region *
758new_omp_region (basic_block bb, enum tree_code type, struct omp_region *parent)
50674e96 759{
777f7f9a 760 struct omp_region *region = xcalloc (1, sizeof (*region));
50674e96
DN
761
762 region->outer = parent;
777f7f9a
RH
763 region->entry = bb;
764 region->type = type;
50674e96
DN
765
766 if (parent)
767 {
768 /* This is a nested region. Add it to the list of inner
769 regions in PARENT. */
770 region->next = parent->inner;
771 parent->inner = region;
772 }
777f7f9a 773 else
50674e96
DN
774 {
775 /* This is a toplevel region. Add it to the list of toplevel
776 regions in ROOT_OMP_REGION. */
777 region->next = root_omp_region;
778 root_omp_region = region;
779 }
777f7f9a
RH
780
781 return region;
782}
783
784/* Release the memory associated with the region tree rooted at REGION. */
785
786static void
787free_omp_region_1 (struct omp_region *region)
788{
789 struct omp_region *i, *n;
790
791 for (i = region->inner; i ; i = n)
50674e96 792 {
777f7f9a
RH
793 n = i->next;
794 free_omp_region_1 (i);
50674e96
DN
795 }
796
777f7f9a
RH
797 free (region);
798}
50674e96 799
777f7f9a
RH
800/* Release the memory for the entire omp region tree. */
801
802void
803free_omp_regions (void)
804{
805 struct omp_region *r, *n;
806 for (r = root_omp_region; r ; r = n)
807 {
808 n = r->next;
809 free_omp_region_1 (r);
810 }
811 root_omp_region = NULL;
50674e96
DN
812}
813
814
953ff289
DN
815/* Create a new context, with OUTER_CTX being the surrounding context. */
816
817static omp_context *
818new_omp_context (tree stmt, omp_context *outer_ctx)
819{
820 omp_context *ctx = XCNEW (omp_context);
821
822 splay_tree_insert (all_contexts, (splay_tree_key) stmt,
823 (splay_tree_value) ctx);
824 ctx->stmt = stmt;
825
826 if (outer_ctx)
827 {
828 ctx->outer = outer_ctx;
829 ctx->cb = outer_ctx->cb;
830 ctx->cb.block = NULL;
831 ctx->depth = outer_ctx->depth + 1;
832 }
833 else
834 {
835 ctx->cb.src_fn = current_function_decl;
836 ctx->cb.dst_fn = current_function_decl;
837 ctx->cb.src_node = cgraph_node (current_function_decl);
838 ctx->cb.dst_node = ctx->cb.src_node;
839 ctx->cb.src_cfun = cfun;
840 ctx->cb.copy_decl = omp_copy_decl;
841 ctx->cb.eh_region = -1;
842 ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
843 ctx->depth = 1;
844 }
845
846 ctx->cb.decl_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
847
848 return ctx;
849}
850
851/* Destroy a omp_context data structures. Called through the splay tree
852 value delete callback. */
853
854static void
855delete_omp_context (splay_tree_value value)
856{
857 omp_context *ctx = (omp_context *) value;
858
859 splay_tree_delete (ctx->cb.decl_map);
860
861 if (ctx->field_map)
862 splay_tree_delete (ctx->field_map);
863
864 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
865 it produces corrupt debug information. */
866 if (ctx->record_type)
867 {
868 tree t;
869 for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
870 DECL_ABSTRACT_ORIGIN (t) = NULL;
871 }
872
873 XDELETE (ctx);
874}
875
876/* Fix up RECEIVER_DECL with a type that has been remapped to the child
877 context. */
878
879static void
880fixup_child_record_type (omp_context *ctx)
881{
882 tree f, type = ctx->record_type;
883
884 /* ??? It isn't sufficient to just call remap_type here, because
885 variably_modified_type_p doesn't work the way we expect for
886 record types. Testing each field for whether it needs remapping
887 and creating a new record by hand works, however. */
888 for (f = TYPE_FIELDS (type); f ; f = TREE_CHAIN (f))
889 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
890 break;
891 if (f)
892 {
893 tree name, new_fields = NULL;
894
895 type = lang_hooks.types.make_type (RECORD_TYPE);
896 name = DECL_NAME (TYPE_NAME (ctx->record_type));
897 name = build_decl (TYPE_DECL, name, type);
898 TYPE_NAME (type) = name;
899
900 for (f = TYPE_FIELDS (ctx->record_type); f ; f = TREE_CHAIN (f))
901 {
902 tree new_f = copy_node (f);
903 DECL_CONTEXT (new_f) = type;
904 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
905 TREE_CHAIN (new_f) = new_fields;
906 new_fields = new_f;
907
908 /* Arrange to be able to look up the receiver field
909 given the sender field. */
910 splay_tree_insert (ctx->field_map, (splay_tree_key) f,
911 (splay_tree_value) new_f);
912 }
913 TYPE_FIELDS (type) = nreverse (new_fields);
914 layout_type (type);
915 }
916
917 TREE_TYPE (ctx->receiver_decl) = build_pointer_type (type);
918}
919
920/* Instantiate decls as necessary in CTX to satisfy the data sharing
921 specified by CLAUSES. */
922
923static void
924scan_sharing_clauses (tree clauses, omp_context *ctx)
925{
926 tree c, decl;
927 bool scan_array_reductions = false;
928
929 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
930 {
931 bool by_ref;
932
aaf46ef9 933 switch (OMP_CLAUSE_CODE (c))
953ff289
DN
934 {
935 case OMP_CLAUSE_PRIVATE:
936 decl = OMP_CLAUSE_DECL (c);
937 if (!is_variable_sized (decl))
938 install_var_local (decl, ctx);
939 break;
940
941 case OMP_CLAUSE_SHARED:
942 gcc_assert (is_parallel_ctx (ctx));
943 decl = OMP_CLAUSE_DECL (c);
944 gcc_assert (!is_variable_sized (decl));
945 by_ref = use_pointer_for_field (decl, true);
8ca5b2a2
JJ
946 /* Global variables don't need to be copied,
947 the receiver side will use them directly. */
948 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
949 break;
953ff289
DN
950 if (! TREE_READONLY (decl)
951 || TREE_ADDRESSABLE (decl)
952 || by_ref
953 || is_reference (decl))
954 {
955 install_var_field (decl, by_ref, ctx);
956 install_var_local (decl, ctx);
957 break;
958 }
959 /* We don't need to copy const scalar vars back. */
aaf46ef9 960 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
953ff289
DN
961 goto do_private;
962
963 case OMP_CLAUSE_LASTPRIVATE:
964 /* Let the corresponding firstprivate clause create
965 the variable. */
966 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
967 break;
968 /* FALLTHRU */
969
970 case OMP_CLAUSE_FIRSTPRIVATE:
971 case OMP_CLAUSE_REDUCTION:
972 decl = OMP_CLAUSE_DECL (c);
973 do_private:
974 if (is_variable_sized (decl))
975 break;
8ca5b2a2
JJ
976 else if (is_parallel_ctx (ctx)
977 && ! is_global_var (maybe_lookup_decl_in_outer_ctx (decl,
978 ctx)))
953ff289
DN
979 {
980 by_ref = use_pointer_for_field (decl, false);
981 install_var_field (decl, by_ref, ctx);
982 }
983 install_var_local (decl, ctx);
984 break;
985
986 case OMP_CLAUSE_COPYPRIVATE:
987 if (ctx->outer)
988 scan_omp (&OMP_CLAUSE_DECL (c), ctx->outer);
989 /* FALLTHRU */
990
991 case OMP_CLAUSE_COPYIN:
992 decl = OMP_CLAUSE_DECL (c);
993 by_ref = use_pointer_for_field (decl, false);
994 install_var_field (decl, by_ref, ctx);
995 break;
996
997 case OMP_CLAUSE_DEFAULT:
998 ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
999 break;
1000
1001 case OMP_CLAUSE_IF:
1002 case OMP_CLAUSE_NUM_THREADS:
1003 case OMP_CLAUSE_SCHEDULE:
1004 if (ctx->outer)
aaf46ef9 1005 scan_omp (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
953ff289
DN
1006 break;
1007
1008 case OMP_CLAUSE_NOWAIT:
1009 case OMP_CLAUSE_ORDERED:
1010 break;
1011
1012 default:
1013 gcc_unreachable ();
1014 }
1015 }
1016
1017 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1018 {
aaf46ef9 1019 switch (OMP_CLAUSE_CODE (c))
953ff289
DN
1020 {
1021 case OMP_CLAUSE_LASTPRIVATE:
1022 /* Let the corresponding firstprivate clause create
1023 the variable. */
1024 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1025 break;
1026 /* FALLTHRU */
1027
1028 case OMP_CLAUSE_PRIVATE:
1029 case OMP_CLAUSE_FIRSTPRIVATE:
1030 case OMP_CLAUSE_REDUCTION:
1031 decl = OMP_CLAUSE_DECL (c);
1032 if (is_variable_sized (decl))
1033 install_var_local (decl, ctx);
1034 fixup_remapped_decl (decl, ctx,
aaf46ef9 1035 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
953ff289 1036 && OMP_CLAUSE_PRIVATE_DEBUG (c));
aaf46ef9 1037 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
953ff289
DN
1038 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1039 scan_array_reductions = true;
1040 break;
1041
1042 case OMP_CLAUSE_SHARED:
1043 decl = OMP_CLAUSE_DECL (c);
8ca5b2a2
JJ
1044 if (! is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1045 fixup_remapped_decl (decl, ctx, false);
953ff289
DN
1046 break;
1047
1048 case OMP_CLAUSE_COPYPRIVATE:
1049 case OMP_CLAUSE_COPYIN:
1050 case OMP_CLAUSE_DEFAULT:
1051 case OMP_CLAUSE_IF:
1052 case OMP_CLAUSE_NUM_THREADS:
1053 case OMP_CLAUSE_SCHEDULE:
1054 case OMP_CLAUSE_NOWAIT:
1055 case OMP_CLAUSE_ORDERED:
1056 break;
1057
1058 default:
1059 gcc_unreachable ();
1060 }
1061 }
1062
1063 if (scan_array_reductions)
1064 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
aaf46ef9 1065 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
953ff289
DN
1066 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1067 {
1068 scan_omp (&OMP_CLAUSE_REDUCTION_INIT (c), ctx);
1069 scan_omp (&OMP_CLAUSE_REDUCTION_MERGE (c), ctx);
1070 }
1071}
1072
1073/* Create a new name for omp child function. Returns an identifier. */
1074
1075static GTY(()) unsigned int tmp_ompfn_id_num;
1076
1077static tree
1078create_omp_child_function_name (void)
1079{
1080 tree name = DECL_ASSEMBLER_NAME (current_function_decl);
1081 size_t len = IDENTIFIER_LENGTH (name);
1082 char *tmp_name, *prefix;
1083
1084 prefix = alloca (len + sizeof ("_omp_fn"));
1085 memcpy (prefix, IDENTIFIER_POINTER (name), len);
1086 strcpy (prefix + len, "_omp_fn");
1087#ifndef NO_DOT_IN_LABEL
1088 prefix[len] = '.';
1089#elif !defined NO_DOLLAR_IN_LABEL
1090 prefix[len] = '$';
1091#endif
1092 ASM_FORMAT_PRIVATE_NAME (tmp_name, prefix, tmp_ompfn_id_num++);
1093 return get_identifier (tmp_name);
1094}
1095
1096/* Build a decl for the omp child function. It'll not contain a body
1097 yet, just the bare decl. */
1098
1099static void
1100create_omp_child_function (omp_context *ctx)
1101{
1102 tree decl, type, name, t;
1103
1104 name = create_omp_child_function_name ();
1105 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
1106
1107 decl = build_decl (FUNCTION_DECL, name, type);
1108 decl = lang_hooks.decls.pushdecl (decl);
1109
1110 ctx->cb.dst_fn = decl;
1111
1112 TREE_STATIC (decl) = 1;
1113 TREE_USED (decl) = 1;
1114 DECL_ARTIFICIAL (decl) = 1;
1115 DECL_IGNORED_P (decl) = 0;
1116 TREE_PUBLIC (decl) = 0;
1117 DECL_UNINLINABLE (decl) = 1;
1118 DECL_EXTERNAL (decl) = 0;
1119 DECL_CONTEXT (decl) = NULL_TREE;
50674e96 1120 DECL_INITIAL (decl) = make_node (BLOCK);
953ff289
DN
1121
1122 t = build_decl (RESULT_DECL, NULL_TREE, void_type_node);
1123 DECL_ARTIFICIAL (t) = 1;
1124 DECL_IGNORED_P (t) = 1;
1125 DECL_RESULT (decl) = t;
1126
1127 t = build_decl (PARM_DECL, get_identifier (".omp_data_i"), ptr_type_node);
1128 DECL_ARTIFICIAL (t) = 1;
1129 DECL_ARG_TYPE (t) = ptr_type_node;
50674e96 1130 DECL_CONTEXT (t) = current_function_decl;
953ff289
DN
1131 TREE_USED (t) = 1;
1132 DECL_ARGUMENTS (decl) = t;
1133 ctx->receiver_decl = t;
1134
1135 /* Allocate memory for the function structure. The call to
50674e96 1136 allocate_struct_function clobbers CFUN, so we need to restore
953ff289
DN
1137 it afterward. */
1138 allocate_struct_function (decl);
1139 DECL_SOURCE_LOCATION (decl) = EXPR_LOCATION (ctx->stmt);
1140 cfun->function_end_locus = EXPR_LOCATION (ctx->stmt);
1141 cfun = ctx->cb.src_cfun;
1142}
1143
953ff289
DN
1144
1145/* Scan an OpenMP parallel directive. */
1146
1147static void
1148scan_omp_parallel (tree *stmt_p, omp_context *outer_ctx)
1149{
1150 omp_context *ctx;
1151 tree name;
1152
1153 /* Ignore parallel directives with empty bodies, unless there
1154 are copyin clauses. */
1155 if (optimize > 0
1156 && empty_body_p (OMP_PARALLEL_BODY (*stmt_p))
1157 && find_omp_clause (OMP_CLAUSES (*stmt_p), OMP_CLAUSE_COPYIN) == NULL)
1158 {
1159 *stmt_p = build_empty_stmt ();
1160 return;
1161 }
1162
1163 ctx = new_omp_context (*stmt_p, outer_ctx);
50674e96
DN
1164 if (parallel_nesting_level > 1)
1165 ctx->is_nested = true;
953ff289 1166 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
953ff289
DN
1167 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
1168 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
953ff289
DN
1169 name = create_tmp_var_name (".omp_data_s");
1170 name = build_decl (TYPE_DECL, name, ctx->record_type);
1171 TYPE_NAME (ctx->record_type) = name;
1172 create_omp_child_function (ctx);
50674e96 1173 OMP_PARALLEL_FN (*stmt_p) = ctx->cb.dst_fn;
953ff289
DN
1174
1175 scan_sharing_clauses (OMP_PARALLEL_CLAUSES (*stmt_p), ctx);
1176 scan_omp (&OMP_PARALLEL_BODY (*stmt_p), ctx);
1177
1178 if (TYPE_FIELDS (ctx->record_type) == NULL)
1179 ctx->record_type = ctx->receiver_decl = NULL;
1180 else
1181 {
1182 layout_type (ctx->record_type);
1183 fixup_child_record_type (ctx);
1184 }
1185}
1186
1187
50674e96 1188/* Scan an OpenMP loop directive. */
953ff289
DN
1189
1190static void
50674e96 1191scan_omp_for (tree *stmt_p, omp_context *outer_ctx)
953ff289 1192{
50674e96
DN
1193 omp_context *ctx;
1194 tree stmt;
953ff289 1195
50674e96
DN
1196 stmt = *stmt_p;
1197 ctx = new_omp_context (stmt, outer_ctx);
953ff289 1198
50674e96 1199 scan_sharing_clauses (OMP_FOR_CLAUSES (stmt), ctx);
953ff289 1200
953ff289
DN
1201 scan_omp (&OMP_FOR_PRE_BODY (stmt), ctx);
1202 scan_omp (&OMP_FOR_INIT (stmt), ctx);
1203 scan_omp (&OMP_FOR_COND (stmt), ctx);
1204 scan_omp (&OMP_FOR_INCR (stmt), ctx);
1205 scan_omp (&OMP_FOR_BODY (stmt), ctx);
1206}
1207
1208/* Scan an OpenMP sections directive. */
1209
1210static void
1211scan_omp_sections (tree *stmt_p, omp_context *outer_ctx)
1212{
50674e96 1213 tree stmt;
953ff289
DN
1214 omp_context *ctx;
1215
50674e96 1216 stmt = *stmt_p;
953ff289
DN
1217 ctx = new_omp_context (stmt, outer_ctx);
1218 scan_sharing_clauses (OMP_SECTIONS_CLAUSES (stmt), ctx);
1219 scan_omp (&OMP_SECTIONS_BODY (stmt), ctx);
1220}
1221
1222/* Scan an OpenMP single directive. */
1223
1224static void
1225scan_omp_single (tree *stmt_p, omp_context *outer_ctx)
1226{
1227 tree stmt = *stmt_p;
1228 omp_context *ctx;
1229 tree name;
1230
1231 ctx = new_omp_context (stmt, outer_ctx);
1232 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1233 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
1234 name = create_tmp_var_name (".omp_copy_s");
1235 name = build_decl (TYPE_DECL, name, ctx->record_type);
1236 TYPE_NAME (ctx->record_type) = name;
1237
1238 scan_sharing_clauses (OMP_SINGLE_CLAUSES (stmt), ctx);
1239 scan_omp (&OMP_SINGLE_BODY (stmt), ctx);
1240
1241 if (TYPE_FIELDS (ctx->record_type) == NULL)
1242 ctx->record_type = NULL;
1243 else
1244 layout_type (ctx->record_type);
1245}
1246
953ff289
DN
1247
1248/* Callback for walk_stmts used to scan for OpenMP directives at TP. */
1249
1250static tree
1251scan_omp_1 (tree *tp, int *walk_subtrees, void *data)
1252{
1253 struct walk_stmt_info *wi = data;
1254 omp_context *ctx = wi->info;
1255 tree t = *tp;
1256
1257 if (EXPR_HAS_LOCATION (t))
1258 input_location = EXPR_LOCATION (t);
1259
1260 *walk_subtrees = 0;
1261 switch (TREE_CODE (t))
1262 {
1263 case OMP_PARALLEL:
50674e96
DN
1264 parallel_nesting_level++;
1265 scan_omp_parallel (tp, ctx);
953ff289
DN
1266 parallel_nesting_level--;
1267 break;
1268
1269 case OMP_FOR:
50674e96 1270 scan_omp_for (tp, ctx);
953ff289
DN
1271 break;
1272
1273 case OMP_SECTIONS:
50674e96 1274 scan_omp_sections (tp, ctx);
953ff289
DN
1275 break;
1276
1277 case OMP_SINGLE:
50674e96 1278 scan_omp_single (tp, ctx);
953ff289
DN
1279 break;
1280
1281 case OMP_SECTION:
1282 case OMP_MASTER:
1283 case OMP_ORDERED:
1284 case OMP_CRITICAL:
1285 ctx = new_omp_context (*tp, ctx);
1286 scan_omp (&OMP_BODY (*tp), ctx);
1287 break;
1288
1289 case BIND_EXPR:
1290 {
1291 tree var;
1292 *walk_subtrees = 1;
1293
1294 for (var = BIND_EXPR_VARS (t); var ; var = TREE_CHAIN (var))
50674e96 1295 insert_decl_map (&ctx->cb, var, var);
953ff289
DN
1296 }
1297 break;
1298
1299 case VAR_DECL:
1300 case PARM_DECL:
1301 case LABEL_DECL:
077b0dfb 1302 case RESULT_DECL:
953ff289
DN
1303 if (ctx)
1304 *tp = remap_decl (t, &ctx->cb);
1305 break;
1306
1307 default:
1308 if (ctx && TYPE_P (t))
1309 *tp = remap_type (t, &ctx->cb);
1310 else if (!DECL_P (t))
1311 *walk_subtrees = 1;
1312 break;
1313 }
1314
1315 return NULL_TREE;
1316}
1317
1318
1319/* Scan all the statements starting at STMT_P. CTX contains context
1320 information about the OpenMP directives and clauses found during
1321 the scan. */
1322
1323static void
1324scan_omp (tree *stmt_p, omp_context *ctx)
1325{
1326 location_t saved_location;
1327 struct walk_stmt_info wi;
1328
1329 memset (&wi, 0, sizeof (wi));
1330 wi.callback = scan_omp_1;
1331 wi.info = ctx;
1332 wi.want_bind_expr = (ctx != NULL);
1333 wi.want_locations = true;
1334
1335 saved_location = input_location;
1336 walk_stmts (&wi, stmt_p);
1337 input_location = saved_location;
1338}
1339\f
1340/* Re-gimplification and code generation routines. */
1341
1342/* Build a call to GOMP_barrier. */
1343
1344static void
1345build_omp_barrier (tree *stmt_list)
1346{
1347 tree t;
1348
1349 t = built_in_decls[BUILT_IN_GOMP_BARRIER];
1350 t = build_function_call_expr (t, NULL);
1351 gimplify_and_add (t, stmt_list);
1352}
1353
1354/* If a context was created for STMT when it was scanned, return it. */
1355
1356static omp_context *
1357maybe_lookup_ctx (tree stmt)
1358{
1359 splay_tree_node n;
1360 n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
1361 return n ? (omp_context *) n->value : NULL;
1362}
1363
50674e96
DN
1364
1365/* Find the mapping for DECL in CTX or the immediately enclosing
1366 context that has a mapping for DECL.
1367
1368 If CTX is a nested parallel directive, we may have to use the decl
1369 mappings created in CTX's parent context. Suppose that we have the
1370 following parallel nesting (variable UIDs showed for clarity):
1371
1372 iD.1562 = 0;
1373 #omp parallel shared(iD.1562) -> outer parallel
1374 iD.1562 = iD.1562 + 1;
1375
1376 #omp parallel shared (iD.1562) -> inner parallel
1377 iD.1562 = iD.1562 - 1;
1378
1379 Each parallel structure will create a distinct .omp_data_s structure
1380 for copying iD.1562 in/out of the directive:
1381
1382 outer parallel .omp_data_s.1.i -> iD.1562
1383 inner parallel .omp_data_s.2.i -> iD.1562
1384
1385 A shared variable mapping will produce a copy-out operation before
1386 the parallel directive and a copy-in operation after it. So, in
1387 this case we would have:
1388
1389 iD.1562 = 0;
1390 .omp_data_o.1.i = iD.1562;
1391 #omp parallel shared(iD.1562) -> outer parallel
1392 .omp_data_i.1 = &.omp_data_o.1
1393 .omp_data_i.1->i = .omp_data_i.1->i + 1;
1394
1395 .omp_data_o.2.i = iD.1562; -> **
1396 #omp parallel shared(iD.1562) -> inner parallel
1397 .omp_data_i.2 = &.omp_data_o.2
1398 .omp_data_i.2->i = .omp_data_i.2->i - 1;
1399
1400
1401 ** This is a problem. The symbol iD.1562 cannot be referenced
1402 inside the body of the outer parallel region. But since we are
1403 emitting this copy operation while expanding the inner parallel
1404 directive, we need to access the CTX structure of the outer
1405 parallel directive to get the correct mapping:
1406
1407 .omp_data_o.2.i = .omp_data_i.1->i
1408
1409 Since there may be other workshare or parallel directives enclosing
1410 the parallel directive, it may be necessary to walk up the context
1411 parent chain. This is not a problem in general because nested
1412 parallelism happens only rarely. */
1413
1414static tree
1415lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
1416{
1417 tree t;
1418 omp_context *up;
1419
1420 gcc_assert (ctx->is_nested);
1421
1422 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
1423 t = maybe_lookup_decl (decl, up);
1424
1425 gcc_assert (t);
1426
1427 return t;
1428}
1429
1430
8ca5b2a2
JJ
1431/* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
1432 in outer contexts. */
1433
1434static tree
1435maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
1436{
1437 tree t = NULL;
1438 omp_context *up;
1439
1440 if (ctx->is_nested)
1441 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
1442 t = maybe_lookup_decl (decl, up);
1443
1444 return t ? t : decl;
1445}
1446
1447
953ff289
DN
1448/* Construct the initialization value for reduction CLAUSE. */
1449
1450tree
1451omp_reduction_init (tree clause, tree type)
1452{
1453 switch (OMP_CLAUSE_REDUCTION_CODE (clause))
1454 {
1455 case PLUS_EXPR:
1456 case MINUS_EXPR:
1457 case BIT_IOR_EXPR:
1458 case BIT_XOR_EXPR:
1459 case TRUTH_OR_EXPR:
1460 case TRUTH_ORIF_EXPR:
1461 case TRUTH_XOR_EXPR:
1462 case NE_EXPR:
1463 return fold_convert (type, integer_zero_node);
1464
1465 case MULT_EXPR:
1466 case TRUTH_AND_EXPR:
1467 case TRUTH_ANDIF_EXPR:
1468 case EQ_EXPR:
1469 return fold_convert (type, integer_one_node);
1470
1471 case BIT_AND_EXPR:
1472 return fold_convert (type, integer_minus_one_node);
1473
1474 case MAX_EXPR:
1475 if (SCALAR_FLOAT_TYPE_P (type))
1476 {
1477 REAL_VALUE_TYPE max, min;
1478 if (HONOR_INFINITIES (TYPE_MODE (type)))
1479 {
1480 real_inf (&max);
1481 real_arithmetic (&min, NEGATE_EXPR, &max, NULL);
1482 }
1483 else
1484 real_maxval (&min, 1, TYPE_MODE (type));
1485 return build_real (type, min);
1486 }
1487 else
1488 {
1489 gcc_assert (INTEGRAL_TYPE_P (type));
1490 return TYPE_MIN_VALUE (type);
1491 }
1492
1493 case MIN_EXPR:
1494 if (SCALAR_FLOAT_TYPE_P (type))
1495 {
1496 REAL_VALUE_TYPE max;
1497 if (HONOR_INFINITIES (TYPE_MODE (type)))
1498 real_inf (&max);
1499 else
1500 real_maxval (&max, 0, TYPE_MODE (type));
1501 return build_real (type, max);
1502 }
1503 else
1504 {
1505 gcc_assert (INTEGRAL_TYPE_P (type));
1506 return TYPE_MAX_VALUE (type);
1507 }
1508
1509 default:
1510 gcc_unreachable ();
1511 }
1512}
1513
1514/* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
1515 from the receiver (aka child) side and initializers for REFERENCE_TYPE
1516 private variables. Initialization statements go in ILIST, while calls
1517 to destructors go in DLIST. */
1518
1519static void
50674e96 1520lower_rec_input_clauses (tree clauses, tree *ilist, tree *dlist,
953ff289
DN
1521 omp_context *ctx)
1522{
1523 tree_stmt_iterator diter;
1524 tree c, dtor, copyin_seq, x, args, ptr;
1525 bool copyin_by_ref = false;
8ca5b2a2 1526 bool lastprivate_firstprivate = false;
953ff289
DN
1527 int pass;
1528
1529 *dlist = alloc_stmt_list ();
1530 diter = tsi_start (*dlist);
1531 copyin_seq = NULL;
1532
1533 /* Do all the fixed sized types in the first pass, and the variable sized
1534 types in the second pass. This makes sure that the scalar arguments to
1535 the variable sized types are processed before we use them in the
1536 variable sized operations. */
1537 for (pass = 0; pass < 2; ++pass)
1538 {
1539 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
1540 {
aaf46ef9 1541 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
953ff289
DN
1542 tree var, new_var;
1543 bool by_ref;
1544
1545 switch (c_kind)
1546 {
1547 case OMP_CLAUSE_PRIVATE:
1548 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
1549 continue;
1550 break;
1551 case OMP_CLAUSE_SHARED:
8ca5b2a2
JJ
1552 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
1553 {
1554 gcc_assert (is_global_var (OMP_CLAUSE_DECL (c)));
1555 continue;
1556 }
953ff289 1557 case OMP_CLAUSE_FIRSTPRIVATE:
953ff289
DN
1558 case OMP_CLAUSE_COPYIN:
1559 case OMP_CLAUSE_REDUCTION:
1560 break;
077b0dfb 1561 case OMP_CLAUSE_LASTPRIVATE:
8ca5b2a2
JJ
1562 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1563 {
1564 lastprivate_firstprivate = true;
1565 if (pass != 0)
1566 continue;
1567 }
077b0dfb 1568 break;
953ff289
DN
1569 default:
1570 continue;
1571 }
1572
1573 new_var = var = OMP_CLAUSE_DECL (c);
1574 if (c_kind != OMP_CLAUSE_COPYIN)
1575 new_var = lookup_decl (var, ctx);
1576
1577 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
1578 {
1579 if (pass != 0)
1580 continue;
1581 }
953ff289
DN
1582 else if (is_variable_sized (var))
1583 {
50674e96
DN
1584 /* For variable sized types, we need to allocate the
1585 actual storage here. Call alloca and store the
1586 result in the pointer decl that we created elsewhere. */
953ff289
DN
1587 if (pass == 0)
1588 continue;
1589
1590 ptr = DECL_VALUE_EXPR (new_var);
1591 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
1592 ptr = TREE_OPERAND (ptr, 0);
1593 gcc_assert (DECL_P (ptr));
1594
1595 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
1596 args = tree_cons (NULL, x, NULL);
1597 x = built_in_decls[BUILT_IN_ALLOCA];
1598 x = build_function_call_expr (x, args);
1599 x = fold_convert (TREE_TYPE (ptr), x);
1600 x = build2 (MODIFY_EXPR, void_type_node, ptr, x);
1601 gimplify_and_add (x, ilist);
1602 }
953ff289
DN
1603 else if (is_reference (var))
1604 {
50674e96
DN
1605 /* For references that are being privatized for Fortran,
1606 allocate new backing storage for the new pointer
1607 variable. This allows us to avoid changing all the
1608 code that expects a pointer to something that expects
1609 a direct variable. Note that this doesn't apply to
1610 C++, since reference types are disallowed in data
077b0dfb
JJ
1611 sharing clauses there, except for NRV optimized
1612 return values. */
953ff289
DN
1613 if (pass == 0)
1614 continue;
1615
1616 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
1617 if (TREE_CONSTANT (x))
1618 {
1619 const char *name = NULL;
1620 if (DECL_NAME (var))
1621 name = IDENTIFIER_POINTER (DECL_NAME (new_var));
1622
077b0dfb
JJ
1623 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
1624 name);
1625 gimple_add_tmp_var (x);
953ff289
DN
1626 x = build_fold_addr_expr_with_type (x, TREE_TYPE (new_var));
1627 }
1628 else
1629 {
1630 args = tree_cons (NULL, x, NULL);
1631 x = built_in_decls[BUILT_IN_ALLOCA];
1632 x = build_function_call_expr (x, args);
1633 x = fold_convert (TREE_TYPE (new_var), x);
1634 }
1635
1636 x = build2 (MODIFY_EXPR, void_type_node, new_var, x);
1637 gimplify_and_add (x, ilist);
1638
1639 new_var = build_fold_indirect_ref (new_var);
1640 }
1641 else if (c_kind == OMP_CLAUSE_REDUCTION
1642 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1643 {
1644 if (pass == 0)
1645 continue;
1646 }
1647 else if (pass != 0)
1648 continue;
1649
aaf46ef9 1650 switch (OMP_CLAUSE_CODE (c))
953ff289
DN
1651 {
1652 case OMP_CLAUSE_SHARED:
8ca5b2a2
JJ
1653 /* Shared global vars are just accessed directly. */
1654 if (is_global_var (new_var))
1655 break;
953ff289
DN
1656 /* Set up the DECL_VALUE_EXPR for shared variables now. This
1657 needs to be delayed until after fixup_child_record_type so
1658 that we get the correct type during the dereference. */
1659 by_ref = use_pointer_for_field (var, true);
1660 x = build_receiver_ref (var, by_ref, ctx);
1661 SET_DECL_VALUE_EXPR (new_var, x);
1662 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
1663
1664 /* ??? If VAR is not passed by reference, and the variable
1665 hasn't been initialized yet, then we'll get a warning for
1666 the store into the omp_data_s structure. Ideally, we'd be
1667 able to notice this and not store anything at all, but
1668 we're generating code too early. Suppress the warning. */
1669 if (!by_ref)
1670 TREE_NO_WARNING (var) = 1;
1671 break;
1672
1673 case OMP_CLAUSE_LASTPRIVATE:
1674 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1675 break;
1676 /* FALLTHRU */
1677
1678 case OMP_CLAUSE_PRIVATE:
1679 x = lang_hooks.decls.omp_clause_default_ctor (c, new_var);
1680 if (x)
1681 gimplify_and_add (x, ilist);
1682 /* FALLTHRU */
1683
1684 do_dtor:
1685 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
1686 if (x)
1687 {
1688 dtor = x;
1689 gimplify_stmt (&dtor);
1690 tsi_link_before (&diter, dtor, TSI_SAME_STMT);
1691 }
1692 break;
1693
1694 case OMP_CLAUSE_FIRSTPRIVATE:
1695 x = build_outer_var_ref (var, ctx);
1696 x = lang_hooks.decls.omp_clause_copy_ctor (c, new_var, x);
1697 gimplify_and_add (x, ilist);
1698 goto do_dtor;
1699 break;
1700
1701 case OMP_CLAUSE_COPYIN:
1702 by_ref = use_pointer_for_field (var, false);
1703 x = build_receiver_ref (var, by_ref, ctx);
1704 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
1705 append_to_statement_list (x, &copyin_seq);
1706 copyin_by_ref |= by_ref;
1707 break;
1708
1709 case OMP_CLAUSE_REDUCTION:
1710 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1711 {
1712 gimplify_and_add (OMP_CLAUSE_REDUCTION_INIT (c), ilist);
1713 OMP_CLAUSE_REDUCTION_INIT (c) = NULL;
1714 }
1715 else
1716 {
1717 x = omp_reduction_init (c, TREE_TYPE (new_var));
1718 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
1719 x = build2 (MODIFY_EXPR, void_type_node, new_var, x);
1720 gimplify_and_add (x, ilist);
1721 }
1722 break;
1723
1724 default:
1725 gcc_unreachable ();
1726 }
1727 }
1728 }
1729
1730 /* The copyin sequence is not to be executed by the main thread, since
1731 that would result in self-copies. Perhaps not visible to scalars,
1732 but it certainly is to C++ operator=. */
1733 if (copyin_seq)
1734 {
1735 x = built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM];
1736 x = build_function_call_expr (x, NULL);
1737 x = build2 (NE_EXPR, boolean_type_node, x,
1738 build_int_cst (TREE_TYPE (x), 0));
1739 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
1740 gimplify_and_add (x, ilist);
1741 }
1742
1743 /* If any copyin variable is passed by reference, we must ensure the
1744 master thread doesn't modify it before it is copied over in all
8ca5b2a2
JJ
1745 threads. Similarly for variables in both firstprivate and
1746 lastprivate clauses we need to ensure the lastprivate copying
1747 happens after firstprivate copying in all threads. */
1748 if (copyin_by_ref || lastprivate_firstprivate)
953ff289
DN
1749 build_omp_barrier (ilist);
1750}
1751
50674e96 1752
953ff289
DN
1753/* Generate code to implement the LASTPRIVATE clauses. This is used for
1754 both parallel and workshare constructs. PREDICATE may be NULL if it's
1755 always true. */
1756
1757static void
50674e96 1758lower_lastprivate_clauses (tree clauses, tree predicate, tree *stmt_list,
953ff289
DN
1759 omp_context *ctx)
1760{
1761 tree sub_list, x, c;
1762
1763 /* Early exit if there are no lastprivate clauses. */
1764 clauses = find_omp_clause (clauses, OMP_CLAUSE_LASTPRIVATE);
1765 if (clauses == NULL)
1766 {
1767 /* If this was a workshare clause, see if it had been combined
1768 with its parallel. In that case, look for the clauses on the
1769 parallel statement itself. */
1770 if (is_parallel_ctx (ctx))
1771 return;
1772
1773 ctx = ctx->outer;
1774 if (ctx == NULL || !is_parallel_ctx (ctx))
1775 return;
1776
1777 clauses = find_omp_clause (OMP_PARALLEL_CLAUSES (ctx->stmt),
1778 OMP_CLAUSE_LASTPRIVATE);
1779 if (clauses == NULL)
1780 return;
1781 }
1782
1783 sub_list = alloc_stmt_list ();
1784
1785 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
1786 {
1787 tree var, new_var;
1788
aaf46ef9 1789 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LASTPRIVATE)
953ff289
DN
1790 continue;
1791
1792 var = OMP_CLAUSE_DECL (c);
1793 new_var = lookup_decl (var, ctx);
1794
1795 x = build_outer_var_ref (var, ctx);
1796 if (is_reference (var))
1797 new_var = build_fold_indirect_ref (new_var);
1798 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
1799 append_to_statement_list (x, &sub_list);
1800 }
1801
1802 if (predicate)
1803 x = build3 (COND_EXPR, void_type_node, predicate, sub_list, NULL);
1804 else
1805 x = sub_list;
50674e96 1806
953ff289
DN
1807 gimplify_and_add (x, stmt_list);
1808}
1809
50674e96 1810
953ff289
DN
1811/* Generate code to implement the REDUCTION clauses. */
1812
1813static void
50674e96 1814lower_reduction_clauses (tree clauses, tree *stmt_list, omp_context *ctx)
953ff289
DN
1815{
1816 tree sub_list = NULL, x, c;
1817 int count = 0;
1818
1819 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
1820 update in that case, otherwise use a lock. */
1821 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
aaf46ef9 1822 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
953ff289
DN
1823 {
1824 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1825 {
1826 /* Never use OMP_ATOMIC for array reductions. */
1827 count = -1;
1828 break;
1829 }
1830 count++;
1831 }
1832
1833 if (count == 0)
1834 return;
1835
1836 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
1837 {
1838 tree var, ref, new_var;
1839 enum tree_code code;
1840
aaf46ef9 1841 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
953ff289
DN
1842 continue;
1843
1844 var = OMP_CLAUSE_DECL (c);
1845 new_var = lookup_decl (var, ctx);
1846 if (is_reference (var))
1847 new_var = build_fold_indirect_ref (new_var);
1848 ref = build_outer_var_ref (var, ctx);
1849 code = OMP_CLAUSE_REDUCTION_CODE (c);
50674e96
DN
1850
1851 /* reduction(-:var) sums up the partial results, so it acts
1852 identically to reduction(+:var). */
953ff289
DN
1853 if (code == MINUS_EXPR)
1854 code = PLUS_EXPR;
1855
1856 if (count == 1)
1857 {
1858 tree addr = build_fold_addr_expr (ref);
1859
1860 addr = save_expr (addr);
1861 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
1862 x = fold_build2 (code, TREE_TYPE (ref), ref, new_var);
1863 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
1864 gimplify_and_add (x, stmt_list);
1865 return;
1866 }
1867
1868 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1869 {
1870 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
1871
1872 if (is_reference (var))
1873 ref = build_fold_addr_expr (ref);
1874 SET_DECL_VALUE_EXPR (placeholder, ref);
1875 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
1876 gimplify_and_add (OMP_CLAUSE_REDUCTION_MERGE (c), &sub_list);
1877 OMP_CLAUSE_REDUCTION_MERGE (c) = NULL;
1878 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
1879 }
1880 else
1881 {
1882 x = build2 (code, TREE_TYPE (ref), ref, new_var);
1883 ref = build_outer_var_ref (var, ctx);
1884 x = build2 (MODIFY_EXPR, void_type_node, ref, x);
1885 append_to_statement_list (x, &sub_list);
1886 }
1887 }
1888
1889 x = built_in_decls[BUILT_IN_GOMP_ATOMIC_START];
1890 x = build_function_call_expr (x, NULL);
1891 gimplify_and_add (x, stmt_list);
1892
1893 gimplify_and_add (sub_list, stmt_list);
1894
1895 x = built_in_decls[BUILT_IN_GOMP_ATOMIC_END];
1896 x = build_function_call_expr (x, NULL);
1897 gimplify_and_add (x, stmt_list);
1898}
1899
50674e96 1900
953ff289
DN
1901/* Generate code to implement the COPYPRIVATE clauses. */
1902
1903static void
50674e96 1904lower_copyprivate_clauses (tree clauses, tree *slist, tree *rlist,
953ff289
DN
1905 omp_context *ctx)
1906{
1907 tree c;
1908
1909 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
1910 {
1911 tree var, ref, x;
1912 bool by_ref;
1913
aaf46ef9 1914 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
953ff289
DN
1915 continue;
1916
1917 var = OMP_CLAUSE_DECL (c);
1918 by_ref = use_pointer_for_field (var, false);
1919
1920 ref = build_sender_ref (var, ctx);
50674e96
DN
1921 x = (ctx->is_nested) ? lookup_decl_in_outer_ctx (var, ctx) : var;
1922 x = by_ref ? build_fold_addr_expr (x) : x;
953ff289
DN
1923 x = build2 (MODIFY_EXPR, void_type_node, ref, x);
1924 gimplify_and_add (x, slist);
1925
1926 ref = build_receiver_ref (var, by_ref, ctx);
1927 if (is_reference (var))
1928 {
1929 ref = build_fold_indirect_ref (ref);
1930 var = build_fold_indirect_ref (var);
1931 }
1932 x = lang_hooks.decls.omp_clause_assign_op (c, var, ref);
1933 gimplify_and_add (x, rlist);
1934 }
1935}
1936
50674e96 1937
953ff289
DN
1938/* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
1939 and REDUCTION from the sender (aka parent) side. */
1940
1941static void
50674e96 1942lower_send_clauses (tree clauses, tree *ilist, tree *olist, omp_context *ctx)
953ff289
DN
1943{
1944 tree c;
1945
1946 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
1947 {
50674e96 1948 tree val, ref, x, var;
953ff289
DN
1949 bool by_ref, do_in = false, do_out = false;
1950
aaf46ef9 1951 switch (OMP_CLAUSE_CODE (c))
953ff289
DN
1952 {
1953 case OMP_CLAUSE_FIRSTPRIVATE:
1954 case OMP_CLAUSE_COPYIN:
1955 case OMP_CLAUSE_LASTPRIVATE:
1956 case OMP_CLAUSE_REDUCTION:
1957 break;
1958 default:
1959 continue;
1960 }
1961
50674e96
DN
1962 var = val = OMP_CLAUSE_DECL (c);
1963 if (ctx->is_nested)
1964 var = lookup_decl_in_outer_ctx (val, ctx);
1965
8ca5b2a2
JJ
1966 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
1967 && is_global_var (var))
1968 continue;
953ff289
DN
1969 if (is_variable_sized (val))
1970 continue;
1971 by_ref = use_pointer_for_field (val, false);
1972
aaf46ef9 1973 switch (OMP_CLAUSE_CODE (c))
953ff289
DN
1974 {
1975 case OMP_CLAUSE_FIRSTPRIVATE:
1976 case OMP_CLAUSE_COPYIN:
1977 do_in = true;
1978 break;
1979
1980 case OMP_CLAUSE_LASTPRIVATE:
1981 if (by_ref || is_reference (val))
1982 {
1983 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1984 continue;
1985 do_in = true;
1986 }
1987 else
1988 do_out = true;
1989 break;
1990
1991 case OMP_CLAUSE_REDUCTION:
1992 do_in = true;
1993 do_out = !(by_ref || is_reference (val));
1994 break;
1995
1996 default:
1997 gcc_unreachable ();
1998 }
1999
2000 if (do_in)
2001 {
2002 ref = build_sender_ref (val, ctx);
50674e96 2003 x = by_ref ? build_fold_addr_expr (var) : var;
953ff289
DN
2004 x = build2 (MODIFY_EXPR, void_type_node, ref, x);
2005 gimplify_and_add (x, ilist);
2006 }
50674e96 2007
953ff289
DN
2008 if (do_out)
2009 {
2010 ref = build_sender_ref (val, ctx);
50674e96 2011 x = build2 (MODIFY_EXPR, void_type_node, var, ref);
953ff289
DN
2012 gimplify_and_add (x, olist);
2013 }
2014 }
2015}
2016
2017/* Generate code to implement SHARED from the sender (aka parent) side.
2018 This is trickier, since OMP_PARALLEL_CLAUSES doesn't list things that
2019 got automatically shared. */
2020
2021static void
50674e96 2022lower_send_shared_vars (tree *ilist, tree *olist, omp_context *ctx)
953ff289 2023{
50674e96 2024 tree var, ovar, nvar, f, x;
953ff289
DN
2025
2026 if (ctx->record_type == NULL)
2027 return;
50674e96 2028
953ff289
DN
2029 for (f = TYPE_FIELDS (ctx->record_type); f ; f = TREE_CHAIN (f))
2030 {
2031 ovar = DECL_ABSTRACT_ORIGIN (f);
2032 nvar = maybe_lookup_decl (ovar, ctx);
2033 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
2034 continue;
2035
50674e96
DN
2036 var = ovar;
2037
2038 /* If CTX is a nested parallel directive. Find the immediately
2039 enclosing parallel or workshare construct that contains a
2040 mapping for OVAR. */
2041 if (ctx->is_nested)
2042 var = lookup_decl_in_outer_ctx (ovar, ctx);
2043
953ff289
DN
2044 if (use_pointer_for_field (ovar, true))
2045 {
2046 x = build_sender_ref (ovar, ctx);
50674e96
DN
2047 var = build_fold_addr_expr (var);
2048 x = build2 (MODIFY_EXPR, void_type_node, x, var);
953ff289
DN
2049 gimplify_and_add (x, ilist);
2050 }
2051 else
2052 {
2053 x = build_sender_ref (ovar, ctx);
50674e96 2054 x = build2 (MODIFY_EXPR, void_type_node, x, var);
953ff289
DN
2055 gimplify_and_add (x, ilist);
2056
2057 x = build_sender_ref (ovar, ctx);
50674e96 2058 x = build2 (MODIFY_EXPR, void_type_node, var, x);
953ff289
DN
2059 gimplify_and_add (x, olist);
2060 }
2061 }
2062}
2063
2064/* Build the function calls to GOMP_parallel_start etc to actually
50674e96
DN
2065 generate the parallel operation. REGION is the parallel region
2066 being expanded. BB is the block where to insert the code. WS_ARGS
2067 will be set if this is a call to a combined parallel+workshare
2068 construct, it contains the list of additional arguments needed by
2069 the workshare construct. */
953ff289
DN
2070
2071static void
777f7f9a
RH
2072expand_parallel_call (struct omp_region *region, basic_block bb,
2073 tree entry_stmt, tree ws_args)
953ff289 2074{
50674e96
DN
2075 tree t, args, val, cond, c, list, clauses;
2076 block_stmt_iterator si;
2077 int start_ix;
2078
777f7f9a 2079 clauses = OMP_PARALLEL_CLAUSES (entry_stmt);
50674e96
DN
2080 push_gimplify_context ();
2081
c0220ea4 2082 /* Determine what flavor of GOMP_parallel_start we will be
50674e96
DN
2083 emitting. */
2084 start_ix = BUILT_IN_GOMP_PARALLEL_START;
2085 if (is_combined_parallel (region))
2086 {
777f7f9a 2087 switch (region->inner->type)
50674e96 2088 {
777f7f9a 2089 case OMP_FOR:
21a66e91
JJ
2090 start_ix = BUILT_IN_GOMP_PARALLEL_LOOP_STATIC_START
2091 + region->inner->sched_kind;
777f7f9a
RH
2092 break;
2093 case OMP_SECTIONS:
2094 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS_START;
2095 break;
2096 default:
2097 gcc_unreachable ();
50674e96 2098 }
50674e96 2099 }
953ff289
DN
2100
2101 /* By default, the value of NUM_THREADS is zero (selected at run time)
2102 and there is no conditional. */
2103 cond = NULL_TREE;
2104 val = build_int_cst (unsigned_type_node, 0);
2105
2106 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
2107 if (c)
2108 cond = OMP_CLAUSE_IF_EXPR (c);
2109
2110 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
2111 if (c)
2112 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
2113
2114 /* Ensure 'val' is of the correct type. */
2115 val = fold_convert (unsigned_type_node, val);
2116
2117 /* If we found the clause 'if (cond)', build either
2118 (cond != 0) or (cond ? val : 1u). */
2119 if (cond)
2120 {
50674e96
DN
2121 block_stmt_iterator si;
2122
2123 cond = gimple_boolify (cond);
2124
953ff289
DN
2125 if (integer_zerop (val))
2126 val = build2 (EQ_EXPR, unsigned_type_node, cond,
2127 build_int_cst (TREE_TYPE (cond), 0));
2128 else
50674e96
DN
2129 {
2130 basic_block cond_bb, then_bb, else_bb;
2131 edge e;
2132 tree t, then_lab, else_lab, tmp;
2133
2134 tmp = create_tmp_var (TREE_TYPE (val), NULL);
2135 e = split_block (bb, NULL);
2136 cond_bb = e->src;
2137 bb = e->dest;
2138 remove_edge (e);
2139
2140 then_bb = create_empty_bb (cond_bb);
2141 else_bb = create_empty_bb (then_bb);
2142 then_lab = create_artificial_label ();
2143 else_lab = create_artificial_label ();
2144
2145 t = build3 (COND_EXPR, void_type_node,
2146 cond,
2147 build_and_jump (&then_lab),
2148 build_and_jump (&else_lab));
2149
2150 si = bsi_start (cond_bb);
2151 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
2152
2153 si = bsi_start (then_bb);
2154 t = build1 (LABEL_EXPR, void_type_node, then_lab);
2155 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
2156 t = build2 (MODIFY_EXPR, void_type_node, tmp, val);
2157 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
2158
2159 si = bsi_start (else_bb);
2160 t = build1 (LABEL_EXPR, void_type_node, else_lab);
2161 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
2162 t = build2 (MODIFY_EXPR, void_type_node, tmp,
2163 build_int_cst (unsigned_type_node, 1));
2164 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
2165
2166 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
2167 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
2168 make_edge (then_bb, bb, EDGE_FALLTHRU);
2169 make_edge (else_bb, bb, EDGE_FALLTHRU);
2170
2171 val = tmp;
2172 }
2173
2174 list = NULL_TREE;
2175 val = get_formal_tmp_var (val, &list);
2176 si = bsi_start (bb);
2177 bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
953ff289
DN
2178 }
2179
50674e96 2180 list = NULL_TREE;
953ff289 2181 args = tree_cons (NULL, val, NULL);
777f7f9a 2182 t = OMP_PARALLEL_DATA_ARG (entry_stmt);
953ff289
DN
2183 if (t == NULL)
2184 t = null_pointer_node;
2185 else
2186 t = build_fold_addr_expr (t);
2187 args = tree_cons (NULL, t, args);
777f7f9a 2188 t = build_fold_addr_expr (OMP_PARALLEL_FN (entry_stmt));
953ff289 2189 args = tree_cons (NULL, t, args);
50674e96
DN
2190
2191 if (ws_args)
2192 args = chainon (args, ws_args);
2193
2194 t = built_in_decls[start_ix];
953ff289 2195 t = build_function_call_expr (t, args);
50674e96 2196 gimplify_and_add (t, &list);
953ff289 2197
777f7f9a 2198 t = OMP_PARALLEL_DATA_ARG (entry_stmt);
953ff289
DN
2199 if (t == NULL)
2200 t = null_pointer_node;
2201 else
2202 t = build_fold_addr_expr (t);
2203 args = tree_cons (NULL, t, NULL);
777f7f9a 2204 t = build_function_call_expr (OMP_PARALLEL_FN (entry_stmt), args);
50674e96 2205 gimplify_and_add (t, &list);
953ff289
DN
2206
2207 t = built_in_decls[BUILT_IN_GOMP_PARALLEL_END];
2208 t = build_function_call_expr (t, NULL);
50674e96
DN
2209 gimplify_and_add (t, &list);
2210
2211 si = bsi_last (bb);
2212 bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
2213
2214 pop_gimplify_context (NULL_TREE);
953ff289
DN
2215}
2216
50674e96 2217
953ff289
DN
2218/* If exceptions are enabled, wrap *STMT_P in a MUST_NOT_THROW catch
2219 handler. This prevents programs from violating the structured
2220 block semantics with throws. */
2221
2222static void
2223maybe_catch_exception (tree *stmt_p)
2224{
2225 tree f, t;
2226
2227 if (!flag_exceptions)
2228 return;
2229
2230 if (lang_protect_cleanup_actions)
2231 t = lang_protect_cleanup_actions ();
2232 else
2233 {
2234 t = built_in_decls[BUILT_IN_TRAP];
2235 t = build_function_call_expr (t, NULL);
2236 }
2237 f = build2 (EH_FILTER_EXPR, void_type_node, NULL, NULL);
2238 EH_FILTER_MUST_NOT_THROW (f) = 1;
2239 gimplify_and_add (t, &EH_FILTER_FAILURE (f));
2240
2241 t = build2 (TRY_CATCH_EXPR, void_type_node, *stmt_p, NULL);
2242 append_to_statement_list (f, &TREE_OPERAND (t, 1));
2243
2244 *stmt_p = NULL;
2245 append_to_statement_list (t, stmt_p);
2246}
2247
50674e96 2248/* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
953ff289 2249
50674e96
DN
2250static tree
2251list2chain (tree list)
953ff289 2252{
50674e96 2253 tree t;
953ff289 2254
50674e96
DN
2255 for (t = list; t; t = TREE_CHAIN (t))
2256 {
2257 tree var = TREE_VALUE (t);
2258 if (TREE_CHAIN (t))
2259 TREE_CHAIN (var) = TREE_VALUE (TREE_CHAIN (t));
2260 else
2261 TREE_CHAIN (var) = NULL_TREE;
2262 }
953ff289 2263
50674e96
DN
2264 return list ? TREE_VALUE (list) : NULL_TREE;
2265}
953ff289 2266
953ff289 2267
50674e96
DN
2268/* Remove barriers in REGION->EXIT's block. Note that this is only
2269 valid for OMP_PARALLEL regions. Since the end of a parallel region
2270 is an implicit barrier, any workshare inside the OMP_PARALLEL that
2271 left a barrier at the end of the OMP_PARALLEL region can now be
2272 removed. */
953ff289 2273
50674e96
DN
2274static void
2275remove_exit_barrier (struct omp_region *region)
2276{
2277 block_stmt_iterator si;
2278 basic_block exit_bb;
777f7f9a
RH
2279 edge_iterator ei;
2280 edge e;
50674e96 2281 tree t;
953ff289 2282
777f7f9a 2283 exit_bb = region->exit;
953ff289 2284
2aee3e57
JJ
2285 /* If the parallel region doesn't return, we don't have REGION->EXIT
2286 block at all. */
2287 if (! exit_bb)
2288 return;
2289
777f7f9a 2290 /* The last insn in the block will be the parallel's OMP_RETURN. The
75c40d56 2291 workshare's OMP_RETURN will be in a preceding block. The kinds of
777f7f9a
RH
2292 statements that can appear in between are extremely limited -- no
2293 memory operations at all. Here, we allow nothing at all, so the
75c40d56 2294 only thing we allow to precede this OMP_RETURN is a label. */
50674e96 2295 si = bsi_last (exit_bb);
777f7f9a 2296 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_RETURN);
50674e96 2297 bsi_prev (&si);
777f7f9a 2298 if (!bsi_end_p (si) && TREE_CODE (bsi_stmt (si)) != LABEL_EXPR)
50674e96 2299 return;
953ff289 2300
777f7f9a
RH
2301 FOR_EACH_EDGE (e, ei, exit_bb->preds)
2302 {
2303 si = bsi_last (e->src);
2304 if (bsi_end_p (si))
2305 continue;
2306 t = bsi_stmt (si);
2307 if (TREE_CODE (t) == OMP_RETURN)
2308 OMP_RETURN_NOWAIT (t) = 1;
2309 }
953ff289
DN
2310}
2311
777f7f9a
RH
2312static void
2313remove_exit_barriers (struct omp_region *region)
2314{
2315 if (region->type == OMP_PARALLEL)
2316 remove_exit_barrier (region);
2317
2318 if (region->inner)
2319 {
2320 region = region->inner;
2321 remove_exit_barriers (region);
2322 while (region->next)
2323 {
2324 region = region->next;
2325 remove_exit_barriers (region);
2326 }
2327 }
2328}
50674e96
DN
2329
2330/* Expand the OpenMP parallel directive starting at REGION. */
953ff289
DN
2331
2332static void
50674e96 2333expand_omp_parallel (struct omp_region *region)
953ff289 2334{
50674e96
DN
2335 basic_block entry_bb, exit_bb, new_bb;
2336 struct function *child_cfun, *saved_cfun;
2337 tree child_fn, block, t, ws_args;
2338 block_stmt_iterator si;
777f7f9a 2339 tree entry_stmt;
50674e96
DN
2340 edge e;
2341
777f7f9a
RH
2342 entry_stmt = last_stmt (region->entry);
2343 child_fn = OMP_PARALLEL_FN (entry_stmt);
50674e96
DN
2344 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
2345 saved_cfun = cfun;
2346
777f7f9a
RH
2347 entry_bb = region->entry;
2348 exit_bb = region->exit;
50674e96 2349
50674e96 2350 if (is_combined_parallel (region))
777f7f9a 2351 ws_args = region->ws_args;
50674e96
DN
2352 else
2353 ws_args = NULL_TREE;
953ff289 2354
777f7f9a 2355 if (child_cfun->cfg)
953ff289 2356 {
50674e96
DN
2357 /* Due to inlining, it may happen that we have already outlined
2358 the region, in which case all we need to do is make the
2359 sub-graph unreachable and emit the parallel call. */
2360 edge entry_succ_e, exit_succ_e;
2361 block_stmt_iterator si;
2362
2363 entry_succ_e = single_succ_edge (entry_bb);
2364 exit_succ_e = single_succ_edge (exit_bb);
2365
2366 si = bsi_last (entry_bb);
777f7f9a 2367 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_PARALLEL);
50674e96
DN
2368 bsi_remove (&si, true);
2369
2370 new_bb = entry_bb;
2371 remove_edge (entry_succ_e);
2372 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
953ff289 2373 }
50674e96
DN
2374 else
2375 {
2376 /* If the parallel region needs data sent from the parent
2377 function, then the very first statement of the parallel body
2378 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
2379 &.OMP_DATA_O is passed as an argument to the child function,
2380 we need to replace it with the argument as seen by the child
2381 function.
2382
2383 In most cases, this will end up being the identity assignment
2384 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
2385 a function call that has been inlined, the original PARM_DECL
2386 .OMP_DATA_I may have been converted into a different local
2387 variable. In which case, we need to keep the assignment. */
777f7f9a 2388 if (OMP_PARALLEL_DATA_ARG (entry_stmt))
50674e96
DN
2389 {
2390 basic_block entry_succ_bb = single_succ (entry_bb);
2391 block_stmt_iterator si = bsi_start (entry_succ_bb);
2392 tree stmt;
953ff289 2393
50674e96 2394 gcc_assert (!bsi_end_p (si));
953ff289 2395
50674e96
DN
2396 stmt = bsi_stmt (si);
2397 gcc_assert (TREE_CODE (stmt) == MODIFY_EXPR
2398 && TREE_CODE (TREE_OPERAND (stmt, 1)) == ADDR_EXPR
2399 && TREE_OPERAND (TREE_OPERAND (stmt, 1), 0)
777f7f9a 2400 == OMP_PARALLEL_DATA_ARG (entry_stmt));
50674e96
DN
2401
2402 if (TREE_OPERAND (stmt, 0) == DECL_ARGUMENTS (child_fn))
2403 bsi_remove (&si, true);
2404 else
2405 TREE_OPERAND (stmt, 1) = DECL_ARGUMENTS (child_fn);
2406 }
2407
2408 /* Declare local variables needed in CHILD_CFUN. */
2409 block = DECL_INITIAL (child_fn);
2410 BLOCK_VARS (block) = list2chain (child_cfun->unexpanded_var_list);
2411 DECL_SAVED_TREE (child_fn) = single_succ (entry_bb)->stmt_list;
2412
2413 /* Reset DECL_CONTEXT on locals and function arguments. */
2414 for (t = BLOCK_VARS (block); t; t = TREE_CHAIN (t))
2415 DECL_CONTEXT (t) = child_fn;
2416
2417 for (t = DECL_ARGUMENTS (child_fn); t; t = TREE_CHAIN (t))
2418 DECL_CONTEXT (t) = child_fn;
2419
2420 /* Split ENTRY_BB at OMP_PARALLEL so that it can be moved to the
2421 child function. */
2422 si = bsi_last (entry_bb);
2423 t = bsi_stmt (si);
2424 gcc_assert (t && TREE_CODE (t) == OMP_PARALLEL);
2425 bsi_remove (&si, true);
2426 e = split_block (entry_bb, t);
2427 entry_bb = e->dest;
2428 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
2429
2430 /* Move the parallel region into CHILD_CFUN. We need to reset
2431 dominance information because the expansion of the inner
2432 regions has invalidated it. */
2433 free_dominance_info (CDI_DOMINATORS);
2434 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb);
2aee3e57
JJ
2435 if (exit_bb)
2436 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
50674e96
DN
2437 cgraph_add_new_function (child_fn);
2438
2439 /* Convert OMP_RETURN into a RETURN_EXPR. */
2aee3e57
JJ
2440 if (exit_bb)
2441 {
2442 si = bsi_last (exit_bb);
2443 gcc_assert (!bsi_end_p (si)
2444 && TREE_CODE (bsi_stmt (si)) == OMP_RETURN);
2445 t = build1 (RETURN_EXPR, void_type_node, NULL);
2446 bsi_insert_after (&si, t, TSI_SAME_STMT);
2447 bsi_remove (&si, true);
2448 }
50674e96
DN
2449 }
2450
2451 /* Emit a library call to launch the children threads. */
777f7f9a 2452 expand_parallel_call (region, new_bb, entry_stmt, ws_args);
953ff289
DN
2453}
2454
50674e96
DN
2455
2456/* A subroutine of expand_omp_for. Generate code for a parallel
953ff289
DN
2457 loop with any schedule. Given parameters:
2458
2459 for (V = N1; V cond N2; V += STEP) BODY;
2460
2461 where COND is "<" or ">", we generate pseudocode
2462
2463 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
50674e96 2464 if (more) goto L0; else goto L3;
953ff289
DN
2465 L0:
2466 V = istart0;
2467 iend = iend0;
2468 L1:
2469 BODY;
2470 V += STEP;
50674e96 2471 if (V cond iend) goto L1; else goto L2;
953ff289 2472 L2:
50674e96
DN
2473 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
2474 L3:
953ff289 2475
50674e96
DN
2476 If this is a combined omp parallel loop, instead of the call to
2477 GOMP_loop_foo_start, we emit 'goto L3'. */
953ff289 2478
777f7f9a 2479static void
50674e96
DN
2480expand_omp_for_generic (struct omp_region *region,
2481 struct omp_for_data *fd,
953ff289
DN
2482 enum built_in_function start_fn,
2483 enum built_in_function next_fn)
2484{
50674e96 2485 tree l0, l1, l2, l3;
953ff289 2486 tree type, istart0, iend0, iend;
50674e96 2487 tree t, args, list;
777f7f9a 2488 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, l2_bb, l3_bb;
50674e96
DN
2489 block_stmt_iterator si;
2490 bool in_combined_parallel = is_combined_parallel (region);
953ff289
DN
2491
2492 type = TREE_TYPE (fd->v);
2493
2494 istart0 = create_tmp_var (long_integer_type_node, ".istart0");
2495 iend0 = create_tmp_var (long_integer_type_node, ".iend0");
777f7f9a 2496 iend = create_tmp_var (type, NULL);
5b4fc8fb
JJ
2497 TREE_ADDRESSABLE (istart0) = 1;
2498 TREE_ADDRESSABLE (iend0) = 1;
953ff289 2499
777f7f9a
RH
2500 entry_bb = region->entry;
2501 l0_bb = create_empty_bb (entry_bb);
50674e96 2502 l1_bb = single_succ (entry_bb);
777f7f9a
RH
2503 cont_bb = region->cont;
2504 l2_bb = create_empty_bb (cont_bb);
2505 l3_bb = single_succ (cont_bb);
2506 exit_bb = region->exit;
50674e96 2507
777f7f9a
RH
2508 l0 = tree_block_label (l0_bb);
2509 l1 = tree_block_label (l1_bb);
2510 l2 = tree_block_label (l2_bb);
2511 l3 = tree_block_label (l3_bb);
50674e96 2512
777f7f9a
RH
2513 si = bsi_last (entry_bb);
2514 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_FOR);
50674e96 2515 if (!in_combined_parallel)
953ff289 2516 {
50674e96
DN
2517 /* If this is not a combined parallel loop, emit a call to
2518 GOMP_loop_foo_start in ENTRY_BB. */
777f7f9a 2519 list = alloc_stmt_list ();
953ff289
DN
2520 t = build_fold_addr_expr (iend0);
2521 args = tree_cons (NULL, t, NULL);
2522 t = build_fold_addr_expr (istart0);
2523 args = tree_cons (NULL, t, args);
2524 if (fd->chunk_size)
2525 {
2526 t = fold_convert (long_integer_type_node, fd->chunk_size);
2527 args = tree_cons (NULL, t, args);
2528 }
2529 t = fold_convert (long_integer_type_node, fd->step);
2530 args = tree_cons (NULL, t, args);
2531 t = fold_convert (long_integer_type_node, fd->n2);
2532 args = tree_cons (NULL, t, args);
2533 t = fold_convert (long_integer_type_node, fd->n1);
2534 args = tree_cons (NULL, t, args);
2535 t = build_function_call_expr (built_in_decls[start_fn], args);
50674e96
DN
2536 t = get_formal_tmp_var (t, &list);
2537 t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&l0),
2538 build_and_jump (&l3));
2539 append_to_statement_list (t, &list);
777f7f9a 2540 bsi_insert_after (&si, list, BSI_SAME_STMT);
953ff289 2541 }
777f7f9a 2542 bsi_remove (&si, true);
953ff289 2543
50674e96
DN
2544 /* Iteration setup for sequential loop goes in L0_BB. */
2545 list = alloc_stmt_list ();
953ff289
DN
2546 t = fold_convert (type, istart0);
2547 t = build2 (MODIFY_EXPR, void_type_node, fd->v, t);
50674e96 2548 gimplify_and_add (t, &list);
953ff289
DN
2549
2550 t = fold_convert (type, iend0);
2551 t = build2 (MODIFY_EXPR, void_type_node, iend, t);
50674e96 2552 gimplify_and_add (t, &list);
953ff289 2553
50674e96
DN
2554 si = bsi_start (l0_bb);
2555 bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
2556
50674e96
DN
2557 /* Code to control the increment and predicate for the sequential
2558 loop goes in the first half of EXIT_BB (we split EXIT_BB so
2559 that we can inherit all the edges going out of the loop
2560 body). */
2561 list = alloc_stmt_list ();
953ff289
DN
2562
2563 t = build2 (PLUS_EXPR, type, fd->v, fd->step);
2564 t = build2 (MODIFY_EXPR, void_type_node, fd->v, t);
50674e96 2565 gimplify_and_add (t, &list);
953ff289
DN
2566
2567 t = build2 (fd->cond_code, boolean_type_node, fd->v, iend);
50674e96
DN
2568 t = get_formal_tmp_var (t, &list);
2569 t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&l1),
2570 build_and_jump (&l2));
2571 append_to_statement_list (t, &list);
2572
777f7f9a
RH
2573 si = bsi_last (cont_bb);
2574 bsi_insert_after (&si, list, BSI_SAME_STMT);
2575 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_CONTINUE);
50674e96 2576 bsi_remove (&si, true);
50674e96
DN
2577
2578 /* Emit code to get the next parallel iteration in L2_BB. */
2579 list = alloc_stmt_list ();
50674e96
DN
2580
2581 t = build_fold_addr_expr (iend0);
2582 args = tree_cons (NULL, t, NULL);
2583 t = build_fold_addr_expr (istart0);
2584 args = tree_cons (NULL, t, args);
2585 t = build_function_call_expr (built_in_decls[next_fn], args);
2586 t = get_formal_tmp_var (t, &list);
2587 t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&l0),
2588 build_and_jump (&l3));
2589 append_to_statement_list (t, &list);
2590
50674e96
DN
2591 si = bsi_start (l2_bb);
2592 bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
953ff289 2593
777f7f9a
RH
2594 /* Add the loop cleanup function. */
2595 si = bsi_last (exit_bb);
2596 if (OMP_RETURN_NOWAIT (bsi_stmt (si)))
2597 t = built_in_decls[BUILT_IN_GOMP_LOOP_END_NOWAIT];
2598 else
2599 t = built_in_decls[BUILT_IN_GOMP_LOOP_END];
2600 t = build_function_call_expr (t, NULL);
2601 bsi_insert_after (&si, t, BSI_SAME_STMT);
2602 bsi_remove (&si, true);
50674e96
DN
2603
2604 /* Connect the new blocks. */
2605 remove_edge (single_succ_edge (entry_bb));
953ff289 2606 if (in_combined_parallel)
50674e96 2607 make_edge (entry_bb, l2_bb, EDGE_FALLTHRU);
953ff289
DN
2608 else
2609 {
50674e96 2610 make_edge (entry_bb, l0_bb, EDGE_TRUE_VALUE);
777f7f9a 2611 make_edge (entry_bb, l3_bb, EDGE_FALSE_VALUE);
953ff289
DN
2612 }
2613
50674e96 2614 make_edge (l0_bb, l1_bb, EDGE_FALLTHRU);
50674e96 2615
777f7f9a
RH
2616 remove_edge (single_succ_edge (cont_bb));
2617 make_edge (cont_bb, l1_bb, EDGE_TRUE_VALUE);
2618 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
2619
2620 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
2621 make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
953ff289
DN
2622}
2623
2624
50674e96
DN
2625/* A subroutine of expand_omp_for. Generate code for a parallel
2626 loop with static schedule and no specified chunk size. Given
2627 parameters:
953ff289
DN
2628
2629 for (V = N1; V cond N2; V += STEP) BODY;
2630
2631 where COND is "<" or ">", we generate pseudocode
2632
2633 if (cond is <)
2634 adj = STEP - 1;
2635 else
2636 adj = STEP + 1;
2637 n = (adj + N2 - N1) / STEP;
2638 q = n / nthreads;
2639 q += (q * nthreads != n);
2640 s0 = q * threadid;
2641 e0 = min(s0 + q, n);
2642 if (s0 >= e0) goto L2; else goto L0;
2643 L0:
2644 V = s0 * STEP + N1;
2645 e = e0 * STEP + N1;
2646 L1:
2647 BODY;
2648 V += STEP;
2649 if (V cond e) goto L1;
953ff289
DN
2650 L2:
2651*/
2652
777f7f9a 2653static void
50674e96
DN
2654expand_omp_for_static_nochunk (struct omp_region *region,
2655 struct omp_for_data *fd)
953ff289
DN
2656{
2657 tree l0, l1, l2, n, q, s0, e0, e, t, nthreads, threadid;
50674e96 2658 tree type, utype, list;
777f7f9a
RH
2659 basic_block entry_bb, exit_bb, seq_start_bb, body_bb, cont_bb;
2660 basic_block fin_bb;
50674e96 2661 block_stmt_iterator si;
953ff289 2662
953ff289
DN
2663 type = TREE_TYPE (fd->v);
2664 utype = lang_hooks.types.unsigned_type (type);
2665
777f7f9a
RH
2666 entry_bb = region->entry;
2667 seq_start_bb = create_empty_bb (entry_bb);
50674e96 2668 body_bb = single_succ (entry_bb);
777f7f9a
RH
2669 cont_bb = region->cont;
2670 fin_bb = single_succ (cont_bb);
2671 exit_bb = region->exit;
2672
2673 l0 = tree_block_label (seq_start_bb);
2674 l1 = tree_block_label (body_bb);
2675 l2 = tree_block_label (fin_bb);
50674e96
DN
2676
2677 /* Iteration space partitioning goes in ENTRY_BB. */
2678 list = alloc_stmt_list ();
777f7f9a 2679
953ff289
DN
2680 t = built_in_decls[BUILT_IN_OMP_GET_NUM_THREADS];
2681 t = build_function_call_expr (t, NULL);
2682 t = fold_convert (utype, t);
50674e96 2683 nthreads = get_formal_tmp_var (t, &list);
953ff289
DN
2684
2685 t = built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM];
2686 t = build_function_call_expr (t, NULL);
2687 t = fold_convert (utype, t);
50674e96 2688 threadid = get_formal_tmp_var (t, &list);
953ff289
DN
2689
2690 fd->n1 = fold_convert (type, fd->n1);
2691 if (!is_gimple_val (fd->n1))
50674e96 2692 fd->n1 = get_formal_tmp_var (fd->n1, &list);
953ff289
DN
2693
2694 fd->n2 = fold_convert (type, fd->n2);
2695 if (!is_gimple_val (fd->n2))
50674e96 2696 fd->n2 = get_formal_tmp_var (fd->n2, &list);
953ff289
DN
2697
2698 fd->step = fold_convert (type, fd->step);
2699 if (!is_gimple_val (fd->step))
50674e96 2700 fd->step = get_formal_tmp_var (fd->step, &list);
953ff289
DN
2701
2702 t = build_int_cst (type, (fd->cond_code == LT_EXPR ? -1 : 1));
2703 t = fold_build2 (PLUS_EXPR, type, fd->step, t);
2704 t = fold_build2 (PLUS_EXPR, type, t, fd->n2);
2705 t = fold_build2 (MINUS_EXPR, type, t, fd->n1);
2706 t = fold_build2 (TRUNC_DIV_EXPR, type, t, fd->step);
2707 t = fold_convert (utype, t);
2708 if (is_gimple_val (t))
2709 n = t;
2710 else
50674e96 2711 n = get_formal_tmp_var (t, &list);
953ff289
DN
2712
2713 t = build2 (TRUNC_DIV_EXPR, utype, n, nthreads);
50674e96 2714 q = get_formal_tmp_var (t, &list);
953ff289
DN
2715
2716 t = build2 (MULT_EXPR, utype, q, nthreads);
2717 t = build2 (NE_EXPR, utype, t, n);
2718 t = build2 (PLUS_EXPR, utype, q, t);
50674e96 2719 q = get_formal_tmp_var (t, &list);
953ff289
DN
2720
2721 t = build2 (MULT_EXPR, utype, q, threadid);
50674e96 2722 s0 = get_formal_tmp_var (t, &list);
953ff289
DN
2723
2724 t = build2 (PLUS_EXPR, utype, s0, q);
2725 t = build2 (MIN_EXPR, utype, t, n);
50674e96 2726 e0 = get_formal_tmp_var (t, &list);
953ff289
DN
2727
2728 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
50674e96
DN
2729 t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&l2),
2730 build_and_jump (&l0));
2731 append_to_statement_list (t, &list);
2732
2733 si = bsi_last (entry_bb);
777f7f9a
RH
2734 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_FOR);
2735 bsi_insert_after (&si, list, BSI_SAME_STMT);
50674e96 2736 bsi_remove (&si, true);
50674e96
DN
2737
2738 /* Setup code for sequential iteration goes in SEQ_START_BB. */
2739 list = alloc_stmt_list ();
953ff289 2740
953ff289
DN
2741 t = fold_convert (type, s0);
2742 t = build2 (MULT_EXPR, type, t, fd->step);
2743 t = build2 (PLUS_EXPR, type, t, fd->n1);
2744 t = build2 (MODIFY_EXPR, void_type_node, fd->v, t);
50674e96 2745 gimplify_and_add (t, &list);
953ff289
DN
2746
2747 t = fold_convert (type, e0);
2748 t = build2 (MULT_EXPR, type, t, fd->step);
2749 t = build2 (PLUS_EXPR, type, t, fd->n1);
50674e96 2750 e = get_formal_tmp_var (t, &list);
953ff289 2751
50674e96
DN
2752 si = bsi_start (seq_start_bb);
2753 bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
953ff289 2754
777f7f9a 2755 /* The code controlling the sequential loop replaces the OMP_CONTINUE. */
50674e96 2756 list = alloc_stmt_list ();
953ff289
DN
2757
2758 t = build2 (PLUS_EXPR, type, fd->v, fd->step);
2759 t = build2 (MODIFY_EXPR, void_type_node, fd->v, t);
50674e96 2760 gimplify_and_add (t, &list);
953ff289
DN
2761
2762 t = build2 (fd->cond_code, boolean_type_node, fd->v, e);
50674e96
DN
2763 t = get_formal_tmp_var (t, &list);
2764 t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&l1),
2765 build_and_jump (&l2));
2766 append_to_statement_list (t, &list);
953ff289 2767
777f7f9a
RH
2768 si = bsi_last (cont_bb);
2769 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_CONTINUE);
2770 bsi_insert_after (&si, list, BSI_SAME_STMT);
2771 bsi_remove (&si, true);
50674e96 2772
777f7f9a
RH
2773 /* Replace the OMP_RETURN with a barrier, or nothing. */
2774 si = bsi_last (exit_bb);
2775 if (!OMP_RETURN_NOWAIT (bsi_stmt (si)))
2776 {
2777 list = alloc_stmt_list ();
2778 build_omp_barrier (&list);
2779 bsi_insert_after (&si, list, BSI_SAME_STMT);
2780 }
2781 bsi_remove (&si, true);
50674e96
DN
2782
2783 /* Connect all the blocks. */
2784 make_edge (seq_start_bb, body_bb, EDGE_FALLTHRU);
2785
2786 remove_edge (single_succ_edge (entry_bb));
777f7f9a 2787 make_edge (entry_bb, fin_bb, EDGE_TRUE_VALUE);
50674e96
DN
2788 make_edge (entry_bb, seq_start_bb, EDGE_FALSE_VALUE);
2789
777f7f9a
RH
2790 make_edge (cont_bb, body_bb, EDGE_TRUE_VALUE);
2791 find_edge (cont_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
953ff289
DN
2792}
2793
50674e96
DN
2794
2795/* A subroutine of expand_omp_for. Generate code for a parallel
2796 loop with static schedule and a specified chunk size. Given
2797 parameters:
953ff289
DN
2798
2799 for (V = N1; V cond N2; V += STEP) BODY;
2800
2801 where COND is "<" or ">", we generate pseudocode
2802
2803 if (cond is <)
2804 adj = STEP - 1;
2805 else
2806 adj = STEP + 1;
2807 n = (adj + N2 - N1) / STEP;
2808 trip = 0;
2809 L0:
2810 s0 = (trip * nthreads + threadid) * CHUNK;
2811 e0 = min(s0 + CHUNK, n);
2812 if (s0 < n) goto L1; else goto L4;
2813 L1:
2814 V = s0 * STEP + N1;
2815 e = e0 * STEP + N1;
2816 L2:
2817 BODY;
2818 V += STEP;
2819 if (V cond e) goto L2; else goto L3;
2820 L3:
2821 trip += 1;
2822 goto L0;
2823 L4:
953ff289
DN
2824*/
2825
777f7f9a 2826static void
50674e96 2827expand_omp_for_static_chunk (struct omp_region *region, struct omp_for_data *fd)
953ff289 2828{
50674e96 2829 tree l0, l1, l2, l3, l4, n, s0, e0, e, t;
953ff289
DN
2830 tree trip, nthreads, threadid;
2831 tree type, utype;
50674e96 2832 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
777f7f9a 2833 basic_block trip_update_bb, cont_bb, fin_bb;
50674e96
DN
2834 tree list;
2835 block_stmt_iterator si;
953ff289 2836
953ff289
DN
2837 type = TREE_TYPE (fd->v);
2838 utype = lang_hooks.types.unsigned_type (type);
2839
777f7f9a
RH
2840 entry_bb = region->entry;
2841 iter_part_bb = create_empty_bb (entry_bb);
2842 seq_start_bb = create_empty_bb (iter_part_bb);
50674e96 2843 body_bb = single_succ (entry_bb);
777f7f9a
RH
2844 cont_bb = region->cont;
2845 trip_update_bb = create_empty_bb (cont_bb);
2846 fin_bb = single_succ (cont_bb);
2847 exit_bb = region->exit;
50674e96 2848
777f7f9a
RH
2849 l0 = tree_block_label (iter_part_bb);
2850 l1 = tree_block_label (seq_start_bb);
2851 l2 = tree_block_label (body_bb);
2852 l3 = tree_block_label (trip_update_bb);
2853 l4 = tree_block_label (fin_bb);
50674e96
DN
2854
2855 /* Trip and adjustment setup goes in ENTRY_BB. */
2856 list = alloc_stmt_list ();
2857
953ff289
DN
2858 t = built_in_decls[BUILT_IN_OMP_GET_NUM_THREADS];
2859 t = build_function_call_expr (t, NULL);
2860 t = fold_convert (utype, t);
50674e96 2861 nthreads = get_formal_tmp_var (t, &list);
953ff289
DN
2862
2863 t = built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM];
2864 t = build_function_call_expr (t, NULL);
2865 t = fold_convert (utype, t);
50674e96 2866 threadid = get_formal_tmp_var (t, &list);
953ff289
DN
2867
2868 fd->n1 = fold_convert (type, fd->n1);
2869 if (!is_gimple_val (fd->n1))
50674e96 2870 fd->n1 = get_formal_tmp_var (fd->n1, &list);
953ff289
DN
2871
2872 fd->n2 = fold_convert (type, fd->n2);
2873 if (!is_gimple_val (fd->n2))
50674e96 2874 fd->n2 = get_formal_tmp_var (fd->n2, &list);
953ff289
DN
2875
2876 fd->step = fold_convert (type, fd->step);
2877 if (!is_gimple_val (fd->step))
50674e96 2878 fd->step = get_formal_tmp_var (fd->step, &list);
953ff289
DN
2879
2880 fd->chunk_size = fold_convert (utype, fd->chunk_size);
2881 if (!is_gimple_val (fd->chunk_size))
50674e96 2882 fd->chunk_size = get_formal_tmp_var (fd->chunk_size, &list);
953ff289
DN
2883
2884 t = build_int_cst (type, (fd->cond_code == LT_EXPR ? -1 : 1));
2885 t = fold_build2 (PLUS_EXPR, type, fd->step, t);
2886 t = fold_build2 (PLUS_EXPR, type, t, fd->n2);
2887 t = fold_build2 (MINUS_EXPR, type, t, fd->n1);
2888 t = fold_build2 (TRUNC_DIV_EXPR, type, t, fd->step);
2889 t = fold_convert (utype, t);
2890 if (is_gimple_val (t))
2891 n = t;
2892 else
50674e96 2893 n = get_formal_tmp_var (t, &list);
953ff289
DN
2894
2895 t = build_int_cst (utype, 0);
50674e96
DN
2896 trip = get_initialized_tmp_var (t, &list, NULL);
2897
2898 si = bsi_last (entry_bb);
777f7f9a
RH
2899 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_FOR);
2900 bsi_insert_after (&si, list, BSI_SAME_STMT);
50674e96 2901 bsi_remove (&si, true);
50674e96
DN
2902
2903 /* Iteration space partitioning goes in ITER_PART_BB. */
2904 list = alloc_stmt_list ();
953ff289 2905
953ff289
DN
2906 t = build2 (MULT_EXPR, utype, trip, nthreads);
2907 t = build2 (PLUS_EXPR, utype, t, threadid);
2908 t = build2 (MULT_EXPR, utype, t, fd->chunk_size);
50674e96 2909 s0 = get_formal_tmp_var (t, &list);
953ff289
DN
2910
2911 t = build2 (PLUS_EXPR, utype, s0, fd->chunk_size);
2912 t = build2 (MIN_EXPR, utype, t, n);
50674e96 2913 e0 = get_formal_tmp_var (t, &list);
953ff289
DN
2914
2915 t = build2 (LT_EXPR, boolean_type_node, s0, n);
2916 t = build3 (COND_EXPR, void_type_node, t,
2917 build_and_jump (&l1), build_and_jump (&l4));
50674e96
DN
2918 append_to_statement_list (t, &list);
2919
50674e96
DN
2920 si = bsi_start (iter_part_bb);
2921 bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
2922
2923 /* Setup code for sequential iteration goes in SEQ_START_BB. */
2924 list = alloc_stmt_list ();
953ff289 2925
953ff289
DN
2926 t = fold_convert (type, s0);
2927 t = build2 (MULT_EXPR, type, t, fd->step);
2928 t = build2 (PLUS_EXPR, type, t, fd->n1);
2929 t = build2 (MODIFY_EXPR, void_type_node, fd->v, t);
50674e96 2930 gimplify_and_add (t, &list);
953ff289
DN
2931
2932 t = fold_convert (type, e0);
2933 t = build2 (MULT_EXPR, type, t, fd->step);
2934 t = build2 (PLUS_EXPR, type, t, fd->n1);
50674e96
DN
2935 e = get_formal_tmp_var (t, &list);
2936
50674e96
DN
2937 si = bsi_start (seq_start_bb);
2938 bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
953ff289 2939
777f7f9a
RH
2940 /* The code controlling the sequential loop goes in CONT_BB,
2941 replacing the OMP_CONTINUE. */
50674e96 2942 list = alloc_stmt_list ();
953ff289
DN
2943
2944 t = build2 (PLUS_EXPR, type, fd->v, fd->step);
2945 t = build2 (MODIFY_EXPR, void_type_node, fd->v, t);
50674e96 2946 gimplify_and_add (t, &list);
953ff289
DN
2947
2948 t = build2 (fd->cond_code, boolean_type_node, fd->v, e);
50674e96 2949 t = get_formal_tmp_var (t, &list);
953ff289
DN
2950 t = build3 (COND_EXPR, void_type_node, t,
2951 build_and_jump (&l2), build_and_jump (&l3));
50674e96
DN
2952 append_to_statement_list (t, &list);
2953
777f7f9a
RH
2954 si = bsi_last (cont_bb);
2955 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_CONTINUE);
2956 bsi_insert_after (&si, list, BSI_SAME_STMT);
50674e96 2957 bsi_remove (&si, true);
50674e96
DN
2958
2959 /* Trip update code goes into TRIP_UPDATE_BB. */
50674e96 2960 list = alloc_stmt_list ();
953ff289 2961
953ff289
DN
2962 t = build_int_cst (utype, 1);
2963 t = build2 (PLUS_EXPR, utype, trip, t);
2964 t = build2 (MODIFY_EXPR, void_type_node, trip, t);
50674e96 2965 gimplify_and_add (t, &list);
953ff289 2966
50674e96
DN
2967 si = bsi_start (trip_update_bb);
2968 bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
953ff289 2969
777f7f9a
RH
2970 /* Replace the OMP_RETURN with a barrier, or nothing. */
2971 si = bsi_last (exit_bb);
2972 if (!OMP_RETURN_NOWAIT (bsi_stmt (si)))
2973 {
2974 list = alloc_stmt_list ();
2975 build_omp_barrier (&list);
2976 bsi_insert_after (&si, list, BSI_SAME_STMT);
2977 }
2978 bsi_remove (&si, true);
953ff289 2979
50674e96
DN
2980 /* Connect the new blocks. */
2981 remove_edge (single_succ_edge (entry_bb));
2982 make_edge (entry_bb, iter_part_bb, EDGE_FALLTHRU);
953ff289 2983
50674e96 2984 make_edge (iter_part_bb, seq_start_bb, EDGE_TRUE_VALUE);
777f7f9a 2985 make_edge (iter_part_bb, fin_bb, EDGE_FALSE_VALUE);
50674e96
DN
2986
2987 make_edge (seq_start_bb, body_bb, EDGE_FALLTHRU);
2988
777f7f9a
RH
2989 remove_edge (single_succ_edge (cont_bb));
2990 make_edge (cont_bb, body_bb, EDGE_TRUE_VALUE);
2991 make_edge (cont_bb, trip_update_bb, EDGE_FALSE_VALUE);
50674e96
DN
2992
2993 make_edge (trip_update_bb, iter_part_bb, EDGE_FALLTHRU);
953ff289
DN
2994}
2995
953ff289 2996
50674e96 2997/* Expand the OpenMP loop defined by REGION. */
953ff289 2998
50674e96
DN
2999static void
3000expand_omp_for (struct omp_region *region)
3001{
3002 struct omp_for_data fd;
953ff289 3003
50674e96 3004 push_gimplify_context ();
953ff289 3005
777f7f9a 3006 extract_omp_for_data (last_stmt (region->entry), &fd);
21a66e91 3007 region->sched_kind = fd.sched_kind;
953ff289
DN
3008
3009 if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC && !fd.have_ordered)
3010 {
3011 if (fd.chunk_size == NULL)
777f7f9a 3012 expand_omp_for_static_nochunk (region, &fd);
953ff289 3013 else
777f7f9a 3014 expand_omp_for_static_chunk (region, &fd);
953ff289
DN
3015 }
3016 else
3017 {
50674e96
DN
3018 int fn_index = fd.sched_kind + fd.have_ordered * 4;
3019 int start_ix = BUILT_IN_GOMP_LOOP_STATIC_START + fn_index;
3020 int next_ix = BUILT_IN_GOMP_LOOP_STATIC_NEXT + fn_index;
777f7f9a 3021 expand_omp_for_generic (region, &fd, start_ix, next_ix);
953ff289
DN
3022 }
3023
50674e96 3024 pop_gimplify_context (NULL);
953ff289
DN
3025}
3026
953ff289
DN
3027
3028/* Expand code for an OpenMP sections directive. In pseudo code, we generate
3029
953ff289
DN
3030 v = GOMP_sections_start (n);
3031 L0:
3032 switch (v)
3033 {
3034 case 0:
3035 goto L2;
3036 case 1:
3037 section 1;
3038 goto L1;
3039 case 2:
3040 ...
3041 case n:
3042 ...
953ff289
DN
3043 default:
3044 abort ();
3045 }
3046 L1:
3047 v = GOMP_sections_next ();
3048 goto L0;
3049 L2:
3050 reduction;
3051
50674e96
DN
3052 If this is a combined parallel sections, replace the call to
3053 GOMP_sections_start with 'goto L1'. */
953ff289
DN
3054
3055static void
50674e96 3056expand_omp_sections (struct omp_region *region)
953ff289 3057{
777f7f9a 3058 tree label_vec, l0, l1, l2, t, u, v, sections_stmt;
953ff289 3059 unsigned i, len;
777f7f9a 3060 basic_block entry_bb, exit_bb, l0_bb, l1_bb, l2_bb, default_bb;
50674e96 3061 block_stmt_iterator si;
777f7f9a
RH
3062 struct omp_region *inner;
3063 edge e;
953ff289 3064
777f7f9a
RH
3065 entry_bb = region->entry;
3066 l0_bb = create_empty_bb (entry_bb);
3067 l1_bb = region->cont;
3068 l2_bb = single_succ (l1_bb);
3069 default_bb = create_empty_bb (l1_bb->prev_bb);
3070 exit_bb = region->exit;
953ff289 3071
777f7f9a
RH
3072 l0 = tree_block_label (l0_bb);
3073 l1 = tree_block_label (l1_bb);
3074 l2 = tree_block_label (l2_bb);
50674e96 3075
953ff289 3076 v = create_tmp_var (unsigned_type_node, ".section");
50674e96
DN
3077
3078 /* We will build a switch() with enough cases for all the
3079 OMP_SECTION regions, a '0' case to handle the end of more work
3080 and a default case to abort if something goes wrong. */
3081 len = EDGE_COUNT (entry_bb->succs);
953ff289
DN
3082 label_vec = make_tree_vec (len + 2);
3083
777f7f9a
RH
3084 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
3085 OMP_SECTIONS statement. */
50674e96 3086 si = bsi_last (entry_bb);
777f7f9a
RH
3087 sections_stmt = bsi_stmt (si);
3088 gcc_assert (TREE_CODE (sections_stmt) == OMP_SECTIONS);
50674e96 3089 if (!is_combined_parallel (region))
953ff289 3090 {
50674e96
DN
3091 /* If we are not inside a combined parallel+sections region,
3092 call GOMP_sections_start. */
3093 t = build_int_cst (unsigned_type_node, len);
3094 t = tree_cons (NULL, t, NULL);
953ff289
DN
3095 u = built_in_decls[BUILT_IN_GOMP_SECTIONS_START];
3096 t = build_function_call_expr (u, t);
3097 t = build2 (MODIFY_EXPR, void_type_node, v, t);
777f7f9a 3098 bsi_insert_after (&si, t, BSI_SAME_STMT);
953ff289 3099 }
777f7f9a 3100 bsi_remove (&si, true);
953ff289 3101
50674e96 3102 /* The switch() statement replacing OMP_SECTIONS goes in L0_BB. */
777f7f9a 3103 si = bsi_start (l0_bb);
953ff289
DN
3104
3105 t = build3 (SWITCH_EXPR, void_type_node, v, NULL, label_vec);
50674e96 3106 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
953ff289
DN
3107
3108 t = build3 (CASE_LABEL_EXPR, void_type_node,
3109 build_int_cst (unsigned_type_node, 0), NULL, l2);
3110 TREE_VEC_ELT (label_vec, 0) = t;
777f7f9a 3111 make_edge (l0_bb, l2_bb, 0);
953ff289 3112
50674e96 3113 /* Convert each OMP_SECTION into a CASE_LABEL_EXPR. */
777f7f9a 3114 for (inner = region->inner, i = 1; inner; inner = inner->next, ++i)
953ff289 3115 {
50674e96
DN
3116 basic_block s_entry_bb, s_exit_bb;
3117
777f7f9a
RH
3118 s_entry_bb = inner->entry;
3119 s_exit_bb = inner->exit;
953ff289 3120
777f7f9a 3121 t = tree_block_label (s_entry_bb);
50674e96 3122 u = build_int_cst (unsigned_type_node, i);
953ff289 3123 u = build3 (CASE_LABEL_EXPR, void_type_node, u, NULL, t);
50674e96 3124 TREE_VEC_ELT (label_vec, i) = u;
777f7f9a 3125
50674e96 3126 si = bsi_last (s_entry_bb);
777f7f9a
RH
3127 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_SECTION);
3128 gcc_assert (i < len || OMP_SECTION_LAST (bsi_stmt (si)));
3129 bsi_remove (&si, true);
50674e96
DN
3130
3131 si = bsi_last (s_exit_bb);
777f7f9a 3132 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_RETURN);
50674e96 3133 bsi_remove (&si, true);
777f7f9a
RH
3134
3135 e = single_pred_edge (s_entry_bb);
3136 e->flags = 0;
3137 redirect_edge_pred (e, l0_bb);
3138
3139 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
50674e96 3140 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
953ff289
DN
3141 }
3142
50674e96 3143 /* Error handling code goes in DEFAULT_BB. */
777f7f9a 3144 t = tree_block_label (default_bb);
953ff289
DN
3145 u = build3 (CASE_LABEL_EXPR, void_type_node, NULL, NULL, t);
3146 TREE_VEC_ELT (label_vec, len + 1) = u;
777f7f9a 3147 make_edge (l0_bb, default_bb, 0);
953ff289 3148
777f7f9a 3149 si = bsi_start (default_bb);
953ff289
DN
3150 t = built_in_decls[BUILT_IN_TRAP];
3151 t = build_function_call_expr (t, NULL);
50674e96
DN
3152 bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
3153
50674e96 3154 /* Code to get the next section goes in L1_BB. */
777f7f9a
RH
3155 si = bsi_last (l1_bb);
3156 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_CONTINUE);
953ff289 3157
50674e96
DN
3158 t = built_in_decls[BUILT_IN_GOMP_SECTIONS_NEXT];
3159 t = build_function_call_expr (t, NULL);
3160 t = build2 (MODIFY_EXPR, void_type_node, v, t);
777f7f9a
RH
3161 bsi_insert_after (&si, t, BSI_SAME_STMT);
3162 bsi_remove (&si, true);
50674e96 3163
777f7f9a 3164 /* Cleanup function replaces OMP_RETURN in EXIT_BB. */
50674e96 3165 si = bsi_last (exit_bb);
777f7f9a
RH
3166 if (OMP_RETURN_NOWAIT (bsi_stmt (si)))
3167 t = built_in_decls[BUILT_IN_GOMP_SECTIONS_END_NOWAIT];
3168 else
3169 t = built_in_decls[BUILT_IN_GOMP_SECTIONS_END];
3170 t = build_function_call_expr (t, NULL);
3171 bsi_insert_after (&si, t, BSI_SAME_STMT);
3172 bsi_remove (&si, true);
50674e96 3173
777f7f9a 3174 /* Connect the new blocks. */
50674e96 3175 if (is_combined_parallel (region))
953ff289 3176 {
50674e96
DN
3177 /* If this was a combined parallel+sections region, we did not
3178 emit a GOMP_sections_start in the entry block, so we just
3179 need to jump to L1_BB to get the next section. */
50674e96 3180 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
953ff289 3181 }
777f7f9a
RH
3182 else
3183 make_edge (entry_bb, l0_bb, EDGE_FALLTHRU);
3184
3185 e = single_succ_edge (l1_bb);
3186 redirect_edge_succ (e, l0_bb);
3187 e->flags = EDGE_FALLTHRU;
50674e96 3188}
953ff289 3189
953ff289 3190
777f7f9a
RH
3191/* Expand code for an OpenMP single directive. We've already expanded
3192 much of the code, here we simply place the GOMP_barrier call. */
3193
3194static void
3195expand_omp_single (struct omp_region *region)
3196{
3197 basic_block entry_bb, exit_bb;
3198 block_stmt_iterator si;
3199 bool need_barrier = false;
3200
3201 entry_bb = region->entry;
3202 exit_bb = region->exit;
3203
3204 si = bsi_last (entry_bb);
3205 /* The terminal barrier at the end of a GOMP_single_copy sequence cannot
3206 be removed. We need to ensure that the thread that entered the single
3207 does not exit before the data is copied out by the other threads. */
3208 if (find_omp_clause (OMP_SINGLE_CLAUSES (bsi_stmt (si)),
3209 OMP_CLAUSE_COPYPRIVATE))
3210 need_barrier = true;
3211 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_SINGLE);
3212 bsi_remove (&si, true);
3213 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
3214
3215 si = bsi_last (exit_bb);
3216 if (!OMP_RETURN_NOWAIT (bsi_stmt (si)) || need_barrier)
3217 {
3218 tree t = alloc_stmt_list ();
3219 build_omp_barrier (&t);
3220 bsi_insert_after (&si, t, BSI_SAME_STMT);
3221 }
3222 bsi_remove (&si, true);
3223 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
3224}
3225
3226
3227/* Generic expansion for OpenMP synchronization directives: master,
3228 ordered and critical. All we need to do here is remove the entry
3229 and exit markers for REGION. */
50674e96
DN
3230
3231static void
3232expand_omp_synch (struct omp_region *region)
3233{
3234 basic_block entry_bb, exit_bb;
3235 block_stmt_iterator si;
50674e96 3236
777f7f9a
RH
3237 entry_bb = region->entry;
3238 exit_bb = region->exit;
50674e96
DN
3239
3240 si = bsi_last (entry_bb);
777f7f9a
RH
3241 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_SINGLE
3242 || TREE_CODE (bsi_stmt (si)) == OMP_MASTER
3243 || TREE_CODE (bsi_stmt (si)) == OMP_ORDERED
3244 || TREE_CODE (bsi_stmt (si)) == OMP_CRITICAL);
50674e96
DN
3245 bsi_remove (&si, true);
3246 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
3247
3248 si = bsi_last (exit_bb);
777f7f9a 3249 gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_RETURN);
50674e96
DN
3250 bsi_remove (&si, true);
3251 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
3252}
953ff289 3253
953ff289 3254
50674e96
DN
3255/* Expand the parallel region tree rooted at REGION. Expansion
3256 proceeds in depth-first order. Innermost regions are expanded
3257 first. This way, parallel regions that require a new function to
3258 be created (e.g., OMP_PARALLEL) can be expanded without having any
3259 internal dependencies in their body. */
3260
3261static void
3262expand_omp (struct omp_region *region)
3263{
3264 while (region)
3265 {
50674e96
DN
3266 if (region->inner)
3267 expand_omp (region->inner);
3268
777f7f9a 3269 switch (region->type)
50674e96 3270 {
777f7f9a
RH
3271 case OMP_PARALLEL:
3272 expand_omp_parallel (region);
3273 break;
50674e96 3274
777f7f9a
RH
3275 case OMP_FOR:
3276 expand_omp_for (region);
3277 break;
50674e96 3278
777f7f9a
RH
3279 case OMP_SECTIONS:
3280 expand_omp_sections (region);
3281 break;
50674e96 3282
777f7f9a
RH
3283 case OMP_SECTION:
3284 /* Individual omp sections are handled together with their
3285 parent OMP_SECTIONS region. */
3286 break;
50674e96 3287
777f7f9a
RH
3288 case OMP_SINGLE:
3289 expand_omp_single (region);
3290 break;
50674e96 3291
777f7f9a
RH
3292 case OMP_MASTER:
3293 case OMP_ORDERED:
3294 case OMP_CRITICAL:
3295 expand_omp_synch (region);
3296 break;
50674e96 3297
777f7f9a
RH
3298 default:
3299 gcc_unreachable ();
3300 }
8d9c1aec 3301
50674e96
DN
3302 region = region->next;
3303 }
3304}
3305
3306
3307/* Helper for build_omp_regions. Scan the dominator tree starting at
3308 block BB. PARENT is the region that contains BB. */
3309
3310static void
3311build_omp_regions_1 (basic_block bb, struct omp_region *parent)
3312{
3313 block_stmt_iterator si;
3314 tree stmt;
3315 basic_block son;
3316
3317 si = bsi_last (bb);
3318 if (!bsi_end_p (si) && OMP_DIRECTIVE_P (bsi_stmt (si)))
3319 {
3320 struct omp_region *region;
777f7f9a 3321 enum tree_code code;
50674e96
DN
3322
3323 stmt = bsi_stmt (si);
777f7f9a 3324 code = TREE_CODE (stmt);
50674e96 3325
777f7f9a 3326 if (code == OMP_RETURN)
50674e96
DN
3327 {
3328 /* STMT is the return point out of region PARENT. Mark it
3329 as the exit point and make PARENT the immediately
3330 enclosing region. */
3331 gcc_assert (parent);
3332 region = parent;
777f7f9a 3333 region->exit = bb;
50674e96
DN
3334 parent = parent->outer;
3335
3336 /* If REGION is a parallel region, determine whether it is
3337 a combined parallel+workshare region. */
777f7f9a 3338 if (region->type == OMP_PARALLEL)
50674e96
DN
3339 determine_parallel_type (region);
3340 }
777f7f9a
RH
3341 else if (code == OMP_CONTINUE)
3342 {
3343 gcc_assert (parent);
3344 parent->cont = bb;
3345 }
50674e96
DN
3346 else
3347 {
3348 /* Otherwise, this directive becomes the parent for a new
3349 region. */
777f7f9a 3350 region = new_omp_region (bb, code, parent);
50674e96
DN
3351 parent = region;
3352 }
50674e96
DN
3353 }
3354
3355 for (son = first_dom_son (CDI_DOMINATORS, bb);
3356 son;
3357 son = next_dom_son (CDI_DOMINATORS, son))
3358 build_omp_regions_1 (son, parent);
3359}
3360
3361
3362/* Scan the CFG and build a tree of OMP regions. Return the root of
3363 the OMP region tree. */
3364
3365static void
3366build_omp_regions (void)
3367{
777f7f9a 3368 gcc_assert (root_omp_region == NULL);
50674e96
DN
3369 calculate_dominance_info (CDI_DOMINATORS);
3370 build_omp_regions_1 (ENTRY_BLOCK_PTR, NULL);
3371}
3372
3373
3374/* Main entry point for expanding OMP-GIMPLE into runtime calls. */
3375
c2924966 3376static unsigned int
50674e96
DN
3377execute_expand_omp (void)
3378{
3379 build_omp_regions ();
3380
777f7f9a
RH
3381 if (!root_omp_region)
3382 return 0;
50674e96 3383
777f7f9a
RH
3384 if (dump_file)
3385 {
3386 fprintf (dump_file, "\nOMP region tree\n\n");
3387 dump_omp_region (dump_file, root_omp_region, 0);
3388 fprintf (dump_file, "\n");
50674e96 3389 }
777f7f9a
RH
3390
3391 remove_exit_barriers (root_omp_region);
3392
3393 expand_omp (root_omp_region);
3394
3395 free_dominance_info (CDI_DOMINATORS);
3396 free_dominance_info (CDI_POST_DOMINATORS);
3397 cleanup_tree_cfg ();
3398
3399 free_omp_regions ();
3400
c2924966 3401 return 0;
50674e96
DN
3402}
3403
3404static bool
3405gate_expand_omp (void)
3406{
3407 return flag_openmp != 0 && errorcount == 0;
3408}
3409
3410struct tree_opt_pass pass_expand_omp =
3411{
3412 "ompexp", /* name */
3413 gate_expand_omp, /* gate */
3414 execute_expand_omp, /* execute */
3415 NULL, /* sub */
3416 NULL, /* next */
3417 0, /* static_pass_number */
3418 0, /* tv_id */
3419 PROP_gimple_any, /* properties_required */
3420 PROP_gimple_lomp, /* properties_provided */
3421 0, /* properties_destroyed */
3422 0, /* todo_flags_start */
3423 TODO_dump_func, /* todo_flags_finish */
3424 0 /* letter */
3425};
3426\f
3427/* Routines to lower OpenMP directives into OMP-GIMPLE. */
3428
3429/* Lower the OpenMP sections directive in *STMT_P. */
3430
3431static void
3432lower_omp_sections (tree *stmt_p, omp_context *ctx)
3433{
3434 tree new_stmt, stmt, body, bind, block, ilist, olist, new_body;
777f7f9a 3435 tree t, dlist;
50674e96
DN
3436 tree_stmt_iterator tsi;
3437 unsigned i, len;
3438
3439 stmt = *stmt_p;
3440
50674e96
DN
3441 push_gimplify_context ();
3442
3443 dlist = NULL;
3444 ilist = NULL;
3445 lower_rec_input_clauses (OMP_SECTIONS_CLAUSES (stmt), &ilist, &dlist, ctx);
3446
3447 tsi = tsi_start (OMP_SECTIONS_BODY (stmt));
3448 for (len = 0; !tsi_end_p (tsi); len++, tsi_next (&tsi))
3449 continue;
3450
50674e96
DN
3451 tsi = tsi_start (OMP_SECTIONS_BODY (stmt));
3452 body = alloc_stmt_list ();
3453 for (i = 0; i < len; i++, tsi_next (&tsi))
3454 {
3455 omp_context *sctx;
777f7f9a 3456 tree sec_start, sec_end;
50674e96
DN
3457
3458 sec_start = tsi_stmt (tsi);
50674e96
DN
3459 sctx = maybe_lookup_ctx (sec_start);
3460 gcc_assert (sctx);
3461
777f7f9a
RH
3462 append_to_statement_list (sec_start, &body);
3463
50674e96 3464 lower_omp (&OMP_SECTION_BODY (sec_start), sctx);
777f7f9a
RH
3465 append_to_statement_list (OMP_SECTION_BODY (sec_start), &body);
3466 OMP_SECTION_BODY (sec_start) = NULL;
50674e96
DN
3467
3468 if (i == len - 1)
3469 {
3470 tree l = alloc_stmt_list ();
3471 lower_lastprivate_clauses (OMP_SECTIONS_CLAUSES (stmt), NULL,
3472 &l, ctx);
777f7f9a
RH
3473 append_to_statement_list (l, &body);
3474 OMP_SECTION_LAST (sec_start) = 1;
50674e96
DN
3475 }
3476
777f7f9a 3477 sec_end = make_node (OMP_RETURN);
50674e96 3478 append_to_statement_list (sec_end, &body);
50674e96 3479 }
953ff289
DN
3480
3481 block = make_node (BLOCK);
50674e96 3482 bind = build3 (BIND_EXPR, void_type_node, NULL, body, block);
953ff289 3483
50674e96
DN
3484 olist = NULL_TREE;
3485 lower_reduction_clauses (OMP_SECTIONS_CLAUSES (stmt), &olist, ctx);
3486
50674e96
DN
3487 pop_gimplify_context (NULL_TREE);
3488 record_vars_into (ctx->block_vars, ctx->cb.dst_fn);
3489
3490 new_stmt = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
3491 TREE_SIDE_EFFECTS (new_stmt) = 1;
50674e96
DN
3492
3493 new_body = alloc_stmt_list ();
3494 append_to_statement_list (ilist, &new_body);
3495 append_to_statement_list (stmt, &new_body);
777f7f9a
RH
3496 append_to_statement_list (bind, &new_body);
3497
3498 t = make_node (OMP_CONTINUE);
3499 append_to_statement_list (t, &new_body);
3500
50674e96
DN
3501 append_to_statement_list (olist, &new_body);
3502 append_to_statement_list (dlist, &new_body);
50674e96 3503
4a31b7ee
JJ
3504 maybe_catch_exception (&new_body);
3505
777f7f9a
RH
3506 t = make_node (OMP_RETURN);
3507 OMP_RETURN_NOWAIT (t) = !!find_omp_clause (OMP_SECTIONS_CLAUSES (stmt),
3508 OMP_CLAUSE_NOWAIT);
3509 append_to_statement_list (t, &new_body);
3510
3511 BIND_EXPR_BODY (new_stmt) = new_body;
3512 OMP_SECTIONS_BODY (stmt) = NULL;
50674e96
DN
3513
3514 *stmt_p = new_stmt;
953ff289
DN
3515}
3516
3517
50674e96 3518/* A subroutine of lower_omp_single. Expand the simple form of
953ff289
DN
3519 an OMP_SINGLE, without a copyprivate clause:
3520
3521 if (GOMP_single_start ())
3522 BODY;
3523 [ GOMP_barrier (); ] -> unless 'nowait' is present.
50674e96
DN
3524
3525 FIXME. It may be better to delay expanding the logic of this until
3526 pass_expand_omp. The expanded logic may make the job more difficult
3527 to a synchronization analysis pass. */
953ff289
DN
3528
3529static void
50674e96 3530lower_omp_single_simple (tree single_stmt, tree *pre_p)
953ff289
DN
3531{
3532 tree t;
3533
3534 t = built_in_decls[BUILT_IN_GOMP_SINGLE_START];
3535 t = build_function_call_expr (t, NULL);
3536 t = build3 (COND_EXPR, void_type_node, t,
3537 OMP_SINGLE_BODY (single_stmt), NULL);
3538 gimplify_and_add (t, pre_p);
953ff289
DN
3539}
3540
50674e96
DN
3541
3542/* A subroutine of lower_omp_single. Expand the simple form of
953ff289
DN
3543 an OMP_SINGLE, with a copyprivate clause:
3544
3545 #pragma omp single copyprivate (a, b, c)
3546
3547 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
3548
3549 {
3550 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
3551 {
3552 BODY;
3553 copyout.a = a;
3554 copyout.b = b;
3555 copyout.c = c;
3556 GOMP_single_copy_end (&copyout);
3557 }
3558 else
3559 {
3560 a = copyout_p->a;
3561 b = copyout_p->b;
3562 c = copyout_p->c;
3563 }
3564 GOMP_barrier ();
3565 }
50674e96
DN
3566
3567 FIXME. It may be better to delay expanding the logic of this until
3568 pass_expand_omp. The expanded logic may make the job more difficult
3569 to a synchronization analysis pass. */
953ff289
DN
3570
3571static void
50674e96 3572lower_omp_single_copy (tree single_stmt, tree *pre_p, omp_context *ctx)
953ff289
DN
3573{
3574 tree ptr_type, t, args, l0, l1, l2, copyin_seq;
3575
3576 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
3577
3578 ptr_type = build_pointer_type (ctx->record_type);
3579 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
3580
3581 l0 = create_artificial_label ();
3582 l1 = create_artificial_label ();
3583 l2 = create_artificial_label ();
3584
3585 t = built_in_decls[BUILT_IN_GOMP_SINGLE_COPY_START];
3586 t = build_function_call_expr (t, NULL);
3587 t = fold_convert (ptr_type, t);
3588 t = build2 (MODIFY_EXPR, void_type_node, ctx->receiver_decl, t);
3589 gimplify_and_add (t, pre_p);
3590
3591 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
3592 build_int_cst (ptr_type, 0));
3593 t = build3 (COND_EXPR, void_type_node, t,
3594 build_and_jump (&l0), build_and_jump (&l1));
3595 gimplify_and_add (t, pre_p);
3596
3597 t = build1 (LABEL_EXPR, void_type_node, l0);
3598 gimplify_and_add (t, pre_p);
3599
3600 append_to_statement_list (OMP_SINGLE_BODY (single_stmt), pre_p);
3601
3602 copyin_seq = NULL;
50674e96 3603 lower_copyprivate_clauses (OMP_SINGLE_CLAUSES (single_stmt), pre_p,
953ff289
DN
3604 &copyin_seq, ctx);
3605
3606 t = build_fold_addr_expr (ctx->sender_decl);
3607 args = tree_cons (NULL, t, NULL);
3608 t = built_in_decls[BUILT_IN_GOMP_SINGLE_COPY_END];
3609 t = build_function_call_expr (t, args);
3610 gimplify_and_add (t, pre_p);
3611
3612 t = build_and_jump (&l2);
3613 gimplify_and_add (t, pre_p);
3614
3615 t = build1 (LABEL_EXPR, void_type_node, l1);
3616 gimplify_and_add (t, pre_p);
3617
3618 append_to_statement_list (copyin_seq, pre_p);
3619
3620 t = build1 (LABEL_EXPR, void_type_node, l2);
3621 gimplify_and_add (t, pre_p);
953ff289
DN
3622}
3623
50674e96 3624
953ff289
DN
3625/* Expand code for an OpenMP single directive. */
3626
3627static void
50674e96 3628lower_omp_single (tree *stmt_p, omp_context *ctx)
953ff289 3629{
50674e96 3630 tree t, bind, block, single_stmt = *stmt_p, dlist;
953ff289
DN
3631
3632 push_gimplify_context ();
3633
3634 block = make_node (BLOCK);
777f7f9a 3635 *stmt_p = bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, block);
50674e96 3636 TREE_SIDE_EFFECTS (bind) = 1;
953ff289 3637
50674e96
DN
3638 lower_rec_input_clauses (OMP_SINGLE_CLAUSES (single_stmt),
3639 &BIND_EXPR_BODY (bind), &dlist, ctx);
3640 lower_omp (&OMP_SINGLE_BODY (single_stmt), ctx);
777f7f9a
RH
3641
3642 append_to_statement_list (single_stmt, &BIND_EXPR_BODY (bind));
953ff289
DN
3643
3644 if (ctx->record_type)
50674e96 3645 lower_omp_single_copy (single_stmt, &BIND_EXPR_BODY (bind), ctx);
953ff289 3646 else
50674e96 3647 lower_omp_single_simple (single_stmt, &BIND_EXPR_BODY (bind));
953ff289 3648
777f7f9a
RH
3649 OMP_SINGLE_BODY (single_stmt) = NULL;
3650
953ff289 3651 append_to_statement_list (dlist, &BIND_EXPR_BODY (bind));
777f7f9a 3652
4a31b7ee
JJ
3653 maybe_catch_exception (&BIND_EXPR_BODY (bind));
3654
777f7f9a
RH
3655 t = make_node (OMP_RETURN);
3656 OMP_RETURN_NOWAIT (t) = !!find_omp_clause (OMP_SINGLE_CLAUSES (single_stmt),
3657 OMP_CLAUSE_NOWAIT);
50674e96 3658 append_to_statement_list (t, &BIND_EXPR_BODY (bind));
777f7f9a 3659
953ff289 3660 pop_gimplify_context (bind);
50674e96 3661
953ff289
DN
3662 BIND_EXPR_VARS (bind) = chainon (BIND_EXPR_VARS (bind), ctx->block_vars);
3663 BLOCK_VARS (block) = BIND_EXPR_VARS (bind);
3664}
3665
50674e96 3666
953ff289
DN
3667/* Expand code for an OpenMP master directive. */
3668
3669static void
50674e96 3670lower_omp_master (tree *stmt_p, omp_context *ctx)
953ff289
DN
3671{
3672 tree bind, block, stmt = *stmt_p, lab = NULL, x;
3673
3674 push_gimplify_context ();
3675
3676 block = make_node (BLOCK);
777f7f9a 3677 *stmt_p = bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, block);
50674e96 3678 TREE_SIDE_EFFECTS (bind) = 1;
953ff289 3679
777f7f9a
RH
3680 append_to_statement_list (stmt, &BIND_EXPR_BODY (bind));
3681
953ff289
DN
3682 x = built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM];
3683 x = build_function_call_expr (x, NULL);
3684 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
3685 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
3686 gimplify_and_add (x, &BIND_EXPR_BODY (bind));
3687
50674e96 3688 lower_omp (&OMP_MASTER_BODY (stmt), ctx);
777f7f9a 3689 maybe_catch_exception (&OMP_MASTER_BODY (stmt));
953ff289 3690 append_to_statement_list (OMP_MASTER_BODY (stmt), &BIND_EXPR_BODY (bind));
777f7f9a 3691 OMP_MASTER_BODY (stmt) = NULL;
953ff289
DN
3692
3693 x = build1 (LABEL_EXPR, void_type_node, lab);
3694 gimplify_and_add (x, &BIND_EXPR_BODY (bind));
777f7f9a
RH
3695
3696 x = make_node (OMP_RETURN);
3697 OMP_RETURN_NOWAIT (x) = 1;
50674e96 3698 append_to_statement_list (x, &BIND_EXPR_BODY (bind));
777f7f9a 3699
953ff289 3700 pop_gimplify_context (bind);
50674e96 3701
953ff289
DN
3702 BIND_EXPR_VARS (bind) = chainon (BIND_EXPR_VARS (bind), ctx->block_vars);
3703 BLOCK_VARS (block) = BIND_EXPR_VARS (bind);
3704}
3705
50674e96 3706
953ff289
DN
3707/* Expand code for an OpenMP ordered directive. */
3708
3709static void
50674e96 3710lower_omp_ordered (tree *stmt_p, omp_context *ctx)
953ff289
DN
3711{
3712 tree bind, block, stmt = *stmt_p, x;
3713
3714 push_gimplify_context ();
3715
3716 block = make_node (BLOCK);
777f7f9a 3717 *stmt_p = bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, block);
50674e96 3718 TREE_SIDE_EFFECTS (bind) = 1;
953ff289 3719
777f7f9a
RH
3720 append_to_statement_list (stmt, &BIND_EXPR_BODY (bind));
3721
953ff289
DN
3722 x = built_in_decls[BUILT_IN_GOMP_ORDERED_START];
3723 x = build_function_call_expr (x, NULL);
3724 gimplify_and_add (x, &BIND_EXPR_BODY (bind));
3725
50674e96 3726 lower_omp (&OMP_ORDERED_BODY (stmt), ctx);
777f7f9a 3727 maybe_catch_exception (&OMP_ORDERED_BODY (stmt));
953ff289 3728 append_to_statement_list (OMP_ORDERED_BODY (stmt), &BIND_EXPR_BODY (bind));
777f7f9a 3729 OMP_ORDERED_BODY (stmt) = NULL;
953ff289
DN
3730
3731 x = built_in_decls[BUILT_IN_GOMP_ORDERED_END];
3732 x = build_function_call_expr (x, NULL);
3733 gimplify_and_add (x, &BIND_EXPR_BODY (bind));
777f7f9a
RH
3734
3735 x = make_node (OMP_RETURN);
3736 OMP_RETURN_NOWAIT (x) = 1;
50674e96 3737 append_to_statement_list (x, &BIND_EXPR_BODY (bind));
777f7f9a 3738
953ff289 3739 pop_gimplify_context (bind);
50674e96 3740
953ff289
DN
3741 BIND_EXPR_VARS (bind) = chainon (BIND_EXPR_VARS (bind), ctx->block_vars);
3742 BLOCK_VARS (block) = BIND_EXPR_VARS (bind);
3743}
3744
953ff289
DN
3745
3746/* Gimplify an OMP_CRITICAL statement. This is a relatively simple
3747 substitution of a couple of function calls. But in the NAMED case,
3748 requires that languages coordinate a symbol name. It is therefore
3749 best put here in common code. */
3750
3751static GTY((param1_is (tree), param2_is (tree)))
3752 splay_tree critical_name_mutexes;
3753
3754static void
50674e96 3755lower_omp_critical (tree *stmt_p, omp_context *ctx)
953ff289
DN
3756{
3757 tree bind, block, stmt = *stmt_p;
50674e96 3758 tree t, lock, unlock, name;
953ff289
DN
3759
3760 name = OMP_CRITICAL_NAME (stmt);
3761 if (name)
3762 {
3763 tree decl, args;
3764 splay_tree_node n;
3765
3766 if (!critical_name_mutexes)
3767 critical_name_mutexes
3768 = splay_tree_new_ggc (splay_tree_compare_pointers);
3769
3770 n = splay_tree_lookup (critical_name_mutexes, (splay_tree_key) name);
3771 if (n == NULL)
3772 {
3773 char *new_str;
3774
3775 decl = create_tmp_var_raw (ptr_type_node, NULL);
3776
3777 new_str = ACONCAT ((".gomp_critical_user_",
3778 IDENTIFIER_POINTER (name), NULL));
3779 DECL_NAME (decl) = get_identifier (new_str);
3780 TREE_PUBLIC (decl) = 1;
3781 TREE_STATIC (decl) = 1;
3782 DECL_COMMON (decl) = 1;
3783 DECL_ARTIFICIAL (decl) = 1;
3784 DECL_IGNORED_P (decl) = 1;
3785 cgraph_varpool_finalize_decl (decl);
3786
3787 splay_tree_insert (critical_name_mutexes, (splay_tree_key) name,
3788 (splay_tree_value) decl);
3789 }
3790 else
3791 decl = (tree) n->value;
3792
3793 args = tree_cons (NULL, build_fold_addr_expr (decl), NULL);
3794 lock = built_in_decls[BUILT_IN_GOMP_CRITICAL_NAME_START];
3795 lock = build_function_call_expr (lock, args);
3796
3797 args = tree_cons (NULL, build_fold_addr_expr (decl), NULL);
3798 unlock = built_in_decls[BUILT_IN_GOMP_CRITICAL_NAME_END];
3799 unlock = build_function_call_expr (unlock, args);
3800 }
3801 else
3802 {
3803 lock = built_in_decls[BUILT_IN_GOMP_CRITICAL_START];
3804 lock = build_function_call_expr (lock, NULL);
3805
3806 unlock = built_in_decls[BUILT_IN_GOMP_CRITICAL_END];
3807 unlock = build_function_call_expr (unlock, NULL);
3808 }
3809
3810 push_gimplify_context ();
3811
3812 block = make_node (BLOCK);
777f7f9a 3813 *stmt_p = bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, block);
50674e96 3814 TREE_SIDE_EFFECTS (bind) = 1;
953ff289 3815
777f7f9a
RH
3816 append_to_statement_list (stmt, &BIND_EXPR_BODY (bind));
3817
953ff289
DN
3818 gimplify_and_add (lock, &BIND_EXPR_BODY (bind));
3819
50674e96 3820 lower_omp (&OMP_CRITICAL_BODY (stmt), ctx);
953ff289
DN
3821 maybe_catch_exception (&OMP_CRITICAL_BODY (stmt));
3822 append_to_statement_list (OMP_CRITICAL_BODY (stmt), &BIND_EXPR_BODY (bind));
777f7f9a 3823 OMP_CRITICAL_BODY (stmt) = NULL;
953ff289
DN
3824
3825 gimplify_and_add (unlock, &BIND_EXPR_BODY (bind));
777f7f9a
RH
3826
3827 t = make_node (OMP_RETURN);
3828 OMP_RETURN_NOWAIT (t) = 1;
50674e96 3829 append_to_statement_list (t, &BIND_EXPR_BODY (bind));
953ff289
DN
3830
3831 pop_gimplify_context (bind);
3832 BIND_EXPR_VARS (bind) = chainon (BIND_EXPR_VARS (bind), ctx->block_vars);
3833 BLOCK_VARS (block) = BIND_EXPR_VARS (bind);
50674e96
DN
3834}
3835
3836
3837/* A subroutine of lower_omp_for. Generate code to emit the predicate
3838 for a lastprivate clause. Given a loop control predicate of (V
3839 cond N2), we gate the clause on (!(V cond N2)). The lowered form
3840 is appended to *BODY_P. */
3841
3842static void
3843lower_omp_for_lastprivate (struct omp_for_data *fd, tree *body_p,
3844 struct omp_context *ctx)
3845{
3846 tree clauses, cond;
3847 enum tree_code cond_code;
3848
3849 cond_code = fd->cond_code;
3850 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
3851
3852 /* When possible, use a strict equality expression. This can let VRP
3853 type optimizations deduce the value and remove a copy. */
3854 if (host_integerp (fd->step, 0))
3855 {
3856 HOST_WIDE_INT step = TREE_INT_CST_LOW (fd->step);
3857 if (step == 1 || step == -1)
3858 cond_code = EQ_EXPR;
3859 }
3860
3861 cond = build2 (cond_code, boolean_type_node, fd->v, fd->n2);
3862
3863 clauses = OMP_FOR_CLAUSES (fd->for_stmt);
3864 lower_lastprivate_clauses (clauses, cond, body_p, ctx);
3865}
3866
3867
3868/* Lower code for an OpenMP loop directive. */
3869
3870static void
3871lower_omp_for (tree *stmt_p, omp_context *ctx)
3872{
3873 tree t, stmt, ilist, dlist, new_stmt, *body_p, *rhs_p;
3874 struct omp_for_data fd;
3875
3876 stmt = *stmt_p;
3877
3878 push_gimplify_context ();
3879
3880 lower_omp (&OMP_FOR_PRE_BODY (stmt), ctx);
3881 lower_omp (&OMP_FOR_BODY (stmt), ctx);
3882
3883 /* Move declaration of temporaries in the loop body before we make
3884 it go away. */
3885 if (TREE_CODE (OMP_FOR_BODY (stmt)) == BIND_EXPR)
3886 record_vars_into (BIND_EXPR_VARS (OMP_FOR_BODY (stmt)), ctx->cb.dst_fn);
3887
3888 new_stmt = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
3889 TREE_SIDE_EFFECTS (new_stmt) = 1;
3890 body_p = &BIND_EXPR_BODY (new_stmt);
3891
3892 /* The pre-body and input clauses go before the lowered OMP_FOR. */
3893 ilist = NULL;
3894 dlist = NULL;
3895 append_to_statement_list (OMP_FOR_PRE_BODY (stmt), body_p);
3896 lower_rec_input_clauses (OMP_FOR_CLAUSES (stmt), body_p, &dlist, ctx);
3897
3898 /* Lower the header expressions. At this point, we can assume that
3899 the header is of the form:
3900
3901 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
3902
3903 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
3904 using the .omp_data_s mapping, if needed. */
3905 rhs_p = &TREE_OPERAND (OMP_FOR_INIT (stmt), 1);
3906 if (!is_gimple_min_invariant (*rhs_p))
3907 *rhs_p = get_formal_tmp_var (*rhs_p, body_p);
3908
3909 rhs_p = &TREE_OPERAND (OMP_FOR_COND (stmt), 1);
3910 if (!is_gimple_min_invariant (*rhs_p))
3911 *rhs_p = get_formal_tmp_var (*rhs_p, body_p);
3912
3913 rhs_p = &TREE_OPERAND (TREE_OPERAND (OMP_FOR_INCR (stmt), 1), 1);
3914 if (!is_gimple_min_invariant (*rhs_p))
3915 *rhs_p = get_formal_tmp_var (*rhs_p, body_p);
3916
3917 /* Once lowered, extract the bounds and clauses. */
3918 extract_omp_for_data (stmt, &fd);
3919
50674e96
DN
3920 append_to_statement_list (stmt, body_p);
3921
777f7f9a
RH
3922 append_to_statement_list (OMP_FOR_BODY (stmt), body_p);
3923
3924 t = make_node (OMP_CONTINUE);
3925 append_to_statement_list (t, body_p);
3926
50674e96
DN
3927 /* After the loop, add exit clauses. */
3928 lower_omp_for_lastprivate (&fd, &dlist, ctx);
3929 lower_reduction_clauses (OMP_FOR_CLAUSES (stmt), body_p, ctx);
3930 append_to_statement_list (dlist, body_p);
3931
4a31b7ee
JJ
3932 maybe_catch_exception (body_p);
3933
777f7f9a
RH
3934 /* Region exit marker goes at the end of the loop body. */
3935 t = make_node (OMP_RETURN);
3936 OMP_RETURN_NOWAIT (t) = fd.have_nowait;
3937 append_to_statement_list (t, body_p);
50674e96
DN
3938
3939 pop_gimplify_context (NULL_TREE);
3940 record_vars_into (ctx->block_vars, ctx->cb.dst_fn);
3941
777f7f9a 3942 OMP_FOR_BODY (stmt) = NULL_TREE;
50674e96
DN
3943 OMP_FOR_PRE_BODY (stmt) = NULL_TREE;
3944 *stmt_p = new_stmt;
953ff289
DN
3945}
3946
50674e96
DN
3947
3948/* Lower the OpenMP parallel directive in *STMT_P. CTX holds context
3949 information for the directive. */
3950
3951static void
3952lower_omp_parallel (tree *stmt_p, omp_context *ctx)
3953{
3954 tree clauses, par_bind, par_body, new_body, bind;
3955 tree olist, ilist, par_olist, par_ilist;
3956 tree stmt, child_fn, t;
3957
3958 stmt = *stmt_p;
3959
3960 clauses = OMP_PARALLEL_CLAUSES (stmt);
3961 par_bind = OMP_PARALLEL_BODY (stmt);
3962 par_body = BIND_EXPR_BODY (par_bind);
3963 child_fn = ctx->cb.dst_fn;
3964
3965 push_gimplify_context ();
3966
3967 par_olist = NULL_TREE;
3968 par_ilist = NULL_TREE;
3969 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx);
3970 lower_omp (&par_body, ctx);
50674e96
DN
3971 lower_reduction_clauses (clauses, &par_olist, ctx);
3972
3973 /* Declare all the variables created by mapping and the variables
3974 declared in the scope of the parallel body. */
3975 record_vars_into (ctx->block_vars, child_fn);
3976 record_vars_into (BIND_EXPR_VARS (par_bind), child_fn);
3977
3978 if (ctx->record_type)
3979 {
3980 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_data_o");
3981 OMP_PARALLEL_DATA_ARG (stmt) = ctx->sender_decl;
3982 }
3983
3984 olist = NULL_TREE;
3985 ilist = NULL_TREE;
3986 lower_send_clauses (clauses, &ilist, &olist, ctx);
3987 lower_send_shared_vars (&ilist, &olist, ctx);
3988
3989 /* Once all the expansions are done, sequence all the different
3990 fragments inside OMP_PARALLEL_BODY. */
3991 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
3992 append_to_statement_list (ilist, &BIND_EXPR_BODY (bind));
3993
3994 new_body = alloc_stmt_list ();
3995
3996 if (ctx->record_type)
3997 {
3998 t = build_fold_addr_expr (ctx->sender_decl);
3999 t = build2 (MODIFY_EXPR, void_type_node, ctx->receiver_decl, t);
4000 append_to_statement_list (t, &new_body);
4001 }
4002
4003 append_to_statement_list (par_ilist, &new_body);
4004 append_to_statement_list (par_body, &new_body);
4005 append_to_statement_list (par_olist, &new_body);
4a31b7ee 4006 maybe_catch_exception (&new_body);
777f7f9a 4007 t = make_node (OMP_RETURN);
50674e96
DN
4008 append_to_statement_list (t, &new_body);
4009 OMP_PARALLEL_BODY (stmt) = new_body;
4010
4011 append_to_statement_list (stmt, &BIND_EXPR_BODY (bind));
4012 append_to_statement_list (olist, &BIND_EXPR_BODY (bind));
4013
4014 *stmt_p = bind;
4015
4016 pop_gimplify_context (NULL_TREE);
4017}
4018
4019
953ff289
DN
4020/* Pass *TP back through the gimplifier within the context determined by WI.
4021 This handles replacement of DECL_VALUE_EXPR, as well as adjusting the
4022 flags on ADDR_EXPR. */
4023
4024static void
50674e96 4025lower_regimplify (tree *tp, struct walk_stmt_info *wi)
953ff289
DN
4026{
4027 enum gimplify_status gs;
4028 tree pre = NULL;
4029
4030 if (wi->is_lhs)
4031 gs = gimplify_expr (tp, &pre, NULL, is_gimple_lvalue, fb_lvalue);
4032 else if (wi->val_only)
4033 gs = gimplify_expr (tp, &pre, NULL, is_gimple_val, fb_rvalue);
4034 else
4035 gs = gimplify_expr (tp, &pre, NULL, is_gimple_formal_tmp_var, fb_rvalue);
4036 gcc_assert (gs == GS_ALL_DONE);
4037
4038 if (pre)
4039 tsi_link_before (&wi->tsi, pre, TSI_SAME_STMT);
4040}
4041
50674e96
DN
4042
4043/* Callback for walk_stmts. Lower the OpenMP directive pointed by TP. */
4044
953ff289 4045static tree
50674e96 4046lower_omp_1 (tree *tp, int *walk_subtrees, void *data)
953ff289
DN
4047{
4048 struct walk_stmt_info *wi = data;
4049 omp_context *ctx = wi->info;
4050 tree t = *tp;
4051
50674e96
DN
4052 /* If we have issued syntax errors, avoid doing any heavy lifting.
4053 Just replace the OpenMP directives with a NOP to avoid
4054 confusing RTL expansion. */
4055 if (errorcount && OMP_DIRECTIVE_P (*tp))
4056 {
4057 *tp = build_empty_stmt ();
4058 return NULL_TREE;
4059 }
4060
953ff289
DN
4061 *walk_subtrees = 0;
4062 switch (TREE_CODE (*tp))
4063 {
4064 case OMP_PARALLEL:
4065 ctx = maybe_lookup_ctx (t);
50674e96 4066 lower_omp_parallel (tp, ctx);
953ff289
DN
4067 break;
4068
4069 case OMP_FOR:
4070 ctx = maybe_lookup_ctx (t);
4071 gcc_assert (ctx);
50674e96 4072 lower_omp_for (tp, ctx);
953ff289
DN
4073 break;
4074
4075 case OMP_SECTIONS:
4076 ctx = maybe_lookup_ctx (t);
4077 gcc_assert (ctx);
50674e96 4078 lower_omp_sections (tp, ctx);
953ff289
DN
4079 break;
4080
4081 case OMP_SINGLE:
4082 ctx = maybe_lookup_ctx (t);
4083 gcc_assert (ctx);
50674e96 4084 lower_omp_single (tp, ctx);
953ff289
DN
4085 break;
4086
4087 case OMP_MASTER:
4088 ctx = maybe_lookup_ctx (t);
4089 gcc_assert (ctx);
50674e96 4090 lower_omp_master (tp, ctx);
953ff289
DN
4091 break;
4092
4093 case OMP_ORDERED:
4094 ctx = maybe_lookup_ctx (t);
4095 gcc_assert (ctx);
50674e96 4096 lower_omp_ordered (tp, ctx);
953ff289
DN
4097 break;
4098
4099 case OMP_CRITICAL:
4100 ctx = maybe_lookup_ctx (t);
4101 gcc_assert (ctx);
50674e96 4102 lower_omp_critical (tp, ctx);
953ff289
DN
4103 break;
4104
4105 case VAR_DECL:
4106 if (ctx && DECL_HAS_VALUE_EXPR_P (t))
50674e96 4107 lower_regimplify (tp, wi);
953ff289
DN
4108 break;
4109
4110 case ADDR_EXPR:
4111 if (ctx)
50674e96 4112 lower_regimplify (tp, wi);
953ff289
DN
4113 break;
4114
4115 case ARRAY_REF:
4116 case ARRAY_RANGE_REF:
4117 case REALPART_EXPR:
4118 case IMAGPART_EXPR:
4119 case COMPONENT_REF:
4120 case VIEW_CONVERT_EXPR:
4121 if (ctx)
50674e96 4122 lower_regimplify (tp, wi);
953ff289
DN
4123 break;
4124
4125 case INDIRECT_REF:
4126 if (ctx)
4127 {
4128 wi->is_lhs = false;
4129 wi->val_only = true;
50674e96 4130 lower_regimplify (&TREE_OPERAND (t, 0), wi);
953ff289
DN
4131 }
4132 break;
4133
4134 default:
4135 if (!TYPE_P (t) && !DECL_P (t))
4136 *walk_subtrees = 1;
4137 break;
4138 }
4139
4140 return NULL_TREE;
4141}
4142
4143static void
50674e96 4144lower_omp (tree *stmt_p, omp_context *ctx)
953ff289
DN
4145{
4146 struct walk_stmt_info wi;
4147
4148 memset (&wi, 0, sizeof (wi));
50674e96 4149 wi.callback = lower_omp_1;
953ff289
DN
4150 wi.info = ctx;
4151 wi.val_only = true;
4152 wi.want_locations = true;
4153
4154 walk_stmts (&wi, stmt_p);
4155}
4156\f
4157/* Main entry point. */
4158
c2924966 4159static unsigned int
953ff289
DN
4160execute_lower_omp (void)
4161{
4162 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
4163 delete_omp_context);
4164
4165 scan_omp (&DECL_SAVED_TREE (current_function_decl), NULL);
4166 gcc_assert (parallel_nesting_level == 0);
4167
4168 if (all_contexts->root)
50674e96 4169 lower_omp (&DECL_SAVED_TREE (current_function_decl), NULL);
953ff289 4170
50674e96
DN
4171 if (all_contexts)
4172 {
4173 splay_tree_delete (all_contexts);
4174 all_contexts = NULL;
4175 }
c2924966 4176 return 0;
953ff289
DN
4177}
4178
4179static bool
4180gate_lower_omp (void)
4181{
4182 return flag_openmp != 0;
4183}
4184
4185struct tree_opt_pass pass_lower_omp =
4186{
4187 "omplower", /* name */
4188 gate_lower_omp, /* gate */
4189 execute_lower_omp, /* execute */
4190 NULL, /* sub */
4191 NULL, /* next */
4192 0, /* static_pass_number */
4193 0, /* tv_id */
4194 PROP_gimple_any, /* properties_required */
4195 PROP_gimple_lomp, /* properties_provided */
4196 0, /* properties_destroyed */
4197 0, /* todo_flags_start */
4198 TODO_dump_func, /* todo_flags_finish */
4199 0 /* letter */
4200};
953ff289
DN
4201\f
4202/* The following is a utility to diagnose OpenMP structured block violations.
777f7f9a
RH
4203 It is not part of the "omplower" pass, as that's invoked too late. It
4204 should be invoked by the respective front ends after gimplification. */
953ff289
DN
4205
4206static splay_tree all_labels;
4207
4208/* Check for mismatched contexts and generate an error if needed. Return
4209 true if an error is detected. */
4210
4211static bool
4212diagnose_sb_0 (tree *stmt_p, tree branch_ctx, tree label_ctx)
4213{
4214 bool exit_p = true;
4215
4216 if ((label_ctx ? TREE_VALUE (label_ctx) : NULL) == branch_ctx)
4217 return false;
4218
4219 /* Try to avoid confusing the user by producing and error message
4220 with correct "exit" or "enter" verbage. We prefer "exit"
4221 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
4222 if (branch_ctx == NULL)
4223 exit_p = false;
4224 else
4225 {
4226 while (label_ctx)
4227 {
4228 if (TREE_VALUE (label_ctx) == branch_ctx)
4229 {
4230 exit_p = false;
4231 break;
4232 }
4233 label_ctx = TREE_CHAIN (label_ctx);
4234 }
4235 }
4236
4237 if (exit_p)
4238 error ("invalid exit from OpenMP structured block");
4239 else
4240 error ("invalid entry to OpenMP structured block");
4241
4242 *stmt_p = build_empty_stmt ();
4243 return true;
4244}
4245
4246/* Pass 1: Create a minimal tree of OpenMP structured blocks, and record
4247 where in the tree each label is found. */
4248
4249static tree
4250diagnose_sb_1 (tree *tp, int *walk_subtrees, void *data)
4251{
4252 struct walk_stmt_info *wi = data;
4253 tree context = (tree) wi->info;
4254 tree inner_context;
4255 tree t = *tp;
4256
4257 *walk_subtrees = 0;
4258 switch (TREE_CODE (t))
4259 {
4260 case OMP_PARALLEL:
4261 case OMP_SECTIONS:
4262 case OMP_SINGLE:
4263 walk_tree (&OMP_CLAUSES (t), diagnose_sb_1, wi, NULL);
4264 /* FALLTHRU */
4265 case OMP_SECTION:
4266 case OMP_MASTER:
4267 case OMP_ORDERED:
4268 case OMP_CRITICAL:
4269 /* The minimal context here is just a tree of statements. */
4270 inner_context = tree_cons (NULL, t, context);
4271 wi->info = inner_context;
4272 walk_stmts (wi, &OMP_BODY (t));
4273 wi->info = context;
4274 break;
4275
4276 case OMP_FOR:
4277 walk_tree (&OMP_FOR_CLAUSES (t), diagnose_sb_1, wi, NULL);
4278 inner_context = tree_cons (NULL, t, context);
4279 wi->info = inner_context;
4280 walk_tree (&OMP_FOR_INIT (t), diagnose_sb_1, wi, NULL);
4281 walk_tree (&OMP_FOR_COND (t), diagnose_sb_1, wi, NULL);
4282 walk_tree (&OMP_FOR_INCR (t), diagnose_sb_1, wi, NULL);
4283 walk_stmts (wi, &OMP_FOR_PRE_BODY (t));
4284 walk_stmts (wi, &OMP_FOR_BODY (t));
4285 wi->info = context;
4286 break;
4287
4288 case LABEL_EXPR:
4289 splay_tree_insert (all_labels, (splay_tree_key) LABEL_EXPR_LABEL (t),
4290 (splay_tree_value) context);
4291 break;
4292
4293 default:
4294 break;
4295 }
4296
4297 return NULL_TREE;
4298}
4299
4300/* Pass 2: Check each branch and see if its context differs from that of
4301 the destination label's context. */
4302
4303static tree
4304diagnose_sb_2 (tree *tp, int *walk_subtrees, void *data)
4305{
4306 struct walk_stmt_info *wi = data;
4307 tree context = (tree) wi->info;
4308 splay_tree_node n;
4309 tree t = *tp;
4310
4311 *walk_subtrees = 0;
4312 switch (TREE_CODE (t))
4313 {
4314 case OMP_PARALLEL:
4315 case OMP_SECTIONS:
4316 case OMP_SINGLE:
4317 walk_tree (&OMP_CLAUSES (t), diagnose_sb_2, wi, NULL);
4318 /* FALLTHRU */
4319 case OMP_SECTION:
4320 case OMP_MASTER:
4321 case OMP_ORDERED:
4322 case OMP_CRITICAL:
4323 wi->info = t;
4324 walk_stmts (wi, &OMP_BODY (t));
4325 wi->info = context;
4326 break;
4327
4328 case OMP_FOR:
4329 walk_tree (&OMP_FOR_CLAUSES (t), diagnose_sb_2, wi, NULL);
4330 wi->info = t;
4331 walk_tree (&OMP_FOR_INIT (t), diagnose_sb_2, wi, NULL);
4332 walk_tree (&OMP_FOR_COND (t), diagnose_sb_2, wi, NULL);
4333 walk_tree (&OMP_FOR_INCR (t), diagnose_sb_2, wi, NULL);
4334 walk_stmts (wi, &OMP_FOR_PRE_BODY (t));
4335 walk_stmts (wi, &OMP_FOR_BODY (t));
4336 wi->info = context;
4337 break;
4338
4339 case GOTO_EXPR:
4340 {
4341 tree lab = GOTO_DESTINATION (t);
4342 if (TREE_CODE (lab) != LABEL_DECL)
4343 break;
4344
4345 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
4346 diagnose_sb_0 (tp, context, n ? (tree) n->value : NULL_TREE);
4347 }
4348 break;
4349
4350 case SWITCH_EXPR:
4351 {
4352 tree vec = SWITCH_LABELS (t);
4353 int i, len = TREE_VEC_LENGTH (vec);
4354 for (i = 0; i < len; ++i)
4355 {
4356 tree lab = CASE_LABEL (TREE_VEC_ELT (vec, i));
4357 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
4358 if (diagnose_sb_0 (tp, context, (tree) n->value))
4359 break;
4360 }
4361 }
4362 break;
4363
4364 case RETURN_EXPR:
4365 diagnose_sb_0 (tp, context, NULL_TREE);
4366 break;
4367
4368 default:
4369 break;
4370 }
4371
4372 return NULL_TREE;
4373}
4374
4375void
4376diagnose_omp_structured_block_errors (tree fndecl)
4377{
4378 tree save_current = current_function_decl;
4379 struct walk_stmt_info wi;
4380
4381 current_function_decl = fndecl;
4382
4383 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
4384
4385 memset (&wi, 0, sizeof (wi));
4386 wi.callback = diagnose_sb_1;
4387 walk_stmts (&wi, &DECL_SAVED_TREE (fndecl));
4388
4389 memset (&wi, 0, sizeof (wi));
4390 wi.callback = diagnose_sb_2;
4391 wi.want_locations = true;
4392 wi.want_return_expr = true;
4393 walk_stmts (&wi, &DECL_SAVED_TREE (fndecl));
4394
4395 splay_tree_delete (all_labels);
4396 all_labels = NULL;
4397
4398 current_function_decl = save_current;
4399}
4400
4401#include "gt-omp-low.h"