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