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