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