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-2013 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 3, 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 COPYING3. If not see
22 <http://www.gnu.org/licenses/>. */
26 #include "coretypes.h"
31 #include "tree-iterator.h"
32 #include "tree-inline.h"
33 #include "langhooks.h"
34 #include "diagnostic-core.h"
35 #include "tree-flow.h"
39 #include "tree-pass.h"
42 #include "splay-tree.h"
48 /* Lowering of OpenMP parallel and workshare constructs proceeds in two
49 phases. The first phase scans the function looking for OMP statements
50 and then for variables that must be replaced to satisfy data sharing
51 clauses. The second phase expands code for the constructs, as well as
52 re-gimplifying things when variables have been replaced with complex
55 Final code generation is done by pass_expand_omp. The flowgraph is
56 scanned for parallel regions which are then moved to a new
57 function, to be invoked by the thread library. */
59 /* Context structure. Used to store information about each parallel
60 directive in the code. */
62 typedef struct omp_context
64 /* This field must be at the beginning, as we do "inheritance": Some
65 callback functions for tree-inline.c (e.g., omp_copy_decl)
66 receive a copy_body_data pointer that is up-casted to an
67 omp_context pointer. */
70 /* The tree of contexts corresponding to the encountered constructs. */
71 struct omp_context
*outer
;
74 /* Map variables to fields in a structure that allows communication
75 between sending and receiving threads. */
81 /* These are used just by task contexts, if task firstprivate fn is
82 needed. srecord_type is used to communicate from the thread
83 that encountered the task construct to task firstprivate fn,
84 record_type is allocated by GOMP_task, initialized by task firstprivate
85 fn and passed to the task body fn. */
86 splay_tree sfield_map
;
89 /* A chain of variables to add to the top-level block surrounding the
90 construct. In the case of a parallel, this is in the child function. */
93 /* What to do with variables with implicitly determined sharing
95 enum omp_clause_default_kind default_kind
;
97 /* Nesting depth of this context. Used to beautify error messages re
98 invalid gotos. The outermost ctx is depth 1, with depth 0 being
99 reserved for the main body of the function. */
102 /* True if this parallel directive is nested within another. */
107 struct omp_for_data_loop
109 tree v
, n1
, n2
, step
;
110 enum tree_code cond_code
;
113 /* A structure describing the main elements of a parallel loop. */
117 struct omp_for_data_loop loop
;
122 bool have_nowait
, have_ordered
;
123 enum omp_clause_schedule_kind sched_kind
;
124 struct omp_for_data_loop
*loops
;
128 static splay_tree all_contexts
;
129 static int taskreg_nesting_level
;
130 struct omp_region
*root_omp_region
;
131 static bitmap task_shared_vars
;
133 static void scan_omp (gimple_seq
*, omp_context
*);
134 static tree
scan_omp_1_op (tree
*, int *, void *);
136 #define WALK_SUBSTMTS \
140 case GIMPLE_EH_FILTER: \
141 case GIMPLE_TRANSACTION: \
142 /* The sub-statements for these should be walked. */ \
143 *handled_ops_p = false; \
146 /* Convenience function for calling scan_omp_1_op on tree operands. */
149 scan_omp_op (tree
*tp
, omp_context
*ctx
)
151 struct walk_stmt_info wi
;
153 memset (&wi
, 0, sizeof (wi
));
155 wi
.want_locations
= true;
157 return walk_tree (tp
, scan_omp_1_op
, &wi
, NULL
);
160 static void lower_omp (gimple_seq
*, omp_context
*);
161 static tree
lookup_decl_in_outer_ctx (tree
, omp_context
*);
162 static tree
maybe_lookup_decl_in_outer_ctx (tree
, omp_context
*);
164 /* Find an OpenMP clause of type KIND within CLAUSES. */
167 find_omp_clause (tree clauses
, enum omp_clause_code kind
)
169 for (; clauses
; clauses
= OMP_CLAUSE_CHAIN (clauses
))
170 if (OMP_CLAUSE_CODE (clauses
) == kind
)
176 /* Return true if CTX is for an omp parallel. */
179 is_parallel_ctx (omp_context
*ctx
)
181 return gimple_code (ctx
->stmt
) == GIMPLE_OMP_PARALLEL
;
185 /* Return true if CTX is for an omp task. */
188 is_task_ctx (omp_context
*ctx
)
190 return gimple_code (ctx
->stmt
) == GIMPLE_OMP_TASK
;
194 /* Return true if CTX is for an omp parallel or omp task. */
197 is_taskreg_ctx (omp_context
*ctx
)
199 return gimple_code (ctx
->stmt
) == GIMPLE_OMP_PARALLEL
200 || gimple_code (ctx
->stmt
) == GIMPLE_OMP_TASK
;
204 /* Return true if REGION is a combined parallel+workshare region. */
207 is_combined_parallel (struct omp_region
*region
)
209 return region
->is_combined_parallel
;
213 /* Extract the header elements of parallel loop FOR_STMT and store
217 extract_omp_for_data (gimple for_stmt
, struct omp_for_data
*fd
,
218 struct omp_for_data_loop
*loops
)
220 tree t
, var
, *collapse_iter
, *collapse_count
;
221 tree count
= NULL_TREE
, iter_type
= long_integer_type_node
;
222 struct omp_for_data_loop
*loop
;
224 struct omp_for_data_loop dummy_loop
;
225 location_t loc
= gimple_location (for_stmt
);
226 bool simd
= gimple_omp_for_kind (for_stmt
) == GF_OMP_FOR_KIND_SIMD
;
228 fd
->for_stmt
= for_stmt
;
230 fd
->collapse
= gimple_omp_for_collapse (for_stmt
);
231 if (fd
->collapse
> 1)
234 fd
->loops
= &fd
->loop
;
236 fd
->have_nowait
= fd
->have_ordered
= false;
237 fd
->sched_kind
= OMP_CLAUSE_SCHEDULE_STATIC
;
238 fd
->chunk_size
= NULL_TREE
;
239 collapse_iter
= NULL
;
240 collapse_count
= NULL
;
242 for (t
= gimple_omp_for_clauses (for_stmt
); t
; t
= OMP_CLAUSE_CHAIN (t
))
243 switch (OMP_CLAUSE_CODE (t
))
245 case OMP_CLAUSE_NOWAIT
:
246 fd
->have_nowait
= true;
248 case OMP_CLAUSE_ORDERED
:
249 fd
->have_ordered
= true;
251 case OMP_CLAUSE_SCHEDULE
:
252 fd
->sched_kind
= OMP_CLAUSE_SCHEDULE_KIND (t
);
253 fd
->chunk_size
= OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t
);
255 case OMP_CLAUSE_COLLAPSE
:
256 if (fd
->collapse
> 1)
258 collapse_iter
= &OMP_CLAUSE_COLLAPSE_ITERVAR (t
);
259 collapse_count
= &OMP_CLAUSE_COLLAPSE_COUNT (t
);
265 /* FIXME: for now map schedule(auto) to schedule(static).
266 There should be analysis to determine whether all iterations
267 are approximately the same amount of work (then schedule(static)
268 is best) or if it varies (then schedule(dynamic,N) is better). */
269 if (fd
->sched_kind
== OMP_CLAUSE_SCHEDULE_AUTO
)
271 fd
->sched_kind
= OMP_CLAUSE_SCHEDULE_STATIC
;
272 gcc_assert (fd
->chunk_size
== NULL
);
274 gcc_assert (fd
->collapse
== 1 || collapse_iter
!= NULL
);
275 if (fd
->sched_kind
== OMP_CLAUSE_SCHEDULE_RUNTIME
)
276 gcc_assert (fd
->chunk_size
== NULL
);
277 else if (fd
->chunk_size
== NULL
)
279 /* We only need to compute a default chunk size for ordered
280 static loops and dynamic loops. */
281 if (fd
->sched_kind
!= OMP_CLAUSE_SCHEDULE_STATIC
284 fd
->chunk_size
= (fd
->sched_kind
== OMP_CLAUSE_SCHEDULE_STATIC
)
285 ? integer_zero_node
: integer_one_node
;
288 for (i
= 0; i
< fd
->collapse
; i
++)
290 if (fd
->collapse
== 1)
292 else if (loops
!= NULL
)
298 loop
->v
= gimple_omp_for_index (for_stmt
, i
);
299 gcc_assert (SSA_VAR_P (loop
->v
));
300 gcc_assert (TREE_CODE (TREE_TYPE (loop
->v
)) == INTEGER_TYPE
301 || TREE_CODE (TREE_TYPE (loop
->v
)) == POINTER_TYPE
);
302 var
= TREE_CODE (loop
->v
) == SSA_NAME
? SSA_NAME_VAR (loop
->v
) : loop
->v
;
303 loop
->n1
= gimple_omp_for_initial (for_stmt
, i
);
305 loop
->cond_code
= gimple_omp_for_cond (for_stmt
, i
);
306 loop
->n2
= gimple_omp_for_final (for_stmt
, i
);
307 switch (loop
->cond_code
)
313 if (POINTER_TYPE_P (TREE_TYPE (loop
->n2
)))
314 loop
->n2
= fold_build_pointer_plus_hwi_loc (loc
, loop
->n2
, 1);
316 loop
->n2
= fold_build2_loc (loc
,
317 PLUS_EXPR
, TREE_TYPE (loop
->n2
), loop
->n2
,
318 build_int_cst (TREE_TYPE (loop
->n2
), 1));
319 loop
->cond_code
= LT_EXPR
;
322 if (POINTER_TYPE_P (TREE_TYPE (loop
->n2
)))
323 loop
->n2
= fold_build_pointer_plus_hwi_loc (loc
, loop
->n2
, -1);
325 loop
->n2
= fold_build2_loc (loc
,
326 MINUS_EXPR
, TREE_TYPE (loop
->n2
), loop
->n2
,
327 build_int_cst (TREE_TYPE (loop
->n2
), 1));
328 loop
->cond_code
= GT_EXPR
;
334 t
= gimple_omp_for_incr (for_stmt
, i
);
335 gcc_assert (TREE_OPERAND (t
, 0) == var
);
336 switch (TREE_CODE (t
))
339 loop
->step
= TREE_OPERAND (t
, 1);
341 case POINTER_PLUS_EXPR
:
342 loop
->step
= fold_convert (ssizetype
, TREE_OPERAND (t
, 1));
345 loop
->step
= TREE_OPERAND (t
, 1);
346 loop
->step
= fold_build1_loc (loc
,
347 NEGATE_EXPR
, TREE_TYPE (loop
->step
),
356 if (fd
->collapse
== 1)
357 iter_type
= TREE_TYPE (loop
->v
);
359 || TYPE_PRECISION (iter_type
)
360 < TYPE_PRECISION (TREE_TYPE (loop
->v
)))
362 = build_nonstandard_integer_type
363 (TYPE_PRECISION (TREE_TYPE (loop
->v
)), 1);
365 else if (iter_type
!= long_long_unsigned_type_node
)
367 if (POINTER_TYPE_P (TREE_TYPE (loop
->v
)))
368 iter_type
= long_long_unsigned_type_node
;
369 else if (TYPE_UNSIGNED (TREE_TYPE (loop
->v
))
370 && TYPE_PRECISION (TREE_TYPE (loop
->v
))
371 >= TYPE_PRECISION (iter_type
))
375 if (loop
->cond_code
== LT_EXPR
)
376 n
= fold_build2_loc (loc
,
377 PLUS_EXPR
, TREE_TYPE (loop
->v
),
378 loop
->n2
, loop
->step
);
381 if (TREE_CODE (n
) != INTEGER_CST
382 || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type
), n
))
383 iter_type
= long_long_unsigned_type_node
;
385 else if (TYPE_PRECISION (TREE_TYPE (loop
->v
))
386 > TYPE_PRECISION (iter_type
))
390 if (loop
->cond_code
== LT_EXPR
)
393 n2
= fold_build2_loc (loc
,
394 PLUS_EXPR
, TREE_TYPE (loop
->v
),
395 loop
->n2
, loop
->step
);
399 n1
= fold_build2_loc (loc
,
400 MINUS_EXPR
, TREE_TYPE (loop
->v
),
401 loop
->n2
, loop
->step
);
404 if (TREE_CODE (n1
) != INTEGER_CST
405 || TREE_CODE (n2
) != INTEGER_CST
406 || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type
), n1
)
407 || !tree_int_cst_lt (n2
, TYPE_MAX_VALUE (iter_type
)))
408 iter_type
= long_long_unsigned_type_node
;
412 if (collapse_count
&& *collapse_count
== NULL
)
414 t
= fold_binary (loop
->cond_code
, boolean_type_node
,
415 fold_convert (TREE_TYPE (loop
->v
), loop
->n1
),
416 fold_convert (TREE_TYPE (loop
->v
), loop
->n2
));
417 if (t
&& integer_zerop (t
))
418 count
= build_zero_cst (long_long_unsigned_type_node
);
419 else if ((i
== 0 || count
!= NULL_TREE
)
420 && TREE_CODE (TREE_TYPE (loop
->v
)) == INTEGER_TYPE
421 && TREE_CONSTANT (loop
->n1
)
422 && TREE_CONSTANT (loop
->n2
)
423 && TREE_CODE (loop
->step
) == INTEGER_CST
)
425 tree itype
= TREE_TYPE (loop
->v
);
427 if (POINTER_TYPE_P (itype
))
428 itype
= signed_type_for (itype
);
429 t
= build_int_cst (itype
, (loop
->cond_code
== LT_EXPR
? -1 : 1));
430 t
= fold_build2_loc (loc
,
432 fold_convert_loc (loc
, itype
, loop
->step
), t
);
433 t
= fold_build2_loc (loc
, PLUS_EXPR
, itype
, t
,
434 fold_convert_loc (loc
, itype
, loop
->n2
));
435 t
= fold_build2_loc (loc
, MINUS_EXPR
, itype
, t
,
436 fold_convert_loc (loc
, itype
, loop
->n1
));
437 if (TYPE_UNSIGNED (itype
) && loop
->cond_code
== GT_EXPR
)
438 t
= fold_build2_loc (loc
, TRUNC_DIV_EXPR
, itype
,
439 fold_build1_loc (loc
, NEGATE_EXPR
, itype
, t
),
440 fold_build1_loc (loc
, NEGATE_EXPR
, itype
,
441 fold_convert_loc (loc
, itype
,
444 t
= fold_build2_loc (loc
, TRUNC_DIV_EXPR
, itype
, t
,
445 fold_convert_loc (loc
, itype
, loop
->step
));
446 t
= fold_convert_loc (loc
, long_long_unsigned_type_node
, t
);
447 if (count
!= NULL_TREE
)
448 count
= fold_build2_loc (loc
,
449 MULT_EXPR
, long_long_unsigned_type_node
,
453 if (TREE_CODE (count
) != INTEGER_CST
)
456 else if (count
&& !integer_zerop (count
))
464 if (!tree_int_cst_lt (count
, TYPE_MAX_VALUE (long_integer_type_node
)))
465 iter_type
= long_long_unsigned_type_node
;
467 iter_type
= long_integer_type_node
;
469 else if (collapse_iter
&& *collapse_iter
!= NULL
)
470 iter_type
= TREE_TYPE (*collapse_iter
);
471 fd
->iter_type
= iter_type
;
472 if (collapse_iter
&& *collapse_iter
== NULL
)
473 *collapse_iter
= create_tmp_var (iter_type
, ".iter");
474 if (collapse_count
&& *collapse_count
== NULL
)
477 *collapse_count
= fold_convert_loc (loc
, iter_type
, count
);
479 *collapse_count
= create_tmp_var (iter_type
, ".count");
482 if (fd
->collapse
> 1)
484 fd
->loop
.v
= *collapse_iter
;
485 fd
->loop
.n1
= build_int_cst (TREE_TYPE (fd
->loop
.v
), 0);
486 fd
->loop
.n2
= *collapse_count
;
487 fd
->loop
.step
= build_int_cst (TREE_TYPE (fd
->loop
.v
), 1);
488 fd
->loop
.cond_code
= LT_EXPR
;
493 /* Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB
494 is the immediate dominator of PAR_ENTRY_BB, return true if there
495 are no data dependencies that would prevent expanding the parallel
496 directive at PAR_ENTRY_BB as a combined parallel+workshare region.
498 When expanding a combined parallel+workshare region, the call to
499 the child function may need additional arguments in the case of
500 GIMPLE_OMP_FOR regions. In some cases, these arguments are
501 computed out of variables passed in from the parent to the child
502 via 'struct .omp_data_s'. For instance:
504 #pragma omp parallel for schedule (guided, i * 4)
509 # BLOCK 2 (PAR_ENTRY_BB)
511 #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
513 # BLOCK 3 (WS_ENTRY_BB)
514 .omp_data_i = &.omp_data_o;
515 D.1667 = .omp_data_i->i;
517 #pragma omp for schedule (guided, D.1598)
519 When we outline the parallel region, the call to the child function
520 'bar.omp_fn.0' will need the value D.1598 in its argument list, but
521 that value is computed *after* the call site. So, in principle we
522 cannot do the transformation.
524 To see whether the code in WS_ENTRY_BB blocks the combined
525 parallel+workshare call, we collect all the variables used in the
526 GIMPLE_OMP_FOR header check whether they appear on the LHS of any
527 statement in WS_ENTRY_BB. If so, then we cannot emit the combined
530 FIXME. If we had the SSA form built at this point, we could merely
531 hoist the code in block 3 into block 2 and be done with it. But at
532 this point we don't have dataflow information and though we could
533 hack something up here, it is really not worth the aggravation. */
536 workshare_safe_to_combine_p (basic_block ws_entry_bb
)
538 struct omp_for_data fd
;
539 gimple ws_stmt
= last_stmt (ws_entry_bb
);
541 if (gimple_code (ws_stmt
) == GIMPLE_OMP_SECTIONS
)
544 gcc_assert (gimple_code (ws_stmt
) == GIMPLE_OMP_FOR
);
546 extract_omp_for_data (ws_stmt
, &fd
, NULL
);
548 if (fd
.collapse
> 1 && TREE_CODE (fd
.loop
.n2
) != INTEGER_CST
)
550 if (fd
.iter_type
!= long_integer_type_node
)
553 /* FIXME. We give up too easily here. If any of these arguments
554 are not constants, they will likely involve variables that have
555 been mapped into fields of .omp_data_s for sharing with the child
556 function. With appropriate data flow, it would be possible to
558 if (!is_gimple_min_invariant (fd
.loop
.n1
)
559 || !is_gimple_min_invariant (fd
.loop
.n2
)
560 || !is_gimple_min_invariant (fd
.loop
.step
)
561 || (fd
.chunk_size
&& !is_gimple_min_invariant (fd
.chunk_size
)))
568 /* Collect additional arguments needed to emit a combined
569 parallel+workshare call. WS_STMT is the workshare directive being
572 static vec
<tree
, va_gc
> *
573 get_ws_args_for (gimple ws_stmt
)
576 location_t loc
= gimple_location (ws_stmt
);
577 vec
<tree
, va_gc
> *ws_args
;
579 if (gimple_code (ws_stmt
) == GIMPLE_OMP_FOR
)
581 struct omp_for_data fd
;
583 extract_omp_for_data (ws_stmt
, &fd
, NULL
);
585 vec_alloc (ws_args
, 3 + (fd
.chunk_size
!= 0));
587 t
= fold_convert_loc (loc
, long_integer_type_node
, fd
.loop
.n1
);
588 ws_args
->quick_push (t
);
590 t
= fold_convert_loc (loc
, long_integer_type_node
, fd
.loop
.n2
);
591 ws_args
->quick_push (t
);
593 t
= fold_convert_loc (loc
, long_integer_type_node
, fd
.loop
.step
);
594 ws_args
->quick_push (t
);
598 t
= fold_convert_loc (loc
, long_integer_type_node
, fd
.chunk_size
);
599 ws_args
->quick_push (t
);
604 else if (gimple_code (ws_stmt
) == GIMPLE_OMP_SECTIONS
)
606 /* Number of sections is equal to the number of edges from the
607 GIMPLE_OMP_SECTIONS_SWITCH statement, except for the one to
608 the exit of the sections region. */
609 basic_block bb
= single_succ (gimple_bb (ws_stmt
));
610 t
= build_int_cst (unsigned_type_node
, EDGE_COUNT (bb
->succs
) - 1);
611 vec_alloc (ws_args
, 1);
612 ws_args
->quick_push (t
);
620 /* Discover whether REGION is a combined parallel+workshare region. */
623 determine_parallel_type (struct omp_region
*region
)
625 basic_block par_entry_bb
, par_exit_bb
;
626 basic_block ws_entry_bb
, ws_exit_bb
;
628 if (region
== NULL
|| region
->inner
== NULL
629 || region
->exit
== NULL
|| region
->inner
->exit
== NULL
630 || region
->inner
->cont
== NULL
)
633 /* We only support parallel+for and parallel+sections. */
634 if (region
->type
!= GIMPLE_OMP_PARALLEL
635 || (region
->inner
->type
!= GIMPLE_OMP_FOR
636 && region
->inner
->type
!= GIMPLE_OMP_SECTIONS
))
639 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
640 WS_EXIT_BB -> PAR_EXIT_BB. */
641 par_entry_bb
= region
->entry
;
642 par_exit_bb
= region
->exit
;
643 ws_entry_bb
= region
->inner
->entry
;
644 ws_exit_bb
= region
->inner
->exit
;
646 if (single_succ (par_entry_bb
) == ws_entry_bb
647 && single_succ (ws_exit_bb
) == par_exit_bb
648 && workshare_safe_to_combine_p (ws_entry_bb
)
649 && (gimple_omp_parallel_combined_p (last_stmt (par_entry_bb
))
650 || (last_and_only_stmt (ws_entry_bb
)
651 && last_and_only_stmt (par_exit_bb
))))
653 gimple ws_stmt
= last_stmt (ws_entry_bb
);
655 if (region
->inner
->type
== GIMPLE_OMP_FOR
)
657 /* If this is a combined parallel loop, we need to determine
658 whether or not to use the combined library calls. There
659 are two cases where we do not apply the transformation:
660 static loops and any kind of ordered loop. In the first
661 case, we already open code the loop so there is no need
662 to do anything else. In the latter case, the combined
663 parallel loop call would still need extra synchronization
664 to implement ordered semantics, so there would not be any
665 gain in using the combined call. */
666 tree clauses
= gimple_omp_for_clauses (ws_stmt
);
667 tree c
= find_omp_clause (clauses
, OMP_CLAUSE_SCHEDULE
);
669 || OMP_CLAUSE_SCHEDULE_KIND (c
) == OMP_CLAUSE_SCHEDULE_STATIC
670 || find_omp_clause (clauses
, OMP_CLAUSE_ORDERED
))
672 region
->is_combined_parallel
= false;
673 region
->inner
->is_combined_parallel
= false;
678 region
->is_combined_parallel
= true;
679 region
->inner
->is_combined_parallel
= true;
680 region
->ws_args
= get_ws_args_for (ws_stmt
);
685 /* Return true if EXPR is variable sized. */
688 is_variable_sized (const_tree expr
)
690 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr
)));
693 /* Return true if DECL is a reference type. */
696 is_reference (tree decl
)
698 return lang_hooks
.decls
.omp_privatize_by_reference (decl
);
701 /* Lookup variables in the decl or field splay trees. The "maybe" form
702 allows for the variable form to not have been entered, otherwise we
703 assert that the variable must have been entered. */
706 lookup_decl (tree var
, omp_context
*ctx
)
709 n
= (tree
*) pointer_map_contains (ctx
->cb
.decl_map
, var
);
714 maybe_lookup_decl (const_tree var
, omp_context
*ctx
)
717 n
= (tree
*) pointer_map_contains (ctx
->cb
.decl_map
, var
);
718 return n
? *n
: NULL_TREE
;
722 lookup_field (tree var
, omp_context
*ctx
)
725 n
= splay_tree_lookup (ctx
->field_map
, (splay_tree_key
) var
);
726 return (tree
) n
->value
;
730 lookup_sfield (tree var
, omp_context
*ctx
)
733 n
= splay_tree_lookup (ctx
->sfield_map
734 ? ctx
->sfield_map
: ctx
->field_map
,
735 (splay_tree_key
) var
);
736 return (tree
) n
->value
;
740 maybe_lookup_field (tree var
, omp_context
*ctx
)
743 n
= splay_tree_lookup (ctx
->field_map
, (splay_tree_key
) var
);
744 return n
? (tree
) n
->value
: NULL_TREE
;
747 /* Return true if DECL should be copied by pointer. SHARED_CTX is
748 the parallel context if DECL is to be shared. */
751 use_pointer_for_field (tree decl
, omp_context
*shared_ctx
)
753 if (AGGREGATE_TYPE_P (TREE_TYPE (decl
)))
756 /* We can only use copy-in/copy-out semantics for shared variables
757 when we know the value is not accessible from an outer scope. */
760 /* ??? Trivially accessible from anywhere. But why would we even
761 be passing an address in this case? Should we simply assert
762 this to be false, or should we have a cleanup pass that removes
763 these from the list of mappings? */
764 if (TREE_STATIC (decl
) || DECL_EXTERNAL (decl
))
767 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
768 without analyzing the expression whether or not its location
769 is accessible to anyone else. In the case of nested parallel
770 regions it certainly may be. */
771 if (TREE_CODE (decl
) != RESULT_DECL
&& DECL_HAS_VALUE_EXPR_P (decl
))
774 /* Do not use copy-in/copy-out for variables that have their
776 if (TREE_ADDRESSABLE (decl
))
779 /* lower_send_shared_vars only uses copy-in, but not copy-out
781 if (TREE_READONLY (decl
)
782 || ((TREE_CODE (decl
) == RESULT_DECL
783 || TREE_CODE (decl
) == PARM_DECL
)
784 && DECL_BY_REFERENCE (decl
)))
787 /* Disallow copy-in/out in nested parallel if
788 decl is shared in outer parallel, otherwise
789 each thread could store the shared variable
790 in its own copy-in location, making the
791 variable no longer really shared. */
792 if (shared_ctx
->is_nested
)
796 for (up
= shared_ctx
->outer
; up
; up
= up
->outer
)
797 if (is_taskreg_ctx (up
) && maybe_lookup_decl (decl
, up
))
804 for (c
= gimple_omp_taskreg_clauses (up
->stmt
);
805 c
; c
= OMP_CLAUSE_CHAIN (c
))
806 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_SHARED
807 && OMP_CLAUSE_DECL (c
) == decl
)
811 goto maybe_mark_addressable_and_ret
;
815 /* For tasks avoid using copy-in/out. As tasks can be
816 deferred or executed in different thread, when GOMP_task
817 returns, the task hasn't necessarily terminated. */
818 if (is_task_ctx (shared_ctx
))
821 maybe_mark_addressable_and_ret
:
822 outer
= maybe_lookup_decl_in_outer_ctx (decl
, shared_ctx
);
823 if (is_gimple_reg (outer
))
825 /* Taking address of OUTER in lower_send_shared_vars
826 might need regimplification of everything that uses the
828 if (!task_shared_vars
)
829 task_shared_vars
= BITMAP_ALLOC (NULL
);
830 bitmap_set_bit (task_shared_vars
, DECL_UID (outer
));
831 TREE_ADDRESSABLE (outer
) = 1;
840 /* Create a new VAR_DECL and copy information from VAR to it. */
843 copy_var_decl (tree var
, tree name
, tree type
)
845 tree copy
= build_decl (DECL_SOURCE_LOCATION (var
), VAR_DECL
, name
, type
);
847 TREE_ADDRESSABLE (copy
) = TREE_ADDRESSABLE (var
);
848 TREE_THIS_VOLATILE (copy
) = TREE_THIS_VOLATILE (var
);
849 DECL_GIMPLE_REG_P (copy
) = DECL_GIMPLE_REG_P (var
);
850 DECL_ARTIFICIAL (copy
) = DECL_ARTIFICIAL (var
);
851 DECL_IGNORED_P (copy
) = DECL_IGNORED_P (var
);
852 DECL_CONTEXT (copy
) = DECL_CONTEXT (var
);
853 TREE_NO_WARNING (copy
) = TREE_NO_WARNING (var
);
854 TREE_USED (copy
) = 1;
855 DECL_SEEN_IN_BIND_EXPR_P (copy
) = 1;
860 /* Construct a new automatic decl similar to VAR. */
863 omp_copy_decl_2 (tree var
, tree name
, tree type
, omp_context
*ctx
)
865 tree copy
= copy_var_decl (var
, name
, type
);
867 DECL_CONTEXT (copy
) = current_function_decl
;
868 DECL_CHAIN (copy
) = ctx
->block_vars
;
869 ctx
->block_vars
= copy
;
875 omp_copy_decl_1 (tree var
, omp_context
*ctx
)
877 return omp_copy_decl_2 (var
, DECL_NAME (var
), TREE_TYPE (var
), ctx
);
880 /* Build COMPONENT_REF and set TREE_THIS_VOLATILE and TREE_READONLY on it
883 omp_build_component_ref (tree obj
, tree field
)
885 tree ret
= build3 (COMPONENT_REF
, TREE_TYPE (field
), obj
, field
, NULL
);
886 if (TREE_THIS_VOLATILE (field
))
887 TREE_THIS_VOLATILE (ret
) |= 1;
888 if (TREE_READONLY (field
))
889 TREE_READONLY (ret
) |= 1;
893 /* Build tree nodes to access the field for VAR on the receiver side. */
896 build_receiver_ref (tree var
, bool by_ref
, omp_context
*ctx
)
898 tree x
, field
= lookup_field (var
, ctx
);
900 /* If the receiver record type was remapped in the child function,
901 remap the field into the new record type. */
902 x
= maybe_lookup_field (field
, ctx
);
906 x
= build_simple_mem_ref (ctx
->receiver_decl
);
907 x
= omp_build_component_ref (x
, field
);
909 x
= build_simple_mem_ref (x
);
914 /* Build tree nodes to access VAR in the scope outer to CTX. In the case
915 of a parallel, this is a component reference; for workshare constructs
916 this is some variable. */
919 build_outer_var_ref (tree var
, omp_context
*ctx
)
923 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var
, ctx
)))
925 else if (is_variable_sized (var
))
927 x
= TREE_OPERAND (DECL_VALUE_EXPR (var
), 0);
928 x
= build_outer_var_ref (x
, ctx
);
929 x
= build_simple_mem_ref (x
);
931 else if (is_taskreg_ctx (ctx
))
933 bool by_ref
= use_pointer_for_field (var
, NULL
);
934 x
= build_receiver_ref (var
, by_ref
, ctx
);
936 else if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_FOR
937 && gimple_omp_for_kind (ctx
->stmt
) == GF_OMP_FOR_KIND_SIMD
)
939 /* #pragma omp simd isn't a worksharing construct, and can reference even
940 private vars in its linear etc. clauses. */
942 if (ctx
->outer
&& is_taskreg_ctx (ctx
))
943 x
= lookup_decl (var
, ctx
->outer
);
945 x
= maybe_lookup_decl (var
, ctx
->outer
);
950 x
= lookup_decl (var
, ctx
->outer
);
951 else if (is_reference (var
))
952 /* This can happen with orphaned constructs. If var is reference, it is
953 possible it is shared and as such valid. */
958 if (is_reference (var
))
959 x
= build_simple_mem_ref (x
);
964 /* Build tree nodes to access the field for VAR on the sender side. */
967 build_sender_ref (tree var
, omp_context
*ctx
)
969 tree field
= lookup_sfield (var
, ctx
);
970 return omp_build_component_ref (ctx
->sender_decl
, field
);
973 /* Add a new field for VAR inside the structure CTX->SENDER_DECL. */
976 install_var_field (tree var
, bool by_ref
, int mask
, omp_context
*ctx
)
978 tree field
, type
, sfield
= NULL_TREE
;
980 gcc_assert ((mask
& 1) == 0
981 || !splay_tree_lookup (ctx
->field_map
, (splay_tree_key
) var
));
982 gcc_assert ((mask
& 2) == 0 || !ctx
->sfield_map
983 || !splay_tree_lookup (ctx
->sfield_map
, (splay_tree_key
) var
));
985 type
= TREE_TYPE (var
);
987 type
= build_pointer_type (type
);
988 else if ((mask
& 3) == 1 && is_reference (var
))
989 type
= TREE_TYPE (type
);
991 field
= build_decl (DECL_SOURCE_LOCATION (var
),
992 FIELD_DECL
, DECL_NAME (var
), type
);
994 /* Remember what variable this field was created for. This does have a
995 side effect of making dwarf2out ignore this member, so for helpful
996 debugging we clear it later in delete_omp_context. */
997 DECL_ABSTRACT_ORIGIN (field
) = var
;
998 if (type
== TREE_TYPE (var
))
1000 DECL_ALIGN (field
) = DECL_ALIGN (var
);
1001 DECL_USER_ALIGN (field
) = DECL_USER_ALIGN (var
);
1002 TREE_THIS_VOLATILE (field
) = TREE_THIS_VOLATILE (var
);
1005 DECL_ALIGN (field
) = TYPE_ALIGN (type
);
1007 if ((mask
& 3) == 3)
1009 insert_field_into_struct (ctx
->record_type
, field
);
1010 if (ctx
->srecord_type
)
1012 sfield
= build_decl (DECL_SOURCE_LOCATION (var
),
1013 FIELD_DECL
, DECL_NAME (var
), type
);
1014 DECL_ABSTRACT_ORIGIN (sfield
) = var
;
1015 DECL_ALIGN (sfield
) = DECL_ALIGN (field
);
1016 DECL_USER_ALIGN (sfield
) = DECL_USER_ALIGN (field
);
1017 TREE_THIS_VOLATILE (sfield
) = TREE_THIS_VOLATILE (field
);
1018 insert_field_into_struct (ctx
->srecord_type
, sfield
);
1023 if (ctx
->srecord_type
== NULL_TREE
)
1027 ctx
->srecord_type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
1028 ctx
->sfield_map
= splay_tree_new (splay_tree_compare_pointers
, 0, 0);
1029 for (t
= TYPE_FIELDS (ctx
->record_type
); t
; t
= TREE_CHAIN (t
))
1031 sfield
= build_decl (DECL_SOURCE_LOCATION (var
),
1032 FIELD_DECL
, DECL_NAME (t
), TREE_TYPE (t
));
1033 DECL_ABSTRACT_ORIGIN (sfield
) = DECL_ABSTRACT_ORIGIN (t
);
1034 insert_field_into_struct (ctx
->srecord_type
, sfield
);
1035 splay_tree_insert (ctx
->sfield_map
,
1036 (splay_tree_key
) DECL_ABSTRACT_ORIGIN (t
),
1037 (splay_tree_value
) sfield
);
1041 insert_field_into_struct ((mask
& 1) ? ctx
->record_type
1042 : ctx
->srecord_type
, field
);
1046 splay_tree_insert (ctx
->field_map
, (splay_tree_key
) var
,
1047 (splay_tree_value
) field
);
1048 if ((mask
& 2) && ctx
->sfield_map
)
1049 splay_tree_insert (ctx
->sfield_map
, (splay_tree_key
) var
,
1050 (splay_tree_value
) sfield
);
1054 install_var_local (tree var
, omp_context
*ctx
)
1056 tree new_var
= omp_copy_decl_1 (var
, ctx
);
1057 insert_decl_map (&ctx
->cb
, var
, new_var
);
1061 /* Adjust the replacement for DECL in CTX for the new context. This means
1062 copying the DECL_VALUE_EXPR, and fixing up the type. */
1065 fixup_remapped_decl (tree decl
, omp_context
*ctx
, bool private_debug
)
1067 tree new_decl
, size
;
1069 new_decl
= lookup_decl (decl
, ctx
);
1071 TREE_TYPE (new_decl
) = remap_type (TREE_TYPE (decl
), &ctx
->cb
);
1073 if ((!TREE_CONSTANT (DECL_SIZE (new_decl
)) || private_debug
)
1074 && DECL_HAS_VALUE_EXPR_P (decl
))
1076 tree ve
= DECL_VALUE_EXPR (decl
);
1077 walk_tree (&ve
, copy_tree_body_r
, &ctx
->cb
, NULL
);
1078 SET_DECL_VALUE_EXPR (new_decl
, ve
);
1079 DECL_HAS_VALUE_EXPR_P (new_decl
) = 1;
1082 if (!TREE_CONSTANT (DECL_SIZE (new_decl
)))
1084 size
= remap_decl (DECL_SIZE (decl
), &ctx
->cb
);
1085 if (size
== error_mark_node
)
1086 size
= TYPE_SIZE (TREE_TYPE (new_decl
));
1087 DECL_SIZE (new_decl
) = size
;
1089 size
= remap_decl (DECL_SIZE_UNIT (decl
), &ctx
->cb
);
1090 if (size
== error_mark_node
)
1091 size
= TYPE_SIZE_UNIT (TREE_TYPE (new_decl
));
1092 DECL_SIZE_UNIT (new_decl
) = size
;
1096 /* The callback for remap_decl. Search all containing contexts for a
1097 mapping of the variable; this avoids having to duplicate the splay
1098 tree ahead of time. We know a mapping doesn't already exist in the
1099 given context. Create new mappings to implement default semantics. */
1102 omp_copy_decl (tree var
, copy_body_data
*cb
)
1104 omp_context
*ctx
= (omp_context
*) cb
;
1107 if (TREE_CODE (var
) == LABEL_DECL
)
1109 new_var
= create_artificial_label (DECL_SOURCE_LOCATION (var
));
1110 DECL_CONTEXT (new_var
) = current_function_decl
;
1111 insert_decl_map (&ctx
->cb
, var
, new_var
);
1115 while (!is_taskreg_ctx (ctx
))
1120 new_var
= maybe_lookup_decl (var
, ctx
);
1125 if (is_global_var (var
) || decl_function_context (var
) != ctx
->cb
.src_fn
)
1128 return error_mark_node
;
1132 /* Return the parallel region associated with STMT. */
1134 /* Debugging dumps for parallel regions. */
1135 void dump_omp_region (FILE *, struct omp_region
*, int);
1136 void debug_omp_region (struct omp_region
*);
1137 void debug_all_omp_regions (void);
1139 /* Dump the parallel region tree rooted at REGION. */
1142 dump_omp_region (FILE *file
, struct omp_region
*region
, int indent
)
1144 fprintf (file
, "%*sbb %d: %s\n", indent
, "", region
->entry
->index
,
1145 gimple_code_name
[region
->type
]);
1148 dump_omp_region (file
, region
->inner
, indent
+ 4);
1152 fprintf (file
, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent
, "",
1153 region
->cont
->index
);
1157 fprintf (file
, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent
, "",
1158 region
->exit
->index
);
1160 fprintf (file
, "%*s[no exit marker]\n", indent
, "");
1163 dump_omp_region (file
, region
->next
, indent
);
1167 debug_omp_region (struct omp_region
*region
)
1169 dump_omp_region (stderr
, region
, 0);
1173 debug_all_omp_regions (void)
1175 dump_omp_region (stderr
, root_omp_region
, 0);
1179 /* Create a new parallel region starting at STMT inside region PARENT. */
1182 new_omp_region (basic_block bb
, enum gimple_code type
,
1183 struct omp_region
*parent
)
1185 struct omp_region
*region
= XCNEW (struct omp_region
);
1187 region
->outer
= parent
;
1189 region
->type
= type
;
1193 /* This is a nested region. Add it to the list of inner
1194 regions in PARENT. */
1195 region
->next
= parent
->inner
;
1196 parent
->inner
= region
;
1200 /* This is a toplevel region. Add it to the list of toplevel
1201 regions in ROOT_OMP_REGION. */
1202 region
->next
= root_omp_region
;
1203 root_omp_region
= region
;
1209 /* Release the memory associated with the region tree rooted at REGION. */
1212 free_omp_region_1 (struct omp_region
*region
)
1214 struct omp_region
*i
, *n
;
1216 for (i
= region
->inner
; i
; i
= n
)
1219 free_omp_region_1 (i
);
1225 /* Release the memory for the entire omp region tree. */
1228 free_omp_regions (void)
1230 struct omp_region
*r
, *n
;
1231 for (r
= root_omp_region
; r
; r
= n
)
1234 free_omp_region_1 (r
);
1236 root_omp_region
= NULL
;
1240 /* Create a new context, with OUTER_CTX being the surrounding context. */
1242 static omp_context
*
1243 new_omp_context (gimple stmt
, omp_context
*outer_ctx
)
1245 omp_context
*ctx
= XCNEW (omp_context
);
1247 splay_tree_insert (all_contexts
, (splay_tree_key
) stmt
,
1248 (splay_tree_value
) ctx
);
1253 ctx
->outer
= outer_ctx
;
1254 ctx
->cb
= outer_ctx
->cb
;
1255 ctx
->cb
.block
= NULL
;
1256 ctx
->depth
= outer_ctx
->depth
+ 1;
1260 ctx
->cb
.src_fn
= current_function_decl
;
1261 ctx
->cb
.dst_fn
= current_function_decl
;
1262 ctx
->cb
.src_node
= cgraph_get_node (current_function_decl
);
1263 gcc_checking_assert (ctx
->cb
.src_node
);
1264 ctx
->cb
.dst_node
= ctx
->cb
.src_node
;
1265 ctx
->cb
.src_cfun
= cfun
;
1266 ctx
->cb
.copy_decl
= omp_copy_decl
;
1267 ctx
->cb
.eh_lp_nr
= 0;
1268 ctx
->cb
.transform_call_graph_edges
= CB_CGE_MOVE
;
1272 ctx
->cb
.decl_map
= pointer_map_create ();
1277 static gimple_seq
maybe_catch_exception (gimple_seq
);
1279 /* Finalize task copyfn. */
1282 finalize_task_copyfn (gimple task_stmt
)
1284 struct function
*child_cfun
;
1286 gimple_seq seq
= NULL
, new_seq
;
1289 child_fn
= gimple_omp_task_copy_fn (task_stmt
);
1290 if (child_fn
== NULL_TREE
)
1293 child_cfun
= DECL_STRUCT_FUNCTION (child_fn
);
1294 DECL_STRUCT_FUNCTION (child_fn
)->curr_properties
= cfun
->curr_properties
;
1296 push_cfun (child_cfun
);
1297 bind
= gimplify_body (child_fn
, false);
1298 gimple_seq_add_stmt (&seq
, bind
);
1299 new_seq
= maybe_catch_exception (seq
);
1302 bind
= gimple_build_bind (NULL
, new_seq
, NULL
);
1304 gimple_seq_add_stmt (&seq
, bind
);
1306 gimple_set_body (child_fn
, seq
);
1309 /* Inform the callgraph about the new function. */
1310 cgraph_add_new_function (child_fn
, false);
1313 /* Destroy a omp_context data structures. Called through the splay tree
1314 value delete callback. */
1317 delete_omp_context (splay_tree_value value
)
1319 omp_context
*ctx
= (omp_context
*) value
;
1321 pointer_map_destroy (ctx
->cb
.decl_map
);
1324 splay_tree_delete (ctx
->field_map
);
1325 if (ctx
->sfield_map
)
1326 splay_tree_delete (ctx
->sfield_map
);
1328 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
1329 it produces corrupt debug information. */
1330 if (ctx
->record_type
)
1333 for (t
= TYPE_FIELDS (ctx
->record_type
); t
; t
= DECL_CHAIN (t
))
1334 DECL_ABSTRACT_ORIGIN (t
) = NULL
;
1336 if (ctx
->srecord_type
)
1339 for (t
= TYPE_FIELDS (ctx
->srecord_type
); t
; t
= DECL_CHAIN (t
))
1340 DECL_ABSTRACT_ORIGIN (t
) = NULL
;
1343 if (is_task_ctx (ctx
))
1344 finalize_task_copyfn (ctx
->stmt
);
1349 /* Fix up RECEIVER_DECL with a type that has been remapped to the child
1353 fixup_child_record_type (omp_context
*ctx
)
1355 tree f
, type
= ctx
->record_type
;
1357 /* ??? It isn't sufficient to just call remap_type here, because
1358 variably_modified_type_p doesn't work the way we expect for
1359 record types. Testing each field for whether it needs remapping
1360 and creating a new record by hand works, however. */
1361 for (f
= TYPE_FIELDS (type
); f
; f
= DECL_CHAIN (f
))
1362 if (variably_modified_type_p (TREE_TYPE (f
), ctx
->cb
.src_fn
))
1366 tree name
, new_fields
= NULL
;
1368 type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
1369 name
= DECL_NAME (TYPE_NAME (ctx
->record_type
));
1370 name
= build_decl (DECL_SOURCE_LOCATION (ctx
->receiver_decl
),
1371 TYPE_DECL
, name
, type
);
1372 TYPE_NAME (type
) = name
;
1374 for (f
= TYPE_FIELDS (ctx
->record_type
); f
; f
= DECL_CHAIN (f
))
1376 tree new_f
= copy_node (f
);
1377 DECL_CONTEXT (new_f
) = type
;
1378 TREE_TYPE (new_f
) = remap_type (TREE_TYPE (f
), &ctx
->cb
);
1379 DECL_CHAIN (new_f
) = new_fields
;
1380 walk_tree (&DECL_SIZE (new_f
), copy_tree_body_r
, &ctx
->cb
, NULL
);
1381 walk_tree (&DECL_SIZE_UNIT (new_f
), copy_tree_body_r
,
1383 walk_tree (&DECL_FIELD_OFFSET (new_f
), copy_tree_body_r
,
1387 /* Arrange to be able to look up the receiver field
1388 given the sender field. */
1389 splay_tree_insert (ctx
->field_map
, (splay_tree_key
) f
,
1390 (splay_tree_value
) new_f
);
1392 TYPE_FIELDS (type
) = nreverse (new_fields
);
1396 TREE_TYPE (ctx
->receiver_decl
) = build_pointer_type (type
);
1399 /* Instantiate decls as necessary in CTX to satisfy the data sharing
1400 specified by CLAUSES. */
1403 scan_sharing_clauses (tree clauses
, omp_context
*ctx
)
1406 bool scan_array_reductions
= false;
1408 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
1412 switch (OMP_CLAUSE_CODE (c
))
1414 case OMP_CLAUSE_PRIVATE
:
1415 decl
= OMP_CLAUSE_DECL (c
);
1416 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c
))
1418 else if (!is_variable_sized (decl
))
1419 install_var_local (decl
, ctx
);
1422 case OMP_CLAUSE_SHARED
:
1423 gcc_assert (is_taskreg_ctx (ctx
));
1424 decl
= OMP_CLAUSE_DECL (c
);
1425 gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl
))
1426 || !is_variable_sized (decl
));
1427 /* Global variables don't need to be copied,
1428 the receiver side will use them directly. */
1429 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl
, ctx
)))
1431 by_ref
= use_pointer_for_field (decl
, ctx
);
1432 if (! TREE_READONLY (decl
)
1433 || TREE_ADDRESSABLE (decl
)
1435 || is_reference (decl
))
1437 install_var_field (decl
, by_ref
, 3, ctx
);
1438 install_var_local (decl
, ctx
);
1441 /* We don't need to copy const scalar vars back. */
1442 OMP_CLAUSE_SET_CODE (c
, OMP_CLAUSE_FIRSTPRIVATE
);
1445 case OMP_CLAUSE_LASTPRIVATE
:
1446 /* Let the corresponding firstprivate clause create
1448 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c
))
1452 case OMP_CLAUSE_FIRSTPRIVATE
:
1453 case OMP_CLAUSE_REDUCTION
:
1454 case OMP_CLAUSE_LINEAR
:
1455 decl
= OMP_CLAUSE_DECL (c
);
1457 if (is_variable_sized (decl
))
1459 if (is_task_ctx (ctx
))
1460 install_var_field (decl
, false, 1, ctx
);
1463 else if (is_taskreg_ctx (ctx
))
1466 = is_global_var (maybe_lookup_decl_in_outer_ctx (decl
, ctx
));
1467 by_ref
= use_pointer_for_field (decl
, NULL
);
1469 if (is_task_ctx (ctx
)
1470 && (global
|| by_ref
|| is_reference (decl
)))
1472 install_var_field (decl
, false, 1, ctx
);
1474 install_var_field (decl
, by_ref
, 2, ctx
);
1477 install_var_field (decl
, by_ref
, 3, ctx
);
1479 install_var_local (decl
, ctx
);
1482 case OMP_CLAUSE_COPYPRIVATE
:
1483 case OMP_CLAUSE_COPYIN
:
1484 decl
= OMP_CLAUSE_DECL (c
);
1485 by_ref
= use_pointer_for_field (decl
, NULL
);
1486 install_var_field (decl
, by_ref
, 3, ctx
);
1489 case OMP_CLAUSE_DEFAULT
:
1490 ctx
->default_kind
= OMP_CLAUSE_DEFAULT_KIND (c
);
1493 case OMP_CLAUSE_FINAL
:
1495 case OMP_CLAUSE_NUM_THREADS
:
1496 case OMP_CLAUSE_SCHEDULE
:
1498 scan_omp_op (&OMP_CLAUSE_OPERAND (c
, 0), ctx
->outer
);
1501 case OMP_CLAUSE_NOWAIT
:
1502 case OMP_CLAUSE_ORDERED
:
1503 case OMP_CLAUSE_COLLAPSE
:
1504 case OMP_CLAUSE_UNTIED
:
1505 case OMP_CLAUSE_MERGEABLE
:
1506 case OMP_CLAUSE_SAFELEN
:
1514 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
1516 switch (OMP_CLAUSE_CODE (c
))
1518 case OMP_CLAUSE_LASTPRIVATE
:
1519 /* Let the corresponding firstprivate clause create
1521 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
))
1522 scan_array_reductions
= true;
1523 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c
))
1527 case OMP_CLAUSE_PRIVATE
:
1528 case OMP_CLAUSE_FIRSTPRIVATE
:
1529 case OMP_CLAUSE_REDUCTION
:
1530 case OMP_CLAUSE_LINEAR
:
1531 decl
= OMP_CLAUSE_DECL (c
);
1532 if (is_variable_sized (decl
))
1533 install_var_local (decl
, ctx
);
1534 fixup_remapped_decl (decl
, ctx
,
1535 OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_PRIVATE
1536 && OMP_CLAUSE_PRIVATE_DEBUG (c
));
1537 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_REDUCTION
1538 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
1539 scan_array_reductions
= true;
1542 case OMP_CLAUSE_SHARED
:
1543 decl
= OMP_CLAUSE_DECL (c
);
1544 if (! is_global_var (maybe_lookup_decl_in_outer_ctx (decl
, ctx
)))
1545 fixup_remapped_decl (decl
, ctx
, false);
1548 case OMP_CLAUSE_COPYPRIVATE
:
1549 case OMP_CLAUSE_COPYIN
:
1550 case OMP_CLAUSE_DEFAULT
:
1552 case OMP_CLAUSE_NUM_THREADS
:
1553 case OMP_CLAUSE_SCHEDULE
:
1554 case OMP_CLAUSE_NOWAIT
:
1555 case OMP_CLAUSE_ORDERED
:
1556 case OMP_CLAUSE_COLLAPSE
:
1557 case OMP_CLAUSE_UNTIED
:
1558 case OMP_CLAUSE_FINAL
:
1559 case OMP_CLAUSE_MERGEABLE
:
1560 case OMP_CLAUSE_SAFELEN
:
1568 if (scan_array_reductions
)
1569 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
1570 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_REDUCTION
1571 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
1573 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
), ctx
);
1574 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
), ctx
);
1576 else if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LASTPRIVATE
1577 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
))
1578 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
), ctx
);
1581 /* Create a new name for omp child function. Returns an identifier. */
1583 static GTY(()) unsigned int tmp_ompfn_id_num
;
1586 create_omp_child_function_name (bool task_copy
)
1588 return (clone_function_name (current_function_decl
,
1589 task_copy
? "_omp_cpyfn" : "_omp_fn"));
1592 /* Build a decl for the omp child function. It'll not contain a body
1593 yet, just the bare decl. */
1596 create_omp_child_function (omp_context
*ctx
, bool task_copy
)
1598 tree decl
, type
, name
, t
;
1600 name
= create_omp_child_function_name (task_copy
);
1602 type
= build_function_type_list (void_type_node
, ptr_type_node
,
1603 ptr_type_node
, NULL_TREE
);
1605 type
= build_function_type_list (void_type_node
, ptr_type_node
, NULL_TREE
);
1607 decl
= build_decl (gimple_location (ctx
->stmt
),
1608 FUNCTION_DECL
, name
, type
);
1611 ctx
->cb
.dst_fn
= decl
;
1613 gimple_omp_task_set_copy_fn (ctx
->stmt
, decl
);
1615 TREE_STATIC (decl
) = 1;
1616 TREE_USED (decl
) = 1;
1617 DECL_ARTIFICIAL (decl
) = 1;
1618 DECL_NAMELESS (decl
) = 1;
1619 DECL_IGNORED_P (decl
) = 0;
1620 TREE_PUBLIC (decl
) = 0;
1621 DECL_UNINLINABLE (decl
) = 1;
1622 DECL_EXTERNAL (decl
) = 0;
1623 DECL_CONTEXT (decl
) = NULL_TREE
;
1624 DECL_INITIAL (decl
) = make_node (BLOCK
);
1626 t
= build_decl (DECL_SOURCE_LOCATION (decl
),
1627 RESULT_DECL
, NULL_TREE
, void_type_node
);
1628 DECL_ARTIFICIAL (t
) = 1;
1629 DECL_IGNORED_P (t
) = 1;
1630 DECL_CONTEXT (t
) = decl
;
1631 DECL_RESULT (decl
) = t
;
1633 t
= build_decl (DECL_SOURCE_LOCATION (decl
),
1634 PARM_DECL
, get_identifier (".omp_data_i"), ptr_type_node
);
1635 DECL_ARTIFICIAL (t
) = 1;
1636 DECL_NAMELESS (t
) = 1;
1637 DECL_ARG_TYPE (t
) = ptr_type_node
;
1638 DECL_CONTEXT (t
) = current_function_decl
;
1640 DECL_ARGUMENTS (decl
) = t
;
1642 ctx
->receiver_decl
= t
;
1645 t
= build_decl (DECL_SOURCE_LOCATION (decl
),
1646 PARM_DECL
, get_identifier (".omp_data_o"),
1648 DECL_ARTIFICIAL (t
) = 1;
1649 DECL_NAMELESS (t
) = 1;
1650 DECL_ARG_TYPE (t
) = ptr_type_node
;
1651 DECL_CONTEXT (t
) = current_function_decl
;
1653 TREE_ADDRESSABLE (t
) = 1;
1654 DECL_CHAIN (t
) = DECL_ARGUMENTS (decl
);
1655 DECL_ARGUMENTS (decl
) = t
;
1658 /* Allocate memory for the function structure. The call to
1659 allocate_struct_function clobbers CFUN, so we need to restore
1661 push_struct_function (decl
);
1662 cfun
->function_end_locus
= gimple_location (ctx
->stmt
);
1666 /* Scan an OpenMP parallel directive. */
1669 scan_omp_parallel (gimple_stmt_iterator
*gsi
, omp_context
*outer_ctx
)
1673 gimple stmt
= gsi_stmt (*gsi
);
1675 /* Ignore parallel directives with empty bodies, unless there
1676 are copyin clauses. */
1678 && empty_body_p (gimple_omp_body (stmt
))
1679 && find_omp_clause (gimple_omp_parallel_clauses (stmt
),
1680 OMP_CLAUSE_COPYIN
) == NULL
)
1682 gsi_replace (gsi
, gimple_build_nop (), false);
1686 ctx
= new_omp_context (stmt
, outer_ctx
);
1687 if (taskreg_nesting_level
> 1)
1688 ctx
->is_nested
= true;
1689 ctx
->field_map
= splay_tree_new (splay_tree_compare_pointers
, 0, 0);
1690 ctx
->default_kind
= OMP_CLAUSE_DEFAULT_SHARED
;
1691 ctx
->record_type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
1692 name
= create_tmp_var_name (".omp_data_s");
1693 name
= build_decl (gimple_location (stmt
),
1694 TYPE_DECL
, name
, ctx
->record_type
);
1695 DECL_ARTIFICIAL (name
) = 1;
1696 DECL_NAMELESS (name
) = 1;
1697 TYPE_NAME (ctx
->record_type
) = name
;
1698 create_omp_child_function (ctx
, false);
1699 gimple_omp_parallel_set_child_fn (stmt
, ctx
->cb
.dst_fn
);
1701 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt
), ctx
);
1702 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
1704 if (TYPE_FIELDS (ctx
->record_type
) == NULL
)
1705 ctx
->record_type
= ctx
->receiver_decl
= NULL
;
1708 layout_type (ctx
->record_type
);
1709 fixup_child_record_type (ctx
);
1713 /* Scan an OpenMP task directive. */
1716 scan_omp_task (gimple_stmt_iterator
*gsi
, omp_context
*outer_ctx
)
1720 gimple stmt
= gsi_stmt (*gsi
);
1721 location_t loc
= gimple_location (stmt
);
1723 /* Ignore task directives with empty bodies. */
1725 && empty_body_p (gimple_omp_body (stmt
)))
1727 gsi_replace (gsi
, gimple_build_nop (), false);
1731 ctx
= new_omp_context (stmt
, outer_ctx
);
1732 if (taskreg_nesting_level
> 1)
1733 ctx
->is_nested
= true;
1734 ctx
->field_map
= splay_tree_new (splay_tree_compare_pointers
, 0, 0);
1735 ctx
->default_kind
= OMP_CLAUSE_DEFAULT_SHARED
;
1736 ctx
->record_type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
1737 name
= create_tmp_var_name (".omp_data_s");
1738 name
= build_decl (gimple_location (stmt
),
1739 TYPE_DECL
, name
, ctx
->record_type
);
1740 DECL_ARTIFICIAL (name
) = 1;
1741 DECL_NAMELESS (name
) = 1;
1742 TYPE_NAME (ctx
->record_type
) = name
;
1743 create_omp_child_function (ctx
, false);
1744 gimple_omp_task_set_child_fn (stmt
, ctx
->cb
.dst_fn
);
1746 scan_sharing_clauses (gimple_omp_task_clauses (stmt
), ctx
);
1748 if (ctx
->srecord_type
)
1750 name
= create_tmp_var_name (".omp_data_a");
1751 name
= build_decl (gimple_location (stmt
),
1752 TYPE_DECL
, name
, ctx
->srecord_type
);
1753 DECL_ARTIFICIAL (name
) = 1;
1754 DECL_NAMELESS (name
) = 1;
1755 TYPE_NAME (ctx
->srecord_type
) = name
;
1756 create_omp_child_function (ctx
, true);
1759 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
1761 if (TYPE_FIELDS (ctx
->record_type
) == NULL
)
1763 ctx
->record_type
= ctx
->receiver_decl
= NULL
;
1764 t
= build_int_cst (long_integer_type_node
, 0);
1765 gimple_omp_task_set_arg_size (stmt
, t
);
1766 t
= build_int_cst (long_integer_type_node
, 1);
1767 gimple_omp_task_set_arg_align (stmt
, t
);
1771 tree
*p
, vla_fields
= NULL_TREE
, *q
= &vla_fields
;
1772 /* Move VLA fields to the end. */
1773 p
= &TYPE_FIELDS (ctx
->record_type
);
1775 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p
))
1776 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p
))))
1779 *p
= TREE_CHAIN (*p
);
1780 TREE_CHAIN (*q
) = NULL_TREE
;
1781 q
= &TREE_CHAIN (*q
);
1784 p
= &DECL_CHAIN (*p
);
1786 layout_type (ctx
->record_type
);
1787 fixup_child_record_type (ctx
);
1788 if (ctx
->srecord_type
)
1789 layout_type (ctx
->srecord_type
);
1790 t
= fold_convert_loc (loc
, long_integer_type_node
,
1791 TYPE_SIZE_UNIT (ctx
->record_type
));
1792 gimple_omp_task_set_arg_size (stmt
, t
);
1793 t
= build_int_cst (long_integer_type_node
,
1794 TYPE_ALIGN_UNIT (ctx
->record_type
));
1795 gimple_omp_task_set_arg_align (stmt
, t
);
1800 /* Scan an OpenMP loop directive. */
1803 scan_omp_for (gimple stmt
, omp_context
*outer_ctx
)
1808 ctx
= new_omp_context (stmt
, outer_ctx
);
1810 scan_sharing_clauses (gimple_omp_for_clauses (stmt
), ctx
);
1812 scan_omp (gimple_omp_for_pre_body_ptr (stmt
), ctx
);
1813 for (i
= 0; i
< gimple_omp_for_collapse (stmt
); i
++)
1815 scan_omp_op (gimple_omp_for_index_ptr (stmt
, i
), ctx
);
1816 scan_omp_op (gimple_omp_for_initial_ptr (stmt
, i
), ctx
);
1817 scan_omp_op (gimple_omp_for_final_ptr (stmt
, i
), ctx
);
1818 scan_omp_op (gimple_omp_for_incr_ptr (stmt
, i
), ctx
);
1820 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
1823 /* Scan an OpenMP sections directive. */
1826 scan_omp_sections (gimple stmt
, omp_context
*outer_ctx
)
1830 ctx
= new_omp_context (stmt
, outer_ctx
);
1831 scan_sharing_clauses (gimple_omp_sections_clauses (stmt
), ctx
);
1832 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
1835 /* Scan an OpenMP single directive. */
1838 scan_omp_single (gimple stmt
, omp_context
*outer_ctx
)
1843 ctx
= new_omp_context (stmt
, outer_ctx
);
1844 ctx
->field_map
= splay_tree_new (splay_tree_compare_pointers
, 0, 0);
1845 ctx
->record_type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
1846 name
= create_tmp_var_name (".omp_copy_s");
1847 name
= build_decl (gimple_location (stmt
),
1848 TYPE_DECL
, name
, ctx
->record_type
);
1849 TYPE_NAME (ctx
->record_type
) = name
;
1851 scan_sharing_clauses (gimple_omp_single_clauses (stmt
), ctx
);
1852 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
1854 if (TYPE_FIELDS (ctx
->record_type
) == NULL
)
1855 ctx
->record_type
= NULL
;
1857 layout_type (ctx
->record_type
);
1861 /* Check OpenMP nesting restrictions. */
1863 check_omp_nesting_restrictions (gimple stmt
, omp_context
*ctx
)
1867 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_FOR
1868 && gimple_omp_for_kind (ctx
->stmt
) == GF_OMP_FOR_KIND_SIMD
)
1870 error_at (gimple_location (stmt
),
1871 "OpenMP constructs may not be nested inside simd region");
1875 switch (gimple_code (stmt
))
1877 case GIMPLE_OMP_FOR
:
1878 if (gimple_omp_for_kind (stmt
) == GF_OMP_FOR_KIND_SIMD
)
1881 case GIMPLE_OMP_SECTIONS
:
1882 case GIMPLE_OMP_SINGLE
:
1884 for (; ctx
!= NULL
; ctx
= ctx
->outer
)
1885 switch (gimple_code (ctx
->stmt
))
1887 case GIMPLE_OMP_FOR
:
1888 case GIMPLE_OMP_SECTIONS
:
1889 case GIMPLE_OMP_SINGLE
:
1890 case GIMPLE_OMP_ORDERED
:
1891 case GIMPLE_OMP_MASTER
:
1892 case GIMPLE_OMP_TASK
:
1893 if (is_gimple_call (stmt
))
1895 error_at (gimple_location (stmt
),
1896 "barrier region may not be closely nested inside "
1897 "of work-sharing, critical, ordered, master or "
1898 "explicit task region");
1901 error_at (gimple_location (stmt
),
1902 "work-sharing region may not be closely nested inside "
1903 "of work-sharing, critical, ordered, master or explicit "
1906 case GIMPLE_OMP_PARALLEL
:
1912 case GIMPLE_OMP_MASTER
:
1913 for (; ctx
!= NULL
; ctx
= ctx
->outer
)
1914 switch (gimple_code (ctx
->stmt
))
1916 case GIMPLE_OMP_FOR
:
1917 case GIMPLE_OMP_SECTIONS
:
1918 case GIMPLE_OMP_SINGLE
:
1919 case GIMPLE_OMP_TASK
:
1920 error_at (gimple_location (stmt
),
1921 "master region may not be closely nested inside "
1922 "of work-sharing or explicit task region");
1924 case GIMPLE_OMP_PARALLEL
:
1930 case GIMPLE_OMP_ORDERED
:
1931 for (; ctx
!= NULL
; ctx
= ctx
->outer
)
1932 switch (gimple_code (ctx
->stmt
))
1934 case GIMPLE_OMP_CRITICAL
:
1935 case GIMPLE_OMP_TASK
:
1936 error_at (gimple_location (stmt
),
1937 "ordered region may not be closely nested inside "
1938 "of critical or explicit task region");
1940 case GIMPLE_OMP_FOR
:
1941 if (find_omp_clause (gimple_omp_for_clauses (ctx
->stmt
),
1942 OMP_CLAUSE_ORDERED
) == NULL
)
1944 error_at (gimple_location (stmt
),
1945 "ordered region must be closely nested inside "
1946 "a loop region with an ordered clause");
1950 case GIMPLE_OMP_PARALLEL
:
1956 case GIMPLE_OMP_CRITICAL
:
1957 for (; ctx
!= NULL
; ctx
= ctx
->outer
)
1958 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_CRITICAL
1959 && (gimple_omp_critical_name (stmt
)
1960 == gimple_omp_critical_name (ctx
->stmt
)))
1962 error_at (gimple_location (stmt
),
1963 "critical region may not be nested inside a critical "
1964 "region with the same name");
1975 /* Helper function scan_omp.
1977 Callback for walk_tree or operators in walk_gimple_stmt used to
1978 scan for OpenMP directives in TP. */
1981 scan_omp_1_op (tree
*tp
, int *walk_subtrees
, void *data
)
1983 struct walk_stmt_info
*wi
= (struct walk_stmt_info
*) data
;
1984 omp_context
*ctx
= (omp_context
*) wi
->info
;
1987 switch (TREE_CODE (t
))
1994 *tp
= remap_decl (t
, &ctx
->cb
);
1998 if (ctx
&& TYPE_P (t
))
1999 *tp
= remap_type (t
, &ctx
->cb
);
2000 else if (!DECL_P (t
))
2005 tree tem
= remap_type (TREE_TYPE (t
), &ctx
->cb
);
2006 if (tem
!= TREE_TYPE (t
))
2008 if (TREE_CODE (t
) == INTEGER_CST
)
2009 *tp
= build_int_cst_wide (tem
,
2010 TREE_INT_CST_LOW (t
),
2011 TREE_INT_CST_HIGH (t
));
2013 TREE_TYPE (t
) = tem
;
2024 /* Helper function for scan_omp.
2026 Callback for walk_gimple_stmt used to scan for OpenMP directives in
2027 the current statement in GSI. */
2030 scan_omp_1_stmt (gimple_stmt_iterator
*gsi
, bool *handled_ops_p
,
2031 struct walk_stmt_info
*wi
)
2033 gimple stmt
= gsi_stmt (*gsi
);
2034 omp_context
*ctx
= (omp_context
*) wi
->info
;
2036 if (gimple_has_location (stmt
))
2037 input_location
= gimple_location (stmt
);
2039 /* Check the OpenMP nesting restrictions. */
2042 bool remove
= false;
2043 if (is_gimple_omp (stmt
))
2044 remove
= !check_omp_nesting_restrictions (stmt
, ctx
);
2045 else if (is_gimple_call (stmt
))
2047 tree fndecl
= gimple_call_fndecl (stmt
);
2048 if (fndecl
&& DECL_BUILT_IN_CLASS (fndecl
) == BUILT_IN_NORMAL
2049 && DECL_FUNCTION_CODE (fndecl
) == BUILT_IN_GOMP_BARRIER
)
2050 remove
= !check_omp_nesting_restrictions (stmt
, ctx
);
2054 stmt
= gimple_build_nop ();
2055 gsi_replace (gsi
, stmt
, false);
2059 *handled_ops_p
= true;
2061 switch (gimple_code (stmt
))
2063 case GIMPLE_OMP_PARALLEL
:
2064 taskreg_nesting_level
++;
2065 scan_omp_parallel (gsi
, ctx
);
2066 taskreg_nesting_level
--;
2069 case GIMPLE_OMP_TASK
:
2070 taskreg_nesting_level
++;
2071 scan_omp_task (gsi
, ctx
);
2072 taskreg_nesting_level
--;
2075 case GIMPLE_OMP_FOR
:
2076 scan_omp_for (stmt
, ctx
);
2079 case GIMPLE_OMP_SECTIONS
:
2080 scan_omp_sections (stmt
, ctx
);
2083 case GIMPLE_OMP_SINGLE
:
2084 scan_omp_single (stmt
, ctx
);
2087 case GIMPLE_OMP_SECTION
:
2088 case GIMPLE_OMP_MASTER
:
2089 case GIMPLE_OMP_ORDERED
:
2090 case GIMPLE_OMP_CRITICAL
:
2091 ctx
= new_omp_context (stmt
, ctx
);
2092 scan_omp (gimple_omp_body_ptr (stmt
), ctx
);
2099 *handled_ops_p
= false;
2101 for (var
= gimple_bind_vars (stmt
); var
; var
= DECL_CHAIN (var
))
2102 insert_decl_map (&ctx
->cb
, var
, var
);
2106 *handled_ops_p
= false;
2114 /* Scan all the statements starting at the current statement. CTX
2115 contains context information about the OpenMP directives and
2116 clauses found during the scan. */
2119 scan_omp (gimple_seq
*body_p
, omp_context
*ctx
)
2121 location_t saved_location
;
2122 struct walk_stmt_info wi
;
2124 memset (&wi
, 0, sizeof (wi
));
2126 wi
.want_locations
= true;
2128 saved_location
= input_location
;
2129 walk_gimple_seq_mod (body_p
, scan_omp_1_stmt
, scan_omp_1_op
, &wi
);
2130 input_location
= saved_location
;
2133 /* Re-gimplification and code generation routines. */
2135 /* Build a call to GOMP_barrier. */
2138 build_omp_barrier (void)
2140 return build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_BARRIER
), 0);
2143 /* If a context was created for STMT when it was scanned, return it. */
2145 static omp_context
*
2146 maybe_lookup_ctx (gimple stmt
)
2149 n
= splay_tree_lookup (all_contexts
, (splay_tree_key
) stmt
);
2150 return n
? (omp_context
*) n
->value
: NULL
;
2154 /* Find the mapping for DECL in CTX or the immediately enclosing
2155 context that has a mapping for DECL.
2157 If CTX is a nested parallel directive, we may have to use the decl
2158 mappings created in CTX's parent context. Suppose that we have the
2159 following parallel nesting (variable UIDs showed for clarity):
2162 #omp parallel shared(iD.1562) -> outer parallel
2163 iD.1562 = iD.1562 + 1;
2165 #omp parallel shared (iD.1562) -> inner parallel
2166 iD.1562 = iD.1562 - 1;
2168 Each parallel structure will create a distinct .omp_data_s structure
2169 for copying iD.1562 in/out of the directive:
2171 outer parallel .omp_data_s.1.i -> iD.1562
2172 inner parallel .omp_data_s.2.i -> iD.1562
2174 A shared variable mapping will produce a copy-out operation before
2175 the parallel directive and a copy-in operation after it. So, in
2176 this case we would have:
2179 .omp_data_o.1.i = iD.1562;
2180 #omp parallel shared(iD.1562) -> outer parallel
2181 .omp_data_i.1 = &.omp_data_o.1
2182 .omp_data_i.1->i = .omp_data_i.1->i + 1;
2184 .omp_data_o.2.i = iD.1562; -> **
2185 #omp parallel shared(iD.1562) -> inner parallel
2186 .omp_data_i.2 = &.omp_data_o.2
2187 .omp_data_i.2->i = .omp_data_i.2->i - 1;
2190 ** This is a problem. The symbol iD.1562 cannot be referenced
2191 inside the body of the outer parallel region. But since we are
2192 emitting this copy operation while expanding the inner parallel
2193 directive, we need to access the CTX structure of the outer
2194 parallel directive to get the correct mapping:
2196 .omp_data_o.2.i = .omp_data_i.1->i
2198 Since there may be other workshare or parallel directives enclosing
2199 the parallel directive, it may be necessary to walk up the context
2200 parent chain. This is not a problem in general because nested
2201 parallelism happens only rarely. */
2204 lookup_decl_in_outer_ctx (tree decl
, omp_context
*ctx
)
2209 for (up
= ctx
->outer
, t
= NULL
; up
&& t
== NULL
; up
= up
->outer
)
2210 t
= maybe_lookup_decl (decl
, up
);
2212 gcc_assert (!ctx
->is_nested
|| t
|| is_global_var (decl
));
2214 return t
? t
: decl
;
2218 /* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
2219 in outer contexts. */
2222 maybe_lookup_decl_in_outer_ctx (tree decl
, omp_context
*ctx
)
2227 for (up
= ctx
->outer
, t
= NULL
; up
&& t
== NULL
; up
= up
->outer
)
2228 t
= maybe_lookup_decl (decl
, up
);
2230 return t
? t
: decl
;
2234 /* Construct the initialization value for reduction CLAUSE. */
2237 omp_reduction_init (tree clause
, tree type
)
2239 location_t loc
= OMP_CLAUSE_LOCATION (clause
);
2240 switch (OMP_CLAUSE_REDUCTION_CODE (clause
))
2247 case TRUTH_ORIF_EXPR
:
2248 case TRUTH_XOR_EXPR
:
2250 return build_zero_cst (type
);
2253 case TRUTH_AND_EXPR
:
2254 case TRUTH_ANDIF_EXPR
:
2256 return fold_convert_loc (loc
, type
, integer_one_node
);
2259 return fold_convert_loc (loc
, type
, integer_minus_one_node
);
2262 if (SCALAR_FLOAT_TYPE_P (type
))
2264 REAL_VALUE_TYPE max
, min
;
2265 if (HONOR_INFINITIES (TYPE_MODE (type
)))
2268 real_arithmetic (&min
, NEGATE_EXPR
, &max
, NULL
);
2271 real_maxval (&min
, 1, TYPE_MODE (type
));
2272 return build_real (type
, min
);
2276 gcc_assert (INTEGRAL_TYPE_P (type
));
2277 return TYPE_MIN_VALUE (type
);
2281 if (SCALAR_FLOAT_TYPE_P (type
))
2283 REAL_VALUE_TYPE max
;
2284 if (HONOR_INFINITIES (TYPE_MODE (type
)))
2287 real_maxval (&max
, 0, TYPE_MODE (type
));
2288 return build_real (type
, max
);
2292 gcc_assert (INTEGRAL_TYPE_P (type
));
2293 return TYPE_MAX_VALUE (type
);
2301 /* Return maximum possible vectorization factor for the target. */
2308 || (!flag_tree_vectorize
2309 && global_options_set
.x_flag_tree_vectorize
))
2312 int vs
= targetm
.vectorize
.autovectorize_vector_sizes ();
2315 vs
= 1 << floor_log2 (vs
);
2318 enum machine_mode vqimode
= targetm
.vectorize
.preferred_simd_mode (QImode
);
2319 if (GET_MODE_CLASS (vqimode
) == MODE_VECTOR_INT
)
2320 return GET_MODE_NUNITS (vqimode
);
2324 /* Helper function of lower_rec_input_clauses, used for #pragma omp simd
2328 lower_rec_simd_input_clauses (tree new_var
, omp_context
*ctx
, int &max_vf
,
2329 tree
&idx
, tree
&lane
, tree
&ivar
, tree
&lvar
)
2333 max_vf
= omp_max_vf ();
2336 tree c
= find_omp_clause (gimple_omp_for_clauses (ctx
->stmt
),
2337 OMP_CLAUSE_SAFELEN
);
2339 && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c
), max_vf
) == -1)
2340 max_vf
= tree_low_cst (OMP_CLAUSE_SAFELEN_EXPR (c
), 0);
2344 idx
= create_tmp_var (unsigned_type_node
, NULL
);
2345 lane
= create_tmp_var (unsigned_type_node
, NULL
);
2351 tree atype
= build_array_type_nelts (TREE_TYPE (new_var
), max_vf
);
2352 tree avar
= create_tmp_var_raw (atype
, NULL
);
2353 if (TREE_ADDRESSABLE (new_var
))
2354 TREE_ADDRESSABLE (avar
) = 1;
2355 DECL_ATTRIBUTES (avar
)
2356 = tree_cons (get_identifier ("omp simd array"), NULL
,
2357 DECL_ATTRIBUTES (avar
));
2358 gimple_add_tmp_var (avar
);
2359 ivar
= build4 (ARRAY_REF
, TREE_TYPE (new_var
), avar
, idx
,
2360 NULL_TREE
, NULL_TREE
);
2361 lvar
= build4 (ARRAY_REF
, TREE_TYPE (new_var
), avar
, lane
,
2362 NULL_TREE
, NULL_TREE
);
2363 SET_DECL_VALUE_EXPR (new_var
, lvar
);
2364 DECL_HAS_VALUE_EXPR_P (new_var
) = 1;
2368 /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
2369 from the receiver (aka child) side and initializers for REFERENCE_TYPE
2370 private variables. Initialization statements go in ILIST, while calls
2371 to destructors go in DLIST. */
2374 lower_rec_input_clauses (tree clauses
, gimple_seq
*ilist
, gimple_seq
*dlist
,
2377 tree c
, dtor
, copyin_seq
, x
, ptr
;
2378 bool copyin_by_ref
= false;
2379 bool lastprivate_firstprivate
= false;
2381 bool is_simd
= (gimple_code (ctx
->stmt
) == GIMPLE_OMP_FOR
2382 && gimple_omp_for_kind (ctx
->stmt
) == GF_OMP_FOR_KIND_SIMD
);
2384 tree lane
= NULL_TREE
, idx
= NULL_TREE
;
2385 tree ivar
= NULL_TREE
, lvar
= NULL_TREE
;
2386 gimple_seq llist
[2] = { NULL
, NULL
};
2390 /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
2391 with data sharing clauses referencing variable sized vars. That
2392 is unnecessarily hard to support and very unlikely to result in
2393 vectorized code anyway. */
2395 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
2396 switch (OMP_CLAUSE_CODE (c
))
2398 case OMP_CLAUSE_REDUCTION
:
2399 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
2402 case OMP_CLAUSE_PRIVATE
:
2403 case OMP_CLAUSE_FIRSTPRIVATE
:
2404 case OMP_CLAUSE_LASTPRIVATE
:
2405 case OMP_CLAUSE_LINEAR
:
2406 if (is_variable_sized (OMP_CLAUSE_DECL (c
)))
2413 /* Do all the fixed sized types in the first pass, and the variable sized
2414 types in the second pass. This makes sure that the scalar arguments to
2415 the variable sized types are processed before we use them in the
2416 variable sized operations. */
2417 for (pass
= 0; pass
< 2; ++pass
)
2419 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
2421 enum omp_clause_code c_kind
= OMP_CLAUSE_CODE (c
);
2424 location_t clause_loc
= OMP_CLAUSE_LOCATION (c
);
2428 case OMP_CLAUSE_PRIVATE
:
2429 if (OMP_CLAUSE_PRIVATE_DEBUG (c
))
2432 case OMP_CLAUSE_SHARED
:
2433 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c
), ctx
) == NULL
)
2435 gcc_assert (is_global_var (OMP_CLAUSE_DECL (c
)));
2438 case OMP_CLAUSE_FIRSTPRIVATE
:
2439 case OMP_CLAUSE_COPYIN
:
2440 case OMP_CLAUSE_REDUCTION
:
2442 case OMP_CLAUSE_LINEAR
:
2444 case OMP_CLAUSE_LASTPRIVATE
:
2445 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c
))
2447 lastprivate_firstprivate
= true;
2456 new_var
= var
= OMP_CLAUSE_DECL (c
);
2457 if (c_kind
!= OMP_CLAUSE_COPYIN
)
2458 new_var
= lookup_decl (var
, ctx
);
2460 if (c_kind
== OMP_CLAUSE_SHARED
|| c_kind
== OMP_CLAUSE_COPYIN
)
2465 else if (is_variable_sized (var
))
2467 /* For variable sized types, we need to allocate the
2468 actual storage here. Call alloca and store the
2469 result in the pointer decl that we created elsewhere. */
2473 if (c_kind
!= OMP_CLAUSE_FIRSTPRIVATE
|| !is_task_ctx (ctx
))
2478 ptr
= DECL_VALUE_EXPR (new_var
);
2479 gcc_assert (TREE_CODE (ptr
) == INDIRECT_REF
);
2480 ptr
= TREE_OPERAND (ptr
, 0);
2481 gcc_assert (DECL_P (ptr
));
2482 x
= TYPE_SIZE_UNIT (TREE_TYPE (new_var
));
2484 /* void *tmp = __builtin_alloca */
2485 atmp
= builtin_decl_explicit (BUILT_IN_ALLOCA
);
2486 stmt
= gimple_build_call (atmp
, 1, x
);
2487 tmp
= create_tmp_var_raw (ptr_type_node
, NULL
);
2488 gimple_add_tmp_var (tmp
);
2489 gimple_call_set_lhs (stmt
, tmp
);
2491 gimple_seq_add_stmt (ilist
, stmt
);
2493 x
= fold_convert_loc (clause_loc
, TREE_TYPE (ptr
), tmp
);
2494 gimplify_assign (ptr
, x
, ilist
);
2497 else if (is_reference (var
))
2499 /* For references that are being privatized for Fortran,
2500 allocate new backing storage for the new pointer
2501 variable. This allows us to avoid changing all the
2502 code that expects a pointer to something that expects
2503 a direct variable. Note that this doesn't apply to
2504 C++, since reference types are disallowed in data
2505 sharing clauses there, except for NRV optimized
2510 x
= TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var
)));
2511 if (c_kind
== OMP_CLAUSE_FIRSTPRIVATE
&& is_task_ctx (ctx
))
2513 x
= build_receiver_ref (var
, false, ctx
);
2514 x
= build_fold_addr_expr_loc (clause_loc
, x
);
2516 else if (TREE_CONSTANT (x
))
2518 const char *name
= NULL
;
2519 if (DECL_NAME (var
))
2520 name
= IDENTIFIER_POINTER (DECL_NAME (new_var
));
2522 x
= create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var
)),
2524 gimple_add_tmp_var (x
);
2525 TREE_ADDRESSABLE (x
) = 1;
2526 x
= build_fold_addr_expr_loc (clause_loc
, x
);
2530 tree atmp
= builtin_decl_explicit (BUILT_IN_ALLOCA
);
2531 x
= build_call_expr_loc (clause_loc
, atmp
, 1, x
);
2534 x
= fold_convert_loc (clause_loc
, TREE_TYPE (new_var
), x
);
2535 gimplify_assign (new_var
, x
, ilist
);
2537 new_var
= build_simple_mem_ref_loc (clause_loc
, new_var
);
2539 else if (c_kind
== OMP_CLAUSE_REDUCTION
2540 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
2548 switch (OMP_CLAUSE_CODE (c
))
2550 case OMP_CLAUSE_SHARED
:
2551 /* Shared global vars are just accessed directly. */
2552 if (is_global_var (new_var
))
2554 /* Set up the DECL_VALUE_EXPR for shared variables now. This
2555 needs to be delayed until after fixup_child_record_type so
2556 that we get the correct type during the dereference. */
2557 by_ref
= use_pointer_for_field (var
, ctx
);
2558 x
= build_receiver_ref (var
, by_ref
, ctx
);
2559 SET_DECL_VALUE_EXPR (new_var
, x
);
2560 DECL_HAS_VALUE_EXPR_P (new_var
) = 1;
2562 /* ??? If VAR is not passed by reference, and the variable
2563 hasn't been initialized yet, then we'll get a warning for
2564 the store into the omp_data_s structure. Ideally, we'd be
2565 able to notice this and not store anything at all, but
2566 we're generating code too early. Suppress the warning. */
2568 TREE_NO_WARNING (var
) = 1;
2571 case OMP_CLAUSE_LASTPRIVATE
:
2572 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c
))
2576 case OMP_CLAUSE_PRIVATE
:
2577 if (OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_PRIVATE
)
2578 x
= build_outer_var_ref (var
, ctx
);
2579 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c
))
2581 if (is_task_ctx (ctx
))
2582 x
= build_receiver_ref (var
, false, ctx
);
2584 x
= build_outer_var_ref (var
, ctx
);
2589 x
= lang_hooks
.decls
.omp_clause_default_ctor (c
, new_var
, x
);
2592 tree y
= lang_hooks
.decls
.omp_clause_dtor (c
, new_var
);
2593 if ((TREE_ADDRESSABLE (new_var
) || x
|| y
2594 || OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LASTPRIVATE
)
2595 && lower_rec_simd_input_clauses (new_var
, ctx
, max_vf
,
2596 idx
, lane
, ivar
, lvar
))
2599 x
= lang_hooks
.decls
.omp_clause_default_ctor
2600 (c
, unshare_expr (ivar
), x
);
2602 gimplify_and_add (x
, &llist
[0]);
2605 y
= lang_hooks
.decls
.omp_clause_dtor (c
, ivar
);
2608 gimple_seq tseq
= NULL
;
2611 gimplify_stmt (&dtor
, &tseq
);
2612 gimple_seq_add_seq (&llist
[1], tseq
);
2619 gimplify_and_add (x
, ilist
);
2623 x
= lang_hooks
.decls
.omp_clause_dtor (c
, new_var
);
2626 gimple_seq tseq
= NULL
;
2629 gimplify_stmt (&dtor
, &tseq
);
2630 gimple_seq_add_seq (dlist
, tseq
);
2634 case OMP_CLAUSE_LINEAR
:
2635 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c
))
2636 goto do_firstprivate
;
2637 if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c
))
2640 x
= build_outer_var_ref (var
, ctx
);
2643 case OMP_CLAUSE_FIRSTPRIVATE
:
2644 if (is_task_ctx (ctx
))
2646 if (is_reference (var
) || is_variable_sized (var
))
2648 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var
,
2650 || use_pointer_for_field (var
, NULL
))
2652 x
= build_receiver_ref (var
, false, ctx
);
2653 SET_DECL_VALUE_EXPR (new_var
, x
);
2654 DECL_HAS_VALUE_EXPR_P (new_var
) = 1;
2659 x
= build_outer_var_ref (var
, ctx
);
2662 if ((OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_LINEAR
2663 || TREE_ADDRESSABLE (new_var
))
2664 && lower_rec_simd_input_clauses (new_var
, ctx
, max_vf
,
2665 idx
, lane
, ivar
, lvar
))
2667 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LINEAR
)
2669 tree iv
= create_tmp_var (TREE_TYPE (new_var
), NULL
);
2670 x
= lang_hooks
.decls
.omp_clause_copy_ctor (c
, iv
, x
);
2671 gimplify_and_add (x
, ilist
);
2672 gimple_stmt_iterator gsi
2673 = gsi_start_1 (gimple_omp_body_ptr (ctx
->stmt
));
2675 = gimple_build_assign (unshare_expr (lvar
), iv
);
2676 gsi_insert_before_without_update (&gsi
, g
,
2678 tree stept
= POINTER_TYPE_P (TREE_TYPE (x
))
2679 ? sizetype
: TREE_TYPE (x
);
2680 tree t
= fold_convert (stept
,
2681 OMP_CLAUSE_LINEAR_STEP (c
));
2682 enum tree_code code
= PLUS_EXPR
;
2683 if (POINTER_TYPE_P (TREE_TYPE (new_var
)))
2684 code
= POINTER_PLUS_EXPR
;
2685 g
= gimple_build_assign_with_ops (code
, iv
, iv
, t
);
2686 gsi_insert_before_without_update (&gsi
, g
,
2690 x
= lang_hooks
.decls
.omp_clause_copy_ctor
2691 (c
, unshare_expr (ivar
), x
);
2692 gimplify_and_add (x
, &llist
[0]);
2693 x
= lang_hooks
.decls
.omp_clause_dtor (c
, ivar
);
2696 gimple_seq tseq
= NULL
;
2699 gimplify_stmt (&dtor
, &tseq
);
2700 gimple_seq_add_seq (&llist
[1], tseq
);
2705 x
= lang_hooks
.decls
.omp_clause_copy_ctor (c
, new_var
, x
);
2706 gimplify_and_add (x
, ilist
);
2709 case OMP_CLAUSE_COPYIN
:
2710 by_ref
= use_pointer_for_field (var
, NULL
);
2711 x
= build_receiver_ref (var
, by_ref
, ctx
);
2712 x
= lang_hooks
.decls
.omp_clause_assign_op (c
, new_var
, x
);
2713 append_to_statement_list (x
, ©in_seq
);
2714 copyin_by_ref
|= by_ref
;
2717 case OMP_CLAUSE_REDUCTION
:
2718 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
2720 tree placeholder
= OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
);
2721 x
= build_outer_var_ref (var
, ctx
);
2723 /* FIXME: Not handled yet. */
2724 gcc_assert (!is_simd
);
2725 if (is_reference (var
))
2726 x
= build_fold_addr_expr_loc (clause_loc
, x
);
2727 SET_DECL_VALUE_EXPR (placeholder
, x
);
2728 DECL_HAS_VALUE_EXPR_P (placeholder
) = 1;
2729 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
), ctx
);
2730 gimple_seq_add_seq (ilist
,
2731 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
));
2732 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c
) = NULL
;
2733 DECL_HAS_VALUE_EXPR_P (placeholder
) = 0;
2737 x
= omp_reduction_init (c
, TREE_TYPE (new_var
));
2738 gcc_assert (TREE_CODE (TREE_TYPE (new_var
)) != ARRAY_TYPE
);
2740 && lower_rec_simd_input_clauses (new_var
, ctx
, max_vf
,
2741 idx
, lane
, ivar
, lvar
))
2743 enum tree_code code
= OMP_CLAUSE_REDUCTION_CODE (c
);
2744 tree ref
= build_outer_var_ref (var
, ctx
);
2746 gimplify_assign (unshare_expr (ivar
), x
, &llist
[0]);
2748 /* reduction(-:var) sums up the partial results, so it
2749 acts identically to reduction(+:var). */
2750 if (code
== MINUS_EXPR
)
2753 x
= build2 (code
, TREE_TYPE (ref
), ref
, ivar
);
2754 ref
= build_outer_var_ref (var
, ctx
);
2755 gimplify_assign (ref
, x
, &llist
[1]);
2759 gimplify_assign (new_var
, x
, ilist
);
2761 gimplify_assign (build_outer_var_ref (var
, ctx
),
2775 tree uid
= create_tmp_var (ptr_type_node
, "simduid");
2777 = gimple_build_call_internal (IFN_GOMP_SIMD_LANE
, 1, uid
);
2778 gimple_call_set_lhs (g
, lane
);
2779 gimple_stmt_iterator gsi
= gsi_start_1 (gimple_omp_body_ptr (ctx
->stmt
));
2780 gsi_insert_before_without_update (&gsi
, g
, GSI_SAME_STMT
);
2781 c
= build_omp_clause (UNKNOWN_LOCATION
, OMP_CLAUSE__SIMDUID_
);
2782 OMP_CLAUSE__SIMDUID__DECL (c
) = uid
;
2783 OMP_CLAUSE_CHAIN (c
) = gimple_omp_for_clauses (ctx
->stmt
);
2784 gimple_omp_for_set_clauses (ctx
->stmt
, c
);
2785 g
= gimple_build_assign_with_ops (INTEGER_CST
, lane
,
2786 build_int_cst (unsigned_type_node
, 0),
2788 gimple_seq_add_stmt (ilist
, g
);
2789 for (int i
= 0; i
< 2; i
++)
2792 tree vf
= create_tmp_var (unsigned_type_node
, NULL
);
2793 g
= gimple_build_call_internal (IFN_GOMP_SIMD_VF
, 1, uid
);
2794 gimple_call_set_lhs (g
, vf
);
2795 gimple_seq
*seq
= i
== 0 ? ilist
: dlist
;
2796 gimple_seq_add_stmt (seq
, g
);
2797 tree t
= build_int_cst (unsigned_type_node
, 0);
2798 g
= gimple_build_assign_with_ops (INTEGER_CST
, idx
, t
, NULL_TREE
);
2799 gimple_seq_add_stmt (seq
, g
);
2800 tree body
= create_artificial_label (UNKNOWN_LOCATION
);
2801 tree header
= create_artificial_label (UNKNOWN_LOCATION
);
2802 tree end
= create_artificial_label (UNKNOWN_LOCATION
);
2803 gimple_seq_add_stmt (seq
, gimple_build_goto (header
));
2804 gimple_seq_add_stmt (seq
, gimple_build_label (body
));
2805 gimple_seq_add_seq (seq
, llist
[i
]);
2806 t
= build_int_cst (unsigned_type_node
, 1);
2807 g
= gimple_build_assign_with_ops (PLUS_EXPR
, idx
, idx
, t
);
2808 gimple_seq_add_stmt (seq
, g
);
2809 gimple_seq_add_stmt (seq
, gimple_build_label (header
));
2810 g
= gimple_build_cond (LT_EXPR
, idx
, vf
, body
, end
);
2811 gimple_seq_add_stmt (seq
, g
);
2812 gimple_seq_add_stmt (seq
, gimple_build_label (end
));
2816 /* The copyin sequence is not to be executed by the main thread, since
2817 that would result in self-copies. Perhaps not visible to scalars,
2818 but it certainly is to C++ operator=. */
2821 x
= build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM
),
2823 x
= build2 (NE_EXPR
, boolean_type_node
, x
,
2824 build_int_cst (TREE_TYPE (x
), 0));
2825 x
= build3 (COND_EXPR
, void_type_node
, x
, copyin_seq
, NULL
);
2826 gimplify_and_add (x
, ilist
);
2829 /* If any copyin variable is passed by reference, we must ensure the
2830 master thread doesn't modify it before it is copied over in all
2831 threads. Similarly for variables in both firstprivate and
2832 lastprivate clauses we need to ensure the lastprivate copying
2833 happens after firstprivate copying in all threads. */
2834 if (copyin_by_ref
|| lastprivate_firstprivate
)
2836 /* Don't add any barrier for #pragma omp simd or
2837 #pragma omp distribute. */
2838 if (gimple_code (ctx
->stmt
) != GIMPLE_OMP_FOR
2839 || gimple_omp_for_kind (ctx
->stmt
) == GF_OMP_FOR_KIND_FOR
)
2840 gimplify_and_add (build_omp_barrier (), ilist
);
2843 /* If max_vf is non-zero, then we can use only a vectorization factor
2844 up to the max_vf we chose. So stick it into the safelen clause. */
2847 tree c
= find_omp_clause (gimple_omp_for_clauses (ctx
->stmt
),
2848 OMP_CLAUSE_SAFELEN
);
2850 || compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c
),
2853 c
= build_omp_clause (UNKNOWN_LOCATION
, OMP_CLAUSE_SAFELEN
);
2854 OMP_CLAUSE_SAFELEN_EXPR (c
) = build_int_cst (integer_type_node
,
2856 OMP_CLAUSE_CHAIN (c
) = gimple_omp_for_clauses (ctx
->stmt
);
2857 gimple_omp_for_set_clauses (ctx
->stmt
, c
);
2863 /* Generate code to implement the LASTPRIVATE clauses. This is used for
2864 both parallel and workshare constructs. PREDICATE may be NULL if it's
2868 lower_lastprivate_clauses (tree clauses
, tree predicate
, gimple_seq
*stmt_list
,
2871 tree x
, c
, label
= NULL
, orig_clauses
= clauses
;
2872 bool par_clauses
= false;
2873 tree simduid
= NULL
, lastlane
= NULL
;
2875 /* Early exit if there are no lastprivate or linear clauses. */
2876 for (; clauses
; clauses
= OMP_CLAUSE_CHAIN (clauses
))
2877 if (OMP_CLAUSE_CODE (clauses
) == OMP_CLAUSE_LASTPRIVATE
2878 || (OMP_CLAUSE_CODE (clauses
) == OMP_CLAUSE_LINEAR
2879 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses
)))
2881 if (clauses
== NULL
)
2883 /* If this was a workshare clause, see if it had been combined
2884 with its parallel. In that case, look for the clauses on the
2885 parallel statement itself. */
2886 if (is_parallel_ctx (ctx
))
2890 if (ctx
== NULL
|| !is_parallel_ctx (ctx
))
2893 clauses
= find_omp_clause (gimple_omp_parallel_clauses (ctx
->stmt
),
2894 OMP_CLAUSE_LASTPRIVATE
);
2895 if (clauses
== NULL
)
2903 tree label_true
, arm1
, arm2
;
2905 label
= create_artificial_label (UNKNOWN_LOCATION
);
2906 label_true
= create_artificial_label (UNKNOWN_LOCATION
);
2907 arm1
= TREE_OPERAND (predicate
, 0);
2908 arm2
= TREE_OPERAND (predicate
, 1);
2909 gimplify_expr (&arm1
, stmt_list
, NULL
, is_gimple_val
, fb_rvalue
);
2910 gimplify_expr (&arm2
, stmt_list
, NULL
, is_gimple_val
, fb_rvalue
);
2911 stmt
= gimple_build_cond (TREE_CODE (predicate
), arm1
, arm2
,
2913 gimple_seq_add_stmt (stmt_list
, stmt
);
2914 gimple_seq_add_stmt (stmt_list
, gimple_build_label (label_true
));
2917 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_FOR
2918 && gimple_omp_for_kind (ctx
->stmt
) == GF_OMP_FOR_KIND_SIMD
)
2920 simduid
= find_omp_clause (orig_clauses
, OMP_CLAUSE__SIMDUID_
);
2922 simduid
= OMP_CLAUSE__SIMDUID__DECL (simduid
);
2925 for (c
= clauses
; c
;)
2928 location_t clause_loc
= OMP_CLAUSE_LOCATION (c
);
2930 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LASTPRIVATE
2931 || (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LINEAR
2932 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c
)))
2934 var
= OMP_CLAUSE_DECL (c
);
2935 new_var
= lookup_decl (var
, ctx
);
2937 if (simduid
&& DECL_HAS_VALUE_EXPR_P (new_var
))
2939 tree val
= DECL_VALUE_EXPR (new_var
);
2940 if (TREE_CODE (val
) == ARRAY_REF
2941 && VAR_P (TREE_OPERAND (val
, 0))
2942 && lookup_attribute ("omp simd array",
2943 DECL_ATTRIBUTES (TREE_OPERAND (val
,
2946 if (lastlane
== NULL
)
2948 lastlane
= create_tmp_var (unsigned_type_node
, NULL
);
2950 = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE
,
2952 TREE_OPERAND (val
, 1));
2953 gimple_call_set_lhs (g
, lastlane
);
2954 gimple_seq_add_stmt (stmt_list
, g
);
2956 new_var
= build4 (ARRAY_REF
, TREE_TYPE (val
),
2957 TREE_OPERAND (val
, 0), lastlane
,
2958 NULL_TREE
, NULL_TREE
);
2962 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_LASTPRIVATE
2963 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
))
2965 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
), ctx
);
2966 gimple_seq_add_seq (stmt_list
,
2967 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
));
2968 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c
) = NULL
;
2971 x
= build_outer_var_ref (var
, ctx
);
2972 if (is_reference (var
))
2973 new_var
= build_simple_mem_ref_loc (clause_loc
, new_var
);
2974 x
= lang_hooks
.decls
.omp_clause_assign_op (c
, x
, new_var
);
2975 gimplify_and_add (x
, stmt_list
);
2977 c
= OMP_CLAUSE_CHAIN (c
);
2978 if (c
== NULL
&& !par_clauses
)
2980 /* If this was a workshare clause, see if it had been combined
2981 with its parallel. In that case, continue looking for the
2982 clauses also on the parallel statement itself. */
2983 if (is_parallel_ctx (ctx
))
2987 if (ctx
== NULL
|| !is_parallel_ctx (ctx
))
2990 c
= find_omp_clause (gimple_omp_parallel_clauses (ctx
->stmt
),
2991 OMP_CLAUSE_LASTPRIVATE
);
2997 gimple_seq_add_stmt (stmt_list
, gimple_build_label (label
));
3001 /* Generate code to implement the REDUCTION clauses. */
3004 lower_reduction_clauses (tree clauses
, gimple_seq
*stmt_seqp
, omp_context
*ctx
)
3006 gimple_seq sub_seq
= NULL
;
3011 /* SIMD reductions are handled in lower_rec_input_clauses. */
3012 if (gimple_code (ctx
->stmt
) == GIMPLE_OMP_FOR
3013 && gimple_omp_for_kind (ctx
->stmt
) == GF_OMP_FOR_KIND_SIMD
)
3016 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
3017 update in that case, otherwise use a lock. */
3018 for (c
= clauses
; c
&& count
< 2; c
= OMP_CLAUSE_CHAIN (c
))
3019 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_REDUCTION
)
3021 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
3023 /* Never use OMP_ATOMIC for array reductions. */
3033 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
3035 tree var
, ref
, new_var
;
3036 enum tree_code code
;
3037 location_t clause_loc
= OMP_CLAUSE_LOCATION (c
);
3039 if (OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_REDUCTION
)
3042 var
= OMP_CLAUSE_DECL (c
);
3043 new_var
= lookup_decl (var
, ctx
);
3044 if (is_reference (var
))
3045 new_var
= build_simple_mem_ref_loc (clause_loc
, new_var
);
3046 ref
= build_outer_var_ref (var
, ctx
);
3047 code
= OMP_CLAUSE_REDUCTION_CODE (c
);
3049 /* reduction(-:var) sums up the partial results, so it acts
3050 identically to reduction(+:var). */
3051 if (code
== MINUS_EXPR
)
3056 tree addr
= build_fold_addr_expr_loc (clause_loc
, ref
);
3058 addr
= save_expr (addr
);
3059 ref
= build1 (INDIRECT_REF
, TREE_TYPE (TREE_TYPE (addr
)), addr
);
3060 x
= fold_build2_loc (clause_loc
, code
, TREE_TYPE (ref
), ref
, new_var
);
3061 x
= build2 (OMP_ATOMIC
, void_type_node
, addr
, x
);
3062 gimplify_and_add (x
, stmt_seqp
);
3066 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
))
3068 tree placeholder
= OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
);
3070 if (is_reference (var
))
3071 ref
= build_fold_addr_expr_loc (clause_loc
, ref
);
3072 SET_DECL_VALUE_EXPR (placeholder
, ref
);
3073 DECL_HAS_VALUE_EXPR_P (placeholder
) = 1;
3074 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
), ctx
);
3075 gimple_seq_add_seq (&sub_seq
, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
));
3076 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c
) = NULL
;
3077 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c
) = NULL
;
3081 x
= build2 (code
, TREE_TYPE (ref
), ref
, new_var
);
3082 ref
= build_outer_var_ref (var
, ctx
);
3083 gimplify_assign (ref
, x
, &sub_seq
);
3087 stmt
= gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START
),
3089 gimple_seq_add_stmt (stmt_seqp
, stmt
);
3091 gimple_seq_add_seq (stmt_seqp
, sub_seq
);
3093 stmt
= gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END
),
3095 gimple_seq_add_stmt (stmt_seqp
, stmt
);
3099 /* Generate code to implement the COPYPRIVATE clauses. */
3102 lower_copyprivate_clauses (tree clauses
, gimple_seq
*slist
, gimple_seq
*rlist
,
3107 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
3109 tree var
, new_var
, ref
, x
;
3111 location_t clause_loc
= OMP_CLAUSE_LOCATION (c
);
3113 if (OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_COPYPRIVATE
)
3116 var
= OMP_CLAUSE_DECL (c
);
3117 by_ref
= use_pointer_for_field (var
, NULL
);
3119 ref
= build_sender_ref (var
, ctx
);
3120 x
= new_var
= lookup_decl_in_outer_ctx (var
, ctx
);
3123 x
= build_fold_addr_expr_loc (clause_loc
, new_var
);
3124 x
= fold_convert_loc (clause_loc
, TREE_TYPE (ref
), x
);
3126 gimplify_assign (ref
, x
, slist
);
3128 ref
= build_receiver_ref (var
, false, ctx
);
3131 ref
= fold_convert_loc (clause_loc
,
3132 build_pointer_type (TREE_TYPE (new_var
)),
3134 ref
= build_fold_indirect_ref_loc (clause_loc
, ref
);
3136 if (is_reference (var
))
3138 ref
= fold_convert_loc (clause_loc
, TREE_TYPE (new_var
), ref
);
3139 ref
= build_simple_mem_ref_loc (clause_loc
, ref
);
3140 new_var
= build_simple_mem_ref_loc (clause_loc
, new_var
);
3142 x
= lang_hooks
.decls
.omp_clause_assign_op (c
, new_var
, ref
);
3143 gimplify_and_add (x
, rlist
);
3148 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
3149 and REDUCTION from the sender (aka parent) side. */
3152 lower_send_clauses (tree clauses
, gimple_seq
*ilist
, gimple_seq
*olist
,
3157 for (c
= clauses
; c
; c
= OMP_CLAUSE_CHAIN (c
))
3159 tree val
, ref
, x
, var
;
3160 bool by_ref
, do_in
= false, do_out
= false;
3161 location_t clause_loc
= OMP_CLAUSE_LOCATION (c
);
3163 switch (OMP_CLAUSE_CODE (c
))
3165 case OMP_CLAUSE_PRIVATE
:
3166 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c
))
3169 case OMP_CLAUSE_FIRSTPRIVATE
:
3170 case OMP_CLAUSE_COPYIN
:
3171 case OMP_CLAUSE_LASTPRIVATE
:
3172 case OMP_CLAUSE_REDUCTION
:
3178 val
= OMP_CLAUSE_DECL (c
);
3179 var
= lookup_decl_in_outer_ctx (val
, ctx
);
3181 if (OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_COPYIN
3182 && is_global_var (var
))
3184 if (is_variable_sized (val
))
3186 by_ref
= use_pointer_for_field (val
, NULL
);
3188 switch (OMP_CLAUSE_CODE (c
))
3190 case OMP_CLAUSE_PRIVATE
:
3191 case OMP_CLAUSE_FIRSTPRIVATE
:
3192 case OMP_CLAUSE_COPYIN
:
3196 case OMP_CLAUSE_LASTPRIVATE
:
3197 if (by_ref
|| is_reference (val
))
3199 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c
))
3206 if (lang_hooks
.decls
.omp_private_outer_ref (val
))
3211 case OMP_CLAUSE_REDUCTION
:
3213 do_out
= !(by_ref
|| is_reference (val
));
3222 ref
= build_sender_ref (val
, ctx
);
3223 x
= by_ref
? build_fold_addr_expr_loc (clause_loc
, var
) : var
;
3224 gimplify_assign (ref
, x
, ilist
);
3225 if (is_task_ctx (ctx
))
3226 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref
, 1)) = NULL
;
3231 ref
= build_sender_ref (val
, ctx
);
3232 gimplify_assign (var
, ref
, olist
);
3237 /* Generate code to implement SHARED from the sender (aka parent)
3238 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
3239 list things that got automatically shared. */
3242 lower_send_shared_vars (gimple_seq
*ilist
, gimple_seq
*olist
, omp_context
*ctx
)
3244 tree var
, ovar
, nvar
, f
, x
, record_type
;
3246 if (ctx
->record_type
== NULL
)
3249 record_type
= ctx
->srecord_type
? ctx
->srecord_type
: ctx
->record_type
;
3250 for (f
= TYPE_FIELDS (record_type
); f
; f
= DECL_CHAIN (f
))
3252 ovar
= DECL_ABSTRACT_ORIGIN (f
);
3253 nvar
= maybe_lookup_decl (ovar
, ctx
);
3254 if (!nvar
|| !DECL_HAS_VALUE_EXPR_P (nvar
))
3257 /* If CTX is a nested parallel directive. Find the immediately
3258 enclosing parallel or workshare construct that contains a
3259 mapping for OVAR. */
3260 var
= lookup_decl_in_outer_ctx (ovar
, ctx
);
3262 if (use_pointer_for_field (ovar
, ctx
))
3264 x
= build_sender_ref (ovar
, ctx
);
3265 var
= build_fold_addr_expr (var
);
3266 gimplify_assign (x
, var
, ilist
);
3270 x
= build_sender_ref (ovar
, ctx
);
3271 gimplify_assign (x
, var
, ilist
);
3273 if (!TREE_READONLY (var
)
3274 /* We don't need to receive a new reference to a result
3275 or parm decl. In fact we may not store to it as we will
3276 invalidate any pending RSO and generate wrong gimple
3278 && !((TREE_CODE (var
) == RESULT_DECL
3279 || TREE_CODE (var
) == PARM_DECL
)
3280 && DECL_BY_REFERENCE (var
)))
3282 x
= build_sender_ref (ovar
, ctx
);
3283 gimplify_assign (var
, x
, olist
);
3290 /* A convenience function to build an empty GIMPLE_COND with just the
3294 gimple_build_cond_empty (tree cond
)
3296 enum tree_code pred_code
;
3299 gimple_cond_get_ops_from_tree (cond
, &pred_code
, &lhs
, &rhs
);
3300 return gimple_build_cond (pred_code
, lhs
, rhs
, NULL_TREE
, NULL_TREE
);
3304 /* Build the function calls to GOMP_parallel_start etc to actually
3305 generate the parallel operation. REGION is the parallel region
3306 being expanded. BB is the block where to insert the code. WS_ARGS
3307 will be set if this is a call to a combined parallel+workshare
3308 construct, it contains the list of additional arguments needed by
3309 the workshare construct. */
3312 expand_parallel_call (struct omp_region
*region
, basic_block bb
,
3313 gimple entry_stmt
, vec
<tree
, va_gc
> *ws_args
)
3315 tree t
, t1
, t2
, val
, cond
, c
, clauses
;
3316 gimple_stmt_iterator gsi
;
3318 enum built_in_function start_ix
;
3320 location_t clause_loc
;
3321 vec
<tree
, va_gc
> *args
;
3323 clauses
= gimple_omp_parallel_clauses (entry_stmt
);
3325 /* Determine what flavor of GOMP_parallel_start we will be
3327 start_ix
= BUILT_IN_GOMP_PARALLEL_START
;
3328 if (is_combined_parallel (region
))
3330 switch (region
->inner
->type
)
3332 case GIMPLE_OMP_FOR
:
3333 gcc_assert (region
->inner
->sched_kind
!= OMP_CLAUSE_SCHEDULE_AUTO
);
3334 start_ix2
= ((int)BUILT_IN_GOMP_PARALLEL_LOOP_STATIC_START
3335 + (region
->inner
->sched_kind
3336 == OMP_CLAUSE_SCHEDULE_RUNTIME
3337 ? 3 : region
->inner
->sched_kind
));
3338 start_ix
= (enum built_in_function
)start_ix2
;
3340 case GIMPLE_OMP_SECTIONS
:
3341 start_ix
= BUILT_IN_GOMP_PARALLEL_SECTIONS_START
;
3348 /* By default, the value of NUM_THREADS is zero (selected at run time)
3349 and there is no conditional. */
3351 val
= build_int_cst (unsigned_type_node
, 0);
3353 c
= find_omp_clause (clauses
, OMP_CLAUSE_IF
);
3355 cond
= OMP_CLAUSE_IF_EXPR (c
);
3357 c
= find_omp_clause (clauses
, OMP_CLAUSE_NUM_THREADS
);
3360 val
= OMP_CLAUSE_NUM_THREADS_EXPR (c
);
3361 clause_loc
= OMP_CLAUSE_LOCATION (c
);
3364 clause_loc
= gimple_location (entry_stmt
);
3366 /* Ensure 'val' is of the correct type. */
3367 val
= fold_convert_loc (clause_loc
, unsigned_type_node
, val
);
3369 /* If we found the clause 'if (cond)', build either
3370 (cond != 0) or (cond ? val : 1u). */
3373 gimple_stmt_iterator gsi
;
3375 cond
= gimple_boolify (cond
);
3377 if (integer_zerop (val
))
3378 val
= fold_build2_loc (clause_loc
,
3379 EQ_EXPR
, unsigned_type_node
, cond
,
3380 build_int_cst (TREE_TYPE (cond
), 0));
3383 basic_block cond_bb
, then_bb
, else_bb
;
3384 edge e
, e_then
, e_else
;
3385 tree tmp_then
, tmp_else
, tmp_join
, tmp_var
;
3387 tmp_var
= create_tmp_var (TREE_TYPE (val
), NULL
);
3388 if (gimple_in_ssa_p (cfun
))
3390 tmp_then
= make_ssa_name (tmp_var
, NULL
);
3391 tmp_else
= make_ssa_name (tmp_var
, NULL
);
3392 tmp_join
= make_ssa_name (tmp_var
, NULL
);
3401 e
= split_block (bb
, NULL
);
3406 then_bb
= create_empty_bb (cond_bb
);
3407 else_bb
= create_empty_bb (then_bb
);
3408 set_immediate_dominator (CDI_DOMINATORS
, then_bb
, cond_bb
);
3409 set_immediate_dominator (CDI_DOMINATORS
, else_bb
, cond_bb
);
3411 stmt
= gimple_build_cond_empty (cond
);
3412 gsi
= gsi_start_bb (cond_bb
);
3413 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
3415 gsi
= gsi_start_bb (then_bb
);
3416 stmt
= gimple_build_assign (tmp_then
, val
);
3417 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
3419 gsi
= gsi_start_bb (else_bb
);
3420 stmt
= gimple_build_assign
3421 (tmp_else
, build_int_cst (unsigned_type_node
, 1));
3422 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
3424 make_edge (cond_bb
, then_bb
, EDGE_TRUE_VALUE
);
3425 make_edge (cond_bb
, else_bb
, EDGE_FALSE_VALUE
);
3428 add_bb_to_loop (then_bb
, cond_bb
->loop_father
);
3429 add_bb_to_loop (else_bb
, cond_bb
->loop_father
);
3431 e_then
= make_edge (then_bb
, bb
, EDGE_FALLTHRU
);
3432 e_else
= make_edge (else_bb
, bb
, EDGE_FALLTHRU
);
3434 if (gimple_in_ssa_p (cfun
))
3436 gimple phi
= create_phi_node (tmp_join
, bb
);
3437 add_phi_arg (phi
, tmp_then
, e_then
, UNKNOWN_LOCATION
);
3438 add_phi_arg (phi
, tmp_else
, e_else
, UNKNOWN_LOCATION
);
3444 gsi
= gsi_start_bb (bb
);
3445 val
= force_gimple_operand_gsi (&gsi
, val
, true, NULL_TREE
,
3446 false, GSI_CONTINUE_LINKING
);
3449 gsi
= gsi_last_bb (bb
);
3450 t
= gimple_omp_parallel_data_arg (entry_stmt
);
3452 t1
= null_pointer_node
;
3454 t1
= build_fold_addr_expr (t
);
3455 t2
= build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt
));
3457 vec_alloc (args
, 3 + vec_safe_length (ws_args
));
3458 args
->quick_push (t2
);
3459 args
->quick_push (t1
);
3460 args
->quick_push (val
);
3462 args
->splice (*ws_args
);
3464 t
= build_call_expr_loc_vec (UNKNOWN_LOCATION
,
3465 builtin_decl_explicit (start_ix
), args
);
3467 force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
3468 false, GSI_CONTINUE_LINKING
);
3470 t
= gimple_omp_parallel_data_arg (entry_stmt
);
3472 t
= null_pointer_node
;
3474 t
= build_fold_addr_expr (t
);
3475 t
= build_call_expr_loc (gimple_location (entry_stmt
),
3476 gimple_omp_parallel_child_fn (entry_stmt
), 1, t
);
3477 force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
3478 false, GSI_CONTINUE_LINKING
);
3480 t
= build_call_expr_loc (gimple_location (entry_stmt
),
3481 builtin_decl_explicit (BUILT_IN_GOMP_PARALLEL_END
),
3483 force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
3484 false, GSI_CONTINUE_LINKING
);
3488 /* Build the function call to GOMP_task to actually
3489 generate the task operation. BB is the block where to insert the code. */
3492 expand_task_call (basic_block bb
, gimple entry_stmt
)
3494 tree t
, t1
, t2
, t3
, flags
, cond
, c
, c2
, clauses
;
3495 gimple_stmt_iterator gsi
;
3496 location_t loc
= gimple_location (entry_stmt
);
3498 clauses
= gimple_omp_task_clauses (entry_stmt
);
3500 c
= find_omp_clause (clauses
, OMP_CLAUSE_IF
);
3502 cond
= gimple_boolify (OMP_CLAUSE_IF_EXPR (c
));
3504 cond
= boolean_true_node
;
3506 c
= find_omp_clause (clauses
, OMP_CLAUSE_UNTIED
);
3507 c2
= find_omp_clause (clauses
, OMP_CLAUSE_MERGEABLE
);
3508 flags
= build_int_cst (unsigned_type_node
,
3509 (c
? 1 : 0) + (c2
? 4 : 0));
3511 c
= find_omp_clause (clauses
, OMP_CLAUSE_FINAL
);
3514 c
= gimple_boolify (OMP_CLAUSE_FINAL_EXPR (c
));
3515 c
= fold_build3_loc (loc
, COND_EXPR
, unsigned_type_node
, c
,
3516 build_int_cst (unsigned_type_node
, 2),
3517 build_int_cst (unsigned_type_node
, 0));
3518 flags
= fold_build2_loc (loc
, PLUS_EXPR
, unsigned_type_node
, flags
, c
);
3521 gsi
= gsi_last_bb (bb
);
3522 t
= gimple_omp_task_data_arg (entry_stmt
);
3524 t2
= null_pointer_node
;
3526 t2
= build_fold_addr_expr_loc (loc
, t
);
3527 t1
= build_fold_addr_expr_loc (loc
, gimple_omp_task_child_fn (entry_stmt
));
3528 t
= gimple_omp_task_copy_fn (entry_stmt
);
3530 t3
= null_pointer_node
;
3532 t3
= build_fold_addr_expr_loc (loc
, t
);
3534 t
= build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK
),
3536 gimple_omp_task_arg_size (entry_stmt
),
3537 gimple_omp_task_arg_align (entry_stmt
), cond
, flags
);
3539 force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
3540 false, GSI_CONTINUE_LINKING
);
3544 /* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
3545 catch handler and return it. This prevents programs from violating the
3546 structured block semantics with throws. */
3549 maybe_catch_exception (gimple_seq body
)
3554 if (!flag_exceptions
)
3557 if (lang_hooks
.eh_protect_cleanup_actions
!= NULL
)
3558 decl
= lang_hooks
.eh_protect_cleanup_actions ();
3560 decl
= builtin_decl_explicit (BUILT_IN_TRAP
);
3562 g
= gimple_build_eh_must_not_throw (decl
);
3563 g
= gimple_build_try (body
, gimple_seq_alloc_with_stmt (g
),
3566 return gimple_seq_alloc_with_stmt (g
);
3569 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
3572 vec2chain (vec
<tree
, va_gc
> *v
)
3574 tree chain
= NULL_TREE
, t
;
3577 FOR_EACH_VEC_SAFE_ELT_REVERSE (v
, ix
, t
)
3579 DECL_CHAIN (t
) = chain
;
3587 /* Remove barriers in REGION->EXIT's block. Note that this is only
3588 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
3589 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
3590 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
3594 remove_exit_barrier (struct omp_region
*region
)
3596 gimple_stmt_iterator gsi
;
3597 basic_block exit_bb
;
3601 int any_addressable_vars
= -1;
3603 exit_bb
= region
->exit
;
3605 /* If the parallel region doesn't return, we don't have REGION->EXIT
3610 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
3611 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
3612 statements that can appear in between are extremely limited -- no
3613 memory operations at all. Here, we allow nothing at all, so the
3614 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
3615 gsi
= gsi_last_bb (exit_bb
);
3616 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_RETURN
);
3618 if (!gsi_end_p (gsi
) && gimple_code (gsi_stmt (gsi
)) != GIMPLE_LABEL
)
3621 FOR_EACH_EDGE (e
, ei
, exit_bb
->preds
)
3623 gsi
= gsi_last_bb (e
->src
);
3624 if (gsi_end_p (gsi
))
3626 stmt
= gsi_stmt (gsi
);
3627 if (gimple_code (stmt
) == GIMPLE_OMP_RETURN
3628 && !gimple_omp_return_nowait_p (stmt
))
3630 /* OpenMP 3.0 tasks unfortunately prevent this optimization
3631 in many cases. If there could be tasks queued, the barrier
3632 might be needed to let the tasks run before some local
3633 variable of the parallel that the task uses as shared
3634 runs out of scope. The task can be spawned either
3635 from within current function (this would be easy to check)
3636 or from some function it calls and gets passed an address
3637 of such a variable. */
3638 if (any_addressable_vars
< 0)
3640 gimple parallel_stmt
= last_stmt (region
->entry
);
3641 tree child_fun
= gimple_omp_parallel_child_fn (parallel_stmt
);
3642 tree local_decls
, block
, decl
;
3645 any_addressable_vars
= 0;
3646 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun
), ix
, decl
)
3647 if (TREE_ADDRESSABLE (decl
))
3649 any_addressable_vars
= 1;
3652 for (block
= gimple_block (stmt
);
3653 !any_addressable_vars
3655 && TREE_CODE (block
) == BLOCK
;
3656 block
= BLOCK_SUPERCONTEXT (block
))
3658 for (local_decls
= BLOCK_VARS (block
);
3660 local_decls
= DECL_CHAIN (local_decls
))
3661 if (TREE_ADDRESSABLE (local_decls
))
3663 any_addressable_vars
= 1;
3666 if (block
== gimple_block (parallel_stmt
))
3670 if (!any_addressable_vars
)
3671 gimple_omp_return_set_nowait (stmt
);
3677 remove_exit_barriers (struct omp_region
*region
)
3679 if (region
->type
== GIMPLE_OMP_PARALLEL
)
3680 remove_exit_barrier (region
);
3684 region
= region
->inner
;
3685 remove_exit_barriers (region
);
3686 while (region
->next
)
3688 region
= region
->next
;
3689 remove_exit_barriers (region
);
3694 /* Optimize omp_get_thread_num () and omp_get_num_threads ()
3695 calls. These can't be declared as const functions, but
3696 within one parallel body they are constant, so they can be
3697 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
3698 which are declared const. Similarly for task body, except
3699 that in untied task omp_get_thread_num () can change at any task
3700 scheduling point. */
3703 optimize_omp_library_calls (gimple entry_stmt
)
3706 gimple_stmt_iterator gsi
;
3707 tree thr_num_tree
= builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM
);
3708 tree thr_num_id
= DECL_ASSEMBLER_NAME (thr_num_tree
);
3709 tree num_thr_tree
= builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS
);
3710 tree num_thr_id
= DECL_ASSEMBLER_NAME (num_thr_tree
);
3711 bool untied_task
= (gimple_code (entry_stmt
) == GIMPLE_OMP_TASK
3712 && find_omp_clause (gimple_omp_task_clauses (entry_stmt
),
3713 OMP_CLAUSE_UNTIED
) != NULL
);
3716 for (gsi
= gsi_start_bb (bb
); !gsi_end_p (gsi
); gsi_next (&gsi
))
3718 gimple call
= gsi_stmt (gsi
);
3721 if (is_gimple_call (call
)
3722 && (decl
= gimple_call_fndecl (call
))
3723 && DECL_EXTERNAL (decl
)
3724 && TREE_PUBLIC (decl
)
3725 && DECL_INITIAL (decl
) == NULL
)
3729 if (DECL_NAME (decl
) == thr_num_id
)
3731 /* In #pragma omp task untied omp_get_thread_num () can change
3732 during the execution of the task region. */
3735 built_in
= builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM
);
3737 else if (DECL_NAME (decl
) == num_thr_id
)
3738 built_in
= builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS
);
3742 if (DECL_ASSEMBLER_NAME (decl
) != DECL_ASSEMBLER_NAME (built_in
)
3743 || gimple_call_num_args (call
) != 0)
3746 if (flag_exceptions
&& !TREE_NOTHROW (decl
))
3749 if (TREE_CODE (TREE_TYPE (decl
)) != FUNCTION_TYPE
3750 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl
)),
3751 TREE_TYPE (TREE_TYPE (built_in
))))
3754 gimple_call_set_fndecl (call
, built_in
);
3759 /* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
3763 expand_omp_regimplify_p (tree
*tp
, int *walk_subtrees
, void *)
3767 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
3768 if (TREE_CODE (t
) == VAR_DECL
&& DECL_HAS_VALUE_EXPR_P (t
))
3771 if (TREE_CODE (t
) == ADDR_EXPR
)
3772 recompute_tree_invariant_for_addr_expr (t
);
3774 *walk_subtrees
= !TYPE_P (t
) && !DECL_P (t
);
3778 /* Prepend TO = FROM assignment before *GSI_P. */
3781 expand_omp_build_assign (gimple_stmt_iterator
*gsi_p
, tree to
, tree from
)
3783 bool simple_p
= DECL_P (to
) && TREE_ADDRESSABLE (to
);
3784 from
= force_gimple_operand_gsi (gsi_p
, from
, simple_p
, NULL_TREE
,
3785 true, GSI_SAME_STMT
);
3786 gimple stmt
= gimple_build_assign (to
, from
);
3787 gsi_insert_before (gsi_p
, stmt
, GSI_SAME_STMT
);
3788 if (walk_tree (&from
, expand_omp_regimplify_p
, NULL
, NULL
)
3789 || walk_tree (&to
, expand_omp_regimplify_p
, NULL
, NULL
))
3791 gimple_stmt_iterator gsi
= gsi_for_stmt (stmt
);
3792 gimple_regimplify_operands (stmt
, &gsi
);
3796 /* Expand the OpenMP parallel or task directive starting at REGION. */
3799 expand_omp_taskreg (struct omp_region
*region
)
3801 basic_block entry_bb
, exit_bb
, new_bb
;
3802 struct function
*child_cfun
;
3803 tree child_fn
, block
, t
;
3804 gimple_stmt_iterator gsi
;
3805 gimple entry_stmt
, stmt
;
3807 vec
<tree
, va_gc
> *ws_args
;
3809 entry_stmt
= last_stmt (region
->entry
);
3810 child_fn
= gimple_omp_taskreg_child_fn (entry_stmt
);
3811 child_cfun
= DECL_STRUCT_FUNCTION (child_fn
);
3813 entry_bb
= region
->entry
;
3814 exit_bb
= region
->exit
;
3816 if (is_combined_parallel (region
))
3817 ws_args
= region
->ws_args
;
3821 if (child_cfun
->cfg
)
3823 /* Due to inlining, it may happen that we have already outlined
3824 the region, in which case all we need to do is make the
3825 sub-graph unreachable and emit the parallel call. */
3826 edge entry_succ_e
, exit_succ_e
;
3827 gimple_stmt_iterator gsi
;
3829 entry_succ_e
= single_succ_edge (entry_bb
);
3831 gsi
= gsi_last_bb (entry_bb
);
3832 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_PARALLEL
3833 || gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_TASK
);
3834 gsi_remove (&gsi
, true);
3839 exit_succ_e
= single_succ_edge (exit_bb
);
3840 make_edge (new_bb
, exit_succ_e
->dest
, EDGE_FALLTHRU
);
3842 remove_edge_and_dominated_blocks (entry_succ_e
);
3846 unsigned srcidx
, dstidx
, num
;
3848 /* If the parallel region needs data sent from the parent
3849 function, then the very first statement (except possible
3850 tree profile counter updates) of the parallel body
3851 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
3852 &.OMP_DATA_O is passed as an argument to the child function,
3853 we need to replace it with the argument as seen by the child
3856 In most cases, this will end up being the identity assignment
3857 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
3858 a function call that has been inlined, the original PARM_DECL
3859 .OMP_DATA_I may have been converted into a different local
3860 variable. In which case, we need to keep the assignment. */
3861 if (gimple_omp_taskreg_data_arg (entry_stmt
))
3863 basic_block entry_succ_bb
= single_succ (entry_bb
);
3864 gimple_stmt_iterator gsi
;
3866 gimple parcopy_stmt
= NULL
;
3868 for (gsi
= gsi_start_bb (entry_succ_bb
); ; gsi_next (&gsi
))
3872 gcc_assert (!gsi_end_p (gsi
));
3873 stmt
= gsi_stmt (gsi
);
3874 if (gimple_code (stmt
) != GIMPLE_ASSIGN
)
3877 if (gimple_num_ops (stmt
) == 2)
3879 tree arg
= gimple_assign_rhs1 (stmt
);
3881 /* We're ignore the subcode because we're
3882 effectively doing a STRIP_NOPS. */
3884 if (TREE_CODE (arg
) == ADDR_EXPR
3885 && TREE_OPERAND (arg
, 0)
3886 == gimple_omp_taskreg_data_arg (entry_stmt
))
3888 parcopy_stmt
= stmt
;
3894 gcc_assert (parcopy_stmt
!= NULL
);
3895 arg
= DECL_ARGUMENTS (child_fn
);
3897 if (!gimple_in_ssa_p (cfun
))
3899 if (gimple_assign_lhs (parcopy_stmt
) == arg
)
3900 gsi_remove (&gsi
, true);
3903 /* ?? Is setting the subcode really necessary ?? */
3904 gimple_omp_set_subcode (parcopy_stmt
, TREE_CODE (arg
));
3905 gimple_assign_set_rhs1 (parcopy_stmt
, arg
);
3910 /* If we are in ssa form, we must load the value from the default
3911 definition of the argument. That should not be defined now,
3912 since the argument is not used uninitialized. */
3913 gcc_assert (ssa_default_def (cfun
, arg
) == NULL
);
3914 narg
= make_ssa_name (arg
, gimple_build_nop ());
3915 set_ssa_default_def (cfun
, arg
, narg
);
3916 /* ?? Is setting the subcode really necessary ?? */
3917 gimple_omp_set_subcode (parcopy_stmt
, TREE_CODE (narg
));
3918 gimple_assign_set_rhs1 (parcopy_stmt
, narg
);
3919 update_stmt (parcopy_stmt
);
3923 /* Declare local variables needed in CHILD_CFUN. */
3924 block
= DECL_INITIAL (child_fn
);
3925 BLOCK_VARS (block
) = vec2chain (child_cfun
->local_decls
);
3926 /* The gimplifier could record temporaries in parallel/task block
3927 rather than in containing function's local_decls chain,
3928 which would mean cgraph missed finalizing them. Do it now. */
3929 for (t
= BLOCK_VARS (block
); t
; t
= DECL_CHAIN (t
))
3930 if (TREE_CODE (t
) == VAR_DECL
3932 && !DECL_EXTERNAL (t
))
3933 varpool_finalize_decl (t
);
3934 DECL_SAVED_TREE (child_fn
) = NULL
;
3935 /* We'll create a CFG for child_fn, so no gimple body is needed. */
3936 gimple_set_body (child_fn
, NULL
);
3937 TREE_USED (block
) = 1;
3939 /* Reset DECL_CONTEXT on function arguments. */
3940 for (t
= DECL_ARGUMENTS (child_fn
); t
; t
= DECL_CHAIN (t
))
3941 DECL_CONTEXT (t
) = child_fn
;
3943 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
3944 so that it can be moved to the child function. */
3945 gsi
= gsi_last_bb (entry_bb
);
3946 stmt
= gsi_stmt (gsi
);
3947 gcc_assert (stmt
&& (gimple_code (stmt
) == GIMPLE_OMP_PARALLEL
3948 || gimple_code (stmt
) == GIMPLE_OMP_TASK
));
3949 gsi_remove (&gsi
, true);
3950 e
= split_block (entry_bb
, stmt
);
3952 single_succ_edge (entry_bb
)->flags
= EDGE_FALLTHRU
;
3954 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
3957 gsi
= gsi_last_bb (exit_bb
);
3958 gcc_assert (!gsi_end_p (gsi
)
3959 && gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_RETURN
);
3960 stmt
= gimple_build_return (NULL
);
3961 gsi_insert_after (&gsi
, stmt
, GSI_SAME_STMT
);
3962 gsi_remove (&gsi
, true);
3965 /* Move the parallel region into CHILD_CFUN. */
3967 if (gimple_in_ssa_p (cfun
))
3969 init_tree_ssa (child_cfun
);
3970 init_ssa_operands (child_cfun
);
3971 child_cfun
->gimple_df
->in_ssa_p
= true;
3975 block
= gimple_block (entry_stmt
);
3977 new_bb
= move_sese_region_to_fn (child_cfun
, entry_bb
, exit_bb
, block
);
3979 single_succ_edge (new_bb
)->flags
= EDGE_FALLTHRU
;
3980 /* When the OMP expansion process cannot guarantee an up-to-date
3981 loop tree arrange for the child function to fixup loops. */
3982 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP
))
3983 child_cfun
->x_current_loops
->state
|= LOOPS_NEED_FIXUP
;
3985 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
3986 num
= vec_safe_length (child_cfun
->local_decls
);
3987 for (srcidx
= 0, dstidx
= 0; srcidx
< num
; srcidx
++)
3989 t
= (*child_cfun
->local_decls
)[srcidx
];
3990 if (DECL_CONTEXT (t
) == cfun
->decl
)
3992 if (srcidx
!= dstidx
)
3993 (*child_cfun
->local_decls
)[dstidx
] = t
;
3997 vec_safe_truncate (child_cfun
->local_decls
, dstidx
);
3999 /* Inform the callgraph about the new function. */
4000 DECL_STRUCT_FUNCTION (child_fn
)->curr_properties
= cfun
->curr_properties
;
4001 cgraph_add_new_function (child_fn
, true);
4003 /* Fix the callgraph edges for child_cfun. Those for cfun will be
4004 fixed in a following pass. */
4005 push_cfun (child_cfun
);
4007 optimize_omp_library_calls (entry_stmt
);
4008 rebuild_cgraph_edges ();
4010 /* Some EH regions might become dead, see PR34608. If
4011 pass_cleanup_cfg isn't the first pass to happen with the
4012 new child, these dead EH edges might cause problems.
4013 Clean them up now. */
4014 if (flag_exceptions
)
4017 bool changed
= false;
4020 changed
|= gimple_purge_dead_eh_edges (bb
);
4022 cleanup_tree_cfg ();
4024 if (gimple_in_ssa_p (cfun
))
4025 update_ssa (TODO_update_ssa
);
4029 /* Emit a library call to launch the children threads. */
4030 if (gimple_code (entry_stmt
) == GIMPLE_OMP_PARALLEL
)
4031 expand_parallel_call (region
, new_bb
, entry_stmt
, ws_args
);
4033 expand_task_call (new_bb
, entry_stmt
);
4034 if (gimple_in_ssa_p (cfun
))
4035 update_ssa (TODO_update_ssa_only_virtuals
);
4039 /* Helper function for expand_omp_{for_*,simd}. If this is the outermost
4040 of the combined collapse > 1 loop constructs, generate code like:
4041 if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
4046 count3 = (adj + N32 - N31) / STEP3;
4047 if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
4052 count2 = (adj + N22 - N21) / STEP2;
4053 if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
4058 count1 = (adj + N12 - N11) / STEP1;
4059 count = count1 * count2 * count3;
4060 Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
4062 and set ZERO_ITER_BB to that bb. */
4064 /* NOTE: It *could* be better to moosh all of the BBs together,
4065 creating one larger BB with all the computation and the unexpected
4066 jump at the end. I.e.
4068 bool zero3, zero2, zero1, zero;
4071 count3 = (N32 - N31) /[cl] STEP3;
4073 count2 = (N22 - N21) /[cl] STEP2;
4075 count1 = (N12 - N11) /[cl] STEP1;
4076 zero = zero3 || zero2 || zero1;
4077 count = count1 * count2 * count3;
4078 if (__builtin_expect(zero, false)) goto zero_iter_bb;
4080 After all, we expect the zero=false, and thus we expect to have to
4081 evaluate all of the comparison expressions, so short-circuiting
4082 oughtn't be a win. Since the condition isn't protecting a
4083 denominator, we're not concerned about divide-by-zero, so we can
4084 fully evaluate count even if a numerator turned out to be wrong.
4086 It seems like putting this all together would create much better
4087 scheduling opportunities, and less pressure on the chip's branch
4091 expand_omp_for_init_counts (struct omp_for_data
*fd
, gimple_stmt_iterator
*gsi
,
4092 basic_block
&entry_bb
, tree
*counts
,
4093 basic_block
&zero_iter_bb
, int &first_zero_iter
,
4094 basic_block
&l2_dom_bb
)
4096 tree t
, type
= TREE_TYPE (fd
->loop
.v
);
4101 /* Collapsed loops need work for expansion into SSA form. */
4102 gcc_assert (!gimple_in_ssa_p (cfun
));
4104 for (i
= 0; i
< fd
->collapse
; i
++)
4106 tree itype
= TREE_TYPE (fd
->loops
[i
].v
);
4108 if (SSA_VAR_P (fd
->loop
.n2
)
4109 && ((t
= fold_binary (fd
->loops
[i
].cond_code
, boolean_type_node
,
4110 fold_convert (itype
, fd
->loops
[i
].n1
),
4111 fold_convert (itype
, fd
->loops
[i
].n2
)))
4112 == NULL_TREE
|| !integer_onep (t
)))
4115 n1
= fold_convert (itype
, unshare_expr (fd
->loops
[i
].n1
));
4116 n1
= force_gimple_operand_gsi (gsi
, n1
, true, NULL_TREE
,
4117 true, GSI_SAME_STMT
);
4118 n2
= fold_convert (itype
, unshare_expr (fd
->loops
[i
].n2
));
4119 n2
= force_gimple_operand_gsi (gsi
, n2
, true, NULL_TREE
,
4120 true, GSI_SAME_STMT
);
4121 stmt
= gimple_build_cond (fd
->loops
[i
].cond_code
, n1
, n2
,
4122 NULL_TREE
, NULL_TREE
);
4123 gsi_insert_before (gsi
, stmt
, GSI_SAME_STMT
);
4124 if (walk_tree (gimple_cond_lhs_ptr (stmt
),
4125 expand_omp_regimplify_p
, NULL
, NULL
)
4126 || walk_tree (gimple_cond_rhs_ptr (stmt
),
4127 expand_omp_regimplify_p
, NULL
, NULL
))
4129 *gsi
= gsi_for_stmt (stmt
);
4130 gimple_regimplify_operands (stmt
, gsi
);
4132 e
= split_block (entry_bb
, stmt
);
4133 if (zero_iter_bb
== NULL
)
4135 first_zero_iter
= i
;
4136 zero_iter_bb
= create_empty_bb (entry_bb
);
4138 add_bb_to_loop (zero_iter_bb
, entry_bb
->loop_father
);
4139 *gsi
= gsi_after_labels (zero_iter_bb
);
4140 stmt
= gimple_build_assign (fd
->loop
.n2
,
4141 build_zero_cst (type
));
4142 gsi_insert_before (gsi
, stmt
, GSI_SAME_STMT
);
4143 set_immediate_dominator (CDI_DOMINATORS
, zero_iter_bb
,
4146 ne
= make_edge (entry_bb
, zero_iter_bb
, EDGE_FALSE_VALUE
);
4147 ne
->probability
= REG_BR_PROB_BASE
/ 2000 - 1;
4148 e
->flags
= EDGE_TRUE_VALUE
;
4149 e
->probability
= REG_BR_PROB_BASE
- ne
->probability
;
4150 if (l2_dom_bb
== NULL
)
4151 l2_dom_bb
= entry_bb
;
4153 *gsi
= gsi_last_bb (entry_bb
);
4156 if (POINTER_TYPE_P (itype
))
4157 itype
= signed_type_for (itype
);
4158 t
= build_int_cst (itype
, (fd
->loops
[i
].cond_code
== LT_EXPR
4160 t
= fold_build2 (PLUS_EXPR
, itype
,
4161 fold_convert (itype
, fd
->loops
[i
].step
), t
);
4162 t
= fold_build2 (PLUS_EXPR
, itype
, t
,
4163 fold_convert (itype
, fd
->loops
[i
].n2
));
4164 t
= fold_build2 (MINUS_EXPR
, itype
, t
,
4165 fold_convert (itype
, fd
->loops
[i
].n1
));
4166 /* ?? We could probably use CEIL_DIV_EXPR instead of
4167 TRUNC_DIV_EXPR and adjusting by hand. Unless we can't
4168 generate the same code in the end because generically we
4169 don't know that the values involved must be negative for
4171 if (TYPE_UNSIGNED (itype
) && fd
->loops
[i
].cond_code
== GT_EXPR
)
4172 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
,
4173 fold_build1 (NEGATE_EXPR
, itype
, t
),
4174 fold_build1 (NEGATE_EXPR
, itype
,
4175 fold_convert (itype
,
4176 fd
->loops
[i
].step
)));
4178 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
, t
,
4179 fold_convert (itype
, fd
->loops
[i
].step
));
4180 t
= fold_convert (type
, t
);
4181 if (TREE_CODE (t
) == INTEGER_CST
)
4185 counts
[i
] = create_tmp_reg (type
, ".count");
4186 expand_omp_build_assign (gsi
, counts
[i
], t
);
4188 if (SSA_VAR_P (fd
->loop
.n2
))
4193 t
= fold_build2 (MULT_EXPR
, type
, fd
->loop
.n2
, counts
[i
]);
4194 expand_omp_build_assign (gsi
, fd
->loop
.n2
, t
);
4200 /* Helper function for expand_omp_{for_*,simd}. Generate code like:
4202 V3 = N31 + (T % count3) * STEP3;
4204 V2 = N21 + (T % count2) * STEP2;
4206 V1 = N11 + T * STEP1;
4207 if this loop doesn't have an inner loop construct combined with it. */
4210 expand_omp_for_init_vars (struct omp_for_data
*fd
, gimple_stmt_iterator
*gsi
,
4211 tree
*counts
, tree startvar
)
4214 tree type
= TREE_TYPE (fd
->loop
.v
);
4215 tree tem
= create_tmp_reg (type
, ".tem");
4216 gimple stmt
= gimple_build_assign (tem
, startvar
);
4217 gsi_insert_after (gsi
, stmt
, GSI_CONTINUE_LINKING
);
4219 for (i
= fd
->collapse
- 1; i
>= 0; i
--)
4221 tree vtype
= TREE_TYPE (fd
->loops
[i
].v
), itype
, t
;
4223 if (POINTER_TYPE_P (vtype
))
4224 itype
= signed_type_for (vtype
);
4226 t
= fold_build2 (TRUNC_MOD_EXPR
, type
, tem
, counts
[i
]);
4229 t
= fold_convert (itype
, t
);
4230 t
= fold_build2 (MULT_EXPR
, itype
, t
,
4231 fold_convert (itype
, fd
->loops
[i
].step
));
4232 if (POINTER_TYPE_P (vtype
))
4233 t
= fold_build_pointer_plus (fd
->loops
[i
].n1
, t
);
4235 t
= fold_build2 (PLUS_EXPR
, itype
, fd
->loops
[i
].n1
, t
);
4236 t
= force_gimple_operand_gsi (gsi
, t
,
4237 DECL_P (fd
->loops
[i
].v
)
4238 && TREE_ADDRESSABLE (fd
->loops
[i
].v
),
4240 GSI_CONTINUE_LINKING
);
4241 stmt
= gimple_build_assign (fd
->loops
[i
].v
, t
);
4242 gsi_insert_after (gsi
, stmt
, GSI_CONTINUE_LINKING
);
4245 t
= fold_build2 (TRUNC_DIV_EXPR
, type
, tem
, counts
[i
]);
4246 t
= force_gimple_operand_gsi (gsi
, t
, false, NULL_TREE
,
4247 false, GSI_CONTINUE_LINKING
);
4248 stmt
= gimple_build_assign (tem
, t
);
4249 gsi_insert_after (gsi
, stmt
, GSI_CONTINUE_LINKING
);
4255 /* Helper function for expand_omp_for_*. Generate code like:
4258 if (V3 cond3 N32) goto BODY_BB; else goto L11;
4262 if (V2 cond2 N22) goto BODY_BB; else goto L12;
4269 extract_omp_for_update_vars (struct omp_for_data
*fd
, basic_block cont_bb
,
4270 basic_block body_bb
)
4272 basic_block last_bb
, bb
, collapse_bb
= NULL
;
4274 gimple_stmt_iterator gsi
;
4280 for (i
= fd
->collapse
- 1; i
>= 0; i
--)
4282 tree vtype
= TREE_TYPE (fd
->loops
[i
].v
);
4284 bb
= create_empty_bb (last_bb
);
4286 add_bb_to_loop (bb
, last_bb
->loop_father
);
4287 gsi
= gsi_start_bb (bb
);
4289 if (i
< fd
->collapse
- 1)
4291 e
= make_edge (last_bb
, bb
, EDGE_FALSE_VALUE
);
4292 e
->probability
= REG_BR_PROB_BASE
/ 8;
4294 t
= fd
->loops
[i
+ 1].n1
;
4295 t
= force_gimple_operand_gsi (&gsi
, t
,
4296 DECL_P (fd
->loops
[i
+ 1].v
)
4297 && TREE_ADDRESSABLE (fd
->loops
[i
4300 GSI_CONTINUE_LINKING
);
4301 stmt
= gimple_build_assign (fd
->loops
[i
+ 1].v
, t
);
4302 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
4307 set_immediate_dominator (CDI_DOMINATORS
, bb
, last_bb
);
4309 if (POINTER_TYPE_P (vtype
))
4310 t
= fold_build_pointer_plus (fd
->loops
[i
].v
, fd
->loops
[i
].step
);
4312 t
= fold_build2 (PLUS_EXPR
, vtype
, fd
->loops
[i
].v
, fd
->loops
[i
].step
);
4313 t
= force_gimple_operand_gsi (&gsi
, t
,
4314 DECL_P (fd
->loops
[i
].v
)
4315 && TREE_ADDRESSABLE (fd
->loops
[i
].v
),
4316 NULL_TREE
, false, GSI_CONTINUE_LINKING
);
4317 stmt
= gimple_build_assign (fd
->loops
[i
].v
, t
);
4318 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
4322 t
= fd
->loops
[i
].n2
;
4323 t
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
4324 false, GSI_CONTINUE_LINKING
);
4325 tree v
= fd
->loops
[i
].v
;
4326 if (DECL_P (v
) && TREE_ADDRESSABLE (v
))
4327 v
= force_gimple_operand_gsi (&gsi
, v
, true, NULL_TREE
,
4328 false, GSI_CONTINUE_LINKING
);
4329 t
= fold_build2 (fd
->loops
[i
].cond_code
, boolean_type_node
, v
, t
);
4330 stmt
= gimple_build_cond_empty (t
);
4331 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
4332 e
= make_edge (bb
, body_bb
, EDGE_TRUE_VALUE
);
4333 e
->probability
= REG_BR_PROB_BASE
* 7 / 8;
4336 make_edge (bb
, body_bb
, EDGE_FALLTHRU
);
4344 /* A subroutine of expand_omp_for. Generate code for a parallel
4345 loop with any schedule. Given parameters:
4347 for (V = N1; V cond N2; V += STEP) BODY;
4349 where COND is "<" or ">", we generate pseudocode
4351 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
4352 if (more) goto L0; else goto L3;
4359 if (V cond iend) goto L1; else goto L2;
4361 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
4364 If this is a combined omp parallel loop, instead of the call to
4365 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
4367 For collapsed loops, given parameters:
4369 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
4370 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
4371 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
4374 we generate pseudocode
4376 if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
4381 count3 = (adj + N32 - N31) / STEP3;
4382 if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
4387 count2 = (adj + N22 - N21) / STEP2;
4388 if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
4393 count1 = (adj + N12 - N11) / STEP1;
4394 count = count1 * count2 * count3;
4399 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
4400 if (more) goto L0; else goto L3;
4404 V3 = N31 + (T % count3) * STEP3;
4406 V2 = N21 + (T % count2) * STEP2;
4408 V1 = N11 + T * STEP1;
4413 if (V < iend) goto L10; else goto L2;
4416 if (V3 cond3 N32) goto L1; else goto L11;
4420 if (V2 cond2 N22) goto L1; else goto L12;
4426 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
4432 expand_omp_for_generic (struct omp_region
*region
,
4433 struct omp_for_data
*fd
,
4434 enum built_in_function start_fn
,
4435 enum built_in_function next_fn
)
4437 tree type
, istart0
, iend0
, iend
;
4438 tree t
, vmain
, vback
, bias
= NULL_TREE
;
4439 basic_block entry_bb
, cont_bb
, exit_bb
, l0_bb
, l1_bb
, collapse_bb
;
4440 basic_block l2_bb
= NULL
, l3_bb
= NULL
;
4441 gimple_stmt_iterator gsi
;
4443 bool in_combined_parallel
= is_combined_parallel (region
);
4444 bool broken_loop
= region
->cont
== NULL
;
4446 tree
*counts
= NULL
;
4449 gcc_assert (!broken_loop
|| !in_combined_parallel
);
4450 gcc_assert (fd
->iter_type
== long_integer_type_node
4451 || !in_combined_parallel
);
4453 type
= TREE_TYPE (fd
->loop
.v
);
4454 istart0
= create_tmp_var (fd
->iter_type
, ".istart0");
4455 iend0
= create_tmp_var (fd
->iter_type
, ".iend0");
4456 TREE_ADDRESSABLE (istart0
) = 1;
4457 TREE_ADDRESSABLE (iend0
) = 1;
4459 /* See if we need to bias by LLONG_MIN. */
4460 if (fd
->iter_type
== long_long_unsigned_type_node
4461 && TREE_CODE (type
) == INTEGER_TYPE
4462 && !TYPE_UNSIGNED (type
))
4466 if (fd
->loop
.cond_code
== LT_EXPR
)
4469 n2
= fold_build2 (PLUS_EXPR
, type
, fd
->loop
.n2
, fd
->loop
.step
);
4473 n1
= fold_build2 (MINUS_EXPR
, type
, fd
->loop
.n2
, fd
->loop
.step
);
4476 if (TREE_CODE (n1
) != INTEGER_CST
4477 || TREE_CODE (n2
) != INTEGER_CST
4478 || ((tree_int_cst_sgn (n1
) < 0) ^ (tree_int_cst_sgn (n2
) < 0)))
4479 bias
= fold_convert (fd
->iter_type
, TYPE_MIN_VALUE (type
));
4482 entry_bb
= region
->entry
;
4483 cont_bb
= region
->cont
;
4485 gcc_assert (EDGE_COUNT (entry_bb
->succs
) == 2);
4486 gcc_assert (broken_loop
4487 || BRANCH_EDGE (entry_bb
)->dest
== FALLTHRU_EDGE (cont_bb
)->dest
);
4488 l0_bb
= split_edge (FALLTHRU_EDGE (entry_bb
));
4489 l1_bb
= single_succ (l0_bb
);
4492 l2_bb
= create_empty_bb (cont_bb
);
4493 gcc_assert (BRANCH_EDGE (cont_bb
)->dest
== l1_bb
);
4494 gcc_assert (EDGE_COUNT (cont_bb
->succs
) == 2);
4498 l3_bb
= BRANCH_EDGE (entry_bb
)->dest
;
4499 exit_bb
= region
->exit
;
4501 gsi
= gsi_last_bb (entry_bb
);
4503 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
4504 if (fd
->collapse
> 1)
4506 int first_zero_iter
= -1;
4507 basic_block zero_iter_bb
= NULL
, l2_dom_bb
= NULL
;
4509 counts
= XALLOCAVEC (tree
, fd
->collapse
);
4510 expand_omp_for_init_counts (fd
, &gsi
, entry_bb
, counts
,
4511 zero_iter_bb
, first_zero_iter
,
4516 /* Some counts[i] vars might be uninitialized if
4517 some loop has zero iterations. But the body shouldn't
4518 be executed in that case, so just avoid uninit warnings. */
4519 for (i
= first_zero_iter
; i
< fd
->collapse
; i
++)
4520 if (SSA_VAR_P (counts
[i
]))
4521 TREE_NO_WARNING (counts
[i
]) = 1;
4523 e
= split_block (entry_bb
, gsi_stmt (gsi
));
4525 make_edge (zero_iter_bb
, entry_bb
, EDGE_FALLTHRU
);
4526 gsi
= gsi_last_bb (entry_bb
);
4527 set_immediate_dominator (CDI_DOMINATORS
, entry_bb
,
4528 get_immediate_dominator (CDI_DOMINATORS
,
4532 if (in_combined_parallel
)
4534 /* In a combined parallel loop, emit a call to
4535 GOMP_loop_foo_next. */
4536 t
= build_call_expr (builtin_decl_explicit (next_fn
), 2,
4537 build_fold_addr_expr (istart0
),
4538 build_fold_addr_expr (iend0
));
4542 tree t0
, t1
, t2
, t3
, t4
;
4543 /* If this is not a combined parallel loop, emit a call to
4544 GOMP_loop_foo_start in ENTRY_BB. */
4545 t4
= build_fold_addr_expr (iend0
);
4546 t3
= build_fold_addr_expr (istart0
);
4547 t2
= fold_convert (fd
->iter_type
, fd
->loop
.step
);
4550 if (POINTER_TYPE_P (TREE_TYPE (t0
))
4551 && TYPE_PRECISION (TREE_TYPE (t0
))
4552 != TYPE_PRECISION (fd
->iter_type
))
4554 /* Avoid casting pointers to integer of a different size. */
4555 tree itype
= signed_type_for (type
);
4556 t1
= fold_convert (fd
->iter_type
, fold_convert (itype
, t1
));
4557 t0
= fold_convert (fd
->iter_type
, fold_convert (itype
, t0
));
4561 t1
= fold_convert (fd
->iter_type
, t1
);
4562 t0
= fold_convert (fd
->iter_type
, t0
);
4566 t1
= fold_build2 (PLUS_EXPR
, fd
->iter_type
, t1
, bias
);
4567 t0
= fold_build2 (PLUS_EXPR
, fd
->iter_type
, t0
, bias
);
4569 if (fd
->iter_type
== long_integer_type_node
)
4573 t
= fold_convert (fd
->iter_type
, fd
->chunk_size
);
4574 t
= build_call_expr (builtin_decl_explicit (start_fn
),
4575 6, t0
, t1
, t2
, t
, t3
, t4
);
4578 t
= build_call_expr (builtin_decl_explicit (start_fn
),
4579 5, t0
, t1
, t2
, t3
, t4
);
4587 /* The GOMP_loop_ull_*start functions have additional boolean
4588 argument, true for < loops and false for > loops.
4589 In Fortran, the C bool type can be different from
4590 boolean_type_node. */
4591 bfn_decl
= builtin_decl_explicit (start_fn
);
4592 c_bool_type
= TREE_TYPE (TREE_TYPE (bfn_decl
));
4593 t5
= build_int_cst (c_bool_type
,
4594 fd
->loop
.cond_code
== LT_EXPR
? 1 : 0);
4597 tree bfn_decl
= builtin_decl_explicit (start_fn
);
4598 t
= fold_convert (fd
->iter_type
, fd
->chunk_size
);
4599 t
= build_call_expr (bfn_decl
, 7, t5
, t0
, t1
, t2
, t
, t3
, t4
);
4602 t
= build_call_expr (builtin_decl_explicit (start_fn
),
4603 6, t5
, t0
, t1
, t2
, t3
, t4
);
4606 if (TREE_TYPE (t
) != boolean_type_node
)
4607 t
= fold_build2 (NE_EXPR
, boolean_type_node
,
4608 t
, build_int_cst (TREE_TYPE (t
), 0));
4609 t
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
4610 true, GSI_SAME_STMT
);
4611 gsi_insert_after (&gsi
, gimple_build_cond_empty (t
), GSI_SAME_STMT
);
4613 /* Remove the GIMPLE_OMP_FOR statement. */
4614 gsi_remove (&gsi
, true);
4616 /* Iteration setup for sequential loop goes in L0_BB. */
4617 tree startvar
= fd
->loop
.v
;
4618 tree endvar
= NULL_TREE
;
4620 gsi
= gsi_start_bb (l0_bb
);
4623 t
= fold_build2 (MINUS_EXPR
, fd
->iter_type
, t
, bias
);
4624 if (POINTER_TYPE_P (TREE_TYPE (startvar
)))
4625 t
= fold_convert (signed_type_for (TREE_TYPE (startvar
)), t
);
4626 t
= fold_convert (TREE_TYPE (startvar
), t
);
4627 t
= force_gimple_operand_gsi (&gsi
, t
,
4629 && TREE_ADDRESSABLE (startvar
),
4630 NULL_TREE
, false, GSI_CONTINUE_LINKING
);
4631 stmt
= gimple_build_assign (startvar
, t
);
4632 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
4636 t
= fold_build2 (MINUS_EXPR
, fd
->iter_type
, t
, bias
);
4637 if (POINTER_TYPE_P (TREE_TYPE (startvar
)))
4638 t
= fold_convert (signed_type_for (TREE_TYPE (startvar
)), t
);
4639 t
= fold_convert (TREE_TYPE (startvar
), t
);
4640 iend
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
4641 false, GSI_CONTINUE_LINKING
);
4644 stmt
= gimple_build_assign (endvar
, iend
);
4645 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
4647 if (fd
->collapse
> 1)
4648 expand_omp_for_init_vars (fd
, &gsi
, counts
, startvar
);
4652 /* Code to control the increment and predicate for the sequential
4653 loop goes in the CONT_BB. */
4654 gsi
= gsi_last_bb (cont_bb
);
4655 stmt
= gsi_stmt (gsi
);
4656 gcc_assert (gimple_code (stmt
) == GIMPLE_OMP_CONTINUE
);
4657 vmain
= gimple_omp_continue_control_use (stmt
);
4658 vback
= gimple_omp_continue_control_def (stmt
);
4660 /* OMP4 placeholder: if (!gimple_omp_for_combined_p (fd->for_stmt)). */
4663 if (POINTER_TYPE_P (type
))
4664 t
= fold_build_pointer_plus (vmain
, fd
->loop
.step
);
4666 t
= fold_build2 (PLUS_EXPR
, type
, vmain
, fd
->loop
.step
);
4667 t
= force_gimple_operand_gsi (&gsi
, t
,
4669 && TREE_ADDRESSABLE (vback
),
4670 NULL_TREE
, true, GSI_SAME_STMT
);
4671 stmt
= gimple_build_assign (vback
, t
);
4672 gsi_insert_before (&gsi
, stmt
, GSI_SAME_STMT
);
4674 t
= build2 (fd
->loop
.cond_code
, boolean_type_node
,
4675 DECL_P (vback
) && TREE_ADDRESSABLE (vback
) ? t
: vback
,
4677 stmt
= gimple_build_cond_empty (t
);
4678 gsi_insert_before (&gsi
, stmt
, GSI_SAME_STMT
);
4681 /* Remove GIMPLE_OMP_CONTINUE. */
4682 gsi_remove (&gsi
, true);
4684 if (fd
->collapse
> 1)
4685 collapse_bb
= extract_omp_for_update_vars (fd
, cont_bb
, l1_bb
);
4687 /* Emit code to get the next parallel iteration in L2_BB. */
4688 gsi
= gsi_start_bb (l2_bb
);
4690 t
= build_call_expr (builtin_decl_explicit (next_fn
), 2,
4691 build_fold_addr_expr (istart0
),
4692 build_fold_addr_expr (iend0
));
4693 t
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
4694 false, GSI_CONTINUE_LINKING
);
4695 if (TREE_TYPE (t
) != boolean_type_node
)
4696 t
= fold_build2 (NE_EXPR
, boolean_type_node
,
4697 t
, build_int_cst (TREE_TYPE (t
), 0));
4698 stmt
= gimple_build_cond_empty (t
);
4699 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
4702 /* Add the loop cleanup function. */
4703 gsi
= gsi_last_bb (exit_bb
);
4704 if (gimple_omp_return_nowait_p (gsi_stmt (gsi
)))
4705 t
= builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT
);
4707 t
= builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END
);
4708 stmt
= gimple_build_call (t
, 0);
4709 gsi_insert_after (&gsi
, stmt
, GSI_SAME_STMT
);
4710 gsi_remove (&gsi
, true);
4712 /* Connect the new blocks. */
4713 find_edge (entry_bb
, l0_bb
)->flags
= EDGE_TRUE_VALUE
;
4714 find_edge (entry_bb
, l3_bb
)->flags
= EDGE_FALSE_VALUE
;
4720 e
= find_edge (cont_bb
, l3_bb
);
4721 ne
= make_edge (l2_bb
, l3_bb
, EDGE_FALSE_VALUE
);
4723 phis
= phi_nodes (l3_bb
);
4724 for (gsi
= gsi_start (phis
); !gsi_end_p (gsi
); gsi_next (&gsi
))
4726 gimple phi
= gsi_stmt (gsi
);
4727 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi
, ne
),
4728 PHI_ARG_DEF_FROM_EDGE (phi
, e
));
4732 make_edge (cont_bb
, l2_bb
, EDGE_FALSE_VALUE
);
4734 add_bb_to_loop (l2_bb
, cont_bb
->loop_father
);
4735 e
= find_edge (cont_bb
, l1_bb
);
4736 /* OMP4 placeholder for gimple_omp_for_combined_p (fd->for_stmt). */
4739 else if (fd
->collapse
> 1)
4742 e
= make_edge (cont_bb
, collapse_bb
, EDGE_TRUE_VALUE
);
4745 e
->flags
= EDGE_TRUE_VALUE
;
4748 e
->probability
= REG_BR_PROB_BASE
* 7 / 8;
4749 find_edge (cont_bb
, l2_bb
)->probability
= REG_BR_PROB_BASE
/ 8;
4753 e
= find_edge (cont_bb
, l2_bb
);
4754 e
->flags
= EDGE_FALLTHRU
;
4756 make_edge (l2_bb
, l0_bb
, EDGE_TRUE_VALUE
);
4758 set_immediate_dominator (CDI_DOMINATORS
, l2_bb
,
4759 recompute_dominator (CDI_DOMINATORS
, l2_bb
));
4760 set_immediate_dominator (CDI_DOMINATORS
, l3_bb
,
4761 recompute_dominator (CDI_DOMINATORS
, l3_bb
));
4762 set_immediate_dominator (CDI_DOMINATORS
, l0_bb
,
4763 recompute_dominator (CDI_DOMINATORS
, l0_bb
));
4764 set_immediate_dominator (CDI_DOMINATORS
, l1_bb
,
4765 recompute_dominator (CDI_DOMINATORS
, l1_bb
));
4767 struct loop
*outer_loop
= alloc_loop ();
4768 outer_loop
->header
= l0_bb
;
4769 outer_loop
->latch
= l2_bb
;
4770 add_loop (outer_loop
, l0_bb
->loop_father
);
4772 /* OMP4 placeholder: if (!gimple_omp_for_combined_p (fd->for_stmt)). */
4775 struct loop
*loop
= alloc_loop ();
4776 loop
->header
= l1_bb
;
4777 /* The loop may have multiple latches. */
4778 add_loop (loop
, outer_loop
);
4784 /* A subroutine of expand_omp_for. Generate code for a parallel
4785 loop with static schedule and no specified chunk size. Given
4788 for (V = N1; V cond N2; V += STEP) BODY;
4790 where COND is "<" or ">", we generate pseudocode
4792 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
4797 if ((__typeof (V)) -1 > 0 && cond is >)
4798 n = -(adj + N2 - N1) / -STEP;
4800 n = (adj + N2 - N1) / STEP;
4803 if (threadid < tt) goto L3; else goto L4;
4808 s0 = q * threadid + tt;
4811 if (s0 >= e0) goto L2; else goto L0;
4817 if (V cond e) goto L1;
4822 expand_omp_for_static_nochunk (struct omp_region
*region
,
4823 struct omp_for_data
*fd
)
4825 tree n
, q
, s0
, e0
, e
, t
, tt
, nthreads
, threadid
;
4826 tree type
, itype
, vmain
, vback
;
4827 basic_block entry_bb
, second_bb
, third_bb
, exit_bb
, seq_start_bb
;
4828 basic_block body_bb
, cont_bb
;
4830 gimple_stmt_iterator gsi
;
4834 itype
= type
= TREE_TYPE (fd
->loop
.v
);
4835 if (POINTER_TYPE_P (type
))
4836 itype
= signed_type_for (type
);
4838 entry_bb
= region
->entry
;
4839 cont_bb
= region
->cont
;
4840 gcc_assert (EDGE_COUNT (entry_bb
->succs
) == 2);
4841 gcc_assert (BRANCH_EDGE (entry_bb
)->dest
== FALLTHRU_EDGE (cont_bb
)->dest
);
4842 seq_start_bb
= split_edge (FALLTHRU_EDGE (entry_bb
));
4843 body_bb
= single_succ (seq_start_bb
);
4844 gcc_assert (BRANCH_EDGE (cont_bb
)->dest
== body_bb
);
4845 gcc_assert (EDGE_COUNT (cont_bb
->succs
) == 2);
4846 fin_bb
= FALLTHRU_EDGE (cont_bb
)->dest
;
4847 exit_bb
= region
->exit
;
4849 /* Iteration space partitioning goes in ENTRY_BB. */
4850 gsi
= gsi_last_bb (entry_bb
);
4851 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
4853 t
= fold_binary (fd
->loop
.cond_code
, boolean_type_node
,
4854 fold_convert (type
, fd
->loop
.n1
),
4855 fold_convert (type
, fd
->loop
.n2
));
4856 if (TYPE_UNSIGNED (type
)
4857 && (t
== NULL_TREE
|| !integer_onep (t
)))
4860 n1
= fold_convert (type
, unshare_expr (fd
->loop
.n1
));
4861 n1
= force_gimple_operand_gsi (&gsi
, n1
, true, NULL_TREE
,
4862 true, GSI_SAME_STMT
);
4863 n2
= fold_convert (type
, unshare_expr (fd
->loop
.n2
));
4864 n2
= force_gimple_operand_gsi (&gsi
, n2
, true, NULL_TREE
,
4865 true, GSI_SAME_STMT
);
4866 stmt
= gimple_build_cond (fd
->loop
.cond_code
, n1
, n2
,
4867 NULL_TREE
, NULL_TREE
);
4868 gsi_insert_before (&gsi
, stmt
, GSI_SAME_STMT
);
4869 if (walk_tree (gimple_cond_lhs_ptr (stmt
),
4870 expand_omp_regimplify_p
, NULL
, NULL
)
4871 || walk_tree (gimple_cond_rhs_ptr (stmt
),
4872 expand_omp_regimplify_p
, NULL
, NULL
))
4874 gsi
= gsi_for_stmt (stmt
);
4875 gimple_regimplify_operands (stmt
, &gsi
);
4877 ep
= split_block (entry_bb
, stmt
);
4878 ep
->flags
= EDGE_TRUE_VALUE
;
4879 entry_bb
= ep
->dest
;
4880 ep
->probability
= REG_BR_PROB_BASE
- (REG_BR_PROB_BASE
/ 2000 - 1);
4881 ep
= make_edge (ep
->src
, fin_bb
, EDGE_FALSE_VALUE
);
4882 ep
->probability
= REG_BR_PROB_BASE
/ 2000 - 1;
4883 if (gimple_in_ssa_p (cfun
))
4885 int dest_idx
= find_edge (entry_bb
, fin_bb
)->dest_idx
;
4886 for (gsi
= gsi_start_phis (fin_bb
);
4887 !gsi_end_p (gsi
); gsi_next (&gsi
))
4889 gimple phi
= gsi_stmt (gsi
);
4890 add_phi_arg (phi
, gimple_phi_arg_def (phi
, dest_idx
),
4891 ep
, UNKNOWN_LOCATION
);
4894 gsi
= gsi_last_bb (entry_bb
);
4897 t
= build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS
), 0);
4898 t
= fold_convert (itype
, t
);
4899 nthreads
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
4900 true, GSI_SAME_STMT
);
4902 t
= build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM
), 0);
4903 t
= fold_convert (itype
, t
);
4904 threadid
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
4905 true, GSI_SAME_STMT
);
4908 = force_gimple_operand_gsi (&gsi
, fold_convert (type
, fd
->loop
.n1
),
4909 true, NULL_TREE
, true, GSI_SAME_STMT
);
4911 = force_gimple_operand_gsi (&gsi
, fold_convert (itype
, fd
->loop
.n2
),
4912 true, NULL_TREE
, true, GSI_SAME_STMT
);
4914 = force_gimple_operand_gsi (&gsi
, fold_convert (itype
, fd
->loop
.step
),
4915 true, NULL_TREE
, true, GSI_SAME_STMT
);
4917 t
= build_int_cst (itype
, (fd
->loop
.cond_code
== LT_EXPR
? -1 : 1));
4918 t
= fold_build2 (PLUS_EXPR
, itype
, fd
->loop
.step
, t
);
4919 t
= fold_build2 (PLUS_EXPR
, itype
, t
, fd
->loop
.n2
);
4920 t
= fold_build2 (MINUS_EXPR
, itype
, t
, fold_convert (itype
, fd
->loop
.n1
));
4921 if (TYPE_UNSIGNED (itype
) && fd
->loop
.cond_code
== GT_EXPR
)
4922 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
,
4923 fold_build1 (NEGATE_EXPR
, itype
, t
),
4924 fold_build1 (NEGATE_EXPR
, itype
, fd
->loop
.step
));
4926 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
, t
, fd
->loop
.step
);
4927 t
= fold_convert (itype
, t
);
4928 n
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
, true, GSI_SAME_STMT
);
4930 q
= create_tmp_reg (itype
, "q");
4931 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
, n
, nthreads
);
4932 t
= force_gimple_operand_gsi (&gsi
, t
, false, NULL_TREE
, true, GSI_SAME_STMT
);
4933 gsi_insert_before (&gsi
, gimple_build_assign (q
, t
), GSI_SAME_STMT
);
4935 tt
= create_tmp_reg (itype
, "tt");
4936 t
= fold_build2 (TRUNC_MOD_EXPR
, itype
, n
, nthreads
);
4937 t
= force_gimple_operand_gsi (&gsi
, t
, false, NULL_TREE
, true, GSI_SAME_STMT
);
4938 gsi_insert_before (&gsi
, gimple_build_assign (tt
, t
), GSI_SAME_STMT
);
4940 t
= build2 (LT_EXPR
, boolean_type_node
, threadid
, tt
);
4941 stmt
= gimple_build_cond_empty (t
);
4942 gsi_insert_before (&gsi
, stmt
, GSI_SAME_STMT
);
4944 second_bb
= split_block (entry_bb
, stmt
)->dest
;
4945 gsi
= gsi_last_bb (second_bb
);
4946 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
4948 gsi_insert_before (&gsi
, gimple_build_assign (tt
, build_int_cst (itype
, 0)),
4950 stmt
= gimple_build_assign_with_ops (PLUS_EXPR
, q
, q
,
4951 build_int_cst (itype
, 1));
4952 gsi_insert_before (&gsi
, stmt
, GSI_SAME_STMT
);
4954 third_bb
= split_block (second_bb
, stmt
)->dest
;
4955 gsi
= gsi_last_bb (third_bb
);
4956 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
4958 t
= build2 (MULT_EXPR
, itype
, q
, threadid
);
4959 t
= build2 (PLUS_EXPR
, itype
, t
, tt
);
4960 s0
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
, true, GSI_SAME_STMT
);
4962 t
= fold_build2 (PLUS_EXPR
, itype
, s0
, q
);
4963 e0
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
, true, GSI_SAME_STMT
);
4965 t
= build2 (GE_EXPR
, boolean_type_node
, s0
, e0
);
4966 gsi_insert_before (&gsi
, gimple_build_cond_empty (t
), GSI_SAME_STMT
);
4968 /* Remove the GIMPLE_OMP_FOR statement. */
4969 gsi_remove (&gsi
, true);
4971 /* Setup code for sequential iteration goes in SEQ_START_BB. */
4972 gsi
= gsi_start_bb (seq_start_bb
);
4974 t
= fold_convert (itype
, s0
);
4975 t
= fold_build2 (MULT_EXPR
, itype
, t
, fd
->loop
.step
);
4976 if (POINTER_TYPE_P (type
))
4977 t
= fold_build_pointer_plus (fd
->loop
.n1
, t
);
4979 t
= fold_build2 (PLUS_EXPR
, type
, t
, fd
->loop
.n1
);
4980 t
= force_gimple_operand_gsi (&gsi
, t
,
4982 && TREE_ADDRESSABLE (fd
->loop
.v
),
4983 NULL_TREE
, false, GSI_CONTINUE_LINKING
);
4984 stmt
= gimple_build_assign (fd
->loop
.v
, t
);
4985 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
4987 t
= fold_convert (itype
, e0
);
4988 t
= fold_build2 (MULT_EXPR
, itype
, t
, fd
->loop
.step
);
4989 if (POINTER_TYPE_P (type
))
4990 t
= fold_build_pointer_plus (fd
->loop
.n1
, t
);
4992 t
= fold_build2 (PLUS_EXPR
, type
, t
, fd
->loop
.n1
);
4993 e
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
4994 false, GSI_CONTINUE_LINKING
);
4996 /* The code controlling the sequential loop replaces the
4997 GIMPLE_OMP_CONTINUE. */
4998 gsi
= gsi_last_bb (cont_bb
);
4999 stmt
= gsi_stmt (gsi
);
5000 gcc_assert (gimple_code (stmt
) == GIMPLE_OMP_CONTINUE
);
5001 vmain
= gimple_omp_continue_control_use (stmt
);
5002 vback
= gimple_omp_continue_control_def (stmt
);
5004 if (POINTER_TYPE_P (type
))
5005 t
= fold_build_pointer_plus (vmain
, fd
->loop
.step
);
5007 t
= fold_build2 (PLUS_EXPR
, type
, vmain
, fd
->loop
.step
);
5008 t
= force_gimple_operand_gsi (&gsi
, t
,
5009 DECL_P (vback
) && TREE_ADDRESSABLE (vback
),
5010 NULL_TREE
, true, GSI_SAME_STMT
);
5011 stmt
= gimple_build_assign (vback
, t
);
5012 gsi_insert_before (&gsi
, stmt
, GSI_SAME_STMT
);
5014 t
= build2 (fd
->loop
.cond_code
, boolean_type_node
,
5015 DECL_P (vback
) && TREE_ADDRESSABLE (vback
) ? t
: vback
, e
);
5016 gsi_insert_before (&gsi
, gimple_build_cond_empty (t
), GSI_SAME_STMT
);
5018 /* Remove the GIMPLE_OMP_CONTINUE statement. */
5019 gsi_remove (&gsi
, true);
5021 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
5022 gsi
= gsi_last_bb (exit_bb
);
5023 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi
)))
5024 force_gimple_operand_gsi (&gsi
, build_omp_barrier (), false, NULL_TREE
,
5025 false, GSI_SAME_STMT
);
5026 gsi_remove (&gsi
, true);
5028 /* Connect all the blocks. */
5029 ep
= make_edge (entry_bb
, third_bb
, EDGE_FALSE_VALUE
);
5030 ep
->probability
= REG_BR_PROB_BASE
/ 4 * 3;
5031 ep
= find_edge (entry_bb
, second_bb
);
5032 ep
->flags
= EDGE_TRUE_VALUE
;
5033 ep
->probability
= REG_BR_PROB_BASE
/ 4;
5034 find_edge (third_bb
, seq_start_bb
)->flags
= EDGE_FALSE_VALUE
;
5035 find_edge (third_bb
, fin_bb
)->flags
= EDGE_TRUE_VALUE
;
5037 find_edge (cont_bb
, body_bb
)->flags
= EDGE_TRUE_VALUE
;
5038 find_edge (cont_bb
, fin_bb
)->flags
= EDGE_FALSE_VALUE
;
5040 set_immediate_dominator (CDI_DOMINATORS
, second_bb
, entry_bb
);
5041 set_immediate_dominator (CDI_DOMINATORS
, third_bb
, entry_bb
);
5042 set_immediate_dominator (CDI_DOMINATORS
, seq_start_bb
, third_bb
);
5043 set_immediate_dominator (CDI_DOMINATORS
, body_bb
,
5044 recompute_dominator (CDI_DOMINATORS
, body_bb
));
5045 set_immediate_dominator (CDI_DOMINATORS
, fin_bb
,
5046 recompute_dominator (CDI_DOMINATORS
, fin_bb
));
5048 struct loop
*loop
= alloc_loop ();
5049 loop
->header
= body_bb
;
5050 loop
->latch
= cont_bb
;
5051 add_loop (loop
, body_bb
->loop_father
);
5055 /* A subroutine of expand_omp_for. Generate code for a parallel
5056 loop with static schedule and a specified chunk size. Given
5059 for (V = N1; V cond N2; V += STEP) BODY;
5061 where COND is "<" or ">", we generate pseudocode
5063 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
5068 if ((__typeof (V)) -1 > 0 && cond is >)
5069 n = -(adj + N2 - N1) / -STEP;
5071 n = (adj + N2 - N1) / STEP;
5073 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
5074 here so that V is defined
5075 if the loop is not entered
5077 s0 = (trip * nthreads + threadid) * CHUNK;
5078 e0 = min(s0 + CHUNK, n);
5079 if (s0 < n) goto L1; else goto L4;
5086 if (V cond e) goto L2; else goto L3;
5094 expand_omp_for_static_chunk (struct omp_region
*region
, struct omp_for_data
*fd
)
5096 tree n
, s0
, e0
, e
, t
;
5097 tree trip_var
, trip_init
, trip_main
, trip_back
, nthreads
, threadid
;
5098 tree type
, itype
, v_main
, v_back
, v_extra
;
5099 basic_block entry_bb
, exit_bb
, body_bb
, seq_start_bb
, iter_part_bb
;
5100 basic_block trip_update_bb
, cont_bb
, fin_bb
;
5101 gimple_stmt_iterator si
;
5105 itype
= type
= TREE_TYPE (fd
->loop
.v
);
5106 if (POINTER_TYPE_P (type
))
5107 itype
= signed_type_for (type
);
5109 entry_bb
= region
->entry
;
5110 se
= split_block (entry_bb
, last_stmt (entry_bb
));
5112 iter_part_bb
= se
->dest
;
5113 cont_bb
= region
->cont
;
5114 gcc_assert (EDGE_COUNT (iter_part_bb
->succs
) == 2);
5115 gcc_assert (BRANCH_EDGE (iter_part_bb
)->dest
5116 == FALLTHRU_EDGE (cont_bb
)->dest
);
5117 seq_start_bb
= split_edge (FALLTHRU_EDGE (iter_part_bb
));
5118 body_bb
= single_succ (seq_start_bb
);
5119 gcc_assert (BRANCH_EDGE (cont_bb
)->dest
== body_bb
);
5120 gcc_assert (EDGE_COUNT (cont_bb
->succs
) == 2);
5121 fin_bb
= FALLTHRU_EDGE (cont_bb
)->dest
;
5122 trip_update_bb
= split_edge (FALLTHRU_EDGE (cont_bb
));
5123 exit_bb
= region
->exit
;
5125 /* Trip and adjustment setup goes in ENTRY_BB. */
5126 si
= gsi_last_bb (entry_bb
);
5127 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_FOR
);
5129 t
= fold_binary (fd
->loop
.cond_code
, boolean_type_node
,
5130 fold_convert (type
, fd
->loop
.n1
),
5131 fold_convert (type
, fd
->loop
.n2
));
5132 if (TYPE_UNSIGNED (type
)
5133 && (t
== NULL_TREE
|| !integer_onep (t
)))
5136 n1
= fold_convert (type
, unshare_expr (fd
->loop
.n1
));
5137 n1
= force_gimple_operand_gsi (&si
, n1
, true, NULL_TREE
,
5138 true, GSI_SAME_STMT
);
5139 n2
= fold_convert (type
, unshare_expr (fd
->loop
.n2
));
5140 n2
= force_gimple_operand_gsi (&si
, n2
, true, NULL_TREE
,
5141 true, GSI_SAME_STMT
);
5142 stmt
= gimple_build_cond (fd
->loop
.cond_code
, n1
, n2
,
5143 NULL_TREE
, NULL_TREE
);
5144 gsi_insert_before (&si
, stmt
, GSI_SAME_STMT
);
5145 if (walk_tree (gimple_cond_lhs_ptr (stmt
),
5146 expand_omp_regimplify_p
, NULL
, NULL
)
5147 || walk_tree (gimple_cond_rhs_ptr (stmt
),
5148 expand_omp_regimplify_p
, NULL
, NULL
))
5150 si
= gsi_for_stmt (stmt
);
5151 gimple_regimplify_operands (stmt
, &si
);
5153 se
= split_block (entry_bb
, stmt
);
5154 se
->flags
= EDGE_TRUE_VALUE
;
5155 entry_bb
= se
->dest
;
5156 se
->probability
= REG_BR_PROB_BASE
- (REG_BR_PROB_BASE
/ 2000 - 1);
5157 se
= make_edge (se
->src
, fin_bb
, EDGE_FALSE_VALUE
);
5158 se
->probability
= REG_BR_PROB_BASE
/ 2000 - 1;
5159 if (gimple_in_ssa_p (cfun
))
5161 int dest_idx
= find_edge (entry_bb
, fin_bb
)->dest_idx
;
5162 for (si
= gsi_start_phis (fin_bb
);
5163 !gsi_end_p (si
); gsi_next (&si
))
5165 gimple phi
= gsi_stmt (si
);
5166 add_phi_arg (phi
, gimple_phi_arg_def (phi
, dest_idx
),
5167 se
, UNKNOWN_LOCATION
);
5170 si
= gsi_last_bb (entry_bb
);
5173 t
= build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS
), 0);
5174 t
= fold_convert (itype
, t
);
5175 nthreads
= force_gimple_operand_gsi (&si
, t
, true, NULL_TREE
,
5176 true, GSI_SAME_STMT
);
5178 t
= build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM
), 0);
5179 t
= fold_convert (itype
, t
);
5180 threadid
= force_gimple_operand_gsi (&si
, t
, true, NULL_TREE
,
5181 true, GSI_SAME_STMT
);
5184 = force_gimple_operand_gsi (&si
, fold_convert (type
, fd
->loop
.n1
),
5185 true, NULL_TREE
, true, GSI_SAME_STMT
);
5187 = force_gimple_operand_gsi (&si
, fold_convert (itype
, fd
->loop
.n2
),
5188 true, NULL_TREE
, true, GSI_SAME_STMT
);
5190 = force_gimple_operand_gsi (&si
, fold_convert (itype
, fd
->loop
.step
),
5191 true, NULL_TREE
, true, GSI_SAME_STMT
);
5193 = force_gimple_operand_gsi (&si
, fold_convert (itype
, fd
->chunk_size
),
5194 true, NULL_TREE
, true, GSI_SAME_STMT
);
5196 t
= build_int_cst (itype
, (fd
->loop
.cond_code
== LT_EXPR
? -1 : 1));
5197 t
= fold_build2 (PLUS_EXPR
, itype
, fd
->loop
.step
, t
);
5198 t
= fold_build2 (PLUS_EXPR
, itype
, t
, fd
->loop
.n2
);
5199 t
= fold_build2 (MINUS_EXPR
, itype
, t
, fold_convert (itype
, fd
->loop
.n1
));
5200 if (TYPE_UNSIGNED (itype
) && fd
->loop
.cond_code
== GT_EXPR
)
5201 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
,
5202 fold_build1 (NEGATE_EXPR
, itype
, t
),
5203 fold_build1 (NEGATE_EXPR
, itype
, fd
->loop
.step
));
5205 t
= fold_build2 (TRUNC_DIV_EXPR
, itype
, t
, fd
->loop
.step
);
5206 t
= fold_convert (itype
, t
);
5207 n
= force_gimple_operand_gsi (&si
, t
, true, NULL_TREE
,
5208 true, GSI_SAME_STMT
);
5210 trip_var
= create_tmp_reg (itype
, ".trip");
5211 if (gimple_in_ssa_p (cfun
))
5213 trip_init
= make_ssa_name (trip_var
, NULL
);
5214 trip_main
= make_ssa_name (trip_var
, NULL
);
5215 trip_back
= make_ssa_name (trip_var
, NULL
);
5219 trip_init
= trip_var
;
5220 trip_main
= trip_var
;
5221 trip_back
= trip_var
;
5224 stmt
= gimple_build_assign (trip_init
, build_int_cst (itype
, 0));
5225 gsi_insert_before (&si
, stmt
, GSI_SAME_STMT
);
5227 t
= fold_build2 (MULT_EXPR
, itype
, threadid
, fd
->chunk_size
);
5228 t
= fold_build2 (MULT_EXPR
, itype
, t
, fd
->loop
.step
);
5229 if (POINTER_TYPE_P (type
))
5230 t
= fold_build_pointer_plus (fd
->loop
.n1
, t
);
5232 t
= fold_build2 (PLUS_EXPR
, type
, t
, fd
->loop
.n1
);
5233 v_extra
= force_gimple_operand_gsi (&si
, t
, true, NULL_TREE
,
5234 true, GSI_SAME_STMT
);
5236 /* Remove the GIMPLE_OMP_FOR. */
5237 gsi_remove (&si
, true);
5239 /* Iteration space partitioning goes in ITER_PART_BB. */
5240 si
= gsi_last_bb (iter_part_bb
);
5242 t
= fold_build2 (MULT_EXPR
, itype
, trip_main
, nthreads
);
5243 t
= fold_build2 (PLUS_EXPR
, itype
, t
, threadid
);
5244 t
= fold_build2 (MULT_EXPR
, itype
, t
, fd
->chunk_size
);
5245 s0
= force_gimple_operand_gsi (&si
, t
, true, NULL_TREE
,
5246 false, GSI_CONTINUE_LINKING
);
5248 t
= fold_build2 (PLUS_EXPR
, itype
, s0
, fd
->chunk_size
);
5249 t
= fold_build2 (MIN_EXPR
, itype
, t
, n
);
5250 e0
= force_gimple_operand_gsi (&si
, t
, true, NULL_TREE
,
5251 false, GSI_CONTINUE_LINKING
);
5253 t
= build2 (LT_EXPR
, boolean_type_node
, s0
, n
);
5254 gsi_insert_after (&si
, gimple_build_cond_empty (t
), GSI_CONTINUE_LINKING
);
5256 /* Setup code for sequential iteration goes in SEQ_START_BB. */
5257 si
= gsi_start_bb (seq_start_bb
);
5259 t
= fold_convert (itype
, s0
);
5260 t
= fold_build2 (MULT_EXPR
, itype
, t
, fd
->loop
.step
);
5261 if (POINTER_TYPE_P (type
))
5262 t
= fold_build_pointer_plus (fd
->loop
.n1
, t
);
5264 t
= fold_build2 (PLUS_EXPR
, type
, t
, fd
->loop
.n1
);
5265 t
= force_gimple_operand_gsi (&si
, t
,
5267 && TREE_ADDRESSABLE (fd
->loop
.v
),
5268 NULL_TREE
, false, GSI_CONTINUE_LINKING
);
5269 stmt
= gimple_build_assign (fd
->loop
.v
, t
);
5270 gsi_insert_after (&si
, stmt
, GSI_CONTINUE_LINKING
);
5272 t
= fold_convert (itype
, e0
);
5273 t
= fold_build2 (MULT_EXPR
, itype
, t
, fd
->loop
.step
);
5274 if (POINTER_TYPE_P (type
))
5275 t
= fold_build_pointer_plus (fd
->loop
.n1
, t
);
5277 t
= fold_build2 (PLUS_EXPR
, type
, t
, fd
->loop
.n1
);
5278 e
= force_gimple_operand_gsi (&si
, t
, true, NULL_TREE
,
5279 false, GSI_CONTINUE_LINKING
);
5281 /* The code controlling the sequential loop goes in CONT_BB,
5282 replacing the GIMPLE_OMP_CONTINUE. */
5283 si
= gsi_last_bb (cont_bb
);
5284 stmt
= gsi_stmt (si
);
5285 gcc_assert (gimple_code (stmt
) == GIMPLE_OMP_CONTINUE
);
5286 v_main
= gimple_omp_continue_control_use (stmt
);
5287 v_back
= gimple_omp_continue_control_def (stmt
);
5289 if (POINTER_TYPE_P (type
))
5290 t
= fold_build_pointer_plus (v_main
, fd
->loop
.step
);
5292 t
= fold_build2 (PLUS_EXPR
, type
, v_main
, fd
->loop
.step
);
5293 if (DECL_P (v_back
) && TREE_ADDRESSABLE (v_back
))
5294 t
= force_gimple_operand_gsi (&si
, t
, true, NULL_TREE
,
5295 true, GSI_SAME_STMT
);
5296 stmt
= gimple_build_assign (v_back
, t
);
5297 gsi_insert_before (&si
, stmt
, GSI_SAME_STMT
);
5299 t
= build2 (fd
->loop
.cond_code
, boolean_type_node
,
5300 DECL_P (v_back
) && TREE_ADDRESSABLE (v_back
)
5302 gsi_insert_before (&si
, gimple_build_cond_empty (t
), GSI_SAME_STMT
);
5304 /* Remove GIMPLE_OMP_CONTINUE. */
5305 gsi_remove (&si
, true);
5307 /* Trip update code goes into TRIP_UPDATE_BB. */
5308 si
= gsi_start_bb (trip_update_bb
);
5310 t
= build_int_cst (itype
, 1);
5311 t
= build2 (PLUS_EXPR
, itype
, trip_main
, t
);
5312 stmt
= gimple_build_assign (trip_back
, t
);
5313 gsi_insert_after (&si
, stmt
, GSI_CONTINUE_LINKING
);
5315 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
5316 si
= gsi_last_bb (exit_bb
);
5317 if (!gimple_omp_return_nowait_p (gsi_stmt (si
)))
5318 force_gimple_operand_gsi (&si
, build_omp_barrier (), false, NULL_TREE
,
5319 false, GSI_SAME_STMT
);
5320 gsi_remove (&si
, true);
5322 /* Connect the new blocks. */
5323 find_edge (iter_part_bb
, seq_start_bb
)->flags
= EDGE_TRUE_VALUE
;
5324 find_edge (iter_part_bb
, fin_bb
)->flags
= EDGE_FALSE_VALUE
;
5326 find_edge (cont_bb
, body_bb
)->flags
= EDGE_TRUE_VALUE
;
5327 find_edge (cont_bb
, trip_update_bb
)->flags
= EDGE_FALSE_VALUE
;
5329 redirect_edge_and_branch (single_succ_edge (trip_update_bb
), iter_part_bb
);
5331 if (gimple_in_ssa_p (cfun
))
5333 gimple_stmt_iterator psi
;
5336 edge_var_map_vector
*head
;
5340 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
5341 remove arguments of the phi nodes in fin_bb. We need to create
5342 appropriate phi nodes in iter_part_bb instead. */
5343 se
= single_pred_edge (fin_bb
);
5344 re
= single_succ_edge (trip_update_bb
);
5345 head
= redirect_edge_var_map_vector (re
);
5346 ene
= single_succ_edge (entry_bb
);
5348 psi
= gsi_start_phis (fin_bb
);
5349 for (i
= 0; !gsi_end_p (psi
) && head
->iterate (i
, &vm
);
5350 gsi_next (&psi
), ++i
)
5353 source_location locus
;
5355 phi
= gsi_stmt (psi
);
5356 t
= gimple_phi_result (phi
);
5357 gcc_assert (t
== redirect_edge_var_map_result (vm
));
5358 nphi
= create_phi_node (t
, iter_part_bb
);
5360 t
= PHI_ARG_DEF_FROM_EDGE (phi
, se
);
5361 locus
= gimple_phi_arg_location_from_edge (phi
, se
);
5363 /* A special case -- fd->loop.v is not yet computed in
5364 iter_part_bb, we need to use v_extra instead. */
5365 if (t
== fd
->loop
.v
)
5367 add_phi_arg (nphi
, t
, ene
, locus
);
5368 locus
= redirect_edge_var_map_location (vm
);
5369 add_phi_arg (nphi
, redirect_edge_var_map_def (vm
), re
, locus
);
5371 gcc_assert (!gsi_end_p (psi
) && i
== head
->length ());
5372 redirect_edge_var_map_clear (re
);
5375 psi
= gsi_start_phis (fin_bb
);
5376 if (gsi_end_p (psi
))
5378 remove_phi_node (&psi
, false);
5381 /* Make phi node for trip. */
5382 phi
= create_phi_node (trip_main
, iter_part_bb
);
5383 add_phi_arg (phi
, trip_back
, single_succ_edge (trip_update_bb
),
5385 add_phi_arg (phi
, trip_init
, single_succ_edge (entry_bb
),
5389 set_immediate_dominator (CDI_DOMINATORS
, trip_update_bb
, cont_bb
);
5390 set_immediate_dominator (CDI_DOMINATORS
, iter_part_bb
,
5391 recompute_dominator (CDI_DOMINATORS
, iter_part_bb
));
5392 set_immediate_dominator (CDI_DOMINATORS
, fin_bb
,
5393 recompute_dominator (CDI_DOMINATORS
, fin_bb
));
5394 set_immediate_dominator (CDI_DOMINATORS
, seq_start_bb
,
5395 recompute_dominator (CDI_DOMINATORS
, seq_start_bb
));
5396 set_immediate_dominator (CDI_DOMINATORS
, body_bb
,
5397 recompute_dominator (CDI_DOMINATORS
, body_bb
));
5399 struct loop
*trip_loop
= alloc_loop ();
5400 trip_loop
->header
= iter_part_bb
;
5401 trip_loop
->latch
= trip_update_bb
;
5402 add_loop (trip_loop
, iter_part_bb
->loop_father
);
5404 struct loop
*loop
= alloc_loop ();
5405 loop
->header
= body_bb
;
5406 loop
->latch
= cont_bb
;
5407 add_loop (loop
, trip_loop
);
5410 /* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
5411 loop. Given parameters:
5413 for (V = N1; V cond N2; V += STEP) BODY;
5415 where COND is "<" or ">", we generate pseudocode
5423 if (V cond N2) goto L0; else goto L2;
5426 For collapsed loops, given parameters:
5428 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
5429 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
5430 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
5433 we generate pseudocode
5439 count3 = (adj + N32 - N31) / STEP3;
5444 count2 = (adj + N22 - N21) / STEP2;
5449 count1 = (adj + N12 - N11) / STEP1;
5450 count = count1 * count2 * count3;
5460 V2 += (V3 cond3 N32) ? 0 : STEP2;
5461 V3 = (V3 cond3 N32) ? V3 : N31;
5462 V1 += (V2 cond2 N22) ? 0 : STEP1;
5463 V2 = (V2 cond2 N22) ? V2 : N21;
5465 if (V < count) goto L0; else goto L2;
5471 expand_omp_simd (struct omp_region
*region
, struct omp_for_data
*fd
)
5474 basic_block entry_bb
, cont_bb
, exit_bb
, l0_bb
, l1_bb
, l2_bb
, l2_dom_bb
;
5475 gimple_stmt_iterator gsi
;
5477 bool broken_loop
= region
->cont
== NULL
;
5479 tree
*counts
= NULL
;
5481 tree safelen
= find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
5482 OMP_CLAUSE_SAFELEN
);
5483 tree simduid
= find_omp_clause (gimple_omp_for_clauses (fd
->for_stmt
),
5484 OMP_CLAUSE__SIMDUID_
);
5487 type
= TREE_TYPE (fd
->loop
.v
);
5488 entry_bb
= region
->entry
;
5489 cont_bb
= region
->cont
;
5490 gcc_assert (EDGE_COUNT (entry_bb
->succs
) == 2);
5491 gcc_assert (broken_loop
5492 || BRANCH_EDGE (entry_bb
)->dest
== FALLTHRU_EDGE (cont_bb
)->dest
);
5493 l0_bb
= FALLTHRU_EDGE (entry_bb
)->dest
;
5496 gcc_assert (BRANCH_EDGE (cont_bb
)->dest
== l0_bb
);
5497 gcc_assert (EDGE_COUNT (cont_bb
->succs
) == 2);
5498 l1_bb
= split_block (cont_bb
, last_stmt (cont_bb
))->dest
;
5499 l2_bb
= BRANCH_EDGE (entry_bb
)->dest
;
5503 BRANCH_EDGE (entry_bb
)->flags
&= ~EDGE_ABNORMAL
;
5504 l1_bb
= split_edge (BRANCH_EDGE (entry_bb
));
5505 l2_bb
= single_succ (l1_bb
);
5507 exit_bb
= region
->exit
;
5510 gsi
= gsi_last_bb (entry_bb
);
5512 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_FOR
);
5513 /* Not needed in SSA form right now. */
5514 gcc_assert (!gimple_in_ssa_p (cfun
));
5515 if (fd
->collapse
> 1)
5517 int first_zero_iter
= -1;
5518 basic_block zero_iter_bb
= l2_bb
;
5520 counts
= XALLOCAVEC (tree
, fd
->collapse
);
5521 expand_omp_for_init_counts (fd
, &gsi
, entry_bb
, counts
,
5522 zero_iter_bb
, first_zero_iter
,
5525 if (l2_dom_bb
== NULL
)
5530 /* Place holder for gimple_omp_for_combined_into_p() in
5531 the upcoming gomp-4_0-branch merge. */;
5534 expand_omp_build_assign (&gsi
, fd
->loop
.v
,
5535 fold_convert (type
, fd
->loop
.n1
));
5536 if (fd
->collapse
> 1)
5537 for (i
= 0; i
< fd
->collapse
; i
++)
5539 tree itype
= TREE_TYPE (fd
->loops
[i
].v
);
5540 if (POINTER_TYPE_P (itype
))
5541 itype
= signed_type_for (itype
);
5542 t
= fold_convert (TREE_TYPE (fd
->loops
[i
].v
), fd
->loops
[i
].n1
);
5543 expand_omp_build_assign (&gsi
, fd
->loops
[i
].v
, t
);
5547 /* Remove the GIMPLE_OMP_FOR statement. */
5548 gsi_remove (&gsi
, true);
5552 /* Code to control the increment goes in the CONT_BB. */
5553 gsi
= gsi_last_bb (cont_bb
);
5554 stmt
= gsi_stmt (gsi
);
5555 gcc_assert (gimple_code (stmt
) == GIMPLE_OMP_CONTINUE
);
5557 if (POINTER_TYPE_P (type
))
5558 t
= fold_build_pointer_plus (fd
->loop
.v
, fd
->loop
.step
);
5560 t
= fold_build2 (PLUS_EXPR
, type
, fd
->loop
.v
, fd
->loop
.step
);
5561 expand_omp_build_assign (&gsi
, fd
->loop
.v
, t
);
5563 if (fd
->collapse
> 1)
5565 i
= fd
->collapse
- 1;
5566 if (POINTER_TYPE_P (TREE_TYPE (fd
->loops
[i
].v
)))
5568 t
= fold_convert (sizetype
, fd
->loops
[i
].step
);
5569 t
= fold_build_pointer_plus (fd
->loops
[i
].v
, t
);
5573 t
= fold_convert (TREE_TYPE (fd
->loops
[i
].v
),
5575 t
= fold_build2 (PLUS_EXPR
, TREE_TYPE (fd
->loops
[i
].v
),
5578 expand_omp_build_assign (&gsi
, fd
->loops
[i
].v
, t
);
5580 for (i
= fd
->collapse
- 1; i
> 0; i
--)
5582 tree itype
= TREE_TYPE (fd
->loops
[i
].v
);
5583 tree itype2
= TREE_TYPE (fd
->loops
[i
- 1].v
);
5584 if (POINTER_TYPE_P (itype2
))
5585 itype2
= signed_type_for (itype2
);
5586 t
= build3 (COND_EXPR
, itype2
,
5587 build2 (fd
->loops
[i
].cond_code
, boolean_type_node
,
5589 fold_convert (itype
, fd
->loops
[i
].n2
)),
5590 build_int_cst (itype2
, 0),
5591 fold_convert (itype2
, fd
->loops
[i
- 1].step
));
5592 if (POINTER_TYPE_P (TREE_TYPE (fd
->loops
[i
- 1].v
)))
5593 t
= fold_build_pointer_plus (fd
->loops
[i
- 1].v
, t
);
5595 t
= fold_build2 (PLUS_EXPR
, itype2
, fd
->loops
[i
- 1].v
, t
);
5596 expand_omp_build_assign (&gsi
, fd
->loops
[i
- 1].v
, t
);
5598 t
= build3 (COND_EXPR
, itype
,
5599 build2 (fd
->loops
[i
].cond_code
, boolean_type_node
,
5601 fold_convert (itype
, fd
->loops
[i
].n2
)),
5603 fold_convert (itype
, fd
->loops
[i
].n1
));
5604 expand_omp_build_assign (&gsi
, fd
->loops
[i
].v
, t
);
5608 /* Remove GIMPLE_OMP_CONTINUE. */
5609 gsi_remove (&gsi
, true);
5612 /* Emit the condition in L1_BB. */
5613 gsi
= gsi_start_bb (l1_bb
);
5615 t
= fold_convert (type
, n2
);
5616 t
= force_gimple_operand_gsi (&gsi
, t
, true, NULL_TREE
,
5617 false, GSI_CONTINUE_LINKING
);
5618 t
= build2 (fd
->loop
.cond_code
, boolean_type_node
, fd
->loop
.v
, t
);
5619 stmt
= gimple_build_cond_empty (t
);
5620 gsi_insert_after (&gsi
, stmt
, GSI_CONTINUE_LINKING
);
5621 if (walk_tree (gimple_cond_lhs_ptr (stmt
), expand_omp_regimplify_p
,
5623 || walk_tree (gimple_cond_rhs_ptr (stmt
), expand_omp_regimplify_p
,
5626 gsi
= gsi_for_stmt (stmt
);
5627 gimple_regimplify_operands (stmt
, &gsi
);
5630 /* Remove GIMPLE_OMP_RETURN. */
5631 gsi
= gsi_last_bb (exit_bb
);
5632 gsi_remove (&gsi
, true);
5634 /* Connect the new blocks. */
5635 remove_edge (FALLTHRU_EDGE (entry_bb
));
5639 remove_edge (BRANCH_EDGE (entry_bb
));
5640 make_edge (entry_bb
, l1_bb
, EDGE_FALLTHRU
);
5642 e
= BRANCH_EDGE (l1_bb
);
5643 ne
= FALLTHRU_EDGE (l1_bb
);
5644 e
->flags
= EDGE_TRUE_VALUE
;
5648 single_succ_edge (entry_bb
)->flags
= EDGE_FALLTHRU
;
5650 ne
= single_succ_edge (l1_bb
);
5651 e
= make_edge (l1_bb
, l0_bb
, EDGE_TRUE_VALUE
);
5654 ne
->flags
= EDGE_FALSE_VALUE
;
5655 e
->probability
= REG_BR_PROB_BASE
* 7 / 8;
5656 ne
->probability
= REG_BR_PROB_BASE
/ 8;
5658 set_immediate_dominator (CDI_DOMINATORS
, l1_bb
, entry_bb
);
5659 set_immediate_dominator (CDI_DOMINATORS
, l2_bb
, l2_dom_bb
);
5660 set_immediate_dominator (CDI_DOMINATORS
, l0_bb
, l1_bb
);
5664 struct loop
*loop
= alloc_loop ();
5665 loop
->header
= l1_bb
;
5666 loop
->latch
= e
->dest
;
5667 add_loop (loop
, l1_bb
->loop_father
);
5668 if (safelen
== NULL_TREE
)
5669 loop
->safelen
= INT_MAX
;
5672 safelen
= OMP_CLAUSE_SAFELEN_EXPR (safelen
);
5673 if (!host_integerp (safelen
, 1)
5674 || (unsigned HOST_WIDE_INT
) tree_low_cst (safelen
, 1)
5676 loop
->safelen
= INT_MAX
;
5678 loop
->safelen
= tree_low_cst (safelen
, 1);
5679 if (loop
->safelen
== 1)
5684 loop
->simduid
= OMP_CLAUSE__SIMDUID__DECL (simduid
);
5685 cfun
->has_simduid_loops
= true;
5687 /* If not -fno-tree-vectorize, hint that we want to vectorize
5689 if ((flag_tree_vectorize
5690 || !global_options_set
.x_flag_tree_vectorize
)
5691 && loop
->safelen
> 1)
5693 loop
->force_vect
= true;
5694 cfun
->has_force_vect_loops
= true;
5700 /* Expand the OpenMP loop defined by REGION. */
5703 expand_omp_for (struct omp_region
*region
)
5705 struct omp_for_data fd
;
5706 struct omp_for_data_loop
*loops
;
5709 = (struct omp_for_data_loop
*)
5710 alloca (gimple_omp_for_collapse (last_stmt (region
->entry
))
5711 * sizeof (struct omp_for_data_loop
));
5712 extract_omp_for_data (last_stmt (region
->entry
), &fd
, loops
);
5713 region
->sched_kind
= fd
.sched_kind
;
5715 gcc_assert (EDGE_COUNT (region
->entry
->succs
) == 2);
5716 BRANCH_EDGE (region
->entry
)->flags
&= ~EDGE_ABNORMAL
;
5717 FALLTHRU_EDGE (region
->entry
)->flags
&= ~EDGE_ABNORMAL
;
5720 gcc_assert (EDGE_COUNT (region
->cont
->succs
) == 2);
5721 BRANCH_EDGE (region
->cont
)->flags
&= ~EDGE_ABNORMAL
;
5722 FALLTHRU_EDGE (region
->cont
)->flags
&= ~EDGE_ABNORMAL
;
5725 /* If there isn't a continue then this is a degerate case where
5726 the introduction of abnormal edges during lowering will prevent
5727 original loops from being detected. Fix that up. */
5728 loops_state_set (LOOPS_NEED_FIXUP
);
5730 if (gimple_omp_for_kind (fd
.for_stmt
) == GF_OMP_FOR_KIND_SIMD
)
5731 expand_omp_simd (region
, &fd
);
5732 else if (fd
.sched_kind
== OMP_CLAUSE_SCHEDULE_STATIC
5735 && region
->cont
!= NULL
)
5737 if (fd
.chunk_size
== NULL
)
5738 expand_omp_for_static_nochunk (region
, &fd
);
5740 expand_omp_for_static_chunk (region
, &fd
);
5744 int fn_index
, start_ix
, next_ix
;
5746 gcc_assert (gimple_omp_for_kind (fd
.for_stmt
)
5747 == GF_OMP_FOR_KIND_FOR
);
5748 if (fd
.chunk_size
== NULL
5749 && fd
.sched_kind
== OMP_CLAUSE_SCHEDULE_STATIC
)
5750 fd
.chunk_size
= integer_zero_node
;
5751 gcc_assert (fd
.sched_kind
!= OMP_CLAUSE_SCHEDULE_AUTO
);
5752 fn_index
= (fd
.sched_kind
== OMP_CLAUSE_SCHEDULE_RUNTIME
)
5753 ? 3 : fd
.sched_kind
;
5754 fn_index
+= fd
.have_ordered
* 4;
5755 start_ix
= ((int)BUILT_IN_GOMP_LOOP_STATIC_START
) + fn_index
;
5756 next_ix
= ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT
) + fn_index
;
5757 if (fd
.iter_type
== long_long_unsigned_type_node
)
5759 start_ix
+= ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
5760 - (int)BUILT_IN_GOMP_LOOP_STATIC_START
);
5761 next_ix
+= ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
5762 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT
);
5764 expand_omp_for_generic (region
, &fd
, (enum built_in_function
) start_ix
,
5765 (enum built_in_function
) next_ix
);
5768 if (gimple_in_ssa_p (cfun
))
5769 update_ssa (TODO_update_ssa_only_virtuals
);
5773 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
5775 v = GOMP_sections_start (n);
5792 v = GOMP_sections_next ();
5797 If this is a combined parallel sections, replace the call to
5798 GOMP_sections_start with call to GOMP_sections_next. */
5801 expand_omp_sections (struct omp_region
*region
)
5803 tree t
, u
, vin
= NULL
, vmain
, vnext
, l2
;
5804 vec
<tree
> label_vec
;
5806 basic_block entry_bb
, l0_bb
, l1_bb
, l2_bb
, default_bb
;
5807 gimple_stmt_iterator si
, switch_si
;
5808 gimple sections_stmt
, stmt
, cont
;
5811 struct omp_region
*inner
;
5813 bool exit_reachable
= region
->cont
!= NULL
;
5815 gcc_assert (region
->exit
!= NULL
);
5816 entry_bb
= region
->entry
;
5817 l0_bb
= single_succ (entry_bb
);
5818 l1_bb
= region
->cont
;
5819 l2_bb
= region
->exit
;
5820 if (single_pred_p (l2_bb
) && single_pred (l2_bb
) == l0_bb
)
5821 l2
= gimple_block_label (l2_bb
);
5824 /* This can happen if there are reductions. */
5825 len
= EDGE_COUNT (l0_bb
->succs
);
5826 gcc_assert (len
> 0);
5827 e
= EDGE_SUCC (l0_bb
, len
- 1);
5828 si
= gsi_last_bb (e
->dest
);
5831 || gimple_code (gsi_stmt (si
)) != GIMPLE_OMP_SECTION
)
5832 l2
= gimple_block_label (e
->dest
);
5834 FOR_EACH_EDGE (e
, ei
, l0_bb
->succs
)
5836 si
= gsi_last_bb (e
->dest
);
5838 || gimple_code (gsi_stmt (si
)) != GIMPLE_OMP_SECTION
)
5840 l2
= gimple_block_label (e
->dest
);
5846 default_bb
= create_empty_bb (l1_bb
->prev_bb
);
5848 default_bb
= create_empty_bb (l0_bb
);
5850 /* We will build a switch() with enough cases for all the
5851 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
5852 and a default case to abort if something goes wrong. */
5853 len
= EDGE_COUNT (l0_bb
->succs
);
5855 /* Use vec::quick_push on label_vec throughout, since we know the size
5857 label_vec
.create (len
);
5859 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
5860 GIMPLE_OMP_SECTIONS statement. */
5861 si
= gsi_last_bb (entry_bb
);
5862 sections_stmt
= gsi_stmt (si
);
5863 gcc_assert (gimple_code (sections_stmt
) == GIMPLE_OMP_SECTIONS
);
5864 vin
= gimple_omp_sections_control (sections_stmt
);
5865 if (!is_combined_parallel (region
))
5867 /* If we are not inside a combined parallel+sections region,
5868 call GOMP_sections_start. */
5869 t
= build_int_cst (unsigned_type_node
,
5870 exit_reachable
? len
- 1 : len
);
5871 u
= builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START
);
5872 stmt
= gimple_build_call (u
, 1, t
);
5876 /* Otherwise, call GOMP_sections_next. */
5877 u
= builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT
);
5878 stmt
= gimple_build_call (u
, 0);
5880 gimple_call_set_lhs (stmt
, vin
);
5881 gsi_insert_after (&si
, stmt
, GSI_SAME_STMT
);
5882 gsi_remove (&si
, true);
5884 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
5886 switch_si
= gsi_last_bb (l0_bb
);
5887 gcc_assert (gimple_code (gsi_stmt (switch_si
)) == GIMPLE_OMP_SECTIONS_SWITCH
);
5890 cont
= last_stmt (l1_bb
);
5891 gcc_assert (gimple_code (cont
) == GIMPLE_OMP_CONTINUE
);
5892 vmain
= gimple_omp_continue_control_use (cont
);
5893 vnext
= gimple_omp_continue_control_def (cont
);
5901 t
= build_case_label (build_int_cst (unsigned_type_node
, 0), NULL
, l2
);
5902 label_vec
.quick_push (t
);
5905 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
5906 for (inner
= region
->inner
, casei
= 1;
5908 inner
= inner
->next
, i
++, casei
++)
5910 basic_block s_entry_bb
, s_exit_bb
;
5912 /* Skip optional reduction region. */
5913 if (inner
->type
== GIMPLE_OMP_ATOMIC_LOAD
)
5920 s_entry_bb
= inner
->entry
;
5921 s_exit_bb
= inner
->exit
;
5923 t
= gimple_block_label (s_entry_bb
);
5924 u
= build_int_cst (unsigned_type_node
, casei
);
5925 u
= build_case_label (u
, NULL
, t
);
5926 label_vec
.quick_push (u
);
5928 si
= gsi_last_bb (s_entry_bb
);
5929 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_SECTION
);
5930 gcc_assert (i
< len
|| gimple_omp_section_last_p (gsi_stmt (si
)));
5931 gsi_remove (&si
, true);
5932 single_succ_edge (s_entry_bb
)->flags
= EDGE_FALLTHRU
;
5934 if (s_exit_bb
== NULL
)
5937 si
= gsi_last_bb (s_exit_bb
);
5938 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_RETURN
);
5939 gsi_remove (&si
, true);
5941 single_succ_edge (s_exit_bb
)->flags
= EDGE_FALLTHRU
;
5944 /* Error handling code goes in DEFAULT_BB. */
5945 t
= gimple_block_label (default_bb
);
5946 u
= build_case_label (NULL
, NULL
, t
);
5947 make_edge (l0_bb
, default_bb
, 0);
5949 add_bb_to_loop (default_bb
, current_loops
->tree_root
);
5951 stmt
= gimple_build_switch (vmain
, u
, label_vec
);
5952 gsi_insert_after (&switch_si
, stmt
, GSI_SAME_STMT
);
5953 gsi_remove (&switch_si
, true);
5954 label_vec
.release ();
5956 si
= gsi_start_bb (default_bb
);
5957 stmt
= gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP
), 0);
5958 gsi_insert_after (&si
, stmt
, GSI_CONTINUE_LINKING
);
5964 /* Code to get the next section goes in L1_BB. */
5965 si
= gsi_last_bb (l1_bb
);
5966 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_CONTINUE
);
5968 bfn_decl
= builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT
);
5969 stmt
= gimple_build_call (bfn_decl
, 0);
5970 gimple_call_set_lhs (stmt
, vnext
);
5971 gsi_insert_after (&si
, stmt
, GSI_SAME_STMT
);
5972 gsi_remove (&si
, true);
5974 single_succ_edge (l1_bb
)->flags
= EDGE_FALLTHRU
;
5977 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
5978 si
= gsi_last_bb (l2_bb
);
5979 if (gimple_omp_return_nowait_p (gsi_stmt (si
)))
5980 t
= builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT
);
5982 t
= builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END
);
5983 stmt
= gimple_build_call (t
, 0);
5984 gsi_insert_after (&si
, stmt
, GSI_SAME_STMT
);
5985 gsi_remove (&si
, true);
5987 set_immediate_dominator (CDI_DOMINATORS
, default_bb
, l0_bb
);
5991 /* Expand code for an OpenMP single directive. We've already expanded
5992 much of the code, here we simply place the GOMP_barrier call. */
5995 expand_omp_single (struct omp_region
*region
)
5997 basic_block entry_bb
, exit_bb
;
5998 gimple_stmt_iterator si
;
5999 bool need_barrier
= false;
6001 entry_bb
= region
->entry
;
6002 exit_bb
= region
->exit
;
6004 si
= gsi_last_bb (entry_bb
);
6005 /* The terminal barrier at the end of a GOMP_single_copy sequence cannot
6006 be removed. We need to ensure that the thread that entered the single
6007 does not exit before the data is copied out by the other threads. */
6008 if (find_omp_clause (gimple_omp_single_clauses (gsi_stmt (si
)),
6009 OMP_CLAUSE_COPYPRIVATE
))
6010 need_barrier
= true;
6011 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_SINGLE
);
6012 gsi_remove (&si
, true);
6013 single_succ_edge (entry_bb
)->flags
= EDGE_FALLTHRU
;
6015 si
= gsi_last_bb (exit_bb
);
6016 if (!gimple_omp_return_nowait_p (gsi_stmt (si
)) || need_barrier
)
6017 force_gimple_operand_gsi (&si
, build_omp_barrier (), false, NULL_TREE
,
6018 false, GSI_SAME_STMT
);
6019 gsi_remove (&si
, true);
6020 single_succ_edge (exit_bb
)->flags
= EDGE_FALLTHRU
;
6024 /* Generic expansion for OpenMP synchronization directives: master,
6025 ordered and critical. All we need to do here is remove the entry
6026 and exit markers for REGION. */
6029 expand_omp_synch (struct omp_region
*region
)
6031 basic_block entry_bb
, exit_bb
;
6032 gimple_stmt_iterator si
;
6034 entry_bb
= region
->entry
;
6035 exit_bb
= region
->exit
;
6037 si
= gsi_last_bb (entry_bb
);
6038 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_SINGLE
6039 || gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_MASTER
6040 || gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_ORDERED
6041 || gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_CRITICAL
);
6042 gsi_remove (&si
, true);
6043 single_succ_edge (entry_bb
)->flags
= EDGE_FALLTHRU
;
6047 si
= gsi_last_bb (exit_bb
);
6048 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_RETURN
);
6049 gsi_remove (&si
, true);
6050 single_succ_edge (exit_bb
)->flags
= EDGE_FALLTHRU
;
6054 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
6055 operation as a normal volatile load. */
6058 expand_omp_atomic_load (basic_block load_bb
, tree addr
,
6059 tree loaded_val
, int index
)
6061 enum built_in_function tmpbase
;
6062 gimple_stmt_iterator gsi
;
6063 basic_block store_bb
;
6066 tree decl
, call
, type
, itype
;
6068 gsi
= gsi_last_bb (load_bb
);
6069 stmt
= gsi_stmt (gsi
);
6070 gcc_assert (gimple_code (stmt
) == GIMPLE_OMP_ATOMIC_LOAD
);
6071 loc
= gimple_location (stmt
);
6073 /* ??? If the target does not implement atomic_load_optab[mode], and mode
6074 is smaller than word size, then expand_atomic_load assumes that the load
6075 is atomic. We could avoid the builtin entirely in this case. */
6077 tmpbase
= (enum built_in_function
) (BUILT_IN_ATOMIC_LOAD_N
+ index
+ 1);
6078 decl
= builtin_decl_explicit (tmpbase
);
6079 if (decl
== NULL_TREE
)
6082 type
= TREE_TYPE (loaded_val
);
6083 itype
= TREE_TYPE (TREE_TYPE (decl
));
6085 call
= build_call_expr_loc (loc
, decl
, 2, addr
,
6086 build_int_cst (NULL
, MEMMODEL_RELAXED
));
6087 if (!useless_type_conversion_p (type
, itype
))
6088 call
= fold_build1_loc (loc
, VIEW_CONVERT_EXPR
, type
, call
);
6089 call
= build2_loc (loc
, MODIFY_EXPR
, void_type_node
, loaded_val
, call
);
6091 force_gimple_operand_gsi (&gsi
, call
, true, NULL_TREE
, true, GSI_SAME_STMT
);
6092 gsi_remove (&gsi
, true);
6094 store_bb
= single_succ (load_bb
);
6095 gsi
= gsi_last_bb (store_bb
);
6096 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_ATOMIC_STORE
);
6097 gsi_remove (&gsi
, true);
6099 if (gimple_in_ssa_p (cfun
))
6100 update_ssa (TODO_update_ssa_no_phi
);
6105 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
6106 operation as a normal volatile store. */
6109 expand_omp_atomic_store (basic_block load_bb
, tree addr
,
6110 tree loaded_val
, tree stored_val
, int index
)
6112 enum built_in_function tmpbase
;
6113 gimple_stmt_iterator gsi
;
6114 basic_block store_bb
= single_succ (load_bb
);
6117 tree decl
, call
, type
, itype
;
6118 enum machine_mode imode
;
6121 gsi
= gsi_last_bb (load_bb
);
6122 stmt
= gsi_stmt (gsi
);
6123 gcc_assert (gimple_code (stmt
) == GIMPLE_OMP_ATOMIC_LOAD
);
6125 /* If the load value is needed, then this isn't a store but an exchange. */
6126 exchange
= gimple_omp_atomic_need_value_p (stmt
);
6128 gsi
= gsi_last_bb (store_bb
);
6129 stmt
= gsi_stmt (gsi
);
6130 gcc_assert (gimple_code (stmt
) == GIMPLE_OMP_ATOMIC_STORE
);
6131 loc
= gimple_location (stmt
);
6133 /* ??? If the target does not implement atomic_store_optab[mode], and mode
6134 is smaller than word size, then expand_atomic_store assumes that the store
6135 is atomic. We could avoid the builtin entirely in this case. */
6137 tmpbase
= (exchange
? BUILT_IN_ATOMIC_EXCHANGE_N
: BUILT_IN_ATOMIC_STORE_N
);
6138 tmpbase
= (enum built_in_function
) ((int) tmpbase
+ index
+ 1);
6139 decl
= builtin_decl_explicit (tmpbase
);
6140 if (decl
== NULL_TREE
)
6143 type
= TREE_TYPE (stored_val
);
6145 /* Dig out the type of the function's second argument. */
6146 itype
= TREE_TYPE (decl
);
6147 itype
= TYPE_ARG_TYPES (itype
);
6148 itype
= TREE_CHAIN (itype
);
6149 itype
= TREE_VALUE (itype
);
6150 imode
= TYPE_MODE (itype
);
6152 if (exchange
&& !can_atomic_exchange_p (imode
, true))
6155 if (!useless_type_conversion_p (itype
, type
))
6156 stored_val
= fold_build1_loc (loc
, VIEW_CONVERT_EXPR
, itype
, stored_val
);
6157 call
= build_call_expr_loc (loc
, decl
, 3, addr
, stored_val
,
6158 build_int_cst (NULL
, MEMMODEL_RELAXED
));
6161 if (!useless_type_conversion_p (type
, itype
))
6162 call
= build1_loc (loc
, VIEW_CONVERT_EXPR
, type
, call
);
6163 call
= build2_loc (loc
, MODIFY_EXPR
, void_type_node
, loaded_val
, call
);
6166 force_gimple_operand_gsi (&gsi
, call
, true, NULL_TREE
, true, GSI_SAME_STMT
);
6167 gsi_remove (&gsi
, true);
6169 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
6170 gsi
= gsi_last_bb (load_bb
);
6171 gsi_remove (&gsi
, true);
6173 if (gimple_in_ssa_p (cfun
))
6174 update_ssa (TODO_update_ssa_no_phi
);
6179 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
6180 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
6181 size of the data type, and thus usable to find the index of the builtin
6182 decl. Returns false if the expression is not of the proper form. */
6185 expand_omp_atomic_fetch_op (basic_block load_bb
,
6186 tree addr
, tree loaded_val
,
6187 tree stored_val
, int index
)
6189 enum built_in_function oldbase
, newbase
, tmpbase
;
6190 tree decl
, itype
, call
;
6192 basic_block store_bb
= single_succ (load_bb
);
6193 gimple_stmt_iterator gsi
;
6196 enum tree_code code
;
6197 bool need_old
, need_new
;
6198 enum machine_mode imode
;
6200 /* We expect to find the following sequences:
6203 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
6206 val = tmp OP something; (or: something OP tmp)
6207 GIMPLE_OMP_STORE (val)
6209 ???FIXME: Allow a more flexible sequence.
6210 Perhaps use data flow to pick the statements.
6214 gsi
= gsi_after_labels (store_bb
);
6215 stmt
= gsi_stmt (gsi
);
6216 loc
= gimple_location (stmt
);
6217 if (!is_gimple_assign (stmt
))
6220 if (gimple_code (gsi_stmt (gsi
)) != GIMPLE_OMP_ATOMIC_STORE
)
6222 need_new
= gimple_omp_atomic_need_value_p (gsi_stmt (gsi
));
6223 need_old
= gimple_omp_atomic_need_value_p (last_stmt (load_bb
));
6224 gcc_checking_assert (!need_old
|| !need_new
);
6226 if (!operand_equal_p (gimple_assign_lhs (stmt
), stored_val
, 0))
6229 /* Check for one of the supported fetch-op operations. */
6230 code
= gimple_assign_rhs_code (stmt
);
6234 case POINTER_PLUS_EXPR
:
6235 oldbase
= BUILT_IN_ATOMIC_FETCH_ADD_N
;
6236 newbase
= BUILT_IN_ATOMIC_ADD_FETCH_N
;
6239 oldbase
= BUILT_IN_ATOMIC_FETCH_SUB_N
;
6240 newbase
= BUILT_IN_ATOMIC_SUB_FETCH_N
;
6243 oldbase
= BUILT_IN_ATOMIC_FETCH_AND_N
;
6244 newbase
= BUILT_IN_ATOMIC_AND_FETCH_N
;
6247 oldbase
= BUILT_IN_ATOMIC_FETCH_OR_N
;
6248 newbase
= BUILT_IN_ATOMIC_OR_FETCH_N
;
6251 oldbase
= BUILT_IN_ATOMIC_FETCH_XOR_N
;
6252 newbase
= BUILT_IN_ATOMIC_XOR_FETCH_N
;
6258 /* Make sure the expression is of the proper form. */
6259 if (operand_equal_p (gimple_assign_rhs1 (stmt
), loaded_val
, 0))
6260 rhs
= gimple_assign_rhs2 (stmt
);
6261 else if (commutative_tree_code (gimple_assign_rhs_code (stmt
))
6262 && operand_equal_p (gimple_assign_rhs2 (stmt
), loaded_val
, 0))
6263 rhs
= gimple_assign_rhs1 (stmt
);
6267 tmpbase
= ((enum built_in_function
)
6268 ((need_new
? newbase
: oldbase
) + index
+ 1));
6269 decl
= builtin_decl_explicit (tmpbase
);
6270 if (decl
== NULL_TREE
)
6272 itype
= TREE_TYPE (TREE_TYPE (decl
));
6273 imode
= TYPE_MODE (itype
);
6275 /* We could test all of the various optabs involved, but the fact of the
6276 matter is that (with the exception of i486 vs i586 and xadd) all targets
6277 that support any atomic operaton optab also implements compare-and-swap.
6278 Let optabs.c take care of expanding any compare-and-swap loop. */
6279 if (!can_compare_and_swap_p (imode
, true))
6282 gsi
= gsi_last_bb (load_bb
);
6283 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_ATOMIC_LOAD
);
6285 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
6286 It only requires that the operation happen atomically. Thus we can
6287 use the RELAXED memory model. */
6288 call
= build_call_expr_loc (loc
, decl
, 3, addr
,
6289 fold_convert_loc (loc
, itype
, rhs
),
6290 build_int_cst (NULL
, MEMMODEL_RELAXED
));
6292 if (need_old
|| need_new
)
6294 lhs
= need_old
? loaded_val
: stored_val
;
6295 call
= fold_convert_loc (loc
, TREE_TYPE (lhs
), call
);
6296 call
= build2_loc (loc
, MODIFY_EXPR
, void_type_node
, lhs
, call
);
6299 call
= fold_convert_loc (loc
, void_type_node
, call
);
6300 force_gimple_operand_gsi (&gsi
, call
, true, NULL_TREE
, true, GSI_SAME_STMT
);
6301 gsi_remove (&gsi
, true);
6303 gsi
= gsi_last_bb (store_bb
);
6304 gcc_assert (gimple_code (gsi_stmt (gsi
)) == GIMPLE_OMP_ATOMIC_STORE
);
6305 gsi_remove (&gsi
, true);
6306 gsi
= gsi_last_bb (store_bb
);
6307 gsi_remove (&gsi
, true);
6309 if (gimple_in_ssa_p (cfun
))
6310 update_ssa (TODO_update_ssa_no_phi
);
6315 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
6319 newval = rhs; // with oldval replacing *addr in rhs
6320 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
6321 if (oldval != newval)
6324 INDEX is log2 of the size of the data type, and thus usable to find the
6325 index of the builtin decl. */
6328 expand_omp_atomic_pipeline (basic_block load_bb
, basic_block store_bb
,
6329 tree addr
, tree loaded_val
, tree stored_val
,
6332 tree loadedi
, storedi
, initial
, new_storedi
, old_vali
;
6333 tree type
, itype
, cmpxchg
, iaddr
;
6334 gimple_stmt_iterator si
;
6335 basic_block loop_header
= single_succ (load_bb
);
6338 enum built_in_function fncode
;
6340 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
6341 order to use the RELAXED memory model effectively. */
6342 fncode
= (enum built_in_function
)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
6344 cmpxchg
= builtin_decl_explicit (fncode
);
6345 if (cmpxchg
== NULL_TREE
)
6347 type
= TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr
)));
6348 itype
= TREE_TYPE (TREE_TYPE (cmpxchg
));
6350 if (!can_compare_and_swap_p (TYPE_MODE (itype
), true))
6353 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
6354 si
= gsi_last_bb (load_bb
);
6355 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_ATOMIC_LOAD
);
6357 /* For floating-point values, we'll need to view-convert them to integers
6358 so that we can perform the atomic compare and swap. Simplify the
6359 following code by always setting up the "i"ntegral variables. */
6360 if (!INTEGRAL_TYPE_P (type
) && !POINTER_TYPE_P (type
))
6364 iaddr
= create_tmp_reg (build_pointer_type_for_mode (itype
, ptr_mode
,
6367 = force_gimple_operand_gsi (&si
,
6368 fold_convert (TREE_TYPE (iaddr
), addr
),
6369 false, NULL_TREE
, true, GSI_SAME_STMT
);
6370 stmt
= gimple_build_assign (iaddr
, iaddr_val
);
6371 gsi_insert_before (&si
, stmt
, GSI_SAME_STMT
);
6372 loadedi
= create_tmp_var (itype
, NULL
);
6373 if (gimple_in_ssa_p (cfun
))
6374 loadedi
= make_ssa_name (loadedi
, NULL
);
6379 loadedi
= loaded_val
;
6383 = force_gimple_operand_gsi (&si
,
6384 build2 (MEM_REF
, TREE_TYPE (TREE_TYPE (iaddr
)),
6386 build_int_cst (TREE_TYPE (iaddr
), 0)),
6387 true, NULL_TREE
, true, GSI_SAME_STMT
);
6389 /* Move the value to the LOADEDI temporary. */
6390 if (gimple_in_ssa_p (cfun
))
6392 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header
)));
6393 phi
= create_phi_node (loadedi
, loop_header
);
6394 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi
, single_succ_edge (load_bb
)),
6398 gsi_insert_before (&si
,
6399 gimple_build_assign (loadedi
, initial
),
6401 if (loadedi
!= loaded_val
)
6403 gimple_stmt_iterator gsi2
;
6406 x
= build1 (VIEW_CONVERT_EXPR
, type
, loadedi
);
6407 gsi2
= gsi_start_bb (loop_header
);
6408 if (gimple_in_ssa_p (cfun
))
6411 x
= force_gimple_operand_gsi (&gsi2
, x
, true, NULL_TREE
,
6412 true, GSI_SAME_STMT
);
6413 stmt
= gimple_build_assign (loaded_val
, x
);
6414 gsi_insert_before (&gsi2
, stmt
, GSI_SAME_STMT
);
6418 x
= build2 (MODIFY_EXPR
, TREE_TYPE (loaded_val
), loaded_val
, x
);
6419 force_gimple_operand_gsi (&gsi2
, x
, true, NULL_TREE
,
6420 true, GSI_SAME_STMT
);
6423 gsi_remove (&si
, true);
6425 si
= gsi_last_bb (store_bb
);
6426 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_ATOMIC_STORE
);
6429 storedi
= stored_val
;
6432 force_gimple_operand_gsi (&si
,
6433 build1 (VIEW_CONVERT_EXPR
, itype
,
6434 stored_val
), true, NULL_TREE
, true,
6437 /* Build the compare&swap statement. */
6438 new_storedi
= build_call_expr (cmpxchg
, 3, iaddr
, loadedi
, storedi
);
6439 new_storedi
= force_gimple_operand_gsi (&si
,
6440 fold_convert (TREE_TYPE (loadedi
),
6443 true, GSI_SAME_STMT
);
6445 if (gimple_in_ssa_p (cfun
))
6449 old_vali
= create_tmp_var (TREE_TYPE (loadedi
), NULL
);
6450 stmt
= gimple_build_assign (old_vali
, loadedi
);
6451 gsi_insert_before (&si
, stmt
, GSI_SAME_STMT
);
6453 stmt
= gimple_build_assign (loadedi
, new_storedi
);
6454 gsi_insert_before (&si
, stmt
, GSI_SAME_STMT
);
6457 /* Note that we always perform the comparison as an integer, even for
6458 floating point. This allows the atomic operation to properly
6459 succeed even with NaNs and -0.0. */
6460 stmt
= gimple_build_cond_empty
6461 (build2 (NE_EXPR
, boolean_type_node
,
6462 new_storedi
, old_vali
));
6463 gsi_insert_before (&si
, stmt
, GSI_SAME_STMT
);
6466 e
= single_succ_edge (store_bb
);
6467 e
->flags
&= ~EDGE_FALLTHRU
;
6468 e
->flags
|= EDGE_FALSE_VALUE
;
6470 e
= make_edge (store_bb
, loop_header
, EDGE_TRUE_VALUE
);
6472 /* Copy the new value to loadedi (we already did that before the condition
6473 if we are not in SSA). */
6474 if (gimple_in_ssa_p (cfun
))
6476 phi
= gimple_seq_first_stmt (phi_nodes (loop_header
));
6477 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi
, e
), new_storedi
);
6480 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
6481 gsi_remove (&si
, true);
6483 struct loop
*loop
= alloc_loop ();
6484 loop
->header
= loop_header
;
6485 loop
->latch
= store_bb
;
6486 add_loop (loop
, loop_header
->loop_father
);
6488 if (gimple_in_ssa_p (cfun
))
6489 update_ssa (TODO_update_ssa_no_phi
);
6494 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
6496 GOMP_atomic_start ();
6500 The result is not globally atomic, but works so long as all parallel
6501 references are within #pragma omp atomic directives. According to
6502 responses received from omp@openmp.org, appears to be within spec.
6503 Which makes sense, since that's how several other compilers handle
6504 this situation as well.
6505 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
6506 expanding. STORED_VAL is the operand of the matching
6507 GIMPLE_OMP_ATOMIC_STORE.
6510 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
6514 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
6519 expand_omp_atomic_mutex (basic_block load_bb
, basic_block store_bb
,
6520 tree addr
, tree loaded_val
, tree stored_val
)
6522 gimple_stmt_iterator si
;
6526 si
= gsi_last_bb (load_bb
);
6527 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_ATOMIC_LOAD
);
6529 t
= builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START
);
6530 t
= build_call_expr (t
, 0);
6531 force_gimple_operand_gsi (&si
, t
, true, NULL_TREE
, true, GSI_SAME_STMT
);
6533 stmt
= gimple_build_assign (loaded_val
, build_simple_mem_ref (addr
));
6534 gsi_insert_before (&si
, stmt
, GSI_SAME_STMT
);
6535 gsi_remove (&si
, true);
6537 si
= gsi_last_bb (store_bb
);
6538 gcc_assert (gimple_code (gsi_stmt (si
)) == GIMPLE_OMP_ATOMIC_STORE
);
6540 stmt
= gimple_build_assign (build_simple_mem_ref (unshare_expr (addr
)),
6542 gsi_insert_before (&si
, stmt
, GSI_SAME_STMT
);
6544 t
= builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END
);
6545 t
= build_call_expr (t
, 0);
6546 force_gimple_operand_gsi (&si
, t
, true, NULL_TREE
, true, GSI_SAME_STMT
);
6547 gsi_remove (&si
, true);
6549 if (gimple_in_ssa_p (cfun
))
6550 update_ssa (TODO_update_ssa_no_phi
);
6554 /* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
6555 using expand_omp_atomic_fetch_op. If it failed, we try to
6556 call expand_omp_atomic_pipeline, and if it fails too, the
6557 ultimate fallback is wrapping the operation in a mutex
6558 (expand_omp_atomic_mutex). REGION is the atomic region built
6559 by build_omp_regions_1(). */
6562 expand_omp_atomic (struct omp_region
*region
)
6564 basic_block load_bb
= region
->entry
, store_bb
= region
->exit
;
6565 gimple load
= last_stmt (load_bb
), store
= last_stmt (store_bb
);
6566 tree loaded_val
= gimple_omp_atomic_load_lhs (load
);
6567 tree addr
= gimple_omp_atomic_load_rhs (load
);
6568 tree stored_val
= gimple_omp_atomic_store_val (store
);
6569 tree type
= TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr
)));
6570 HOST_WIDE_INT index
;
6572 /* Make sure the type is one of the supported sizes. */
6573 index
= tree_low_cst (TYPE_SIZE_UNIT (type
), 1);
6574 index
= exact_log2 (index
);
6575 if (index
>= 0 && index
<= 4)
6577 unsigned int align
= TYPE_ALIGN_UNIT (type
);
6579 /* __sync builtins require strict data alignment. */
6580 if (exact_log2 (align
) >= index
)
6583 if (loaded_val
== stored_val
6584 && (GET_MODE_CLASS (TYPE_MODE (type
)) == MODE_INT
6585 || GET_MODE_CLASS (TYPE_MODE (type
)) == MODE_FLOAT
)
6586 && GET_MODE_BITSIZE (TYPE_MODE (type
)) <= BITS_PER_WORD
6587 && expand_omp_atomic_load (load_bb
, addr
, loaded_val
, index
))
6591 if ((GET_MODE_CLASS (TYPE_MODE (type
)) == MODE_INT
6592 || GET_MODE_CLASS (TYPE_MODE (type
)) == MODE_FLOAT
)
6593 && GET_MODE_BITSIZE (TYPE_MODE (type
)) <= BITS_PER_WORD
6594 && store_bb
== single_succ (load_bb
)
6595 && first_stmt (store_bb
) == store
6596 && expand_omp_atomic_store (load_bb
, addr
, loaded_val
,
6600 /* When possible, use specialized atomic update functions. */
6601 if ((INTEGRAL_TYPE_P (type
) || POINTER_TYPE_P (type
))
6602 && store_bb
== single_succ (load_bb
)
6603 && expand_omp_atomic_fetch_op (load_bb
, addr
,
6604 loaded_val
, stored_val
, index
))
6607 /* If we don't have specialized __sync builtins, try and implement
6608 as a compare and swap loop. */
6609 if (expand_omp_atomic_pipeline (load_bb
, store_bb
, addr
,
6610 loaded_val
, stored_val
, index
))
6615 /* The ultimate fallback is wrapping the operation in a mutex. */
6616 expand_omp_atomic_mutex (load_bb
, store_bb
, addr
, loaded_val
, stored_val
);
6620 /* Expand the parallel region tree rooted at REGION. Expansion
6621 proceeds in depth-first order. Innermost regions are expanded
6622 first. This way, parallel regions that require a new function to
6623 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
6624 internal dependencies in their body. */
6627 expand_omp (struct omp_region
*region
)
6631 location_t saved_location
;
6633 /* First, determine whether this is a combined parallel+workshare
6635 if (region
->type
== GIMPLE_OMP_PARALLEL
)
6636 determine_parallel_type (region
);
6639 expand_omp (region
->inner
);
6641 saved_location
= input_location
;
6642 if (gimple_has_location (last_stmt (region
->entry
)))
6643 input_location
= gimple_location (last_stmt (region
->entry
));
6645 switch (region
->type
)
6647 case GIMPLE_OMP_PARALLEL
:
6648 case GIMPLE_OMP_TASK
:
6649 expand_omp_taskreg (region
);
6652 case GIMPLE_OMP_FOR
:
6653 expand_omp_for (region
);
6656 case GIMPLE_OMP_SECTIONS
:
6657 expand_omp_sections (region
);
6660 case GIMPLE_OMP_SECTION
:
6661 /* Individual omp sections are handled together with their
6662 parent GIMPLE_OMP_SECTIONS region. */
6665 case GIMPLE_OMP_SINGLE
:
6666 expand_omp_single (region
);
6669 case GIMPLE_OMP_MASTER
:
6670 case GIMPLE_OMP_ORDERED
:
6671 case GIMPLE_OMP_CRITICAL
:
6672 expand_omp_synch (region
);
6675 case GIMPLE_OMP_ATOMIC_LOAD
:
6676 expand_omp_atomic (region
);
6683 input_location
= saved_location
;
6684 region
= region
->next
;
6689 /* Helper for build_omp_regions. Scan the dominator tree starting at
6690 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
6691 true, the function ends once a single tree is built (otherwise, whole
6692 forest of OMP constructs may be built). */
6695 build_omp_regions_1 (basic_block bb
, struct omp_region
*parent
,
6698 gimple_stmt_iterator gsi
;
6702 gsi
= gsi_last_bb (bb
);
6703 if (!gsi_end_p (gsi
) && is_gimple_omp (gsi_stmt (gsi
)))
6705 struct omp_region
*region
;
6706 enum gimple_code code
;
6708 stmt
= gsi_stmt (gsi
);
6709 code
= gimple_code (stmt
);
6710 if (code
== GIMPLE_OMP_RETURN
)
6712 /* STMT is the return point out of region PARENT. Mark it
6713 as the exit point and make PARENT the immediately
6714 enclosing region. */
6715 gcc_assert (parent
);
6718 parent
= parent
->outer
;
6720 else if (code
== GIMPLE_OMP_ATOMIC_STORE
)
6722 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
6723 GIMPLE_OMP_RETURN, but matches with
6724 GIMPLE_OMP_ATOMIC_LOAD. */
6725 gcc_assert (parent
);
6726 gcc_assert (parent
->type
== GIMPLE_OMP_ATOMIC_LOAD
);
6729 parent
= parent
->outer
;
6732 else if (code
== GIMPLE_OMP_CONTINUE
)
6734 gcc_assert (parent
);
6737 else if (code
== GIMPLE_OMP_SECTIONS_SWITCH
)
6739 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
6740 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
6745 /* Otherwise, this directive becomes the parent for a new
6747 region
= new_omp_region (bb
, code
, parent
);
6752 if (single_tree
&& !parent
)
6755 for (son
= first_dom_son (CDI_DOMINATORS
, bb
);
6757 son
= next_dom_son (CDI_DOMINATORS
, son
))
6758 build_omp_regions_1 (son
, parent
, single_tree
);
6761 /* Builds the tree of OMP regions rooted at ROOT, storing it to
6765 build_omp_regions_root (basic_block root
)
6767 gcc_assert (root_omp_region
== NULL
);
6768 build_omp_regions_1 (root
, NULL
, true);
6769 gcc_assert (root_omp_region
!= NULL
);
6772 /* Expands omp construct (and its subconstructs) starting in HEAD. */
6775 omp_expand_local (basic_block head
)
6777 build_omp_regions_root (head
);
6778 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
6780 fprintf (dump_file
, "\nOMP region tree\n\n");
6781 dump_omp_region (dump_file
, root_omp_region
, 0);
6782 fprintf (dump_file
, "\n");
6785 remove_exit_barriers (root_omp_region
);
6786 expand_omp (root_omp_region
);
6788 free_omp_regions ();
6791 /* Scan the CFG and build a tree of OMP regions. Return the root of
6792 the OMP region tree. */
6795 build_omp_regions (void)
6797 gcc_assert (root_omp_region
== NULL
);
6798 calculate_dominance_info (CDI_DOMINATORS
);
6799 build_omp_regions_1 (ENTRY_BLOCK_PTR
, NULL
, false);
6802 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
6805 execute_expand_omp (void)
6807 build_omp_regions ();
6809 if (!root_omp_region
)
6814 fprintf (dump_file
, "\nOMP region tree\n\n");
6815 dump_omp_region (dump_file
, root_omp_region
, 0);
6816 fprintf (dump_file
, "\n");
6819 remove_exit_barriers (root_omp_region
);
6821 expand_omp (root_omp_region
);
6823 cleanup_tree_cfg ();
6825 free_omp_regions ();
6830 /* OMP expansion -- the default pass, run before creation of SSA form. */
6833 gate_expand_omp (void)
6835 return (flag_openmp
!= 0 && !seen_error ());
6840 const pass_data pass_data_expand_omp
=
6842 GIMPLE_PASS
, /* type */
6843 "ompexp", /* name */
6844 OPTGROUP_NONE
, /* optinfo_flags */
6845 true, /* has_gate */
6846 true, /* has_execute */
6847 TV_NONE
, /* tv_id */
6848 PROP_gimple_any
, /* properties_required */
6849 0, /* properties_provided */
6850 0, /* properties_destroyed */
6851 0, /* todo_flags_start */
6852 0, /* todo_flags_finish */
6855 class pass_expand_omp
: public gimple_opt_pass
6858 pass_expand_omp(gcc::context
*ctxt
)
6859 : gimple_opt_pass(pass_data_expand_omp
, ctxt
)
6862 /* opt_pass methods: */
6863 bool gate () { return gate_expand_omp (); }
6864 unsigned int execute () { return execute_expand_omp (); }
6866 }; // class pass_expand_omp
6871 make_pass_expand_omp (gcc::context
*ctxt
)
6873 return new pass_expand_omp (ctxt
);
6876 /* Routines to lower OpenMP directives into OMP-GIMPLE. */
6878 /* Lower the OpenMP sections directive in the current statement in GSI_P.
6879 CTX is the enclosing OMP context for the current statement. */
6882 lower_omp_sections (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
6884 tree block
, control
;
6885 gimple_stmt_iterator tgsi
;
6886 gimple stmt
, new_stmt
, bind
, t
;
6887 gimple_seq ilist
, dlist
, olist
, new_body
;
6888 struct gimplify_ctx gctx
;
6890 stmt
= gsi_stmt (*gsi_p
);
6892 push_gimplify_context (&gctx
);
6896 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt
),
6897 &ilist
, &dlist
, ctx
);
6899 new_body
= gimple_omp_body (stmt
);
6900 gimple_omp_set_body (stmt
, NULL
);
6901 tgsi
= gsi_start (new_body
);
6902 for (; !gsi_end_p (tgsi
); gsi_next (&tgsi
))
6907 sec_start
= gsi_stmt (tgsi
);
6908 sctx
= maybe_lookup_ctx (sec_start
);
6911 lower_omp (gimple_omp_body_ptr (sec_start
), sctx
);
6912 gsi_insert_seq_after (&tgsi
, gimple_omp_body (sec_start
),
6913 GSI_CONTINUE_LINKING
);
6914 gimple_omp_set_body (sec_start
, NULL
);
6916 if (gsi_one_before_end_p (tgsi
))
6918 gimple_seq l
= NULL
;
6919 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt
), NULL
,
6921 gsi_insert_seq_after (&tgsi
, l
, GSI_CONTINUE_LINKING
);
6922 gimple_omp_section_set_last (sec_start
);
6925 gsi_insert_after (&tgsi
, gimple_build_omp_return (false),
6926 GSI_CONTINUE_LINKING
);
6929 block
= make_node (BLOCK
);
6930 bind
= gimple_build_bind (NULL
, new_body
, block
);
6933 lower_reduction_clauses (gimple_omp_sections_clauses (stmt
), &olist
, ctx
);
6935 block
= make_node (BLOCK
);
6936 new_stmt
= gimple_build_bind (NULL
, NULL
, block
);
6937 gsi_replace (gsi_p
, new_stmt
, true);
6939 pop_gimplify_context (new_stmt
);
6940 gimple_bind_append_vars (new_stmt
, ctx
->block_vars
);
6941 BLOCK_VARS (block
) = gimple_bind_vars (bind
);
6942 if (BLOCK_VARS (block
))
6943 TREE_USED (block
) = 1;
6946 gimple_seq_add_seq (&new_body
, ilist
);
6947 gimple_seq_add_stmt (&new_body
, stmt
);
6948 gimple_seq_add_stmt (&new_body
, gimple_build_omp_sections_switch ());
6949 gimple_seq_add_stmt (&new_body
, bind
);
6951 control
= create_tmp_var (unsigned_type_node
, ".section");
6952 t
= gimple_build_omp_continue (control
, control
);
6953 gimple_omp_sections_set_control (stmt
, control
);
6954 gimple_seq_add_stmt (&new_body
, t
);
6956 gimple_seq_add_seq (&new_body
, olist
);
6957 gimple_seq_add_seq (&new_body
, dlist
);
6959 new_body
= maybe_catch_exception (new_body
);
6961 t
= gimple_build_omp_return
6962 (!!find_omp_clause (gimple_omp_sections_clauses (stmt
),
6963 OMP_CLAUSE_NOWAIT
));
6964 gimple_seq_add_stmt (&new_body
, t
);
6966 gimple_bind_set_body (new_stmt
, new_body
);
6970 /* A subroutine of lower_omp_single. Expand the simple form of
6971 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
6973 if (GOMP_single_start ())
6975 [ GOMP_barrier (); ] -> unless 'nowait' is present.
6977 FIXME. It may be better to delay expanding the logic of this until
6978 pass_expand_omp. The expanded logic may make the job more difficult
6979 to a synchronization analysis pass. */
6982 lower_omp_single_simple (gimple single_stmt
, gimple_seq
*pre_p
)
6984 location_t loc
= gimple_location (single_stmt
);
6985 tree tlabel
= create_artificial_label (loc
);
6986 tree flabel
= create_artificial_label (loc
);
6990 decl
= builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START
);
6991 lhs
= create_tmp_var (TREE_TYPE (TREE_TYPE (decl
)), NULL
);
6992 call
= gimple_build_call (decl
, 0);
6993 gimple_call_set_lhs (call
, lhs
);
6994 gimple_seq_add_stmt (pre_p
, call
);
6996 cond
= gimple_build_cond (EQ_EXPR
, lhs
,
6997 fold_convert_loc (loc
, TREE_TYPE (lhs
),
7000 gimple_seq_add_stmt (pre_p
, cond
);
7001 gimple_seq_add_stmt (pre_p
, gimple_build_label (tlabel
));
7002 gimple_seq_add_seq (pre_p
, gimple_omp_body (single_stmt
));
7003 gimple_seq_add_stmt (pre_p
, gimple_build_label (flabel
));
7007 /* A subroutine of lower_omp_single. Expand the simple form of
7008 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
7010 #pragma omp single copyprivate (a, b, c)
7012 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
7015 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
7021 GOMP_single_copy_end (©out);
7032 FIXME. It may be better to delay expanding the logic of this until
7033 pass_expand_omp. The expanded logic may make the job more difficult
7034 to a synchronization analysis pass. */
7037 lower_omp_single_copy (gimple single_stmt
, gimple_seq
*pre_p
, omp_context
*ctx
)
7039 tree ptr_type
, t
, l0
, l1
, l2
, bfn_decl
;
7040 gimple_seq copyin_seq
;
7041 location_t loc
= gimple_location (single_stmt
);
7043 ctx
->sender_decl
= create_tmp_var (ctx
->record_type
, ".omp_copy_o");
7045 ptr_type
= build_pointer_type (ctx
->record_type
);
7046 ctx
->receiver_decl
= create_tmp_var (ptr_type
, ".omp_copy_i");
7048 l0
= create_artificial_label (loc
);
7049 l1
= create_artificial_label (loc
);
7050 l2
= create_artificial_label (loc
);
7052 bfn_decl
= builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START
);
7053 t
= build_call_expr_loc (loc
, bfn_decl
, 0);
7054 t
= fold_convert_loc (loc
, ptr_type
, t
);
7055 gimplify_assign (ctx
->receiver_decl
, t
, pre_p
);
7057 t
= build2 (EQ_EXPR
, boolean_type_node
, ctx
->receiver_decl
,
7058 build_int_cst (ptr_type
, 0));
7059 t
= build3 (COND_EXPR
, void_type_node
, t
,
7060 build_and_jump (&l0
), build_and_jump (&l1
));
7061 gimplify_and_add (t
, pre_p
);
7063 gimple_seq_add_stmt (pre_p
, gimple_build_label (l0
));
7065 gimple_seq_add_seq (pre_p
, gimple_omp_body (single_stmt
));
7068 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt
), pre_p
,
7071 t
= build_fold_addr_expr_loc (loc
, ctx
->sender_decl
);
7072 bfn_decl
= builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END
);
7073 t
= build_call_expr_loc (loc
, bfn_decl
, 1, t
);
7074 gimplify_and_add (t
, pre_p
);
7076 t
= build_and_jump (&l2
);
7077 gimplify_and_add (t
, pre_p
);
7079 gimple_seq_add_stmt (pre_p
, gimple_build_label (l1
));
7081 gimple_seq_add_seq (pre_p
, copyin_seq
);
7083 gimple_seq_add_stmt (pre_p
, gimple_build_label (l2
));
7087 /* Expand code for an OpenMP single directive. */
7090 lower_omp_single (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
7093 gimple t
, bind
, single_stmt
= gsi_stmt (*gsi_p
);
7094 gimple_seq bind_body
, dlist
;
7095 struct gimplify_ctx gctx
;
7097 push_gimplify_context (&gctx
);
7099 block
= make_node (BLOCK
);
7100 bind
= gimple_build_bind (NULL
, NULL
, block
);
7101 gsi_replace (gsi_p
, bind
, true);
7104 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt
),
7105 &bind_body
, &dlist
, ctx
);
7106 lower_omp (gimple_omp_body_ptr (single_stmt
), ctx
);
7108 gimple_seq_add_stmt (&bind_body
, single_stmt
);
7110 if (ctx
->record_type
)
7111 lower_omp_single_copy (single_stmt
, &bind_body
, ctx
);
7113 lower_omp_single_simple (single_stmt
, &bind_body
);
7115 gimple_omp_set_body (single_stmt
, NULL
);
7117 gimple_seq_add_seq (&bind_body
, dlist
);
7119 bind_body
= maybe_catch_exception (bind_body
);
7121 t
= gimple_build_omp_return
7122 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt
),
7123 OMP_CLAUSE_NOWAIT
));
7124 gimple_seq_add_stmt (&bind_body
, t
);
7125 gimple_bind_set_body (bind
, bind_body
);
7127 pop_gimplify_context (bind
);
7129 gimple_bind_append_vars (bind
, ctx
->block_vars
);
7130 BLOCK_VARS (block
) = ctx
->block_vars
;
7131 if (BLOCK_VARS (block
))
7132 TREE_USED (block
) = 1;
7136 /* Expand code for an OpenMP master directive. */
7139 lower_omp_master (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
7141 tree block
, lab
= NULL
, x
, bfn_decl
;
7142 gimple stmt
= gsi_stmt (*gsi_p
), bind
;
7143 location_t loc
= gimple_location (stmt
);
7145 struct gimplify_ctx gctx
;
7147 push_gimplify_context (&gctx
);
7149 block
= make_node (BLOCK
);
7150 bind
= gimple_build_bind (NULL
, NULL
, block
);
7151 gsi_replace (gsi_p
, bind
, true);
7152 gimple_bind_add_stmt (bind
, stmt
);
7154 bfn_decl
= builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM
);
7155 x
= build_call_expr_loc (loc
, bfn_decl
, 0);
7156 x
= build2 (EQ_EXPR
, boolean_type_node
, x
, integer_zero_node
);
7157 x
= build3 (COND_EXPR
, void_type_node
, x
, NULL
, build_and_jump (&lab
));
7159 gimplify_and_add (x
, &tseq
);
7160 gimple_bind_add_seq (bind
, tseq
);
7162 lower_omp (gimple_omp_body_ptr (stmt
), ctx
);
7163 gimple_omp_set_body (stmt
, maybe_catch_exception (gimple_omp_body (stmt
)));
7164 gimple_bind_add_seq (bind
, gimple_omp_body (stmt
));
7165 gimple_omp_set_body (stmt
, NULL
);
7167 gimple_bind_add_stmt (bind
, gimple_build_label (lab
));
7169 gimple_bind_add_stmt (bind
, gimple_build_omp_return (true));
7171 pop_gimplify_context (bind
);
7173 gimple_bind_append_vars (bind
, ctx
->block_vars
);
7174 BLOCK_VARS (block
) = ctx
->block_vars
;
7178 /* Expand code for an OpenMP ordered directive. */
7181 lower_omp_ordered (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
7184 gimple stmt
= gsi_stmt (*gsi_p
), bind
, x
;
7185 struct gimplify_ctx gctx
;
7187 push_gimplify_context (&gctx
);
7189 block
= make_node (BLOCK
);
7190 bind
= gimple_build_bind (NULL
, NULL
, block
);
7191 gsi_replace (gsi_p
, bind
, true);
7192 gimple_bind_add_stmt (bind
, stmt
);
7194 x
= gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START
),
7196 gimple_bind_add_stmt (bind
, x
);
7198 lower_omp (gimple_omp_body_ptr (stmt
), ctx
);
7199 gimple_omp_set_body (stmt
, maybe_catch_exception (gimple_omp_body (stmt
)));
7200 gimple_bind_add_seq (bind
, gimple_omp_body (stmt
));
7201 gimple_omp_set_body (stmt
, NULL
);
7203 x
= gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END
), 0);
7204 gimple_bind_add_stmt (bind
, x
);
7206 gimple_bind_add_stmt (bind
, gimple_build_omp_return (true));
7208 pop_gimplify_context (bind
);
7210 gimple_bind_append_vars (bind
, ctx
->block_vars
);
7211 BLOCK_VARS (block
) = gimple_bind_vars (bind
);
7215 /* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
7216 substitution of a couple of function calls. But in the NAMED case,
7217 requires that languages coordinate a symbol name. It is therefore
7218 best put here in common code. */
7220 static GTY((param1_is (tree
), param2_is (tree
)))
7221 splay_tree critical_name_mutexes
;
7224 lower_omp_critical (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
7227 tree name
, lock
, unlock
;
7228 gimple stmt
= gsi_stmt (*gsi_p
), bind
;
7229 location_t loc
= gimple_location (stmt
);
7231 struct gimplify_ctx gctx
;
7233 name
= gimple_omp_critical_name (stmt
);
7239 if (!critical_name_mutexes
)
7240 critical_name_mutexes
7241 = splay_tree_new_ggc (splay_tree_compare_pointers
,
7242 ggc_alloc_splay_tree_tree_node_tree_node_splay_tree_s
,
7243 ggc_alloc_splay_tree_tree_node_tree_node_splay_tree_node_s
);
7245 n
= splay_tree_lookup (critical_name_mutexes
, (splay_tree_key
) name
);
7250 decl
= create_tmp_var_raw (ptr_type_node
, NULL
);
7252 new_str
= ACONCAT ((".gomp_critical_user_",
7253 IDENTIFIER_POINTER (name
), NULL
));
7254 DECL_NAME (decl
) = get_identifier (new_str
);
7255 TREE_PUBLIC (decl
) = 1;
7256 TREE_STATIC (decl
) = 1;
7257 DECL_COMMON (decl
) = 1;
7258 DECL_ARTIFICIAL (decl
) = 1;
7259 DECL_IGNORED_P (decl
) = 1;
7260 varpool_finalize_decl (decl
);
7262 splay_tree_insert (critical_name_mutexes
, (splay_tree_key
) name
,
7263 (splay_tree_value
) decl
);
7266 decl
= (tree
) n
->value
;
7268 lock
= builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START
);
7269 lock
= build_call_expr_loc (loc
, lock
, 1, build_fold_addr_expr_loc (loc
, decl
));
7271 unlock
= builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END
);
7272 unlock
= build_call_expr_loc (loc
, unlock
, 1,
7273 build_fold_addr_expr_loc (loc
, decl
));
7277 lock
= builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START
);
7278 lock
= build_call_expr_loc (loc
, lock
, 0);
7280 unlock
= builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END
);
7281 unlock
= build_call_expr_loc (loc
, unlock
, 0);
7284 push_gimplify_context (&gctx
);
7286 block
= make_node (BLOCK
);
7287 bind
= gimple_build_bind (NULL
, NULL
, block
);
7288 gsi_replace (gsi_p
, bind
, true);
7289 gimple_bind_add_stmt (bind
, stmt
);
7291 tbody
= gimple_bind_body (bind
);
7292 gimplify_and_add (lock
, &tbody
);
7293 gimple_bind_set_body (bind
, tbody
);
7295 lower_omp (gimple_omp_body_ptr (stmt
), ctx
);
7296 gimple_omp_set_body (stmt
, maybe_catch_exception (gimple_omp_body (stmt
)));
7297 gimple_bind_add_seq (bind
, gimple_omp_body (stmt
));
7298 gimple_omp_set_body (stmt
, NULL
);
7300 tbody
= gimple_bind_body (bind
);
7301 gimplify_and_add (unlock
, &tbody
);
7302 gimple_bind_set_body (bind
, tbody
);
7304 gimple_bind_add_stmt (bind
, gimple_build_omp_return (true));
7306 pop_gimplify_context (bind
);
7307 gimple_bind_append_vars (bind
, ctx
->block_vars
);
7308 BLOCK_VARS (block
) = gimple_bind_vars (bind
);
7312 /* A subroutine of lower_omp_for. Generate code to emit the predicate
7313 for a lastprivate clause. Given a loop control predicate of (V
7314 cond N2), we gate the clause on (!(V cond N2)). The lowered form
7315 is appended to *DLIST, iterator initialization is appended to
7319 lower_omp_for_lastprivate (struct omp_for_data
*fd
, gimple_seq
*body_p
,
7320 gimple_seq
*dlist
, struct omp_context
*ctx
)
7322 tree clauses
, cond
, vinit
;
7323 enum tree_code cond_code
;
7326 cond_code
= fd
->loop
.cond_code
;
7327 cond_code
= cond_code
== LT_EXPR
? GE_EXPR
: LE_EXPR
;
7329 /* When possible, use a strict equality expression. This can let VRP
7330 type optimizations deduce the value and remove a copy. */
7331 if (host_integerp (fd
->loop
.step
, 0))
7333 HOST_WIDE_INT step
= TREE_INT_CST_LOW (fd
->loop
.step
);
7334 if (step
== 1 || step
== -1)
7335 cond_code
= EQ_EXPR
;
7338 cond
= build2 (cond_code
, boolean_type_node
, fd
->loop
.v
, fd
->loop
.n2
);
7340 clauses
= gimple_omp_for_clauses (fd
->for_stmt
);
7342 lower_lastprivate_clauses (clauses
, cond
, &stmts
, ctx
);
7343 if (!gimple_seq_empty_p (stmts
))
7345 gimple_seq_add_seq (&stmts
, *dlist
);
7348 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
7349 vinit
= fd
->loop
.n1
;
7350 if (cond_code
== EQ_EXPR
7351 && host_integerp (fd
->loop
.n2
, 0)
7352 && ! integer_zerop (fd
->loop
.n2
))
7353 vinit
= build_int_cst (TREE_TYPE (fd
->loop
.v
), 0);
7355 vinit
= unshare_expr (vinit
);
7357 /* Initialize the iterator variable, so that threads that don't execute
7358 any iterations don't execute the lastprivate clauses by accident. */
7359 gimplify_assign (fd
->loop
.v
, vinit
, body_p
);
7364 /* Lower code for an OpenMP loop directive. */
7367 lower_omp_for (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
7370 struct omp_for_data fd
;
7371 gimple stmt
= gsi_stmt (*gsi_p
), new_stmt
;
7372 gimple_seq omp_for_body
, body
, dlist
;
7374 struct gimplify_ctx gctx
;
7376 push_gimplify_context (&gctx
);
7378 lower_omp (gimple_omp_for_pre_body_ptr (stmt
), ctx
);
7380 block
= make_node (BLOCK
);
7381 new_stmt
= gimple_build_bind (NULL
, NULL
, block
);
7382 /* Replace at gsi right away, so that 'stmt' is no member
7383 of a sequence anymore as we're going to add to to a different
7385 gsi_replace (gsi_p
, new_stmt
, true);
7387 /* Move declaration of temporaries in the loop body before we make
7389 omp_for_body
= gimple_omp_body (stmt
);
7390 if (!gimple_seq_empty_p (omp_for_body
)
7391 && gimple_code (gimple_seq_first_stmt (omp_for_body
)) == GIMPLE_BIND
)
7393 tree vars
= gimple_bind_vars (gimple_seq_first_stmt (omp_for_body
));
7394 gimple_bind_append_vars (new_stmt
, vars
);
7397 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
7400 lower_rec_input_clauses (gimple_omp_for_clauses (stmt
), &body
, &dlist
, ctx
);
7401 gimple_seq_add_seq (&body
, gimple_omp_for_pre_body (stmt
));
7403 lower_omp (gimple_omp_body_ptr (stmt
), ctx
);
7405 /* Lower the header expressions. At this point, we can assume that
7406 the header is of the form:
7408 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
7410 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
7411 using the .omp_data_s mapping, if needed. */
7412 for (i
= 0; i
< gimple_omp_for_collapse (stmt
); i
++)
7414 rhs_p
= gimple_omp_for_initial_ptr (stmt
, i
);
7415 if (!is_gimple_min_invariant (*rhs_p
))
7416 *rhs_p
= get_formal_tmp_var (*rhs_p
, &body
);
7418 rhs_p
= gimple_omp_for_final_ptr (stmt
, i
);
7419 if (!is_gimple_min_invariant (*rhs_p
))
7420 *rhs_p
= get_formal_tmp_var (*rhs_p
, &body
);
7422 rhs_p
= &TREE_OPERAND (gimple_omp_for_incr (stmt
, i
), 1);
7423 if (!is_gimple_min_invariant (*rhs_p
))
7424 *rhs_p
= get_formal_tmp_var (*rhs_p
, &body
);
7427 /* Once lowered, extract the bounds and clauses. */
7428 extract_omp_for_data (stmt
, &fd
, NULL
);
7430 lower_omp_for_lastprivate (&fd
, &body
, &dlist
, ctx
);
7432 gimple_seq_add_stmt (&body
, stmt
);
7433 gimple_seq_add_seq (&body
, gimple_omp_body (stmt
));
7435 gimple_seq_add_stmt (&body
, gimple_build_omp_continue (fd
.loop
.v
,
7438 /* After the loop, add exit clauses. */
7439 lower_reduction_clauses (gimple_omp_for_clauses (stmt
), &body
, ctx
);
7440 gimple_seq_add_seq (&body
, dlist
);
7442 body
= maybe_catch_exception (body
);
7444 /* Region exit marker goes at the end of the loop body. */
7445 gimple_seq_add_stmt (&body
, gimple_build_omp_return (fd
.have_nowait
));
7447 pop_gimplify_context (new_stmt
);
7449 gimple_bind_append_vars (new_stmt
, ctx
->block_vars
);
7450 BLOCK_VARS (block
) = gimple_bind_vars (new_stmt
);
7451 if (BLOCK_VARS (block
))
7452 TREE_USED (block
) = 1;
7454 gimple_bind_set_body (new_stmt
, body
);
7455 gimple_omp_set_body (stmt
, NULL
);
7456 gimple_omp_for_set_pre_body (stmt
, NULL
);
7459 /* Callback for walk_stmts. Check if the current statement only contains
7460 GIMPLE_OMP_FOR or GIMPLE_OMP_PARALLEL. */
7463 check_combined_parallel (gimple_stmt_iterator
*gsi_p
,
7464 bool *handled_ops_p
,
7465 struct walk_stmt_info
*wi
)
7467 int *info
= (int *) wi
->info
;
7468 gimple stmt
= gsi_stmt (*gsi_p
);
7470 *handled_ops_p
= true;
7471 switch (gimple_code (stmt
))
7475 case GIMPLE_OMP_FOR
:
7476 case GIMPLE_OMP_SECTIONS
:
7477 *info
= *info
== 0 ? 1 : -1;
7486 struct omp_taskcopy_context
7488 /* This field must be at the beginning, as we do "inheritance": Some
7489 callback functions for tree-inline.c (e.g., omp_copy_decl)
7490 receive a copy_body_data pointer that is up-casted to an
7491 omp_context pointer. */
7497 task_copyfn_copy_decl (tree var
, copy_body_data
*cb
)
7499 struct omp_taskcopy_context
*tcctx
= (struct omp_taskcopy_context
*) cb
;
7501 if (splay_tree_lookup (tcctx
->ctx
->sfield_map
, (splay_tree_key
) var
))
7502 return create_tmp_var (TREE_TYPE (var
), NULL
);
7508 task_copyfn_remap_type (struct omp_taskcopy_context
*tcctx
, tree orig_type
)
7510 tree name
, new_fields
= NULL
, type
, f
;
7512 type
= lang_hooks
.types
.make_type (RECORD_TYPE
);
7513 name
= DECL_NAME (TYPE_NAME (orig_type
));
7514 name
= build_decl (gimple_location (tcctx
->ctx
->stmt
),
7515 TYPE_DECL
, name
, type
);
7516 TYPE_NAME (type
) = name
;
7518 for (f
= TYPE_FIELDS (orig_type
); f
; f
= TREE_CHAIN (f
))
7520 tree new_f
= copy_node (f
);
7521 DECL_CONTEXT (new_f
) = type
;
7522 TREE_TYPE (new_f
) = remap_type (TREE_TYPE (f
), &tcctx
->cb
);
7523 TREE_CHAIN (new_f
) = new_fields
;
7524 walk_tree (&DECL_SIZE (new_f
), copy_tree_body_r
, &tcctx
->cb
, NULL
);
7525 walk_tree (&DECL_SIZE_UNIT (new_f
), copy_tree_body_r
, &tcctx
->cb
, NULL
);
7526 walk_tree (&DECL_FIELD_OFFSET (new_f
), copy_tree_body_r
,
7529 *pointer_map_insert (tcctx
->cb
.decl_map
, f
) = new_f
;
7531 TYPE_FIELDS (type
) = nreverse (new_fields
);
7536 /* Create task copyfn. */
7539 create_task_copyfn (gimple task_stmt
, omp_context
*ctx
)
7541 struct function
*child_cfun
;
7542 tree child_fn
, t
, c
, src
, dst
, f
, sf
, arg
, sarg
, decl
;
7543 tree record_type
, srecord_type
, bind
, list
;
7544 bool record_needs_remap
= false, srecord_needs_remap
= false;
7546 struct omp_taskcopy_context tcctx
;
7547 struct gimplify_ctx gctx
;
7548 location_t loc
= gimple_location (task_stmt
);
7550 child_fn
= gimple_omp_task_copy_fn (task_stmt
);
7551 child_cfun
= DECL_STRUCT_FUNCTION (child_fn
);
7552 gcc_assert (child_cfun
->cfg
== NULL
);
7553 DECL_SAVED_TREE (child_fn
) = alloc_stmt_list ();
7555 /* Reset DECL_CONTEXT on function arguments. */
7556 for (t
= DECL_ARGUMENTS (child_fn
); t
; t
= DECL_CHAIN (t
))
7557 DECL_CONTEXT (t
) = child_fn
;
7559 /* Populate the function. */
7560 push_gimplify_context (&gctx
);
7561 push_cfun (child_cfun
);
7563 bind
= build3 (BIND_EXPR
, void_type_node
, NULL
, NULL
, NULL
);
7564 TREE_SIDE_EFFECTS (bind
) = 1;
7566 DECL_SAVED_TREE (child_fn
) = bind
;
7567 DECL_SOURCE_LOCATION (child_fn
) = gimple_location (task_stmt
);
7569 /* Remap src and dst argument types if needed. */
7570 record_type
= ctx
->record_type
;
7571 srecord_type
= ctx
->srecord_type
;
7572 for (f
= TYPE_FIELDS (record_type
); f
; f
= DECL_CHAIN (f
))
7573 if (variably_modified_type_p (TREE_TYPE (f
), ctx
->cb
.src_fn
))
7575 record_needs_remap
= true;
7578 for (f
= TYPE_FIELDS (srecord_type
); f
; f
= DECL_CHAIN (f
))
7579 if (variably_modified_type_p (TREE_TYPE (f
), ctx
->cb
.src_fn
))
7581 srecord_needs_remap
= true;
7585 if (record_needs_remap
|| srecord_needs_remap
)
7587 memset (&tcctx
, '\0', sizeof (tcctx
));
7588 tcctx
.cb
.src_fn
= ctx
->cb
.src_fn
;
7589 tcctx
.cb
.dst_fn
= child_fn
;
7590 tcctx
.cb
.src_node
= cgraph_get_node (tcctx
.cb
.src_fn
);
7591 gcc_checking_assert (tcctx
.cb
.src_node
);
7592 tcctx
.cb
.dst_node
= tcctx
.cb
.src_node
;
7593 tcctx
.cb
.src_cfun
= ctx
->cb
.src_cfun
;
7594 tcctx
.cb
.copy_decl
= task_copyfn_copy_decl
;
7595 tcctx
.cb
.eh_lp_nr
= 0;
7596 tcctx
.cb
.transform_call_graph_edges
= CB_CGE_MOVE
;
7597 tcctx
.cb
.decl_map
= pointer_map_create ();
7600 if (record_needs_remap
)
7601 record_type
= task_copyfn_remap_type (&tcctx
, record_type
);
7602 if (srecord_needs_remap
)
7603 srecord_type
= task_copyfn_remap_type (&tcctx
, srecord_type
);
7606 tcctx
.cb
.decl_map
= NULL
;
7608 arg
= DECL_ARGUMENTS (child_fn
);
7609 TREE_TYPE (arg
) = build_pointer_type (record_type
);
7610 sarg
= DECL_CHAIN (arg
);
7611 TREE_TYPE (sarg
) = build_pointer_type (srecord_type
);
7613 /* First pass: initialize temporaries used in record_type and srecord_type
7614 sizes and field offsets. */
7615 if (tcctx
.cb
.decl_map
)
7616 for (c
= gimple_omp_task_clauses (task_stmt
); c
; c
= OMP_CLAUSE_CHAIN (c
))
7617 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_FIRSTPRIVATE
)
7621 decl
= OMP_CLAUSE_DECL (c
);
7622 p
= (tree
*) pointer_map_contains (tcctx
.cb
.decl_map
, decl
);
7625 n
= splay_tree_lookup (ctx
->sfield_map
, (splay_tree_key
) decl
);
7626 sf
= (tree
) n
->value
;
7627 sf
= *(tree
*) pointer_map_contains (tcctx
.cb
.decl_map
, sf
);
7628 src
= build_simple_mem_ref_loc (loc
, sarg
);
7629 src
= omp_build_component_ref (src
, sf
);
7630 t
= build2 (MODIFY_EXPR
, TREE_TYPE (*p
), *p
, src
);
7631 append_to_statement_list (t
, &list
);
7634 /* Second pass: copy shared var pointers and copy construct non-VLA
7635 firstprivate vars. */
7636 for (c
= gimple_omp_task_clauses (task_stmt
); c
; c
= OMP_CLAUSE_CHAIN (c
))
7637 switch (OMP_CLAUSE_CODE (c
))
7639 case OMP_CLAUSE_SHARED
:
7640 decl
= OMP_CLAUSE_DECL (c
);
7641 n
= splay_tree_lookup (ctx
->field_map
, (splay_tree_key
) decl
);
7644 f
= (tree
) n
->value
;
7645 if (tcctx
.cb
.decl_map
)
7646 f
= *(tree
*) pointer_map_contains (tcctx
.cb
.decl_map
, f
);
7647 n
= splay_tree_lookup (ctx
->sfield_map
, (splay_tree_key
) decl
);
7648 sf
= (tree
) n
->value
;
7649 if (tcctx
.cb
.decl_map
)
7650 sf
= *(tree
*) pointer_map_contains (tcctx
.cb
.decl_map
, sf
);
7651 src
= build_simple_mem_ref_loc (loc
, sarg
);
7652 src
= omp_build_component_ref (src
, sf
);
7653 dst
= build_simple_mem_ref_loc (loc
, arg
);
7654 dst
= omp_build_component_ref (dst
, f
);
7655 t
= build2 (MODIFY_EXPR
, TREE_TYPE (dst
), dst
, src
);
7656 append_to_statement_list (t
, &list
);
7658 case OMP_CLAUSE_FIRSTPRIVATE
:
7659 decl
= OMP_CLAUSE_DECL (c
);
7660 if (is_variable_sized (decl
))
7662 n
= splay_tree_lookup (ctx
->field_map
, (splay_tree_key
) decl
);
7665 f
= (tree
) n
->value
;
7666 if (tcctx
.cb
.decl_map
)
7667 f
= *(tree
*) pointer_map_contains (tcctx
.cb
.decl_map
, f
);
7668 n
= splay_tree_lookup (ctx
->sfield_map
, (splay_tree_key
) decl
);
7671 sf
= (tree
) n
->value
;
7672 if (tcctx
.cb
.decl_map
)
7673 sf
= *(tree
*) pointer_map_contains (tcctx
.cb
.decl_map
, sf
);
7674 src
= build_simple_mem_ref_loc (loc
, sarg
);
7675 src
= omp_build_component_ref (src
, sf
);
7676 if (use_pointer_for_field (decl
, NULL
) || is_reference (decl
))
7677 src
= build_simple_mem_ref_loc (loc
, src
);
7681 dst
= build_simple_mem_ref_loc (loc
, arg
);
7682 dst
= omp_build_component_ref (dst
, f
);
7683 t
= lang_hooks
.decls
.omp_clause_copy_ctor (c
, dst
, src
);
7684 append_to_statement_list (t
, &list
);
7686 case OMP_CLAUSE_PRIVATE
:
7687 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c
))
7689 decl
= OMP_CLAUSE_DECL (c
);
7690 n
= splay_tree_lookup (ctx
->field_map
, (splay_tree_key
) decl
);
7691 f
= (tree
) n
->value
;
7692 if (tcctx
.cb
.decl_map
)
7693 f
= *(tree
*) pointer_map_contains (tcctx
.cb
.decl_map
, f
);
7694 n
= splay_tree_lookup (ctx
->sfield_map
, (splay_tree_key
) decl
);
7697 sf
= (tree
) n
->value
;
7698 if (tcctx
.cb
.decl_map
)
7699 sf
= *(tree
*) pointer_map_contains (tcctx
.cb
.decl_map
, sf
);
7700 src
= build_simple_mem_ref_loc (loc
, sarg
);
7701 src
= omp_build_component_ref (src
, sf
);
7702 if (use_pointer_for_field (decl
, NULL
))
7703 src
= build_simple_mem_ref_loc (loc
, src
);
7707 dst
= build_simple_mem_ref_loc (loc
, arg
);
7708 dst
= omp_build_component_ref (dst
, f
);
7709 t
= build2 (MODIFY_EXPR
, TREE_TYPE (dst
), dst
, src
);
7710 append_to_statement_list (t
, &list
);
7716 /* Last pass: handle VLA firstprivates. */
7717 if (tcctx
.cb
.decl_map
)
7718 for (c
= gimple_omp_task_clauses (task_stmt
); c
; c
= OMP_CLAUSE_CHAIN (c
))
7719 if (OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_FIRSTPRIVATE
)
7723 decl
= OMP_CLAUSE_DECL (c
);
7724 if (!is_variable_sized (decl
))
7726 n
= splay_tree_lookup (ctx
->field_map
, (splay_tree_key
) decl
);
7729 f
= (tree
) n
->value
;
7730 f
= *(tree
*) pointer_map_contains (tcctx
.cb
.decl_map
, f
);
7731 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl
));
7732 ind
= DECL_VALUE_EXPR (decl
);
7733 gcc_assert (TREE_CODE (ind
) == INDIRECT_REF
);
7734 gcc_assert (DECL_P (TREE_OPERAND (ind
, 0)));
7735 n
= splay_tree_lookup (ctx
->sfield_map
,
7736 (splay_tree_key
) TREE_OPERAND (ind
, 0));
7737 sf
= (tree
) n
->value
;
7738 sf
= *(tree
*) pointer_map_contains (tcctx
.cb
.decl_map
, sf
);
7739 src
= build_simple_mem_ref_loc (loc
, sarg
);
7740 src
= omp_build_component_ref (src
, sf
);
7741 src
= build_simple_mem_ref_loc (loc
, src
);
7742 dst
= build_simple_mem_ref_loc (loc
, arg
);
7743 dst
= omp_build_component_ref (dst
, f
);
7744 t
= lang_hooks
.decls
.omp_clause_copy_ctor (c
, dst
, src
);
7745 append_to_statement_list (t
, &list
);
7746 n
= splay_tree_lookup (ctx
->field_map
,
7747 (splay_tree_key
) TREE_OPERAND (ind
, 0));
7748 df
= (tree
) n
->value
;
7749 df
= *(tree
*) pointer_map_contains (tcctx
.cb
.decl_map
, df
);
7750 ptr
= build_simple_mem_ref_loc (loc
, arg
);
7751 ptr
= omp_build_component_ref (ptr
, df
);
7752 t
= build2 (MODIFY_EXPR
, TREE_TYPE (ptr
), ptr
,
7753 build_fold_addr_expr_loc (loc
, dst
));
7754 append_to_statement_list (t
, &list
);
7757 t
= build1 (RETURN_EXPR
, void_type_node
, NULL
);
7758 append_to_statement_list (t
, &list
);
7760 if (tcctx
.cb
.decl_map
)
7761 pointer_map_destroy (tcctx
.cb
.decl_map
);
7762 pop_gimplify_context (NULL
);
7763 BIND_EXPR_BODY (bind
) = list
;
7767 /* Lower the OpenMP parallel or task directive in the current statement
7768 in GSI_P. CTX holds context information for the directive. */
7771 lower_omp_taskreg (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
7775 gimple stmt
= gsi_stmt (*gsi_p
);
7776 gimple par_bind
, bind
;
7777 gimple_seq par_body
, olist
, ilist
, par_olist
, par_ilist
, new_body
;
7778 struct gimplify_ctx gctx
;
7779 location_t loc
= gimple_location (stmt
);
7781 clauses
= gimple_omp_taskreg_clauses (stmt
);
7782 par_bind
= gimple_seq_first_stmt (gimple_omp_body (stmt
));
7783 par_body
= gimple_bind_body (par_bind
);
7784 child_fn
= ctx
->cb
.dst_fn
;
7785 if (gimple_code (stmt
) == GIMPLE_OMP_PARALLEL
7786 && !gimple_omp_parallel_combined_p (stmt
))
7788 struct walk_stmt_info wi
;
7791 memset (&wi
, 0, sizeof (wi
));
7794 walk_gimple_seq (par_body
, check_combined_parallel
, NULL
, &wi
);
7796 gimple_omp_parallel_set_combined_p (stmt
, true);
7798 if (ctx
->srecord_type
)
7799 create_task_copyfn (stmt
, ctx
);
7801 push_gimplify_context (&gctx
);
7805 lower_rec_input_clauses (clauses
, &par_ilist
, &par_olist
, ctx
);
7806 lower_omp (&par_body
, ctx
);
7807 if (gimple_code (stmt
) == GIMPLE_OMP_PARALLEL
)
7808 lower_reduction_clauses (clauses
, &par_olist
, ctx
);
7810 /* Declare all the variables created by mapping and the variables
7811 declared in the scope of the parallel body. */
7812 record_vars_into (ctx
->block_vars
, child_fn
);
7813 record_vars_into (gimple_bind_vars (par_bind
), child_fn
);
7815 if (ctx
->record_type
)
7818 = create_tmp_var (ctx
->srecord_type
? ctx
->srecord_type
7819 : ctx
->record_type
, ".omp_data_o");
7820 DECL_NAMELESS (ctx
->sender_decl
) = 1;
7821 TREE_ADDRESSABLE (ctx
->sender_decl
) = 1;
7822 gimple_omp_taskreg_set_data_arg (stmt
, ctx
->sender_decl
);
7827 lower_send_clauses (clauses
, &ilist
, &olist
, ctx
);
7828 lower_send_shared_vars (&ilist
, &olist
, ctx
);
7830 /* Once all the expansions are done, sequence all the different
7831 fragments inside gimple_omp_body. */
7835 if (ctx
->record_type
)
7837 t
= build_fold_addr_expr_loc (loc
, ctx
->sender_decl
);
7838 /* fixup_child_record_type might have changed receiver_decl's type. */
7839 t
= fold_convert_loc (loc
, TREE_TYPE (ctx
->receiver_decl
), t
);
7840 gimple_seq_add_stmt (&new_body
,
7841 gimple_build_assign (ctx
->receiver_decl
, t
));
7844 gimple_seq_add_seq (&new_body
, par_ilist
);
7845 gimple_seq_add_seq (&new_body
, par_body
);
7846 gimple_seq_add_seq (&new_body
, par_olist
);
7847 new_body
= maybe_catch_exception (new_body
);
7848 gimple_seq_add_stmt (&new_body
, gimple_build_omp_return (false));
7849 gimple_omp_set_body (stmt
, new_body
);
7851 bind
= gimple_build_bind (NULL
, NULL
, gimple_bind_block (par_bind
));
7852 gsi_replace (gsi_p
, bind
, true);
7853 gimple_bind_add_seq (bind
, ilist
);
7854 gimple_bind_add_stmt (bind
, stmt
);
7855 gimple_bind_add_seq (bind
, olist
);
7857 pop_gimplify_context (NULL
);
7860 /* Callback for lower_omp_1. Return non-NULL if *tp needs to be
7861 regimplified. If DATA is non-NULL, lower_omp_1 is outside
7862 of OpenMP context, but with task_shared_vars set. */
7865 lower_omp_regimplify_p (tree
*tp
, int *walk_subtrees
,
7870 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
7871 if (TREE_CODE (t
) == VAR_DECL
&& data
== NULL
&& DECL_HAS_VALUE_EXPR_P (t
))
7874 if (task_shared_vars
7876 && bitmap_bit_p (task_shared_vars
, DECL_UID (t
)))
7879 /* If a global variable has been privatized, TREE_CONSTANT on
7880 ADDR_EXPR might be wrong. */
7881 if (data
== NULL
&& TREE_CODE (t
) == ADDR_EXPR
)
7882 recompute_tree_invariant_for_addr_expr (t
);
7884 *walk_subtrees
= !TYPE_P (t
) && !DECL_P (t
);
7889 lower_omp_1 (gimple_stmt_iterator
*gsi_p
, omp_context
*ctx
)
7891 gimple stmt
= gsi_stmt (*gsi_p
);
7892 struct walk_stmt_info wi
;
7894 if (gimple_has_location (stmt
))
7895 input_location
= gimple_location (stmt
);
7897 if (task_shared_vars
)
7898 memset (&wi
, '\0', sizeof (wi
));
7900 /* If we have issued syntax errors, avoid doing any heavy lifting.
7901 Just replace the OpenMP directives with a NOP to avoid
7902 confusing RTL expansion. */
7903 if (seen_error () && is_gimple_omp (stmt
))
7905 gsi_replace (gsi_p
, gimple_build_nop (), true);
7909 switch (gimple_code (stmt
))
7912 if ((ctx
|| task_shared_vars
)
7913 && (walk_tree (gimple_cond_lhs_ptr (stmt
), lower_omp_regimplify_p
,
7914 ctx
? NULL
: &wi
, NULL
)
7915 || walk_tree (gimple_cond_rhs_ptr (stmt
), lower_omp_regimplify_p
,
7916 ctx
? NULL
: &wi
, NULL
)))
7917 gimple_regimplify_operands (stmt
, gsi_p
);
7920 lower_omp (gimple_catch_handler_ptr (stmt
), ctx
);
7922 case GIMPLE_EH_FILTER
:
7923 lower_omp (gimple_eh_filter_failure_ptr (stmt
), ctx
);
7926 lower_omp (gimple_try_eval_ptr (stmt
), ctx
);
7927 lower_omp (gimple_try_cleanup_ptr (stmt
), ctx
);
7929 case GIMPLE_TRANSACTION
:
7930 lower_omp (gimple_transaction_body_ptr (stmt
), ctx
);
7933 lower_omp (gimple_bind_body_ptr (stmt
), ctx
);
7935 case GIMPLE_OMP_PARALLEL
:
7936 case GIMPLE_OMP_TASK
:
7937 ctx
= maybe_lookup_ctx (stmt
);
7938 lower_omp_taskreg (gsi_p
, ctx
);
7940 case GIMPLE_OMP_FOR
:
7941 ctx
= maybe_lookup_ctx (stmt
);
7943 lower_omp_for (gsi_p
, ctx
);
7945 case GIMPLE_OMP_SECTIONS
:
7946 ctx
= maybe_lookup_ctx (stmt
);
7948 lower_omp_sections (gsi_p
, ctx
);
7950 case GIMPLE_OMP_SINGLE
:
7951 ctx
= maybe_lookup_ctx (stmt
);
7953 lower_omp_single (gsi_p
, ctx
);
7955 case GIMPLE_OMP_MASTER
:
7956 ctx
= maybe_lookup_ctx (stmt
);
7958 lower_omp_master (gsi_p
, ctx
);
7960 case GIMPLE_OMP_ORDERED
:
7961 ctx
= maybe_lookup_ctx (stmt
);
7963 lower_omp_ordered (gsi_p
, ctx
);
7965 case GIMPLE_OMP_CRITICAL
:
7966 ctx
= maybe_lookup_ctx (stmt
);
7968 lower_omp_critical (gsi_p
, ctx
);
7970 case GIMPLE_OMP_ATOMIC_LOAD
:
7971 if ((ctx
|| task_shared_vars
)
7972 && walk_tree (gimple_omp_atomic_load_rhs_ptr (stmt
),
7973 lower_omp_regimplify_p
, ctx
? NULL
: &wi
, NULL
))
7974 gimple_regimplify_operands (stmt
, gsi_p
);
7977 if ((ctx
|| task_shared_vars
)
7978 && walk_gimple_op (stmt
, lower_omp_regimplify_p
,
7980 gimple_regimplify_operands (stmt
, gsi_p
);
7986 lower_omp (gimple_seq
*body
, omp_context
*ctx
)
7988 location_t saved_location
= input_location
;
7989 gimple_stmt_iterator gsi
;
7990 for (gsi
= gsi_start (*body
); !gsi_end_p (gsi
); gsi_next (&gsi
))
7991 lower_omp_1 (&gsi
, ctx
);
7992 input_location
= saved_location
;
7995 /* Main entry point. */
7998 execute_lower_omp (void)
8002 /* This pass always runs, to provide PROP_gimple_lomp.
8003 But there is nothing to do unless -fopenmp is given. */
8004 if (flag_openmp
== 0)
8007 all_contexts
= splay_tree_new (splay_tree_compare_pointers
, 0,
8008 delete_omp_context
);
8010 body
= gimple_body (current_function_decl
);
8011 scan_omp (&body
, NULL
);
8012 gcc_assert (taskreg_nesting_level
== 0);
8014 if (all_contexts
->root
)
8016 struct gimplify_ctx gctx
;
8018 if (task_shared_vars
)
8019 push_gimplify_context (&gctx
);
8020 lower_omp (&body
, NULL
);
8021 if (task_shared_vars
)
8022 pop_gimplify_context (NULL
);
8027 splay_tree_delete (all_contexts
);
8028 all_contexts
= NULL
;
8030 BITMAP_FREE (task_shared_vars
);
8036 const pass_data pass_data_lower_omp
=
8038 GIMPLE_PASS
, /* type */
8039 "omplower", /* name */
8040 OPTGROUP_NONE
, /* optinfo_flags */
8041 false, /* has_gate */
8042 true, /* has_execute */
8043 TV_NONE
, /* tv_id */
8044 PROP_gimple_any
, /* properties_required */
8045 PROP_gimple_lomp
, /* properties_provided */
8046 0, /* properties_destroyed */
8047 0, /* todo_flags_start */
8048 0, /* todo_flags_finish */
8051 class pass_lower_omp
: public gimple_opt_pass
8054 pass_lower_omp(gcc::context
*ctxt
)
8055 : gimple_opt_pass(pass_data_lower_omp
, ctxt
)
8058 /* opt_pass methods: */
8059 unsigned int execute () { return execute_lower_omp (); }
8061 }; // class pass_lower_omp
8066 make_pass_lower_omp (gcc::context
*ctxt
)
8068 return new pass_lower_omp (ctxt
);
8071 /* The following is a utility to diagnose OpenMP structured block violations.
8072 It is not part of the "omplower" pass, as that's invoked too late. It
8073 should be invoked by the respective front ends after gimplification. */
8075 static splay_tree all_labels
;
8077 /* Check for mismatched contexts and generate an error if needed. Return
8078 true if an error is detected. */
8081 diagnose_sb_0 (gimple_stmt_iterator
*gsi_p
,
8082 gimple branch_ctx
, gimple label_ctx
)
8084 if (label_ctx
== branch_ctx
)
8089 Previously we kept track of the label's entire context in diagnose_sb_[12]
8090 so we could traverse it and issue a correct "exit" or "enter" error
8091 message upon a structured block violation.
8093 We built the context by building a list with tree_cons'ing, but there is
8094 no easy counterpart in gimple tuples. It seems like far too much work
8095 for issuing exit/enter error messages. If someone really misses the
8096 distinct error message... patches welcome.
8100 /* Try to avoid confusing the user by producing and error message
8101 with correct "exit" or "enter" verbiage. We prefer "exit"
8102 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
8103 if (branch_ctx
== NULL
)
8109 if (TREE_VALUE (label_ctx
) == branch_ctx
)
8114 label_ctx
= TREE_CHAIN (label_ctx
);
8119 error ("invalid exit from OpenMP structured block");
8121 error ("invalid entry to OpenMP structured block");
8124 /* If it's obvious we have an invalid entry, be specific about the error. */
8125 if (branch_ctx
== NULL
)
8126 error ("invalid entry to OpenMP structured block");
8128 /* Otherwise, be vague and lazy, but efficient. */
8129 error ("invalid branch to/from an OpenMP structured block");
8131 gsi_replace (gsi_p
, gimple_build_nop (), false);
8135 /* Pass 1: Create a minimal tree of OpenMP structured blocks, and record
8136 where each label is found. */
8139 diagnose_sb_1 (gimple_stmt_iterator
*gsi_p
, bool *handled_ops_p
,
8140 struct walk_stmt_info
*wi
)
8142 gimple context
= (gimple
) wi
->info
;
8143 gimple inner_context
;
8144 gimple stmt
= gsi_stmt (*gsi_p
);
8146 *handled_ops_p
= true;
8148 switch (gimple_code (stmt
))
8152 case GIMPLE_OMP_PARALLEL
:
8153 case GIMPLE_OMP_TASK
:
8154 case GIMPLE_OMP_SECTIONS
:
8155 case GIMPLE_OMP_SINGLE
:
8156 case GIMPLE_OMP_SECTION
:
8157 case GIMPLE_OMP_MASTER
:
8158 case GIMPLE_OMP_ORDERED
:
8159 case GIMPLE_OMP_CRITICAL
:
8160 /* The minimal context here is just the current OMP construct. */
8161 inner_context
= stmt
;
8162 wi
->info
= inner_context
;
8163 walk_gimple_seq (gimple_omp_body (stmt
), diagnose_sb_1
, NULL
, wi
);
8167 case GIMPLE_OMP_FOR
:
8168 inner_context
= stmt
;
8169 wi
->info
= inner_context
;
8170 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
8172 walk_gimple_seq (gimple_omp_for_pre_body (stmt
),
8173 diagnose_sb_1
, NULL
, wi
);
8174 walk_gimple_seq (gimple_omp_body (stmt
), diagnose_sb_1
, NULL
, wi
);
8179 splay_tree_insert (all_labels
, (splay_tree_key
) gimple_label_label (stmt
),
8180 (splay_tree_value
) context
);
8190 /* Pass 2: Check each branch and see if its context differs from that of
8191 the destination label's context. */
8194 diagnose_sb_2 (gimple_stmt_iterator
*gsi_p
, bool *handled_ops_p
,
8195 struct walk_stmt_info
*wi
)
8197 gimple context
= (gimple
) wi
->info
;
8199 gimple stmt
= gsi_stmt (*gsi_p
);
8201 *handled_ops_p
= true;
8203 switch (gimple_code (stmt
))
8207 case GIMPLE_OMP_PARALLEL
:
8208 case GIMPLE_OMP_TASK
:
8209 case GIMPLE_OMP_SECTIONS
:
8210 case GIMPLE_OMP_SINGLE
:
8211 case GIMPLE_OMP_SECTION
:
8212 case GIMPLE_OMP_MASTER
:
8213 case GIMPLE_OMP_ORDERED
:
8214 case GIMPLE_OMP_CRITICAL
:
8216 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt
), diagnose_sb_2
, NULL
, wi
);
8220 case GIMPLE_OMP_FOR
:
8222 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
8224 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt
),
8225 diagnose_sb_2
, NULL
, wi
);
8226 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt
), diagnose_sb_2
, NULL
, wi
);
8232 tree lab
= gimple_cond_true_label (stmt
);
8235 n
= splay_tree_lookup (all_labels
,
8236 (splay_tree_key
) lab
);
8237 diagnose_sb_0 (gsi_p
, context
,
8238 n
? (gimple
) n
->value
: NULL
);
8240 lab
= gimple_cond_false_label (stmt
);
8243 n
= splay_tree_lookup (all_labels
,
8244 (splay_tree_key
) lab
);
8245 diagnose_sb_0 (gsi_p
, context
,
8246 n
? (gimple
) n
->value
: NULL
);
8253 tree lab
= gimple_goto_dest (stmt
);
8254 if (TREE_CODE (lab
) != LABEL_DECL
)
8257 n
= splay_tree_lookup (all_labels
, (splay_tree_key
) lab
);
8258 diagnose_sb_0 (gsi_p
, context
, n
? (gimple
) n
->value
: NULL
);
8265 for (i
= 0; i
< gimple_switch_num_labels (stmt
); ++i
)
8267 tree lab
= CASE_LABEL (gimple_switch_label (stmt
, i
));
8268 n
= splay_tree_lookup (all_labels
, (splay_tree_key
) lab
);
8269 if (n
&& diagnose_sb_0 (gsi_p
, context
, (gimple
) n
->value
))
8276 diagnose_sb_0 (gsi_p
, context
, NULL
);
8287 diagnose_omp_structured_block_errors (void)
8289 struct walk_stmt_info wi
;
8290 gimple_seq body
= gimple_body (current_function_decl
);
8292 all_labels
= splay_tree_new (splay_tree_compare_pointers
, 0, 0);
8294 memset (&wi
, 0, sizeof (wi
));
8295 walk_gimple_seq (body
, diagnose_sb_1
, NULL
, &wi
);
8297 memset (&wi
, 0, sizeof (wi
));
8298 wi
.want_locations
= true;
8299 walk_gimple_seq_mod (&body
, diagnose_sb_2
, NULL
, &wi
);
8301 gimple_set_body (current_function_decl
, body
);
8303 splay_tree_delete (all_labels
);
8310 gate_diagnose_omp_blocks (void)
8312 return flag_openmp
!= 0;
8317 const pass_data pass_data_diagnose_omp_blocks
=
8319 GIMPLE_PASS
, /* type */
8320 "*diagnose_omp_blocks", /* name */
8321 OPTGROUP_NONE
, /* optinfo_flags */
8322 true, /* has_gate */
8323 true, /* has_execute */
8324 TV_NONE
, /* tv_id */
8325 PROP_gimple_any
, /* properties_required */
8326 0, /* properties_provided */
8327 0, /* properties_destroyed */
8328 0, /* todo_flags_start */
8329 0, /* todo_flags_finish */
8332 class pass_diagnose_omp_blocks
: public gimple_opt_pass
8335 pass_diagnose_omp_blocks(gcc::context
*ctxt
)
8336 : gimple_opt_pass(pass_data_diagnose_omp_blocks
, ctxt
)
8339 /* opt_pass methods: */
8340 bool gate () { return gate_diagnose_omp_blocks (); }
8341 unsigned int execute () {
8342 return diagnose_omp_structured_block_errors ();
8345 }; // class pass_diagnose_omp_blocks
8350 make_pass_diagnose_omp_blocks (gcc::context
*ctxt
)
8352 return new pass_diagnose_omp_blocks (ctxt
);
8355 #include "gt-omp-low.h"