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