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