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>
6 Copyright (C) 2005, 2006 Free Software Foundation, Inc.
8 This file is part of GCC.
10 GCC is free software; you can redistribute it and/or modify it under
11 the terms of the GNU General Public License as published by the Free
12 Software Foundation; either version 2, or (at your option) any later
15 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
16 WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 You should have received a copy of the GNU General Public License
21 along with GCC; see the file COPYING. If not, write to the Free
22 Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
27 #include "coretypes.h"
31 #include "tree-gimple.h"
32 #include "tree-inline.h"
33 #include "langhooks.h"
34 #include "diagnostic.h"
35 #include "tree-flow.h"
41 #include "tree-pass.h"
46 /* Lowering of OpenMP parallel and workshare constructs proceeds in two
47 phases. The first phase scans the function looking for OMP statements
48 and then for variables that must be replaced to satisfy data sharing
49 clauses. The second phase expands code for the constructs, as well as
50 re-gimplifying things when variables have been replaced with complex
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. */
57 /* Context structure. Used to store information about each parallel
58 directive in the code. */
60 typedef struct omp_context
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. */
68 /* The tree of contexts corresponding to the encountered constructs. */
69 struct omp_context
*outer
;
72 /* Map variables to fields in a structure that allows communication
73 between sending and receiving threads. */
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. */
83 /* What to do with variables with implicitly determined sharing
85 enum omp_clause_default_kind default_kind
;
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. */
92 /* True if this parallel directive is nested within another. */
97 /* A structure describing the main elements of a parallel loop. */
101 tree v
, n1
, n2
, step
, chunk_size
, for_stmt
;
102 enum tree_code cond_code
;
104 bool have_nowait
, have_ordered
;
105 enum omp_clause_schedule_kind sched_kind
;
109 static splay_tree all_contexts
;
110 static int parallel_nesting_level
;
111 struct omp_region
*root_omp_region
;
113 static void scan_omp (tree
*, omp_context
*);
114 static void lower_omp (tree
*, omp_context
*);
116 /* Find an OpenMP clause of type KIND within CLAUSES. */
119 find_omp_clause (tree clauses
, enum tree_code kind
)
121 for (; clauses
; clauses
= OMP_CLAUSE_CHAIN (clauses
))
122 if (OMP_CLAUSE_CODE (clauses
) == kind
)
128 /* Return true if CTX is for an omp parallel. */
131 is_parallel_ctx (omp_context
*ctx
)
133 return TREE_CODE (ctx
->stmt
) == OMP_PARALLEL
;
137 /* Return true if REGION is a combined parallel+workshare region. */
140 is_combined_parallel (struct omp_region
*region
)
142 return region
->is_combined_parallel
;
146 /* Extract the header elements of parallel loop FOR_STMT and store
150 extract_omp_for_data (tree for_stmt
, struct omp_for_data
*fd
)
154 fd
->for_stmt
= for_stmt
;
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);
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
)
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
;
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
;
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
))
195 fd
->step
= TREE_OPERAND (t
, 1);
198 fd
->step
= TREE_OPERAND (t
, 1);
199 fd
->step
= fold_build1 (NEGATE_EXPR
, TREE_TYPE (fd
->step
), fd
->step
);
205 fd
->have_nowait
= fd
->have_ordered
= false;
206 fd
->sched_kind
= OMP_CLAUSE_SCHEDULE_STATIC
;
207 fd
->chunk_size
= NULL_TREE
;
209 for (t
= OMP_FOR_CLAUSES (for_stmt
); t
; t
= OMP_CLAUSE_CHAIN (t
))
210 switch (OMP_CLAUSE_CODE (t
))
212 case OMP_CLAUSE_NOWAIT
:
213 fd
->have_nowait
= true;
215 case OMP_CLAUSE_ORDERED
:
216 fd
->have_ordered
= true;
218 case OMP_CLAUSE_SCHEDULE
:
219 fd
->sched_kind
= OMP_CLAUSE_SCHEDULE_KIND (t
);
220 fd
->chunk_size
= OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t
);
226 if (fd
->sched_kind
== OMP_CLAUSE_SCHEDULE_RUNTIME
)
227 gcc_assert (fd
->chunk_size
== NULL
);
228 else if (fd
->chunk_size
== NULL
)
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
;
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.
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:
250 #pragma omp parallel for schedule (guided, i * 4)
255 # BLOCK 2 (PAR_ENTRY_BB)
257 #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
259 # BLOCK 3 (WS_ENTRY_BB)
260 .omp_data_i = &.omp_data_o;
261 D.1667 = .omp_data_i->i;
263 #pragma omp for schedule (guided, D.1598)
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.
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
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. */
282 workshare_safe_to_combine_p (basic_block par_entry_bb
, basic_block ws_entry_bb
)
284 struct omp_for_data fd
;
285 tree par_stmt
, ws_stmt
;
287 par_stmt
= last_stmt (par_entry_bb
);
288 ws_stmt
= last_stmt (ws_entry_bb
);
290 if (TREE_CODE (ws_stmt
) == OMP_SECTIONS
)
293 gcc_assert (TREE_CODE (ws_stmt
) == OMP_FOR
);
295 extract_omp_for_data (ws_stmt
, &fd
);
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
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
)))
312 /* Collect additional arguments needed to emit a combined
313 parallel+workshare call. WS_STMT is the workshare directive being
317 get_ws_args_for (tree ws_stmt
)
321 if (TREE_CODE (ws_stmt
) == OMP_FOR
)
323 struct omp_for_data fd
;
326 extract_omp_for_data (ws_stmt
, &fd
);
331 t
= fold_convert (long_integer_type_node
, fd
.chunk_size
);
332 ws_args
= tree_cons (NULL
, t
, ws_args
);
335 t
= fold_convert (long_integer_type_node
, fd
.step
);
336 ws_args
= tree_cons (NULL
, t
, ws_args
);
338 t
= fold_convert (long_integer_type_node
, fd
.n2
);
339 ws_args
= tree_cons (NULL
, t
, ws_args
);
341 t
= fold_convert (long_integer_type_node
, fd
.n1
);
342 ws_args
= tree_cons (NULL
, t
, ws_args
);
346 else if (TREE_CODE (ws_stmt
) == OMP_SECTIONS
)
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
);
358 /* Discover whether REGION is a combined parallel+workshare region. */
361 determine_parallel_type (struct omp_region
*region
)
363 basic_block par_entry_bb
, par_exit_bb
;
364 basic_block ws_entry_bb
, ws_exit_bb
;
366 if (region
== NULL
|| region
->inner
== NULL
)
369 /* We only support parallel+for and parallel+sections. */
370 if (region
->type
!= OMP_PARALLEL
371 || (region
->inner
->type
!= OMP_FOR
372 && region
->inner
->type
!= OMP_SECTIONS
))
375 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
376 WS_EXIT_BB -> PAR_EXIT_BB. */
377 par_entry_bb
= region
->entry
;
378 par_exit_bb
= region
->exit
;
379 ws_entry_bb
= region
->inner
->entry
;
380 ws_exit_bb
= region
->inner
->exit
;
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
))
386 tree ws_stmt
= last_stmt (region
->inner
->entry
);
388 if (region
->inner
->type
== OMP_FOR
)
390 /* If this is a combined parallel loop, we need to determine
391 whether or not to use the combined library calls. There
392 are two cases where we do not apply the transformation:
393 static loops and any kind of ordered loop. In the first
394 case, we already open code the loop so there is no need
395 to do anything else. In the latter case, the combined
396 parallel loop call would still need extra synchronization
397 to implement ordered semantics, so there would not be any
398 gain in using the combined call. */
399 tree clauses
= OMP_FOR_CLAUSES (ws_stmt
);
400 tree c
= find_omp_clause (clauses
, OMP_CLAUSE_SCHEDULE
);
402 || OMP_CLAUSE_SCHEDULE_KIND (c
) == OMP_CLAUSE_SCHEDULE_STATIC
403 || find_omp_clause (clauses
, OMP_CLAUSE_ORDERED
))
405 region
->is_combined_parallel
= false;
406 region
->inner
->is_combined_parallel
= false;
411 region
->is_combined_parallel
= true;
412 region
->inner
->is_combined_parallel
= true;
413 region
->ws_args
= get_ws_args_for (ws_stmt
);
418 /* Return true if EXPR is variable sized. */
421 is_variable_sized (tree expr
)
423 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr
)));
426 /* Return true if DECL is a reference type. */
429 is_reference (tree decl
)
431 return lang_hooks
.decls
.omp_privatize_by_reference (decl
);
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. */
439 lookup_decl (tree var
, omp_context
*ctx
)
442 n
= splay_tree_lookup (ctx
->cb
.decl_map
, (splay_tree_key
) var
);
443 return (tree
) n
->value
;
447 maybe_lookup_decl (tree var
, omp_context
*ctx
)
450 n
= splay_tree_lookup (ctx
->cb
.decl_map
, (splay_tree_key
) var
);
451 return n
? (tree
) n
->value
: NULL_TREE
;
455 lookup_field (tree var
, omp_context
*ctx
)
458 n
= splay_tree_lookup (ctx
->field_map
, (splay_tree_key
) var
);
459 return (tree
) n
->value
;
463 maybe_lookup_field (tree var
, omp_context
*ctx
)
466 n
= splay_tree_lookup (ctx
->field_map
, (splay_tree_key
) var
);
467 return n
? (tree
) n
->value
: NULL_TREE
;
470 /* Return true if DECL should be copied by pointer. SHARED_P is true
471 if DECL is to be shared. */
474 use_pointer_for_field (tree decl
, bool shared_p
)
476 if (AGGREGATE_TYPE_P (TREE_TYPE (decl
)))
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. */
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
))
490 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
491 without analyzing the expression whether or not its location
492 is accessible to anyone else. In the case of nested parallel
493 regions it certainly may be. */
494 if (DECL_HAS_VALUE_EXPR_P (decl
))
497 /* Do not use copy-in/copy-out for variables that have their
499 if (TREE_ADDRESSABLE (decl
))
506 /* Construct a new automatic decl similar to VAR. */
509 omp_copy_decl_2 (tree var
, tree name
, tree type
, omp_context
*ctx
)
511 tree copy
= build_decl (VAR_DECL
, name
, type
);
513 TREE_ADDRESSABLE (copy
) = TREE_ADDRESSABLE (var
);
514 DECL_COMPLEX_GIMPLE_REG_P (copy
) = DECL_COMPLEX_GIMPLE_REG_P (var
);
515 DECL_ARTIFICIAL (copy
) = DECL_ARTIFICIAL (var
);
516 DECL_IGNORED_P (copy
) = DECL_IGNORED_P (var
);
517 TREE_USED (copy
) = 1;
518 DECL_CONTEXT (copy
) = current_function_decl
;
519 DECL_SEEN_IN_BIND_EXPR_P (copy
) = 1;
521 TREE_CHAIN (copy
) = ctx
->block_vars
;
522 ctx
->block_vars
= copy
;
528 omp_copy_decl_1 (tree var
, omp_context
*ctx
)
530 return omp_copy_decl_2 (var
, DECL_NAME (var
), TREE_TYPE (var
), ctx
);
533 /* Build tree nodes to access the field for VAR on the receiver side. */
536 build_receiver_ref (tree var
, bool by_ref
, omp_context
*ctx
)
538 tree x
, field
= lookup_field (var
, ctx
);
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
);
546 x
= build_fold_indirect_ref (ctx
->receiver_decl
);
547 x
= build3 (COMPONENT_REF
, TREE_TYPE (field
), x
, field
, NULL
);
549 x
= build_fold_indirect_ref (x
);
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. */
559 build_outer_var_ref (tree var
, omp_context
*ctx
)
563 if (is_global_var (var
))
565 else if (is_variable_sized (var
))
567 x
= TREE_OPERAND (DECL_VALUE_EXPR (var
), 0);
568 x
= build_outer_var_ref (x
, ctx
);
569 x
= build_fold_indirect_ref (x
);
571 else if (is_parallel_ctx (ctx
))
573 bool by_ref
= use_pointer_for_field (var
, false);
574 x
= build_receiver_ref (var
, by_ref
, ctx
);
577 x
= lookup_decl (var
, ctx
->outer
);
581 if (is_reference (var
))
582 x
= build_fold_indirect_ref (x
);
587 /* Build tree nodes to access the field for VAR on the sender side. */
590 build_sender_ref (tree var
, omp_context
*ctx
)
592 tree field
= lookup_field (var
, ctx
);
593 return build3 (COMPONENT_REF
, TREE_TYPE (field
),
594 ctx
->sender_decl
, field
, NULL
);
597 /* Add a new field for VAR inside the structure CTX->SENDER_DECL. */
600 install_var_field (tree var
, bool by_ref
, omp_context
*ctx
)
604 gcc_assert (!splay_tree_lookup (ctx
->field_map
, (splay_tree_key
) var
));
606 type
= TREE_TYPE (var
);
608 type
= build_pointer_type (type
);
610 field
= build_decl (FIELD_DECL
, DECL_NAME (var
), type
);
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
;
617 insert_field_into_struct (ctx
->record_type
, field
);
619 splay_tree_insert (ctx
->field_map
, (splay_tree_key
) var
,
620 (splay_tree_value
) field
);
624 install_var_local (tree var
, omp_context
*ctx
)
626 tree new_var
= omp_copy_decl_1 (var
, ctx
);
627 insert_decl_map (&ctx
->cb
, var
, new_var
);
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. */
635 fixup_remapped_decl (tree decl
, omp_context
*ctx
, bool private_debug
)
639 new_decl
= lookup_decl (decl
, ctx
);
641 TREE_TYPE (new_decl
) = remap_type (TREE_TYPE (decl
), &ctx
->cb
);
643 if ((!TREE_CONSTANT (DECL_SIZE (new_decl
)) || private_debug
)
644 && DECL_HAS_VALUE_EXPR_P (decl
))
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;
652 if (!TREE_CONSTANT (DECL_SIZE (new_decl
)))
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
;
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
;
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. */
672 omp_copy_decl (tree var
, copy_body_data
*cb
)
674 omp_context
*ctx
= (omp_context
*) cb
;
677 if (is_global_var (var
) || decl_function_context (var
) != ctx
->cb
.src_fn
)
680 if (TREE_CODE (var
) == LABEL_DECL
)
682 new_var
= create_artificial_label ();
683 DECL_CONTEXT (new_var
) = current_function_decl
;
684 insert_decl_map (&ctx
->cb
, var
, new_var
);
688 while (!is_parallel_ctx (ctx
))
693 new_var
= maybe_lookup_decl (var
, ctx
);
698 return error_mark_node
;
702 /* Return the parallel region associated with STMT. */
704 /* Debugging dumps for parallel regions. */
705 void dump_omp_region (FILE *, struct omp_region
*, int);
706 void debug_omp_region (struct omp_region
*);
707 void debug_all_omp_regions (void);
709 /* Dump the parallel region tree rooted at REGION. */
712 dump_omp_region (FILE *file
, struct omp_region
*region
, int indent
)
714 fprintf (file
, "%*sbb %d: %s\n", indent
, "", region
->entry
->index
,
715 tree_code_name
[region
->type
]);
718 dump_omp_region (file
, region
->inner
, indent
+ 4);
722 fprintf (file
, "%*sbb %d: OMP_CONTINUE\n", indent
, "",
723 region
->cont
->index
);
727 fprintf (file
, "%*sbb: %d: OMP_RETURN\n", indent
, "",
728 region
->exit
->index
);
730 fprintf (file
, "%*s[no exit marker]\n", indent
, "");
733 dump_omp_region (file
, region
->next
, indent
);
737 debug_omp_region (struct omp_region
*region
)
739 dump_omp_region (stderr
, region
, 0);
743 debug_all_omp_regions (void)
745 dump_omp_region (stderr
, root_omp_region
, 0);
749 /* Create a new parallel region starting at STMT inside region PARENT. */
752 new_omp_region (basic_block bb
, enum tree_code type
, struct omp_region
*parent
)
754 struct omp_region
*region
= xcalloc (1, sizeof (*region
));
756 region
->outer
= parent
;
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
;
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
;
778 /* Release the memory associated with the region tree rooted at REGION. */
781 free_omp_region_1 (struct omp_region
*region
)
783 struct omp_region
*i
, *n
;
785 for (i
= region
->inner
; i
; i
= n
)
788 free_omp_region_1 (i
);
794 /* Release the memory for the entire omp region tree. */
797 free_omp_regions (void)
799 struct omp_region
*r
, *n
;
800 for (r
= root_omp_region
; r
; r
= n
)
803 free_omp_region_1 (r
);
805 root_omp_region
= NULL
;
809 /* Create a new context, with OUTER_CTX being the surrounding context. */
812 new_omp_context (tree stmt
, omp_context
*outer_ctx
)
814 omp_context
*ctx
= XCNEW (omp_context
);
816 splay_tree_insert (all_contexts
, (splay_tree_key
) stmt
,
817 (splay_tree_value
) ctx
);
822 ctx
->outer
= outer_ctx
;
823 ctx
->cb
= outer_ctx
->cb
;
824 ctx
->cb
.block
= NULL
;
825 ctx
->depth
= outer_ctx
->depth
+ 1;
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
;
840 ctx
->cb
.decl_map
= splay_tree_new (splay_tree_compare_pointers
, 0, 0);
845 /* Destroy a omp_context data structures. Called through the splay tree
846 value delete callback. */
849 delete_omp_context (splay_tree_value value
)
851 omp_context
*ctx
= (omp_context
*) value
;
853 splay_tree_delete (ctx
->cb
.decl_map
);
856 splay_tree_delete (ctx
->field_map
);
858 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
859 it produces corrupt debug information. */
860 if (ctx
->record_type
)
863 for (t
= TYPE_FIELDS (ctx
->record_type
); t
; t
= TREE_CHAIN (t
))
864 DECL_ABSTRACT_ORIGIN (t
) = NULL
;
870 /* Fix up RECEIVER_DECL with a type that has been remapped to the child
874 fixup_child_record_type (omp_context
*ctx
)
876 tree f
, type
= ctx
->record_type
;
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
))
887 tree name
, new_fields
= NULL
;
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
;
894 for (f
= TYPE_FIELDS (ctx
->record_type
); f
; f
= TREE_CHAIN (f
))
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
;
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
);
907 TYPE_FIELDS (type
) = nreverse (new_fields
);
911 TREE_TYPE (ctx
->receiver_decl
) = build_pointer_type (type
);
914 /* Instantiate decls as necessary in CTX to satisfy the data sharing
915 specified by CLAUSES. */
918 scan_sharing_clauses (tree clauses
, omp_context
*ctx
)
921 bool scan_array_reductions
= false;
923 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
927 switch (OMP_CLAUSE_CODE (c
))
929 case OMP_CLAUSE_PRIVATE
:
930 decl
= OMP_CLAUSE_DECL (c
);
931 if (!is_variable_sized (decl
))
932 install_var_local (decl
, ctx
);
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
)
943 || is_reference (decl
))
945 install_var_field (decl
, by_ref
, ctx
);
946 install_var_local (decl
, ctx
);
949 /* We don't need to copy const scalar vars back. */
950 OMP_CLAUSE_SET_CODE (c
, OMP_CLAUSE_FIRSTPRIVATE
);
953 case OMP_CLAUSE_LASTPRIVATE
:
954 /* Let the corresponding firstprivate clause create
956 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c
))
960 case OMP_CLAUSE_FIRSTPRIVATE
:
961 case OMP_CLAUSE_REDUCTION
:
962 decl
= OMP_CLAUSE_DECL (c
);
964 if (is_variable_sized (decl
))
966 else if (is_parallel_ctx (ctx
))
968 by_ref
= use_pointer_for_field (decl
, false);
969 install_var_field (decl
, by_ref
, ctx
);
971 install_var_local (decl
, ctx
);
974 case OMP_CLAUSE_COPYPRIVATE
:
976 scan_omp (&OMP_CLAUSE_DECL (c
), ctx
->outer
);
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
);
985 case OMP_CLAUSE_DEFAULT
:
986 ctx
->default_kind
= OMP_CLAUSE_DEFAULT_KIND (c
);
990 case OMP_CLAUSE_NUM_THREADS
:
991 case OMP_CLAUSE_SCHEDULE
:
993 scan_omp (&OMP_CLAUSE_OPERAND (c
, 0), ctx
->outer
);
996 case OMP_CLAUSE_NOWAIT
:
997 case OMP_CLAUSE_ORDERED
:
1005 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
1007 switch (OMP_CLAUSE_CODE (c
))
1009 case OMP_CLAUSE_LASTPRIVATE
:
1010 /* Let the corresponding firstprivate clause create
1012 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c
))
1016 case OMP_CLAUSE_PRIVATE
:
1017 case OMP_CLAUSE_FIRSTPRIVATE
:
1018 case OMP_CLAUSE_REDUCTION
:
1019 decl
= OMP_CLAUSE_DECL (c
);
1020 if (is_variable_sized (decl
))
1021 install_var_local (decl
, ctx
);
1022 fixup_remapped_decl (decl
, ctx
,
1023 OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_PRIVATE
1024 && OMP_CLAUSE_PRIVATE_DEBUG (c
));
1025 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_REDUCTION
1026 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
1027 scan_array_reductions
= true;
1030 case OMP_CLAUSE_SHARED
:
1031 decl
= OMP_CLAUSE_DECL (c
);
1032 fixup_remapped_decl (decl
, ctx
, false);
1035 case OMP_CLAUSE_COPYPRIVATE
:
1036 case OMP_CLAUSE_COPYIN
:
1037 case OMP_CLAUSE_DEFAULT
:
1039 case OMP_CLAUSE_NUM_THREADS
:
1040 case OMP_CLAUSE_SCHEDULE
:
1041 case OMP_CLAUSE_NOWAIT
:
1042 case OMP_CLAUSE_ORDERED
:
1050 if (scan_array_reductions
)
1051 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
1052 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_REDUCTION
1053 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
1055 scan_omp (&OMP_CLAUSE_REDUCTION_INIT (c
), ctx
);
1056 scan_omp (&OMP_CLAUSE_REDUCTION_MERGE (c
), ctx
);
1060 /* Create a new name for omp child function. Returns an identifier. */
1062 static GTY(()) unsigned int tmp_ompfn_id_num
;
1065 create_omp_child_function_name (void)
1067 tree name
= DECL_ASSEMBLER_NAME (current_function_decl
);
1068 size_t len
= IDENTIFIER_LENGTH (name
);
1069 char *tmp_name
, *prefix
;
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
1076 #elif !defined NO_DOLLAR_IN_LABEL
1079 ASM_FORMAT_PRIVATE_NAME (tmp_name
, prefix
, tmp_ompfn_id_num
++);
1080 return get_identifier (tmp_name
);
1083 /* Build a decl for the omp child function. It'll not contain a body
1084 yet, just the bare decl. */
1087 create_omp_child_function (omp_context
*ctx
)
1089 tree decl
, type
, name
, t
;
1091 name
= create_omp_child_function_name ();
1092 type
= build_function_type_list (void_type_node
, ptr_type_node
, NULL_TREE
);
1094 decl
= build_decl (FUNCTION_DECL
, name
, type
);
1095 decl
= lang_hooks
.decls
.pushdecl (decl
);
1097 ctx
->cb
.dst_fn
= decl
;
1099 TREE_STATIC (decl
) = 1;
1100 TREE_USED (decl
) = 1;
1101 DECL_ARTIFICIAL (decl
) = 1;
1102 DECL_IGNORED_P (decl
) = 0;
1103 TREE_PUBLIC (decl
) = 0;
1104 DECL_UNINLINABLE (decl
) = 1;
1105 DECL_EXTERNAL (decl
) = 0;
1106 DECL_CONTEXT (decl
) = NULL_TREE
;
1107 DECL_INITIAL (decl
) = make_node (BLOCK
);
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
;
1114 t
= build_decl (PARM_DECL
, get_identifier (".omp_data_i"), ptr_type_node
);
1115 DECL_ARTIFICIAL (t
) = 1;
1116 DECL_ARG_TYPE (t
) = ptr_type_node
;
1117 DECL_CONTEXT (t
) = current_function_decl
;
1119 DECL_ARGUMENTS (decl
) = t
;
1120 ctx
->receiver_decl
= t
;
1122 /* Allocate memory for the function structure. The call to
1123 allocate_struct_function clobbers CFUN, so we need to restore
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
;
1132 /* Scan an OpenMP parallel directive. */
1135 scan_omp_parallel (tree
*stmt_p
, omp_context
*outer_ctx
)
1140 /* Ignore parallel directives with empty bodies, unless there
1141 are copyin clauses. */
1143 && empty_body_p (OMP_PARALLEL_BODY (*stmt_p
))
1144 && find_omp_clause (OMP_CLAUSES (*stmt_p
), OMP_CLAUSE_COPYIN
) == NULL
)
1146 *stmt_p
= build_empty_stmt ();
1150 ctx
= new_omp_context (*stmt_p
, outer_ctx
);
1151 if (parallel_nesting_level
> 1)
1152 ctx
->is_nested
= true;
1153 ctx
->field_map
= splay_tree_new (splay_tree_compare_pointers
, 0, 0);
1154 ctx
->default_kind
= OMP_CLAUSE_DEFAULT_SHARED
;
1155 ctx
->record_type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
1156 name
= create_tmp_var_name (".omp_data_s");
1157 name
= build_decl (TYPE_DECL
, name
, ctx
->record_type
);
1158 TYPE_NAME (ctx
->record_type
) = name
;
1159 create_omp_child_function (ctx
);
1160 OMP_PARALLEL_FN (*stmt_p
) = ctx
->cb
.dst_fn
;
1162 scan_sharing_clauses (OMP_PARALLEL_CLAUSES (*stmt_p
), ctx
);
1163 scan_omp (&OMP_PARALLEL_BODY (*stmt_p
), ctx
);
1165 if (TYPE_FIELDS (ctx
->record_type
) == NULL
)
1166 ctx
->record_type
= ctx
->receiver_decl
= NULL
;
1169 layout_type (ctx
->record_type
);
1170 fixup_child_record_type (ctx
);
1175 /* Scan an OpenMP loop directive. */
1178 scan_omp_for (tree
*stmt_p
, omp_context
*outer_ctx
)
1184 ctx
= new_omp_context (stmt
, outer_ctx
);
1186 scan_sharing_clauses (OMP_FOR_CLAUSES (stmt
), ctx
);
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
);
1195 /* Scan an OpenMP sections directive. */
1198 scan_omp_sections (tree
*stmt_p
, omp_context
*outer_ctx
)
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
);
1209 /* Scan an OpenMP single directive. */
1212 scan_omp_single (tree
*stmt_p
, omp_context
*outer_ctx
)
1214 tree stmt
= *stmt_p
;
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
;
1225 scan_sharing_clauses (OMP_SINGLE_CLAUSES (stmt
), ctx
);
1226 scan_omp (&OMP_SINGLE_BODY (stmt
), ctx
);
1228 if (TYPE_FIELDS (ctx
->record_type
) == NULL
)
1229 ctx
->record_type
= NULL
;
1231 layout_type (ctx
->record_type
);
1235 /* Callback for walk_stmts used to scan for OpenMP directives at TP. */
1238 scan_omp_1 (tree
*tp
, int *walk_subtrees
, void *data
)
1240 struct walk_stmt_info
*wi
= data
;
1241 omp_context
*ctx
= wi
->info
;
1244 if (EXPR_HAS_LOCATION (t
))
1245 input_location
= EXPR_LOCATION (t
);
1248 switch (TREE_CODE (t
))
1251 parallel_nesting_level
++;
1252 scan_omp_parallel (tp
, ctx
);
1253 parallel_nesting_level
--;
1257 scan_omp_for (tp
, ctx
);
1261 scan_omp_sections (tp
, ctx
);
1265 scan_omp_single (tp
, ctx
);
1272 ctx
= new_omp_context (*tp
, ctx
);
1273 scan_omp (&OMP_BODY (*tp
), ctx
);
1281 for (var
= BIND_EXPR_VARS (t
); var
; var
= TREE_CHAIN (var
))
1282 insert_decl_map (&ctx
->cb
, var
, var
);
1290 *tp
= remap_decl (t
, &ctx
->cb
);
1294 if (ctx
&& TYPE_P (t
))
1295 *tp
= remap_type (t
, &ctx
->cb
);
1296 else if (!DECL_P (t
))
1305 /* Scan all the statements starting at STMT_P. CTX contains context
1306 information about the OpenMP directives and clauses found during
1310 scan_omp (tree
*stmt_p
, omp_context
*ctx
)
1312 location_t saved_location
;
1313 struct walk_stmt_info wi
;
1315 memset (&wi
, 0, sizeof (wi
));
1316 wi
.callback
= scan_omp_1
;
1318 wi
.want_bind_expr
= (ctx
!= NULL
);
1319 wi
.want_locations
= true;
1321 saved_location
= input_location
;
1322 walk_stmts (&wi
, stmt_p
);
1323 input_location
= saved_location
;
1326 /* Re-gimplification and code generation routines. */
1328 /* Build a call to GOMP_barrier. */
1331 build_omp_barrier (tree
*stmt_list
)
1335 t
= built_in_decls
[BUILT_IN_GOMP_BARRIER
];
1336 t
= build_function_call_expr (t
, NULL
);
1337 gimplify_and_add (t
, stmt_list
);
1340 /* If a context was created for STMT when it was scanned, return it. */
1342 static omp_context
*
1343 maybe_lookup_ctx (tree stmt
)
1346 n
= splay_tree_lookup (all_contexts
, (splay_tree_key
) stmt
);
1347 return n
? (omp_context
*) n
->value
: NULL
;
1351 /* Find the mapping for DECL in CTX or the immediately enclosing
1352 context that has a mapping for DECL.
1354 If CTX is a nested parallel directive, we may have to use the decl
1355 mappings created in CTX's parent context. Suppose that we have the
1356 following parallel nesting (variable UIDs showed for clarity):
1359 #omp parallel shared(iD.1562) -> outer parallel
1360 iD.1562 = iD.1562 + 1;
1362 #omp parallel shared (iD.1562) -> inner parallel
1363 iD.1562 = iD.1562 - 1;
1365 Each parallel structure will create a distinct .omp_data_s structure
1366 for copying iD.1562 in/out of the directive:
1368 outer parallel .omp_data_s.1.i -> iD.1562
1369 inner parallel .omp_data_s.2.i -> iD.1562
1371 A shared variable mapping will produce a copy-out operation before
1372 the parallel directive and a copy-in operation after it. So, in
1373 this case we would have:
1376 .omp_data_o.1.i = iD.1562;
1377 #omp parallel shared(iD.1562) -> outer parallel
1378 .omp_data_i.1 = &.omp_data_o.1
1379 .omp_data_i.1->i = .omp_data_i.1->i + 1;
1381 .omp_data_o.2.i = iD.1562; -> **
1382 #omp parallel shared(iD.1562) -> inner parallel
1383 .omp_data_i.2 = &.omp_data_o.2
1384 .omp_data_i.2->i = .omp_data_i.2->i - 1;
1387 ** This is a problem. The symbol iD.1562 cannot be referenced
1388 inside the body of the outer parallel region. But since we are
1389 emitting this copy operation while expanding the inner parallel
1390 directive, we need to access the CTX structure of the outer
1391 parallel directive to get the correct mapping:
1393 .omp_data_o.2.i = .omp_data_i.1->i
1395 Since there may be other workshare or parallel directives enclosing
1396 the parallel directive, it may be necessary to walk up the context
1397 parent chain. This is not a problem in general because nested
1398 parallelism happens only rarely. */
1401 lookup_decl_in_outer_ctx (tree decl
, omp_context
*ctx
)
1406 gcc_assert (ctx
->is_nested
);
1408 for (up
= ctx
->outer
, t
= NULL
; up
&& t
== NULL
; up
= up
->outer
)
1409 t
= maybe_lookup_decl (decl
, up
);
1417 /* Construct the initialization value for reduction CLAUSE. */
1420 omp_reduction_init (tree clause
, tree type
)
1422 switch (OMP_CLAUSE_REDUCTION_CODE (clause
))
1429 case TRUTH_ORIF_EXPR
:
1430 case TRUTH_XOR_EXPR
:
1432 return fold_convert (type
, integer_zero_node
);
1435 case TRUTH_AND_EXPR
:
1436 case TRUTH_ANDIF_EXPR
:
1438 return fold_convert (type
, integer_one_node
);
1441 return fold_convert (type
, integer_minus_one_node
);
1444 if (SCALAR_FLOAT_TYPE_P (type
))
1446 REAL_VALUE_TYPE max
, min
;
1447 if (HONOR_INFINITIES (TYPE_MODE (type
)))
1450 real_arithmetic (&min
, NEGATE_EXPR
, &max
, NULL
);
1453 real_maxval (&min
, 1, TYPE_MODE (type
));
1454 return build_real (type
, min
);
1458 gcc_assert (INTEGRAL_TYPE_P (type
));
1459 return TYPE_MIN_VALUE (type
);
1463 if (SCALAR_FLOAT_TYPE_P (type
))
1465 REAL_VALUE_TYPE max
;
1466 if (HONOR_INFINITIES (TYPE_MODE (type
)))
1469 real_maxval (&max
, 0, TYPE_MODE (type
));
1470 return build_real (type
, max
);
1474 gcc_assert (INTEGRAL_TYPE_P (type
));
1475 return TYPE_MAX_VALUE (type
);
1483 /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
1484 from the receiver (aka child) side and initializers for REFERENCE_TYPE
1485 private variables. Initialization statements go in ILIST, while calls
1486 to destructors go in DLIST. */
1489 lower_rec_input_clauses (tree clauses
, tree
*ilist
, tree
*dlist
,
1492 tree_stmt_iterator diter
;
1493 tree c
, dtor
, copyin_seq
, x
, args
, ptr
;
1494 bool copyin_by_ref
= false;
1497 *dlist
= alloc_stmt_list ();
1498 diter
= tsi_start (*dlist
);
1501 /* Do all the fixed sized types in the first pass, and the variable sized
1502 types in the second pass. This makes sure that the scalar arguments to
1503 the variable sized types are processed before we use them in the
1504 variable sized operations. */
1505 for (pass
= 0; pass
< 2; ++pass
)
1507 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
1509 enum omp_clause_code c_kind
= OMP_CLAUSE_CODE (c
);
1515 case OMP_CLAUSE_PRIVATE
:
1516 if (OMP_CLAUSE_PRIVATE_DEBUG (c
))
1519 case OMP_CLAUSE_SHARED
:
1520 case OMP_CLAUSE_FIRSTPRIVATE
:
1521 case OMP_CLAUSE_LASTPRIVATE
:
1522 case OMP_CLAUSE_COPYIN
:
1523 case OMP_CLAUSE_REDUCTION
:
1529 new_var
= var
= OMP_CLAUSE_DECL (c
);
1530 if (c_kind
!= OMP_CLAUSE_COPYIN
)
1531 new_var
= lookup_decl (var
, ctx
);
1533 if (c_kind
== OMP_CLAUSE_SHARED
|| c_kind
== OMP_CLAUSE_COPYIN
)
1538 else if (is_variable_sized (var
))
1540 /* For variable sized types, we need to allocate the
1541 actual storage here. Call alloca and store the
1542 result in the pointer decl that we created elsewhere. */
1546 ptr
= DECL_VALUE_EXPR (new_var
);
1547 gcc_assert (TREE_CODE (ptr
) == INDIRECT_REF
);
1548 ptr
= TREE_OPERAND (ptr
, 0);
1549 gcc_assert (DECL_P (ptr
));
1551 x
= TYPE_SIZE_UNIT (TREE_TYPE (new_var
));
1552 args
= tree_cons (NULL
, x
, NULL
);
1553 x
= built_in_decls
[BUILT_IN_ALLOCA
];
1554 x
= build_function_call_expr (x
, args
);
1555 x
= fold_convert (TREE_TYPE (ptr
), x
);
1556 x
= build2 (MODIFY_EXPR
, void_type_node
, ptr
, x
);
1557 gimplify_and_add (x
, ilist
);
1559 else if (is_reference (var
))
1561 /* For references that are being privatized for Fortran,
1562 allocate new backing storage for the new pointer
1563 variable. This allows us to avoid changing all the
1564 code that expects a pointer to something that expects
1565 a direct variable. Note that this doesn't apply to
1566 C++, since reference types are disallowed in data
1567 sharing clauses there. */
1571 x
= TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var
)));
1572 if (TREE_CONSTANT (x
))
1574 const char *name
= NULL
;
1575 if (DECL_NAME (var
))
1576 name
= IDENTIFIER_POINTER (DECL_NAME (new_var
));
1578 x
= create_tmp_var (TREE_TYPE (TREE_TYPE (new_var
)), name
);
1579 x
= build_fold_addr_expr_with_type (x
, TREE_TYPE (new_var
));
1583 args
= tree_cons (NULL
, x
, NULL
);
1584 x
= built_in_decls
[BUILT_IN_ALLOCA
];
1585 x
= build_function_call_expr (x
, args
);
1586 x
= fold_convert (TREE_TYPE (new_var
), x
);
1589 x
= build2 (MODIFY_EXPR
, void_type_node
, new_var
, x
);
1590 gimplify_and_add (x
, ilist
);
1592 new_var
= build_fold_indirect_ref (new_var
);
1594 else if (c_kind
== OMP_CLAUSE_REDUCTION
1595 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
1603 switch (OMP_CLAUSE_CODE (c
))
1605 case OMP_CLAUSE_SHARED
:
1606 /* Set up the DECL_VALUE_EXPR for shared variables now. This
1607 needs to be delayed until after fixup_child_record_type so
1608 that we get the correct type during the dereference. */
1609 by_ref
= use_pointer_for_field (var
, true);
1610 x
= build_receiver_ref (var
, by_ref
, ctx
);
1611 SET_DECL_VALUE_EXPR (new_var
, x
);
1612 DECL_HAS_VALUE_EXPR_P (new_var
) = 1;
1614 /* ??? If VAR is not passed by reference, and the variable
1615 hasn't been initialized yet, then we'll get a warning for
1616 the store into the omp_data_s structure. Ideally, we'd be
1617 able to notice this and not store anything at all, but
1618 we're generating code too early. Suppress the warning. */
1620 TREE_NO_WARNING (var
) = 1;
1623 case OMP_CLAUSE_LASTPRIVATE
:
1624 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c
))
1628 case OMP_CLAUSE_PRIVATE
:
1629 x
= lang_hooks
.decls
.omp_clause_default_ctor (c
, new_var
);
1631 gimplify_and_add (x
, ilist
);
1635 x
= lang_hooks
.decls
.omp_clause_dtor (c
, new_var
);
1639 gimplify_stmt (&dtor
);
1640 tsi_link_before (&diter
, dtor
, TSI_SAME_STMT
);
1644 case OMP_CLAUSE_FIRSTPRIVATE
:
1645 x
= build_outer_var_ref (var
, ctx
);
1646 x
= lang_hooks
.decls
.omp_clause_copy_ctor (c
, new_var
, x
);
1647 gimplify_and_add (x
, ilist
);
1651 case OMP_CLAUSE_COPYIN
:
1652 by_ref
= use_pointer_for_field (var
, false);
1653 x
= build_receiver_ref (var
, by_ref
, ctx
);
1654 x
= lang_hooks
.decls
.omp_clause_assign_op (c
, new_var
, x
);
1655 append_to_statement_list (x
, ©in_seq
);
1656 copyin_by_ref
|= by_ref
;
1659 case OMP_CLAUSE_REDUCTION
:
1660 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
1662 gimplify_and_add (OMP_CLAUSE_REDUCTION_INIT (c
), ilist
);
1663 OMP_CLAUSE_REDUCTION_INIT (c
) = NULL
;
1667 x
= omp_reduction_init (c
, TREE_TYPE (new_var
));
1668 gcc_assert (TREE_CODE (TREE_TYPE (new_var
)) != ARRAY_TYPE
);
1669 x
= build2 (MODIFY_EXPR
, void_type_node
, new_var
, x
);
1670 gimplify_and_add (x
, ilist
);
1680 /* The copyin sequence is not to be executed by the main thread, since
1681 that would result in self-copies. Perhaps not visible to scalars,
1682 but it certainly is to C++ operator=. */
1685 x
= built_in_decls
[BUILT_IN_OMP_GET_THREAD_NUM
];
1686 x
= build_function_call_expr (x
, NULL
);
1687 x
= build2 (NE_EXPR
, boolean_type_node
, x
,
1688 build_int_cst (TREE_TYPE (x
), 0));
1689 x
= build3 (COND_EXPR
, void_type_node
, x
, copyin_seq
, NULL
);
1690 gimplify_and_add (x
, ilist
);
1693 /* If any copyin variable is passed by reference, we must ensure the
1694 master thread doesn't modify it before it is copied over in all
1697 build_omp_barrier (ilist
);
1701 /* Generate code to implement the LASTPRIVATE clauses. This is used for
1702 both parallel and workshare constructs. PREDICATE may be NULL if it's
1706 lower_lastprivate_clauses (tree clauses
, tree predicate
, tree
*stmt_list
,
1709 tree sub_list
, x
, c
;
1711 /* Early exit if there are no lastprivate clauses. */
1712 clauses
= find_omp_clause (clauses
, OMP_CLAUSE_LASTPRIVATE
);
1713 if (clauses
== NULL
)
1715 /* If this was a workshare clause, see if it had been combined
1716 with its parallel. In that case, look for the clauses on the
1717 parallel statement itself. */
1718 if (is_parallel_ctx (ctx
))
1722 if (ctx
== NULL
|| !is_parallel_ctx (ctx
))
1725 clauses
= find_omp_clause (OMP_PARALLEL_CLAUSES (ctx
->stmt
),
1726 OMP_CLAUSE_LASTPRIVATE
);
1727 if (clauses
== NULL
)
1731 sub_list
= alloc_stmt_list ();
1733 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
1737 if (OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_LASTPRIVATE
)
1740 var
= OMP_CLAUSE_DECL (c
);
1741 new_var
= lookup_decl (var
, ctx
);
1743 x
= build_outer_var_ref (var
, ctx
);
1744 if (is_reference (var
))
1745 new_var
= build_fold_indirect_ref (new_var
);
1746 x
= lang_hooks
.decls
.omp_clause_assign_op (c
, x
, new_var
);
1747 append_to_statement_list (x
, &sub_list
);
1751 x
= build3 (COND_EXPR
, void_type_node
, predicate
, sub_list
, NULL
);
1755 gimplify_and_add (x
, stmt_list
);
1759 /* Generate code to implement the REDUCTION clauses. */
1762 lower_reduction_clauses (tree clauses
, tree
*stmt_list
, omp_context
*ctx
)
1764 tree sub_list
= NULL
, x
, c
;
1767 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
1768 update in that case, otherwise use a lock. */
1769 for (c
= clauses
; c
&& count
< 2; c
= OMP_CLAUSE_CHAIN (c
))
1770 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_REDUCTION
)
1772 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
1774 /* Never use OMP_ATOMIC for array reductions. */
1784 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
1786 tree var
, ref
, new_var
;
1787 enum tree_code code
;
1789 if (OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_REDUCTION
)
1792 var
= OMP_CLAUSE_DECL (c
);
1793 new_var
= lookup_decl (var
, ctx
);
1794 if (is_reference (var
))
1795 new_var
= build_fold_indirect_ref (new_var
);
1796 ref
= build_outer_var_ref (var
, ctx
);
1797 code
= OMP_CLAUSE_REDUCTION_CODE (c
);
1799 /* reduction(-:var) sums up the partial results, so it acts
1800 identically to reduction(+:var). */
1801 if (code
== MINUS_EXPR
)
1806 tree addr
= build_fold_addr_expr (ref
);
1808 addr
= save_expr (addr
);
1809 ref
= build1 (INDIRECT_REF
, TREE_TYPE (TREE_TYPE (addr
)), addr
);
1810 x
= fold_build2 (code
, TREE_TYPE (ref
), ref
, new_var
);
1811 x
= build2 (OMP_ATOMIC
, void_type_node
, addr
, x
);
1812 gimplify_and_add (x
, stmt_list
);
1816 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
1818 tree placeholder
= OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
);
1820 if (is_reference (var
))
1821 ref
= build_fold_addr_expr (ref
);
1822 SET_DECL_VALUE_EXPR (placeholder
, ref
);
1823 DECL_HAS_VALUE_EXPR_P (placeholder
) = 1;
1824 gimplify_and_add (OMP_CLAUSE_REDUCTION_MERGE (c
), &sub_list
);
1825 OMP_CLAUSE_REDUCTION_MERGE (c
) = NULL
;
1826 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
) = NULL
;
1830 x
= build2 (code
, TREE_TYPE (ref
), ref
, new_var
);
1831 ref
= build_outer_var_ref (var
, ctx
);
1832 x
= build2 (MODIFY_EXPR
, void_type_node
, ref
, x
);
1833 append_to_statement_list (x
, &sub_list
);
1837 x
= built_in_decls
[BUILT_IN_GOMP_ATOMIC_START
];
1838 x
= build_function_call_expr (x
, NULL
);
1839 gimplify_and_add (x
, stmt_list
);
1841 gimplify_and_add (sub_list
, stmt_list
);
1843 x
= built_in_decls
[BUILT_IN_GOMP_ATOMIC_END
];
1844 x
= build_function_call_expr (x
, NULL
);
1845 gimplify_and_add (x
, stmt_list
);
1849 /* Generate code to implement the COPYPRIVATE clauses. */
1852 lower_copyprivate_clauses (tree clauses
, tree
*slist
, tree
*rlist
,
1857 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
1862 if (OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_COPYPRIVATE
)
1865 var
= OMP_CLAUSE_DECL (c
);
1866 by_ref
= use_pointer_for_field (var
, false);
1868 ref
= build_sender_ref (var
, ctx
);
1869 x
= (ctx
->is_nested
) ? lookup_decl_in_outer_ctx (var
, ctx
) : var
;
1870 x
= by_ref
? build_fold_addr_expr (x
) : x
;
1871 x
= build2 (MODIFY_EXPR
, void_type_node
, ref
, x
);
1872 gimplify_and_add (x
, slist
);
1874 ref
= build_receiver_ref (var
, by_ref
, ctx
);
1875 if (is_reference (var
))
1877 ref
= build_fold_indirect_ref (ref
);
1878 var
= build_fold_indirect_ref (var
);
1880 x
= lang_hooks
.decls
.omp_clause_assign_op (c
, var
, ref
);
1881 gimplify_and_add (x
, rlist
);
1886 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
1887 and REDUCTION from the sender (aka parent) side. */
1890 lower_send_clauses (tree clauses
, tree
*ilist
, tree
*olist
, omp_context
*ctx
)
1894 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
1896 tree val
, ref
, x
, var
;
1897 bool by_ref
, do_in
= false, do_out
= false;
1899 switch (OMP_CLAUSE_CODE (c
))
1901 case OMP_CLAUSE_FIRSTPRIVATE
:
1902 case OMP_CLAUSE_COPYIN
:
1903 case OMP_CLAUSE_LASTPRIVATE
:
1904 case OMP_CLAUSE_REDUCTION
:
1910 var
= val
= OMP_CLAUSE_DECL (c
);
1912 var
= lookup_decl_in_outer_ctx (val
, ctx
);
1914 if (is_variable_sized (val
))
1916 by_ref
= use_pointer_for_field (val
, false);
1918 switch (OMP_CLAUSE_CODE (c
))
1920 case OMP_CLAUSE_FIRSTPRIVATE
:
1921 case OMP_CLAUSE_COPYIN
:
1925 case OMP_CLAUSE_LASTPRIVATE
:
1926 if (by_ref
|| is_reference (val
))
1928 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c
))
1936 case OMP_CLAUSE_REDUCTION
:
1938 do_out
= !(by_ref
|| is_reference (val
));
1947 ref
= build_sender_ref (val
, ctx
);
1948 x
= by_ref
? build_fold_addr_expr (var
) : var
;
1949 x
= build2 (MODIFY_EXPR
, void_type_node
, ref
, x
);
1950 gimplify_and_add (x
, ilist
);
1955 ref
= build_sender_ref (val
, ctx
);
1956 x
= build2 (MODIFY_EXPR
, void_type_node
, var
, ref
);
1957 gimplify_and_add (x
, olist
);
1962 /* Generate code to implement SHARED from the sender (aka parent) side.
1963 This is trickier, since OMP_PARALLEL_CLAUSES doesn't list things that
1964 got automatically shared. */
1967 lower_send_shared_vars (tree
*ilist
, tree
*olist
, omp_context
*ctx
)
1969 tree var
, ovar
, nvar
, f
, x
;
1971 if (ctx
->record_type
== NULL
)
1974 for (f
= TYPE_FIELDS (ctx
->record_type
); f
; f
= TREE_CHAIN (f
))
1976 ovar
= DECL_ABSTRACT_ORIGIN (f
);
1977 nvar
= maybe_lookup_decl (ovar
, ctx
);
1978 if (!nvar
|| !DECL_HAS_VALUE_EXPR_P (nvar
))
1983 /* If CTX is a nested parallel directive. Find the immediately
1984 enclosing parallel or workshare construct that contains a
1985 mapping for OVAR. */
1987 var
= lookup_decl_in_outer_ctx (ovar
, ctx
);
1989 if (use_pointer_for_field (ovar
, true))
1991 x
= build_sender_ref (ovar
, ctx
);
1992 var
= build_fold_addr_expr (var
);
1993 x
= build2 (MODIFY_EXPR
, void_type_node
, x
, var
);
1994 gimplify_and_add (x
, ilist
);
1998 x
= build_sender_ref (ovar
, ctx
);
1999 x
= build2 (MODIFY_EXPR
, void_type_node
, x
, var
);
2000 gimplify_and_add (x
, ilist
);
2002 x
= build_sender_ref (ovar
, ctx
);
2003 x
= build2 (MODIFY_EXPR
, void_type_node
, var
, x
);
2004 gimplify_and_add (x
, olist
);
2009 /* Build the function calls to GOMP_parallel_start etc to actually
2010 generate the parallel operation. REGION is the parallel region
2011 being expanded. BB is the block where to insert the code. WS_ARGS
2012 will be set if this is a call to a combined parallel+workshare
2013 construct, it contains the list of additional arguments needed by
2014 the workshare construct. */
2017 expand_parallel_call (struct omp_region
*region
, basic_block bb
,
2018 tree entry_stmt
, tree ws_args
)
2020 tree t
, args
, val
, cond
, c
, list
, clauses
;
2021 block_stmt_iterator si
;
2024 clauses
= OMP_PARALLEL_CLAUSES (entry_stmt
);
2025 push_gimplify_context ();
2027 /* Determine what flavor of GOMP_parallel_start we will be
2029 start_ix
= BUILT_IN_GOMP_PARALLEL_START
;
2030 if (is_combined_parallel (region
))
2032 switch (region
->inner
->type
)
2035 start_ix
= BUILT_IN_GOMP_PARALLEL_LOOP_STATIC_START
2036 + region
->inner
->sched_kind
;
2039 start_ix
= BUILT_IN_GOMP_PARALLEL_SECTIONS_START
;
2046 /* By default, the value of NUM_THREADS is zero (selected at run time)
2047 and there is no conditional. */
2049 val
= build_int_cst (unsigned_type_node
, 0);
2051 c
= find_omp_clause (clauses
, OMP_CLAUSE_IF
);
2053 cond
= OMP_CLAUSE_IF_EXPR (c
);
2055 c
= find_omp_clause (clauses
, OMP_CLAUSE_NUM_THREADS
);
2057 val
= OMP_CLAUSE_NUM_THREADS_EXPR (c
);
2059 /* Ensure 'val' is of the correct type. */
2060 val
= fold_convert (unsigned_type_node
, val
);
2062 /* If we found the clause 'if (cond)', build either
2063 (cond != 0) or (cond ? val : 1u). */
2066 block_stmt_iterator si
;
2068 cond
= gimple_boolify (cond
);
2070 if (integer_zerop (val
))
2071 val
= build2 (EQ_EXPR
, unsigned_type_node
, cond
,
2072 build_int_cst (TREE_TYPE (cond
), 0));
2075 basic_block cond_bb
, then_bb
, else_bb
;
2077 tree t
, then_lab
, else_lab
, tmp
;
2079 tmp
= create_tmp_var (TREE_TYPE (val
), NULL
);
2080 e
= split_block (bb
, NULL
);
2085 then_bb
= create_empty_bb (cond_bb
);
2086 else_bb
= create_empty_bb (then_bb
);
2087 then_lab
= create_artificial_label ();
2088 else_lab
= create_artificial_label ();
2090 t
= build3 (COND_EXPR
, void_type_node
,
2092 build_and_jump (&then_lab
),
2093 build_and_jump (&else_lab
));
2095 si
= bsi_start (cond_bb
);
2096 bsi_insert_after (&si
, t
, BSI_CONTINUE_LINKING
);
2098 si
= bsi_start (then_bb
);
2099 t
= build1 (LABEL_EXPR
, void_type_node
, then_lab
);
2100 bsi_insert_after (&si
, t
, BSI_CONTINUE_LINKING
);
2101 t
= build2 (MODIFY_EXPR
, void_type_node
, tmp
, val
);
2102 bsi_insert_after (&si
, t
, BSI_CONTINUE_LINKING
);
2104 si
= bsi_start (else_bb
);
2105 t
= build1 (LABEL_EXPR
, void_type_node
, else_lab
);
2106 bsi_insert_after (&si
, t
, BSI_CONTINUE_LINKING
);
2107 t
= build2 (MODIFY_EXPR
, void_type_node
, tmp
,
2108 build_int_cst (unsigned_type_node
, 1));
2109 bsi_insert_after (&si
, t
, BSI_CONTINUE_LINKING
);
2111 make_edge (cond_bb
, then_bb
, EDGE_TRUE_VALUE
);
2112 make_edge (cond_bb
, else_bb
, EDGE_FALSE_VALUE
);
2113 make_edge (then_bb
, bb
, EDGE_FALLTHRU
);
2114 make_edge (else_bb
, bb
, EDGE_FALLTHRU
);
2120 val
= get_formal_tmp_var (val
, &list
);
2121 si
= bsi_start (bb
);
2122 bsi_insert_after (&si
, list
, BSI_CONTINUE_LINKING
);
2126 args
= tree_cons (NULL
, val
, NULL
);
2127 t
= OMP_PARALLEL_DATA_ARG (entry_stmt
);
2129 t
= null_pointer_node
;
2131 t
= build_fold_addr_expr (t
);
2132 args
= tree_cons (NULL
, t
, args
);
2133 t
= build_fold_addr_expr (OMP_PARALLEL_FN (entry_stmt
));
2134 args
= tree_cons (NULL
, t
, args
);
2137 args
= chainon (args
, ws_args
);
2139 t
= built_in_decls
[start_ix
];
2140 t
= build_function_call_expr (t
, args
);
2141 gimplify_and_add (t
, &list
);
2143 t
= OMP_PARALLEL_DATA_ARG (entry_stmt
);
2145 t
= null_pointer_node
;
2147 t
= build_fold_addr_expr (t
);
2148 args
= tree_cons (NULL
, t
, NULL
);
2149 t
= build_function_call_expr (OMP_PARALLEL_FN (entry_stmt
), args
);
2150 gimplify_and_add (t
, &list
);
2152 t
= built_in_decls
[BUILT_IN_GOMP_PARALLEL_END
];
2153 t
= build_function_call_expr (t
, NULL
);
2154 gimplify_and_add (t
, &list
);
2157 bsi_insert_after (&si
, list
, BSI_CONTINUE_LINKING
);
2159 pop_gimplify_context (NULL_TREE
);
2163 /* If exceptions are enabled, wrap *STMT_P in a MUST_NOT_THROW catch
2164 handler. This prevents programs from violating the structured
2165 block semantics with throws. */
2168 maybe_catch_exception (tree
*stmt_p
)
2172 if (!flag_exceptions
)
2175 if (lang_protect_cleanup_actions
)
2176 t
= lang_protect_cleanup_actions ();
2179 t
= built_in_decls
[BUILT_IN_TRAP
];
2180 t
= build_function_call_expr (t
, NULL
);
2182 f
= build2 (EH_FILTER_EXPR
, void_type_node
, NULL
, NULL
);
2183 EH_FILTER_MUST_NOT_THROW (f
) = 1;
2184 gimplify_and_add (t
, &EH_FILTER_FAILURE (f
));
2186 t
= build2 (TRY_CATCH_EXPR
, void_type_node
, *stmt_p
, NULL
);
2187 append_to_statement_list (f
, &TREE_OPERAND (t
, 1));
2190 append_to_statement_list (t
, stmt_p
);
2193 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
2196 list2chain (tree list
)
2200 for (t
= list
; t
; t
= TREE_CHAIN (t
))
2202 tree var
= TREE_VALUE (t
);
2204 TREE_CHAIN (var
) = TREE_VALUE (TREE_CHAIN (t
));
2206 TREE_CHAIN (var
) = NULL_TREE
;
2209 return list
? TREE_VALUE (list
) : NULL_TREE
;
2213 /* Remove barriers in REGION->EXIT's block. Note that this is only
2214 valid for OMP_PARALLEL regions. Since the end of a parallel region
2215 is an implicit barrier, any workshare inside the OMP_PARALLEL that
2216 left a barrier at the end of the OMP_PARALLEL region can now be
2220 remove_exit_barrier (struct omp_region
*region
)
2222 block_stmt_iterator si
;
2223 basic_block exit_bb
;
2228 exit_bb
= region
->exit
;
2230 /* The last insn in the block will be the parallel's OMP_RETURN. The
2231 workshare's OMP_RETURN will be in a preceding block. The kinds of
2232 statements that can appear in between are extremely limited -- no
2233 memory operations at all. Here, we allow nothing at all, so the
2234 only thing we allow to precede this OMP_RETURN is a label. */
2235 si
= bsi_last (exit_bb
);
2236 gcc_assert (TREE_CODE (bsi_stmt (si
)) == OMP_RETURN
);
2238 if (!bsi_end_p (si
) && TREE_CODE (bsi_stmt (si
)) != LABEL_EXPR
)
2241 FOR_EACH_EDGE (e
, ei
, exit_bb
->preds
)
2243 si
= bsi_last (e
->src
);
2247 if (TREE_CODE (t
) == OMP_RETURN
)
2248 OMP_RETURN_NOWAIT (t
) = 1;
2253 remove_exit_barriers (struct omp_region
*region
)
2255 if (region
->type
== OMP_PARALLEL
)
2256 remove_exit_barrier (region
);
2260 region
= region
->inner
;
2261 remove_exit_barriers (region
);
2262 while (region
->next
)
2264 region
= region
->next
;
2265 remove_exit_barriers (region
);
2270 /* Expand the OpenMP parallel directive starting at REGION. */
2273 expand_omp_parallel (struct omp_region
*region
)
2275 basic_block entry_bb
, exit_bb
, new_bb
;
2276 struct function
*child_cfun
, *saved_cfun
;
2277 tree child_fn
, block
, t
, ws_args
;
2278 block_stmt_iterator si
;
2282 entry_stmt
= last_stmt (region
->entry
);
2283 child_fn
= OMP_PARALLEL_FN (entry_stmt
);
2284 child_cfun
= DECL_STRUCT_FUNCTION (child_fn
);
2287 entry_bb
= region
->entry
;
2288 exit_bb
= region
->exit
;
2290 if (is_combined_parallel (region
))
2291 ws_args
= region
->ws_args
;
2293 ws_args
= NULL_TREE
;
2295 if (child_cfun
->cfg
)
2297 /* Due to inlining, it may happen that we have already outlined
2298 the region, in which case all we need to do is make the
2299 sub-graph unreachable and emit the parallel call. */
2300 edge entry_succ_e
, exit_succ_e
;
2301 block_stmt_iterator si
;
2303 entry_succ_e
= single_succ_edge (entry_bb
);
2304 exit_succ_e
= single_succ_edge (exit_bb
);
2306 si
= bsi_last (entry_bb
);
2307 gcc_assert (TREE_CODE (bsi_stmt (si
)) == OMP_PARALLEL
);
2308 bsi_remove (&si
, true);
2311 remove_edge (entry_succ_e
);
2312 make_edge (new_bb
, exit_succ_e
->dest
, EDGE_FALLTHRU
);
2316 /* If the parallel region needs data sent from the parent
2317 function, then the very first statement of the parallel body
2318 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
2319 &.OMP_DATA_O is passed as an argument to the child function,
2320 we need to replace it with the argument as seen by the child
2323 In most cases, this will end up being the identity assignment
2324 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
2325 a function call that has been inlined, the original PARM_DECL
2326 .OMP_DATA_I may have been converted into a different local
2327 variable. In which case, we need to keep the assignment. */
2328 if (OMP_PARALLEL_DATA_ARG (entry_stmt
))
2330 basic_block entry_succ_bb
= single_succ (entry_bb
);
2331 block_stmt_iterator si
= bsi_start (entry_succ_bb
);
2334 gcc_assert (!bsi_end_p (si
));
2336 stmt
= bsi_stmt (si
);
2337 gcc_assert (TREE_CODE (stmt
) == MODIFY_EXPR
2338 && TREE_CODE (TREE_OPERAND (stmt
, 1)) == ADDR_EXPR
2339 && TREE_OPERAND (TREE_OPERAND (stmt
, 1), 0)
2340 == OMP_PARALLEL_DATA_ARG (entry_stmt
));
2342 if (TREE_OPERAND (stmt
, 0) == DECL_ARGUMENTS (child_fn
))
2343 bsi_remove (&si
, true);
2345 TREE_OPERAND (stmt
, 1) = DECL_ARGUMENTS (child_fn
);
2348 /* Declare local variables needed in CHILD_CFUN. */
2349 block
= DECL_INITIAL (child_fn
);
2350 BLOCK_VARS (block
) = list2chain (child_cfun
->unexpanded_var_list
);
2351 DECL_SAVED_TREE (child_fn
) = single_succ (entry_bb
)->stmt_list
;
2353 /* Reset DECL_CONTEXT on locals and function arguments. */
2354 for (t
= BLOCK_VARS (block
); t
; t
= TREE_CHAIN (t
))
2355 DECL_CONTEXT (t
) = child_fn
;
2357 for (t
= DECL_ARGUMENTS (child_fn
); t
; t
= TREE_CHAIN (t
))
2358 DECL_CONTEXT (t
) = child_fn
;
2360 /* Split ENTRY_BB at OMP_PARALLEL so that it can be moved to the
2362 si
= bsi_last (entry_bb
);
2364 gcc_assert (t
&& TREE_CODE (t
) == OMP_PARALLEL
);
2365 bsi_remove (&si
, true);
2366 e
= split_block (entry_bb
, t
);
2368 single_succ_edge (entry_bb
)->flags
= EDGE_FALLTHRU
;
2370 /* Move the parallel region into CHILD_CFUN. We need to reset
2371 dominance information because the expansion of the inner
2372 regions has invalidated it. */
2373 free_dominance_info (CDI_DOMINATORS
);
2374 new_bb
= move_sese_region_to_fn (child_cfun
, entry_bb
, exit_bb
);
2375 single_succ_edge (new_bb
)->flags
= EDGE_FALLTHRU
;
2376 cgraph_add_new_function (child_fn
);
2378 /* Convert OMP_RETURN into a RETURN_EXPR. */
2379 si
= bsi_last (exit_bb
);
2380 gcc_assert (!bsi_end_p (si
) && TREE_CODE (bsi_stmt (si
)) == OMP_RETURN
);
2381 t
= build1 (RETURN_EXPR
, void_type_node
, NULL
);
2382 bsi_insert_after (&si
, t
, TSI_SAME_STMT
);
2383 bsi_remove (&si
, true);
2386 /* Emit a library call to launch the children threads. */
2387 expand_parallel_call (region
, new_bb
, entry_stmt
, ws_args
);
2391 /* A subroutine of expand_omp_for. Generate code for a parallel
2392 loop with any schedule. Given parameters:
2394 for (V = N1; V cond N2; V += STEP) BODY;
2396 where COND is "<" or ">", we generate pseudocode
2398 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
2399 if (more) goto L0; else goto L3;
2406 if (V cond iend) goto L1; else goto L2;
2408 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
2411 If this is a combined omp parallel loop, instead of the call to
2412 GOMP_loop_foo_start, we emit 'goto L3'. */
2415 expand_omp_for_generic (struct omp_region
*region
,
2416 struct omp_for_data
*fd
,
2417 enum built_in_function start_fn
,
2418 enum built_in_function next_fn
)
2420 tree l0
, l1
, l2
, l3
;
2421 tree type
, istart0
, iend0
, iend
;
2423 basic_block entry_bb
, cont_bb
, exit_bb
, l0_bb
, l1_bb
, l2_bb
, l3_bb
;
2424 block_stmt_iterator si
;
2425 bool in_combined_parallel
= is_combined_parallel (region
);
2427 type
= TREE_TYPE (fd
->v
);
2429 istart0
= create_tmp_var (long_integer_type_node
, ".istart0");
2430 iend0
= create_tmp_var (long_integer_type_node
, ".iend0");
2431 iend
= create_tmp_var (type
, NULL
);
2432 TREE_ADDRESSABLE (istart0
) = 1;
2433 TREE_ADDRESSABLE (iend0
) = 1;
2435 entry_bb
= region
->entry
;
2436 l0_bb
= create_empty_bb (entry_bb
);
2437 l1_bb
= single_succ (entry_bb
);
2438 cont_bb
= region
->cont
;
2439 l2_bb
= create_empty_bb (cont_bb
);
2440 l3_bb
= single_succ (cont_bb
);
2441 exit_bb
= region
->exit
;
2443 l0
= tree_block_label (l0_bb
);
2444 l1
= tree_block_label (l1_bb
);
2445 l2
= tree_block_label (l2_bb
);
2446 l3
= tree_block_label (l3_bb
);
2448 si
= bsi_last (entry_bb
);
2449 gcc_assert (TREE_CODE (bsi_stmt (si
)) == OMP_FOR
);
2450 if (!in_combined_parallel
)
2452 /* If this is not a combined parallel loop, emit a call to
2453 GOMP_loop_foo_start in ENTRY_BB. */
2454 list
= alloc_stmt_list ();
2455 t
= build_fold_addr_expr (iend0
);
2456 args
= tree_cons (NULL
, t
, NULL
);
2457 t
= build_fold_addr_expr (istart0
);
2458 args
= tree_cons (NULL
, t
, args
);
2461 t
= fold_convert (long_integer_type_node
, fd
->chunk_size
);
2462 args
= tree_cons (NULL
, t
, args
);
2464 t
= fold_convert (long_integer_type_node
, fd
->step
);
2465 args
= tree_cons (NULL
, t
, args
);
2466 t
= fold_convert (long_integer_type_node
, fd
->n2
);
2467 args
= tree_cons (NULL
, t
, args
);
2468 t
= fold_convert (long_integer_type_node
, fd
->n1
);
2469 args
= tree_cons (NULL
, t
, args
);
2470 t
= build_function_call_expr (built_in_decls
[start_fn
], args
);
2471 t
= get_formal_tmp_var (t
, &list
);
2472 t
= build3 (COND_EXPR
, void_type_node
, t
, build_and_jump (&l0
),
2473 build_and_jump (&l3
));
2474 append_to_statement_list (t
, &list
);
2475 bsi_insert_after (&si
, list
, BSI_SAME_STMT
);
2477 bsi_remove (&si
, true);
2479 /* Iteration setup for sequential loop goes in L0_BB. */
2480 list
= alloc_stmt_list ();
2481 t
= fold_convert (type
, istart0
);
2482 t
= build2 (MODIFY_EXPR
, void_type_node
, fd
->v
, t
);
2483 gimplify_and_add (t
, &list
);
2485 t
= fold_convert (type
, iend0
);
2486 t
= build2 (MODIFY_EXPR
, void_type_node
, iend
, t
);
2487 gimplify_and_add (t
, &list
);
2489 si
= bsi_start (l0_bb
);
2490 bsi_insert_after (&si
, list
, BSI_CONTINUE_LINKING
);
2492 /* Code to control the increment and predicate for the sequential
2493 loop goes in the first half of EXIT_BB (we split EXIT_BB so
2494 that we can inherit all the edges going out of the loop
2496 list
= alloc_stmt_list ();
2498 t
= build2 (PLUS_EXPR
, type
, fd
->v
, fd
->step
);
2499 t
= build2 (MODIFY_EXPR
, void_type_node
, fd
->v
, t
);
2500 gimplify_and_add (t
, &list
);
2502 t
= build2 (fd
->cond_code
, boolean_type_node
, fd
->v
, iend
);
2503 t
= get_formal_tmp_var (t
, &list
);
2504 t
= build3 (COND_EXPR
, void_type_node
, t
, build_and_jump (&l1
),
2505 build_and_jump (&l2
));
2506 append_to_statement_list (t
, &list
);
2508 si
= bsi_last (cont_bb
);
2509 bsi_insert_after (&si
, list
, BSI_SAME_STMT
);
2510 gcc_assert (TREE_CODE (bsi_stmt (si
)) == OMP_CONTINUE
);
2511 bsi_remove (&si
, true);
2513 /* Emit code to get the next parallel iteration in L2_BB. */
2514 list
= alloc_stmt_list ();
2516 t
= build_fold_addr_expr (iend0
);
2517 args
= tree_cons (NULL
, t
, NULL
);
2518 t
= build_fold_addr_expr (istart0
);
2519 args
= tree_cons (NULL
, t
, args
);
2520 t
= build_function_call_expr (built_in_decls
[next_fn
], args
);
2521 t
= get_formal_tmp_var (t
, &list
);
2522 t
= build3 (COND_EXPR
, void_type_node
, t
, build_and_jump (&l0
),
2523 build_and_jump (&l3
));
2524 append_to_statement_list (t
, &list
);
2526 si
= bsi_start (l2_bb
);
2527 bsi_insert_after (&si
, list
, BSI_CONTINUE_LINKING
);
2529 /* Add the loop cleanup function. */
2530 si
= bsi_last (exit_bb
);
2531 if (OMP_RETURN_NOWAIT (bsi_stmt (si
)))
2532 t
= built_in_decls
[BUILT_IN_GOMP_LOOP_END_NOWAIT
];
2534 t
= built_in_decls
[BUILT_IN_GOMP_LOOP_END
];
2535 t
= build_function_call_expr (t
, NULL
);
2536 bsi_insert_after (&si
, t
, BSI_SAME_STMT
);
2537 bsi_remove (&si
, true);
2539 /* Connect the new blocks. */
2540 remove_edge (single_succ_edge (entry_bb
));
2541 if (in_combined_parallel
)
2542 make_edge (entry_bb
, l2_bb
, EDGE_FALLTHRU
);
2545 make_edge (entry_bb
, l0_bb
, EDGE_TRUE_VALUE
);
2546 make_edge (entry_bb
, l3_bb
, EDGE_FALSE_VALUE
);
2549 make_edge (l0_bb
, l1_bb
, EDGE_FALLTHRU
);
2551 remove_edge (single_succ_edge (cont_bb
));
2552 make_edge (cont_bb
, l1_bb
, EDGE_TRUE_VALUE
);
2553 make_edge (cont_bb
, l2_bb
, EDGE_FALSE_VALUE
);
2555 make_edge (l2_bb
, l0_bb
, EDGE_TRUE_VALUE
);
2556 make_edge (l2_bb
, l3_bb
, EDGE_FALSE_VALUE
);
2560 /* A subroutine of expand_omp_for. Generate code for a parallel
2561 loop with static schedule and no specified chunk size. Given
2564 for (V = N1; V cond N2; V += STEP) BODY;
2566 where COND is "<" or ">", we generate pseudocode
2572 n = (adj + N2 - N1) / STEP;
2574 q += (q * nthreads != n);
2576 e0 = min(s0 + q, n);
2577 if (s0 >= e0) goto L2; else goto L0;
2584 if (V cond e) goto L1;
2589 expand_omp_for_static_nochunk (struct omp_region
*region
,
2590 struct omp_for_data
*fd
)
2592 tree l0
, l1
, l2
, n
, q
, s0
, e0
, e
, t
, nthreads
, threadid
;
2593 tree type
, utype
, list
;
2594 basic_block entry_bb
, exit_bb
, seq_start_bb
, body_bb
, cont_bb
;
2596 block_stmt_iterator si
;
2598 type
= TREE_TYPE (fd
->v
);
2599 utype
= lang_hooks
.types
.unsigned_type (type
);
2601 entry_bb
= region
->entry
;
2602 seq_start_bb
= create_empty_bb (entry_bb
);
2603 body_bb
= single_succ (entry_bb
);
2604 cont_bb
= region
->cont
;
2605 fin_bb
= single_succ (cont_bb
);
2606 exit_bb
= region
->exit
;
2608 l0
= tree_block_label (seq_start_bb
);
2609 l1
= tree_block_label (body_bb
);
2610 l2
= tree_block_label (fin_bb
);
2612 /* Iteration space partitioning goes in ENTRY_BB. */
2613 list
= alloc_stmt_list ();
2615 t
= built_in_decls
[BUILT_IN_OMP_GET_NUM_THREADS
];
2616 t
= build_function_call_expr (t
, NULL
);
2617 t
= fold_convert (utype
, t
);
2618 nthreads
= get_formal_tmp_var (t
, &list
);
2620 t
= built_in_decls
[BUILT_IN_OMP_GET_THREAD_NUM
];
2621 t
= build_function_call_expr (t
, NULL
);
2622 t
= fold_convert (utype
, t
);
2623 threadid
= get_formal_tmp_var (t
, &list
);
2625 fd
->n1
= fold_convert (type
, fd
->n1
);
2626 if (!is_gimple_val (fd
->n1
))
2627 fd
->n1
= get_formal_tmp_var (fd
->n1
, &list
);
2629 fd
->n2
= fold_convert (type
, fd
->n2
);
2630 if (!is_gimple_val (fd
->n2
))
2631 fd
->n2
= get_formal_tmp_var (fd
->n2
, &list
);
2633 fd
->step
= fold_convert (type
, fd
->step
);
2634 if (!is_gimple_val (fd
->step
))
2635 fd
->step
= get_formal_tmp_var (fd
->step
, &list
);
2637 t
= build_int_cst (type
, (fd
->cond_code
== LT_EXPR
? -1 : 1));
2638 t
= fold_build2 (PLUS_EXPR
, type
, fd
->step
, t
);
2639 t
= fold_build2 (PLUS_EXPR
, type
, t
, fd
->n2
);
2640 t
= fold_build2 (MINUS_EXPR
, type
, t
, fd
->n1
);
2641 t
= fold_build2 (TRUNC_DIV_EXPR
, type
, t
, fd
->step
);
2642 t
= fold_convert (utype
, t
);
2643 if (is_gimple_val (t
))
2646 n
= get_formal_tmp_var (t
, &list
);
2648 t
= build2 (TRUNC_DIV_EXPR
, utype
, n
, nthreads
);
2649 q
= get_formal_tmp_var (t
, &list
);
2651 t
= build2 (MULT_EXPR
, utype
, q
, nthreads
);
2652 t
= build2 (NE_EXPR
, utype
, t
, n
);
2653 t
= build2 (PLUS_EXPR
, utype
, q
, t
);
2654 q
= get_formal_tmp_var (t
, &list
);
2656 t
= build2 (MULT_EXPR
, utype
, q
, threadid
);
2657 s0
= get_formal_tmp_var (t
, &list
);
2659 t
= build2 (PLUS_EXPR
, utype
, s0
, q
);
2660 t
= build2 (MIN_EXPR
, utype
, t
, n
);
2661 e0
= get_formal_tmp_var (t
, &list
);
2663 t
= build2 (GE_EXPR
, boolean_type_node
, s0
, e0
);
2664 t
= build3 (COND_EXPR
, void_type_node
, t
, build_and_jump (&l2
),
2665 build_and_jump (&l0
));
2666 append_to_statement_list (t
, &list
);
2668 si
= bsi_last (entry_bb
);
2669 gcc_assert (TREE_CODE (bsi_stmt (si
)) == OMP_FOR
);
2670 bsi_insert_after (&si
, list
, BSI_SAME_STMT
);
2671 bsi_remove (&si
, true);
2673 /* Setup code for sequential iteration goes in SEQ_START_BB. */
2674 list
= alloc_stmt_list ();
2676 t
= fold_convert (type
, s0
);
2677 t
= build2 (MULT_EXPR
, type
, t
, fd
->step
);
2678 t
= build2 (PLUS_EXPR
, type
, t
, fd
->n1
);
2679 t
= build2 (MODIFY_EXPR
, void_type_node
, fd
->v
, t
);
2680 gimplify_and_add (t
, &list
);
2682 t
= fold_convert (type
, e0
);
2683 t
= build2 (MULT_EXPR
, type
, t
, fd
->step
);
2684 t
= build2 (PLUS_EXPR
, type
, t
, fd
->n1
);
2685 e
= get_formal_tmp_var (t
, &list
);
2687 si
= bsi_start (seq_start_bb
);
2688 bsi_insert_after (&si
, list
, BSI_CONTINUE_LINKING
);
2690 /* The code controlling the sequential loop replaces the OMP_CONTINUE. */
2691 list
= alloc_stmt_list ();
2693 t
= build2 (PLUS_EXPR
, type
, fd
->v
, fd
->step
);
2694 t
= build2 (MODIFY_EXPR
, void_type_node
, fd
->v
, t
);
2695 gimplify_and_add (t
, &list
);
2697 t
= build2 (fd
->cond_code
, boolean_type_node
, fd
->v
, e
);
2698 t
= get_formal_tmp_var (t
, &list
);
2699 t
= build3 (COND_EXPR
, void_type_node
, t
, build_and_jump (&l1
),
2700 build_and_jump (&l2
));
2701 append_to_statement_list (t
, &list
);
2703 si
= bsi_last (cont_bb
);
2704 gcc_assert (TREE_CODE (bsi_stmt (si
)) == OMP_CONTINUE
);
2705 bsi_insert_after (&si
, list
, BSI_SAME_STMT
);
2706 bsi_remove (&si
, true);
2708 /* Replace the OMP_RETURN with a barrier, or nothing. */
2709 si
= bsi_last (exit_bb
);
2710 if (!OMP_RETURN_NOWAIT (bsi_stmt (si
)))
2712 list
= alloc_stmt_list ();
2713 build_omp_barrier (&list
);
2714 bsi_insert_after (&si
, list
, BSI_SAME_STMT
);
2716 bsi_remove (&si
, true);
2718 /* Connect all the blocks. */
2719 make_edge (seq_start_bb
, body_bb
, EDGE_FALLTHRU
);
2721 remove_edge (single_succ_edge (entry_bb
));
2722 make_edge (entry_bb
, fin_bb
, EDGE_TRUE_VALUE
);
2723 make_edge (entry_bb
, seq_start_bb
, EDGE_FALSE_VALUE
);
2725 make_edge (cont_bb
, body_bb
, EDGE_TRUE_VALUE
);
2726 find_edge (cont_bb
, fin_bb
)->flags
= EDGE_FALSE_VALUE
;
2730 /* A subroutine of expand_omp_for. Generate code for a parallel
2731 loop with static schedule and a specified chunk size. Given
2734 for (V = N1; V cond N2; V += STEP) BODY;
2736 where COND is "<" or ">", we generate pseudocode
2742 n = (adj + N2 - N1) / STEP;
2745 s0 = (trip * nthreads + threadid) * CHUNK;
2746 e0 = min(s0 + CHUNK, n);
2747 if (s0 < n) goto L1; else goto L4;
2754 if (V cond e) goto L2; else goto L3;
2762 expand_omp_for_static_chunk (struct omp_region
*region
, struct omp_for_data
*fd
)
2764 tree l0
, l1
, l2
, l3
, l4
, n
, s0
, e0
, e
, t
;
2765 tree trip
, nthreads
, threadid
;
2767 basic_block entry_bb
, exit_bb
, body_bb
, seq_start_bb
, iter_part_bb
;
2768 basic_block trip_update_bb
, cont_bb
, fin_bb
;
2770 block_stmt_iterator si
;
2772 type
= TREE_TYPE (fd
->v
);
2773 utype
= lang_hooks
.types
.unsigned_type (type
);
2775 entry_bb
= region
->entry
;
2776 iter_part_bb
= create_empty_bb (entry_bb
);
2777 seq_start_bb
= create_empty_bb (iter_part_bb
);
2778 body_bb
= single_succ (entry_bb
);
2779 cont_bb
= region
->cont
;
2780 trip_update_bb
= create_empty_bb (cont_bb
);
2781 fin_bb
= single_succ (cont_bb
);
2782 exit_bb
= region
->exit
;
2784 l0
= tree_block_label (iter_part_bb
);
2785 l1
= tree_block_label (seq_start_bb
);
2786 l2
= tree_block_label (body_bb
);
2787 l3
= tree_block_label (trip_update_bb
);
2788 l4
= tree_block_label (fin_bb
);
2790 /* Trip and adjustment setup goes in ENTRY_BB. */
2791 list
= alloc_stmt_list ();
2793 t
= built_in_decls
[BUILT_IN_OMP_GET_NUM_THREADS
];
2794 t
= build_function_call_expr (t
, NULL
);
2795 t
= fold_convert (utype
, t
);
2796 nthreads
= get_formal_tmp_var (t
, &list
);
2798 t
= built_in_decls
[BUILT_IN_OMP_GET_THREAD_NUM
];
2799 t
= build_function_call_expr (t
, NULL
);
2800 t
= fold_convert (utype
, t
);
2801 threadid
= get_formal_tmp_var (t
, &list
);
2803 fd
->n1
= fold_convert (type
, fd
->n1
);
2804 if (!is_gimple_val (fd
->n1
))
2805 fd
->n1
= get_formal_tmp_var (fd
->n1
, &list
);
2807 fd
->n2
= fold_convert (type
, fd
->n2
);
2808 if (!is_gimple_val (fd
->n2
))
2809 fd
->n2
= get_formal_tmp_var (fd
->n2
, &list
);
2811 fd
->step
= fold_convert (type
, fd
->step
);
2812 if (!is_gimple_val (fd
->step
))
2813 fd
->step
= get_formal_tmp_var (fd
->step
, &list
);
2815 fd
->chunk_size
= fold_convert (utype
, fd
->chunk_size
);
2816 if (!is_gimple_val (fd
->chunk_size
))
2817 fd
->chunk_size
= get_formal_tmp_var (fd
->chunk_size
, &list
);
2819 t
= build_int_cst (type
, (fd
->cond_code
== LT_EXPR
? -1 : 1));
2820 t
= fold_build2 (PLUS_EXPR
, type
, fd
->step
, t
);
2821 t
= fold_build2 (PLUS_EXPR
, type
, t
, fd
->n2
);
2822 t
= fold_build2 (MINUS_EXPR
, type
, t
, fd
->n1
);
2823 t
= fold_build2 (TRUNC_DIV_EXPR
, type
, t
, fd
->step
);
2824 t
= fold_convert (utype
, t
);
2825 if (is_gimple_val (t
))
2828 n
= get_formal_tmp_var (t
, &list
);
2830 t
= build_int_cst (utype
, 0);
2831 trip
= get_initialized_tmp_var (t
, &list
, NULL
);
2833 si
= bsi_last (entry_bb
);
2834 gcc_assert (TREE_CODE (bsi_stmt (si
)) == OMP_FOR
);
2835 bsi_insert_after (&si
, list
, BSI_SAME_STMT
);
2836 bsi_remove (&si
, true);
2838 /* Iteration space partitioning goes in ITER_PART_BB. */
2839 list
= alloc_stmt_list ();
2841 t
= build2 (MULT_EXPR
, utype
, trip
, nthreads
);
2842 t
= build2 (PLUS_EXPR
, utype
, t
, threadid
);
2843 t
= build2 (MULT_EXPR
, utype
, t
, fd
->chunk_size
);
2844 s0
= get_formal_tmp_var (t
, &list
);
2846 t
= build2 (PLUS_EXPR
, utype
, s0
, fd
->chunk_size
);
2847 t
= build2 (MIN_EXPR
, utype
, t
, n
);
2848 e0
= get_formal_tmp_var (t
, &list
);
2850 t
= build2 (LT_EXPR
, boolean_type_node
, s0
, n
);
2851 t
= build3 (COND_EXPR
, void_type_node
, t
,
2852 build_and_jump (&l1
), build_and_jump (&l4
));
2853 append_to_statement_list (t
, &list
);
2855 si
= bsi_start (iter_part_bb
);
2856 bsi_insert_after (&si
, list
, BSI_CONTINUE_LINKING
);
2858 /* Setup code for sequential iteration goes in SEQ_START_BB. */
2859 list
= alloc_stmt_list ();
2861 t
= fold_convert (type
, s0
);
2862 t
= build2 (MULT_EXPR
, type
, t
, fd
->step
);
2863 t
= build2 (PLUS_EXPR
, type
, t
, fd
->n1
);
2864 t
= build2 (MODIFY_EXPR
, void_type_node
, fd
->v
, t
);
2865 gimplify_and_add (t
, &list
);
2867 t
= fold_convert (type
, e0
);
2868 t
= build2 (MULT_EXPR
, type
, t
, fd
->step
);
2869 t
= build2 (PLUS_EXPR
, type
, t
, fd
->n1
);
2870 e
= get_formal_tmp_var (t
, &list
);
2872 si
= bsi_start (seq_start_bb
);
2873 bsi_insert_after (&si
, list
, BSI_CONTINUE_LINKING
);
2875 /* The code controlling the sequential loop goes in CONT_BB,
2876 replacing the OMP_CONTINUE. */
2877 list
= alloc_stmt_list ();
2879 t
= build2 (PLUS_EXPR
, type
, fd
->v
, fd
->step
);
2880 t
= build2 (MODIFY_EXPR
, void_type_node
, fd
->v
, t
);
2881 gimplify_and_add (t
, &list
);
2883 t
= build2 (fd
->cond_code
, boolean_type_node
, fd
->v
, e
);
2884 t
= get_formal_tmp_var (t
, &list
);
2885 t
= build3 (COND_EXPR
, void_type_node
, t
,
2886 build_and_jump (&l2
), build_and_jump (&l3
));
2887 append_to_statement_list (t
, &list
);
2889 si
= bsi_last (cont_bb
);
2890 gcc_assert (TREE_CODE (bsi_stmt (si
)) == OMP_CONTINUE
);
2891 bsi_insert_after (&si
, list
, BSI_SAME_STMT
);
2892 bsi_remove (&si
, true);
2894 /* Trip update code goes into TRIP_UPDATE_BB. */
2895 list
= alloc_stmt_list ();
2897 t
= build_int_cst (utype
, 1);
2898 t
= build2 (PLUS_EXPR
, utype
, trip
, t
);
2899 t
= build2 (MODIFY_EXPR
, void_type_node
, trip
, t
);
2900 gimplify_and_add (t
, &list
);
2902 si
= bsi_start (trip_update_bb
);
2903 bsi_insert_after (&si
, list
, BSI_CONTINUE_LINKING
);
2905 /* Replace the OMP_RETURN with a barrier, or nothing. */
2906 si
= bsi_last (exit_bb
);
2907 if (!OMP_RETURN_NOWAIT (bsi_stmt (si
)))
2909 list
= alloc_stmt_list ();
2910 build_omp_barrier (&list
);
2911 bsi_insert_after (&si
, list
, BSI_SAME_STMT
);
2913 bsi_remove (&si
, true);
2915 /* Connect the new blocks. */
2916 remove_edge (single_succ_edge (entry_bb
));
2917 make_edge (entry_bb
, iter_part_bb
, EDGE_FALLTHRU
);
2919 make_edge (iter_part_bb
, seq_start_bb
, EDGE_TRUE_VALUE
);
2920 make_edge (iter_part_bb
, fin_bb
, EDGE_FALSE_VALUE
);
2922 make_edge (seq_start_bb
, body_bb
, EDGE_FALLTHRU
);
2924 remove_edge (single_succ_edge (cont_bb
));
2925 make_edge (cont_bb
, body_bb
, EDGE_TRUE_VALUE
);
2926 make_edge (cont_bb
, trip_update_bb
, EDGE_FALSE_VALUE
);
2928 make_edge (trip_update_bb
, iter_part_bb
, EDGE_FALLTHRU
);
2932 /* Expand the OpenMP loop defined by REGION. */
2935 expand_omp_for (struct omp_region
*region
)
2937 struct omp_for_data fd
;
2939 push_gimplify_context ();
2941 extract_omp_for_data (last_stmt (region
->entry
), &fd
);
2942 region
->sched_kind
= fd
.sched_kind
;
2944 if (fd
.sched_kind
== OMP_CLAUSE_SCHEDULE_STATIC
&& !fd
.have_ordered
)
2946 if (fd
.chunk_size
== NULL
)
2947 expand_omp_for_static_nochunk (region
, &fd
);
2949 expand_omp_for_static_chunk (region
, &fd
);
2953 int fn_index
= fd
.sched_kind
+ fd
.have_ordered
* 4;
2954 int start_ix
= BUILT_IN_GOMP_LOOP_STATIC_START
+ fn_index
;
2955 int next_ix
= BUILT_IN_GOMP_LOOP_STATIC_NEXT
+ fn_index
;
2956 expand_omp_for_generic (region
, &fd
, start_ix
, next_ix
);
2959 pop_gimplify_context (NULL
);
2963 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
2965 v = GOMP_sections_start (n);
2982 v = GOMP_sections_next ();
2987 If this is a combined parallel sections, replace the call to
2988 GOMP_sections_start with 'goto L1'. */
2991 expand_omp_sections (struct omp_region
*region
)
2993 tree label_vec
, l0
, l1
, l2
, t
, u
, v
, sections_stmt
;
2995 basic_block entry_bb
, exit_bb
, l0_bb
, l1_bb
, l2_bb
, default_bb
;
2996 block_stmt_iterator si
;
2997 struct omp_region
*inner
;
3000 entry_bb
= region
->entry
;
3001 l0_bb
= create_empty_bb (entry_bb
);
3002 l1_bb
= region
->cont
;
3003 l2_bb
= single_succ (l1_bb
);
3004 default_bb
= create_empty_bb (l1_bb
->prev_bb
);
3005 exit_bb
= region
->exit
;
3007 l0
= tree_block_label (l0_bb
);
3008 l1
= tree_block_label (l1_bb
);
3009 l2
= tree_block_label (l2_bb
);
3011 v
= create_tmp_var (unsigned_type_node
, ".section");
3013 /* We will build a switch() with enough cases for all the
3014 OMP_SECTION regions, a '0' case to handle the end of more work
3015 and a default case to abort if something goes wrong. */
3016 len
= EDGE_COUNT (entry_bb
->succs
);
3017 label_vec
= make_tree_vec (len
+ 2);
3019 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
3020 OMP_SECTIONS statement. */
3021 si
= bsi_last (entry_bb
);
3022 sections_stmt
= bsi_stmt (si
);
3023 gcc_assert (TREE_CODE (sections_stmt
) == OMP_SECTIONS
);
3024 if (!is_combined_parallel (region
))
3026 /* If we are not inside a combined parallel+sections region,
3027 call GOMP_sections_start. */
3028 t
= build_int_cst (unsigned_type_node
, len
);
3029 t
= tree_cons (NULL
, t
, NULL
);
3030 u
= built_in_decls
[BUILT_IN_GOMP_SECTIONS_START
];
3031 t
= build_function_call_expr (u
, t
);
3032 t
= build2 (MODIFY_EXPR
, void_type_node
, v
, t
);
3033 bsi_insert_after (&si
, t
, BSI_SAME_STMT
);
3035 bsi_remove (&si
, true);
3037 /* The switch() statement replacing OMP_SECTIONS goes in L0_BB. */
3038 si
= bsi_start (l0_bb
);
3040 t
= build3 (SWITCH_EXPR
, void_type_node
, v
, NULL
, label_vec
);
3041 bsi_insert_after (&si
, t
, BSI_CONTINUE_LINKING
);
3043 t
= build3 (CASE_LABEL_EXPR
, void_type_node
,
3044 build_int_cst (unsigned_type_node
, 0), NULL
, l2
);
3045 TREE_VEC_ELT (label_vec
, 0) = t
;
3046 make_edge (l0_bb
, l2_bb
, 0);
3048 /* Convert each OMP_SECTION into a CASE_LABEL_EXPR. */
3049 for (inner
= region
->inner
, i
= 1; inner
; inner
= inner
->next
, ++i
)
3051 basic_block s_entry_bb
, s_exit_bb
;
3053 s_entry_bb
= inner
->entry
;
3054 s_exit_bb
= inner
->exit
;
3056 t
= tree_block_label (s_entry_bb
);
3057 u
= build_int_cst (unsigned_type_node
, i
);
3058 u
= build3 (CASE_LABEL_EXPR
, void_type_node
, u
, NULL
, t
);
3059 TREE_VEC_ELT (label_vec
, i
) = u
;
3061 si
= bsi_last (s_entry_bb
);
3062 gcc_assert (TREE_CODE (bsi_stmt (si
)) == OMP_SECTION
);
3063 gcc_assert (i
< len
|| OMP_SECTION_LAST (bsi_stmt (si
)));
3064 bsi_remove (&si
, true);
3066 si
= bsi_last (s_exit_bb
);
3067 gcc_assert (TREE_CODE (bsi_stmt (si
)) == OMP_RETURN
);
3068 bsi_remove (&si
, true);
3070 e
= single_pred_edge (s_entry_bb
);
3072 redirect_edge_pred (e
, l0_bb
);
3074 single_succ_edge (s_entry_bb
)->flags
= EDGE_FALLTHRU
;
3075 single_succ_edge (s_exit_bb
)->flags
= EDGE_FALLTHRU
;
3078 /* Error handling code goes in DEFAULT_BB. */
3079 t
= tree_block_label (default_bb
);
3080 u
= build3 (CASE_LABEL_EXPR
, void_type_node
, NULL
, NULL
, t
);
3081 TREE_VEC_ELT (label_vec
, len
+ 1) = u
;
3082 make_edge (l0_bb
, default_bb
, 0);
3084 si
= bsi_start (default_bb
);
3085 t
= built_in_decls
[BUILT_IN_TRAP
];
3086 t
= build_function_call_expr (t
, NULL
);
3087 bsi_insert_after (&si
, t
, BSI_CONTINUE_LINKING
);
3089 /* Code to get the next section goes in L1_BB. */
3090 si
= bsi_last (l1_bb
);
3091 gcc_assert (TREE_CODE (bsi_stmt (si
)) == OMP_CONTINUE
);
3093 t
= built_in_decls
[BUILT_IN_GOMP_SECTIONS_NEXT
];
3094 t
= build_function_call_expr (t
, NULL
);
3095 t
= build2 (MODIFY_EXPR
, void_type_node
, v
, t
);
3096 bsi_insert_after (&si
, t
, BSI_SAME_STMT
);
3097 bsi_remove (&si
, true);
3099 /* Cleanup function replaces OMP_RETURN in EXIT_BB. */
3100 si
= bsi_last (exit_bb
);
3101 if (OMP_RETURN_NOWAIT (bsi_stmt (si
)))
3102 t
= built_in_decls
[BUILT_IN_GOMP_SECTIONS_END_NOWAIT
];
3104 t
= built_in_decls
[BUILT_IN_GOMP_SECTIONS_END
];
3105 t
= build_function_call_expr (t
, NULL
);
3106 bsi_insert_after (&si
, t
, BSI_SAME_STMT
);
3107 bsi_remove (&si
, true);
3109 /* Connect the new blocks. */
3110 if (is_combined_parallel (region
))
3112 /* If this was a combined parallel+sections region, we did not
3113 emit a GOMP_sections_start in the entry block, so we just
3114 need to jump to L1_BB to get the next section. */
3115 make_edge (entry_bb
, l1_bb
, EDGE_FALLTHRU
);
3118 make_edge (entry_bb
, l0_bb
, EDGE_FALLTHRU
);
3120 e
= single_succ_edge (l1_bb
);
3121 redirect_edge_succ (e
, l0_bb
);
3122 e
->flags
= EDGE_FALLTHRU
;
3126 /* Expand code for an OpenMP single directive. We've already expanded
3127 much of the code, here we simply place the GOMP_barrier call. */
3130 expand_omp_single (struct omp_region
*region
)
3132 basic_block entry_bb
, exit_bb
;
3133 block_stmt_iterator si
;
3134 bool need_barrier
= false;
3136 entry_bb
= region
->entry
;
3137 exit_bb
= region
->exit
;
3139 si
= bsi_last (entry_bb
);
3140 /* The terminal barrier at the end of a GOMP_single_copy sequence cannot
3141 be removed. We need to ensure that the thread that entered the single
3142 does not exit before the data is copied out by the other threads. */
3143 if (find_omp_clause (OMP_SINGLE_CLAUSES (bsi_stmt (si
)),
3144 OMP_CLAUSE_COPYPRIVATE
))
3145 need_barrier
= true;
3146 gcc_assert (TREE_CODE (bsi_stmt (si
)) == OMP_SINGLE
);
3147 bsi_remove (&si
, true);
3148 single_succ_edge (entry_bb
)->flags
= EDGE_FALLTHRU
;
3150 si
= bsi_last (exit_bb
);
3151 if (!OMP_RETURN_NOWAIT (bsi_stmt (si
)) || need_barrier
)
3153 tree t
= alloc_stmt_list ();
3154 build_omp_barrier (&t
);
3155 bsi_insert_after (&si
, t
, BSI_SAME_STMT
);
3157 bsi_remove (&si
, true);
3158 single_succ_edge (exit_bb
)->flags
= EDGE_FALLTHRU
;
3162 /* Generic expansion for OpenMP synchronization directives: master,
3163 ordered and critical. All we need to do here is remove the entry
3164 and exit markers for REGION. */
3167 expand_omp_synch (struct omp_region
*region
)
3169 basic_block entry_bb
, exit_bb
;
3170 block_stmt_iterator si
;
3172 entry_bb
= region
->entry
;
3173 exit_bb
= region
->exit
;
3175 si
= bsi_last (entry_bb
);
3176 gcc_assert (TREE_CODE (bsi_stmt (si
)) == OMP_SINGLE
3177 || TREE_CODE (bsi_stmt (si
)) == OMP_MASTER
3178 || TREE_CODE (bsi_stmt (si
)) == OMP_ORDERED
3179 || TREE_CODE (bsi_stmt (si
)) == OMP_CRITICAL
);
3180 bsi_remove (&si
, true);
3181 single_succ_edge (entry_bb
)->flags
= EDGE_FALLTHRU
;
3183 si
= bsi_last (exit_bb
);
3184 gcc_assert (TREE_CODE (bsi_stmt (si
)) == OMP_RETURN
);
3185 bsi_remove (&si
, true);
3186 single_succ_edge (exit_bb
)->flags
= EDGE_FALLTHRU
;
3190 /* Expand the parallel region tree rooted at REGION. Expansion
3191 proceeds in depth-first order. Innermost regions are expanded
3192 first. This way, parallel regions that require a new function to
3193 be created (e.g., OMP_PARALLEL) can be expanded without having any
3194 internal dependencies in their body. */
3197 expand_omp (struct omp_region
*region
)
3202 expand_omp (region
->inner
);
3204 switch (region
->type
)
3207 expand_omp_parallel (region
);
3211 expand_omp_for (region
);
3215 expand_omp_sections (region
);
3219 /* Individual omp sections are handled together with their
3220 parent OMP_SECTIONS region. */
3224 expand_omp_single (region
);
3230 expand_omp_synch (region
);
3237 region
= region
->next
;
3242 /* Helper for build_omp_regions. Scan the dominator tree starting at
3243 block BB. PARENT is the region that contains BB. */
3246 build_omp_regions_1 (basic_block bb
, struct omp_region
*parent
)
3248 block_stmt_iterator si
;
3253 if (!bsi_end_p (si
) && OMP_DIRECTIVE_P (bsi_stmt (si
)))
3255 struct omp_region
*region
;
3256 enum tree_code code
;
3258 stmt
= bsi_stmt (si
);
3259 code
= TREE_CODE (stmt
);
3261 if (code
== OMP_RETURN
)
3263 /* STMT is the return point out of region PARENT. Mark it
3264 as the exit point and make PARENT the immediately
3265 enclosing region. */
3266 gcc_assert (parent
);
3269 parent
= parent
->outer
;
3271 /* If REGION is a parallel region, determine whether it is
3272 a combined parallel+workshare region. */
3273 if (region
->type
== OMP_PARALLEL
)
3274 determine_parallel_type (region
);
3276 else if (code
== OMP_CONTINUE
)
3278 gcc_assert (parent
);
3283 /* Otherwise, this directive becomes the parent for a new
3285 region
= new_omp_region (bb
, code
, parent
);
3290 for (son
= first_dom_son (CDI_DOMINATORS
, bb
);
3292 son
= next_dom_son (CDI_DOMINATORS
, son
))
3293 build_omp_regions_1 (son
, parent
);
3297 /* Scan the CFG and build a tree of OMP regions. Return the root of
3298 the OMP region tree. */
3301 build_omp_regions (void)
3303 gcc_assert (root_omp_region
== NULL
);
3304 calculate_dominance_info (CDI_DOMINATORS
);
3305 build_omp_regions_1 (ENTRY_BLOCK_PTR
, NULL
);
3309 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
3312 execute_expand_omp (void)
3314 build_omp_regions ();
3316 if (!root_omp_region
)
3321 fprintf (dump_file
, "\nOMP region tree\n\n");
3322 dump_omp_region (dump_file
, root_omp_region
, 0);
3323 fprintf (dump_file
, "\n");
3326 remove_exit_barriers (root_omp_region
);
3328 expand_omp (root_omp_region
);
3330 free_dominance_info (CDI_DOMINATORS
);
3331 free_dominance_info (CDI_POST_DOMINATORS
);
3332 cleanup_tree_cfg ();
3334 free_omp_regions ();
3340 gate_expand_omp (void)
3342 return flag_openmp
!= 0 && errorcount
== 0;
3345 struct tree_opt_pass pass_expand_omp
=
3347 "ompexp", /* name */
3348 gate_expand_omp
, /* gate */
3349 execute_expand_omp
, /* execute */
3352 0, /* static_pass_number */
3354 PROP_gimple_any
, /* properties_required */
3355 PROP_gimple_lomp
, /* properties_provided */
3356 0, /* properties_destroyed */
3357 0, /* todo_flags_start */
3358 TODO_dump_func
, /* todo_flags_finish */
3362 /* Routines to lower OpenMP directives into OMP-GIMPLE. */
3364 /* Lower the OpenMP sections directive in *STMT_P. */
3367 lower_omp_sections (tree
*stmt_p
, omp_context
*ctx
)
3369 tree new_stmt
, stmt
, body
, bind
, block
, ilist
, olist
, new_body
;
3371 tree_stmt_iterator tsi
;
3376 push_gimplify_context ();
3380 lower_rec_input_clauses (OMP_SECTIONS_CLAUSES (stmt
), &ilist
, &dlist
, ctx
);
3382 tsi
= tsi_start (OMP_SECTIONS_BODY (stmt
));
3383 for (len
= 0; !tsi_end_p (tsi
); len
++, tsi_next (&tsi
))
3386 tsi
= tsi_start (OMP_SECTIONS_BODY (stmt
));
3387 body
= alloc_stmt_list ();
3388 for (i
= 0; i
< len
; i
++, tsi_next (&tsi
))
3391 tree sec_start
, sec_end
;
3393 sec_start
= tsi_stmt (tsi
);
3394 sctx
= maybe_lookup_ctx (sec_start
);
3397 append_to_statement_list (sec_start
, &body
);
3399 lower_omp (&OMP_SECTION_BODY (sec_start
), sctx
);
3400 append_to_statement_list (OMP_SECTION_BODY (sec_start
), &body
);
3401 OMP_SECTION_BODY (sec_start
) = NULL
;
3405 tree l
= alloc_stmt_list ();
3406 lower_lastprivate_clauses (OMP_SECTIONS_CLAUSES (stmt
), NULL
,
3408 append_to_statement_list (l
, &body
);
3409 OMP_SECTION_LAST (sec_start
) = 1;
3412 sec_end
= make_node (OMP_RETURN
);
3413 append_to_statement_list (sec_end
, &body
);
3416 block
= make_node (BLOCK
);
3417 bind
= build3 (BIND_EXPR
, void_type_node
, NULL
, body
, block
);
3418 maybe_catch_exception (&BIND_EXPR_BODY (bind
));
3421 lower_reduction_clauses (OMP_SECTIONS_CLAUSES (stmt
), &olist
, ctx
);
3423 pop_gimplify_context (NULL_TREE
);
3424 record_vars_into (ctx
->block_vars
, ctx
->cb
.dst_fn
);
3426 new_stmt
= build3 (BIND_EXPR
, void_type_node
, NULL
, NULL
, NULL
);
3427 TREE_SIDE_EFFECTS (new_stmt
) = 1;
3429 new_body
= alloc_stmt_list ();
3430 append_to_statement_list (ilist
, &new_body
);
3431 append_to_statement_list (stmt
, &new_body
);
3432 append_to_statement_list (bind
, &new_body
);
3434 t
= make_node (OMP_CONTINUE
);
3435 append_to_statement_list (t
, &new_body
);
3437 append_to_statement_list (olist
, &new_body
);
3438 append_to_statement_list (dlist
, &new_body
);
3440 t
= make_node (OMP_RETURN
);
3441 OMP_RETURN_NOWAIT (t
) = !!find_omp_clause (OMP_SECTIONS_CLAUSES (stmt
),
3443 append_to_statement_list (t
, &new_body
);
3445 BIND_EXPR_BODY (new_stmt
) = new_body
;
3446 OMP_SECTIONS_BODY (stmt
) = NULL
;
3452 /* A subroutine of lower_omp_single. Expand the simple form of
3453 an OMP_SINGLE, without a copyprivate clause:
3455 if (GOMP_single_start ())
3457 [ GOMP_barrier (); ] -> unless 'nowait' is present.
3459 FIXME. It may be better to delay expanding the logic of this until
3460 pass_expand_omp. The expanded logic may make the job more difficult
3461 to a synchronization analysis pass. */
3464 lower_omp_single_simple (tree single_stmt
, tree
*pre_p
)
3468 t
= built_in_decls
[BUILT_IN_GOMP_SINGLE_START
];
3469 t
= build_function_call_expr (t
, NULL
);
3470 t
= build3 (COND_EXPR
, void_type_node
, t
,
3471 OMP_SINGLE_BODY (single_stmt
), NULL
);
3472 gimplify_and_add (t
, pre_p
);
3476 /* A subroutine of lower_omp_single. Expand the simple form of
3477 an OMP_SINGLE, with a copyprivate clause:
3479 #pragma omp single copyprivate (a, b, c)
3481 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
3484 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
3490 GOMP_single_copy_end (©out);
3501 FIXME. It may be better to delay expanding the logic of this until
3502 pass_expand_omp. The expanded logic may make the job more difficult
3503 to a synchronization analysis pass. */
3506 lower_omp_single_copy (tree single_stmt
, tree
*pre_p
, omp_context
*ctx
)
3508 tree ptr_type
, t
, args
, l0
, l1
, l2
, copyin_seq
;
3510 ctx
->sender_decl
= create_tmp_var (ctx
->record_type
, ".omp_copy_o");
3512 ptr_type
= build_pointer_type (ctx
->record_type
);
3513 ctx
->receiver_decl
= create_tmp_var (ptr_type
, ".omp_copy_i");
3515 l0
= create_artificial_label ();
3516 l1
= create_artificial_label ();
3517 l2
= create_artificial_label ();
3519 t
= built_in_decls
[BUILT_IN_GOMP_SINGLE_COPY_START
];
3520 t
= build_function_call_expr (t
, NULL
);
3521 t
= fold_convert (ptr_type
, t
);
3522 t
= build2 (MODIFY_EXPR
, void_type_node
, ctx
->receiver_decl
, t
);
3523 gimplify_and_add (t
, pre_p
);
3525 t
= build2 (EQ_EXPR
, boolean_type_node
, ctx
->receiver_decl
,
3526 build_int_cst (ptr_type
, 0));
3527 t
= build3 (COND_EXPR
, void_type_node
, t
,
3528 build_and_jump (&l0
), build_and_jump (&l1
));
3529 gimplify_and_add (t
, pre_p
);
3531 t
= build1 (LABEL_EXPR
, void_type_node
, l0
);
3532 gimplify_and_add (t
, pre_p
);
3534 append_to_statement_list (OMP_SINGLE_BODY (single_stmt
), pre_p
);
3537 lower_copyprivate_clauses (OMP_SINGLE_CLAUSES (single_stmt
), pre_p
,
3540 t
= build_fold_addr_expr (ctx
->sender_decl
);
3541 args
= tree_cons (NULL
, t
, NULL
);
3542 t
= built_in_decls
[BUILT_IN_GOMP_SINGLE_COPY_END
];
3543 t
= build_function_call_expr (t
, args
);
3544 gimplify_and_add (t
, pre_p
);
3546 t
= build_and_jump (&l2
);
3547 gimplify_and_add (t
, pre_p
);
3549 t
= build1 (LABEL_EXPR
, void_type_node
, l1
);
3550 gimplify_and_add (t
, pre_p
);
3552 append_to_statement_list (copyin_seq
, pre_p
);
3554 t
= build1 (LABEL_EXPR
, void_type_node
, l2
);
3555 gimplify_and_add (t
, pre_p
);
3559 /* Expand code for an OpenMP single directive. */
3562 lower_omp_single (tree
*stmt_p
, omp_context
*ctx
)
3564 tree t
, bind
, block
, single_stmt
= *stmt_p
, dlist
;
3566 push_gimplify_context ();
3568 block
= make_node (BLOCK
);
3569 *stmt_p
= bind
= build3 (BIND_EXPR
, void_type_node
, NULL
, NULL
, block
);
3570 TREE_SIDE_EFFECTS (bind
) = 1;
3572 lower_rec_input_clauses (OMP_SINGLE_CLAUSES (single_stmt
),
3573 &BIND_EXPR_BODY (bind
), &dlist
, ctx
);
3574 lower_omp (&OMP_SINGLE_BODY (single_stmt
), ctx
);
3575 maybe_catch_exception (&OMP_SINGLE_BODY (single_stmt
));
3577 append_to_statement_list (single_stmt
, &BIND_EXPR_BODY (bind
));
3579 if (ctx
->record_type
)
3580 lower_omp_single_copy (single_stmt
, &BIND_EXPR_BODY (bind
), ctx
);
3582 lower_omp_single_simple (single_stmt
, &BIND_EXPR_BODY (bind
));
3584 OMP_SINGLE_BODY (single_stmt
) = NULL
;
3586 append_to_statement_list (dlist
, &BIND_EXPR_BODY (bind
));
3588 t
= make_node (OMP_RETURN
);
3589 OMP_RETURN_NOWAIT (t
) = !!find_omp_clause (OMP_SINGLE_CLAUSES (single_stmt
),
3591 append_to_statement_list (t
, &BIND_EXPR_BODY (bind
));
3593 pop_gimplify_context (bind
);
3595 BIND_EXPR_VARS (bind
) = chainon (BIND_EXPR_VARS (bind
), ctx
->block_vars
);
3596 BLOCK_VARS (block
) = BIND_EXPR_VARS (bind
);
3600 /* Expand code for an OpenMP master directive. */
3603 lower_omp_master (tree
*stmt_p
, omp_context
*ctx
)
3605 tree bind
, block
, stmt
= *stmt_p
, lab
= NULL
, x
;
3607 push_gimplify_context ();
3609 block
= make_node (BLOCK
);
3610 *stmt_p
= bind
= build3 (BIND_EXPR
, void_type_node
, NULL
, NULL
, block
);
3611 TREE_SIDE_EFFECTS (bind
) = 1;
3613 append_to_statement_list (stmt
, &BIND_EXPR_BODY (bind
));
3615 x
= built_in_decls
[BUILT_IN_OMP_GET_THREAD_NUM
];
3616 x
= build_function_call_expr (x
, NULL
);
3617 x
= build2 (EQ_EXPR
, boolean_type_node
, x
, integer_zero_node
);
3618 x
= build3 (COND_EXPR
, void_type_node
, x
, NULL
, build_and_jump (&lab
));
3619 gimplify_and_add (x
, &BIND_EXPR_BODY (bind
));
3621 lower_omp (&OMP_MASTER_BODY (stmt
), ctx
);
3622 maybe_catch_exception (&OMP_MASTER_BODY (stmt
));
3623 append_to_statement_list (OMP_MASTER_BODY (stmt
), &BIND_EXPR_BODY (bind
));
3624 OMP_MASTER_BODY (stmt
) = NULL
;
3626 x
= build1 (LABEL_EXPR
, void_type_node
, lab
);
3627 gimplify_and_add (x
, &BIND_EXPR_BODY (bind
));
3629 x
= make_node (OMP_RETURN
);
3630 OMP_RETURN_NOWAIT (x
) = 1;
3631 append_to_statement_list (x
, &BIND_EXPR_BODY (bind
));
3633 pop_gimplify_context (bind
);
3635 BIND_EXPR_VARS (bind
) = chainon (BIND_EXPR_VARS (bind
), ctx
->block_vars
);
3636 BLOCK_VARS (block
) = BIND_EXPR_VARS (bind
);
3640 /* Expand code for an OpenMP ordered directive. */
3643 lower_omp_ordered (tree
*stmt_p
, omp_context
*ctx
)
3645 tree bind
, block
, stmt
= *stmt_p
, x
;
3647 push_gimplify_context ();
3649 block
= make_node (BLOCK
);
3650 *stmt_p
= bind
= build3 (BIND_EXPR
, void_type_node
, NULL
, NULL
, block
);
3651 TREE_SIDE_EFFECTS (bind
) = 1;
3653 append_to_statement_list (stmt
, &BIND_EXPR_BODY (bind
));
3655 x
= built_in_decls
[BUILT_IN_GOMP_ORDERED_START
];
3656 x
= build_function_call_expr (x
, NULL
);
3657 gimplify_and_add (x
, &BIND_EXPR_BODY (bind
));
3659 lower_omp (&OMP_ORDERED_BODY (stmt
), ctx
);
3660 maybe_catch_exception (&OMP_ORDERED_BODY (stmt
));
3661 append_to_statement_list (OMP_ORDERED_BODY (stmt
), &BIND_EXPR_BODY (bind
));
3662 OMP_ORDERED_BODY (stmt
) = NULL
;
3664 x
= built_in_decls
[BUILT_IN_GOMP_ORDERED_END
];
3665 x
= build_function_call_expr (x
, NULL
);
3666 gimplify_and_add (x
, &BIND_EXPR_BODY (bind
));
3668 x
= make_node (OMP_RETURN
);
3669 OMP_RETURN_NOWAIT (x
) = 1;
3670 append_to_statement_list (x
, &BIND_EXPR_BODY (bind
));
3672 pop_gimplify_context (bind
);
3674 BIND_EXPR_VARS (bind
) = chainon (BIND_EXPR_VARS (bind
), ctx
->block_vars
);
3675 BLOCK_VARS (block
) = BIND_EXPR_VARS (bind
);
3679 /* Gimplify an OMP_CRITICAL statement. This is a relatively simple
3680 substitution of a couple of function calls. But in the NAMED case,
3681 requires that languages coordinate a symbol name. It is therefore
3682 best put here in common code. */
3684 static GTY((param1_is (tree
), param2_is (tree
)))
3685 splay_tree critical_name_mutexes
;
3688 lower_omp_critical (tree
*stmt_p
, omp_context
*ctx
)
3690 tree bind
, block
, stmt
= *stmt_p
;
3691 tree t
, lock
, unlock
, name
;
3693 name
= OMP_CRITICAL_NAME (stmt
);
3699 if (!critical_name_mutexes
)
3700 critical_name_mutexes
3701 = splay_tree_new_ggc (splay_tree_compare_pointers
);
3703 n
= splay_tree_lookup (critical_name_mutexes
, (splay_tree_key
) name
);
3708 decl
= create_tmp_var_raw (ptr_type_node
, NULL
);
3710 new_str
= ACONCAT ((".gomp_critical_user_",
3711 IDENTIFIER_POINTER (name
), NULL
));
3712 DECL_NAME (decl
) = get_identifier (new_str
);
3713 TREE_PUBLIC (decl
) = 1;
3714 TREE_STATIC (decl
) = 1;
3715 DECL_COMMON (decl
) = 1;
3716 DECL_ARTIFICIAL (decl
) = 1;
3717 DECL_IGNORED_P (decl
) = 1;
3718 cgraph_varpool_finalize_decl (decl
);
3720 splay_tree_insert (critical_name_mutexes
, (splay_tree_key
) name
,
3721 (splay_tree_value
) decl
);
3724 decl
= (tree
) n
->value
;
3726 args
= tree_cons (NULL
, build_fold_addr_expr (decl
), NULL
);
3727 lock
= built_in_decls
[BUILT_IN_GOMP_CRITICAL_NAME_START
];
3728 lock
= build_function_call_expr (lock
, args
);
3730 args
= tree_cons (NULL
, build_fold_addr_expr (decl
), NULL
);
3731 unlock
= built_in_decls
[BUILT_IN_GOMP_CRITICAL_NAME_END
];
3732 unlock
= build_function_call_expr (unlock
, args
);
3736 lock
= built_in_decls
[BUILT_IN_GOMP_CRITICAL_START
];
3737 lock
= build_function_call_expr (lock
, NULL
);
3739 unlock
= built_in_decls
[BUILT_IN_GOMP_CRITICAL_END
];
3740 unlock
= build_function_call_expr (unlock
, NULL
);
3743 push_gimplify_context ();
3745 block
= make_node (BLOCK
);
3746 *stmt_p
= bind
= build3 (BIND_EXPR
, void_type_node
, NULL
, NULL
, block
);
3747 TREE_SIDE_EFFECTS (bind
) = 1;
3749 append_to_statement_list (stmt
, &BIND_EXPR_BODY (bind
));
3751 gimplify_and_add (lock
, &BIND_EXPR_BODY (bind
));
3753 lower_omp (&OMP_CRITICAL_BODY (stmt
), ctx
);
3754 maybe_catch_exception (&OMP_CRITICAL_BODY (stmt
));
3755 append_to_statement_list (OMP_CRITICAL_BODY (stmt
), &BIND_EXPR_BODY (bind
));
3756 OMP_CRITICAL_BODY (stmt
) = NULL
;
3758 gimplify_and_add (unlock
, &BIND_EXPR_BODY (bind
));
3760 t
= make_node (OMP_RETURN
);
3761 OMP_RETURN_NOWAIT (t
) = 1;
3762 append_to_statement_list (t
, &BIND_EXPR_BODY (bind
));
3764 pop_gimplify_context (bind
);
3765 BIND_EXPR_VARS (bind
) = chainon (BIND_EXPR_VARS (bind
), ctx
->block_vars
);
3766 BLOCK_VARS (block
) = BIND_EXPR_VARS (bind
);
3770 /* A subroutine of lower_omp_for. Generate code to emit the predicate
3771 for a lastprivate clause. Given a loop control predicate of (V
3772 cond N2), we gate the clause on (!(V cond N2)). The lowered form
3773 is appended to *BODY_P. */
3776 lower_omp_for_lastprivate (struct omp_for_data
*fd
, tree
*body_p
,
3777 struct omp_context
*ctx
)
3780 enum tree_code cond_code
;
3782 cond_code
= fd
->cond_code
;
3783 cond_code
= cond_code
== LT_EXPR
? GE_EXPR
: LE_EXPR
;
3785 /* When possible, use a strict equality expression. This can let VRP
3786 type optimizations deduce the value and remove a copy. */
3787 if (host_integerp (fd
->step
, 0))
3789 HOST_WIDE_INT step
= TREE_INT_CST_LOW (fd
->step
);
3790 if (step
== 1 || step
== -1)
3791 cond_code
= EQ_EXPR
;
3794 cond
= build2 (cond_code
, boolean_type_node
, fd
->v
, fd
->n2
);
3796 clauses
= OMP_FOR_CLAUSES (fd
->for_stmt
);
3797 lower_lastprivate_clauses (clauses
, cond
, body_p
, ctx
);
3801 /* Lower code for an OpenMP loop directive. */
3804 lower_omp_for (tree
*stmt_p
, omp_context
*ctx
)
3806 tree t
, stmt
, ilist
, dlist
, new_stmt
, *body_p
, *rhs_p
;
3807 struct omp_for_data fd
;
3811 push_gimplify_context ();
3813 lower_omp (&OMP_FOR_PRE_BODY (stmt
), ctx
);
3814 lower_omp (&OMP_FOR_BODY (stmt
), ctx
);
3816 /* Move declaration of temporaries in the loop body before we make
3818 if (TREE_CODE (OMP_FOR_BODY (stmt
)) == BIND_EXPR
)
3819 record_vars_into (BIND_EXPR_VARS (OMP_FOR_BODY (stmt
)), ctx
->cb
.dst_fn
);
3821 new_stmt
= build3 (BIND_EXPR
, void_type_node
, NULL
, NULL
, NULL
);
3822 TREE_SIDE_EFFECTS (new_stmt
) = 1;
3823 body_p
= &BIND_EXPR_BODY (new_stmt
);
3825 /* The pre-body and input clauses go before the lowered OMP_FOR. */
3828 append_to_statement_list (OMP_FOR_PRE_BODY (stmt
), body_p
);
3829 lower_rec_input_clauses (OMP_FOR_CLAUSES (stmt
), body_p
, &dlist
, ctx
);
3831 /* Lower the header expressions. At this point, we can assume that
3832 the header is of the form:
3834 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
3836 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
3837 using the .omp_data_s mapping, if needed. */
3838 rhs_p
= &TREE_OPERAND (OMP_FOR_INIT (stmt
), 1);
3839 if (!is_gimple_min_invariant (*rhs_p
))
3840 *rhs_p
= get_formal_tmp_var (*rhs_p
, body_p
);
3842 rhs_p
= &TREE_OPERAND (OMP_FOR_COND (stmt
), 1);
3843 if (!is_gimple_min_invariant (*rhs_p
))
3844 *rhs_p
= get_formal_tmp_var (*rhs_p
, body_p
);
3846 rhs_p
= &TREE_OPERAND (TREE_OPERAND (OMP_FOR_INCR (stmt
), 1), 1);
3847 if (!is_gimple_min_invariant (*rhs_p
))
3848 *rhs_p
= get_formal_tmp_var (*rhs_p
, body_p
);
3850 /* Once lowered, extract the bounds and clauses. */
3851 extract_omp_for_data (stmt
, &fd
);
3853 append_to_statement_list (stmt
, body_p
);
3855 maybe_catch_exception (&OMP_FOR_BODY (stmt
));
3856 append_to_statement_list (OMP_FOR_BODY (stmt
), body_p
);
3858 t
= make_node (OMP_CONTINUE
);
3859 append_to_statement_list (t
, body_p
);
3861 /* After the loop, add exit clauses. */
3862 lower_omp_for_lastprivate (&fd
, &dlist
, ctx
);
3863 lower_reduction_clauses (OMP_FOR_CLAUSES (stmt
), body_p
, ctx
);
3864 append_to_statement_list (dlist
, body_p
);
3866 /* Region exit marker goes at the end of the loop body. */
3867 t
= make_node (OMP_RETURN
);
3868 OMP_RETURN_NOWAIT (t
) = fd
.have_nowait
;
3869 append_to_statement_list (t
, body_p
);
3871 pop_gimplify_context (NULL_TREE
);
3872 record_vars_into (ctx
->block_vars
, ctx
->cb
.dst_fn
);
3874 OMP_FOR_BODY (stmt
) = NULL_TREE
;
3875 OMP_FOR_PRE_BODY (stmt
) = NULL_TREE
;
3880 /* Lower the OpenMP parallel directive in *STMT_P. CTX holds context
3881 information for the directive. */
3884 lower_omp_parallel (tree
*stmt_p
, omp_context
*ctx
)
3886 tree clauses
, par_bind
, par_body
, new_body
, bind
;
3887 tree olist
, ilist
, par_olist
, par_ilist
;
3888 tree stmt
, child_fn
, t
;
3892 clauses
= OMP_PARALLEL_CLAUSES (stmt
);
3893 par_bind
= OMP_PARALLEL_BODY (stmt
);
3894 par_body
= BIND_EXPR_BODY (par_bind
);
3895 child_fn
= ctx
->cb
.dst_fn
;
3897 push_gimplify_context ();
3899 par_olist
= NULL_TREE
;
3900 par_ilist
= NULL_TREE
;
3901 lower_rec_input_clauses (clauses
, &par_ilist
, &par_olist
, ctx
);
3902 lower_omp (&par_body
, ctx
);
3903 maybe_catch_exception (&par_body
);
3904 lower_reduction_clauses (clauses
, &par_olist
, ctx
);
3906 /* Declare all the variables created by mapping and the variables
3907 declared in the scope of the parallel body. */
3908 record_vars_into (ctx
->block_vars
, child_fn
);
3909 record_vars_into (BIND_EXPR_VARS (par_bind
), child_fn
);
3911 if (ctx
->record_type
)
3913 ctx
->sender_decl
= create_tmp_var (ctx
->record_type
, ".omp_data_o");
3914 OMP_PARALLEL_DATA_ARG (stmt
) = ctx
->sender_decl
;
3919 lower_send_clauses (clauses
, &ilist
, &olist
, ctx
);
3920 lower_send_shared_vars (&ilist
, &olist
, ctx
);
3922 /* Once all the expansions are done, sequence all the different
3923 fragments inside OMP_PARALLEL_BODY. */
3924 bind
= build3 (BIND_EXPR
, void_type_node
, NULL
, NULL
, NULL
);
3925 append_to_statement_list (ilist
, &BIND_EXPR_BODY (bind
));
3927 new_body
= alloc_stmt_list ();
3929 if (ctx
->record_type
)
3931 t
= build_fold_addr_expr (ctx
->sender_decl
);
3932 t
= build2 (MODIFY_EXPR
, void_type_node
, ctx
->receiver_decl
, t
);
3933 append_to_statement_list (t
, &new_body
);
3936 append_to_statement_list (par_ilist
, &new_body
);
3937 append_to_statement_list (par_body
, &new_body
);
3938 append_to_statement_list (par_olist
, &new_body
);
3939 t
= make_node (OMP_RETURN
);
3940 append_to_statement_list (t
, &new_body
);
3941 OMP_PARALLEL_BODY (stmt
) = new_body
;
3943 append_to_statement_list (stmt
, &BIND_EXPR_BODY (bind
));
3944 append_to_statement_list (olist
, &BIND_EXPR_BODY (bind
));
3948 pop_gimplify_context (NULL_TREE
);
3952 /* Pass *TP back through the gimplifier within the context determined by WI.
3953 This handles replacement of DECL_VALUE_EXPR, as well as adjusting the
3954 flags on ADDR_EXPR. */
3957 lower_regimplify (tree
*tp
, struct walk_stmt_info
*wi
)
3959 enum gimplify_status gs
;
3963 gs
= gimplify_expr (tp
, &pre
, NULL
, is_gimple_lvalue
, fb_lvalue
);
3964 else if (wi
->val_only
)
3965 gs
= gimplify_expr (tp
, &pre
, NULL
, is_gimple_val
, fb_rvalue
);
3967 gs
= gimplify_expr (tp
, &pre
, NULL
, is_gimple_formal_tmp_var
, fb_rvalue
);
3968 gcc_assert (gs
== GS_ALL_DONE
);
3971 tsi_link_before (&wi
->tsi
, pre
, TSI_SAME_STMT
);
3975 /* Callback for walk_stmts. Lower the OpenMP directive pointed by TP. */
3978 lower_omp_1 (tree
*tp
, int *walk_subtrees
, void *data
)
3980 struct walk_stmt_info
*wi
= data
;
3981 omp_context
*ctx
= wi
->info
;
3984 /* If we have issued syntax errors, avoid doing any heavy lifting.
3985 Just replace the OpenMP directives with a NOP to avoid
3986 confusing RTL expansion. */
3987 if (errorcount
&& OMP_DIRECTIVE_P (*tp
))
3989 *tp
= build_empty_stmt ();
3994 switch (TREE_CODE (*tp
))
3997 ctx
= maybe_lookup_ctx (t
);
3998 lower_omp_parallel (tp
, ctx
);
4002 ctx
= maybe_lookup_ctx (t
);
4004 lower_omp_for (tp
, ctx
);
4008 ctx
= maybe_lookup_ctx (t
);
4010 lower_omp_sections (tp
, ctx
);
4014 ctx
= maybe_lookup_ctx (t
);
4016 lower_omp_single (tp
, ctx
);
4020 ctx
= maybe_lookup_ctx (t
);
4022 lower_omp_master (tp
, ctx
);
4026 ctx
= maybe_lookup_ctx (t
);
4028 lower_omp_ordered (tp
, ctx
);
4032 ctx
= maybe_lookup_ctx (t
);
4034 lower_omp_critical (tp
, ctx
);
4038 if (ctx
&& DECL_HAS_VALUE_EXPR_P (t
))
4039 lower_regimplify (tp
, wi
);
4044 lower_regimplify (tp
, wi
);
4048 case ARRAY_RANGE_REF
:
4052 case VIEW_CONVERT_EXPR
:
4054 lower_regimplify (tp
, wi
);
4061 wi
->val_only
= true;
4062 lower_regimplify (&TREE_OPERAND (t
, 0), wi
);
4067 if (!TYPE_P (t
) && !DECL_P (t
))
4076 lower_omp (tree
*stmt_p
, omp_context
*ctx
)
4078 struct walk_stmt_info wi
;
4080 memset (&wi
, 0, sizeof (wi
));
4081 wi
.callback
= lower_omp_1
;
4084 wi
.want_locations
= true;
4086 walk_stmts (&wi
, stmt_p
);
4089 /* Main entry point. */
4092 execute_lower_omp (void)
4094 all_contexts
= splay_tree_new (splay_tree_compare_pointers
, 0,
4095 delete_omp_context
);
4097 scan_omp (&DECL_SAVED_TREE (current_function_decl
), NULL
);
4098 gcc_assert (parallel_nesting_level
== 0);
4100 if (all_contexts
->root
)
4101 lower_omp (&DECL_SAVED_TREE (current_function_decl
), NULL
);
4105 splay_tree_delete (all_contexts
);
4106 all_contexts
= NULL
;
4112 gate_lower_omp (void)
4114 return flag_openmp
!= 0;
4117 struct tree_opt_pass pass_lower_omp
=
4119 "omplower", /* name */
4120 gate_lower_omp
, /* gate */
4121 execute_lower_omp
, /* execute */
4124 0, /* static_pass_number */
4126 PROP_gimple_any
, /* properties_required */
4127 PROP_gimple_lomp
, /* properties_provided */
4128 0, /* properties_destroyed */
4129 0, /* todo_flags_start */
4130 TODO_dump_func
, /* todo_flags_finish */
4134 /* The following is a utility to diagnose OpenMP structured block violations.
4135 It is not part of the "omplower" pass, as that's invoked too late. It
4136 should be invoked by the respective front ends after gimplification. */
4138 static splay_tree all_labels
;
4140 /* Check for mismatched contexts and generate an error if needed. Return
4141 true if an error is detected. */
4144 diagnose_sb_0 (tree
*stmt_p
, tree branch_ctx
, tree label_ctx
)
4148 if ((label_ctx
? TREE_VALUE (label_ctx
) : NULL
) == branch_ctx
)
4151 /* Try to avoid confusing the user by producing and error message
4152 with correct "exit" or "enter" verbage. We prefer "exit"
4153 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
4154 if (branch_ctx
== NULL
)
4160 if (TREE_VALUE (label_ctx
) == branch_ctx
)
4165 label_ctx
= TREE_CHAIN (label_ctx
);
4170 error ("invalid exit from OpenMP structured block");
4172 error ("invalid entry to OpenMP structured block");
4174 *stmt_p
= build_empty_stmt ();
4178 /* Pass 1: Create a minimal tree of OpenMP structured blocks, and record
4179 where in the tree each label is found. */
4182 diagnose_sb_1 (tree
*tp
, int *walk_subtrees
, void *data
)
4184 struct walk_stmt_info
*wi
= data
;
4185 tree context
= (tree
) wi
->info
;
4190 switch (TREE_CODE (t
))
4195 walk_tree (&OMP_CLAUSES (t
), diagnose_sb_1
, wi
, NULL
);
4201 /* The minimal context here is just a tree of statements. */
4202 inner_context
= tree_cons (NULL
, t
, context
);
4203 wi
->info
= inner_context
;
4204 walk_stmts (wi
, &OMP_BODY (t
));
4209 walk_tree (&OMP_FOR_CLAUSES (t
), diagnose_sb_1
, wi
, NULL
);
4210 inner_context
= tree_cons (NULL
, t
, context
);
4211 wi
->info
= inner_context
;
4212 walk_tree (&OMP_FOR_INIT (t
), diagnose_sb_1
, wi
, NULL
);
4213 walk_tree (&OMP_FOR_COND (t
), diagnose_sb_1
, wi
, NULL
);
4214 walk_tree (&OMP_FOR_INCR (t
), diagnose_sb_1
, wi
, NULL
);
4215 walk_stmts (wi
, &OMP_FOR_PRE_BODY (t
));
4216 walk_stmts (wi
, &OMP_FOR_BODY (t
));
4221 splay_tree_insert (all_labels
, (splay_tree_key
) LABEL_EXPR_LABEL (t
),
4222 (splay_tree_value
) context
);
4232 /* Pass 2: Check each branch and see if its context differs from that of
4233 the destination label's context. */
4236 diagnose_sb_2 (tree
*tp
, int *walk_subtrees
, void *data
)
4238 struct walk_stmt_info
*wi
= data
;
4239 tree context
= (tree
) wi
->info
;
4244 switch (TREE_CODE (t
))
4249 walk_tree (&OMP_CLAUSES (t
), diagnose_sb_2
, wi
, NULL
);
4256 walk_stmts (wi
, &OMP_BODY (t
));
4261 walk_tree (&OMP_FOR_CLAUSES (t
), diagnose_sb_2
, wi
, NULL
);
4263 walk_tree (&OMP_FOR_INIT (t
), diagnose_sb_2
, wi
, NULL
);
4264 walk_tree (&OMP_FOR_COND (t
), diagnose_sb_2
, wi
, NULL
);
4265 walk_tree (&OMP_FOR_INCR (t
), diagnose_sb_2
, wi
, NULL
);
4266 walk_stmts (wi
, &OMP_FOR_PRE_BODY (t
));
4267 walk_stmts (wi
, &OMP_FOR_BODY (t
));
4273 tree lab
= GOTO_DESTINATION (t
);
4274 if (TREE_CODE (lab
) != LABEL_DECL
)
4277 n
= splay_tree_lookup (all_labels
, (splay_tree_key
) lab
);
4278 diagnose_sb_0 (tp
, context
, n
? (tree
) n
->value
: NULL_TREE
);
4284 tree vec
= SWITCH_LABELS (t
);
4285 int i
, len
= TREE_VEC_LENGTH (vec
);
4286 for (i
= 0; i
< len
; ++i
)
4288 tree lab
= CASE_LABEL (TREE_VEC_ELT (vec
, i
));
4289 n
= splay_tree_lookup (all_labels
, (splay_tree_key
) lab
);
4290 if (diagnose_sb_0 (tp
, context
, (tree
) n
->value
))
4297 diagnose_sb_0 (tp
, context
, NULL_TREE
);
4308 diagnose_omp_structured_block_errors (tree fndecl
)
4310 tree save_current
= current_function_decl
;
4311 struct walk_stmt_info wi
;
4313 current_function_decl
= fndecl
;
4315 all_labels
= splay_tree_new (splay_tree_compare_pointers
, 0, 0);
4317 memset (&wi
, 0, sizeof (wi
));
4318 wi
.callback
= diagnose_sb_1
;
4319 walk_stmts (&wi
, &DECL_SAVED_TREE (fndecl
));
4321 memset (&wi
, 0, sizeof (wi
));
4322 wi
.callback
= diagnose_sb_2
;
4323 wi
.want_locations
= true;
4324 wi
.want_return_expr
= true;
4325 walk_stmts (&wi
, &DECL_SAVED_TREE (fndecl
));
4327 splay_tree_delete (all_labels
);
4330 current_function_decl
= save_current
;
4333 #include "gt-omp-low.h"