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