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