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