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